Re: [sugar] [PATCH 3/6] Handle the keyboard event handling for tabbing.

2008-06-20 Thread Marco Pesenti Gritti
On Thu, Jun 19, 2008 at 9:09 PM, Benjamin Berg
[EMAIL PROTECTED] wrote:
 +# 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.

I'd remove this comment. Seem implicit in the fact that you defined it as a var.
I'd prefer if this was factored out to TabbingHandler along with the shell.

Marco
___
Sugar mailing list
Sugar@lists.laptop.org
http://lists.laptop.org/listinfo/sugar


[sugar] [PATCH 3/6] Handle the keyboard event handling for tabbing.

2008-06-19 Thread Benjamin Berg

---

 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:
+