Issue
I have a trivial example program that works on Windows and from within PyCharm (on Linux, on a Wayland display):
from pynput import keyboard
from queue import Queue
kbd_q = Queue(maxsize=1)
def on_activate_s():
kbd_q.put("Hotkey s")
listener = keyboard.GlobalHotKeys({
's': on_activate_s,
})
listener.start()
while True:
key = kbd_q.get()
if key:
print(key)
It does not receive any keyboard events when running in the terminal under Wayland (Linux). Here are the limitations of pynput under Linux. I want to control my program with Hotkeys (several keys pressed at once), that is why I would like to use pynput or even pypi keyboard. But if I understand correctly, Wayland purposefully prevents direct access to the keyboard.
How can I get my code to run under Linux and Windows with as little workaround as possible?
My ideas:
- Run as
root
- not great. My program will create files, which can be awkward with wrong file permissions and more permissions than strictly necessary. Also, when running withsudo,
it fails to detect the X server. - turn my application into an X client. Is that possible without the considerable overhead? How does that impact the portability to Windows? Would it make sense to quickly turn this into a pyQT app?
Is there an easy solution for this?
Solution
This works both on Linux and Windows, from within PyCharm and from within a terminal. I am sure there is a lot of unused functionality in PyQt, like this. It hurts me to write code like this because I prefer them lean and simple. Suggestions to that end are welcome.
import queue
import sys
from pynput import keyboard
from queue import Queue
import datetime
from PyQt5.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
w = QWidget()
w.resize(300,300)
w.setWindowTitle("Keyboard Events")
w.show()
kbd_q = Queue(maxsize=1)
def on_activate_1a(): kbd_q.put("Hotkey 1a")
def on_activate_2s(): kbd_q.put("Hotkey 2s")
def on_activate_s(): kbd_q.put("Hotkey s")
listener = keyboard.GlobalHotKeys({
'1+a': on_activate_1a,
'2+s': on_activate_2s,
's': on_activate_s,
})
listener.start()
listener.wait()
ten_sec = datetime.datetime.now() + datetime.timedelta(seconds=10)
while datetime.datetime.now() < ten_sec:
print(".")
try:
key = kbd_q.get(True, timeout=0.1)
if key:
print(key)
except queue.Empty:
pass
listener.stop()
print("10 sec passed")
sys.exit(app.exec_())
Answered By - Andreas Schuldei
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.