factor out consumer control from keyboard hid

This commit is contained in:
xs5871 2022-10-15 19:48:32 +00:00 committed by xs5871
parent 27f101d139
commit 470f16c97f

View File

@ -68,6 +68,10 @@ class AbstractHID:
self.report_mods = memoryview(self._evt)[1:2]
self.report_non_mods = memoryview(self._evt)[3:]
self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
self._cc_report[0] = HIDReportTypes.CONSUMER
self._cc_pending = False
self.post_init()
def __repr__(self):
@ -79,44 +83,19 @@ class AbstractHID:
def create_report(self, keys_pressed):
self.clear_all()
consumer_key = None
for key in keys_pressed:
if isinstance(key, ConsumerKey):
consumer_key = key
break
if key.code >= FIRST_KMK_INTERNAL_KEY:
continue
reporting_device = self.report_device[0]
needed_reporting_device = HIDReportTypes.KEYBOARD
if consumer_key:
needed_reporting_device = HIDReportTypes.CONSUMER
if reporting_device != needed_reporting_device:
# If we are about to change reporting devices, release
# all keys and close our proverbial tab on the existing
# device, or keys will get stuck (mostly when releasing
# media/consumer keys)
self.send()
self.report_device[0] = needed_reporting_device
if consumer_key:
self.add_key(consumer_key)
else:
for key in keys_pressed:
if key.code >= FIRST_KMK_INTERNAL_KEY:
continue
if isinstance(key, ModifierKey):
self.add_modifier(key)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
return self
if isinstance(key, ModifierKey):
self.add_modifier(key)
elif isinstance(key, ConsumerKey):
self.add_cc(key)
else:
self.add_key(key)
if key.has_modifiers:
for mod in key.has_modifiers:
self.add_modifier(mod)
def hid_send(self, evt):
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
@ -131,12 +110,18 @@ class AbstractHID:
self._prev_evt[:] = self._evt
self.hid_send(self._evt)
if self._cc_pending:
self.hid_send(self._cc_report)
self._cc_pending = False
return self
def clear_all(self):
for idx, _ in enumerate(self.report_keys):
self.report_keys[idx] = 0x00
self.remove_cc()
return self
def clear_non_modifiers(self):
@ -175,9 +160,6 @@ class AbstractHID:
where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == 0x00:
where_to_place[idx] = key.code
@ -193,15 +175,24 @@ class AbstractHID:
def remove_key(self, key):
where_to_place = self.report_non_mods
if self.report_device[0] == HIDReportTypes.CONSUMER:
where_to_place = self.report_keys
for idx, _ in enumerate(where_to_place):
if where_to_place[idx] == key.code:
where_to_place[idx] = 0x00
return self
def add_cc(self, cc):
# Add (or write over) consumer control report. There can only be one CC
# active at any time.
self._cc_report[1] = cc.code
self._cc_pending = True
def remove_cc(self):
# Remove consumer control report.
if self._cc_report[1]:
self._cc_pending = True
self._cc_report[1] = 0x00
class USBHID(AbstractHID):
REPORT_BYTES = 9