Refactored global key handling and frame logic.

This commit is contained in:
Tomeu Vizoso 2007-03-17 14:30:23 +01:00
parent 30ee6768a2
commit ebe043a4d2
6 changed files with 105 additions and 97 deletions

View File

@ -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 ;; From sugar-push-scroller.h
(define-function push_scroller_get_type (define-function push_scroller_get_type

View File

@ -23,6 +23,7 @@
#include "sugar-key-grabber.h" #include "sugar-key-grabber.h"
#include "eggaccelerators.h" #include "eggaccelerators.h"
#include "sugar-marshal.h"
/* we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what /* we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what
these modifiers mean these modifiers mean
@ -81,49 +82,31 @@ sugar_key_grabber_class_init(SugarKeyGrabberClass *grabber_class)
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (SugarKeyGrabberClass, key_pressed), G_STRUCT_OFFSET (SugarKeyGrabberClass, key_pressed),
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__STRING, sugar_marshal_BOOLEAN__UINT_UINT,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN, 2,
G_TYPE_STRING); G_TYPE_UINT,
G_TYPE_UINT);
signals[KEY_RELEASED] = g_signal_new ("key-released", signals[KEY_RELEASED] = g_signal_new ("key-released",
G_TYPE_FROM_CLASS (grabber_class), G_TYPE_FROM_CLASS (grabber_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (SugarKeyGrabberClass, key_released), G_STRUCT_OFFSET (SugarKeyGrabberClass, key_released),
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__STRING, sugar_marshal_BOOLEAN__UINT_UINT,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN, 2,
G_TYPE_STRING); G_TYPE_UINT,
G_TYPE_UINT);
} }
static char * char *
get_key_from_event(SugarKeyGrabber *grabber, XEvent *xev) sugar_key_grabber_get_key(SugarKeyGrabber *grabber, guint keycode, guint state)
{ {
GList *l; 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) { for (l = grabber->keys; l != NULL; l = l->next) {
Key *keyinfo = (Key *)l->data; Key *keyinfo = (Key *)l->data;
if (keyinfo->keycode == keycode) { if ((keyinfo->keycode == keycode) &&
if (xev->type == KeyPress && ((state & USED_MODS) == keyinfo->state)) {
(state & USED_MODS) == keyinfo->state) { return g_strdup(keyinfo->key);
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);
}
}
} }
} }
@ -137,36 +120,19 @@ filter_events(GdkXEvent *xevent, GdkEvent *event, gpointer data)
XEvent *xev = (XEvent *)xevent; XEvent *xev = (XEvent *)xevent;
if (xev->type == KeyRelease) { if (xev->type == KeyRelease) {
char *key; int return_value;
g_signal_emit (grabber, signals[KEY_RELEASED], 0, xev->xkey.keycode,
key = get_key_from_event(grabber, xevent); xev->xkey.state, &return_value);
if (key) { if(return_value)
g_signal_emit (grabber, signals[KEY_RELEASED], 0, key); return GDK_FILTER_REMOVE;
g_free(key);
XUngrabKeyboard (GDK_WINDOW_XDISPLAY (grabber->root), 0L);
return GDK_FILTER_REMOVE;
}
} }
if (xev->type == KeyPress) { if (xev->type == KeyPress) {
char *key; int return_value;
g_signal_emit (grabber, signals[KEY_PRESSED], 0, xev->xkey.keycode,
key = get_key_from_event(grabber, xevent); xev->xkey.state, &return_value);
if (key) { if(return_value)
grabber->last_key_pressed = xev->xkey.keycode; return GDK_FILTER_REMOVE;
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;
}
} }
return GDK_FILTER_CONTINUE; return GDK_FILTER_CONTINUE;
@ -180,8 +146,6 @@ sugar_key_grabber_init(SugarKeyGrabber *grabber)
screen = gdk_screen_get_default(); screen = gdk_screen_get_default();
grabber->root = gdk_screen_get_root_window(screen); grabber->root = gdk_screen_get_root_window(screen);
grabber->keys = NULL; grabber->keys = NULL;
grabber->last_key_pressed = 0;
grabber->last_key_pressed_modifier = 0;
gdk_window_add_filter(grabber->root, filter_events, grabber); gdk_window_add_filter(grabber->root, filter_events, grabber);
} }

View File

@ -39,22 +39,25 @@ struct _SugarKeyGrabber {
GdkWindow *root; GdkWindow *root;
GList *keys; GList *keys;
guint last_key_pressed;
guint last_key_pressed_modifier;
}; };
struct _SugarKeyGrabberClass { struct _SugarKeyGrabberClass {
GObjectClass base_class; GObjectClass base_class;
void (* key_pressed) (SugarKeyGrabber *grabber, gboolean (* key_pressed) (SugarKeyGrabber *grabber,
const char *key); guint keycode,
void (* key_released) (SugarKeyGrabber *grabber, guint state);
const char *key); gboolean (* key_released) (SugarKeyGrabber *grabber,
guint keycode,
guint state);
}; };
GType sugar_key_grabber_get_type (void); GType sugar_key_grabber_get_type (void);
void sugar_key_grabber_grab (SugarKeyGrabber *grabber, void sugar_key_grabber_grab (SugarKeyGrabber *grabber,
const char *key); const char *key);
char *sugar_key_grabber_get_key (SugarKeyGrabber *grabber,
guint keycode,
guint state);
G_END_DECLS G_END_DECLS

View File

@ -2,3 +2,4 @@ VOID:OBJECT,STRING,LONG,LONG
VOID:OBJECT,LONG VOID:OBJECT,LONG
VOID:OBJECT VOID:OBJECT
BOOLEAN:BOXED BOOLEAN:BOXED
BOOLEAN:UINT,UINT

View File

@ -13,6 +13,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import gtk import gtk
import gobject import gobject
@ -77,38 +78,36 @@ class _MouseListener(object):
_FRAME_HIDING_DELAY, self._hide_frame_timeout_cb) _FRAME_HIDING_DELAY, self._hide_frame_timeout_cb)
class _KeyListener(object): class _KeyListener(object):
_HIDDEN = 1
_SHOWN_PRESSED = 2
_SHOWN_REPEAT = 3
_SHOWN_RELEASED = 4
def __init__(self, frame): def __init__(self, frame):
self._frame = frame self._frame = frame
self._hide_sid = 0 self._state = _KeyListener._HIDDEN
def key_press(self): def key_press(self):
if self._frame.mode != MODE_NONE and \ if self._frame.mode != MODE_NONE and \
self._frame.mode != MODE_KEYBOARD: self._frame.mode != MODE_KEYBOARD:
return return
if self._frame.visible: if self._state == _KeyListener._HIDDEN:
self._hide_frame() self._frame.show()
else: self._frame.mode = MODE_KEYBOARD
self._show_frame() 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): def key_release(self):
self._hide_frame() if self._state == _KeyListener._SHOWN_PRESSED:
self._state = _KeyListener._SHOWN_RELEASED
def _hide_frame_timeout_cb(self): elif self._state == _KeyListener._SHOWN_REPEAT:
self._frame.hide() self._frame.hide()
return False self._state = _KeyListener._HIDDEN
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)
class Frame(object): class Frame(object):
def __init__(self, shell): def __init__(self, shell):

View File

@ -1,8 +1,10 @@
import os import os
import signal import signal
import logging
import dbus import dbus
import gobject import gobject
import gtk
from sugar import env from sugar import env
from hardware import hardwaremanager from hardware import hardwaremanager
@ -46,6 +48,9 @@ class KeyHandler(object):
self._shell = shell self._shell = shell
self._audio_manager = hardwaremanager.get_audio_manager() self._audio_manager = hardwaremanager.get_audio_manager()
self._screen_rotation = 0 self._screen_rotation = 0
self._key_pressed = None
self._keycode_pressed = 0
self._keystate_pressed = 0
self._key_grabber = KeyGrabber() self._key_grabber = KeyGrabber()
self._key_grabber.connect('key-pressed', self._key_grabber.connect('key-pressed',
@ -166,16 +171,42 @@ class KeyHandler(object):
# FIXME: finish alt+tab support # FIXME: finish alt+tab support
pass pass
def _key_pressed_cb(self, grabber, key): def _key_pressed_cb(self, grabber, keycode, state):
action = _actions_table[key] key = grabber.get_key(keycode, state)
method = getattr(self, 'handle_' + action) if key:
method() 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): action = _actions_table[key]
if key == '<shft><alt>F9': method = getattr(self, 'handle_' + action)
self._shell.get_frame().notify_key_release() method()
elif key == '0x93':
self._shell.get_frame().notify_key_release() 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): def _toggle_console_visibility_cb(self):
bus = dbus.SessionBus() bus = dbus.SessionBus()