diff --git a/input-read b/input-read index 85389c6..060b09d 100755 --- a/input-read +++ b/input-read @@ -94,6 +94,9 @@ else: if args.keymap: from uinputmapper.keymapper import parse_keymap runtime_keymaps, active_keymap_index, revert_keymap_index, active_keymap, revert_default_code, switch_layout_codes, switch_layout_mode, num_codes_to_index = parse_keymap(args, rev_event_keys, event_keys) + shift_down = -1 + rshift = event_keys[1]['KEY_RIGHTSHIFT'] + lshift = event_keys[1]['KEY_LEFTSHIFT'] if args.direct: # setup a new input device @@ -136,13 +139,25 @@ while True: ev = f.next_event() + pre_event = None + post_event = None + if args.keymap: #if ev.type == 4: # MSC_SCAN, works for some keyboards (serio) but not others (usb), not needed if we grab the input # ev.value = active_keymap[ev.value] if ev.type == 1: # EV_KEY - ev.code = active_keymap[ev.code] + new_code, invert_shift = active_keymap[ev.code].get_code(ev.code, shift_down != -1) # we want some events to happen when a key is first pressed or lifted if ev.value == 1: # pressed + if ev.code == lshift or ev.code == rshift: # shift + shift_down = ev.code + + if invert_shift: # swap shift behavior + pre_event = input_event(ev.time, 1, shift_down, 0) + if shift_down == -1: + pre_event.code = lshift + pre_event.value = 1 + if ev.code == revert_default_code: active_keymap = runtime_keymaps[revert_keymap_index] elif ev.code in switch_layout_codes: @@ -157,11 +172,22 @@ while True: # and continue so as to not send this key continue elif ev.value == 0: # lifted + if ev.code == lshift or ev.code == rshift: # shift + shift_down = -1 + + if invert_shift: # swap shift behavior + post_event = input_event(ev.time, 1, shift_down, 1) + if shift_down == -1: + post_event.code = lshift + post_event.value = 0 + if ev.code == revert_default_code: active_keymap = runtime_keymaps[active_keymap_index] elif ev.code in switch_layout_codes: switch_layout_codes[ev.code] = False switch_layout_mode = False + # now actually map the key + ev.code = new_code if args.direct: # try to fire our own events? @@ -170,20 +196,31 @@ while True: d = ofs[idx] else: d = ofs[i] + if pre_event is not None: + d.fire_event(pre_event) d.fire_event(ev) + if post_event is not None: + d.fire_event(post_event) elif args.dump: - try: - #print 'ev.type:', ev.type - print i, ev.time.tv_sec, ev.time.tv_usec - s = '%s(%d) %s(%d) %d' % (rev_events[ev.type], ev.type, - rev_event_keys[ev.type][ev.code], ev.code, ev.value) - print 'Event type:', s - except KeyError: - pass + for ev in [pre_event, ev, post_event]: + if ev is not None: + try: + print i, ev.time.tv_sec, ev.time.tv_usec + s = '%s(%d) %s(%d) %d' % (rev_events[ev.type], ev.type, rev_event_keys[ev.type][ev.code], ev.code, ev.value) + print 'Event type:', s + except KeyError: + pass else: if not args.compat: + if pre_event is not None: + p.dump((i, pre_event)) p.dump((i, ev)) + if post_event is not None: + p.dump((i, post_event)) else: - p.dump((i, (ev.time.tv_sec, ev.time.tv_usec, - ev.type, ev.code, ev.value))) + if pre_event is not None: + p.dump((i, (pre_event.time.tv_sec, pre_event.time.tv_usec, pre_event.type, pre_event.code, pre_event.value))) + p.dump((i, (ev.time.tv_sec, ev.time.tv_usec, ev.type, ev.code, ev.value))) + if post_event is not None: + p.dump((i, (post_event.time.tv_sec, post_event.time.tv_usec, post_event.type, post_event.code, post_event.value))) sys.stdout.flush() diff --git a/keymaps/dvorak.py b/keymaps/dvorak.py index e7c63cf..236e220 100644 --- a/keymaps/dvorak.py +++ b/keymaps/dvorak.py @@ -9,8 +9,8 @@ revert_default_key = 'LEFTCTRL' revert_keymap_index = 0 # this is the default index to use when the program first starts -# in this case, 1 means Dvorak -default_keymap_index = 1 +# in this case, 2 means modified Progammer Dvorak +default_keymap_index = 2 # these are the keymaps available, you can add as many as you want or re-order them, just be aware the mapping is # always done from the first one to all subsequent ones, so you probably want to leave QWERTY or similar up top @@ -33,4 +33,24 @@ keymaps = [ LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3, LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT """, + # Programmer Dvorak http://www.kaufmann.no/roland/dvorak/ without numpad re-ordered + # (to be strict QUOT/SCLN are swapped from regular dvorak, though I can't understand why so I ignored it...) + """ + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ^4:^GRV, ^7:^5, LBRC:7, ^LBRC:5, ^RBRC:3, ^9:1, EQL:9, ^8:0, ^0:2, ^EQL:4, RBRC:6, ^1:8, ^3:GRV, BSPC, INS, HOME,PGUP, NLCK, PSLS:^9, PAST:^0, PMNS:^4, + TAB, QUOT, COMM, DOT, P, Y, F, G, C, R, L, SLSH, ^2:^6, BSLS, DEL, END, PGDN, P7:^A, P8:^B, P9:^C, + CAPS, A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4:^D, P5:^E, P6:^F, PPLS:COMM, + LSFT, SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1:EQL, P2:X, P3:^SCLN, + LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, P0:BSLS, PDOT:SCLN, PENT + """, + # Programmer Dvorak http://www.kaufmann.no/roland/dvorak/ + # (to be strict QUOT/SCLN are swapped from regular dvorak, though I can't understand why so I ignored it...) + """ + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, + ^4:^GRV, ^7:^5, LBRC:7, ^LBRC:5, ^RBRC:3, ^9:1, EQL:9, ^8:0, ^0:2, ^EQL:4, RBRC:6, ^1:8, ^3:GRV, BSPC, INS, HOME,PGUP, NLCK, PSLS:^9, PAST:^0, PMNS:^4, + TAB, QUOT, COMM, DOT, P, Y, F, G, C, R, L, SLSH, ^2:^6, BSLS, DEL, END, PGDN, P1:^A, P2:^B, P3:^C, + CAPS, A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4:^D, P5:^E, P6:^F, PPLS:COMM, + LSFT, SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, P7:EQL, P8:X, P9:^SCLN, + LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, P0:BSLS, PDOT:SCLN, PENT + """, ] diff --git a/uinputmapper/keymapper.py b/uinputmapper/keymapper.py index 4877bab..6a9544c 100644 --- a/uinputmapper/keymapper.py +++ b/uinputmapper/keymapper.py @@ -3,6 +3,33 @@ Module to help with creating fast keycode mapping arrays """ +class KeyCodeMapper(object): + + def __init__(self, noshift_code, noshift_invert_shift, shift_code, shift_invert_shift): + self.noshift_code = noshift_code + self.noshift_invert_shift = noshift_invert_shift + self.shift_code = shift_code + self.shift_invert_shift = shift_invert_shift + + def get_code(self, old_code, shift_down): + # returns new_code, invert_shift + if shift_down: + return self.shift_code, self.shift_invert_shift + else: + return self.noshift_code, self.noshift_invert_shift + + def __repr__(self): + return "KCM{%3s (%5s) : %3s (%5s)}" % (self.noshift_code, self.noshift_invert_shift, self.shift_code, self.shift_invert_shift) + +class NoopKCM(object): + + def get_code(self, old_code, shift_down): + # returns new_code, invert_shift + return old_code, False + + def __repr__(self): + return "KCM{NOOP}" + def parse_keymap(args, rev_event_keys, event_keys): """ Reads in a keymap configuration and returns structures to implement it @@ -67,31 +94,43 @@ def parse_keymap(args, rev_event_keys, event_keys): 'SLSH':'SLASH', 'SPC':'SPACE', } + shift_key_list = [] keymap_list = [] for keymap in keymaps: key_list = [] keymap_list.append(key_list) for key in keymap.split(','): - key = key.strip() + key = key.strip() # remove whitespace + key_arr = key.split(':') + noshift_invert_shift = '^' == key_arr[0][0] + key = key_arr[0].strip('^') new_key = 'KEY_'+short_to_long.get(key, key) if args.dump and new_key not in event_keys[1]: # todo: probably should exit with some helpful error here? - #print 'Key', key, 'does not exist!' - #print "'", key, "':''," print "'%s':''," % key - key_list.append(new_key) + noshift_code = event_keys[1][new_key] + if len(key_arr) == 1: + shift_invert_shift = noshift_invert_shift + shift_code = noshift_code + else: + shift_invert_shift = '^' != key_arr[1][0] + key = key_arr[1].strip('^') + new_key = 'KEY_'+short_to_long.get(key, key) + if args.dump and new_key not in event_keys[1]: # todo: probably should exit with some helpful error here? + print "'%s':''," % key + shift_code = event_keys[1][new_key] + key_list.append(KeyCodeMapper(noshift_code, noshift_invert_shift, shift_code, shift_invert_shift)) #pprint.pprint(keymap_list) #exit(0) mykeymaps = [] default_keymap = keymap_list[0] keymap_range = range(0, len(default_keymap)) - from array import array for keymap in keymap_list: mykeymap = {} mykeymaps.append(mykeymap) for y in keymap_range: if default_keymap[y] != keymap[y]: - mykeymap[default_keymap[y]] = keymap[y] + mykeymap[default_keymap[y].noshift_code] = keymap[y] #pprint.pprint(mykeymaps) #exit(0) @@ -103,17 +142,19 @@ def parse_keymap(args, rev_event_keys, event_keys): #exit(0) # convert mykeymap once, at startup, to a faster array, possibly using a little more memory keycnt_range = range(0, event_keys[1]['KEY_CNT']) + + noop = NoopKCM() runtime_keymaps = [] for mykeymap in mykeymaps: - mycodemap = array('H') + mycodemap = [] runtime_keymaps.append(mycodemap) for x in keycnt_range: - key = rev_event_keys[1].get(x, 'NO_KEY_EXISTS_FOR_THIS_INDEX') - value = event_keys[1].get(mykeymap.get(key, key), x) - mycodemap.append(value) + mycodemap.append(mykeymap.get(x, noop)) + #print 'mycodemap: ', mycodemap #pprint.pprint(runtime_keymaps) #exit(0) + active_keymap_index = default_keymap_index revert_default_code = event_keys[1]['KEY_'+revert_default_key] active_keymap = runtime_keymaps[active_keymap_index]