diff --git a/docs/rules.md b/docs/rules.md index 1ab859cf..3401fc63 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -55,9 +55,9 @@ notification is their integer argument. can only be `Shift`, `Control`, `Alt`, and `Super`. Modifiers conditions are true if their argument is the current keyboard modifiers. -`Key` conditions are true if the Logitech name of the last key down is their -string argument. Logitech key names are shown in the `Key/Button Diversion` -setting. +`Key` conditions are true if the Logitech name of the last diverted key or button down is their +string argument. Logitech key and button names are shown in the `Key/Button Diversion` +setting. Some keyboards have Gn keys, which are diverted using the 'Divert G Keys' setting. `Test` conditions are true if their test evaluates to true on the feature, report, and data of the current notification. Test conditions can return a number instead of a boolean. diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py index b7d36a60..f02675b4 100644 --- a/lib/logitech_receiver/diversion.py +++ b/lib/logitech_receiver/diversion.py @@ -135,7 +135,6 @@ if x11: # See docs/rules.md for documentation -keys_down = [] key_down = None @@ -595,21 +594,17 @@ built_in_rules = Rule([]) if x11: built_in_rules = Rule([ {'Rule': [ # Implement problematic keys for Craft and MX Master - {'Feature': 'REPROG_CONTROLS_V4'}, - {'Report': 0x0}, {'Rule': [{'Key': 'Brightness Down'}, {'KeyPress': 'XF86_MonBrightnessDown'}]}, {'Rule': [{'Key': 'Brightness Up'}, {'KeyPress': 'XF86_MonBrightnessUp'}]}, ]}, {'Rule': [ # In firefox, crown emits keys that move up and down if not pressed, rotate through tabs otherwise {'Process': 'firefox'}, - {'Feature': 'CROWN'}, - {'Report': 0x0}, {'Rule': [{'Test': 'crown_pressed'}, {'Test': 'crown_right_ratchet'}, {'KeyPress': ['Control_R', 'Tab']}]}, {'Rule': [{'Test': 'crown_pressed'}, {'Test': 'crown_left_ratchet'}, {'KeyPress': ['Control_R', 'Shift_R', 'Tab']}]}, {'Rule': [{'Test': 'crown_right_ratchet'}, {'KeyPress': 'Down'}]}, - Rule([Test('crown_left_ratchet'), KeyPress(['Up'])]), + {'Rule': [{'Test': 'crown_left_ratchet'}, {'KeyPress': 'Up'}]}, ]}, {'Rule': [ # Otherwise, crown movements emit keys that modify volume if not pressed, move between tracks otherwise {'Feature': 'CROWN'}, {'Report': 0x0}, @@ -626,12 +621,15 @@ if x11: ]} ]) +keys_down = [] +g_keys_down = 0x00 + # process a notification def process_notification(device, status, notification, feature): if not x11: return - global keys_down, key_down + global keys_down, g_keys_down, key_down key_down = None # need to keep track of keys that are down to find a new key down if feature == _F.REPROG_CONTROLS_V4 and notification.address == 0x00: @@ -640,6 +638,13 @@ def process_notification(device, status, notification, feature): if key and key not in keys_down: key_down = key keys_down = new_keys_down + # and also G keys down + elif feature == _F.GKEY and notification.address == 0x00: + new_g_keys_down, = _unpack('!B', notification.data[:1]) + for i in range(1, 9): + if new_g_keys_down & (0x01 << (i - 1)) and not g_keys_down & (0x01 << (i - 1)): + key_down = _CONTROL['G' + str(i)] + g_keys_down = new_g_keys_down rules.evaluate(feature, notification, device, status, True) diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index 463b3ae2..708c4386 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -97,7 +97,7 @@ _REPROGRAMMABLE_KEYS = ('reprogrammable-keys', _('Key/Button Actions'), _('Change the action for the key or button.') + '\n' + _('Changing important actions (such as for the left mouse button) can result in an unusable system.')) _DIVERT_KEYS = ('divert-keys', _('Key/Button Diversion'), - _('Divert the key or button to report using HID++ notifications.')) + _('Make the key or button send HID++ notifications (which trigger Solaar rules but are otherwise ignored).')) _DISABLE_KEYS = ('disable-keyboard-keys', _('Disable keys'), _('Disable specific keyboard keys.')) _PLATFORM = ('multiplatform', _('Set OS'), _('Change keys to match OS.')) _CHANGE_HOST = ('change-host', _('Change Host'), _('Switch connection to a different host')) @@ -110,7 +110,9 @@ _GESTURE2_PARAMS = ('gesture2-params', _('Gesture params'), _('Change numerical _DPI_SLIDING = ('dpi-sliding', _('DPI Sliding Adjustment'), _('Adjust the DPI by sliding the mouse horizontally while holding the DPI button.')) _DIVERT_CROWN = ('divert-crown', _('Divert crown events'), - _('Make the crown send HID++ events (which are normally ignored in Linux).')) + _('Make crown send CROWN HID++ notifications (which trigger Solaar rules but are otherwise ignored).')) +_DIVERT_GKEYS = ('divert-gkeys', _('Divert G Keys'), + _('Make G keys send GKEY HID++ notifications (which trigger Solaar rules but are otherwise ignored).')) _GESTURE2_GESTURES_LABELS = { _GG['Tap1Finger']: (_('Single tap'), _('Performs a left click.')), @@ -711,6 +713,18 @@ def _feature_divert_crown(): return _Setting(_DIVERT_CROWN, rw, _BooleanV(true_value=0x02, false_value=0x01, mask=0xff), device_kind=(_DK.keyboard, )) +def _feature_divert_gkeys(): + class _DivertGkeysRW(_FeatureRW): + def __init__(self, feature): + super(_DivertGkeysRW, self).__init__(feature, write_fnid=0x20) + + def read(self, device): # no way to read, so just assume not diverted + return 0x00 + + rw = _DivertGkeysRW(_F.GKEY) + return _Setting(_DIVERT_GKEYS, rw, _BooleanV(true_value=0x01, false_value=0x00, mask=0xff), device_kind=(_DK.keyboard, )) + + # # # @@ -743,6 +757,7 @@ _SETTINGS_TABLE = [ _S(_DIVERT_KEYS, _F.REPROG_CONTROLS_V4, _feature_divert_keys), _S(_DISABLE_KEYS, _F.KEYBOARD_DISABLE_KEYS, _feature_disable_keyboard_keys), _S(_DIVERT_CROWN, _F.CROWN, _feature_divert_crown), + _S(_DIVERT_GKEYS, _F.GKEY, _feature_divert_gkeys), _S(_PLATFORM, _F.MULTIPLATFORM, _feature_multiplatform), _S(_PLATFORM, _F.DUALPLATFORM, _feature_dualplatform, identifier='dualplatform'), _S(_CHANGE_HOST, _F.CHANGE_HOST, _feature_change_host), diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py index 17fb086b..d0167cec 100644 --- a/lib/logitech_receiver/special_keys.py +++ b/lib/logitech_receiver/special_keys.py @@ -271,6 +271,10 @@ CONTROL = _NamedInts( LeftAndRightClick=0x0102, LED_Toggle=0x013B, # ) + +for i in range(1, 7): # add in G keys - these are not really Logitech Controls + CONTROL[0x1000 + i] = 'G' + str(i) + CONTROL._fallback = lambda x: 'unknown:%04X' % x #