使用Gtk和XLib的Python3中的全局热键 [英] Global hotkey in Python3 using Gtk and XLib
问题描述
我的X System应用程序保留在后台(并且在面板中作为指示符),并且无论用户处于活动状态如何,只要用户按下某个键,它都应该弹出. 类似于菜单应用.
My application for X System stays in background (and in panel as indicator) and should popup whenever user hits a key, no matter whatever be the active window. Similar to Menu app.
尝试了以下内容:
- 在Linux上的python中侦听全局键组合 但是找不到如何集成此Gtk主循环的方法.
- 使用Python gtk3在X上进行全局键绑定 这个问题的唯一答案是Python 2,它不起作用.
- Listening for global key-combinations in python on Linux But can't find how to integrate this Gtk main loop.
- Global keybinding on X using Python gtk3 The only answer for this question is Python 2 and doesn't work.
混合以上两个代码,我得到以下代码:
Mixing the above two, I got the following code:
from Xlib.display import Display
from Xlib import X, error
from Xlib.ext import record
from Xlib.protocol import rq
from gi.repository import Gtk, GObject, Gdk
import threading
class GlobalKeyBinding(GObject.GObject, threading.Thread):
def __init__(self):
GObject.GObject.__init__(self)
threading.Thread.__init__(self)
self.setDaemon(True)
self.display = Display()
self.Win = Gtk.Window()
self.Win.add(Gtk.Label("Hello"))
self.root = self.display.screen().root
ctx = self.display.record_create_context(
0,
[record.AllClients],
[{
'core_requests': (0, 0),
'core_replies': (0, 0),
'ext_requests': (0, 0, 0, 0),
'ext_replies': (0, 0, 0, 0),
'delivered_events': (0, 0),
'device_events': (X.KeyReleaseMask,
X.ButtonReleaseMask),
'errors': (0, 0),
'client_started': False,
'client_died': False,
}])
self.state = 0
self.display.record_enable_context(ctx, self.handler)
self.display.record_free_context(ctx)
def handler(self, reply):
data = reply.data
wait_for_release = False
while len(data):
event, data = rq.EventField(None).parse_binary_value(
data, self.display.display, None, None)
# KEYCODE IS FOUND USERING event.detail
print(event.detail)
if event.type == X.KeyPress:
# BUTTON PRESSED
print("pressed")
if not self.state:
self.Win.show_all()
self.state = 1
else:
self.Win.hide()
self.state = 0
elif event.type == X.KeyRelease:
# BUTTON RELEASED
print("released")
def run(self):
self.running = True
while self.running:
event = self.display.next_event () # registered keycode(or probably rather event) has been received.
while Gtk.main_iteration():
Gtk.main_iteration_do(True)
def main():
print("starting...")
Gdk.threads_init ()
keybindings=GlobalKeyBinding()
keybindings.start ()
Gtk.main ()
main()
尽管这捕获了我的输入,但它从未显示该窗口. 请帮助:)
Though this catches my input, it never shows the window. Please help : )
推荐答案
因此不需要使用XLib.全局热键可以使用keybinder模块来实现. 示例:
So using XLib is not needed. Global Hotkey can be achieved using keybinder module. Example:
import gi
gi.require_versions({"Gtk": "3.0", "Gdk": "3.0", "Keybinder": "3.0"})
from gi.repository import Gtk, Keybinder
class A:
def __init__(self):
self.win = Gtk.Window()
self.lab = Gtk.Label(label="Hello")
self.win.add(self.lab)
self.win.connect("destroy", Gtk.main_quit)
self.win.show_all()
# Basic setup of a window with a label
self.count = 0
key = Keybinder # The module to bind keys
key.bind("<control>m", self.say, "Hello")
# key.bind(KEYCOMBINATION, FUNC, ARG)
key.init() # Call the mainloop something like Gtk.main()
def say(self, key, msg):
print(msg)
self.lab.set_label(f"Pressed {key} {self.count} times")
self.count += 1
A() # Call the object
Gtk.main() # Call the main loop
您可以在此处找到有关此模块的更多信息: https://github.com/engla/keybinder
You can find more about this module here : https://github.com/engla/keybinder
这篇关于使用Gtk和XLib的Python3中的全局热键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!