rules: add depress and release options to KeyPress rule action
This commit is contained in:
parent
cc0ddb8df5
commit
c8ba397e0e
|
@ -160,10 +160,20 @@ 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, such as "a" or "Control+a",
|
A `KeyPress` action takes either the name of an X11 key symbol, such as "a",
|
||||||
and simulates a chorded keypress on the keyboard to produce these symbols.
|
a list of X11 key symbols, such as "a" or "Control+a",
|
||||||
|
or a two-element list with the first element as above
|
||||||
|
and the second element one of 'click', 'depress', or 'release'
|
||||||
|
and executes key actions on a simulated keyboard to produce these symbols.
|
||||||
Use separate `KeyPress` actions for multiple characters,
|
Use separate `KeyPress` actions for multiple characters,
|
||||||
i.e., don't use a single `KeyPress` like 'a+b'.
|
i.e., don't use a single `KeyPress` like 'a+b'.
|
||||||
|
The `KeyPress` action normally both depresses and releases (clicks) the keys,
|
||||||
|
but can also just depress the keys or just release the keys.
|
||||||
|
Use the depress or release options with extreme care,
|
||||||
|
ensuring that the depressed keys are later released.
|
||||||
|
Otherwise it may become difficult to use your system.
|
||||||
|
The keys are depressed in forward order and released in reverse order.
|
||||||
|
|
||||||
If a key symbol can only be produced by a shfited or level 3 keypress, e.g., "A",
|
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,
|
then Solaar will add keypresses to produce that keysymbol,
|
||||||
e.g., simulating a left shift keypress to get "A" instead of "a".
|
e.g., simulating a left shift keypress to get "A" instead of "a".
|
||||||
|
|
|
@ -820,14 +820,28 @@ class Action(RuleComponent):
|
||||||
|
|
||||||
|
|
||||||
class KeyPress(Action):
|
class KeyPress(Action):
|
||||||
def __init__(self, keys):
|
CLICK, DEPRESS, RELEASE = 'click', 'depress', 'release'
|
||||||
if isinstance(keys, str):
|
|
||||||
keys = [keys]
|
def __init__(self, args):
|
||||||
self.key_names = keys
|
self.key_names, self.action = self.regularize_args(args)
|
||||||
self.key_symbols = [XK_KEYS.get(k, None) for k in keys]
|
if not isinstance(self.key_names, list):
|
||||||
if not all(self.key_symbols):
|
_log.warn('rule KeyPress keys not key names %s', self.keys_names)
|
||||||
_log.warn('rule KeyPress not sequence of key names %s', keys)
|
|
||||||
self.key_symbols = []
|
self.key_symbols = []
|
||||||
|
else:
|
||||||
|
self.key_symbols = [XK_KEYS.get(k, None) for k in self.key_names]
|
||||||
|
if not all(self.key_symbols):
|
||||||
|
_log.warn('rule KeyPress keys not key names %s', self.key_names)
|
||||||
|
self.key_symbols = []
|
||||||
|
|
||||||
|
def regularize_args(self, args):
|
||||||
|
action = self.CLICK
|
||||||
|
if not isinstance(args, list):
|
||||||
|
args = [args]
|
||||||
|
keys = args
|
||||||
|
if len(args) == 2 and args[1] in [self.CLICK, self.DEPRESS, self.RELEASE]:
|
||||||
|
keys = [args[0]] if isinstance(args[0], str) else args[0]
|
||||||
|
action = args[1]
|
||||||
|
return keys, action
|
||||||
|
|
||||||
# WARNING: This is an attempt to reverse the keycode to keysym mappping in XKB. It may not be completely general.
|
# WARNING: This is an attempt to reverse the keycode to keysym mappping in XKB. It may not be completely general.
|
||||||
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
|
||||||
|
@ -849,7 +863,7 @@ class KeyPress(Action):
|
||||||
return (keycode, level)
|
return (keycode, level)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'KeyPress: ' + ' '.join(self.key_names)
|
return 'KeyPress: ' + ' '.join(self.key_names) + ' ' + self.action
|
||||||
|
|
||||||
def needed(self, k, modifiers):
|
def needed(self, k, modifiers):
|
||||||
code = modifier_code(k)
|
code = modifier_code(k)
|
||||||
|
@ -885,16 +899,18 @@ class KeyPress(Action):
|
||||||
if gkeymap:
|
if gkeymap:
|
||||||
current = gkeymap.get_modifier_state()
|
current = gkeymap.get_modifier_state()
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info('KeyPress action: %s, group %s, modifiers %s', self.key_names, kbdgroup(), current)
|
_log.info('KeyPress action: %s %s, group %s, modifiers %s', self.key_names, self.action, kbdgroup(), current)
|
||||||
self.keyDown(self.key_symbols, current)
|
if self.action != self.RELEASE:
|
||||||
self.keyUp(reversed(self.key_symbols), current)
|
self.keyDown(self.key_symbols, current)
|
||||||
|
if self.action != self.DEPRESS:
|
||||||
|
self.keyUp(reversed(self.key_symbols), current)
|
||||||
_time.sleep(0.01)
|
_time.sleep(0.01)
|
||||||
else:
|
else:
|
||||||
_log.warn('no keymap so cannot determine which keycode to send')
|
_log.warn('no keymap so cannot determine which keycode to send')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def data(self):
|
def data(self):
|
||||||
return {'KeyPress': [str(k) for k in self.key_names]}
|
return {'KeyPress': [[str(k) for k in self.key_names], self.action]}
|
||||||
|
|
||||||
|
|
||||||
# KeyDown is dangerous as the key can auto-repeat and make your system unusable
|
# KeyDown is dangerous as the key can auto-repeat and make your system unusable
|
||||||
|
|
Loading…
Reference in New Issue