|
@@ -114,6 +114,7 @@ class ExtendedControls:
|
|
|
self._default_action = ForwardKeyEventAction()
|
|
|
self._engine_window = None
|
|
|
self._other_engine_windows = None
|
|
|
+ self._active_key_registry = {}
|
|
|
self._enabled = False
|
|
|
|
|
|
@property
|
|
@@ -155,16 +156,16 @@ class ExtendedControls:
|
|
|
while self.engine_running:
|
|
|
while self.xdisplay.pending_events():
|
|
|
self._handle_xevent(self._xdisplay.next_event())
|
|
|
+ self._check_active_key_registry()
|
|
|
x_wait_for_event(self.xdisplay, timeout_seconds=1)
|
|
|
|
|
|
def _handle_xevent(self, xevent):
|
|
|
-
|
|
|
-
|
|
|
if isinstance(xevent, Xlib.protocol.event.KeyPress) \
|
|
|
or isinstance(xevent, Xlib.protocol.event.KeyRelease):
|
|
|
self._handle_xkeyevent(xevent)
|
|
|
|
|
|
def _handle_xkeyevent(self, xkeyevent):
|
|
|
+ self._update_active_key_registry(xkeyevent)
|
|
|
keysym_in = self._xdisplay.keycode_to_keysym(
|
|
|
xkeyevent.detail,
|
|
|
index=0,
|
|
@@ -232,3 +233,28 @@ class ExtendedControls:
|
|
|
if not self._other_engine_windows:
|
|
|
self._other_engine_windows = self.find_other_engine_windows()
|
|
|
return self._other_engine_windows
|
|
|
+
|
|
|
+ def _update_active_key_registry(self, xkeyevent):
|
|
|
+
|
|
|
+ keycode = xkeyevent.detail
|
|
|
+ if isinstance(xkeyevent, Xlib.protocol.event.KeyPress):
|
|
|
+ self._active_key_registry[keycode] = xkeyevent
|
|
|
+ elif keycode in self._active_key_registry:
|
|
|
+ del self._active_key_registry[keycode]
|
|
|
+
|
|
|
+ def _check_active_key_registry(self):
|
|
|
+ """
|
|
|
+ WORKAROUND
|
|
|
+ For an unknown reason some key release events don't get queued
|
|
|
+ when multiple keys are being released simultaneously.
|
|
|
+ So we keep a hashmap of supposedly currently pressed keys
|
|
|
+ and periodically compare it with xdispaly.query_keymap().
|
|
|
+
|
|
|
+ ref: https://stackoverflow.com/q/18160792/5894777
|
|
|
+ """
|
|
|
+
|
|
|
+ keymap = self.xdisplay.query_keymap()
|
|
|
+ missed_releases = []
|
|
|
+ for keycode, press_event in self._active_key_registry.items():
|
|
|
+ if not (1 << (keycode & ((1 << 3) - 1))) & keymap[keycode >> 3]:
|
|
|
+ print("WARN missed release event of key {}".format(keycode))
|