使用python捕获和解释XI2 RawKeyPress事件 [英] Capture and interpret XI2 RawKeyPress event with python

查看:105
本文介绍了使用python捕获和解释XI2 RawKeyPress事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它作为答案发布在下面.

It's posted below as an answer.

尝试使用python xlib获取xinput test-xi2 --root打印的内容.
使用来自github的1.9版: https://github.com/python-xlib/python-xlib

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"]内容:

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()

a键时输出:

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  

问题

event._data["data"]中的内容是什么,我如何使其易于阅读?

Question

What is in event._data["data"] and how can I make it human readable?

推荐答案

已成功破解了RawKeyPress事件中的部分二进制数据.
进阶是相当……虽然不太优雅,但我不知道真正的黑客是怎么做到的.

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()

我将python脚本输出与xinput test-xi2 --root的输出进行了A按键比较.

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:

现在脚本将打印:

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

尽管它还很不完整,但是我不得不离开这里,因为我知道RawKeyPress事件不能提供我想要的东西:隐藏用法ID或Linux内核扫描代码.

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.

这篇关于使用python捕获和解释XI2 RawKeyPress事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