Remove NamedInts: Convert KeyFlag to Flag

Related #2273
This commit is contained in:
MattHag 2024-11-05 01:37:42 +01:00 committed by Peter F. Patel-Schneider
parent 0bf7a78553
commit f54eeb7998
2 changed files with 43 additions and 35 deletions

View File

@ -21,6 +21,7 @@ import socket
import struct
import threading
from enum import Flag
from typing import Any
from typing import Dict
from typing import Generator
@ -42,7 +43,6 @@ from .common import BatteryLevelApproximation
from .common import BatteryStatus
from .common import FirmwareKind
from .common import NamedInt
from .common import NamedInts
from .hidpp20_constants import CHARGE_STATUS
from .hidpp20_constants import DEVICE_KIND
from .hidpp20_constants import ChargeLevel
@ -80,22 +80,27 @@ class Device(Protocol):
...
# Capabilities and desired software handling for a control
# Ref: https://drive.google.com/file/d/10imcbmoxTJ1N510poGdsviEhoFfB_Ua4/view
# We treat bytes 4 and 8 of `getCidInfo` as a single bitfield
KEY_FLAG = NamedInts(
analytics_key_events=0x400,
force_raw_XY=0x200,
raw_XY=0x100,
virtual=0x80,
persistently_divertable=0x40,
divertable=0x20,
reprogrammable=0x10,
FN_sensitive=0x08,
nonstandard=0x04,
is_FN=0x02,
mse=0x01,
)
class KeyFlag(Flag):
"""Capabilities and desired software handling for a control.
Ref: https://drive.google.com/file/d/10imcbmoxTJ1N510poGdsviEhoFfB_Ua4/view
We treat bytes 4 and 8 of `getCidInfo` as a single bitfield
"""
ANALYTICS_KEY_EVENTS = 0x400
FORCE_RAW_XY = 0x200
RAW_XY = 0x100
VIRTUAL = 0x80
PERSISTENTLY_DIVERTABLE = 0x40
DIVERTABLE = 0x20
REPROGRAMMABLE = 0x10
FN_SENSITIVE = 0x08
NONSTANDARD = 0x04
IS_FN = 0x02
MSE = 0x01
def __str__(self):
return self.name.replace("_", " ")
class FeaturesArray(dict):
@ -211,7 +216,7 @@ class ReprogrammableKey:
- flags {List[str]} -- capabilities and desired software handling of the control
"""
def __init__(self, device: Device, index, cid, task_id, flags):
def __init__(self, device: Device, index: int, cid: int, task_id: int, flags):
self._device = device
self.index = index
self._cid = cid
@ -236,7 +241,7 @@ class ReprogrammableKey:
@property
def flags(self) -> List[str]:
return KEY_FLAG.flag_names(self._flags)
return list(common.flag_names(KeyFlag, self._flags))
class ReprogrammableKeyV4(ReprogrammableKey):
@ -373,19 +378,20 @@ class ReprogrammableKeyV4(ReprogrammableKey):
# The capability required to set a given reporting flag.
FLAG_TO_CAPABILITY = {
special_keys.MAPPING_FLAG.diverted: KEY_FLAG.divertable,
special_keys.MAPPING_FLAG.persistently_diverted: KEY_FLAG.persistently_divertable,
special_keys.MAPPING_FLAG.analytics_key_events_reporting: KEY_FLAG.analytics_key_events,
special_keys.MAPPING_FLAG.force_raw_XY_diverted: KEY_FLAG.force_raw_XY,
special_keys.MAPPING_FLAG.raw_XY_diverted: KEY_FLAG.raw_XY,
special_keys.MAPPING_FLAG.diverted: KeyFlag.DIVERTABLE,
special_keys.MAPPING_FLAG.persistently_diverted: KeyFlag.PERSISTENTLY_DIVERTABLE,
special_keys.MAPPING_FLAG.analytics_key_events_reporting: KeyFlag.ANALYTICS_KEY_EVENTS,
special_keys.MAPPING_FLAG.force_raw_XY_diverted: KeyFlag.FORCE_RAW_XY,
special_keys.MAPPING_FLAG.raw_XY_diverted: KeyFlag.RAW_XY,
}
bfield = 0
for f, v in flags.items():
if v and FLAG_TO_CAPABILITY[f] not in self.flags:
key_flag = FLAG_TO_CAPABILITY[f].name.lower()
if v and key_flag not in self.flags:
raise exceptions.FeatureNotSupported(
msg=f'Tried to set mapping flag "{f}" on control "{self.key}" '
+ f'which does not support "{FLAG_TO_CAPABILITY[f]}" on device {self._device}.'
+ f'which does not support "{key_flag}" on device {self._device}.'
)
bfield |= int(f) if v else 0
bfield |= int(f) << 1 # The 'Xvalid' bit

View File

@ -170,7 +170,7 @@ def test_reprogrammable_key_key(device, index, cid, task_id, flags, default_task
assert key._flags == flags
assert key.key == special_keys.CONTROL[cid]
assert key.default_task == common.NamedInt(cid, default_task)
assert list(key.flags) == flag_names
assert sorted(list(key.flags)) == sorted(flag_names)
@pytest.mark.parametrize(
@ -188,7 +188,7 @@ def test_reprogrammable_key_key(device, index, cid, task_id, flags, default_task
2,
7,
"Mouse Back Button",
["reprogrammable", "raw XY"],
["reprogrammable", "raw_xy"],
["g1", "g2", "g3"],
),
],
@ -208,7 +208,7 @@ def test_reprogrammable_key_v4_key(
assert key._gmask == gmask
assert key.key == special_keys.CONTROL[cid]
assert key.default_task == common.NamedInt(cid, default_task)
assert list(key.flags) == flag_names
assert sorted(list(key.flags)) == sorted(flag_names)
assert list(key.group_mask) == group_names
@ -256,26 +256,28 @@ def test_ReprogrammableKeyV4_set(responses, index, diverted, persistently_divert
key = device.keys[index]
_mapping_flags = list(key.mapping_flags)
if "divertable" in key.flags or not diverted:
if hidpp20.KeyFlag.DIVERTABLE in key.flags or not diverted:
key.set_diverted(diverted)
else:
with pytest.raises(exceptions.FeatureNotSupported):
key.set_diverted(diverted)
assert ("diverted" in list(key.mapping_flags)) == (diverted and "divertable" in key.flags)
assert ("diverted" in list(key.mapping_flags)) == (diverted and hidpp20.KeyFlag.DIVERTABLE in key.flags)
if "persistently divertable" in key.flags or not persistently_diverted:
if hidpp20.KeyFlag.PERSISTENTLY_DIVERTABLE in key.flags or not persistently_diverted:
key.set_persistently_diverted(persistently_diverted)
else:
with pytest.raises(exceptions.FeatureNotSupported):
key.set_persistently_diverted(persistently_diverted)
assert ("persistently diverted" in key.mapping_flags) == (persistently_diverted and "persistently divertable" in key.flags)
assert (hidpp20.KeyFlag.PERSISTENTLY_DIVERTABLE in key.mapping_flags) == (
persistently_diverted and hidpp20.KeyFlag.PERSISTENTLY_DIVERTABLE in key.flags
)
if "raw XY" in key.flags or not rawXY_reporting:
if hidpp20.KeyFlag.RAW_XY in key.flags or not rawXY_reporting:
key.set_rawXY_reporting(rawXY_reporting)
else:
with pytest.raises(exceptions.FeatureNotSupported):
key.set_rawXY_reporting(rawXY_reporting)
assert ("raw XY diverted" in list(key.mapping_flags)) == (rawXY_reporting and "raw XY" in key.flags)
assert ("raw XY diverted" in list(key.mapping_flags)) == (rawXY_reporting and hidpp20.KeyFlag.RAW_XY in key.flags)
if remap in key.remappable_to or remap == 0:
key.remap(remap)