From ebe043a4d20d408f04fb1a520fd5e707bbbf68db Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Sat, 17 Mar 2007 13:30:23 +0000 Subject: Refactored global key handling and frame logic. --- diff --git a/lib/python/_sugar.defs b/lib/python/_sugar.defs index c894777..a23e752 100644 --- a/lib/python/_sugar.defs +++ b/lib/python/_sugar.defs @@ -153,6 +153,16 @@ ) ) +(define-method get_key + (of-object "SugarKeyGrabber") + (c-name "sugar_key_grabber_get_key") + (return-type "char*") + (parameters + '("guint" "keycode") + '("guint" "state") + ) +) + ;; From sugar-push-scroller.h (define-function push_scroller_get_type diff --git a/lib/src/sugar-key-grabber.c b/lib/src/sugar-key-grabber.c index b086ba0..8c832a7 100644 --- a/lib/src/sugar-key-grabber.c +++ b/lib/src/sugar-key-grabber.c @@ -23,6 +23,7 @@ #include "sugar-key-grabber.h" #include "eggaccelerators.h" +#include "sugar-marshal.h" /* we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what these modifiers mean @@ -81,49 +82,31 @@ sugar_key_grabber_class_init(SugarKeyGrabberClass *grabber_class) G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (SugarKeyGrabberClass, key_pressed), NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); + sugar_marshal_BOOLEAN__UINT_UINT, + G_TYPE_BOOLEAN, 2, + G_TYPE_UINT, + G_TYPE_UINT); signals[KEY_RELEASED] = g_signal_new ("key-released", G_TYPE_FROM_CLASS (grabber_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (SugarKeyGrabberClass, key_released), NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); + sugar_marshal_BOOLEAN__UINT_UINT, + G_TYPE_BOOLEAN, 2, + G_TYPE_UINT, + G_TYPE_UINT); } -static char * -get_key_from_event(SugarKeyGrabber *grabber, XEvent *xev) +char * +sugar_key_grabber_get_key(SugarKeyGrabber *grabber, guint keycode, guint state) { GList *l; - guint keycode, state; - - keycode = xev->xkey.keycode; - state = xev->xkey.state; - - if(grabber->last_key_pressed == keycode) { - grabber->last_key_pressed = 0; - } - if(grabber->last_key_pressed_modifier == state) { - grabber->last_key_pressed_modifier = 0; - } for (l = grabber->keys; l != NULL; l = l->next) { Key *keyinfo = (Key *)l->data; - if (keyinfo->keycode == keycode) { - if (xev->type == KeyPress && - (state & USED_MODS) == keyinfo->state) { - - return g_strdup(keyinfo->key); - } else if (xev->type == KeyRelease) { - if(!grabber->last_key_pressed && - !grabber->last_key_pressed_modifier) { - - return g_strdup(keyinfo->key); - } - } + if ((keyinfo->keycode == keycode) && + ((state & USED_MODS) == keyinfo->state)) { + return g_strdup(keyinfo->key); } } @@ -137,36 +120,19 @@ filter_events(GdkXEvent *xevent, GdkEvent *event, gpointer data) XEvent *xev = (XEvent *)xevent; if (xev->type == KeyRelease) { - char *key; - - key = get_key_from_event(grabber, xevent); - if (key) { - g_signal_emit (grabber, signals[KEY_RELEASED], 0, key); - g_free(key); - - XUngrabKeyboard (GDK_WINDOW_XDISPLAY (grabber->root), 0L); - - return GDK_FILTER_REMOVE; - } + int return_value; + g_signal_emit (grabber, signals[KEY_RELEASED], 0, xev->xkey.keycode, + xev->xkey.state, &return_value); + if(return_value) + return GDK_FILTER_REMOVE; } if (xev->type == KeyPress) { - char *key; - - key = get_key_from_event(grabber, xevent); - if (key) { - grabber->last_key_pressed = xev->xkey.keycode; - grabber->last_key_pressed_modifier = xev->xkey.state; - - g_signal_emit (grabber, signals[KEY_PRESSED], 0, key); - g_free(key); - - XGrabKeyboard (GDK_WINDOW_XDISPLAY (grabber->root), - GDK_WINDOW_XID (grabber->root), - 0, GrabModeAsync, GrabModeAsync, 0L); - - return GDK_FILTER_REMOVE; - } + int return_value; + g_signal_emit (grabber, signals[KEY_PRESSED], 0, xev->xkey.keycode, + xev->xkey.state, &return_value); + if(return_value) + return GDK_FILTER_REMOVE; } return GDK_FILTER_CONTINUE; @@ -180,8 +146,6 @@ sugar_key_grabber_init(SugarKeyGrabber *grabber) screen = gdk_screen_get_default(); grabber->root = gdk_screen_get_root_window(screen); grabber->keys = NULL; - grabber->last_key_pressed = 0; - grabber->last_key_pressed_modifier = 0; gdk_window_add_filter(grabber->root, filter_events, grabber); } diff --git a/lib/src/sugar-key-grabber.h b/lib/src/sugar-key-grabber.h index e45c329..3e9ab5d 100644 --- a/lib/src/sugar-key-grabber.h +++ b/lib/src/sugar-key-grabber.h @@ -39,22 +39,25 @@ struct _SugarKeyGrabber { GdkWindow *root; GList *keys; - guint last_key_pressed; - guint last_key_pressed_modifier; }; struct _SugarKeyGrabberClass { GObjectClass base_class; - void (* key_pressed) (SugarKeyGrabber *grabber, - const char *key); - void (* key_released) (SugarKeyGrabber *grabber, - const char *key); + gboolean (* key_pressed) (SugarKeyGrabber *grabber, + guint keycode, + guint state); + gboolean (* key_released) (SugarKeyGrabber *grabber, + guint keycode, + guint state); }; GType sugar_key_grabber_get_type (void); void sugar_key_grabber_grab (SugarKeyGrabber *grabber, const char *key); +char *sugar_key_grabber_get_key (SugarKeyGrabber *grabber, + guint keycode, + guint state); G_END_DECLS diff --git a/lib/src/sugar-marshal.list b/lib/src/sugar-marshal.list index 81b3ae1..45c0401 100644 --- a/lib/src/sugar-marshal.list +++ b/lib/src/sugar-marshal.list @@ -2,3 +2,4 @@ VOID:OBJECT,STRING,LONG,LONG VOID:OBJECT,LONG VOID:OBJECT BOOLEAN:BOXED +BOOLEAN:UINT,UINT diff --git a/shell/view/frame/frame.py b/shell/view/frame/frame.py index 11aea67..aa152ef 100644 --- a/shell/view/frame/frame.py +++ b/shell/view/frame/frame.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import logging import gtk import gobject @@ -77,38 +78,36 @@ class _MouseListener(object): _FRAME_HIDING_DELAY, self._hide_frame_timeout_cb) class _KeyListener(object): + _HIDDEN = 1 + _SHOWN_PRESSED = 2 + _SHOWN_REPEAT = 3 + _SHOWN_RELEASED = 4 + def __init__(self, frame): self._frame = frame - self._hide_sid = 0 + self._state = _KeyListener._HIDDEN def key_press(self): if self._frame.mode != MODE_NONE and \ self._frame.mode != MODE_KEYBOARD: return - if self._frame.visible: - self._hide_frame() - else: - self._show_frame() + if self._state == _KeyListener._HIDDEN: + self._frame.show() + self._frame.mode = MODE_KEYBOARD + self._state = _KeyListener._SHOWN_PRESSED + elif self._state == _KeyListener._SHOWN_PRESSED: + self._state = _KeyListener._SHOWN_REPEAT + elif self._state == _KeyListener._SHOWN_RELEASED: + self._frame.hide() + self._state = _KeyListener._HIDDEN def key_release(self): - self._hide_frame() - - def _hide_frame_timeout_cb(self): - self._frame.hide() - return False - - def _show_frame(self): - if self._hide_sid != 0: - gobject.source_remove(self._hide_sid) - self._frame.show() - self._frame.mode = MODE_KEYBOARD - - def _hide_frame(self): - if self._hide_sid != 0: - gobject.source_remove(self._hide_sid) - self._hide_sid = gobject.timeout_add( - 100, self._hide_frame_timeout_cb) + if self._state == _KeyListener._SHOWN_PRESSED: + self._state = _KeyListener._SHOWN_RELEASED + elif self._state == _KeyListener._SHOWN_REPEAT: + self._frame.hide() + self._state = _KeyListener._HIDDEN class Frame(object): def __init__(self, shell): diff --git a/shell/view/keyhandler.py b/shell/view/keyhandler.py index ac3e7dd..645f5d6 100644 --- a/shell/view/keyhandler.py +++ b/shell/view/keyhandler.py @@ -1,8 +1,10 @@ import os import signal +import logging import dbus import gobject +import gtk from sugar import env from hardware import hardwaremanager @@ -46,6 +48,9 @@ class KeyHandler(object): self._shell = shell self._audio_manager = hardwaremanager.get_audio_manager() self._screen_rotation = 0 + self._key_pressed = None + self._keycode_pressed = 0 + self._keystate_pressed = 0 self._key_grabber = KeyGrabber() self._key_grabber.connect('key-pressed', @@ -166,16 +171,42 @@ class KeyHandler(object): # FIXME: finish alt+tab support pass - def _key_pressed_cb(self, grabber, key): - action = _actions_table[key] - method = getattr(self, 'handle_' + action) - method() + def _key_pressed_cb(self, grabber, keycode, state): + key = grabber.get_key(keycode, state) + if key: + self._key_pressed = key + self._keycode_pressed = keycode + self._keystate_pressed = state + gtk.gdk.keyboard_grab(gtk.gdk.get_default_root_window(), + owner_events=False, time=0L) - def _key_released_cb(self, grabber, key): - if key == 'F9': - self._shell.get_frame().notify_key_release() - elif key == '0x93': - self._shell.get_frame().notify_key_release() + action = _actions_table[key] + method = getattr(self, 'handle_' + action) + method() + + return True + + return False + + def _key_released_cb(self, grabber, keycode, state): + if self._keycode_pressed == keycode: + self._keycode_pressed = 0 + + if self._keystate_pressed == state: + self._keystate_pressed = 0 + + if not self._keycode_pressed and not self._keystate_pressed and \ + self._key_pressed: + gtk.gdk.keyboard_ungrab(time=0L) + + if self._key_pressed == 'f': + self._shell.get_frame().notify_key_release() + elif self._key_pressed == '0x93': + self._shell.get_frame().notify_key_release() + + return True + + return False def _toggle_console_visibility_cb(self): bus = dbus.SessionBus() -- cgit v0.9.1