2017-02-22 5 views
2

Приложение Python 3 и Gtk 3.22.5 реагирует на глобальную привязку клавиш, благодаря библиотеке Keybinder. В настоящее время он вызывает простой обратный вызов:Имитировать щелчок мышью по виджету в Python Gtk3 +

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

В другом месте в приложении является Gtk.Window, который содержит Gtk.MenuBar. keybinder_callback необходимо активировать панель меню, как если бы пользователь нажал на нее мышь.

(это очень простое приложение док-типа, а не один с типичным окном приложения)

Я попытался посылая сигнал к пункту меню:

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 книгу ...

Кстати, в то время как не правильное решение, это работает из командной строки:

$ 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

посмотрите на [ 'GtkMenu.popup_at_widget'] (https://developer.gnome.org/gtk3/ нестабильный/GtkMenu.html # gtk-menu-popup-at-widget), но будьте осторожны, я почти застыл на своем ПК во время игры с ним. Не совсем уверен, что произошло, но после того, как появилось меню, я больше не мог закрыть программу. –

+0

Ну, я попробовал 'self.menu.popup_at_widget (self, Gdk.Gravity.STATIC, Gdk.Gravity.STATIC, None)' но получил 'Warning: g_object_set_data: assertion 'G_IS_OBJECT (object)' failed' – starfry

ответ

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 
Смежные вопросы