settings: add setting for PERSISTENT_REMAPPABLE_ACTION

This commit is contained in:
Peter F. Patel-Schneider 2020-08-22 06:56:08 -04:00
parent 12ecef004e
commit d646e18543
3 changed files with 58 additions and 14 deletions

View File

@ -443,7 +443,6 @@ class Settings(Setting):
_log.debug('%s: settings prepare key value write(%s,%s) => %r', self.name, key, value, data_bytes) _log.debug('%s: settings prepare key value write(%s,%s) => %r', self.name, key, value, data_bytes)
reply = self._rw.write(self._device, int(key), data_bytes) reply = self._rw.write(self._device, int(key), data_bytes)
if not reply: if not reply:
# tell whomever is calling that the write failed
return None return None
return value return value
@ -978,8 +977,9 @@ class ChoicesMapValidator(ChoicesValidator):
def __init__( def __init__(
self, self,
choices_map, choices_map,
key_byte_count=None, key_byte_count=0,
byte_count=None, key_postfix_bytes=b'',
byte_count=0,
read_skip_byte_count=0, read_skip_byte_count=0,
write_prefix_bytes=b'', write_prefix_bytes=b'',
extra_default=None, extra_default=None,
@ -1005,10 +1005,12 @@ class ChoicesMapValidator(ChoicesValidator):
if byte_count: if byte_count:
assert self._byte_count <= byte_count assert self._byte_count <= byte_count
self._byte_count = byte_count self._byte_count = byte_count
self.choices = choices_map self.choices = choices_map
self.needs_current_value = False self.needs_current_value = False
self.extra_default = extra_default self.extra_default = extra_default
self._read_skip_byte_count = read_skip_byte_count self._key_postfix_bytes = key_postfix_bytes
self._read_skip_byte_count = read_skip_byte_count if read_skip_byte_count else 0
self._write_prefix_bytes = write_prefix_bytes if write_prefix_bytes else b'' self._write_prefix_bytes = write_prefix_bytes if write_prefix_bytes else b''
self.activate = activate self.activate = activate
self.mask = mask self.mask = mask
@ -1029,10 +1031,14 @@ class ChoicesMapValidator(ChoicesValidator):
# reprogrammable keys starts out as 0, which is not a choice, so don't use assert here # reprogrammable keys starts out as 0, which is not a choice, so don't use assert here
if self.extra_default is not None and self.extra_default == reply_value: if self.extra_default is not None and self.extra_default == reply_value:
return int(self.choices[key][0]) return int(self.choices[key][0])
assert reply_value in self.choices[ if reply_value not in self.choices[key]:
key], '%s: failed to validate read value %02X' % (self.__class__.__name__, reply_value) assert reply_value in self.choices[
key], '%s: failed to validate read value %02X' % (self.__class__.__name__, reply_value)
return reply_value return reply_value
def prepare_key(self, key):
return key.to_bytes(self._key_byte_count, 'big') + self._key_postfix_bytes
def prepare_write(self, key, new_value): def prepare_write(self, key, new_value):
choices = self.choices.get(key) choices = self.choices.get(key)
if choices is None or (new_value not in choices and new_value != self.extra_default): if choices is None or (new_value not in choices and new_value != self.extra_default):

View File

@ -449,9 +449,7 @@ class ReprogrammableKeys(_Settings):
tgts = k.remappable_to tgts = k.remappable_to
if len(tgts) > 1: if len(tgts) > 1:
choices[k.key] = tgts choices[k.key] = tgts
if not choices: return cls(choices, key_byte_count=2, byte_count=2, extra_default=0) if choices else None
return None
return cls(choices, key_byte_count=2, byte_count=2, extra_default=0)
class DivertKeys(_Settings): class DivertKeys(_Settings):
@ -1044,6 +1042,48 @@ class MRKeyLED(_Setting):
return b'\x00' return b'\x00'
## Only implemented for devices that can produce HID and Consumer Key Codes
## Only interested in current host, so use 0xFF for it
class PersistentRemappableAction(_Settings):
name = 'persistent-remappable-keys'
label = _('Persistent Key/Button Mapping')
description = (
_('Permanently change the mapping for the key or button.') + '\n' +
_('Changing important keys or buttons (such as for the left mouse button) can result in an unusable system.')
)
persist = False # This setting is persistent in the device so no need to persist it here
feature = _F.PERSISTENT_REMAPPABLE_ACTION
keys_universe = _special_keys.CONTROL
choices_universe = _special_keys.KEYS
class rw_class:
def __init__(self, feature):
self.feature = feature
self.kind = _FeatureRW.kind
def read(self, device, key):
ks = device.remap_keys[device.remap_keys.index(key)]
return b'\x00\x00' + ks.data_bytes
def write(self, device, key, data_bytes):
ks = device.remap_keys[device.remap_keys.index(key)]
v = ks.remap(data_bytes)
return v
class validator_class(_ChoicesMapV):
@classmethod
def build(cls, setting_class, device):
remap_keys = device.remap_keys
if not remap_keys or not device.remap_keys.capabilities & 0x0041 == 0x0041: # HID and Consumer Key Codes
return None
choices = {}
for k in remap_keys:
key = _special_keys.CONTROL[k.key]
choices[key] = _special_keys.KEYS
return cls(choices, key_byte_count=2, byte_count=4) if choices else None
SETTINGS = [ SETTINGS = [
RegisterHandDetection, # simple RegisterHandDetection, # simple
RegisterSmoothScroll, # simple RegisterSmoothScroll, # simple
@ -1071,13 +1111,14 @@ SETTINGS = [
NewFnSwap, # simple NewFnSwap, # simple
K375sFnSwap, # working K375sFnSwap, # working
ReprogrammableKeys, # working ReprogrammableKeys, # working
PersistentRemappableAction,
DivertKeys, # working DivertKeys, # working
DisableKeyboardKeys, # working DisableKeyboardKeys, # working
DivertCrown, # working DivertCrown, # working
CrownSmooth, # working CrownSmooth, # working
DivertGkeys, # working DivertGkeys, # working
MKeyLEDs, # working MKeyLEDs, # working
MRKeyLED, MRKeyLED, # working
Multiplatform, # working Multiplatform, # working
DualPlatform, # simple DualPlatform, # simple
ChangeHost, # working ChangeHost, # working

View File

@ -255,10 +255,7 @@ def _print_device(dev, num=None):
if dev.online and dev.remap_keys: if dev.online and dev.remap_keys:
print(' Has %d persistent remappable keys:' % len(dev.remap_keys)) print(' Has %d persistent remappable keys:' % len(dev.remap_keys))
for k in dev.remap_keys: for k in dev.remap_keys:
print( print(' %2d: %-26s => %s%s' % (k.index, k.key, k.action, ' (remapped)' if k.cidStatus else ''))
' %2d: %4d %-26s => %s%s' %
(k.index, int(k.key), k.key, k.action, ' (remapped)' if k.cidStatus else '')
)
if dev.online and dev.gestures: if dev.online and dev.gestures:
print( print(
' Has %d gesture(s), %d param(s) and %d spec(s):' % ' Has %d gesture(s), %d param(s) and %d spec(s):' %