summaryrefslogtreecommitdiff
path: root/gnome-settings-daemon/gnome-settings-keybindings.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-settings-daemon/gnome-settings-keybindings.c')
-rw-r--r--gnome-settings-daemon/gnome-settings-keybindings.c488
1 files changed, 0 insertions, 488 deletions
diff --git a/gnome-settings-daemon/gnome-settings-keybindings.c b/gnome-settings-daemon/gnome-settings-keybindings.c
deleted file mode 100644
index a6c9ce8e4..000000000
--- a/gnome-settings-daemon/gnome-settings-keybindings.c
+++ /dev/null
@@ -1,488 +0,0 @@
-#include <config.h>
-
-#include <string.h>
-#include <X11/keysym.h>
-#include <glib/gi18n.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#include "gnome-settings-daemon.h"
-#include "gnome-settings-keybindings.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"
-
-typedef struct {
- guint keysym;
- guint state;
- guint keycode;
-} Key;
-
-typedef struct {
- char *binding_str;
- char *action;
- char *gconf_key;
- Key key;
- Key previous_key;
-} Binding;
-
-static GSList *binding_list = NULL;
-static GSList *screens = NULL;
-
-static GSList *
-get_screens_list (void)
-{
- GdkDisplay *display = gdk_display_get_default();
- GSList *list = NULL;
- int i;
-
- if (gdk_display_get_n_screens (display) == 1) {
- list = g_slist_append (list, gdk_screen_get_default ());
- } else {
- for (i = 0; i < gdk_display_get_n_screens (display); i++) {
- GdkScreen *screen;
-
- screen = gdk_display_get_screen (display, i);
- if (screen != NULL) {
- list = g_slist_append (list, screen);
- }
- }
- }
-
- return list;
-}
-
-extern char **environ;
-
-static char *
-screen_exec_display_string (GdkScreen *screen)
-{
- GString *str;
- const char *old_display;
- char *retval;
- char *p;
-
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
- old_display = gdk_display_get_name (gdk_screen_get_display (screen));
-
- str = g_string_new ("DISPLAY=");
- g_string_append (str, old_display);
-
- p = strrchr (str->str, '.');
- if (p && p > strchr (str->str, ':'))
- g_string_truncate (str, p - str->str);
-
- g_string_append_printf (str, ".%d", gdk_screen_get_number (screen));
-
- retval = str->str;
-
- g_string_free (str, FALSE);
-
- return retval;
-}
-
-/**
- * get_exec_environment:
- *
- * Description: Modifies the current program environment to
- * ensure that $DISPLAY is set such that a launched application
- * inheriting this environment would appear on screen.
- *
- * Returns: a newly-allocated %NULL-terminated array of strings or
- * %NULL on error. Use g_strfreev() to free it.
- *
- * mainly ripped from egg_screen_exec_display_string in
- * gnome-panel/egg-screen-exec.c
- **/
-char **
-get_exec_environment (XEvent *xevent)
-{
- char **retval = NULL;
- int i;
- int display_index = -1;
-
- GdkScreen *screen = NULL;
-
- GdkWindow *window = gdk_xid_table_lookup (xevent->xkey.root);
-
- if (window)
- screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
-
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
- for (i = 0; environ [i]; i++)
- if (!strncmp (environ [i], "DISPLAY", 7))
- display_index = i;
-
- if (display_index == -1)
- display_index = i++;
-
- retval = g_new (char *, i + 1);
-
- for (i = 0; environ [i]; i++)
- if (i == display_index)
- retval [i] = screen_exec_display_string (screen);
- else
- retval [i] = g_strdup (environ [i]);
-
- retval [i] = NULL;
-
- return retval;
-}
-
-
-static gint
-compare_bindings (gconstpointer a, gconstpointer b)
-{
- Binding *key_a = (Binding*) a;
- char *key_b = (char*) b;
-
- return strcmp (key_b, key_a->gconf_key);
-}
-
-static gboolean
-parse_binding (Binding *binding)
-{
- g_return_val_if_fail (binding != NULL, FALSE);
-
- binding->key.keysym = 0;
- binding->key.state = 0;
-
- if (binding->binding_str == NULL ||
- binding->binding_str[0] == '\0' ||
- strcmp (binding->binding_str, "Disabled") == 0)
- return FALSE;
-
- if (egg_accelerator_parse_virtual (binding->binding_str, &binding->key.keysym, &binding->key.keycode, &binding->key.state) == FALSE)
- return FALSE;
-
- return TRUE;
-}
-
-gboolean
-bindings_get_entry (char *subdir)
-{
- GConfValue *value;
- Binding *new_binding;
- GSList *tmp_elem = NULL, *list = NULL, *li;
- char *gconf_key;
- char *action = NULL;
- char *key = NULL;
- GConfClient *client = gconf_client_get_default();
-
- g_return_val_if_fail (subdir != NULL, FALSE);
-
- /* value = gconf_entry_get_value (entry); */
- gconf_key = g_path_get_basename (subdir);
-
- if (!gconf_key)
- return FALSE;
-
- /* Get entries for this binding */
- list = gconf_client_all_entries (client, subdir, NULL);
- g_object_unref (client);
-
- for (li = list; li != NULL; li = li->next)
- {
- GConfEntry *entry = li->data;
- char *key_name = g_path_get_basename (gconf_entry_get_key (entry));
- if (strcmp (key_name, "action") == 0)
- {
- if (!action)
- {
- value = gconf_entry_get_value (entry);
- if (value->type != GCONF_VALUE_STRING)
- return FALSE;
- action = g_strdup (gconf_value_get_string (value));
- }
- else
- g_warning (_("Key Binding (%s) has its action defined multiple times\n"),
- gconf_key);
- }
- if (strcmp (key_name, "binding") == 0)
- {
- if (!key)
- {
- value = gconf_entry_get_value (entry);
- if (value->type != GCONF_VALUE_STRING)
- return FALSE;
- key = g_strdup (gconf_value_get_string (value));
- }
- else
- g_warning (_("Key Binding (%s) has its binding defined multiple times\n"),
- gconf_key);
- }
- }
- if (!action || !key)
- {
- g_warning (_("Key Binding (%s) is incomplete\n"), gconf_key);
- return FALSE;
- }
-
- tmp_elem = g_slist_find_custom (binding_list, gconf_key,
- compare_bindings);
-
- if (!tmp_elem)
- new_binding = g_new0 (Binding, 1);
- else
- {
- new_binding = (Binding*) tmp_elem->data;
- g_free (new_binding->binding_str);
- g_free (new_binding->action);
- }
-
- new_binding->binding_str = key;
- new_binding->action = action;
- new_binding->gconf_key = gconf_key;
-
- new_binding->previous_key.keysym = new_binding->key.keysym;
- new_binding->previous_key.state = new_binding->key.state;
- new_binding->previous_key.keycode = new_binding->key.keycode;
-
- if (parse_binding (new_binding))
- binding_list = g_slist_append (binding_list, new_binding);
- else
- {
- g_warning (_("Key Binding (%s) is invalid\n"), gconf_key);
- g_free (new_binding->binding_str);
- g_free (new_binding->action);
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-key_already_used (Binding *binding)
-{
- GSList *li;
-
- for (li = binding_list; li != NULL; li = li->next)
- {
- Binding *tmp_binding = (Binding*) li->data;
-
- if (tmp_binding != binding && tmp_binding->key.keycode == binding->key.keycode &&
- tmp_binding->key.state == binding->key.state)
- return TRUE;
- }
- 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 '%d'."), key->keycode);
- }
-}
-
-/* inspired from all_combinations from gnome-panel/gnome-panel/global-keys.c */
-#define N_BITS 32
-static void
-do_grab (gboolean grab,
- Key *key)
-{
- int indexes[N_BITS];/*indexes of bits we need to flip*/
- int i, bit, bits_set_cnt;
- int uppervalue;
- guint mask_to_traverse = IGNORED_MODS & ~ key->state;
-
- bit = 0;
- for (i = 0; i < N_BITS; i++) {
- if (mask_to_traverse & (1<<i))
- indexes[bit++]=i;
- }
-
- bits_set_cnt = bit;
-
- uppervalue = 1<<bits_set_cnt;
- for (i = 0; i < uppervalue; i++) {
- GSList *l;
- int j, result = 0;
-
- 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;
- grab_key (gdk_screen_get_root_window (screen), key, result,
- grab);
- }
- }
-}
-
-void
-binding_register_keys (void)
-{
- GSList *li;
-
- gdk_error_trap_push();
-
- /* Now check for changes and grab new key if not already used */
- for (li = binding_list ; li != NULL; li = li->next)
- {
- Binding *binding = (Binding *) li->data;
-
- if (binding->previous_key.keycode != binding->key.keycode ||
- binding->previous_key.state != binding->key.state)
- {
- /* Ungrab key if it changed and not clashing with previously set binding */
- if (!key_already_used (binding))
- {
- if (binding->previous_key.keycode)
- do_grab (FALSE, &binding->previous_key);
- do_grab (TRUE, &binding->key);
-
- 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\n"), binding->binding_str);
- }
- }
- gdk_flush ();
- gdk_error_trap_pop();
-}
-
-static void
-bindings_callback (GConfEntry *entry)
-{
- /* ensure we get binding dir not a sub component */
- gchar** key_elems = g_strsplit (gconf_entry_get_key (entry), "/", 15);
- gchar* binding_entry = g_strdup_printf ("/%s/%s/%s/%s", key_elems[1],
- key_elems[2], key_elems[3],
- key_elems[4]);
- g_strfreev (key_elems);
-
- bindings_get_entry (binding_entry);
- g_free (binding_entry);
-
- binding_register_keys ();
-}
-
-GdkFilterReturn
-keybindings_filter (GdkXEvent *gdk_xevent,
- GdkEvent *event,
- gpointer data)
-{
- XEvent *xevent = (XEvent *)gdk_xevent;
- guint keycode, state;
- GSList *li;
-
- if(xevent->type != KeyPress)
- return GDK_FILTER_CONTINUE;
-
- keycode = xevent->xkey.keycode;
- state = xevent->xkey.state;
-
- for (li = binding_list; li != NULL; li = li->next)
- {
- Binding *binding = (Binding*) li->data;
-
- if (keycode == binding->key.keycode &&
- (state & USED_MODS) == binding->key.state)
- {
- GError* error = NULL;
- gboolean retval;
- gchar **argv = NULL;
- gchar **envp = NULL;
-
- g_return_val_if_fail (binding->action != NULL, GDK_FILTER_CONTINUE);
-
- if (!g_shell_parse_argv (binding->action,
- NULL, &argv,
- &error))
- return GDK_FILTER_CONTINUE;
-
- envp = get_exec_environment (xevent);
-
-
- retval = g_spawn_async (NULL,
- argv,
- envp,
- G_SPAWN_SEARCH_PATH,
- NULL,
- NULL,
- NULL,
- &error);
- g_strfreev (argv);
- g_strfreev (envp);
-
- if (!retval)
- {
- GtkWidget *dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE,
- _("Error while trying to run (%s)\n"\
- "which is linked to the key (%s)"),
- binding->action,
- binding->binding_str);
- g_signal_connect (dialog, "response",
- G_CALLBACK (gtk_widget_destroy),
- NULL);
- gtk_widget_show (dialog);
- }
- return GDK_FILTER_REMOVE;
- }
- }
- return GDK_FILTER_CONTINUE;
-}
-
-void
-gnome_settings_keybindings_init (GConfClient *client)
-{
- GdkDisplay *dpy = gdk_display_get_default ();
- GdkScreen *screen;
- int screen_num = gdk_display_get_n_screens (dpy);
- int i;
-
- gnome_settings_daemon_register_callback (GCONF_BINDING_DIR, bindings_callback);
-
- gdk_window_add_filter (gdk_get_default_root_window (),
- keybindings_filter,
- NULL);
- for (i = 0; i < screen_num; i++)
- {
- screen = gdk_display_get_screen (dpy, i);
- gdk_window_add_filter (gdk_screen_get_root_window (screen),
- keybindings_filter, NULL);
- }
-}
-
-void
-gnome_settings_keybindings_load (GConfClient *client)
-{
- GSList *list, *li;
-
- list = gconf_client_all_dirs (client, GCONF_BINDING_DIR, NULL);
- screens = get_screens_list ();
-
- for (li = list; li != NULL; li = li->next)
- {
- char *subdir = li->data;
- li->data = NULL;
- bindings_get_entry (subdir);
- }
- binding_register_keys ();
-}
-