Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2007-03-17 13:30:23 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2007-03-17 13:30:23 (GMT)
commitebe043a4d20d408f04fb1a520fd5e707bbbf68db (patch)
tree5d461f12bc86afe962858775f53617cf3dc6ecb5
parent30ee6768a2049d467b6825a49745cf9552e113e3 (diff)
Refactored global key handling and frame logic.
-rw-r--r--lib/python/_sugar.defs10
-rw-r--r--lib/src/sugar-key-grabber.c84
-rw-r--r--lib/src/sugar-key-grabber.h15
-rw-r--r--lib/src/sugar-marshal.list1
-rw-r--r--shell/view/frame/frame.py43
-rw-r--r--shell/view/keyhandler.py49
6 files changed, 105 insertions, 97 deletions
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 == '<shft><alt>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 == '<alt>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()