Description
Is it possible to block auto-repeat key events in pygfx
for a qt window?
Background
On Linux, in both X11 & Wayland, whenever I press and hold a key, a key release event is fired on key repeat. Here is a minimal example of pyside6
demonstrating this behavior on linux:
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import Qt
import sys
class MainWindow(QMainWindow):
def keyReleaseEvent(self, event):
print(f"Key released: {event.key()} ({Qt.Key(event.key()).name})")
def keyPressEvent(self, event: QKeyEvent) -> None:
print(f"Key down: {event.key()} ({Qt.Key(event.key()).name})")
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("PySide6 Key Up Example")
window.resize(400, 200)
window.show()
app.exec()
output (after pressing and holding, but not physically releasing the 'A' key):
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
Key down: 65 (Key_A)
Key released: 65 (Key_A)
This makes it really hard to implement a fly camera manually, since it's really hard to tell when the player has let go of the forward button.
After a lot of gpt and trial and error, I narrowed it down to every single qt window on linux having this problem. But pyside6
has this nice function called PySide6.QtGui.QKeyEvent.isAutoRepeat()
that automagically detects this key repeat behavior and filters it out.
Utilizing this, I've edited the above code to check for auto-repeating events before printing them, and the result is as follows:
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import Qt
import sys
class MainWindow(QMainWindow):
def keyReleaseEvent(self, event):
if event.isAutoRepeat():
return
print(f"Key released: {event.key()} ({Qt.Key(event.key()).name})")
def keyPressEvent(self, event: QKeyEvent) -> None:
if event.isAutoRepeat():
return
print(f"Key down: {event.key()} ({Qt.Key(event.key()).name})")
app = QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("PySide6 Key Up Example")
window.resize(400, 200)
window.show()
app.exec()
The code when run, has the following output, after clicking, holding (for a few seconds), and then releasing the 'A' key:
Key down: 65 (Key_A)
Key released: 65 (Key_A)
This is a functionality that I need in pygfx
, is there currently a way to do this?