Skip to content

Commit 673734e

Browse files
New functions: toggle(), is_pressed(), is_valid_code()
1 parent 6573988 commit 673734e

3 files changed

Lines changed: 130 additions & 54 deletions

File tree

src/__init__.py

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
]
5555

5656
class Driver(object):
57-
5857
"""Device driver for the Linux uinput-system.
5958
6059
For the documentation of the constructor arguments, see the
@@ -63,7 +62,7 @@ class Driver(object):
6362

6463
def __init__(self, name="python-uinput", bustype=_suinput.BUS_VIRTUAL,
6564
vendor=0, product=0, version=0):
66-
self._input_fd = _suinput.open(name, bustype, vendor, product, version)
65+
self._context = _suinput.open(name, bustype, vendor, product, version)
6766
self._name = name
6867
self._bustype = bustype
6968
self._vendor = vendor
@@ -72,7 +71,7 @@ def __init__(self, name="python-uinput", bustype=_suinput.BUS_VIRTUAL,
7271

7372
@property
7473
def name(self):
75-
"Kernel name of the device."
74+
"Name of the device."
7675
return self._name
7776

7877
@property
@@ -84,66 +83,88 @@ def bustype(self):
8483

8584
@property
8685
def vendor(self):
87-
"""Vendor number of the device."""
86+
"""Arbitrary 16 bit unsigned integer vendor id."""
8887
return self._vendor
8988

9089
@property
9190
def product(self):
92-
"""Product number of the device."""
91+
"""Arbitrary 16 bit unsigned integer product id."""
9392
return self._product
9493

9594
@property
9695
def version(self):
97-
"""Version number of the device."""
96+
"""Arbitrary 16 bit unsigned integer version number."""
9897
return self._version
9998

10099
def move_pointer(self, x, y):
101100
"""Sends a relative pointer motion event to the event device.
102101
Values increase towards right-bottom.
103102
"""
104-
_suinput.move_pointer(self._input_fd, x, y)
103+
_suinput.move_pointer(self._context, x, y)
105104

106-
def press(self, uinput_code):
105+
def press(self, code):
107106
"""Sends a press event to the event device. Event is repeated after
108107
a short delay until a release event is sent.
109108
110-
`uinput_code` must be one of the constant values defined in
109+
code must be one of the constant values defined in
111110
uinput.codes -module.
112111
"""
113-
_suinput.press(self._input_fd, uinput_code)
112+
_suinput.press(self._context, code)
114113

115-
def release(self, uinput_code):
114+
def release(self, code):
116115
"""Sends a release event to the event device.
117116
118-
`uinput_code` must be one of the constant values defined in
117+
code must be one of the constant values defined in
119118
uinput.codes -module.
120119
"""
121-
_suinput.release(self._input_fd, uinput_code)
120+
_suinput.release(self._context, code)
122121

123-
def click(self, uinput_code):
122+
def click(self, code):
124123
"""Sends a press and release events to the event device.
125124
126-
`uinput_code` must be one of the constant values defined in
125+
code must be one of the constant values defined in
127126
uinput.codes -module.
128127
129128
This method is provided as a convenience and has effectively the
130129
same result as calling press() and release() sequentially.
131130
"""
132-
_suinput.click(self._input_fd, uinput_code)
131+
_suinput.click(self._context, code)
133132

134-
def press_release(self, signed_uinput_code):
135-
"""Sends a press or a release event to the event device. The sign
136-
of the `signed_uinput_code` determines which type of event is sent.
137-
Positive `signed_uinput_code` means press and negative means release.
133+
def press_release(self, signed_code):
134+
"""Sends a press or a release event to the event device.
135+
The sign of the signed_code determines which type of event is sent.
136+
Positive signed_code means press and negative means release.
138137
139-
Absolute value of `signed_uinput_code` must be one of the constant
140-
values defined in uinput.codes -module.
138+
Absolute value of signed_code must be one of the constant
139+
values defined in uinput.codes module.
141140
142141
This method is provided as a convenience and has effectively the
143-
same result as calling press() when the value of `signed_uinput_code`
142+
same result as calling press() when the value of signed_code
144143
is positive and release() when negative.
145144
"""
146-
_suinput.press_release(self._input_fd, signed_uinput_code)
145+
_suinput.press_release(self._context, signed_code)
146+
147+
def toggle(self, code):
148+
"""Press button if it is not pressed currently, release it otherwise.
149+
150+
code must be one of the constant values defined in
151+
uinput.codes -module.
152+
153+
This method is provided as a convenience and has effectively the
154+
same result as calling press() if is_pressed() returns False
155+
and release() otherwise.
156+
"""
157+
_suinput.toggle(self._context, code)
158+
159+
def is_pressed(self, code):
160+
"""Return True if button is pressed, False otherwise.
161+
162+
code must be one of the constant values defined in
163+
uinput.codes -module.
164+
"""
165+
return _suinput.is_pressed(self._context, code)
147166

