mirror of
https://github.com/moparisthebest/uinput-mapper
synced 2024-12-21 19:38:47 -05:00
Add keymapper functionality to change shift behavior and de-couple different keys for shift status, to support Programmer Dvorak and basically any other format
This commit is contained in:
parent
61cd9779d5
commit
7828a7990e
59
input-read
59
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()
|
||||
|
@ -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
|
||||
""",
|
||||
]
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user