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

时间:2017-02-22 17:48:34

标签: python gtk3

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

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

应用程序的其他地方是Gtk.Window,其中包含Gtk.MenuBarkeybinder_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_NOTIFYFOCUS_CHANGE),方法是将它们注入Gdk.main_do_event

我尝试过调用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)

1 个答案:

答案 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