1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from Xlib import X
24 from Xlib.display import Display
25 from keymap import parse_keyevent_name
26 from threading import Lock
27 import gtk
28 import gtk.gdk as gdk
29 import threading
30
31 global_key_running = True
32 global_key_lock = Lock()
33
43
53
55 '''
56 Class to handle global key.
57 '''
58
60 '''
61 Init for global key.
62 '''
63 super(GlobalKey, self).__init__()
64 self.daemon = True
65 self.display = Display()
66 self.root = self.display.screen().root
67 self._binding_map = {}
68 self.stop = False
69
70 self.known_modifiers_mask = 0
71 gdk_modifiers = (gtk.gdk.CONTROL_MASK, gtk.gdk.SHIFT_MASK, gtk.gdk.MOD1_MASK,
72 gtk.gdk.MOD2_MASK, gtk.gdk.MOD3_MASK, gtk.gdk.MOD4_MASK, gtk.gdk.MOD5_MASK,
73 gtk.gdk.SUPER_MASK, gtk.gdk.HYPER_MASK)
74 for mod in gdk_modifiers:
75 self.known_modifiers_mask |= mod
76
77 - def bind(self, binding_string, action):
78 '''
79 Binding keymap with given action.
80
81 @param binding_string: Keymap string, return by function `get_keyevent_name` of module dtk.ui.keymap.
82 @param action: Callback.
83 '''
84
85 return
86 keyval, modifiers = parse_keyevent_name(binding_string)
87
88
89 keycode = gtk.gdk.keymap_get_default().get_entries_for_keyval(keyval)[0][0]
90
91
92 self._binding_map[(keycode, modifiers)] = action
93
94
95 num_lock_modifiers = modifiers | gdk.MOD2_MASK
96 self._binding_map[(keycode, num_lock_modifiers)] = action
97
98
99 self.regrab()
100
101 - def unbind(self, binding_string):
102 '''
103 Unbind keymap.
104
105 @param binding_string: Keymap string that return by function `get_keyevent_name` of module dtk.ui.keymap.
106 '''
107
108 keyval, modifiers = parse_keyevent_name(binding_string)
109
110
111 keycode = gtk.gdk.keymap_get_default().get_entries_for_keyval(keyval)[0][0]
112
113
114 num_lock_modifiers = modifiers | gdk.MOD2_MASK
115
116
117 regrab_flag = False
118 if self._binding_map.has_key((keycode, modifiers)):
119 del self._binding_map[(keycode, modifiers)]
120 regrab_flag = True
121
122
123 if self._binding_map.has_key((keycode, num_lock_modifiers)):
124 del self._binding_map[(keycode, num_lock_modifiers)]
125 regrab_flag = True
126
127 if regrab_flag:
128 self.regrab()
129
131 '''
132 Grab key.
133 '''
134 for (keycode, modifiers) in self._binding_map.keys():
135 try:
136 self.root.grab_key(keycode, int(modifiers), True, X.GrabModeAsync, X.GrabModeSync)
137 except Exception, e:
138 print e
139
141 '''
142 Ungrab key.
143 '''
144 for (keycode, modifiers) in self._binding_map.keys():
145 try:
146 self.root.ungrab_key(keycode, modifiers, self.root)
147 except Exception, e:
148 print e
149
151 '''
152 Regrab key.
153 '''
154 self.ungrab()
155 self.grab()
156
158 '''
159 GlobalKey thread loop.
160 '''
161 global global_key_running
162
163 wait_for_release = False
164 while not self.stop:
165 event = self.display.next_event()
166 if global_key_running:
167 if event.type == X.KeyPress and not wait_for_release:
168 keycode = event.detail
169 modifiers = event.state & self.known_modifiers_mask
170 try:
171 action = self._binding_map[(keycode, modifiers)]
172 except KeyError:
173 self.display.allow_events(X.ReplayKeyboard, event.time)
174 else:
175 wait_for_release = True
176 self.display.allow_events(X.AsyncKeyboard, event.time)
177 self._upcoming_action = (keycode, modifiers, action)
178
179 elif event.type == X.KeyRelease and wait_for_release and event.detail == self._upcoming_action[0]:
180 wait_for_release = False
181 action = self._upcoming_action[2]
182 del self._upcoming_action
183 action()
184 self.display.allow_events(X.AsyncKeyboard, event.time)
185 else:
186 self.display.allow_events(X.ReplayKeyboard, event.time)
187 else:
188 self.display.allow_events(X.ReplayKeyboard, event.time)
189
191 '''
192 Exit global key.
193 '''
194 self.stop = True
195 self.ungrab()
196 self.display.close()
197
198 if __name__ == "__main__":
199 gtk.gdk.threads_init()
200
201 - def t(*args, **kwargs):
203 manager = GlobalKey()
204
205 manager.bind('Ctrl + Alt + S', t)
206 manager.start()
207
208 gtk.main()
209