Skip to content

Catch auto-repeat keys in pyside6 #93

Closed
@SpicyRicecaker

Description

@SpicyRicecaker

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions