rules: better determination of keycodes and handle keysym level

This commit is contained in:
Peter F. Patel-Schneider 2022-05-04 11:37:05 -04:00
parent 2b4e272331
commit 97344c4660
2 changed files with 34 additions and 15 deletions

View File

@ -155,14 +155,21 @@ For settings that use gestures as an argument the internal name of the gesture i
which can be found in the GESTURE2_GESTURES_LABELS structure in lib/logitech_receiver/settings_templates. which can be found in the GESTURE2_GESTURES_LABELS structure in lib/logitech_receiver/settings_templates.
For boolean settings '~' can be used to toggle the setting. For boolean settings '~' can be used to toggle the setting.
A `KeyPress` action takes a sequence of X11 key symbols and simulates a chorded keypress on the keyboard, A `KeyPress` action takes a sequence of X11 key symbols, such as "a" or "Control+a",
such as "A", "Shift+A", or "Control+A". and simulates a chorded keypress on the keyboard to produce these symbols.
Use separate `KeyPress` actions for multiple characters. Use separate `KeyPress` actions for multiple characters,
If Solaar can determine the current modifier keys, i.e., don't use a single `KeyPress` like 'a+b'.
any key symbols that correspond to these modifier keys are not pressed. If a key symbol can only be produced by a shfited or level 3 keypress, e.g., "A",
then Solaar will add keypresses to produce that keysymbol,
e.g., simulating a left shift keypress to get "A" instead of "a".
If Solaar can determine the current key modifiers (shift, control, etc.)
any key symbols that correspond to these modifier keys are not pressed,
so if the shift key is currently down on a keyboard Solaar will not bother to simulate a shift key.
Simulating input in Linux is complex. Simulating input in Linux is complex.
Solaar has to try to determine which keyboard key corresponds to which input character as it cannot directly Solaar has to try to determine which keyboard key corresponds to which input character as it cannot directly
simulate inputting a character and, unfortunately, this determination can go wrong in multiple ways and is more likely simulate inputting a key symbol.
Unfortunately, this determination can go wrong in several ways and is more likely
to go wrong under Wayland than under X11. to go wrong under Wayland than under X11.
A `MouseScroll` action takes a sequence of two numbers and simulates a horizontal and vertical mouse scroll of these amounts. A `MouseScroll` action takes a sequence of two numbers and simulates a horizontal and vertical mouse scroll of these amounts.

View File

@ -836,14 +836,14 @@ class KeyPress(Action):
def keysym_to_keycode(self, keysym, modifiers): # maybe should take shift into account def keysym_to_keycode(self, keysym, modifiers): # maybe should take shift into account
group = kbdgroup() or 0 group = kbdgroup() or 0
keycodes = gkeymap.get_entries_for_keyval(keysym) keycodes = gkeymap.get_entries_for_keyval(keysym)
if len(keycodes.keys) == 1: (keycode, level) = (None, None)
k = keycodes.keys[0] for k in keycodes.keys:
return k.keycode if (group == k.group or len(keycodes.keys) == 1) and k.keycode < 256 and (level is None or k.level < level):
else: keycode = k.keycode
for k in keycodes.keys: level = k.level
if group is None or group == k.group: if keycode is None:
return k.keycode
_log.warn('rule KeyPress key symbol not currently available %s', self) _log.warn('rule KeyPress key symbol not currently available %s', self)
return (keycode, level)
def __str__(self): def __str__(self):
return 'KeyPress: ' + ' '.join(self.key_names) return 'KeyPress: ' + ' '.join(self.key_names)
@ -852,17 +852,29 @@ class KeyPress(Action):
code = modifier_code(k) code = modifier_code(k)
return not (code is not None and modifiers & (1 << code)) return not (code is not None and modifiers & (1 << code))
def mods(self, level, modifiers, direction):
if level == 2 or level == 3:
(sk, _) = self.keysym_to_keycode(XK_KEYS.get('ISO_Level3_Shift', None), modifiers)
if sk and self.needed(sk, modifiers):
simulate_key(sk, direction)
if level == 1 or level == 3:
(sk, _) = self.keysym_to_keycode(XK_KEYS.get('Shift_L', None), modifiers)
if sk and self.needed(sk, modifiers):
simulate_key(sk, direction)
def keyDown(self, keysyms, modifiers): def keyDown(self, keysyms, modifiers):
for k in keysyms: for k in keysyms:
keycode = self.keysym_to_keycode(k, modifiers) (keycode, level) = self.keysym_to_keycode(k, modifiers)
if keycode and self.needed(keycode, modifiers): if keycode and self.needed(keycode, modifiers):
self.mods(level, modifiers, _KEY_PRESS)
simulate_key(keycode, _KEY_PRESS) simulate_key(keycode, _KEY_PRESS)
def keyUp(self, keysyms, modifiers): def keyUp(self, keysyms, modifiers):
for k in keysyms: for k in keysyms:
keycode = self.keysym_to_keycode(k, modifiers) (keycode, level) = self.keysym_to_keycode(k, modifiers)
if keycode and self.needed(keycode, modifiers): if keycode and self.needed(keycode, modifiers):
simulate_key(keycode, _KEY_RELEASE) simulate_key(keycode, _KEY_RELEASE)
self.mods(level, modifiers, _KEY_RELEASE)
def evaluate(self, feature, notification, device, status, last_result): def evaluate(self, feature, notification, device, status, last_result):
if gkeymap: if gkeymap: