diff options
Diffstat (limited to 'gnome-settings-daemon/gnome-settings-keybindings.c')
-rw-r--r-- | gnome-settings-daemon/gnome-settings-keybindings.c | 488 |
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 (); -} - |