148167
def __del__(self):
149-
_suinput.close(self._input_fd)
168+
_suinput.close(self._context)
169+
170+
is_valid_code = _suinput.is_valid_code

src/codes.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ PyMODINIT_FUNC initcodes(void)
3030
PyObject *module;
3131
module = Py_InitModule3("codes", codesMethods,
3232
"Button and key codes used in Linux input system");
33-
PyModule_AddIntMacro(module, KEY_RESERVED);
3433
PyModule_AddIntMacro(module, KEY_ESC);
3534
PyModule_AddIntMacro(module, KEY_1);
3635
PyModule_AddIntMacro(module, KEY_2);

src/pysuinput.c

Lines changed: 84 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,82 +32,126 @@ static PyObject *pysuinput_open(PyObject *self, PyObject *args)
3232
&version))
3333
return NULL;
3434
struct input_id id = {bustype, vendor, product, version};
35-
int uinput_fd = suinput_open(name, &id);
36-
if (uinput_fd == -1)
35+
struct suinput_driver *c_driver = suinput_open(name, &id);
36+
if (c_driver == NULL)
3737
return PyErr_SetFromErrno(PyExc_IOError);
38-
return Py_BuildValue("i", uinput_fd);
38+
return PyCObject_FromVoidPtr((void *)c_driver, NULL);
3939
}
4040

4141
static PyObject *pysuinput_close(PyObject *self, PyObject *args)
4242
{
43-
int uinput_fd;
44-
if (!PyArg_ParseTuple(args, "i", &uinput_fd))
43+
PyObject *py_driver;
44+
struct suinput_driver *c_driver;
45+
if (!PyArg_ParseTuple(args, "O", &py_driver))
4546
return NULL;
46-
if (suinput_close(uinput_fd) == -1)
47+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
48+
if (suinput_close(c_driver) == -1)
4749
return PyErr_SetFromErrno(PyExc_IOError);
4850
Py_RETURN_NONE;
4951
}
5052

5153
static PyObject *pysuinput_press(PyObject *self, PyObject *args)
5254
{
53-
int uinput_fd;
55+
PyObject *py_driver;
56+
struct suinput_driver *c_driver;
5457
uint16_t code;
55-
if (!PyArg_ParseTuple(args, "iH", &uinput_fd, &code))
58+
if (!PyArg_ParseTuple(args, "OH", &py_driver, &code))
5659
return NULL;
57-
if (suinput_press(uinput_fd, code) == -1)
60+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
61+
if (suinput_press(c_driver, code) == -1)
5862
return PyErr_SetFromErrno(PyExc_IOError);
5963
Py_RETURN_NONE;
6064
}
6165

