evdev 1.7.1__tar.gz → 1.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {evdev-1.7.1 → evdev-1.9.0}/LICENSE +1 -1
- {evdev-1.7.1 → evdev-1.9.0}/MANIFEST.in +2 -1
- {evdev-1.7.1/evdev.egg-info → evdev-1.9.0}/PKG-INFO +4 -3
- {evdev-1.7.1 → evdev-1.9.0}/README.md +1 -0
- {evdev-1.7.1 → evdev-1.9.0}/pyproject.toml +12 -6
- {evdev-1.7.1 → evdev-1.9.0}/setup.py +34 -12
- evdev-1.9.0/src/evdev/__init__.py +9 -0
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/device.py +47 -51
- evdev-1.9.0/src/evdev/ecodes.py +5 -0
- evdev-1.7.1/evdev/ecodes.py → evdev-1.9.0/src/evdev/ecodes_runtime.py +15 -5
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/eventio.py +21 -9
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/eventio_async.py +2 -2
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/events.py +33 -31
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/evtest.py +9 -14
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/ff.py +1 -1
- evdev-1.9.0/src/evdev/genecodes_c.py +142 -0
- evdev-1.9.0/src/evdev/genecodes_py.py +53 -0
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/input.c +22 -51
- evdev-1.9.0/src/evdev/py.typed +0 -0
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/uinput.c +2 -23
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/uinput.py +41 -47
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev/util.py +9 -10
- {evdev-1.7.1 → evdev-1.9.0/src/evdev.egg-info}/PKG-INFO +4 -3
- evdev-1.9.0/src/evdev.egg-info/SOURCES.txt +29 -0
- {evdev-1.7.1 → evdev-1.9.0}/tests/test_uinput.py +27 -6
- {evdev-1.7.1 → evdev-1.9.0}/tests/test_util.py +1 -1
- evdev-1.7.1/evdev/__init__.py +0 -10
- evdev-1.7.1/evdev/genecodes.py +0 -96
- evdev-1.7.1/evdev.egg-info/SOURCES.txt +0 -26
- {evdev-1.7.1 → evdev-1.9.0}/setup.cfg +0 -0
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev.egg-info/dependency_links.txt +0 -0
- {evdev-1.7.1 → evdev-1.9.0/src}/evdev.egg-info/top_level.txt +0 -0
- {evdev-1.7.1 → evdev-1.9.0}/tests/test_ecodes.py +0 -0
- {evdev-1.7.1 → evdev-1.9.0}/tests/test_events.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: evdev
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
4
|
Summary: Bindings to the Linux input handling subsystem
|
|
5
5
|
Author-email: Georgi Valkov <georgi.t.valkov@gmail.com>
|
|
6
6
|
Maintainer-email: Tobi <proxima@sezanzeb.de>
|
|
7
|
-
License: Copyright (c) 2012-
|
|
7
|
+
License: Copyright (c) 2012-2025 Georgi Valkov. All rights reserved.
|
|
8
8
|
|
|
9
9
|
Redistribution and use in source and binary forms, with or without
|
|
10
10
|
modification, are permitted provided that the following conditions are
|
|
@@ -43,7 +43,7 @@ Classifier: Intended Audience :: Developers
|
|
|
43
43
|
Classifier: Topic :: Software Development :: Libraries
|
|
44
44
|
Classifier: License :: OSI Approved :: BSD License
|
|
45
45
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
46
|
-
Requires-Python: >=3.
|
|
46
|
+
Requires-Python: >=3.8
|
|
47
47
|
Description-Content-Type: text/markdown
|
|
48
48
|
License-File: LICENSE
|
|
49
49
|
|
|
@@ -52,6 +52,7 @@ License-File: LICENSE
|
|
|
52
52
|
<p>
|
|
53
53
|
<a href="https://pypi.python.org/pypi/evdev"><img alt="pypi version" src="https://img.shields.io/pypi/v/evdev.svg"></a>
|
|
54
54
|
<a href="https://github.com/gvalkov/python-evdev/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/evdev"></a>
|
|
55
|
+
<a href="https://repology.org/project/python:evdev/versions"><img alt="Packaging status" src="https://repology.org/badge/tiny-repos/python:evdev.svg"></a>
|
|
55
56
|
</p>
|
|
56
57
|
|
|
57
58
|
This package provides bindings to the generic input event interface in Linux.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<p>
|
|
4
4
|
<a href="https://pypi.python.org/pypi/evdev"><img alt="pypi version" src="https://img.shields.io/pypi/v/evdev.svg"></a>
|
|
5
5
|
<a href="https://github.com/gvalkov/python-evdev/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/evdev"></a>
|
|
6
|
+
<a href="https://repology.org/project/python:evdev/versions"><img alt="Packaging status" src="https://repology.org/badge/tiny-repos/python:evdev.svg"></a>
|
|
6
7
|
</p>
|
|
7
8
|
|
|
8
9
|
This package provides bindings to the generic input event interface in Linux.
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "evdev"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.9.0"
|
|
8
8
|
description = "Bindings to the Linux input handling subsystem"
|
|
9
9
|
keywords = ["evdev", "input", "uinput"]
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = {file = "LICENSE"}
|
|
12
|
-
requires-python = ">=3.
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
13
|
authors = [
|
|
14
14
|
{ name="Georgi Valkov", email="georgi.t.valkov@gmail.com" },
|
|
15
15
|
]
|
|
@@ -29,9 +29,6 @@ classifiers = [
|
|
|
29
29
|
[project.urls]
|
|
30
30
|
"Homepage" = "https://github.com/gvalkov/python-evdev"
|
|
31
31
|
|
|
32
|
-
[tool.setuptools]
|
|
33
|
-
packages = ["evdev"]
|
|
34
|
-
|
|
35
32
|
[tool.ruff]
|
|
36
33
|
line-length = 120
|
|
37
34
|
|
|
@@ -39,7 +36,7 @@ line-length = 120
|
|
|
39
36
|
ignore = ["E265", "E241", "F403", "F401", "E401", "E731"]
|
|
40
37
|
|
|
41
38
|
[tool.bumpversion]
|
|
42
|
-
current_version = "1.
|
|
39
|
+
current_version = "1.9.0"
|
|
43
40
|
commit = true
|
|
44
41
|
tag = true
|
|
45
42
|
allow_dirty = true
|
|
@@ -49,3 +46,12 @@ filename = "pyproject.toml"
|
|
|
49
46
|
|
|
50
47
|
[[tool.bumpversion.files]]
|
|
51
48
|
filename = "docs/conf.py"
|
|
49
|
+
|
|
50
|
+
[tool.pylint.'MESSAGES CONTROL']
|
|
51
|
+
disable = """
|
|
52
|
+
no-member,
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
[tool.pylint.typecheck]
|
|
56
|
+
generated-members = ["evdev.ecodes.*"]
|
|
57
|
+
ignored-modules= ["evdev._*"]
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
+
import shutil
|
|
3
4
|
import textwrap
|
|
5
|
+
import platform
|
|
4
6
|
from pathlib import Path
|
|
7
|
+
from subprocess import run
|
|
5
8
|
|
|
6
9
|
from setuptools import setup, Extension, Command
|
|
7
10
|
from setuptools.command import build_ext as _build_ext
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
curdir = Path(__file__).resolve().parent
|
|
11
|
-
|
|
14
|
+
ecodes_c_path = curdir / "src/evdev/ecodes.c"
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
def create_ecodes(headers=None):
|
|
@@ -23,7 +26,11 @@ def create_ecodes(headers=None):
|
|
|
23
26
|
include_paths.update(c_inc_path.split(":"))
|
|
24
27
|
|
|
25
28
|
include_paths.add("/usr/include")
|
|
26
|
-
|
|
29
|
+
if platform.system().lower() == "freebsd":
|
|
30
|
+
files = ["dev/evdev/input.h", "dev/evdev/input-event-codes.h", "dev/evdev/uinput.h"]
|
|
31
|
+
else:
|
|
32
|
+
files = ["linux/input.h", "linux/input-event-codes.h", "linux/uinput.h"]
|
|
33
|
+
|
|
27
34
|
headers = [os.path.join(path, file) for path in include_paths for file in files]
|
|
28
35
|
|
|
29
36
|
headers = [header for header in headers if os.path.isfile(header)]
|
|
@@ -47,16 +54,18 @@ def create_ecodes(headers=None):
|
|
|
47
54
|
build_ecodes --evdev-headers path/input.h:path/input-event-codes.h \\
|
|
48
55
|
build_ext --include-dirs path/ \\
|
|
49
56
|
install
|
|
57
|
+
|
|
58
|
+
If you want to avoid building this package from source, then please consider
|
|
59
|
+
installing the `evdev-binary` package instead. Keep in mind that it may not be
|
|
60
|
+
fully compatible with, or support all the features of your current kernel.
|
|
50
61
|
"""
|
|
51
62
|
|
|
52
63
|
sys.stderr.write(textwrap.dedent(msg))
|
|
53
64
|
sys.exit(1)
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
with ecodes_path.open("w") as fh:
|
|
59
|
-
cmd = [sys.executable, "evdev/genecodes.py", *headers]
|
|
66
|
+
print("writing %s (using %s)" % (ecodes_c_path, " ".join(headers)))
|
|
67
|
+
with ecodes_c_path.open("w") as fh:
|
|
68
|
+
cmd = [sys.executable, "src/evdev/genecodes_c.py", "--ecodes", *headers]
|
|
60
69
|
run(cmd, check=True, stdout=fh)
|
|
61
70
|
|
|
62
71
|
|
|
@@ -80,14 +89,27 @@ class build_ecodes(Command):
|
|
|
80
89
|
|
|
81
90
|
class build_ext(_build_ext.build_ext):
|
|
82
91
|
def has_ecodes(self):
|
|
83
|
-
if
|
|
92
|
+
if ecodes_c_path.exists():
|
|
84
93
|
print("ecodes.c already exists ... skipping build_ecodes")
|
|
85
|
-
|
|
94
|
+
return False
|
|
95
|
+
return True
|
|
96
|
+
|
|
97
|
+
def generate_ecodes_py(self):
|
|
98
|
+
ecodes_py = Path(self.build_lib) / "evdev/ecodes.py"
|
|
99
|
+
print(f"writing {ecodes_py}")
|
|
100
|
+
with ecodes_py.open("w") as fh:
|
|
101
|
+
cmd = [sys.executable, "-B", "src/evdev/genecodes_py.py"]
|
|
102
|
+
res = run(cmd, env={"PYTHONPATH": self.build_lib}, stdout=fh)
|
|
103
|
+
|
|
104
|
+
if res.returncode != 0:
|
|
105
|
+
print(f"failed to generate static {ecodes_py} - will use ecodes_runtime.py")
|
|
106
|
+
shutil.copy("src/evdev/ecodes_runtime.py", ecodes_py)
|
|
86
107
|
|
|
87
108
|
def run(self):
|
|
88
109
|
for cmd_name in self.get_sub_commands():
|
|
89
110
|
self.run_command(cmd_name)
|
|
90
111
|
_build_ext.build_ext.run(self)
|
|
112
|
+
self.generate_ecodes_py()
|
|
91
113
|
|
|
92
114
|
sub_commands = [("build_ecodes", has_ecodes)] + _build_ext.build_ext.sub_commands
|
|
93
115
|
|
|
@@ -95,9 +117,9 @@ class build_ext(_build_ext.build_ext):
|
|
|
95
117
|
cflags = ["-std=c99", "-Wno-error=declaration-after-statement"]
|
|
96
118
|
setup(
|
|
97
119
|
ext_modules=[
|
|
98
|
-
Extension("evdev._input", sources=["evdev/input.c"], extra_compile_args=cflags),
|
|
99
|
-
Extension("evdev._uinput", sources=["evdev/uinput.c"], extra_compile_args=cflags),
|
|
100
|
-
Extension("evdev._ecodes", sources=["evdev/ecodes.c"], extra_compile_args=cflags),
|
|
120
|
+
Extension("evdev._input", sources=["src/evdev/input.c"], extra_compile_args=cflags),
|
|
121
|
+
Extension("evdev._uinput", sources=["src/evdev/uinput.c"], extra_compile_args=cflags),
|
|
122
|
+
Extension("evdev._ecodes", sources=["src/evdev/ecodes.c"], extra_compile_args=cflags),
|
|
101
123
|
],
|
|
102
124
|
cmdclass={
|
|
103
125
|
"build_ext": build_ext,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# Gather everything into a single, convenient namespace.
|
|
3
|
+
# --------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
from . import ecodes, ff
|
|
6
|
+
from .device import AbsInfo, DeviceInfo, EvdevError, InputDevice
|
|
7
|
+
from .events import AbsEvent, InputEvent, KeyEvent, RelEvent, SynEvent, event_factory
|
|
8
|
+
from .uinput import UInput, UInputError
|
|
9
|
+
from .util import categorize, list_devices, resolve_ecodes, resolve_ecodes_dict
|
|
@@ -1,31 +1,19 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
import warnings
|
|
5
1
|
import contextlib
|
|
6
|
-
import
|
|
2
|
+
import os
|
|
3
|
+
from typing import NamedTuple, Tuple, Union
|
|
7
4
|
|
|
8
|
-
from
|
|
9
|
-
from evdev.events import InputEvent
|
|
5
|
+
from . import _input, ecodes, util
|
|
10
6
|
|
|
11
7
|
try:
|
|
12
|
-
from
|
|
8
|
+
from .eventio_async import EvdevError, EventIO
|
|
13
9
|
except ImportError:
|
|
14
|
-
from
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# --------------------------------------------------------------------------
|
|
18
|
-
_AbsInfo = collections.namedtuple("AbsInfo", ["value", "min", "max", "fuzz", "flat", "resolution"])
|
|
10
|
+
from .eventio import EvdevError, EventIO
|
|
19
11
|
|
|
20
|
-
_KbdInfo = collections.namedtuple("KbdInfo", ["repeat", "delay"])
|
|
21
12
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class AbsInfo(_AbsInfo):
|
|
13
|
+
class AbsInfo(NamedTuple):
|
|
26
14
|
"""Absolute axis information.
|
|
27
15
|
|
|
28
|
-
A ``namedtuple``
|
|
16
|
+
A ``namedtuple`` with absolute axis information -
|
|
29
17
|
corresponds to the ``input_absinfo`` struct:
|
|
30
18
|
|
|
31
19
|
Attributes
|
|
@@ -61,28 +49,38 @@ class AbsInfo(_AbsInfo):
|
|
|
61
49
|
|
|
62
50
|
"""
|
|
63
51
|
|
|
52
|
+
value: int
|
|
53
|
+
min: int
|
|
54
|
+
max: int
|
|
55
|
+
fuzz: int
|
|
56
|
+
flat: int
|
|
57
|
+
resolution: int
|
|
58
|
+
|
|
64
59
|
def __str__(self):
|
|
65
|
-
return "
|
|
60
|
+
return "value {}, min {}, max {}, fuzz {}, flat {}, res {}".format(*self) # pylint: disable=not-an-iterable
|
|
66
61
|
|
|
67
62
|
|
|
68
|
-
class KbdInfo(
|
|
63
|
+
class KbdInfo(NamedTuple):
|
|
69
64
|
"""Keyboard repeat rate.
|
|
70
65
|
|
|
71
66
|
Attributes
|
|
72
67
|
----------
|
|
73
|
-
repeat
|
|
74
|
-
Keyboard repeat rate in characters per second.
|
|
75
|
-
|
|
76
68
|
delay
|
|
77
69
|
Amount of time that a key must be depressed before it will start
|
|
78
70
|
to repeat (in milliseconds).
|
|
71
|
+
|
|
72
|
+
repeat
|
|
73
|
+
Keyboard repeat rate in characters per second.
|
|
79
74
|
"""
|
|
80
75
|
|
|
76
|
+
delay: int
|
|
77
|
+
repeat: int
|
|
78
|
+
|
|
81
79
|
def __str__(self):
|
|
82
|
-
return "
|
|
80
|
+
return "delay {}, repeat {}".format(self.delay, self.repeat)
|
|
83
81
|
|
|
84
82
|
|
|
85
|
-
class DeviceInfo(
|
|
83
|
+
class DeviceInfo(NamedTuple):
|
|
86
84
|
"""
|
|
87
85
|
Attributes
|
|
88
86
|
----------
|
|
@@ -92,9 +90,14 @@ class DeviceInfo(_DeviceInfo):
|
|
|
92
90
|
version
|
|
93
91
|
"""
|
|
94
92
|
|
|
93
|
+
bustype: int
|
|
94
|
+
vendor: int
|
|
95
|
+
product: int
|
|
96
|
+
version: int
|
|
97
|
+
|
|
95
98
|
def __str__(self):
|
|
96
99
|
msg = "bus: {:04x}, vendor {:04x}, product {:04x}, version {:04x}"
|
|
97
|
-
return msg.format(*self)
|
|
100
|
+
return msg.format(*self) # pylint: disable=not-an-iterable
|
|
98
101
|
|
|
99
102
|
|
|
100
103
|
class InputDevice(EventIO):
|
|
@@ -104,7 +107,7 @@ class InputDevice(EventIO):
|
|
|
104
107
|
|
|
105
108
|
__slots__ = ("path", "fd", "info", "name", "phys", "uniq", "_rawcapabilities", "version", "ff_effects_count")
|
|
106
109
|
|
|
107
|
-
def __init__(self, dev):
|
|
110
|
+
def __init__(self, dev: Union[str, bytes, os.PathLike]):
|
|
108
111
|
"""
|
|
109
112
|
Arguments
|
|
110
113
|
---------
|
|
@@ -115,15 +118,14 @@ class InputDevice(EventIO):
|
|
|
115
118
|
#: Path to input device.
|
|
116
119
|
self.path = dev if not hasattr(dev, "__fspath__") else dev.__fspath__()
|
|
117
120
|
|
|
118
|
-
# Certain operations are possible only when the device is opened in
|
|
119
|
-
# read-write mode.
|
|
121
|
+
# Certain operations are possible only when the device is opened in read-write mode.
|
|
120
122
|
try:
|
|
121
123
|
fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
|
|
122
124
|
except OSError:
|
|
123
125
|
fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
|
|
124
126
|
|
|
125
127
|
#: A non-blocking file descriptor to the device file.
|
|
126
|
-
self.fd = fd
|
|
128
|
+
self.fd: int = fd
|
|
127
129
|
|
|
128
130
|
# Returns (bustype, vendor, product, version, name, phys, capabilities).
|
|
129
131
|
info_res = _input.ioctl_devinfo(self.fd)
|
|
@@ -132,16 +134,16 @@ class InputDevice(EventIO):
|
|
|
132
134
|
self.info = DeviceInfo(*info_res[:4])
|
|
133
135
|
|
|
134
136
|
#: The name of the event device.
|
|
135
|
-
self.name = info_res[4]
|
|
137
|
+
self.name: str = info_res[4]
|
|
136
138
|
|
|
137
139
|
#: The physical topology of the device.
|
|
138
|
-
self.phys = info_res[5]
|
|
140
|
+
self.phys: str = info_res[5]
|
|
139
141
|
|
|
140
142
|
#: The unique identifier of the device.
|
|
141
|
-
self.uniq = info_res[6]
|
|
143
|
+
self.uniq: str = info_res[6]
|
|
142
144
|
|
|
143
145
|
#: The evdev protocol version.
|
|
144
|
-
self.version = _input.ioctl_EVIOCGVERSION(self.fd)
|
|
146
|
+
self.version: int = _input.ioctl_EVIOCGVERSION(self.fd)
|
|
145
147
|
|
|
146
148
|
#: The raw dictionary of device capabilities - see `:func:capabilities()`.
|
|
147
149
|
self._rawcapabilities = _input.ioctl_capabilities(self.fd)
|
|
@@ -156,7 +158,7 @@ class InputDevice(EventIO):
|
|
|
156
158
|
except (OSError, ImportError, AttributeError):
|
|
157
159
|
pass
|
|
158
160
|
|
|
159
|
-
def _capabilities(self, absinfo=True):
|
|
161
|
+
def _capabilities(self, absinfo: bool = True):
|
|
160
162
|
res = {}
|
|
161
163
|
|
|
162
164
|
for etype, _ecodes in self._rawcapabilities.items():
|
|
@@ -174,7 +176,7 @@ class InputDevice(EventIO):
|
|
|
174
176
|
|
|
175
177
|
return res
|
|
176
178
|
|
|
177
|
-
def capabilities(self, verbose=False, absinfo=True):
|
|
179
|
+
def capabilities(self, verbose: bool = False, absinfo: bool = True):
|
|
178
180
|
"""
|
|
179
181
|
Return the event types that this device supports as a mapping of
|
|
180
182
|
supported event types to lists of handled event codes.
|
|
@@ -219,7 +221,7 @@ class InputDevice(EventIO):
|
|
|
219
221
|
else:
|
|
220
222
|
return self._capabilities(absinfo)
|
|
221
223
|
|
|
222
|
-
def input_props(self, verbose=False):
|
|
224
|
+
def input_props(self, verbose: bool = False):
|
|
223
225
|
"""
|
|
224
226
|
Get device properties and quirks.
|
|
225
227
|
|
|
@@ -240,7 +242,7 @@ class InputDevice(EventIO):
|
|
|
240
242
|
|
|
241
243
|
return props
|
|
242
244
|
|
|
243
|
-
def leds(self, verbose=False):
|
|
245
|
+
def leds(self, verbose: bool = False):
|
|
244
246
|
"""
|
|
245
247
|
Return currently set LED keys.
|
|
246
248
|
|
|
@@ -261,7 +263,7 @@ class InputDevice(EventIO):
|
|
|
261
263
|
|
|
262
264
|
return leds
|
|
263
265
|
|
|
264
|
-
def set_led(self, led_num, value):
|
|
266
|
+
def set_led(self, led_num: int, value: int):
|
|
265
267
|
"""
|
|
266
268
|
Set the state of the selected LED.
|
|
267
269
|
|
|
@@ -331,7 +333,7 @@ class InputDevice(EventIO):
|
|
|
331
333
|
yield
|
|
332
334
|
self.ungrab()
|
|
333
335
|
|
|
334
|
-
def upload_effect(self, effect):
|
|
336
|
+
def upload_effect(self, effect: "ff.Effect"):
|
|
335
337
|
"""
|
|
336
338
|
Upload a force feedback effect to a force feedback device.
|
|
337
339
|
"""
|
|
@@ -358,10 +360,10 @@ class InputDevice(EventIO):
|
|
|
358
360
|
return KbdInfo(*_input.ioctl_EVIOCGREP(self.fd))
|
|
359
361
|
|
|
360
362
|
@repeat.setter
|
|
361
|
-
def repeat(self, value):
|
|
363
|
+
def repeat(self, value: Tuple[int, int]):
|
|
362
364
|
return _input.ioctl_EVIOCSREP(self.fd, *value)
|
|
363
365
|
|
|
364
|
-
def active_keys(self, verbose=False):
|
|
366
|
+
def active_keys(self, verbose: bool = False):
|
|
365
367
|
"""
|
|
366
368
|
Return currently active keys.
|
|
367
369
|
|
|
@@ -384,13 +386,7 @@ class InputDevice(EventIO):
|
|
|
384
386
|
|
|
385
387
|
return active_keys
|
|
386
388
|
|
|
387
|
-
|
|
388
|
-
def fn(self):
|
|
389
|
-
msg = "Please use {0}.path instead of {0}.fn".format(self.__class__.__name__)
|
|
390
|
-
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
391
|
-
return self.path
|
|
392
|
-
|
|
393
|
-
def absinfo(self, axis_num):
|
|
389
|
+
def absinfo(self, axis_num: int):
|
|
394
390
|
"""
|
|
395
391
|
Return current :class:`AbsInfo` for input device axis
|
|
396
392
|
|
|
@@ -406,7 +402,7 @@ class InputDevice(EventIO):
|
|
|
406
402
|
"""
|
|
407
403
|
return AbsInfo(*_input.ioctl_EVIOCGABS(self.fd, axis_num))
|
|
408
404
|
|
|
409
|
-
def set_absinfo(self, axis_num, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None):
|
|
405
|
+
def set_absinfo(self, axis_num: int, value=None, min=None, max=None, fuzz=None, flat=None, resolution=None):
|
|
410
406
|
"""
|
|
411
407
|
Update :class:`AbsInfo` values. Only specified values will be overwritten.
|
|
412
408
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint: disable=undefined-variable
|
|
1
2
|
"""
|
|
2
3
|
This modules exposes the integer constants defined in ``linux/input.h`` and
|
|
3
4
|
``linux/input-event-codes.h``.
|
|
@@ -32,26 +33,26 @@ Keep in mind that values in reverse mappings may point to one or more event
|
|
|
32
33
|
codes. For example::
|
|
33
34
|
|
|
34
35
|
>>> evdev.ecodes.FF[80]
|
|
35
|
-
|
|
36
|
+
('FF_EFFECT_MIN', 'FF_RUMBLE')
|
|
36
37
|
|
|
37
38
|
>>> evdev.ecodes.FF[81]
|
|
38
39
|
'FF_PERIODIC'
|
|
39
40
|
"""
|
|
40
41
|
|
|
41
42
|
from inspect import getmembers
|
|
42
|
-
from evdev import _ecodes
|
|
43
43
|
|
|
44
|
+
from . import _ecodes
|
|
44
45
|
|
|
45
46
|
#: Mapping of names to values.
|
|
46
47
|
ecodes = {}
|
|
47
48
|
|
|
48
|
-
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP"
|
|
49
|
+
prefixes = "KEY ABS REL SW MSC LED BTN REP SND ID EV BUS SYN FF_STATUS FF INPUT_PROP".split()
|
|
49
50
|
prev_prefix = ""
|
|
50
51
|
g = globals()
|
|
51
52
|
|
|
52
53
|
# eg. code: 'REL_Z', val: 2
|
|
53
54
|
for code, val in getmembers(_ecodes):
|
|
54
|
-
for prefix in prefixes
|
|
55
|
+
for prefix in prefixes: # eg. 'REL'
|
|
55
56
|
if code.startswith(prefix):
|
|
56
57
|
ecodes[code] = val
|
|
57
58
|
# FF_STATUS codes should not appear in the FF reverse mapping
|
|
@@ -70,6 +71,15 @@ for code, val in getmembers(_ecodes):
|
|
|
70
71
|
|
|
71
72
|
prev_prefix = prefix
|
|
72
73
|
|
|
74
|
+
|
|
75
|
+
# Convert lists to tuples.
|
|
76
|
+
k, v = None, None
|
|
77
|
+
for prefix in prefixes:
|
|
78
|
+
for k, v in g[prefix].items():
|
|
79
|
+
if isinstance(v, list):
|
|
80
|
+
g[prefix][k] = tuple(v)
|
|
81
|
+
|
|
82
|
+
|
|
73
83
|
#: Keys are a combination of all BTN and KEY codes.
|
|
74
84
|
keys = {}
|
|
75
85
|
keys.update(BTN)
|
|
@@ -98,4 +108,4 @@ bytype = {
|
|
|
98
108
|
from evdev._ecodes import *
|
|
99
109
|
|
|
100
110
|
# cheaper than whitelisting in an __all__
|
|
101
|
-
del code, val, prefix, getmembers, g, d, prefixes, prev_prefix
|
|
111
|
+
del code, val, prefix, getmembers, g, d, k, v, prefixes, prev_prefix
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import fcntl
|
|
3
|
-
import select
|
|
4
2
|
import functools
|
|
3
|
+
import os
|
|
4
|
+
import select
|
|
5
|
+
from typing import Iterator, Union
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
7
|
+
from . import _input, _uinput, ecodes
|
|
8
|
+
from .events import InputEvent
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
# --------------------------------------------------------------------------
|
|
@@ -35,7 +36,7 @@ class EventIO:
|
|
|
35
36
|
"""
|
|
36
37
|
return self.fd
|
|
37
38
|
|
|
38
|
-
def read_loop(self):
|
|
39
|
+
def read_loop(self) -> Iterator[InputEvent]:
|
|
39
40
|
"""
|
|
40
41
|
Enter an endless :func:`select.select()` loop that yields input events.
|
|
41
42
|
"""
|
|
@@ -45,7 +46,7 @@ class EventIO:
|
|
|
45
46
|
for event in self.read():
|
|
46
47
|
yield event
|
|
47
48
|
|
|
48
|
-
def read_one(self):
|
|
49
|
+
def read_one(self) -> Union[InputEvent, None]:
|
|
49
50
|
"""
|
|
50
51
|
Read and return a single input event as an instance of
|
|
51
52
|
:class:`InputEvent <evdev.events.InputEvent>`.
|
|
@@ -59,19 +60,20 @@ class EventIO:
|
|
|
59
60
|
if event:
|
|
60
61
|
return InputEvent(*event)
|
|
61
62
|
|
|
62
|
-
def read(self):
|
|
63
|
+
def read(self) -> Iterator[InputEvent]:
|
|
63
64
|
"""
|
|
64
65
|
Read multiple input events from device. Return a generator object that
|
|
65
66
|
yields :class:`InputEvent <evdev.events.InputEvent>` instances. Raises
|
|
66
67
|
`BlockingIOError` if there are no available events at the moment.
|
|
67
68
|
"""
|
|
68
69
|
|
|
69
|
-
# events ->
|
|
70
|
+
# events -> ((sec, usec, type, code, val), ...)
|
|
70
71
|
events = _input.device_read_many(self.fd)
|
|
71
72
|
|
|
72
73
|
for event in events:
|
|
73
74
|
yield InputEvent(*event)
|
|
74
75
|
|
|
76
|
+
# pylint: disable=no-self-argument
|
|
75
77
|
def need_write(func):
|
|
76
78
|
"""
|
|
77
79
|
Decorator that raises :class:`EvdevError` if there is no write access to the
|
|
@@ -82,6 +84,7 @@ class EventIO:
|
|
|
82
84
|
def wrapper(*args):
|
|
83
85
|
fd = args[0].fd
|
|
84
86
|
if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR:
|
|
87
|
+
# pylint: disable=not-callable
|
|
85
88
|
return func(*args)
|
|
86
89
|
msg = 'no write access to device "%s"' % args[0].path
|
|
87
90
|
raise EvdevError(msg)
|
|
@@ -112,7 +115,7 @@ class EventIO:
|
|
|
112
115
|
self.write(event.type, event.code, event.value)
|
|
113
116
|
|
|
114
117
|
@need_write
|
|
115
|
-
def write(self, etype, code, value):
|
|
118
|
+
def write(self, etype: int, code: int, value: int):
|
|
116
119
|
"""
|
|
117
120
|
Inject an input event into the input subsystem. Events are
|
|
118
121
|
queued until a synchronization event is received.
|
|
@@ -136,5 +139,14 @@ class EventIO:
|
|
|
136
139
|
|
|
137
140
|
_uinput.write(self.fd, etype, code, value)
|
|
138
141
|
|
|
142
|
+
def syn(self):
|
|
143
|
+
"""
|
|
144
|
+
Inject a ``SYN_REPORT`` event into the input subsystem. Events
|
|
145
|
+
queued by :func:`write()` will be fired. If possible, events
|
|
146
|
+
will be merged into an 'atomic' event.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
self.write(ecodes.EV_SYN, ecodes.SYN_REPORT, 0)
|
|
150
|
+
|
|
139
151
|
def close(self):
|
|
140
152
|
pass
|