Remove NamedInts: Convert Task to enum

Refactor code related to task and task ID.

Related #2273
This commit is contained in:
MattHag 2024-11-04 23:27:50 +01:00 committed by Peter F. Patel-Schneider
parent b74e789715
commit 4c160d1723
4 changed files with 289 additions and 272 deletions

View File

@ -192,11 +192,11 @@ class ReprogrammableKey:
- flags {List[str]} -- capabilities and desired software handling of the control - flags {List[str]} -- capabilities and desired software handling of the control
""" """
def __init__(self, device: Device, index, cid, tid, flags): def __init__(self, device: Device, index, cid, task_id, flags):
self._device = device self._device = device
self.index = index self.index = index
self._cid = cid self._cid = cid
self._tid = tid self._tid = task_id
self._flags = flags self._flags = flags
@property @property
@ -209,7 +209,10 @@ class ReprogrammableKey:
while the name is the Control ID's native task. But this makes more sense while the name is the Control ID's native task. But this makes more sense
than presenting details of controls vs tasks in the interface. The same than presenting details of controls vs tasks in the interface. The same
convention applies to `mapped_to`, `remappable_to`, `remap` in `ReprogrammableKeyV4`.""" convention applies to `mapped_to`, `remappable_to`, `remap` in `ReprogrammableKeyV4`."""
task = str(special_keys.TASK[self._tid]) try:
task = str(special_keys.Task(self._tid))
except ValueError:
task = f"unknown:{self._tid:04X}"
return NamedInt(self._cid, task) return NamedInt(self._cid, task)
@property @property
@ -234,8 +237,8 @@ class ReprogrammableKeyV4(ReprogrammableKey):
- mapping_flags {List[str]} -- mapping flags set on the control - mapping_flags {List[str]} -- mapping flags set on the control
""" """
def __init__(self, device: Device, index, cid, tid, flags, pos, group, gmask): def __init__(self, device: Device, index, cid, task_id, flags, pos, group, gmask):
ReprogrammableKey.__init__(self, device, index, cid, tid, flags) ReprogrammableKey.__init__(self, device, index, cid, task_id, flags)
self.pos = pos self.pos = pos
self.group = group self.group = group
self._gmask = gmask self._gmask = gmask
@ -251,7 +254,7 @@ class ReprogrammableKeyV4(ReprogrammableKey):
if self._mapped_to is None: if self._mapped_to is None:
self._getCidReporting() self._getCidReporting()
self._device.keys._ensure_all_keys_queried() self._device.keys._ensure_all_keys_queried()
task = str(special_keys.TASK[self._device.keys.cid_to_tid[self._mapped_to]]) task = str(special_keys.Task(self._device.keys.cid_to_tid[self._mapped_to]))
return NamedInt(self._mapped_to, task) return NamedInt(self._mapped_to, task)
@property @property
@ -263,7 +266,11 @@ class ReprogrammableKeyV4(ReprogrammableKey):
for g in self.group_mask: for g in self.group_mask:
g = special_keys.CidGroup[str(g)] g = special_keys.CidGroup[str(g)]
for tgt_cid in self._device.keys.group_cids[g]: for tgt_cid in self._device.keys.group_cids[g]:
tgt_task = str(special_keys.TASK[self._device.keys.cid_to_tid[tgt_cid]]) cid = self._device.keys.cid_to_tid[tgt_cid]
try:
tgt_task = str(special_keys.Task(cid))
except ValueError:
tgt_task = f"unknown:{cid:04X}"
tgt_task = NamedInt(tgt_cid, tgt_task) tgt_task = NamedInt(tgt_cid, tgt_task)
if tgt_task != self.default_task: # don't put itself in twice if tgt_task != self.default_task: # don't put itself in twice
ret[tgt_task] = tgt_task ret[tgt_task] = tgt_task
@ -524,9 +531,9 @@ class KeysArrayV2(KeysArray):
raise IndexError(index) raise IndexError(index)
keydata = self.device.feature_request(SupportedFeature.REPROG_CONTROLS, 0x10, index) keydata = self.device.feature_request(SupportedFeature.REPROG_CONTROLS, 0x10, index)
if keydata: if keydata:
cid, tid, flags = struct.unpack("!HHB", keydata[:5]) cid, task_id, flags = struct.unpack("!HHB", keydata[:5])
self.keys[index] = ReprogrammableKey(self.device, index, cid, tid, flags) self.keys[index] = ReprogrammableKey(self.device, index, cid, task_id, flags)
self.cid_to_tid[cid] = tid self.cid_to_tid[cid] = task_id
elif logger.isEnabledFor(logging.WARNING): elif logger.isEnabledFor(logging.WARNING):
logger.warning(f"Key with index {index} was expected to exist but device doesn't report it.") logger.warning(f"Key with index {index} was expected to exist but device doesn't report it.")
@ -540,10 +547,10 @@ class KeysArrayV4(KeysArrayV2):
raise IndexError(index) raise IndexError(index)
keydata = self.device.feature_request(SupportedFeature.REPROG_CONTROLS_V4, 0x10, index) keydata = self.device.feature_request(SupportedFeature.REPROG_CONTROLS_V4, 0x10, index)
if keydata: if keydata:
cid, tid, flags1, pos, group, gmask, flags2 = struct.unpack("!HHBBBBB", keydata[:9]) cid, task_id, flags1, pos, group, gmask, flags2 = struct.unpack("!HHBBBBB", keydata[:9])
flags = flags1 | (flags2 << 8) flags = flags1 | (flags2 << 8)
self.keys[index] = ReprogrammableKeyV4(self.device, index, cid, tid, flags, pos, group, gmask) self.keys[index] = ReprogrammableKeyV4(self.device, index, cid, task_id, flags, pos, group, gmask)
self.cid_to_tid[cid] = tid self.cid_to_tid[cid] = task_id
if group != 0: # 0 = does not belong to a group if group != 0: # 0 = does not belong to a group
self.group_cids[special_keys.CidGroup(group)].append(cid) self.group_cids[special_keys.CidGroup(group)].append(cid)
elif logger.isEnabledFor(logging.WARNING): elif logger.isEnabledFor(logging.WARNING):

