From 416d5164bec949f19c665c7411641ea41b788dc4 Mon Sep 17 00:00:00 2001 From: Ken TY Chiu Date: Sun, 15 Feb 2026 11:27:04 +0800 Subject: [PATCH] engine: Fix sticky keys for thumb shift mode --- engine/python2/engine.py | 37 ++++++++++++++++++++++++++++++++++--- engine/python3/engine.py | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/engine/python2/engine.py b/engine/python2/engine.py index c7ccd3f..ef9cfe1 100644 --- a/engine/python2/engine.py +++ b/engine/python2/engine.py @@ -247,6 +247,8 @@ def __reset(self): self._H = 0 self._RMM = 0 self._RSS = 0 + self._MS = 0 # modifier state + self._CM = 0 # command memory if self.__idle_id != 0: GLib.source_remove(self.__idle_id) self.__idle_id = 0 @@ -1827,9 +1829,8 @@ def insert(keyval): return ret except: pass - - def cmd_exec(keyval, state=0): - key = self._mk_key(keyval, state) + + def __cmd_exec(key, keyval, state): for cmd in self.__keybind.get(key, []): if config.DEBUG: print 'cmd =', cmd @@ -1840,6 +1841,30 @@ def cmd_exec(keyval, state=0): printerr('Error command: %s: %s' % (cmd, str(err))) return False + def cmd_exec(keyval, state=0): + key = self._mk_key(keyval, state) + pair = eval(key) + self._MS = pair[0] + self._CM = pair[1] + return __cmd_exec(key, keyval, state) + + def cmd_term(keyval, state=0): + if self._MS == 0 and self._CM == 0: + return False + + key = self._mk_key(keyval, state) + pair = eval(key) + + prev_keyval = self._CM | IBus.ModifierType.RELEASE_MASK + prev_state = self._MS | IBus.ModifierType.RELEASE_MASK + prev_key = repr([int(prev_state), int(prev_keyval)]) + + self._MS = 0 + self._CM = 0 + + __cmd_exec(prev_key, prev_keyval, prev_state) + return __cmd_exec(key, pair[1], pair[0]) + def RS(): return self.__thumb.get_rs() @@ -1874,6 +1899,12 @@ def T2(): self._RSS = 0 elif keyval == self._RMM: self._RMM = 0 + elif keyval not in self.__thumb.get_chars() or state != 0: + if cmd_term(keyval, state): + return True + elif not self.__preedit_ja_string.is_empty(): + return True + return False else: if keyval in [LS(), RS()] and state == 0: if self._SS: diff --git a/engine/python3/engine.py b/engine/python3/engine.py index 0858614..a1711cb 100644 --- a/engine/python3/engine.py +++ b/engine/python3/engine.py @@ -248,6 +248,8 @@ def __reset(self): self._H = 0 self._RMM = 0 self._RSS = 0 + self._MS = 0 # modifier state + self._CM = 0 # command memory if self.__idle_id != 0: GLib.source_remove(self.__idle_id) self.__idle_id = 0 @@ -1822,9 +1824,8 @@ def insert(keyval): return ret except: pass - - def cmd_exec(keyval, state=0): - key = self._mk_key(keyval, state) + + def __cmd_exec(key, keyval, state): for cmd in self.__keybind.get(key, []): if config.DEBUG: print('cmd =', cmd) @@ -1835,6 +1836,30 @@ def cmd_exec(keyval, state=0): printerr('Error command: %s: %s' % (cmd, str(err))) return False + def cmd_exec(keyval, state=0): + key = self._mk_key(keyval, state) + pair = eval(key) + self._MS = pair[0] + self._CM = pair[1] + return __cmd_exec(key, keyval, state) + + def cmd_term(keyval, state=0): + if self._MS == 0 and self._CM == 0: + return False + + key = self._mk_key(keyval, state) + pair = eval(key) + + prev_keyval = self._CM | IBus.ModifierType.RELEASE_MASK + prev_state = self._MS | IBus.ModifierType.RELEASE_MASK + prev_key = repr([int(prev_state), int(prev_keyval)]) + + self._MS = 0 + self._CM = 0 + + __cmd_exec(prev_key, prev_keyval, prev_state) + return __cmd_exec(key, pair[1], pair[0]) + def RS(): return self.__thumb.get_rs() @@ -1869,6 +1894,12 @@ def T2(): self._RSS = 0 elif keyval == self._RMM: self._RMM = 0 + elif keyval not in self.__thumb.get_chars() or state != 0: + if cmd_term(keyval, state): + return True + elif not self.__preedit_ja_string.is_empty(): + return True + return False else: if keyval in [LS(), RS()] and state == 0: if self._SS: