Package dtk :: Package ui :: Module global_key

Source Code for Module dtk.ui.global_key

  1  #! /usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (C) 2011 ~ 2012 Deepin, Inc. 
  5  #               2011 ~ 2012 Wang Yong 
  6  # 
  7  # Author:     Wang Yong <lazycat.manatee@gmail.com> 
  8  # Maintainer: Wang Yong <lazycat.manatee@gmail.com> 
  9  # 
 10  # This program is free software: you can redistribute it and/or modify 
 11  # it under the terms of the GNU General Public License as published by 
 12  # the Free Software Foundation, either version 3 of the License, or 
 13  # any later version. 
 14  # 
 15  # This program is distributed in the hope that it will be useful, 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  # GNU General Public License for more details. 
 19  # 
 20  # You should have received a copy of the GNU General Public License 
 21  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 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   
34 -def enable_global_key():
35 ''' 36 Enable global key. 37 ''' 38 global global_key_running 39 40 global_key_lock.acquire() 41 global_key_running = True 42 global_key_lock.release()
43
44 -def disable_global_key():
45 ''' 46 Disable global key. 47 ''' 48 global global_key_running 49 50 global_key_lock.acquire() 51 global_key_running = False 52 global_key_lock.release()
53
54 -class GlobalKey(threading.Thread):
55 ''' 56 Class to handle global key. 57 ''' 58
59 - def __init__(self):
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 # Get keybinding's keyval and modifiers. 85 return 86 keyval, modifiers = parse_keyevent_name(binding_string) 87 88 # Get key code. 89 keycode = gtk.gdk.keymap_get_default().get_entries_for_keyval(keyval)[0][0] 90 91 # Binding key. 92 self._binding_map[(keycode, modifiers)] = action 93 94 # Make keybinding can response even user enable Num-Lock key. 95 num_lock_modifiers = modifiers | gdk.MOD2_MASK 96 self._binding_map[(keycode, num_lock_modifiers)] = action 97 98 # Restart grab keybinding. 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 # Get keybinding. 108 keyval, modifiers = parse_keyevent_name(binding_string) 109 110 # Get key code. 111 keycode = gtk.gdk.keymap_get_default().get_entries_for_keyval(keyval)[0][0] 112 113 # Get modifiers with Num-Lock mask. 114 num_lock_modifiers = modifiers | gdk.MOD2_MASK 115 116 # Remove keybinding from binding map. 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 # Try remove key binding (with Num-Lock mask) from binding map. 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
130 - def grab(self):
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
140 - def ungrab(self):
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
150 - def regrab(self):
151 ''' 152 Regrab key. 153 ''' 154 self.ungrab() 155 self.grab()
156
157 - def run(self):
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
190 - def exit(self):
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):
202 print 'Called!'
203 manager = GlobalKey() 204 # manager.bind('Ctrl + Alt + Shift + s', t) 205 manager.bind('Ctrl + Alt + S', t) 206 manager.start() 207 208 gtk.main() 209