View File

@ -323,255 +323,263 @@ CONTROL[0x1200] = "MR" # add in MR key - this is not really a Logitech Control
CONTROL._fallback = lambda x: f"unknown:{x:04X}" CONTROL._fallback = lambda x: f"unknown:{x:04X}"
# <tasks.xml awk -F\" '/<Task /{gsub(/ /, "_", $6); printf("\t%s=0x%04X,\n", $6, $4)}'
TASK = NamedInts( class Task(IntEnum):
Volume_Up=0x0001, """
Volume_Down=0x0002, <tasks.xml awk -F\" '/<Task /{gsub(/ /, "_", $6); printf("\t%s=0x%04X,\n", $6, $4)}'
Mute=0x0003, """
VOLUME_UP = 0x0001
VOLUME_DOWN = 0x0002
MUTE = 0x0003
# Multimedia tasks: # Multimedia tasks:
Play__Pause=0x0004, PLAY_PAUSE = 0x0004
Next=0x0005, NEXT = 0x0005
Previous=0x0006, PREVIOUS = 0x0006
Stop=0x0007, STOP = 0x0007
Application_Switcher=0x0008, APPLICATION_SWITCHER = 0x0008
BurnMediaPlayer=0x0009, BURN_MEDIA_PLAYER = 0x0009
Calculator=0x000A, CALCULATOR = 0x000A
Calendar=0x000B, CALENDAR = 0x000B
Close_Application=0x000C, CLOSE_APPLICATION = 0x000C
Eject=0x000D, EJECT = 0x000D
Email=0x000E, EMAIL = 0x000E
Help=0x000F, HELP = 0x000F
OffDocument=0x0010, OFF_DOCUMENT = 0x0010
OffSpreadsheet=0x0011, OFF_SPREADSHEET = 0x0011
OffPowerpnt=0x0012, OFF_POWERPNT = 0x0012
Undo=0x0013, UNDO = 0x0013
Redo=0x0014, REDO = 0x0014
Print=0x0015, PRINT = 0x0015
Save=0x0016, SAVE = 0x0016
SmartKeySet=0x0017, SMART_KEY_SET = 0x0017
Favorites=0x0018, FAVORITES = 0x0018
GadgetsSet=0x0019, GADGETS_SET = 0x0019
HomePage=0x001A, HOME_PAGE = 0x001A
WindowsRestore=0x001B, WINDOWS_RESTORE = 0x001B
WindowsMinimize=0x001C, WINDOWS_MINIMIZE = 0x001C
Music=0x001D, # also known as MediaPlayer MUSIC = 0x001D # also known as MediaPlayer
# Both 0x001E and 0x001F are known as MediaCenterSet # Both 0x001E and 0x001F are known as MediaCenterSet
Media_Center_Logitech=0x001E, MEDIA_CENTER_LOGITECH = 0x001E
Media_Center_Microsoft=0x001F, MEDIA_CENTER_MICROSOFT = 0x001F
UserMenu=0x0020, USER_MENU = 0x0020
Messenger=0x0021, MESSENGER = 0x0021
PersonalFolders=0x0022, PERSONAL_FOLDERS = 0x0022
MyMusic=0x0023, MY_MUSIC = 0x0023
Webcam=0x0024, WEBCAM = 0x0024
PicturesFolder=0x0025, PICTURES_FOLDER = 0x0025
MyVideos=0x0026, MY_VIDEOS = 0x0026
My_Computer=0x0027, MY_COMPUTER = 0x0027
PictureAppSet=0x0028, PICTURE_APP_SET = 0x0028
Search=0x0029, # also known as AdvSmartSearch SEARCH = 0x0029 # also known as AdvSmartSearch
RecordMediaPlayer=0x002A, RECORD_MEDIA_PLAYER = 0x002A
BrowserRefresh=0x002B, BROWSER_REFRESH = 0x002B
RotateRight=0x002C, ROTATE_RIGHT = 0x002C
Search_Files=0x002D, # SearchForFiles SEARCH_FILES = 0x002D # SearchForFiles
MM_SHUFFLE=0x002E, MM_SHUFFLE = 0x002E
Sleep=0x002F, # also known as StandBySet SLEEP = 0x002F # also known as StandBySet
BrowserStop=0x0030, BROWSER_STOP = 0x0030
OneTouchSync=0x0031, ONE_TOUCH_SYNC = 0x0031
ZoomSet=0x0032, ZOOM_SET = 0x0032
ZoomBtnInSet2=0x0033, ZOOM_BTN_IN_SET_2 = 0x0033
ZoomBtnInSet=0x0034, ZOOM_BTN_IN_SET = 0x0034
ZoomBtnOutSet2=0x0035, ZOOM_BTN_OUT_SET_2 = 0x0035
ZoomBtnOutSet=0x0036, ZOOM_BTN_OUT_SET = 0x0036
ZoomBtnResetSet=0x0037, ZOOM_BTN_RESET_SET = 0x0037
Left_Click=0x0038, # LeftClick LEFT_CLICK = 0x0038 # LeftClick
Right_Click=0x0039, # RightClick RIGHT_CLICK = 0x0039 # RightClick
Mouse_Middle_Button=0x003A, # from M510v2 was MiddleMouseButton MOUSE_MIDDLE_BUTTON = 0x003A # from M510v2 was MiddleMouseButton
Back=0x003B, BACK = 0x003B
Mouse_Back_Button=0x003C, # from M510v2 was BackEx MOUSE_BACK_BUTTON = 0x003C # from M510v2 was BackEx
BrowserForward=0x003D, BROWSER_FORWARD = 0x003D
Mouse_Forward_Button=0x003E, # from M510v2 was BrowserForwardEx MOUSE_FORWARD_BUTTON = 0x003E # from M510v2 was BrowserForwardEx
Mouse_Scroll_Left_Button_=0x003F, # from M510v2 was HorzScrollLeftSet MOUSE_SCROLL_LEFT_BUTTON = 0x003F # from M510v2 was HorzScrollLeftSet
Mouse_Scroll_Right_Button=0x0040, # from M510v2 was HorzScrollRightSet MOUSE_SCROLL_RIGHT_BUTTON = 0x0040 # from M510v2 was HorzScrollRightSet
QuickSwitch=0x0041, QUICK_SWITCH = 0x0041
BatteryStatus=0x0042, BATTERY_STATUS = 0x0042
Show_Desktop=0x0043, # ShowDesktop SHOW_DESKTOP = 0x0043 # ShowDesktop
WindowsLock=0x0044, WINDOWS_LOCK = 0x0044
FileLauncher=0x0045, FILE_LAUNCHER = 0x0045
FolderLauncher=0x0046, FOLDER_LAUNCHER = 0x0046
GotoWebAddress=0x0047, GOTO_WEB_ADDRESS = 0x0047
GenericMouseButton=0x0048, GENERIC_MOUSE_BUTTON = 0x0048
KeystrokeAssignment=0x0049, KEYSTROKE_ASSIGNMENT = 0x0049
LaunchProgram=0x004A, LAUNCH_PROGRAM = 0x004A
MinMaxWindow=0x004B, MIN_MAX_WINDOW = 0x004B
VOLUMEMUTE_NoOSD=0x004C, VOLUME_MUTE_NO_OSD = 0x004C
New=0x004D, NEW = 0x004D
Copy=0x004E, COPY = 0x004E
CruiseDown=0x004F, CRUISE_DOWN = 0x004F
CruiseUp=0x0050, CRUISE_UP = 0x0050
Cut=0x0051, CUT = 0x0051
Do_Nothing=0x0052, DO_NOTHING = 0x0052
PageDown=0x0053, PAGE_DOWN = 0x0053
PageUp=0x0054, PAGE_UP = 0x0054
Paste=0x0055, PASTE = 0x0055
SearchPicture=0x0056, SEARCH_PICTURE = 0x0056
Reply=0x0057, REPLY = 0x0057
PhotoGallerySet=0x0058, PHOTO_GALLERY_SET = 0x0058
MM_REWIND=0x0059, MM_REWIND = 0x0059
MM_FASTFORWARD=0x005A, MM_FASTFORWARD = 0x005A
Send=0x005B, SEND = 0x005B
ControlPanel=0x005C, CONTROL_PANEL = 0x005C
UniversalScroll=0x005D, UNIVERSAL_SCROLL = 0x005D
AutoScroll=0x005E, AUTO_SCROLL = 0x005E
GenericButton=0x005F, GENERIC_BUTTON = 0x005F
MM_NEXT=0x0060, MM_NEXT = 0x0060
MM_PREVIOUS=0x0061, MM_PREVIOUS = 0x0061
Do_Nothing_One=0x0062, # also known as Do_Nothing DO_NOTHING_ONE = 0x0062 # also known as Do_Nothing
SnapLeft=0x0063, SNAP_LEFT = 0x0063
SnapRight=0x0064, SNAP_RIGHT = 0x0064
WinMinRestore=0x0065, WIN_MIN_RESTORE = 0x0065
WinMaxRestore=0x0066, WIN_MAX_RESTORE = 0x0066
WinStretch=0x0067, WIN_STRETCH = 0x0067
SwitchMonitorLeft=0x0068, SWITCH_MONITOR_LEFT = 0x0068
SwitchMonitorRight=0x0069, SWITCH_MONITOR_RIGHT = 0x0069
ShowPresentation=0x006A, SHOW_PRESENTATION = 0x006A
ShowMobilityCenter=0x006B, SHOW_MOBILITY_CENTER = 0x006B
HorzScrollNoRepeatSet=0x006C, HORZ_SCROLL_NO_REPEAT_SET = 0x006C
TouchBackForwardHorzScroll=0x0077, TOUCH_BACK_FORWARD_HORZ_SCROLL = 0x0077
MetroAppSwitch=0x0078, METRO_APP_SWITCH = 0x0078
MetroAppBar=0x0079, METRO_APP_BAR = 0x0079
MetroCharms=0x007A, METRO_CHARMS = 0x007A
Calculator_VKEY=0x007B, # also known as Calculator CALCULATOR_VKEY = 0x007B # also known as Calculator
MetroSearch=0x007C, METRO_SEARCH = 0x007C
MetroStartScreen=0x0080, METRO_START_SCREEN = 0x0080
MetroShare=0x007D, METRO_SHARE = 0x007D
MetroSettings=0x007E, METRO_SETTINGS = 0x007E
MetroDevices=0x007F, METRO_DEVICES = 0x007F
MetroBackLeftHorz=0x0082, METRO_BACK_LEFT_HORZ = 0x0082
MetroForwRightHorz=0x0083, METRO_FORW_RIGHT_HORZ = 0x0083
Win8_Back=0x0084, # also known as MetroCharms WIN8_BACK = 0x0084 # also known as MetroCharms
Win8_Forward=0x0085, # also known as AppSwitchBar WIN8_FORWARD = 0x0085 # also known as AppSwitchBar
Win8Charm_Appswitch_GifAnimation=0x0086, WIN8_CHARM_APPSWITCH_GIF_ANIMATION = 0x0086
Win8BackHorzLeft=0x008B, # also known as Back WIN8_BACK_HORZ_LEFT = 0x008B # also known as Back
Win8ForwardHorzRight=0x008C, # also known as BrowserForward WIN8_FORWARD_HORZ_RIGHT = 0x008C # also known as BrowserForward
MetroSearch2=0x0087, METRO_SEARCH_2 = 0x0087
MetroShare2=0x0088, METROA_SHARE_2 = 0x0088
MetroSettings2=0x008A, METRO_SETTINGS_2 = 0x008A
MetroDevices2=0x0089, METRO_DEVICES_2 = 0x0089
Win8MetroWin7Forward=0x008D, # also known as MetroStartScreen WIN8_METRO_WIN7_FORWARD = 0x008D # also known as MetroStartScreen
Win8ShowDesktopWin7Back=0x008E, # also known as ShowDesktop WIN8_SHOW_DESKTOP_WIN7_BACK = 0x008E # also known as ShowDesktop
MetroApplicationSwitch=0x0090, # also known as MetroStartScreen METRO_APPLICATION_SWITCH = 0x0090 # also known as MetroStartScreen
ShowUI=0x0092, SHOW_UI = 0x0092
# https://docs.google.com/document/d/1Dpx_nWRQAZox_zpZ8SNc9nOkSDE9svjkghOCbzopabc/edit # https://docs.google.com/document/d/1Dpx_nWRQAZox_zpZ8SNc9nOkSDE9svjkghOCbzopabc/edit
# Extract to csv. Eliminate extra linefeeds and spaces. Turn / into __ and space into _ # Extract to csv. Eliminate extra linefeeds and spaces. Turn / into __ and space into _
# awk -F, '/0x/{gsub(" \\+ ","_",$2); gsub("_-","_Down",$2); gsub("_\\+","_Up",$2); # awk -F, '/0x/{gsub(" \\+ ","_",$2); gsub("_-","_Down",$2); gsub("_\\+","_Up",$2);
# gsub("[()\"-]","",$2); gsub(" ","_",$2); printf("\t%s=0x%04X,\n", $2, $1)}' < tasks.csv > tasks.py # gsub("[()\"-]","",$2); gsub(" ","_",$2); printf("\t%s=0x%04X,\n", $2, $1)}' < tasks.csv > tasks.py
Switch_Presentation__Switch_Screen=0x0093, # on K400 Plus SWITCH_PRESENTATION_SWITCH_SCREEN = 0x0093 # on K400 Plus
Minimize_Window=0x0094, MINIMIZE_WINDOW = 0x0094
Maximize_Window=0x0095, # on K400 Plus MAXIMIZE_WINDOW = 0x0095 # on K400 Plus
MultiPlatform_App_Switch=0x0096, MULTI_PLATFORM_APP_SWITCH = 0x0096
MultiPlatform_Home=0x0097, MULTI_PLATFORM_HOME = 0x0097
MultiPlatform_Menu=0x0098, MULTI_PLATFORM_MENU = 0x0098
MultiPlatform_Back=0x0099, MULTI_PLATFORM_BACK = 0x0099
Switch_Language=0x009A, # Mac_switch_language SWITCH_LANGUAGE = 0x009A # Mac_switch_language
Screen_Capture=0x009B, # Mac_screen_Capture, on Craft Keyboard SCREEN_CAPTURE = 0x009B # Mac_screen_Capture, on Craft Keyboard
Gesture_Button=0x009C, GESTURE_BUTTON = 0x009C
Smart_Shift=0x009D, SMART_SHIFT = 0x009D
AppExpose=0x009E, APP_EXPOSE = 0x009E
Smart_Zoom=0x009F, SMART_ZOOM = 0x009F
Lookup=0x00A0, LOOKUP = 0x00A0
Microphone_on__off=0x00A1, MICROPHEON_ON_OFF = 0x00A1
Wifi_on__off=0x00A2, WIFI_ON_OFF = 0x00A2
Brightness_Down=0x00A3, BRIGHTNESS_DOWN = 0x00A3
Brightness_Up=0x00A4, BRIGHTNESS_UP = 0x00A4
Display_Out=0x00A5, DISPLAY_OUT = 0x00A5
View_Open_Apps=0x00A6, VIEW_OPEN_APPS = 0x00A6
View_All_Open_Apps=0x00A7, VIEW_ALL_OPEN_APPS = 0x00A7
AppSwitch=0x00A8, APP_SWITCH = 0x00A8
Gesture_Button_Navigation=0x00A9, # Mouse_Thumb_Button on MX Master GESTURE_BUTTON_NAVIGATION = 0x00A9 # Mouse_Thumb_Button on MX Master
Fn_inversion=0x00AA, FN_INVERSION = 0x00AA
Multiplatform_Back=0x00AB, MULTI_PLATFORM_BACK_2 = 0x00AB # Alternative
Multiplatform_Forward=0x00AC, MULTI_PLATFORM_FORWARD = 0x00AC
Multiplatform_Gesture_Button=0x00AD, MULTI_PLATFORM_Gesture_Button = 0x00AD
HostSwitch_Channel_1=0x00AE, HostSwitch_Channel_1 = 0x00AE
HostSwitch_Channel_2=0x00AF, HostSwitch_Channel_2 = 0x00AF
HostSwitch_Channel_3=0x00B0, HostSwitch_Channel_3 = 0x00B0
Multiplatform_Search=0x00B1, MULTI_PLATFORM_SEARCH = 0x00B1
Multiplatform_Home__Mission_Control=0x00B2, MULTI_PLATFORM_HOME_MISSION_CONTROL = 0x00B2
Multiplatform_Menu__Launchpad=0x00B3, MULTI_PLATFORM_MENU_LAUNCHPAD = 0x00B3
Virtual_Gesture_Button=0x00B4, VIRTUAL_GESTURE_BUTTON = 0x00B4
Cursor=0x00B5, CURSOR = 0x00B5
Keyboard_Right_Arrow=0x00B6, KEYBOARD_RIGHT_ARROW = 0x00B6
SW_Custom_Highlight=0x00B7, SW_CUSTOM_HIGHLIGHT = 0x00B7
Keyboard_Left_Arrow=0x00B8, KEYBOARD_LEFT_ARROW = 0x00B8
TBD=0x00B9, TBD = 0x00B9
Multiplatform_Language_Switch=0x00BA, MULTI_PLATFORM_Language_Switch = 0x00BA
SW_Custom_Highlight_2=0x00BB, SW_CUSTOM_HIGHLIGHT_2 = 0x00BB
Fast_Forward=0x00BC, FAST_FORWARD = 0x00BC
Fast_Backward=0x00BD, FAST_BACKWARD = 0x00BD
Switch_Highlighting=0x00BE, SWITCH_HIGHLIGHTING = 0x00BE
Mission_Control__Task_View=0x00BF, # Switch_Workspace on Craft Keyboard MISSION_CONTROL_TASK_VIEW = 0x00BF # Switch_Workspace on Craft Keyboard
Dashboard_Launchpad__Action_Center=0x00C0, # Application_Launcher on Craft Keyboard DASHBOARD_LAUNCHPAD_ACTION_CENTER = 0x00C0 # Application_Launcher on Craft
Backlight_Down=0x00C1, # Backlight_Down_FW_internal_function # Keyboard
Backlight_Up=0x00C2, # Backlight_Up_FW_internal_function BACKLIGHT_DOWN = 0x00C1 # Backlight_Down_FW_internal_function
Right_Click__App_Contextual_Menu=0x00C3, # Context_Menu on Craft Keyboard BACKLIGHT_UP = 0x00C2 # Backlight_Up_FW_internal_function
DPI_Change=0x00C4, RIGHT_CLICK_APP_CONTEXT_MENU = 0x00C3 # Context_Menu on Craft Keyboard
New_Tab=0x00C5, DPI_Change = 0x00C4
F2=0x00C6, NEW_TAB = 0x00C5
F3=0x00C7, F2 = 0x00C6
F4=0x00C8, F3 = 0x00C7
F5=0x00C9, F4 = 0x00C8
F6=0x00CA, F5 = 0x00C9
F7=0x00CB, F6 = 0x00CA
F8=0x00CC, F7 = 0x00CB
F1=0x00CD, F8 = 0x00CC
Laser_Button=0x00CE, F1 = 0x00CD
Laser_Button_Long_Press=0x00CF, LASER_BUTTON = 0x00CE
Start_Presentation=0x00D0, LASER_BUTTON_LONG_PRESS = 0x00CF
Blank_Screen=0x00D1, START_PRESENTATION = 0x00D0
DPI_Switch=0x00D2, # AdjustDPI on MX Vertical BLANK_SCREEN = 0x00D1
Home__Show_Desktop=0x00D3, DPI_Switch = 0x00D2 # AdjustDPI on MX Vertical
App_Switch__Dashboard=0x00D4, HOME_SHOW_DESKTOP = 0x00D3
App_Switch=0x00D5, APP_SWITCH_DASHBOARD = 0x00D4
Fn_Inversion=0x00D6, APP_SWITCH_2 = 0x00D5 # Alternative
LeftAndRightClick=0x00D7, FN_INVERSION_2 = 0x00D6 # Alternative
Voice_Dictation=0x00D8, LEFT_AND_RIGHT_CLICK = 0x00D7
Emoji_Smiling_Face_With_Heart_Shaped_Eyes=0x00D9, VOICE_DICTATION = 0x00D8
Emoji_Loudly_Crying_Face=0x00DA, EMOJI_SMILING_FACE_WITH_HEART_SHAPED_EYES = 0x00D9
Emoji_Smiley=0x00DB, EMOJI_LOUDLY_CRYING_FACE = 0x00DA
Emoji_Smiley_With_Tears=0x00DC, EMOJI_SMILEY = 0x00DB
Open_Emoji_Panel=0x00DD, EMOJI_SMILE_WITH_TEARS = 0x00DC
Multiplatform_App_Switch__Launchpad=0x00DE, OPEN_EMOJI_PANEL = 0x00DD
Snipping_Tool=0x00DF, MULTI_PLATFORM_APP_SWITCH_LAUNCHPAD = 0x00DE
Grave_Accent=0x00E0, SNIPPING_TOOL = 0x00DF
Standard_Tab_Key=0x00E1, GRAVE_ACCENT = 0x00E0
Caps_Lock=0x00E2, STANDARD_TAB_KEY = 0x00E1
Left_Shift=0x00E3, CAPS_LOCK = 0x00E2
Left_Control=0x00E4, LEFT_SHIFT = 0x00E3
Left_Option__Start=0x00E5, LEFT_CONTROL = 0x00E4
Left_Command__Alt=0x00E6, LEFT_OPTION_START = 0x00E5
Right_Command__Alt=0x00E7, LEFT_COMMAND_ALT = 0x00E6
Right_Option__Start=0x00E8, RIGHT_COMMAND_ALT = 0x00E7
Right_Control=0x00E9, RIGHT_OPTION_START = 0x00E8
Right_Shift=0x0EA, RIGHT_CONTROL = 0x00E9
Insert=0x00EB, RIGHT_SHIFT = 0x0EA
Delete=0x00EC, INSERT = 0x00EB
Home=0x00ED, DELETE = 0x00EC
End=0x00EE, HOME = 0x00ED
Page_Up=0x00EF, END = 0x00EE
Page_Down=0x00F0, PAGE_UP_2 = 0x00EF # Alternative
Mute_Microphone=0x00F1, PAGE_DOWN_2 = 0x00F0 # Alternative
Do_Not_Disturb=0x00F2, MUTE_MICROPHONE = 0x00F1
Backslash=0x00F3, DO_NOT_DISTURB = 0x00F2
Refresh=0x00F4, BACKSLASH = 0x00F3
Close_Tab=0x00F5, REFRESH = 0x00F4
Lang_Switch=0x00F6, CLOSE_TAB = 0x00F5
Standard_Alphabetical_Key=0x00F7, LANG_SWITCH = 0x00F6
Right_Option__Start__2=0x00F8, STANDARD_ALPHABETICAL_KEY = 0x00F7
Left_Option=0x00F9, RRIGH_OPTION_START_2 = 0x00F8
Right_Option=0x00FA, LEFT_OPTION = 0x00F9
Left_Cmd=0x00FB, RIGHT_OPTION = 0x00FA
Right_Cmd=0x00FC, LEFT_CMD = 0x00FB
) RIGHT_CMD = 0x00FC
TASK._fallback = lambda x: f"unknown:{x:04X}"
def __str__(self):
return self.name.replace("_", " ").title()
# Capabilities and desired software handling for a control # Capabilities and desired software handling for a control
# Ref: https://drive.google.com/file/d/10imcbmoxTJ1N510poGdsviEhoFfB_Ua4/view # Ref: https://drive.google.com/file/d/10imcbmoxTJ1N510poGdsviEhoFfB_Ua4/view
# We treat bytes 4 and 8 of `getCidInfo` as a single bitfield # We treat bytes 4 and 8 of `getCidInfo` as a single bitfield

