由于Keybinder库,Python 3和Gtk 3.22.5应用程序响应全局键绑定。目前它调用一个简单的回调:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
应用程序的其他地方是Gtk.Window
,其中包含Gtk.MenuBar
。 keybinder_callback
需要激活菜单栏,就好像用户点击了鼠标一样。
(这是一个非常基本的dock-type应用程序,而不是具有典型应用程序窗口的应用程序)
我尝试向菜单项发送信号:
self.menubar.get_children()[0].emit("activate-item")
没有任何快乐。我也尝试按下按钮
from Xlib.ext.xtest import fake_input
fake_input(display,X.ButtonPress,1)
这也没有任何影响,但无论如何感觉都是错误的方式。我认为发送信号会更合适。
是否可以通过编程方式激活窗口小部件,就像用户点击鼠标一样?
(它不一定是模拟的鼠标点击 - 它只需要以鼠标点击的方式激活和聚焦小部件)
我写了一个example,其中有keybinder_callback
这样:
def keybinder_callback(self, keystr, user_data):
print("Handling", keystr, user_data)
print("Event time:", Keybinder.get_current_event_time())
activate_the_menu()
我需要为activate_the_menu
的函数添加一些命令。
我尝试了许多方法,包括捕获真实事件(通过xev
进行监控)并模拟它们(ENTER_NOTIFY
和FOCUS_CHANGE
),方法是将它们注入Gdk.main_do_event
。
我尝试过调用menu.popup
,menu.popup_at_widget
,menubar.select_item
等众多内容。一切都没有用。
用尽了想法,我甚至把旧的Xlib书都拂去了......
顺便提一下,虽然不是一个合适的解决方案,但这可以从shell中运行:
$ xdotool mousemove 1605 10 click 1 mousemove restore
但不可靠keybinder_callback
:
run("xdotool mousemove %d 10 click 1 mousemove restore" %
(self.get_position().root_x+5) , shell=True)
答案 0 :(得分:0)
在尝试了很多东西后,我发现这很有效。
import Xlib
from Xlib import X
from Xlib.display import Display
from Xlib.ext.xtest import fake_input
import time
def keybinder_callback(self, keystr, user_data):
time.sleep(0.2)
x = self.get_position().root_x+5
display = Display()
mpos = display.screen().root.query_pointer()._data
display.screen().root.warp_pointer(x,5)
display.sync()
fake_input(display,X.ButtonPress,1, X.CurrentTime, X.NONE, x, 5)
display.sync()
fake_input(display,X.ButtonRelease,1)
display.screen().root.warp_pointer(mpos['root_x'],
mpos['root_y'])
display.sync()
我发现时间延迟是避免此错误所必需的:
Gdk-CRITICAL **: Window 0x1e7c660 has not been made visible in GdkSeatGrabPrepareFunc