[sugar] [PATCH 3/6] Handle the keyboard event handling for tabbing.
Benjamin Berg
benjamin at sipsolutions.net
Thu Jun 19 15:09:37 EDT 2008
---
src/view/keyhandler.py | 91 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/src/view/keyhandler.py b/src/view/keyhandler.py
index 16f5a43..b42b93c 100644
--- a/src/view/keyhandler.py
+++ b/src/view/keyhandler.py
@@ -33,6 +33,10 @@ _BRIGHTNESS_STEP = 2
_VOLUME_STEP = 10
_BRIGHTNESS_MAX = 15
_VOLUME_MAX = 100
+# The modifier used for tabbing. Should the shortcuts ever be made user
+# configurable, then some code to figure out the apropriate modifier is
+# needed instead of hardcoding it.
+_TABBING_MODIFIER = gtk.gdk.MOD1_MASK
_actions_table = {
'F1' : 'zoom_mesh',
@@ -78,10 +82,13 @@ class KeyHandler(object):
self._keycode_pressed = 0
self._keystate_pressed = 0
self._speech_proxy = None
+ self._tabbing_windows = False
self._key_grabber = KeyGrabber()
self._key_grabber.connect('key-pressed',
self._key_pressed_cb)
+ self._key_grabber.connect('key-released',
+ self._key_released_cb)
for key in _actions_table.keys():
self._key_grabber.grab(key)
@@ -132,15 +139,70 @@ class KeyHandler(object):
self._get_speech_proxy().SayText(text, reply_handler=lambda: None, \
error_handler=self._on_speech_err)
+ def _window_tabbing(self, direction):
+ shell = view.Shell.get_instance()
+ if not self._tabbing_windows:
+ logging.debug('Grabing the input.')
+
+ screen = gtk.gdk.screen_get_default()
+ window = screen.get_root_window()
+ keyboard_grab_result = gtk.gdk.keyboard_grab(window)
+ pointer_grab_result = gtk.gdk.pointer_grab(window)
+
+ self._tabbing_windows = (keyboard_grab_result == gtk.gdk.GRAB_SUCCESS and
+ pointer_grab_result == gtk.gdk.GRAB_SUCCESS)
+
+ # Now test that the modifier is still active to prevent race
+ # conditions. We also test if one of the grabs failed.
+ mask = window.get_pointer()[2]
+ if not self._tabbing_windows or not (mask & _TABBING_MODIFIER):
+ logging.debug('Releasing grabs again.')
+
+ if keyboard_grab_result != gtk.gdk.GRAB_SUCCESS:
+ gtk.gdk.keyboard_ungrab()
+ if pointer_grab_result != gtk.gdk.GRAB_SUCCESS:
+ gtk.gdk.pointer_ungrab()
+ self._tabbing_windows = False
+ else:
+ shell.tabbing_start()
+
+ first_switch = True
+ else:
+ first_switch = False
+
+ if self._tabbing_windows:
+ if direction == 1:
+ shell.tabbing_next_activity(first_switch)
+ else:
+ shell.tabbing_previous_activity(first_switch)
+
+ return self._tabbing_windows
+
+ def _stop_window_tabbing(self):
+ # Some useless key was pressed, or <Alt> released.
+ if not self._tabbing_windows:
+ return
+
+ logging.debug('Releasing grabs again.')
+ gtk.gdk.keyboard_ungrab()
+ gtk.gdk.pointer_ungrab()
+
+ shell = view.Shell.get_instance()
+ shell.tabbing_stop()
+
+ self._tabbing_windows = False
+
def handle_say_text(self):
clipboard = gtk.clipboard_get(selection="PRIMARY")
clipboard.request_text(self._primary_selection_cb)
def handle_previous_window(self):
- view.Shell.get_instance().activate_previous_activity()
+ if not self._window_tabbing(-1):
+ view.Shell.get_instance().activate_previous_activity()
def handle_next_window(self):
- view.Shell.get_instance().activate_next_activity()
+ if not self._window_tabbing(1):
+ view.Shell.get_instance().activate_next_activity()
def handle_close_window(self):
view.Shell.get_instance().close_current_activity()
@@ -252,9 +314,34 @@ class KeyHandler(object):
self._keystate_pressed = state
action = _actions_table[key]
+ if self._tabbing_windows:
+ # Only accept window tabbing events, everything else
+ # cancels the tabbing operation.
+ if not action in ["next_window", "previous_window"]:
+ self._stop_window_tabbing()
+ return True
+
method = getattr(self, 'handle_' + action)
method()
return True
+ else:
+ # If this is not a registered key, then cancel any active
+ # tabbing.
+ if self._tabbing_windows:
+ if not grabber.is_modifier(keycode):
+ self._stop_window_tabbing()
+ return True
return False
+
+ def _key_released_cb(self, grabber, keycode, state):
+ if self._tabbing_windows:
+ # We stop tabbing and switch to the new window as soon as the
+ # modifier key is raised again.
+ if grabber.is_specific_modifier(keycode, _TABBING_MODIFIER):
+ self._stop_window_tabbing()
+
+ return True
+ return False
+
More information about the Sugar
mailing list