char_to_key_sequence['\r'] = (36, 0) char_to_key_sequence['\t'] = (48, 0) return char_to_key_sequence, key_sequence_to_char, modifier_masks if __name__ == '__main__': layout = KeyboardLayout(False) print(KEY_CODE_VISUALIZATION) print() print(layout.format_modifier_header()) for keycode in range(127): print(layout.format_keycode_keys(keycode)) print() unmapped_characters = [] for char, keyname in sorted(CHAR_TO_KEYNAME.items()): sequence = [] for code, mod in layout.char_to_key_sequence(char): if code is not None: sequence.append( (code, '{}{}'.format( layout._modifier_string(mod), layout.key_code_to_char(code, 0) )) ) else: unmapped_characters.append(char) if sequence: print('Name:\t\t{}\nCharacter:\t{}\nSequence:\t‘{}’\nBase codes:\t‘{}’\n'.format( keyname, char, '’, ‘'.join(combo[1] for combo in sequence), '’, ‘'.join(str(combo[0]) for combo in sequence)
char_to_key_sequence[u'\r'] = (36, 0) char_to_key_sequence[u'\t'] = (48, 0) return char_to_key_sequence, key_sequence_to_char, modifier_masks if __name__ == '__main__': layout = KeyboardLayout(False) print(KEY_CODE_VISUALIZATION) print() print(layout.format_modifier_header()) for keycode in range(127): print(layout.format_keycode_keys(keycode)) print() unmapped_characters = [] for char, keyname in sorted(CHAR_TO_KEYNAME.items()): sequence = [] for code, mod in layout.char_to_key_sequence(char): if code is not None: sequence.append( (code, u'{}{}'.format(layout._modifier_string(mod), layout.key_code_to_char(code, 0)))) else: unmapped_characters.append(char) if sequence: print( u'Name:\t\t{}\nCharacter:\t{}\nSequence:\t‘{}’\nBase codes:\t‘{}’\n' .format(keyname, char, u'’, ‘'.join(combo[1] for combo in sequence), u'’, ‘'.join(str(combo[0]) for combo in sequence))) print(u'No mapping on this layout for characters: ‘{}’'.format(
def __init__(self, layout_id=None, debug=False): if layout_id is None: layout_id = KeyboardLayout.current_layout_id() self.layout_id = layout_id # Find virtual key code for each scan code (if any). sc_to_vk = {} vk_to_sc = {} for sc in range(0x01, 0x7f + 1): vk = MapVirtualKeyEx(sc, 3, layout_id) if vk != 0: sc_to_vk[sc] = vk vk_to_sc[vk] = sc state = (wintypes.BYTE * 256)() strbuf = ctypes.create_unicode_buffer(8) def fill_state(ss): for mod_state, mod_vk in ( (SHIFT_STATE.SHIFT, VK.SHIFT), (SHIFT_STATE.CTRL, VK.CONTROL), (SHIFT_STATE.MENU, VK.MENU), ): state[mod_vk] = 0x80 if (ss & mod_state) != 0 else 0 def to_unichr(vk, sc, ss): fill_state(ss) rc = ToUnicodeEx(vk, sc, state, strbuf, len(strbuf), 0, layout_id) if rc > 0: dead_key = False char = ctypes.wstring_at(strbuf.value, rc) elif rc < 0: # Dead key, flush state. dead_key = True fill_state(0) rc = ToUnicodeEx(VK.SPACE, vk_to_sc[VK.SPACE], state, strbuf, len(strbuf), 0, layout_id) char = ctypes.wstring_at(strbuf.value, rc) if rc > 0 else '' else: dead_key = False char = '' return char, dead_key def sort_vk_ss_list(vk_ss_list): # Prefer lower modifiers combo. return sorted(vk_ss_list, key=lambda vk_ss: popcount_8(vk_ss[1])) char_to_vk_ss = defaultdict(list) keyname_to_vk = defaultdict(list) for sc, vk in sorted(sc_to_vk.items()): for ss in SHIFT_STATE: if ss in (SHIFT_STATE.MENU, SHIFT_STATE.SHIFT_MENU): # Alt and Shift+Alt don't work, so skip them. continue char, dead_key = to_unichr(vk, sc, ss) if debug and char: print('%s%s -> %s [%r] %s' % ( shift_state_str(ss), vk_to_str(vk), char, char, '[dead key]' if dead_key else '', )) kn = None if char: kn = CHAR_TO_KEYNAME.get(char) if dead_key: kn = kn and DEAD_KEYNAME.get(kn, 'dead_' + kn) else: char_to_vk_ss[char].append((vk, ss)) if kn: keyname_to_vk[kn].append((vk, ss)) self.char_to_vk_ss = { char: sort_vk_ss_list(vk_ss_list)[0] for char, vk_ss_list in char_to_vk_ss.items() } self.char_to_vk_ss['\n'] = self.char_to_vk_ss['\r'] self.keyname_to_vk = { kn: vk for vk, kn in VK_TO_KEYNAME.items() } self.keyname_to_vk.update({ 'next' : VK.NEXT, 'prior' : VK.PRIOR, 'kp_delete' : VK.DELETE, 'kp_enter' : VK.RETURN, 'break' : VK.CANCEL, }) self.keyname_to_vk.update({ kn: sort_vk_ss_list(vk_ss_list)[0][0] for kn, vk_ss_list in keyname_to_vk.items() }) add_modifiers_aliases(self.keyname_to_vk) self.ss_to_vks = {} for ss in SHIFT_STATE: vk_list = [] for mod_state, mod_vk in ( (SHIFT_STATE.SHIFT, VK.SHIFT), (SHIFT_STATE.CTRL, VK.CONTROL), (SHIFT_STATE.MENU, VK.MENU), ): if (ss & mod_state) != 0: vk_list.append(mod_vk) self.ss_to_vks[ss] = tuple(vk_list)
vk_list.append(mod_vk) self.ss_to_vks[ss] = tuple(vk_list) @staticmethod def current_layout_id(): pid = GetWindowThreadProcessId(windll.user32.GetForegroundWindow(), 0) return GetKeyboardLayout(pid) # }}} if __name__ == '__main__': sys.stdout = codecs.getwriter('utf8')(sys.stdout) layout = KeyboardLayout(debug=True) print('character to virtual key + shift state [%u]' % len(layout.char_to_vk_ss)) for char, combo in sorted(layout.char_to_vk_ss.items()): vk, ss = combo print('%s [%r:%s] -> %s%s' % (char, char, CHAR_TO_KEYNAME.get(char, '?'), shift_state_str(ss), vk_to_str(vk))) print() print('keyname to virtual key [%u]' % len(layout.keyname_to_vk)) for kn, vk in sorted(layout.keyname_to_vk.items()): print('%s -> %s' % (kn, vk_to_str(vk))) print() print('modifiers combo [%u]' % len(layout.ss_to_vks)) for ss, vk_list in sorted(layout.ss_to_vks.items()): print('%s -> %s' % (shift_state_str(ss), '+'.join(vk_to_str(vk) for vk in vk_list))) # vim: foldmethod=marker
self.ss_to_vks[ss] = tuple(vk_list) @staticmethod def current_layout_id(): pid = GetWindowThreadProcessId(windll.user32.GetForegroundWindow(), 0) return GetKeyboardLayout(pid) # }}} if __name__ == '__main__': sys.stdout = codecs.getwriter('utf8')(sys.stdout) layout = KeyboardLayout(debug=True) print('character to virtual key + shift state [%u]' % len(layout.char_to_vk_ss)) for char, combo in sorted(layout.char_to_vk_ss.items()): vk, ss = combo print('%s [%r:%s] -> %s%s' % (char, char, CHAR_TO_KEYNAME.get( char, '?'), shift_state_str(ss), vk_to_str(vk))) print() print('keyname to virtual key [%u]' % len(layout.keyname_to_vk)) for kn, vk in sorted(layout.keyname_to_vk.items()): print('%s -> %s' % (kn, vk_to_str(vk))) print() print('modifiers combo [%u]' % len(layout.ss_to_vks)) for ss, vk_list in sorted(layout.ss_to_vks.items()): print('%s -> %s' % (shift_state_str(ss), '+'.join(vk_to_str(vk) for vk in vk_list))) # vim: foldmethod=marker
if (ss & mod_state) != 0: vk_list.append(mod_vk) self.ss_to_vks[ss] = tuple(vk_list) @staticmethod def current_layout_id(): pid = GetWindowThreadProcessId(win32gui.GetForegroundWindow(), 0) return GetKeyboardLayout(pid) # }}} if __name__ == "__main__": sys.stdout = codecs.getwriter("utf8")(sys.stdout) layout = KeyboardLayout(debug=True) print("character to virtual key + shift state [%u]" % len(layout.char_to_vk_ss)) for char, combo in sorted(layout.char_to_vk_ss.items()): vk, ss = combo print("%s [%r:%s] -> %s%s" % (char, char, CHAR_TO_KEYNAME.get(char, "?"), shift_state_str(ss), vk_to_str(vk))) print() print("keyname to virtual key [%u]" % len(layout.keyname_to_vk)) for kn, vk in sorted(layout.keyname_to_vk.items()): print("%s -> %s" % (kn, vk_to_str(vk))) print() print("modifiers combo [%u]" % len(layout.ss_to_vks)) for ss, vk_list in sorted(layout.ss_to_vks.items()): print("%s -> %s" % (shift_state_str(ss), "+".join(vk_to_str(vk) for vk in vk_list))) # vim: foldmethod=marker