6266
static PyObject *pysuinput_release(PyObject *self, PyObject *args)
6367
{
64-
int uinput_fd;
68+
PyObject *py_driver;
69+
struct suinput_driver *c_driver;
6570
uint16_t code;
66-
if (!PyArg_ParseTuple(args, "iH", &uinput_fd, &code))
71+
if (!PyArg_ParseTuple(args, "OH", &py_driver, &code))
6772
return NULL;
68-
if (suinput_release(uinput_fd, code) == -1)
73+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
74+
if (suinput_release(c_driver, code) == -1)
6975
return PyErr_SetFromErrno(PyExc_IOError);
7076
Py_RETURN_NONE;
7177
}
7278

7379
static PyObject *pysuinput_click(PyObject *self, PyObject *args)
7480
{
75-
int uinput_fd;
81+
PyObject *py_driver;
82+
struct suinput_driver *c_driver;
7683
uint16_t code;
77-
if (!PyArg_ParseTuple(args, "iH", &uinput_fd, &code))
84+
if (!PyArg_ParseTuple(args, "OH", &py_driver, &code))
7885
return NULL;
79-
if (suinput_click(uinput_fd, code) == -1)
86+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
87+
if (suinput_click(c_driver, code) == -1)
8088
return PyErr_SetFromErrno(PyExc_IOError);
8189
Py_RETURN_NONE;
8290
}
8391

