From 6e920265ad6c21c96bc2c78c783031d7a324c3bc Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Fri, 25 Aug 2006 14:03:48 +0200 Subject: [PATCH] Complete the keybindings stuff and use it for the home page --- bindings/globalkeys/Makefile.am | 1 + bindings/globalkeys/sugar-key-grabber.c | 170 +++++++++++++++++------- configure.ac | 1 + shell/Makefile.am | 1 - shell/Shell.py | 38 +++--- shell/data/kbdconfig | 6 +- shell/sugar-zoom | 14 -- 7 files changed, 146 insertions(+), 85 deletions(-) delete mode 100644 shell/sugar-zoom diff --git a/bindings/globalkeys/Makefile.am b/bindings/globalkeys/Makefile.am index cfedfbe0..210550a6 100644 --- a/bindings/globalkeys/Makefile.am +++ b/bindings/globalkeys/Makefile.am @@ -1,4 +1,5 @@ INCLUDES = \ + $(WARN_CFLAGS) \ $(PYTHON_INCLUDES) \ $(PYGTK_CFLAGS) \ $(GLOBALKEYS_CFLAGS) diff --git a/bindings/globalkeys/sugar-key-grabber.c b/bindings/globalkeys/sugar-key-grabber.c index bf563b46..7b006858 100644 --- a/bindings/globalkeys/sugar-key-grabber.c +++ b/bindings/globalkeys/sugar-key-grabber.c @@ -19,45 +19,111 @@ #include #include #include +#include #include "sugar-key-grabber.h" +#include "eggaccelerators.h" /* we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what these modifiers mean these are the mods whose combinations are bound by the keygrabbing code */ #define IGNORED_MODS (0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | \ GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) +/* these are the ones we actually use for global keys, we always only check + * for these set */ +#define USED_MODS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) struct _SugarKeyGrabber { GObject base_instance; GdkWindow *root; + GList *keys; }; struct _SugarKeyGrabberClass { GObjectClass base_class; + + void (* key_pressed) (SugarKeyGrabber *grabber, + const char *key); }; +enum { + KEY_PRESSED, + N_SIGNALS +}; + +typedef struct { + char *key; + guint keysym; + guint state; + guint keycode; +} Key; + G_DEFINE_TYPE(SugarKeyGrabber, sugar_key_grabber, G_TYPE_OBJECT) +static guint signals[N_SIGNALS]; + static void -sugar_key_grabber_class_init(SugarKeyGrabberClass *key_grabber_class) -{ +free_key_info(Key *key_info) +{ + g_free(key_info->key); + g_free(key_info); +} + +static void +sugar_key_grabber_dispose (GObject *object) +{ + SugarKeyGrabber *grabber = SUGAR_KEY_GRABBER(object); + + if (grabber->keys) { + g_list_foreach(grabber->keys, (GFunc)free_key_info, NULL); + g_list_free(grabber->keys); + grabber->keys = NULL; + } +} + +static void +sugar_key_grabber_class_init(SugarKeyGrabberClass *grabber_class) +{ + GObjectClass *g_object_class = G_OBJECT_CLASS (grabber_class); + + g_object_class->dispose = sugar_key_grabber_dispose; + + signals[KEY_PRESSED] = g_signal_new ("key-pressed", + G_TYPE_FROM_CLASS (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); } static GdkFilterReturn filter_events(GdkXEvent *xevent, GdkEvent *event, gpointer data) { - SugarKeyGrabber *grabber = (SugarKeyGrabber *)data; + SugarKeyGrabber *grabber = (SugarKeyGrabber *)data; XEvent *xev = (XEvent *)xevent; - XAnyEvent *xanyev = (XAnyEvent *)xevent; - guint keycode, state; - int i; - keycode = xev->xkey.keycode; - state = xev->xkey.state; + if (xev->type == KeyPress) { + GList *l; + guint keycode, state; - g_print("KeyCode %d", keycode); + keycode = xev->xkey.keycode; + state = xev->xkey.state; + + for (l = grabber->keys; l != NULL; l = l->next) { + Key *keyinfo = (Key *)l->data; + if (keyinfo->keycode == keycode && + (state & USED_MODS) == keyinfo->state) { + g_signal_emit (grabber, signals[KEY_PRESSED], + 0, keyinfo->key); + return GDK_FILTER_REMOVE; + } + } + } + + return GDK_FILTER_CONTINUE; } static void @@ -67,60 +133,74 @@ sugar_key_grabber_init(SugarKeyGrabber *grabber) screen = gdk_screen_get_default(); grabber->root = gdk_screen_get_root_window(screen); + grabber->keys = NULL; gdk_window_add_filter(grabber->root, filter_events, grabber); } +/* grab_key and grab_key_real are from + * gnome-control-center/gnome-settings-daemon/gnome-settings-multimedia-keys.c + */ -/* inspired from all_combinations from gnome-panel/gnome-panel/global-keys.c */ -#define N_BITS 32 -static int -get_modifier(guint state) +static gboolean +grab_key_real (Key *key, GdkWindow *root, gboolean grab, int result) { - int indexes[N_BITS];/*indexes of bits we need to flip*/ - int i, bit, bits_set_cnt; - int uppervalue; - int result = 0; - guint mask_to_traverse = IGNORED_MODS & ~ state; + gdk_error_trap_push (); + if (grab) + XGrabKey (GDK_DISPLAY(), key->keycode, (result | key->state), + GDK_WINDOW_XID (root), True, GrabModeAsync, GrabModeAsync); + else + XUngrabKey(GDK_DISPLAY(), key->keycode, (result | key->state), + GDK_WINDOW_XID (root)); + gdk_flush (); - bit = 0; - for (i = 0; i < N_BITS; i++) { - if (mask_to_traverse & (1<state; - for (j = 0; j < bits_set_cnt; j++) { - if (i & (1<root, grab, result) == FALSE) + return; + } } void sugar_key_grabber_grab(SugarKeyGrabber *grabber, const char *key) { - guint keysym; - guint state; - guint keycode; + Key *keyinfo; - gdk_error_trap_push (); + keyinfo = g_new0 (Key, 1); + keyinfo->key = g_strdup(key); + egg_accelerator_parse_virtual (key, &keyinfo->keysym, + &keyinfo->keycode, &keyinfo->state); - egg_accelerator_parse_virtual (key, &keysym, &keycode, &state); + grab_key(grabber, keyinfo, TRUE); - XGrabKey (GDK_DISPLAY(), keycode, get_modifier(state), - GDK_WINDOW_XID (grabber->root), True, - GrabModeAsync, GrabModeAsync); - - gdk_flush (); - - gdk_error_trap_pop (); + grabber->keys = g_list_append(grabber->keys, keyinfo); } diff --git a/configure.ac b/configure.ac index 4270f39e..cb3a8bbd 100644 --- a/configure.ac +++ b/configure.ac @@ -3,6 +3,7 @@ AC_INIT([Sugar],[0.22],[],[sugar]) AC_PREREQ([2.59]) GNOME_COMMON_INIT +GNOME_COMPILE_WARNINGS AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) diff --git a/shell/Makefile.am b/shell/Makefile.am index 7a9eb50e..bc87e243 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -6,7 +6,6 @@ bin_SCRIPTS = \ sugar-activity-factory \ sugar-console \ sugar-people \ - sugar-zoom \ sugar-presence-service sugardir = $(pkgdatadir)/shell diff --git a/shell/Shell.py b/shell/Shell.py index 4c23a32e..f5ac18ec 100755 --- a/shell/Shell.py +++ b/shell/Shell.py @@ -41,14 +41,6 @@ class ShellDbusService(dbus.service.Object): def show_console(self): gobject.idle_add(self.__show_console_idle) - @dbus.service.method('com.redhat.Sugar.Shell') - def zoom_in(self): - self._shell.zoom_in() - - @dbus.service.method('com.redhat.Sugar.Shell') - def zoom_out(self): - self._shell.zoom_out() - class Shell(gobject.GObject): ZOOM_MESH = 0 ZOOM_FRIENDS = 1 @@ -66,7 +58,11 @@ class Shell(gobject.GObject): gobject.GObject.__init__(self) key_grabber = KeyGrabber() - key_grabber.grab('F8') + key_grabber.connect('key-pressed', self.__global_key_pressed_cb) + key_grabber.grab('F1') + key_grabber.grab('F2') + key_grabber.grab('F3') + key_grabber.grab('F4') self._screen = wnck.screen_get_default() self._hosts = {} @@ -87,6 +83,16 @@ class Shell(gobject.GObject): else: self.start() + def __global_key_pressed_cb(self, grabber, key): + if key == 'F1': + self.set_zoom_level(Shell.ZOOM_ACTIVITY) + elif key == 'F2': + self.set_zoom_level(Shell.ZOOM_HOME) + elif key == 'F3': + self.set_zoom_level(Shell.ZOOM_FRIENDS) + elif key == 'F4': + self.set_zoom_level(Shell.ZOOM_MESH) + def __first_time_dialog_destroy_cb(self, dialog): self.start() @@ -105,7 +111,7 @@ class Shell(gobject.GObject): home_model = HomeModel() self._home_window.set_model(home_model) - self._set_zoom_level(Shell.ZOOM_HOME) + self.set_zoom_level(Shell.ZOOM_HOME) self._panel_manager = PanelManager(self) @@ -204,7 +210,7 @@ class Shell(gobject.GObject): def get_chat_controller(self): return self._chat_controller - def _set_zoom_level(self, level): + def set_zoom_level(self, level): self._zoom_level = level if level == Shell.ZOOM_ACTIVITY: @@ -218,13 +224,3 @@ class Shell(gobject.GObject): self._home_window.set_view(HomeWindow.FRIENDS_VIEW) elif level == Shell.ZOOM_MESH: self._home_window.set_view(HomeWindow.MESH_VIEW) - - def zoom_in(self): - level = self._zoom_level + 1 - if level <= Shell.ZOOM_ACTIVITY: - self._set_zoom_level(level) - - def zoom_out(self): - level = self._zoom_level - 1 - if level >= Shell.ZOOM_MESH: - self._set_zoom_level(level) diff --git a/shell/data/kbdconfig b/shell/data/kbdconfig index 71d8032a..c9f8b7a9 100644 --- a/shell/data/kbdconfig +++ b/shell/data/kbdconfig @@ -5,7 +5,5 @@ n=next p=prev c=close -f1=!sugar-zoom out -f2=!sugar-zoom in -f3=!sugar-people -f4=!sugar-activity org.sugar.Terminal +f5=!sugar-people +f6=!sugar-activity org.sugar.Terminal diff --git a/shell/sugar-zoom b/shell/sugar-zoom deleted file mode 100644 index ee435170..00000000 --- a/shell/sugar-zoom +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/python -import sys - -import dbus -import dbus.glib - -bus = dbus.SessionBus() -proxy_obj = bus.get_object('com.redhat.Sugar.Shell', '/com/redhat/Sugar/Shell') -shell = dbus.Interface(proxy_obj, 'com.redhat.Sugar.Shell') - -if sys.argv[1] == 'in': - shell.zoom_in() -elif sys.argv[1] == 'out': - shell.zoom_out()