Refactored global key handling and frame logic.
This commit is contained in:
parent
30ee6768a2
commit
ebe043a4d2
@ -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
|
||||||
|
@ -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,37 +120,20 @@ 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);
|
|
||||||
g_free(key);
|
|
||||||
|
|
||||||
XUngrabKeyboard (GDK_WINDOW_XDISPLAY (grabber->root), 0L);
|
|
||||||
|
|
||||||
return GDK_FILTER_REMOVE;
|
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;
|
|
||||||
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_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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
|
||||||
else:
|
|
||||||
self._show_frame()
|
|
||||||
|
|
||||||
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.show()
|
||||||
self._frame.mode = MODE_KEYBOARD
|
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 _hide_frame(self):
|
def key_release(self):
|
||||||
if self._hide_sid != 0:
|
if self._state == _KeyListener._SHOWN_PRESSED:
|
||||||
gobject.source_remove(self._hide_sid)
|
self._state = _KeyListener._SHOWN_RELEASED
|
||||||
self._hide_sid = gobject.timeout_add(
|
elif self._state == _KeyListener._SHOWN_REPEAT:
|
||||||
100, self._hide_frame_timeout_cb)
|
self._frame.hide()
|
||||||
|
self._state = _KeyListener._HIDDEN
|
||||||
|
|
||||||
class Frame(object):
|
class Frame(object):
|
||||||
def __init__(self, shell):
|
def __init__(self, shell):
|
||||||
|
@ -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,17 +171,43 @@ 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):
|
||||||
|
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)
|
||||||
|
|
||||||
action = _actions_table[key]
|
action = _actions_table[key]
|
||||||
method = getattr(self, 'handle_' + action)
|
method = getattr(self, 'handle_' + action)
|
||||||
method()
|
method()
|
||||||
|
|
||||||
def _key_released_cb(self, grabber, key):
|
return True
|
||||||
if key == '<shft><alt>F9':
|
|
||||||
|
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()
|
self._shell.get_frame().notify_key_release()
|
||||||
elif key == '0x93':
|
elif self._key_pressed == '0x93':
|
||||||
self._shell.get_frame().notify_key_release()
|
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()
|
||||||
proxy = bus.get_object('org.laptop.sugar.Console',
|
proxy = bus.get_object('org.laptop.sugar.Console',
|
||||||
|
Loading…
Reference in New Issue
Block a user