27
from terminatorlib.config import err
29
29
class KeymapError(Exception):
30
"""Custom exception for errors in keybinding configurations"""
31
def __init__(self, value):
32
Exception.__init__(self, value)
34
self.action = 'unknown'
30
"""Custom exception for errors in keybinding configurations"""
31
def __init__(self, value):
32
Exception.__init__(self, value)
34
self.action = 'unknown'
37
return "Keybinding '%s' invalid: %s" % (self.action, self.value)
37
return "Keybinding '%s' invalid: %s" % (self.action, self.value)
39
39
MODIFIER = re.compile('<([^<]+)>')
40
class TerminatorKeybindings:
41
"""Class to handle loading and lookup of Terminator keybindings"""
44
'ctrl': gtk.gdk.CONTROL_MASK,
45
'control': gtk.gdk.CONTROL_MASK,
46
'shift': gtk.gdk.SHIFT_MASK,
47
'alt': gtk.gdk.MOD1_MASK,
48
'super': gtk.gdk.SUPER_MASK,
57
self.keymap = gtk.gdk.keymap_get_default()
60
def configure(self, bindings):
61
"""Accept new bindings and reconfigure with them"""
66
"""Parse bindings and mangle into an appropriate form"""
69
for action, bindings in self.keys.items():
70
if not isinstance(bindings, tuple):
71
bindings = (bindings,)
73
for binding in bindings:
74
if binding is None or binding == "None":
78
keyval, mask = self._parsebinding(binding)
79
# Does much the same, but with poorer error handling.
80
#keyval, mask = gtk.accelerator_parse(binding)
81
except KeymapError, ex:
84
if mask & gtk.gdk.SHIFT_MASK:
85
if keyval == gtk.keysyms.Tab:
86
keyval = gtk.keysyms.ISO_Left_Tab
87
mask &= ~gtk.gdk.SHIFT_MASK
89
keyvals = gtk.gdk.keyval_convert_case(keyval)
90
if keyvals[0] != keyvals[1]:
92
mask &= ~gtk.gdk.SHIFT_MASK
94
keyval = gtk.gdk.keyval_to_lower(keyval)
95
self._lookup.setdefault(mask, {})
96
self._lookup[mask][keyval] = action
99
def _parsebinding(self, binding):
100
"""Parse an individual binding using gtk's binding function"""
102
modifiers = re.findall(MODIFIER, binding)
104
for modifier in modifiers:
105
mask |= self._lookup_modifier(modifier)
106
key = re.sub(MODIFIER, '', binding)
108
raise KeymapError('No key found')
109
keyval = gtk.gdk.keyval_from_name(key)
111
raise KeymapError("Key '%s' is unrecognised" % key)
112
return (keyval, mask)
114
def _lookup_modifier(self, modifier):
115
"""Map modifier names to gtk values"""
117
return self.modifiers[modifier.lower()]
119
raise KeymapError("Unhandled modifier '<%s>'" % modifier)
121
def lookup(self, event):
122
"""Translate a keyboard event into a mapped key"""
124
keyval, egroup, level, consumed = self.keymap.translate_keyboard_state(
125
event.hardware_keycode,
126
event.state & ~gtk.gdk.LOCK_MASK,
129
err ("keybindings.lookup failed to translate keyboard event: %s" %
132
mask = (event.state & ~consumed) & self._masks
133
return self._lookup.get(mask, self.empty).get(keyval, None)
41
"""Class to handle loading and lookup of Terminator keybindings"""
44
'ctrl': gtk.gdk.CONTROL_MASK,
45
'control': gtk.gdk.CONTROL_MASK,
46
'shift': gtk.gdk.SHIFT_MASK,
47
'alt': gtk.gdk.MOD1_MASK,
48
'super': gtk.gdk.SUPER_MASK,
57
self.keymap = gtk.gdk.keymap_get_default()
60
def configure(self, bindings):
61
"""Accept new bindings and reconfigure with them"""
66
"""Parse bindings and mangle into an appropriate form"""
69
for action, bindings in self.keys.items():
70
if not isinstance(bindings, tuple):
71
bindings = (bindings,)
73
for binding in bindings:
74
if binding is None or binding == "None":
78
keyval, mask = self._parsebinding(binding)
79
# Does much the same, but with poorer error handling.
80
#keyval, mask = gtk.accelerator_parse(binding)
84
if mask & gtk.gdk.SHIFT_MASK:
85
if keyval == gtk.keysyms.Tab:
86
keyval = gtk.keysyms.ISO_Left_Tab
87
mask &= ~gtk.gdk.SHIFT_MASK
89
keyvals = gtk.gdk.keyval_convert_case(keyval)
90
if keyvals[0] != keyvals[1]:
92
mask &= ~gtk.gdk.SHIFT_MASK
94
keyval = gtk.gdk.keyval_to_lower(keyval)
95
self._lookup.setdefault(mask, {})
96
self._lookup[mask][keyval] = action
99
def _parsebinding(self, binding):
100
"""Parse an individual binding using gtk's binding function"""
102
modifiers = re.findall(MODIFIER, binding)
104
for modifier in modifiers:
105
mask |= self._lookup_modifier(modifier)
106
key = re.sub(MODIFIER, '', binding)
108
raise KeymapError('No key found')
109
keyval = gtk.gdk.keyval_from_name(key)
111
raise KeymapError("Key '%s' is unrecognised" % key)
112
return (keyval, mask)
114
def _lookup_modifier(self, modifier):
115
"""Map modifier names to gtk values"""
117
return self.modifiers[modifier.lower()]
119
raise KeymapError("Unhandled modifier '<%s>'" % modifier)
121
def lookup(self, event):
122
"""Translate a keyboard event into a mapped key"""
124
keyval, _egp, _lvl, consumed = self.keymap.translate_keyboard_state(
125
event.hardware_keycode,
126
event.state & ~gtk.gdk.LOCK_MASK,
129
err ("keybindings.lookup failed to translate keyboard event: %s" %
132
mask = (event.state & ~consumed) & self._masks
133
return self._lookup.get(mask, self.empty).get(keyval, None)