Update mouse library

This commit is contained in:
coolneng 2022-06-10 20:03:25 +02:00
parent d62667a652
commit 2cee0396de
Signed by: coolneng
GPG Key ID: 9893DA236405AF57
25 changed files with 801 additions and 12 deletions

101
mouse/.gitignore vendored Normal file
View File

@ -0,0 +1,101 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/

30
mouse/CHANGES.md Normal file
View File

@ -0,0 +1,30 @@
# 0.7.1
- Fixed errors and incorrect information on setup.py.
- Fixed Windows segfault.
- Applied pending bug fixes.
# 0.7.0
- [All] Fix Windows hook error (#1).
- [All] Add __main__ module, allowing `python -m mouse` to save and load events.
# 0.6.1
- [Windows] Fixed ctypes type-checking error.
- [All] Misc fixes to release process.
# 0.6.0
- Added README and API docs.
- Bump version to replace old library.
# 0.0.1
- Initial release, migrated from `keyboard` package.

21
mouse/LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Lucas Boppre Niehues
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

18
mouse/Makefile Normal file
View File

@ -0,0 +1,18 @@
test: tests
tests:
python2 -m coverage run -m mouse._mouse_tests
python2 -m coverage run -am mouse._mouse_tests
python -m coverage run -am mouse._mouse_tests
python -m coverage run -am mouse._mouse_tests
python -m coverage report && coverage3 html
build: tests mouse setup.py
python ../docstring2markdown/docstring2markdown.py mouse "https://github.com/boppreh/mouse/blob/master" > README.md
find . \( -name "*.py" -o -name "*.sh" -o -name "* .md" \) -exec dos2unix {} \;
python setup.py sdist --format=zip bdist_wheel --universal bdist_wininst && twine check dist/*
release:
python make_release.py
clean:
rm -rfv dist build coverage_html_report mouse.egg-info

500
mouse/README.md Normal file
View File

@ -0,0 +1,500 @@
mouse
=====
Take full control of your mouse with this small Python library. Hook global events, register hotkeys, simulate mouse movement and clicks, and much more.
_Huge thanks to [Kirill Pavlov](http://kirillpavlov.com/) for donating the package name. If you are looking for the Cheddargetter.com client implementation, [`pip install mouse==0.5.0`](https://pypi.python.org/pypi/mouse/0.5.0)._
## Features
- Global event hook on all mice devices (captures events regardless of focus).
- **Listen** and **sends** mouse events.
- Works with **Windows** and **Linux** (requires sudo).
- **Pure Python**, no C modules to be compiled.
- **Zero dependencies**. Trivial to install and deploy, just copy the files.
- **Python 2 and 3**.
- Includes **high level API** (e.g. [record](#mouse.record) and [play](#mouse.play).
- Events automatically captured in separate thread, doesn't block main program.
- Tested and documented.
This program makes no attempt to hide itself, so don't use it for keyloggers.
## Usage
Install the [PyPI package](https://pypi.python.org/pypi/mouse/):
$ sudo pip install mouse
or clone the repository (no installation required, source files are sufficient):
$ git clone https://github.com/boppreh/mouse
Then check the [API docs](https://github.com/boppreh/mouse#api) to see what features are available.
## Known limitations:
- Events generated under Windows don't report device id (`event.device == None`). [#21](https://github.com/boppreh/keyboard/issues/21)
- To avoid depending on X the Linux parts reads raw device files (`/dev/input/input*`) but this requries root.
- Other applications, such as some games, may register hooks that swallow all key events. In this case `mouse` will be unable to report events.
# API
#### Table of Contents
- [mouse.**ButtonEvent**](#mouse.ButtonEvent)
- [mouse.**DOUBLE**](#mouse.DOUBLE)
- [mouse.**DOWN**](#mouse.DOWN)
- [mouse.**LEFT**](#mouse.LEFT)
- [mouse.**MIDDLE**](#mouse.MIDDLE)
- [mouse.**MoveEvent**](#mouse.MoveEvent)
- [mouse.**RIGHT**](#mouse.RIGHT)
- [mouse.**UP**](#mouse.UP)
- [mouse.**WheelEvent**](#mouse.WheelEvent)
- [mouse.**X**](#mouse.X)
- [mouse.**X2**](#mouse.X2)
- [mouse.**version**](#mouse.version)
- [mouse.**is\_pressed**](#mouse.is_pressed)
- [mouse.**press**](#mouse.press) *(aliases: `hold`)*
- [mouse.**release**](#mouse.release)
- [mouse.**click**](#mouse.click)
- [mouse.**double\_click**](#mouse.double_click)
- [mouse.**right\_click**](#mouse.right_click)
- [mouse.**wheel**](#mouse.wheel)
- [mouse.**move**](#mouse.move)
- [mouse.**drag**](#mouse.drag)
- [mouse.**on\_button**](#mouse.on_button)
- [mouse.**on\_click**](#mouse.on_click)
- [mouse.**on\_double\_click**](#mouse.on_double_click)
- [mouse.**on\_right\_click**](#mouse.on_right_click)
- [mouse.**on\_middle\_click**](#mouse.on_middle_click)
- [mouse.**wait**](#mouse.wait)
- [mouse.**get\_position**](#mouse.get_position)
- [mouse.**hook**](#mouse.hook)
- [mouse.**unhook**](#mouse.unhook)
- [mouse.**unhook\_all**](#mouse.unhook_all)
- [mouse.**record**](#mouse.record)
- [mouse.**play**](#mouse.play) *(aliases: `replay`)*
<a name="mouse.ButtonEvent"/>
## class mouse.**ButtonEvent**
ButtonEvent(event_type, button, time)
<a name="ButtonEvent.button"/>
### ButtonEvent.**button**
Alias for field number 1
<a name="ButtonEvent.count"/>
### ButtonEvent.**count**(self, value, /)
Return number of occurrences of value.
<a name="ButtonEvent.event_type"/>
### ButtonEvent.**event\_type**
Alias for field number 0
<a name="ButtonEvent.index"/>
### ButtonEvent.**index**(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.
<a name="ButtonEvent.time"/>
### ButtonEvent.**time**
Alias for field number 2
<a name="mouse.DOUBLE"/>
## mouse.**DOUBLE**
```py
= 'double'
```
<a name="mouse.DOWN"/>
## mouse.**DOWN**
```py
= 'down'
```
<a name="mouse.LEFT"/>
## mouse.**LEFT**
```py
= 'left'
```
<a name="mouse.MIDDLE"/>
## mouse.**MIDDLE**
```py
= 'middle'
```
<a name="mouse.MoveEvent"/>
## class mouse.**MoveEvent**
MoveEvent(x, y, time)
<a name="MoveEvent.count"/>
### MoveEvent.**count**(self, value, /)
Return number of occurrences of value.
<a name="MoveEvent.index"/>
### MoveEvent.**index**(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.
<a name="MoveEvent.time"/>
### MoveEvent.**time**
Alias for field number 2
<a name="MoveEvent.x"/>
### MoveEvent.**x**
Alias for field number 0
<a name="MoveEvent.y"/>
### MoveEvent.**y**
Alias for field number 1
<a name="mouse.RIGHT"/>
## mouse.**RIGHT**
```py
= 'right'
```
<a name="mouse.UP"/>
## mouse.**UP**
```py
= 'up'
```
<a name="mouse.WheelEvent"/>
## class mouse.**WheelEvent**
WheelEvent(delta, time)
<a name="WheelEvent.count"/>
### WheelEvent.**count**(self, value, /)
Return number of occurrences of value.
<a name="WheelEvent.delta"/>
### WheelEvent.**delta**
Alias for field number 0
<a name="WheelEvent.index"/>
### WheelEvent.**index**(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.
<a name="WheelEvent.time"/>
### WheelEvent.**time**
Alias for field number 1
<a name="mouse.X"/>
## mouse.**X**
```py
= 'x'
```
<a name="mouse.X2"/>
## mouse.**X2**
```py
= 'x2'
```
<a name="mouse.version"/>
## mouse.**version**
```py
= '0.7.1'
```
<a name="mouse.is_pressed"/>
## mouse.**is\_pressed**(button=&#x27;left&#x27;)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L78)
Returns True if the given button is currently pressed.
<a name="mouse.press"/>
## mouse.**press**(button=&#x27;left&#x27;)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L83)
Presses the given button (but doesn't release).
<a name="mouse.release"/>
## mouse.**release**(button=&#x27;left&#x27;)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L87)
Releases the given button.
<a name="mouse.click"/>
## mouse.**click**(button=&#x27;left&#x27;)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L91)
Sends a click with the given button.
<a name="mouse.double_click"/>
## mouse.**double\_click**(button=&#x27;left&#x27;)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L96)
Sends a double click with the given button.
<a name="mouse.right_click"/>
## mouse.**right\_click**()
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L101)
Sends a right click with the given button.
<a name="mouse.wheel"/>
## mouse.**wheel**(delta=1)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L105)
Scrolls the wheel `delta` clicks. Sign indicates direction.
<a name="mouse.move"/>
## mouse.**move**(x, y, absolute=True, duration=0)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L109)
Moves the mouse. If `absolute`, to position (x, y), otherwise move relative
to the current position. If `duration` is non-zero, animates the movement.
<a name="mouse.drag"/>
## mouse.**drag**(start\_x, start\_y, end\_x, end\_y, absolute=True, duration=0)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L143)
Holds the left mouse button, moving from start to end position, then
releases. `absolute` and `duration` are parameters regarding the mouse
movement.
<a name="mouse.on_button"/>
## mouse.**on\_button**(callback, args=(), buttons=(&#x27;left&#x27;, &#x27;middle&#x27;, &#x27;right&#x27;, &#x27;x&#x27;, &#x27;x2&#x27;), types=(&#x27;up&#x27;, &#x27;down&#x27;, &#x27;double&#x27;))
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L156)
Invokes `callback` with `args` when the specified event happens.
<a name="mouse.on_click"/>
## mouse.**on\_click**(callback, args=())
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L170)
Invokes `callback` with `args` when the left button is clicked.
<a name="mouse.on_double_click"/>
## mouse.**on\_double\_click**(callback, args=())
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L174)
Invokes `callback` with `args` when the left button is double clicked.
<a name="mouse.on_right_click"/>
## mouse.**on\_right\_click**(callback, args=())
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L180)
Invokes `callback` with `args` when the right button is clicked.
<a name="mouse.on_middle_click"/>
## mouse.**on\_middle\_click**(callback, args=())
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L184)
Invokes `callback` with `args` when the middle button is clicked.
<a name="mouse.wait"/>
## mouse.**wait**(button=&#x27;left&#x27;, target\_types=(&#x27;up&#x27;, &#x27;down&#x27;, &#x27;double&#x27;))
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L188)
Blocks program execution until the given button performs an event.
<a name="mouse.get_position"/>
## mouse.**get\_position**()
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L199)
Returns the (x, y) mouse position.
<a name="mouse.hook"/>
## mouse.**hook**(callback)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L203)
Installs a global listener on all available mouses, invoking `callback`
each time it is moved, a key status changes or the wheel is spun. A mouse
event is passed as argument, with type either `mouse.ButtonEvent`,
`mouse.WheelEvent` or `mouse.MoveEvent`.
Returns the given callback for easier development.
<a name="mouse.unhook"/>
## mouse.**unhook**(callback)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L215)
Removes a previously installed hook.
<a name="mouse.unhook_all"/>
## mouse.**unhook\_all**()
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L221)
Removes all hooks registered by this application. Note this may include
hooks installed by high level functions, such as [`record`](#mouse.record).
<a name="mouse.record"/>
## mouse.**record**(button=&#x27;right&#x27;, target\_types=(&#x27;down&#x27;,))
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L228)
Records all mouse events until the user presses the given button.
Then returns the list of events recorded. Pairs well with [`play(events)`](#mouse.play).
Note: this is a blocking function.
Note: for more details on the mouse hook and events see [`hook`](#mouse.hook).
<a name="mouse.play"/>
## mouse.**play**(events, speed\_factor=1.0, include\_clicks=True, include\_moves=True, include\_wheel=True)
[\[source\]](https://github.com/boppreh/mouse/blob/master/mouse/__init__.py#L242)
Plays a sequence of recorded events, maintaining the relative time
intervals. If speed_factor is <= 0 then the actions are replayed as fast
as the OS allows. Pairs well with [`record()`](#mouse.record).
The parameters `include_*` define if events of that type should be inluded
in the replay or ignored.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

91
mouse/make_release.py Normal file
View File

@ -0,0 +1,91 @@
"""
This little guy streamlines the release process of Python packages.
By running `python3 make_release.py` it'll do the following tasks automatically:
- Update README by calling `make_readme.sh` if this file exists.
- Check PyPI RST long_description syntax.
- Show the latest version from CHANGES.md and ask for a new version number.
- Open vim to allow you to edit the list of changes for this new version, showing a list of commits since the last version.
- Prepend your list of changes to CHANGES.md (and ask if you want to commit it now).
- Add a git tag to the current commit.
- Push tag to GitHub.
- Publish a new release to GitHub, asking for the authentication token (optional).
- Publish a new release on PyPI.
Suggested way to organize your project for a smooth process:
- Use Markdown everywhere.
- Keep a description of your project in the package's docstring.
- Generate your README from the package docstring plus API docs.
- Convert your package docstring to RST in setup.py and use that as long_description.
- Use raw semantic versioning for CHANGES.md and PyPI (e.g. 2.3.1), and prepend 'v' for git tags and releases (e.g. v2.3.1).
"""
import re
import sys
import os
from subprocess import run, check_output
import atexit
import requests
import mouse
run(['make', 'clean', 'build'], check=True)
assert re.fullmatch(r'\d+\.\d+\.\d+', mouse.version)
last_version = check_output(['git', 'describe', '--abbrev=0'], universal_newlines=True).strip('v\n')
assert mouse.version != last_version, 'Must update mouse.version first.'
commits = check_output(['git', 'log', 'v{}..HEAD'.format(last_version), '--oneline'], universal_newlines=True)
with open('message.txt', 'w') as message_file:
atexit.register(lambda: os.remove('message.txt'))
message_file.write('\n\n\n')
message_file.write('# Enter changes one per line like this:\n')
message_file.write('# - Added `foobar`.\n\n\n')
message_file.write('# As a reminder, here\'s the last commits since version {}:\n\n'.format(last_version))
for line in commits.strip().split('\n'):
message_file.write('# {}\n'.format(line))
run(['vim', 'message.txt'])
with open('message.txt') as message_file:
lines = [line for line in message_file.readlines() if not line.startswith('#')]
message = ''.join(lines).strip()
if not message:
print('Aborting release due to empty message.')
exit()
with open('message.txt', 'w') as message_file:
message_file.write(message)
with open('CHANGES.md') as changes_file:
old_changes = changes_file.read()
with open('CHANGES.md', 'w') as changes_file:
changes_file.write('# {}\n\n{}\n\n\n{}'.format(mouse.version, message, old_changes))
tag_name = 'v' + mouse.version
if input('Commit README.md and CHANGES.md files? ').lower().startswith('y'):
run(['git', 'add', 'CHANGES.md', 'README.md'])
run(['git', 'commit', '-m', 'Update changes for {}'.format(tag_name)])
run(['git', 'push'])
run(['git', 'tag', '-a', tag_name, '--file', 'message.txt'], check=True)
run(['git', 'push', 'origin', tag_name], check=True)
token = input('To make a release enter your GitHub repo authorization token: ').strip()
if token:
git_remotes = check_output(['git', 'remote', '-v']).decode('utf-8')
repo_path = re.search(r'github.com[:/](.+?)(?:\.git)? \(push\)', git_remotes).group(1)
releases_url = 'https://api.github.com/repos/{}/releases'.format(repo_path)
print(releases_url)
release = {
"tag_name": tag_name,
"target_commitish": "master",
"name": tag_name,
"body": message,
"draft": False,
"prerelease": False,
}
response = requests.post(releases_url, json=release, headers={'Authorization': 'token ' + token})
print(response.status_code, response.text)
run(['twine', 'upload', 'dist/*'], check=True, shell=True)

View File

@ -167,10 +167,6 @@ def on_button(callback, args=(), buttons=(LEFT, MIDDLE, RIGHT, X, X2), types=(UP
_listener.add_handler(handler)
return handler
def on_pressed(callback, args=()):
""" Invokes `callback` with `args` when the left button is pressed. """
return on_button(callback, args, [LEFT], [DOWN])
def on_click(callback, args=()):
""" Invokes `callback` with `args` when the left button is clicked. """
return on_button(callback, args, [LEFT], [UP])

View File

@ -20,8 +20,6 @@ EV_REL = 0x02
EV_ABS = 0x03
EV_MSC = 0x04
INVALID_ARGUMENT_ERRNO = 22
def make_uinput():
import fcntl, struct
@ -31,12 +29,8 @@ def make_uinput():
fcntl.ioctl(uinput, UI_SET_EVBIT, EV_KEY)
UI_SET_KEYBIT = 0x40045565
try:
for i in range(0x300):
fcntl.ioctl(uinput, UI_SET_KEYBIT, i)
except OSError as e:
if e.errno != INVALID_ARGUMENT_ERRNO:
raise e
for i in range(256):
fcntl.ioctl(uinput, UI_SET_KEYBIT, i)
BUS_USB = 0x03
uinput_user_dev = "80sHHHHi64i64i64i64i"

38
mouse/setup.py Normal file
View File

@ -0,0 +1,38 @@
"""
Usage instructions:
- If you are installing: `python setup.py install`
- If you are developing: `python setup.py sdist --format=zip bdist_wheel --universal bdist_wininst && twine check dist/*`
"""
import mouse
from setuptools import setup
setup(
name='mouse',
version=mouse.version,
author='BoppreH',
author_email='boppreh@gmail.com',
packages=['mouse'],
package_data={'mouse': ['*.md']},
url='https://github.com/boppreh/mouse',
license='MIT',
description='Hook and simulate mouse events on Windows and Linux',
keywords = 'mouse hook simulate hotkey',
# Wheel creation breaks with Windows newlines.
# https://github.com/pypa/setuptools/issues/1126
long_description=mouse.__doc__.replace('\r\n', '\n'),
long_description_content_type='text/markdown',
install_requires=[], # OSX-specific dependency
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: MIT License',
'Operating System :: Microsoft :: Windows',
'Operating System :: Unix',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Utilities',
],
)