View File

@ -215,7 +215,7 @@ def test_device_receiver(number, pairing_info, responses, handle, _name, codenam
@pytest.mark.parametrize( @pytest.mark.parametrize(
"number, info, responses, handle, unitId, modelId, tid, kind, firmware, serial, id, psl, rate", "number, info, responses, handle, unitId, modelId, task_id, kind, firmware, serial, id, psl, rate",
zip( zip(
range(1, 7), range(1, 7),
[pi_CCCC, pi_2011, pi_4066, pi_1007, pi_407B, pi_DDDD], [pi_CCCC, pi_2011, pi_4066, pi_1007, pi_407B, pi_DDDD],
@ -239,7 +239,7 @@ def test_device_receiver(number, pairing_info, responses, handle, _name, codenam
["1ms", "2ms", "4ms", "8ms", "1ms", "9ms"], # polling rate ["1ms", "2ms", "4ms", "8ms", "1ms", "9ms"], # polling rate
), ),
) )
def test_device_ids(number, info, responses, handle, unitId, modelId, tid, kind, firmware, serial, id, psl, rate): def test_device_ids(number, info, responses, handle, unitId, modelId, task_id, kind, firmware, serial, id, psl, rate):
low_level = LowLevelInterfaceFake(responses) low_level = LowLevelInterfaceFake(responses)
low_level.request = partial(fake_hidpp.request, fake_hidpp.replace_number(responses, number)) low_level.request = partial(fake_hidpp.request, fake_hidpp.replace_number(responses, number))
low_level.ping = partial(fake_hidpp.ping, fake_hidpp.replace_number(responses, number)) low_level.ping = partial(fake_hidpp.ping, fake_hidpp.replace_number(responses, number))
@ -248,7 +248,7 @@ def test_device_ids(number, info, responses, handle, unitId, modelId, tid, kind,
assert test_device.unitId == unitId assert test_device.unitId == unitId
assert test_device.modelId == modelId assert test_device.modelId == modelId
assert test_device.tid_map == tid assert test_device.tid_map == task_id
assert test_device.kind == kind assert test_device.kind == kind
assert test_device.firmware == firmware or len(test_device.firmware) > 0 and firmware is True assert test_device.firmware == firmware or len(test_device.firmware) > 0 and firmware is True
assert test_device.id == id assert test_device.id == id

View File

@ -154,19 +154,19 @@ def test_FeaturesArray_getitem(device, expected0, expected1, expected2, expected
@pytest.mark.parametrize( @pytest.mark.parametrize(
"device, index, cid, tid, flags, default_task, flag_names", "device, index, cid, task_id, flags, default_task, flag_names",
[ [
(device_standard, 2, 1, 1, 0x30, "Volume Up", ["reprogrammable", "divertable"]), (device_standard, 2, 1, 1, 0x30, "Volume Up", ["reprogrammable", "divertable"]),
(device_standard, 1, 2, 2, 0x20, "Volume Down", ["divertable"]), (device_standard, 1, 2, 2, 0x20, "Volume Down", ["divertable"]),
], ],
) )
def test_ReprogrammableKey_key(device, index, cid, tid, flags, default_task, flag_names): def test_reprogrammable_key_key(device, index, cid, task_id, flags, default_task, flag_names):
key = hidpp20.ReprogrammableKey(device, index, cid, tid, flags) key = hidpp20.ReprogrammableKey(device, index, cid, task_id, flags)
assert key._device == device assert key._device == device
assert key.index == index assert key.index == index
assert key._cid == cid assert key._cid == cid
assert key._tid == tid assert key._tid == task_id
assert key._flags == flags assert key._flags == flags
assert key.key == special_keys.CONTROL[cid] assert key.key == special_keys.CONTROL[cid]
assert key.default_task == common.NamedInt(cid, default_task) assert key.default_task == common.NamedInt(cid, default_task)
@ -174,7 +174,7 @@ def test_ReprogrammableKey_key(device, index, cid, tid, flags, default_task, fla
@pytest.mark.parametrize( @pytest.mark.parametrize(
"device, index, cid, tid, flags, pos, group, gmask, default_task, flag_names, group_names", "device, index, cid, task_id, flags, pos, group, gmask, default_task, flag_names, group_names",
[ [
(device_standard, 1, 0x51, 0x39, 0x60, 0, 1, 1, "Right Click", ["divertable", "persistently divertable"], ["g1"]), (device_standard, 1, 0x51, 0x39, 0x60, 0, 1, 1, "Right Click", ["divertable", "persistently divertable"], ["g1"]),
(device_standard, 2, 0x52, 0x3A, 0x11, 1, 2, 3, "Mouse Middle Button", ["mse", "reprogrammable"], ["g1", "g2"]), (device_standard, 2, 0x52, 0x3A, 0x11, 1, 2, 3, "Mouse Middle Button", ["mse", "reprogrammable"], ["g1", "g2"]),
@ -193,13 +193,15 @@ def test_ReprogrammableKey_key(device, index, cid, tid, flags, default_task, fla
), ),
], ],
) )
def test_reprogrammable_key_v4_key(device, index, cid, tid, flags, pos, group, gmask, default_task, flag_names, group_names): def test_reprogrammable_key_v4_key(
key = hidpp20.ReprogrammableKeyV4(device, index, cid, tid, flags, pos, group, gmask) device, index, cid, task_id, flags, pos, group, gmask, default_task, flag_names, group_names
):
key = hidpp20.ReprogrammableKeyV4(device, index, cid, task_id, flags, pos, group, gmask)
assert key._device == device assert key._device == device
assert key.index == index assert key.index == index
assert key._cid == cid assert key._cid == cid
assert key._tid == tid assert key._tid == task_id
assert key._flags == flags assert key._flags == flags
assert key.pos == pos assert key.pos == pos
assert key.group == group assert key.group == group
@ -220,7 +222,7 @@ def test_reprogrammable_key_v4_key(device, index, cid, tid, flags, pos, group, g
], ],
) )
# these fields need access all the key data, so start by setting up a device and its key data # these fields need access all the key data, so start by setting up a device and its key data
def test_ReprogrammableKeyV4_query(responses, index, mapped_to, remappable_to, mapping_flags): def test_reprogrammable_key_v4_query(responses, index, mapped_to, remappable_to, mapping_flags):
device = fake_hidpp.Device( device = fake_hidpp.Device(
"KEY", responses=responses, feature=hidpp20_constants.SupportedFeature.REPROG_CONTROLS_V4, offset=5 "KEY", responses=responses, feature=hidpp20_constants.SupportedFeature.REPROG_CONTROLS_V4, offset=5
) )
@ -360,14 +362,14 @@ def test_KeysArrayV4_query_key(device, index, top, cid):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"device, count, index, cid, tid, flags, pos, group, gmask", "device, count, index, cid, task_id, flags, pos, group, gmask",
[ [
(device_standard, 4, 0, 0x0011, 0x0012, 0xCDAB, 1, 2, 3), (device_standard, 4, 0, 0x0011, 0x0012, 0xCDAB, 1, 2, 3),
(device_standard, 6, 1, 0x0111, 0x0022, 0xCDAB, 1, 2, 3), (device_standard, 6, 1, 0x0111, 0x0022, 0xCDAB, 1, 2, 3),
(device_standard, 8, 3, 0x0311, 0x0032, 0xCDAB, 1, 2, 4), (device_standard, 8, 3, 0x0311, 0x0032, 0xCDAB, 1, 2, 4),
], ],
) )
def test_KeysArrayV4__getitem(device, count, index, cid, tid, flags, pos, group, gmask): def test_KeysArrayV4__getitem(device, count, index, cid, task_id, flags, pos, group, gmask):
keysarray = hidpp20.KeysArrayV4(device, count) keysarray = hidpp20.KeysArrayV4(device, count)
result = keysarray[index] result = keysarray[index]
@ -375,7 +377,7 @@ def test_KeysArrayV4__getitem(device, count, index, cid, tid, flags, pos, group,
assert result._device == device assert result._device == device
assert result.index == index assert result.index == index
assert result._cid == cid assert result._cid == cid
assert result._tid == tid assert result._tid == task_id
assert result._flags == flags assert result._flags == flags
assert result.pos == pos assert result.pos == pos
assert result.group == group assert result.group == group
@ -421,7 +423,7 @@ device_key = fake_hidpp.Device(
(special_keys.CONTROL.Virtual_Gesture_Button, 7, common.NamedInt(0x51, "Right Click"), None), (special_keys.CONTROL.Virtual_Gesture_Button, 7, common.NamedInt(0x51, "Right Click"), None),
], ],
) )
def test_KeysArrayV4_key(key, expected_index, expected_mapped_to, expected_remappable_to): def test_keys_array_v4_key(key, expected_index, expected_mapped_to, expected_remappable_to):
device_key._keys = _hidpp20.get_keys(device_key) device_key._keys = _hidpp20.get_keys(device_key)
device_key._keys._ensure_all_keys_queried() device_key._keys._ensure_all_keys_queried()