settings: provide symbolic names for per-key lighting keys
This commit is contained in:
parent
4d0f93b35c
commit
f38fbcf949
|
@ -51,7 +51,7 @@ connect via a USB cable or via bluetooth can be determined by their USB or
|
||||||
Bluetooth product ID.
|
Bluetooth product ID.
|
||||||
|
|
||||||
|
|
||||||
# Pairing and Unpairing
|
## Pairing and Unpairing
|
||||||
|
|
||||||
Solaar is able to pair and unpair devices with
|
Solaar is able to pair and unpair devices with
|
||||||
receivers as supported by the device and receiver.
|
receivers as supported by the device and receiver.
|
||||||
|
@ -174,6 +174,18 @@ is sent to the Solaar rule system so that rules can detect these notifications.
|
||||||
For more information on Mouse Gestures rule conditions see
|
For more information on Mouse Gestures rule conditions see
|
||||||
[the rules page](https://pwr-solaar.github.io/Solaar/rules).
|
[the rules page](https://pwr-solaar.github.io/Solaar/rules).
|
||||||
|
|
||||||
|
### Keyboard Key Names and Locations
|
||||||
|
|
||||||
|
Solaar uses the standard Logitech names for keyboard keys. Some Logitech keyboards have different icons on some of their keys and have different functionality than suggested by these names.
|
||||||
|
|
||||||
|
Solaar is uses the standard US keyboard layout. This currently only matters for the `Per-key Lighting` setting. Users who want to have the key names for this setting reflect the keyboard layout that they use can create and edit `~/.config/solaar/keys.yaml` which contains a YAML dictionary of key names and locations. For example, switching the `Y` and `Z` keys can be done as:
|
||||||
|
|
||||||
|
Z: 25
|
||||||
|
Y: 26
|
||||||
|
|
||||||
|
This is an experimental feature and may be modified or even eliminated.
|
||||||
|
|
||||||
|
|
||||||
### Device Profiles
|
### Device Profiles
|
||||||
|
|
||||||
Some mice store one or more profiles, which control aspects of the behavior of the device.
|
Some mice store one or more profiles, which control aspects of the behavior of the device.
|
||||||
|
|
|
@ -1579,7 +1579,7 @@ class PerKeyLighting(_Settings):
|
||||||
label = _("Per-key Lighting")
|
label = _("Per-key Lighting")
|
||||||
description = _("Control per-key lighting.")
|
description = _("Control per-key lighting.")
|
||||||
feature = _F.PER_KEY_LIGHTING_V2
|
feature = _F.PER_KEY_LIGHTING_V2
|
||||||
keys_universe = _NamedInts.range(1, 254)
|
keys_universe = _special_keys.KEYCODES
|
||||||
choices_universe = _special_keys.COLORS
|
choices_universe = _special_keys.COLORS
|
||||||
|
|
||||||
def read(self, cached=True):
|
def read(self, cached=True):
|
||||||
|
@ -1607,7 +1607,7 @@ class PerKeyLighting(_Settings):
|
||||||
return map
|
return map
|
||||||
|
|
||||||
def write_key_value(self, key, value, save=True):
|
def write_key_value(self, key, value, save=True):
|
||||||
result = super().write_key_value(key, value, save)
|
result = super().write_key_value(int(key), value, save)
|
||||||
if self._device.online:
|
if self._device.online:
|
||||||
self._device.feature_request(self.feature, 0x70, 0x00) # signal device to make the change
|
self._device.feature_request(self.feature, 0x70, 0x00) # signal device to make the change
|
||||||
return result
|
return result
|
||||||
|
@ -1624,7 +1624,8 @@ class PerKeyLighting(_Settings):
|
||||||
key_bitmap += device.feature_request(setting_class.feature, 0x00, 0x00, 0x02)[2:]
|
key_bitmap += device.feature_request(setting_class.feature, 0x00, 0x00, 0x02)[2:]
|
||||||
for i in range(1, 255):
|
for i in range(1, 255):
|
||||||
if (key_bitmap[i // 8] >> i % 8) & 0x01:
|
if (key_bitmap[i // 8] >> i % 8) & 0x01:
|
||||||
choices_map[setting_class.keys_universe[i]] = setting_class.choices_universe
|
key = setting_class.keys_universe[i] if i in setting_class.keys_universe else _NamedInt(i, "KEY " + str(i))
|
||||||
|
choices_map[key] = setting_class.choices_universe
|
||||||
result = cls(choices_map) if choices_map else None
|
result = cls(choices_map) if choices_map else None
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,16 @@
|
||||||
# Reprogrammable keys information
|
# Reprogrammable keys information
|
||||||
# Mostly from Logitech documentation, but with some edits for better Lunix compatibility
|
# Mostly from Logitech documentation, but with some edits for better Lunix compatibility
|
||||||
|
|
||||||
|
import os as _os
|
||||||
|
|
||||||
|
import yaml as _yaml
|
||||||
|
|
||||||
from .common import NamedInts as _NamedInts
|
from .common import NamedInts as _NamedInts
|
||||||
from .common import UnsortedNamedInts as _UnsortedNamedInts
|
from .common import UnsortedNamedInts as _UnsortedNamedInts
|
||||||
|
|
||||||
|
_XDG_CONFIG_HOME = _os.environ.get("XDG_CONFIG_HOME") or _os.path.expanduser(_os.path.join("~", ".config"))
|
||||||
|
_keys_file_path = _os.path.join(_XDG_CONFIG_HOME, "solaar", "keys.yaml")
|
||||||
|
|
||||||
# <controls.xml awk -F\" '/<Control /{sub(/^LD_FINFO_(CTRLID_)?/, "", $2);printf("\t%s=0x%04X,\n", $2, $4)}' | sort -t= -k2
|
# <controls.xml awk -F\" '/<Control /{sub(/^LD_FINFO_(CTRLID_)?/, "", $2);printf("\t%s=0x%04X,\n", $2, $4)}' | sort -t= -k2
|
||||||
CONTROL = _NamedInts(
|
CONTROL = _NamedInts(
|
||||||
{
|
{
|
||||||
|
@ -1392,3 +1399,139 @@ COLORS = _UnsortedNamedInts(
|
||||||
"light green": 0x90EE90,
|
"light green": 0x90EE90,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
KEYCODES = _NamedInts(
|
||||||
|
{
|
||||||
|
"A": 1,
|
||||||
|
"B": 2,
|
||||||
|
"C": 3,
|
||||||
|
"D": 4,
|
||||||
|
"E": 5,
|
||||||
|
"F": 6,
|
||||||
|
"G": 7,
|
||||||
|
"H": 8,
|
||||||
|
"I": 9,
|
||||||
|
"J": 10,
|
||||||
|
"K": 11,
|
||||||
|
"L": 12,
|
||||||
|
"M": 13,
|
||||||
|
"N": 14,
|
||||||
|
"O": 15,
|
||||||
|
"P": 16,
|
||||||
|
"Q": 17,
|
||||||
|
"R": 18,
|
||||||
|
"S": 19,
|
||||||
|
"T": 20,
|
||||||
|
"U": 21,
|
||||||
|
"V": 22,
|
||||||
|
"W": 23,
|
||||||
|
"X": 24,
|
||||||
|
"Y": 25,
|
||||||
|
"Z": 26,
|
||||||
|
"1": 27,
|
||||||
|
"2": 28,
|
||||||
|
"3": 29,
|
||||||
|
"4": 30,
|
||||||
|
"5": 31,
|
||||||
|
"6": 32,
|
||||||
|
"7": 33,
|
||||||
|
"8": 34,
|
||||||
|
"9": 35,
|
||||||
|
"0": 36,
|
||||||
|
"ENTER": 37,
|
||||||
|
"ESC": 38,
|
||||||
|
"BACKSPACE": 39,
|
||||||
|
"TAB": 40,
|
||||||
|
"SPACE": 41,
|
||||||
|
"-": 42,
|
||||||
|
"=": 43,
|
||||||
|
"[": 44,
|
||||||
|
"]": 45,
|
||||||
|
"\\": 45,
|
||||||
|
"~": 47,
|
||||||
|
";": 48,
|
||||||
|
"'": 49,
|
||||||
|
"`": 50,
|
||||||
|
",": 51,
|
||||||
|
".": 52,
|
||||||
|
"/": 53,
|
||||||
|
"CAPS LOCK": 54,
|
||||||
|
"F1": 55,
|
||||||
|
"F2": 56,
|
||||||
|
"F3": 57,
|
||||||
|
"F4": 58,
|
||||||
|
"F5": 59,
|
||||||
|
"F6": 60,
|
||||||
|
"F7": 61,
|
||||||
|
"F8": 62,
|
||||||
|
"F9": 63,
|
||||||
|
"F10": 64,
|
||||||
|
"F11": 65,
|
||||||
|
"F12": 66,
|
||||||
|
"PRINT": 67,
|
||||||
|
"SCROLL LOCK": 68,
|
||||||
|
"PASTE": 69,
|
||||||
|
"INSERT": 70,
|
||||||
|
"HOME": 71,
|
||||||
|
"PAGE UP": 72,
|
||||||
|
"DELETE": 73,
|
||||||
|
"END": 74,
|
||||||
|
"PAGE DOWN": 75,
|
||||||
|
"RIGHT": 76,
|
||||||
|
"LEFT": 77,
|
||||||
|
"DOWN": 78,
|
||||||
|
"UP": 79,
|
||||||
|
"NUMLOCK": 80,
|
||||||
|
"KEYPAD /": 81,
|
||||||
|
"KEYPAD *": 82,
|
||||||
|
"KEYPAD -": 83,
|
||||||
|
"KEYPAD +": 84,
|
||||||
|
"KEYPAD ENTER": 85,
|
||||||
|
"KEYPAD 1": 86,
|
||||||
|
"KEYPAD 2": 87,
|
||||||
|
"KEYPAD 3": 88,
|
||||||
|
"KEYPAD 4": 89,
|
||||||
|
"KEYPAD 5": 90,
|
||||||
|
"KEYPAD 6": 91,
|
||||||
|
"KEYPAD 7": 92,
|
||||||
|
"KEYPAD 8": 93,
|
||||||
|
"KEYPAD 9": 94,
|
||||||
|
"KEYPAD 0": 95,
|
||||||
|
"KEYPAD .": 96,
|
||||||
|
"COMPOSE": 98,
|
||||||
|
"POWER": 99,
|
||||||
|
"LEFT CTRL": 104,
|
||||||
|
"LEFT SHIFT": 105,
|
||||||
|
"LEFT ALT": 106,
|
||||||
|
"LEFT WINDOWS": 107,
|
||||||
|
"RIGHT CTRL": 108,
|
||||||
|
"RIGHT SHIFT": 109,
|
||||||
|
"RIGHT ALTGR": 110,
|
||||||
|
"RIGHT WINDOWS": 111,
|
||||||
|
"BRIGHTNESS": 153,
|
||||||
|
"PAUSE": 155,
|
||||||
|
"MUTE": 156,
|
||||||
|
"NEXT": 157,
|
||||||
|
"PREVIOUS": 158,
|
||||||
|
"G1": 180,
|
||||||
|
"G2": 181,
|
||||||
|
"G3": 182,
|
||||||
|
"G4": 183,
|
||||||
|
"G5": 184,
|
||||||
|
"LOGO": 210,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# load in override dictionary for KEYCODES
|
||||||
|
try:
|
||||||
|
with open(_keys_file_path) as keys_file:
|
||||||
|
keys = _yaml.safe_load(keys_file)
|
||||||
|
if isinstance(keys, dict):
|
||||||
|
keys = _NamedInts(**keys)
|
||||||
|
for k in KEYCODES:
|
||||||
|
if int(k) not in keys and str(k) not in keys:
|
||||||
|
keys[int(k)] = str(k)
|
||||||
|
KEYCODES = keys
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
|
@ -560,12 +560,12 @@ key_tests = [
|
||||||
5,
|
5,
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
common.NamedInt(1, "1"): special_keys.COLORS,
|
common.NamedInt(1, "A"): special_keys.COLORS,
|
||||||
common.NamedInt(2, "2"): special_keys.COLORS,
|
common.NamedInt(2, "B"): special_keys.COLORS,
|
||||||
common.NamedInt(9, "9"): special_keys.COLORS,
|
common.NamedInt(9, "I"): special_keys.COLORS,
|
||||||
common.NamedInt(10, "10"): special_keys.COLORS,
|
common.NamedInt(10, "J"): special_keys.COLORS,
|
||||||
common.NamedInt(113, "113"): special_keys.COLORS,
|
common.NamedInt(113, "KEY 113"): special_keys.COLORS,
|
||||||
common.NamedInt(114, "114"): special_keys.COLORS,
|
common.NamedInt(114, "KEY 114"): special_keys.COLORS,
|
||||||
},
|
},
|
||||||
hidpp.Response("00000606000000000000000000000000", 0x0400, "0000"), # first group of keys
|
hidpp.Response("00000606000000000000000000000000", 0x0400, "0000"), # first group of keys
|
||||||
hidpp.Response("00000600000000000000000000000000", 0x0400, "0001"), # second group of keys
|
hidpp.Response("00000600000000000000000000000000", 0x0400, "0001"), # second group of keys
|
||||||
|
@ -586,7 +586,7 @@ def test_key_template(test, mocker):
|
||||||
spy_request = mocker.spy(device, "request")
|
spy_request = mocker.spy(device, "request")
|
||||||
|
|
||||||
setting = settings_templates.check_feature(device, tst.sclass)
|
setting = settings_templates.check_feature(device, tst.sclass)
|
||||||
assert setting is not None
|
assert setting
|
||||||
if isinstance(setting, list):
|
if isinstance(setting, list):
|
||||||
setting = setting[0]
|
setting = setting[0]
|
||||||
assert setting.choices == test.choices
|
assert setting.choices == test.choices
|
||||||
|
|
Loading…
Reference in New Issue