问题
Self resolved
It's posted below as an answer.
Trying to get what xinput test-xi2 --root
prints with python xlib.
Using version 1.9 from github: https://github.com/python-xlib/python-xlib
event._data["data"]
contents for aaaaoo:
a<class 'Xlib.ext.ge.GenericEvent'>(data = b'\t\x00\xa9!v\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b'\x03\x00\xa9!v\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
a<class 'Xlib.ext.ge.GenericEvent'>(data = b"\t\x00A'v\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b"\x03\x00A'v\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
a<class 'Xlib.ext.ge.GenericEvent'>(data = b'\t\x00\xa9Ev\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b'\x03\x00\xa9Ev\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
a<class 'Xlib.ext.ge.GenericEvent'>(data = b"\t\x00\xea\x9dv\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b"\x03\x00\xea\x9dv\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
o<class 'Xlib.ext.ge.GenericEvent'>(data = b"\t\x002\xb4v\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b"\x03\x002\xb4v\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
o<class 'Xlib.ext.ge.GenericEvent'>(data = b"\t\x00\xba\xb8v\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>(data = b"\x03\x00\xba\xb8v\x17'\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sequence_number = 15, length = 2, evtype = 13, extension = 131, type = 35)
Code used to get the above;though some lines need to be commented out to reproduce the output above.
from Xlib import X, XK, display, error
from Xlib.ext import xinput
from Xlib.protocol import rq
from Xlib import protocol
from Xlib import Xutil
class Test:
def __init__(self):
self.dpy_input = display.Display(None)
#try setting events to capture
root = self.dpy_input.screen().root
root.xinput_select_events([(xinput.AllDevices, xinput.RawKeyPressMask)])
extension_info = self.dpy_input.query_extension('XInputExtension')
self.xinput_major = extension_info.major_opcode
self.version_info = self.dpy_input.xinput_query_version()
print('Found XInput version %u.%u' %(
self.version_info.major_version,
self.version_info.major_version,) )
def run(self):
while True:
event = self.dpy_input.next_event()
if event is None:
break
if event.type != self.dpy_input.extension_event.GenericEvent:
break
if event.evtype != xinput.RawKeyPress:
break
print (event.__class__)
print(event.__dict__)
print(event)
estruct = self.dpy_input.display.event_classes.get(
rq.byte2int(event._binary) & 0x7f, protocol.event.AnyEvent)
print(estruct)
e , d= rq.EventField(None).parse_binary_value(
event._binary, self.dpy_input.display, None, None)
print (e)
e , d= rq.EventField(None).parse_binary_value(
event._data["data"], self.dpy_input.display, None, None)
print (e)
break
if __name__ == "__main__":
t = Test()
t.run()
Output upon a a
key press:
Found XInput version 2.2
<class 'Xlib.ext.ge.GenericEvent'>
{'_data': {'sequence_number': 15, 'extension': 131, 'length': 2, 'send_event': False, 'data': b'\t\x00\xbf\xbdc\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'evtype': 13, 'type': 35}, '_binary': b'#\x83\x0f\x00\x02\x00\x00\x00\r\x00'}
<class 'Xlib.ext.ge.GenericEvent'>(sequence_number = 15, extension = 131, length = 2, data = b'\t\x00\xbf\xbdc\x17&\x00\x00\x00\t\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', evtype = 13, type = 35)
<class 'Xlib.ext.ge.GenericEvent'>
<class 'Xlib.ext.ge.GenericEvent'>(sequence_number = 15, extension = 131, length = 2, data = b'', evtype = 13, type = 35)
aTraceback (most recent call last):
File "/home/d/PycharmProjects/GUIConfigurator/xi2_test.py", line 54, in <module>
t.run()
File "/home/d/PycharmProjects/GUIConfigurator/xi2_test.py", line 47, in run
event._data["data"], self.dpy_input.display, None, None)
File "/home/d/PycharmProjects/GUIConfigurator/Xlib/protocol/rq.py", line 859, in parse_binary_value
return estruct(display = display, binarydata = data[:32]), data[32:]
File "/home/d/PycharmProjects/GUIConfigurator/Xlib/protocol/rq.py", line 1403, in __init__
rawdict = 1)
File "/home/d/PycharmProjects/GUIConfigurator/Xlib/protocol/rq.py", line 1146, in parse_binary
val = struct.unpack(self.static_codes, data[:self.static_size])
struct.error: unpack requires a bytes object of length 32
Question
What is in event._data["data"]
and how can I make it human readable?
回答1:
Managed to hack some portion of the binary data in RawKeyPress event.
The precess was rather... inelegant though, I wonder how real hackers do this.
from Xlib import X, XK, display, error
from Xlib.ext import xinput
import time
class Test:
def __init__(self):
self.dpy_input = display.Display(None)
#try setting events to capture
root = self.dpy_input.screen().root
root.xinput_select_events([(xinput.AllMasterDevices, xinput.RawKeyPressMask)])
extension_info = self.dpy_input.query_extension('XInputExtension')
self.xinput_major = extension_info.major_opcode
self.version_info = self.dpy_input.xinput_query_version()
print('Found XInput version %u.%u' %(
self.version_info.major_version,
self.version_info.major_version,) )
def run(self):
while True:
event = self.dpy_input.next_event()
if event is None:
break
if event.type != self.dpy_input.extension_event.GenericEvent:
break
if event.evtype != xinput.RawKeyPress:
break
# print (event.__class__)
# print(event.__dict__)
print(event)
b = event._data["data"]
device = b[0:1]
print("device:%d" % ( int.from_bytes(device,"little")))
# value at b[1] seems like padding, always 0.
# 7th byte contains x11 keycode
keycode = b[6]
print("keycode:"+str(keycode))
# Not certain as to what this really is.
timestamp = b[2:6] # four bytes int
print('timestamp:'+str(int.from_bytes(timestamp,"little")))
# Not certain as to what this really is.
valuators = b[7:9] # 2 bytes, short int
print("valuators:" + str(int.from_bytes(valuators,"little")))
device_id = b[10:11] # 2 bytes, short int
print("device id:" + str(int.from_bytes(device_id,"little")))
if __name__ == "__main__":
t = Test()
t.run()
I compared the python script output with the output from xinput test-xi2 --root
for a A keypress.
Python:
b'\x03\x00H\x8a\xd9\x1c&\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
xinput:
EVENT type 14 (RawKeyRelease)
device: 3 (12)
detail: 38
valuators:
Now the scripts prints:
Found XInput version 2.2
<class 'Xlib.ext.ge.GenericEvent'>(evtype = 13, data = b'\x03\x004=A\x1d&\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', type = 35, length = 2, extension = 131, sequence_number = 15)
device:3
keycode:38
timestamp:490814772
valuators:0
device id:12
Although it's rather incomplete still, I have to leave off here as now I know RawKeyPress event does not provide what I want: hid usage id or linux kernel scancode.
来源:https://stackoverflow.com/questions/45809046/capture-and-interpret-xi2-rawkeypress-event-with-python