8492
static PyObject *pysuinput_move_pointer(PyObject *self, PyObject *args)
8593
{
86-
int uinput_fd;
94+
PyObject *py_driver;
95+
struct suinput_driver *c_driver;
8796
int32_t x;
8897
int32_t y;
89-
if (!PyArg_ParseTuple(args, "iii", &uinput_fd, &x, &y)) {
98+
if (!PyArg_ParseTuple(args, "Oii", &py_driver, &x, &y)) {
9099
return NULL;
91100
}
92-
if (suinput_move_pointer(uinput_fd, x, y) == -1)
101+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
102+
if (suinput_move_pointer(c_driver, x, y) == -1)
93103
return PyErr_SetFromErrno(PyExc_IOError);
94104
Py_RETURN_NONE;
95105
}
96106

97107
static PyObject *pysuinput_press_release(PyObject *self, PyObject *args)
98108
{
99-
int uinput_fd;
109+
PyObject *py_driver;
110+
struct suinput_driver *c_driver;
100111
int16_t code;
101-
if (!PyArg_ParseTuple(args, "ih", &uinput_fd, &code))
112+
if (!PyArg_ParseTuple(args, "Oh", &py_driver, &code))
102113
return NULL;
103-
if (suinput_press_release(uinput_fd, code) == -1)
114+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
115+
if (suinput_press_release(c_driver, code) == -1)
104116
return PyErr_SetFromErrno(PyExc_IOError);
105117
Py_RETURN_NONE;
106118
}
107119

120+
static PyObject *pysuinput_toggle(PyObject *self, PyObject *args)
121+
{
122+
PyObject *py_driver;
123+
struct suinput_driver *c_driver;
124+
uint16_t code;
125+
if (!PyArg_ParseTuple(args, "OH", &py_driver, &code))
126+
return NULL;
127+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
128+
if (suinput_toggle(c_driver, code) == -1)
129+
return PyErr_SetFromErrno(PyExc_IOError);
130+
Py_RETURN_NONE;
131+
}
132+
133+
static PyObject *pysuinput_is_pressed(PyObject *self, PyObject *args)
134+
{
135+
PyObject *py_driver;
136+
struct suinput_driver *c_driver;
137+
uint16_t code;
138+
if (!PyArg_ParseTuple(args, "OH", &py_driver, &code))
139+
return NULL;
140+
c_driver = (struct suinput_driver *)PyCObject_AsVoidPtr(py_driver);
141+
return PyBool_FromLong(suinput_is_pressed(c_driver, code));
142+
}
143+
144+
static PyObject *pysuinput_is_valid_code(PyObject *self, PyObject *args)
145+
{
146+
uint16_t code;
147+
if (!PyArg_ParseTuple(args, "H", &code))
148+
return NULL;
149+
return PyBool_FromLong(suinput_is_valid_code(code));
150+
}
151+
108152
static PyMethodDef pysuinputMethods[] = {
109153
{"open", pysuinput_open, METH_VARARGS,
110-
"open(str(name), int(bustype), int(vendor), int(product), int(version))\n\n"
154+
"open(name, bustype, vendor, product, version)\n\n"
111155
"Creates and opens a connection to the event device. Returns an uinput\n"
112156
"file descriptor on success. On error, -1 is returned, and errno is set\n"
113157
"appropriately.\n"
@@ -117,7 +161,7 @@ static PyMethodDef pysuinputMethods[] = {
117161
},
118162

119163
{"close", pysuinput_close, METH_VARARGS,
120-
"close(int(uinput_fd))\n\n"
164+
"close(driver)\n\n"
121165
"Destroys and closes a connection to the event device. Returns 0 on\n"
122166
"success. On error, -1 is returned, and errno is set appropriately.\n"
123167
"\n"
@@ -126,7 +170,7 @@ static PyMethodDef pysuinputMethods[] = {
126170
},
127171

128172
{"click", pysuinput_click, METH_VARARGS,
129-
"click(int(uinput_fd), int(code))\n\n"
173+
"click(driver, code)\n\n"
130174
"Sends a press and release events to the event device. Returns 0 on\n"
131175
"success. On error, -1 is returned, and errno is set appropriately.\n"
132176
"\n"
@@ -142,7 +186,7 @@ static PyMethodDef pysuinputMethods[] = {
142186
},
143187

144188
{"press", pysuinput_press, METH_VARARGS,
145-
"press(int(uinput_fd), int(code))\n\n"
189+
"press(driver, code)\n\n"
146190
"Sends a press event to the event device. Event is repeated after\n"
147191
"a short delay until a release event is sent. Returns 0 on success.\n"
148192
"On error, -1 is returned, and errno is set appropriately.\n"
@@ -155,7 +199,7 @@ static PyMethodDef pysuinputMethods[] = {
155199
},
156200

157201
{"release", pysuinput_release, METH_VARARGS,
158-
"release(int(uinput_fd), int(code))\n\n"
202+
"release(driver, code)\n\n"
159203
"Sends a release event to the event device. Returns 0 on success.\n"
160204
"On error, -1 is returned, and errno is set appropriately.\n"
161205
"\n"
@@ -167,7 +211,7 @@ static PyMethodDef pysuinputMethods[] = {
167211
},
168212

169213
{"move_pointer", pysuinput_move_pointer, METH_VARARGS,
170-
"move_pointer(int(uinput_fd), int(x), int(y))\n\n"
214+
"move_pointer(driver, x, y)\n\n"
171215
"Sends a relative pointer motion event to the event device. Values\n"
172216
"increase towards right-bottom. Returns 0 on success. On error, -1\n"
173217
"is returned, and errno is set appropriately.\n"
@@ -177,7 +221,7 @@ static PyMethodDef pysuinputMethods[] = {
177221
},
178222

179223
{"press_release", pysuinput_press_release, METH_VARARGS,
180-
"press_release(int(uinput_fd), int(signed_code))\n\n"
224+
"press_release(driver, signed_code)\n\n"
181225
"Sends a press or a release event to the event device. The sign of\n"
182226
"`code` determines which type of event is sent. Positive `code`\n"
183227
"means press and negative `code` means release. Returns 0 on\n"
@@ -195,6 +239,18 @@ static PyMethodDef pysuinputMethods[] = {
195239

196240
},
197241

242+
{"toggle", pysuinput_toggle, METH_VARARGS,
243+
""
244+
},
245+
246+
{"is_pressed", pysuinput_is_pressed, METH_VARARGS,
247+
""
248+
},
249+
250+
{"is_valid_code", pysuinput_is_valid_code, METH_VARARGS,
251+
""
252+
},
253+
198254
{NULL, NULL, 0, NULL}
199255
};
200256

0 commit comments

Comments
 (0)