Commit 3117d231 authored by Jens Granseuer's avatar Jens Granseuer Committed by Jens Granseuer

Extract some functionality used by several plugins into a separate shared

2008-04-13  Jens Granseuer  <jensgr@gmx.net>

	Extract some functionality used by several plugins into a separate
	shared helper library (bug #525426).

	* configure.ac:
	* plugins/Makefile.am:
	* plugins/common/Makefile.am:
	* plugins/common/gsd-keygrab.c:
	* plugins/common/gsd-keygrab.h:
	* plugins/common/eggaccelerators.c:
	* plugins/common/eggaccelerators.h: new shared components

	* plugins/keybindings/Makefile.am:
	* plugins/keybindings/eggaccelerators.c:
	* plugins/keybindings/eggaccelerators.h:
	* plugins/keybindings/gsd-keybindings-manager.c:
	(binding_register_keys), (keybindings_filter):
	* plugins/media-keys/Makefile.am:
	* plugins/media-keys/actions/Makefile.am:
	* plugins/media-keys/actions/acme.h:
	* plugins/media-keys/eggaccelerators.c:
	* plugins/media-keys/eggaccelerators.h:
	* plugins/media-keys/gsd-media-keys-manager.c: (update_kbd_cb),
	(init_kbd), (acme_filter_events):
	make keybindings and media-keys plugins use the shared components

svn path=/trunk/; revision=306
parent 4d592fa9
2008-04-13 Jens Granseuer <jensgr@gmx.net>
Extract some functionality used by several plugins into a separate
shared helper library (bug #525426).
* configure.ac:
* plugins/Makefile.am:
* plugins/common/Makefile.am:
* plugins/common/gsd-keygrab.c:
* plugins/common/gsd-keygrab.h:
* plugins/common/eggaccelerators.c:
* plugins/common/eggaccelerators.h: new shared components
* plugins/keybindings/Makefile.am:
* plugins/keybindings/eggaccelerators.c:
* plugins/keybindings/eggaccelerators.h:
* plugins/keybindings/gsd-keybindings-manager.c:
(binding_register_keys), (keybindings_filter):
* plugins/media-keys/Makefile.am:
* plugins/media-keys/actions/Makefile.am:
* plugins/media-keys/actions/acme.h:
* plugins/media-keys/eggaccelerators.c:
* plugins/media-keys/eggaccelerators.h:
* plugins/media-keys/gsd-media-keys-manager.c: (update_kbd_cb),
(init_kbd), (acme_filter_events):
make keybindings and media-keys plugins use the shared components
2008-04-13 Sergey Udaltsov <svu@gnome.org>
* plugins/keyboard/gsd-keyboard-xkb.c: dropped gconf backup
......
......@@ -56,8 +56,6 @@ PKG_CHECK_MODULES(SETTINGS_DAEMON,
dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
libgnome-2.0
)
AC_SUBST(SETTINGS_DAEMON_CFLAGS)
AC_SUBST(SETTINGS_DAEMON_LIBS)
PKG_CHECK_MODULES(SETTINGS_PLUGIN,
gtk+-2.0 >= $GTK_REQUIRED_VERSION
......@@ -67,8 +65,6 @@ PKG_CHECK_MODULES(SETTINGS_PLUGIN,
libglade-2.0 >= 2.0.0
dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
)
AC_SUBST(SETTINGS_PLUGIN_CFLAGS)
AC_SUBST(SETTINGS_PLUGIN_LIBS)
PKG_CHECK_MODULES(GNOME, libgnome-2.0 libgnomeui-2.0)
PKG_CHECK_MODULES(LIBBACKGROUND, glib-2.0 gobject-2.0 gdk-2.0 gconf-2.0)
......@@ -406,6 +402,7 @@ plugins/a11y-keyboard/Makefile
plugins/background/Makefile
plugins/background/libbackground/Makefile
plugins/clipboard/Makefile
plugins/common/Makefile
plugins/dummy/Makefile
plugins/font/Makefile
plugins/housekeeping/Makefile
......
NULL =
SUBDIRS = \
common \
a11y-keyboard \
background \
clipboard \
......
noinst_LTLIBRARIES = libcommon.la
libcommon_la_SOURCES = \
eggaccelerators.c \
eggaccelerators.h \
gsd-keygrab.c \
gsd-keygrab.h
libcommon_la_CPPFLAGS = \
$(AM_CPPFLAGS)
libcommon_la_CFLAGS = \
$(SETTINGS_PLUGIN_CFLAGS) \
$(AM_CFLAGS)
libcommon_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libcommon_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2001-2003 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
* Copyright (C) 2008 Jens Granseuer <jensgr@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "gsd-keygrab.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 GSD_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 GSD_USED_MODS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)
static gboolean
grab_key_real (guint keycode,
GdkWindow *root,
gboolean grab,
int mask)
{
gdk_error_trap_push ();
if (grab) {
XGrabKey (GDK_DISPLAY (),
keycode,
mask,
GDK_WINDOW_XID (root),
True,
GrabModeAsync,
GrabModeAsync);
} else {
XUngrabKey (GDK_DISPLAY (),
keycode,
mask,
GDK_WINDOW_XID (root));
}
gdk_flush ();
return gdk_error_trap_pop () == 0;
}
/* Grab the key. In order to ignore GSD_IGNORED_MODS we need to grab
* all combinations of the ignored modifiers and those actually used
* for the binding (if any).
*
* inspired by all_combinations from gnome-panel/gnome-panel/global-keys.c */
#define N_BITS 32
void
grab_key (Key *key,
gboolean grab,
GSList *screens)
{
int indexes[N_BITS]; /* indexes of bits we need to flip */
int i;
int bit;
int bits_set_cnt;
int uppervalue;
guint mask = GSD_IGNORED_MODS & ~key->state & GDK_MODIFIER_MASK;
bit = 0;
/* store the indexes of all set bits in mask in the array */
for (i = 0; mask; ++i, mask >>= 1) {
if (mask & 0x1) {
indexes[bit++] = i;
}
}
bits_set_cnt = bit;
uppervalue = 1 << bits_set_cnt;
/* grab all possible modifier combinations for our mask */
for (i = 0; i < uppervalue; ++i) {
GSList *l;
int j;
int result = 0;
/* map bits in the counter to those in the mask */
for (j = 0; j < bits_set_cnt; ++j) {
if (i & (1 << j)) {
result |= (1 << indexes[j]);
}
}
for (l = screens; l; l = l->next) {
GdkScreen *screen = l->data;
if (!grab_key_real (key->keycode,
gdk_screen_get_root_window (screen),
grab,
result | key->state)) {
g_warning ("Grab failed, another application may already have access to key '%u'",
key->keycode);
return;
}
}
}
}
gboolean
match_key (Key *key, XEvent *event)
{
return (key != NULL
&& key->keycode == event->xkey.keycode
&& key->state == (event->xkey.state & GSD_USED_MODS));
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2008 Jens Granseuer <jensgr@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GSD_COMMON_KEYGRAB_H
#define __GSD_COMMON_KEYGRAB_H
G_BEGIN_DECLS
#include <glib.h>
#include <X11/keysym.h>
typedef struct {
guint keysym;
guint state;
guint keycode;
} Key;
void grab_key (Key *key,
gboolean grab,
GSList *screens);
gboolean match_key (Key *key,
XEvent *event);
G_END_DECLS
#endif /* __GSD_COMMON_KEYGRAB_H */
......@@ -9,12 +9,11 @@ libkeybindings_la_SOURCES = \
gsd-keybindings-plugin.c \
gsd-keybindings-manager.h \
gsd-keybindings-manager.c \
eggaccelerators.h \
eggaccelerators.c \
$(NULL)
libkeybindings_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
......@@ -27,7 +26,8 @@ libkeybindings_la_LDFLAGS = \
$(NULL)
libkeybindings_la_LIBADD = \
$(SETTINGS_PLUGIN_LIBS) \
$(top_builddir)/plugins/common/libcommon.la \
$(SETTINGS_PLUGIN_LIBS) \
$(NULL)
plugin_in_files = \
......
......@@ -41,27 +41,13 @@
#include "gnome-settings-profile.h"
#include "gsd-keybindings-manager.h"
#include "gsd-keygrab.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)
#define GCONF_BINDING_DIR "/desktop/gnome/keybindings"
#define GSD_KEYBINDINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBINDINGS_MANAGER, GsdKeybindingsManagerPrivate))
typedef struct {
guint keysym;
guint state;
guint keycode;
} Key;
typedef struct {
char *binding_str;
char *action;
......@@ -257,7 +243,6 @@ bindings_get_entry (GsdKeybindingsManager *manager,
return TRUE;
}
static gboolean
key_already_used (GsdKeybindingsManager *manager,
Binding *binding)
......@@ -276,86 +261,6 @@ key_already_used (GsdKeybindingsManager *manager,
return FALSE;
}
static void
grab_key (GdkWindow *root,
Key *key,
int result,
gboolean grab)
{
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 ();
if (gdk_error_trap_pop ()) {
g_warning (_("It seems that another application already has access to key '%u'."),
key->keycode);
}
}
/* Grab the key. In order to ignore IGNORED_MODS we need to grab
* all combinations of the ignored modifiers and those actually used
* for the binding (if any).
*
* inspired by all_combinations from gnome-panel/gnome-panel/global-keys.c */
#define N_BITS 32
static void
do_grab (GsdKeybindingsManager *manager,
gboolean grab,
Key *key)
{
int indexes[N_BITS]; /* indexes of bits we need to flip */
int i;
int bit;
int bits_set_cnt;
int uppervalue;
guint mask = IGNORED_MODS & ~key->state & GDK_MODIFIER_MASK;
bit = 0;
/* store the indices of all set bits in mask in the array */
for (i = 0; mask; ++i, mask >>= 1) {
if (mask & 0x1) {
indexes[bit++] = i;
}
}
bits_set_cnt = bit;
uppervalue = 1 << bits_set_cnt;
/* grab all possible modifier combinations for our mask */
for (i = 0; i < uppervalue; ++i) {
GSList *l;
int j, result = 0;
/* map bits in the counter to those in the mask */
for (j = 0; j < bits_set_cnt; ++j) {
if (i & (1<<j)) {
result |= (1<<indexes[j]);
}
}
for (l = manager->priv->screens; l ; l = l->next) {
GdkScreen *screen = l->data;
grab_key (gdk_screen_get_root_window (screen),
key,
result,
grab);
}
}
}
static void
binding_register_keys (GsdKeybindingsManager *manager)
{
......@@ -372,15 +277,15 @@ binding_register_keys (GsdKeybindingsManager *manager)
/* Ungrab key if it changed and not clashing with previously set binding */
if (! key_already_used (manager, binding)) {
if (binding->previous_key.keycode) {
do_grab (manager, FALSE, &binding->previous_key);
grab_key (&binding->previous_key, FALSE, manager->priv->screens);
}
do_grab (manager, TRUE, &binding->key);
grab_key (&binding->key, TRUE, manager->priv->screens);
binding->previous_key.keysym = binding->key.keysym;
binding->previous_key.state = binding->key.state;
binding->previous_key.keycode = binding->key.keycode;
} else
g_warning (_("Key Binding (%s) is already in use"), binding->binding_str);
g_warning ("Key binding (%s) is already in use", binding->binding_str);
}
}
gdk_flush ();
......@@ -471,23 +376,17 @@ keybindings_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
GsdKeybindingsManager *manager)
{
XEvent *xevent = (XEvent *)gdk_xevent;
guint keycode;
guint state;
XEvent *xevent = (XEvent *) gdk_xevent;
GSList *li;
if (xevent->type != KeyPress) {
return GDK_FILTER_CONTINUE;
}
keycode = xevent->xkey.keycode;
state = xevent->xkey.state;
for (li = manager->priv->binding_list; li != NULL; li = li->next) {
Binding *binding = (Binding*) li->data;
Binding *binding = (Binding *) li->data;
if (keycode == binding->key.keycode &&
(state & USED_MODS) == binding->key.state) {
if (match_key (&binding->key, xevent)) {
GError *error = NULL;
gboolean retval;
gchar **argv = NULL;
......
......@@ -29,13 +29,12 @@ libmedia_keys_la_SOURCES = \
gsd-media-keys-manager.c \
gsd-media-keys-window.h \
gsd-media-keys-window.c \
eggaccelerators.h \
eggaccelerators.c \
$(BUILT_SOURCES) \
$(NULL)
libmedia_keys_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-I$(top_builddir)/plugins/media-keys/actions \
-DPIXMAPDIR=\""$(pkgdatadir)"\" \
-DGLADEDIR=\""$(pkgdatadir)"\" \
......@@ -50,6 +49,7 @@ libmedia_keys_la_LDFLAGS = \
$(GSD_PLUGIN_LDFLAGS)
libmedia_keys_la_LIBADD = \
$(top_builddir)/plugins/common/libcommon.la \
$(top_builddir)/plugins/media-keys/actions/libacme.la \
$(SETTINGS_PLUGIN_LIBS) \
$(XF86MISC_LIBS) \
......@@ -94,14 +94,13 @@ test_media_keys_SOURCES = \
gsd-media-keys-manager.h \
gsd-media-keys-window.h \
gsd-media-keys-window.c \
eggaccelerators.h \
eggaccelerators.c \
test-media-keys.c \
$(BUILT_SOURCES) \
$(NULL)
test_media_keys_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-I$(top_builddir)/plugins/media-keys/actions \
-DPIXMAPDIR=\""$(pkgdatadir)"\" \
-DGLADEDIR=\""$(pkgdatadir)"\" \
......@@ -114,6 +113,7 @@ test_media_keys_CFLAGS = \
test_media_keys_LDADD = \
$(top_builddir)/gnome-settings-daemon/libgsd-profile.la \
$(top_builddir)/plugins/common/libcommon.la \
$(top_builddir)/plugins/media-keys/actions/libacme.la \
$(SETTINGS_DAEMON_LIBS) \
$(SETTINGS_PLUGIN_LIBS) \
......
......@@ -12,6 +12,7 @@ libacme_la_SOURCES = \
libacme_la_CPPFLAGS = \
-I$(top_srcdir)/gnome-settings-daemon \
-I$(top_srcdir)/plugins/common \
-DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
$(AM_CPPFLAGS)
......
......@@ -21,6 +21,8 @@
#ifndef __ACME_H__
#define __ACME_H__
#include "gsd-keygrab.h"
#define GCONF_BINDING_DIR "/apps/gnome_settings_daemon/keybindings"
#define GCONF_MISC_DIR "/apps/gnome_settings_daemon"
......@@ -47,12 +49,6 @@ enum {
HANDLED_KEYS
};
typedef struct {
guint keysym;
guint state;
guint keycode;
} Key;
static struct {
int key_type;
const char *gconf_key;
......
/* eggaccelerators.c
* Copyright (C) 2002 Red Hat, Inc.; Copyright 1998, 2001 Tim Janik
* Developed by Havoc Pennington, Tim Janik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "eggaccelerators.h"
#include <stdlib.h>
#include <string.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkaccelgroup.h>
enum
{
EGG_MODMAP_ENTRY_SHIFT = 0,
EGG_MODMAP_ENTRY_LOCK = 1,
EGG_MODMAP_ENTRY_CONTROL = 2,
EGG_MODMAP_ENTRY_MOD1 = 3,
EGG_MODMAP_ENTRY_MOD2 = 4,
EGG_MODMAP_ENTRY_MOD3 = 5,
EGG_MODMAP_ENTRY_MOD4 = 6,
EGG_MODMAP_ENTRY_MOD5 = 7,
EGG_MODMAP_ENTRY_LAST = 8
};
#define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x))
typedef struct
{
EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST];
} EggModmap;
const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap);
static inline gboolean
is_alt (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 'a' || string[1] == 'A') &&
(string[2] == 'l' || string[2] == 'L') &&
(string[3] == 't' || string[3] == 'T') &&
(string[4] == '>'));
}
static inline gboolean
is_ctl (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 'c' || string[1] == 'C') &&
(string[2] == 't' || string[2] == 'T') &&
(string[3] == 'l' || string[3] == 'L') &&
(string[4] == '>'));
}
static inline gboolean
is_modx (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 'm' || string[1] == 'M') &&
(string[2] == 'o' || string[2] == 'O') &&
(string[3] == 'd' || string[3] == 'D') &&
(string[4] >= '1' && string[4] <= '5') &&
(string[5] == '>'));
}
static inline gboolean
is_ctrl (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 'c' || string[1] == 'C') &&
(string[2] == 't' || string[2] == 'T') &&
(string[3] == 'r' || string[3] == 'R') &&
(string[4] == 'l' || string[4] == 'L') &&
(string[5] == '>'));
}
static inline gboolean
is_shft (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 's' || string[1] == 'S') &&
(string[2] == 'h' || string[2] == 'H') &&
(string[3] == 'f' || string[3] == 'F') &&
(string[4] == 't' || string[4] == 'T') &&
(string[5] == '>'));
}
static inline gboolean
is_shift (const gchar *string)
{
return ((string[0] == '<') &&
(string[1] == 's' || string[1] == 'S') &&
(string[2] == 'h' ||