在 Python Gtk3+ 中模拟鼠标单击小部件

Simulate mouse-clicking a widget in Python Gtk3+

A Python 3 和 Gtk 3.22.5 应用程序响应全局键绑定,感谢 Keybinder 库。目前它调用一个简单的回调:

def keybinder_callback(self, keystr, user_data):
    print("Handling", keystr, user_data)

应用程序的其他地方是 Gtk.Window,其中包含 Gtk.MenuBarkeybinder_callback 需要激活菜单栏,就像用户在其上单击鼠标一样。

(这是一个非常基本的扩展坞类型应用程序,而不是具有典型应用程序的应用程序 window)

我试过向菜单项发送信号:

self.menubar.get_children()[0].emit("activate-item")

没有任何喜悦。我也试过伪造按钮按下

from Xlib.ext.xtest import fake_input
fake_input(display,X.ButtonPress,1)

这也没有效果,但无论如何感觉都是错误的方法。我觉得发信号比较合适

能否以编程方式激活小部件,就像用户在其上单击鼠标一样?

(不必是模拟的鼠标单击 - 它只需要以与鼠标单击相同的方式激活和聚焦小部件)


我写了一个example that has a 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 进行监控)并通过将它们注入 Gdk.main_do_event 来模拟它们(ENTER_NOTIFYFOCUS_CHANGE) ].

我试过调用 menu.popupmenu.popup_at_widgetmenubar.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)

在尝试了很多东西之后,我发现这行得通。

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