使用python xlib全局捕获,忽略和发送关键事件,识别假输入 [英] globally capture, ignore and send keyevents with python xlib, recognize fake input

查看:76
本文介绍了使用python xlib全局捕获,忽略和发送关键事件,识别假输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在普通键盘上实现和弦,我以为我使用python xlib. 为此,该程序必须全局吞噬所有关键事件,并且仅在以后允许它们通过.

i want to implement key chording on a normal keyboard and i thought i use python xlib. for this to work the program has to globally swallow all keyevents and only later allow them to go through.

我当前的测试只是抓住了"1"键.如果按下此键,它将调用一个处理程序,该处理程序通过xtest.fake_input向焦点窗口发送"x".因为我只是抓住了"1"键,所以应该没有问题吧? 但是以某种方式再次调用了处理程序,因为按下了"x".实际上,当我键入"1"时,程序正在监听所有键. 这可能与调用

my current test just grabs the "1" key. if this key is pressed it calls a handler which sends "x" to the focused window via xtest.fake_input. because im only grabbing the "1"-key, there shouldn't be a problem, right? but somehow the handler gets called again, because "x" was pressed. in fact, the moment i type "1" the program is listening to all keys. this could have something to do with calling

display.allow_events(X.ReplayKeyboard, X.CurrentTime)

处理事件后,但是如果我不这样做,一切都会冻结.

after handling an event, but if i don't do this, everything freezes.

对于最终程序,监听行为的改变并不真正相关,但是我必须能够将假事件与用户事件区分开.要做到这一点,我只是快速转发display.next_event(),但这并不理想,因为用户可能会在那个确切的时间输入内容,然后这些击键就会丢失.

for the final program the change in the listening behaviour is not really relevant, but i have to be able to distinguish the fake events from the user events. to do this i'm just fast forwarding display.next_event(), but this isnt ideal, because the user could be typing at that exact moment and than those keystrokes would be lost.

我尝试通过发送和清空事件队列期间释放钥匙扣

i tried releasing the keygrab during sending and emptying the eventqueue via

display.flush()
display.sync()

但是那什么也没做.

那么,有什么主意如何识别或忽略假输入事件以及为什么我突然听所有按键(和发布)?

so, any idea how to recognize or ignore fake input events and why i'm suddenly listening to all keypresses (and releases)?

xlib非常令人沮丧.

xlib is very frustrating.

from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal 

display = None
root = None

def handle_event(aEvent):
    print "handle!"
    send_key("x")

def send_key(emulated_key):

    global display,root
    print "send key"
    # ungrabbing doesnt help
    root.ungrab_key(10,X.AnyModifier) 
    window = display.get_input_focus()._data["focus"]
    # Generate the correct keycode
    keysym = Xlib.XK.string_to_keysym(emulated_key)
    keycode = display.keysym_to_keycode(keysym)
    # Send a fake keypress via xtestaaa
    Xlib.ext.xtest.fake_input(window, Xlib.X.KeyPress, keycode)
    Xlib.ext.xtest.fake_input(window, Xlib.X.KeyRelease, keycode)
    display.flush()
    display.sync()
    # fast forward those two events,this seems a bit hacky, 
    # what if theres another keyevent coming in at that exact time?
    while display.pending_events():
        display.next_event()
    #
    root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)

def main():
    # current display
    global display,root
    display = Display()
    root = display.screen().root

    # we tell the X server we want to catch keyPress event
    root.change_attributes(event_mask = X.KeyPressMask)
    # just grab the "1"-key for now
    root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)
    # while experimenting everything could freeze, so exit after 10 seconds
    signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
    signal.alarm(10)
    while 1:
        event = display.next_event()
        print "event"
        #if i dont call this, the whole thing freezes
        display.allow_events(X.ReplayKeyboard, X.CurrentTime)
        handle_event(event)

if __name__ == '__main__':
    main()

推荐答案

我发现了问题.我几乎可以肯定xtest.fake_input会做一些奇怪的事情,因为当我手动发送按键和-releases时(使用某些代码,我

i found the problem. im almost certain that xtest.fake_input does something weird, because when i send keypresses and -releases manually (with some code i found), it works

下面是一个示例,该示例仅在按键时吞下"1"键,而在按键释放时将"x"发送到焦点窗口:

here is an example, that swallows only the "1"-key on keypress and sends "x" on keyrelease to the focused window:

from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal 
import time
display = None
root = None

def handle_event(event):
    print "handle!"
    if (event.type == X.KeyRelease):
        send_key("x")

# from http://shallowsky.com/software/crikey/pykey-0.1 
def send_key(emulated_key):
    shift_mask = 0 # or Xlib.X.ShiftMask
    window = display.get_input_focus()._data["focus"]
    keysym = Xlib.XK.string_to_keysym(emulated_key)
    keycode = display.keysym_to_keycode(keysym)
    event = Xlib.protocol.event.KeyPress(
        time = int(time.time()),
        root = root,
        window = window,
        same_screen = 0, child = Xlib.X.NONE,
        root_x = 0, root_y = 0, event_x = 0, event_y = 0,
        state = shift_mask,
        detail = keycode
        )
    window.send_event(event, propagate = True)
    event = Xlib.protocol.event.KeyRelease(
        time = int(time.time()),
        root = display.screen().root,
        window = window,
        same_screen = 0, child = Xlib.X.NONE,
        root_x = 0, root_y = 0, event_x = 0, event_y = 0,
        state = shift_mask,
        detail = keycode
        )
    window.send_event(event, propagate = True)

def main():
    # current display
    global display,root
    display = Display()
    root = display.screen().root

    # we tell the X server we want to catch keyPress event
    root.change_attributes(event_mask = X.KeyPressMask|X.KeyReleaseMask)
    # just grab the "1"-key for now
    root.grab_key(10, 0, True,X.GrabModeSync, X.GrabModeSync)

    signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
    signal.alarm(10)
    while 1:
        event = display.next_event()
        print "event"
        handle_event(event)
        display.allow_events(X.AsyncKeyboard, X.CurrentTime)            

if __name__ == '__main__':
    main()

这篇关于使用python xlib全局捕获,忽略和发送关键事件,识别假输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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