1

简而言之,我正在尝试向我的程序添加一个键绑定,该程序将编辑剪贴板,然后将更改粘贴到您处于​​活动状态的任何窗口中。在 Windows 上,我想我可能可以通过消息传递来做到这一点,但 X 不会像那样使用消息传递,所以为了做到这一点,我只是使用python-evdev向 uinput 发送一个 ctrl+v 事件。当您只运行它时,它运行得相当好,但我需要它在键绑定上运行,在这种情况下是 super+v。问题变成当你发送 ctrl 和 v 事件到 uinput 时,超级掩码仍然处于活动状态,所以它不是发送 ctrl+v 到窗口,而是发送 ctrl+super+v,这实际上并没有做任何事情。这是用于准确解释我在说什么的最少代码:

import evdev,time,keybinder,gtk

def callback():
    with evdev.UInput() as uinput:
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTCTRL, 1)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_V, 1)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_V, 0)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTCTRL, 0)
        uinput.syn()

keybinder.bind("<super>v",callback)
keybinder.bind("Escape",gtk.main_quit)
gtk.main()

如果你发布的速度足够快,你实际上可以让它工作,但它非常快,显然对于实际应用程序来说是不可接受的。我试图发布 super 但这会引发一些问题;它不是很通用,它提出了之后要做什么的问题(让它释放?再按一次?如果他们在你释放然后再次按下它之间的时间内释放怎么办?),最重要的是,它没有似乎真的有效。

无论如何,我想问题是,有没有办法解决这个问题?也许一种发送不会与物理键盘结合的按键事件的方法(不太可能)?如果没有,有没有更好的方法让它在 Linux 上通用粘贴?

4

2 回答 2

0

我认为这没有解决方案。正如您已经清楚地了解的那样,Ctrl-V不是用于启动“粘贴”操作的 IPC 机制,它只是执行此操作的常用键绑定(请注意,如果您碰巧在前台运行 emacs,您的技巧将不起作用,您的小工具只会将窗口向上滚动一页)。而且我认为你是对的,没有标准(例如 freedesktop.org 上的东西)要求窗口“立即粘贴”,也不应该有。

至少正如应用程序普遍理解和实现的那样,粘贴是用户启动的操作。没有应用程序会期望它由外部工具驱动。您要解决的实际问题是什么?你不能绑定一些东西在你的客户端应用程序中运行,或者可能挂钩一个可访问性/输入法框架吗?

这就是说:我认为如果你想让这个特定的 hack 工作,你有正确的方法。在操作开始时查询它们的键盘映射,清除任何修饰键的状态,发送您的事件,然后重置状态。显然,您与硬件键盘的比赛仍然无法解决,但我怀疑在实践中这不会是一个大问题。

于 2013-06-05T22:54:12.810 回答
0

您需要找到一种方法来确定该<super>键当前是否被按住。
在 wxpython 中Super = wx.GetKeyState(wx.WXK_META),我不知道在 Gtk 中会是什么。
那么您的代码将如下所示:

def callback():
   Super = wx.GetKeyState(wx.WXK_META) # Here you require the Gtk equivalent 
   with evdev.UInput() as uinput:
        if Super:
            uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTMETA, 0)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTCTRL, 1)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_V, 1)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_V, 0)
        uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTCTRL, 0)
        if Super:
            uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTMETA, 1)
        uinput.syn()

如您所见,您差一点就可以得到它。
添加的代码只需Super在所需的 Ctrl+v 之前关闭密钥,然后再重新打开。

于 2016-03-29T15:00:02.097 回答