From 6a2262a7f9bf2ab16ecfdfc52e548ef010c76e00 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sat, 17 Oct 2020 10:27:36 +0200 Subject: winkbd: Improve rendering Create self-containted, minimal, but still human-readable C file with all typedefs. Gets rid of the copied header file and all of its weird ifdef logic. Simplifies virtual scancode to virtual key mapping. --- lulua/render.py | 247 +++++--------------------------------------------------- 1 file changed, 21 insertions(+), 226 deletions(-) (limited to 'lulua/render.py') diff --git a/lulua/render.py b/lulua/render.py index 78e2b17..b8514f0 100644 --- a/lulua/render.py +++ b/lulua/render.py @@ -32,6 +32,7 @@ from .layout import LITTLE, RING, MIDDLE, INDEX, THUMB, GenericLayout, defaultLa from .writer import Writer from .keyboard import defaultKeyboards, LetterButton from .util import first, displayText +from .winkbd import qwertyScancodeToVk, VirtualKey, WChar, makeDriverSources RendererSettings = namedtuple ('RendererSetting', ['buttonMargin', 'middleGap', 'buttonWidth', 'rounded', 'shadowOffset', 'markerStroke']) @@ -474,244 +475,38 @@ def renderWinKbd (args): resPath = pkg_resources.resource_filename (__package__, 'data/winkbd') with open (args.output, 'w') as fd: - lines = [] - lines.append (f'/* This header was auto-generated by {__package__}. It is included by {resPath}/keyboard.h. Do not modify. */') - lines.append ('') - - # copied from kbdneo2.c as well - # XXX: modifier keys are fixed for now - # maps virtual keys (first value) to shift bitfield value (second value) - lines.append ('#define MODIFIER_BITS\\') - lines.append (""" { VK_SHIFT , KBDSHIFT }, \\ - { VK_CONTROL , KBDCTRL }, \\ - { VK_MENU , KBDALT }, \\ - { VK_OEM_8 , KBDKANA }, \\ - { VK_OEM_102 , 16 },""") - - # copied from kbdneo2.c - # maps a shift bitfield value (array index) to a layer number in - # virtual key translation (VK_TO_WCHARS, array value) - lines.append ('#define CHAR_MODIFIERS_MASK 24') - lines.append ('#define CHAR_MODIFIERS\\') - lines.append ('\t{ 0, 1, 6, 7, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, 3, 8, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, 2, 4, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, SHFT_INVALID, 5, }') - - # this is the standard layout from windows’ kbd.h (for KBD_TYPE == 4) - scancodeToVk = { - 'T01': 'ESCAPE', - 'T02': '1', - 'T03': '2', - 'T04': '3', - 'T05': '4', - 'T06': '5', - 'T07': '6', - 'T08': '7', - 'T09': '8', - 'T0A': '9', - 'T0B': '0', - 'T0C': 'OEM_MINUS', - 'T0D': 'OEM_PLUS', - 'T0E': 'BACK', - 'T0F': 'TAB', - 'T10': 'Q', - 'T11': 'W', - 'T12': 'E', - 'T13': 'R', - 'T14': 'T', - 'T15': 'Y', - 'T16': 'U', - 'T17': 'I', - 'T18': 'O', - 'T19': 'P', - 'T1A': 'OEM_4', - 'T1B': 'OEM_6', - 'T1C': 'RETURN', - 'T1D': 'LCONTROL', - 'T1E': 'A', - 'T1F': 'S', - 'T20': 'D', - 'T21': 'F', - 'T22': 'G', - 'T23': 'H', - 'T24': 'J', - 'T25': 'K', - 'T26': 'L', - 'T27': 'OEM_1', - 'T28': 'OEM_7', - 'T29': 'OEM_3', - 'T2A': 'LSHIFT', - 'T2B': 'OEM_5', - 'T2C': 'Z', - 'T2D': 'X', - 'T2E': 'C', - 'T2F': 'V', - 'T30': 'B', - 'T31': 'N', - 'T32': 'M', - 'T33': 'OEM_COMMA', - 'T34': 'OEM_PERIOD', - 'T35': 'OEM_2', - 'T36': 'RSHIFT', - 'T37': 'MULTIPLY', - 'T38': 'LMENU', - 'T39': 'SPACE', - 'T3A': 'CAPITAL', - 'T3B': 'F1', - 'T3C': 'F2', - 'T3D': 'F3', - 'T3E': 'F4', - 'T3F': 'F5', - 'T40': 'F6', - 'T41': 'F7', - 'T42': 'F8', - 'T43': 'F9', - 'T44': 'F10', - 'T45': 'NUMLOCK', - 'T46': 'SCROLL', - 'T47': 'HOME', - 'T48': 'UP', - 'T49': 'PRIOR', - 'T4A': 'SUBTRACT', - 'T4B': 'LEFT', - 'T4C': 'CLEAR', - 'T4D': 'RIGHT', - 'T4E': 'ADD', - 'T4F': 'END', - 'T50': 'DOWN', - 'T51': 'NEXT', - 'T52': 'INSERT', - 'T53': 'DELETE', - 'T54': 'SNAPSHOT', - 'T56': 'OEM_102', - 'T57': 'F11', - 'T58': 'F12', - 'T59': 'CLEAR', - 'T5A': 'OEM_WSCTRL', - 'T5B': 'OEM_FINISH', - 'T5C': 'OEM_JUMP', - 'T5D': 'EREOF', - 'T5E': 'OEM_BACKTAB', - 'T5F': 'OEM_AUTO', - 'T62': 'ZOOM', - 'T63': 'HELP', - 'T64': 'F13', - 'T65': 'F14', - 'T66': 'F15', - 'T67': 'F16', - 'T68': 'F17', - 'T69': 'F18', - 'T6A': 'F19', - 'T6B': 'F20', - 'T6C': 'F21', - 'T6D': 'F22', - 'T6E': 'F23', - 'T6F': 'OEM_PA3', - 'T71': 'OEM_RESET', - 'T73': 'ABNT_C1', - 'T76': 'F24', - 'T7B': 'OEM_PA1', - 'T7C': 'TAB', - 'T7E': 'ABNT_C2', - 'T7F': 'OEM_PA2', - - 'X10': 'MEDIA_PREV_TRACK', - 'X19': 'MEDIA_NEXT_TRACK', - 'X1C': 'RETURN', - 'X1D': 'RCONTROL', - 'X20': 'VOLUME_MUTE', - 'X21': 'LAUNCH_APP2', - 'X22': 'MEDIA_PLAY_PAUSE', - 'X24': 'MEDIA_STOP', - 'X2E': 'VOLUME_DOWN', - 'X30': 'VOLUME_UP', - 'X32': 'BROWSER_HOME', - 'X35': 'DIVIDE', - 'X37': 'SNAPSHOT', - 'X38': 'RMENU', - 'X46': 'CANCEL', - 'X47': 'HOME', - 'X48': 'UP', - 'X49': 'PRIOR', - 'X4B': 'LEFT', - 'X4D': 'RIGHT', - 'X4F': 'END', - 'X50': 'DOWN', - 'X51': 'NEXT', - 'X52': 'INSERT', - 'X53': 'DELETE', - 'X5B': 'LWIN', - 'X5C': 'RWIN', - 'X5D': 'APPS', - 'X5E': 'POWER', - 'X5F': 'SLEEP', - 'X65': 'BROWSER_SEARCH', - 'X66': 'BROWSER_FAVORITES', - 'X67': 'BROWSER_REFRESH', - 'X68': 'BROWSER_STOP', - 'X69': 'BROWSER_FORWARD', - 'X6A': 'BROWSER_BACK', - 'X6B': 'LAUNCH_APP1', - 'X6C': 'LAUNCH_MAIL', - 'X6D': 'LAUNCH_MEDIA_SELECT', - } - # modifications copied from kbdneo2.c - # maps modifier keys to oem values used above. + fd.write (f'/* This header was auto-generated by {__package__}. Do not modify directly. */\n\n') + + scancodeToVk = dict (qwertyScancodeToVk) + # Updates for 3rd and 4th layer modifier keys scancodeToVk.update ({ # mod 3 - 'T2B': 'OEM_102', - 'T3A': 'OEM_102', + (0x2B, ): (VirtualKey.OEM_102, ), + (0x3A, ): (VirtualKey.OEM_102, ), # mod 4 - 'X38': 'OEM_8', - 'T56': 'OEM_8', + (0x56, ): (VirtualKey.OEM_8, ), + (0xe0, 0x38): (VirtualKey.OEM_8, ), }) - for k, v in scancodeToVk.items (): - lines.append (f'#undef {k}') - if len (v) == 1: - # character value if not symbolic - lines.append (f'#define {k} \'{v}\'') - else: - lines.append (f'#define {k} _EQ({v})') - lines.append ('') - lines.append ('#define VK_TO_WCH6 \\') + # translate keyboard buttons to text + def toWindows (s): + # convert to windows-convention + if s == '\n': + s = '\r' + return s + wcharMap = [] for btn in unique (keyboard.keys (), key=attrgetter ('windowsScancode')): - def toUnicode (s): - if s is None: - return 'WCH_NONE' - elif len (s) != 1: - logging.error (f'only single-character strings are supported, ignoring {s}') - return 'WCH_NONE' - elif s == '\n': - # convert to windows-convention - s = '\r' - return f'0x{ord (s):x} /*{repr (s)}*/' - text = list (layout.getButtonText (btn)) - assert len (text) < 7, "supporting six layers only right now" # skip unused keys - if sum (map (lambda x: 1 if x is not None else 0, text)) == 0: + if len (list (filter (lambda x: x is not None, text))) == 0: continue - # fixed-length array, need padding - mappedText = [toUnicode (s) for s in text] - while len (mappedText) < 6: - mappedText.append ('WCH_NONE') + mappedText = [toWindows (s) for s in text] + vk = next (filter (lambda x: isinstance (x, VirtualKey), scancodeToVk[btn.windowsScancode])) + wcharMap.append ((vk, 0, mappedText)) - vk = scancodeToVk[btn.windowsScancode] - if len (vk) == 1: - # character value - vk = f"'{vk}'" - else: - # symbolic value - vk = f'VK_{vk}' - mappingStr = ', '.join (mappedText) - lines.append (f'\t{{ {vk}, 0, {mappingStr} }}, \\') - # NUL-termination entry is already present in keyboard.c - lines.append ('\n') - - fd.write ('\n'.join (lines)) - logging.info ('refer to README.rst on how to build a windows driver. ' - f'Template files are located in {resPath}') + fd.write (makeDriverSources (scancodeToVk, wcharMap)) def yamlload (s): try: -- cgit v1.2.3