summaryrefslogtreecommitdiff
path: root/src/keybindings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keybindings.c')
-rw-r--r--src/keybindings.c1295
1 files changed, 906 insertions, 389 deletions
diff --git a/src/keybindings.c b/src/keybindings.c
index b259cf2..7181e97 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -1,7 +1,7 @@
/* Metacity Keybindings */
/*
- * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2001 Havoc Pennington, 2002 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -26,62 +26,77 @@
#include "ui.h"
#include "frame.h"
#include "place.h"
+#include "prefs.h"
#include <X11/keysym.h>
+#include <string.h>
-/* Plainly we'll want some more configurable keybinding system
- * eventually.
- */
static gboolean all_bindings_disabled = FALSE;
-typedef void (* MetaKeyHandler) (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-
-static void handle_activate_workspace (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_activate_menu (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_tab_forward (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_tab_backward (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_focus_previous (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_toggle_fullscreen (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_workspace_left (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_workspace_right (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
-static void handle_toggle_desktop (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data);
+typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+
+static void handle_activate_workspace (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_activate_menu (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_tab_forward (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_focus_previous (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_toggle_fullscreen (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_toggle_desktop (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_toggle_maximize (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_toggle_shade (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_close_window (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_begin_move (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_begin_resize (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_toggle_sticky (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
+static void handle_move_to_workspace (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding);
/* debug */
static void handle_spew_mark (MetaDisplay *display,
MetaWindow *window,
XEvent *event,
- gpointer data);
+ MetaKeyBinding *binding);
static gboolean process_keyboard_move_grab (MetaDisplay *display,
MetaWindow *window,
@@ -93,86 +108,473 @@ static gboolean process_tab_grab (MetaDisplay *display,
XEvent *event,
KeySym keysym);
-typedef struct _MetaKeyBinding MetaKeyBinding;
+static void regrab_screen_bindings (MetaDisplay *display);
+static void regrab_window_bindings (MetaDisplay *display);
+
+typedef struct
+{
+ const char *name;
+ MetaKeyHandlerFunc func;
+ void *data;
+} MetaKeyHandler;
struct _MetaKeyBinding
{
+ const char *name;
KeySym keysym;
- gulong mask;
- int event_type;
- MetaKeyHandler handler;
- gpointer data;
+ unsigned int mask;
int keycode;
+ const MetaKeyHandler *handler;
};
-#define IGNORED_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
-#define INTERESTING_MODIFIERS (~IGNORED_MODIFIERS)
-
-static MetaKeyBinding screen_bindings[] = {
- { XK_F1, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (0), 0 },
- { XK_F2, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (1), 0 },
- { XK_F3, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (2), 0 },
- { XK_F4, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (3), 0 },
- { XK_F5, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (4), 0 },
- { XK_F6, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (5), 0 },
- { XK_1, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (0), 0 },
- { XK_2, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (1), 0 },
- { XK_3, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (2), 0 },
- { XK_4, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (3), 0 },
- { XK_5, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (4), 0 },
- { XK_6, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (5), 0 },
- { XK_Tab, Mod1Mask, KeyPress, handle_tab_forward, GINT_TO_POINTER (META_TAB_LIST_NORMAL), 0 },
- { XK_ISO_Left_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, GINT_TO_POINTER (META_TAB_LIST_NORMAL), 0 },
- { XK_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, GINT_TO_POINTER (META_TAB_LIST_NORMAL), 0 },
- { XK_Tab, Mod1Mask | ControlMask, KeyPress, handle_tab_forward, GINT_TO_POINTER (META_TAB_LIST_DOCKS), 0 },
- { XK_ISO_Left_Tab, ShiftMask | Mod1Mask | ControlMask, KeyPress, handle_tab_backward, GINT_TO_POINTER (META_TAB_LIST_DOCKS), 0 },
- { XK_Tab, ShiftMask | Mod1Mask | ControlMask, KeyPress, handle_tab_backward, GINT_TO_POINTER (META_TAB_LIST_DOCKS), 0 },
- { XK_Escape, Mod1Mask, KeyPress, handle_focus_previous, NULL, 0 },
- { XK_Left, Mod1Mask | ControlMask, KeyPress, handle_workspace_left, NULL, 0 },
- { XK_Right, Mod1Mask | ControlMask, KeyPress, handle_workspace_right, NULL, 0 },
- /* I don't like this binding, but haven't picked the right one yet */
- { XK_d, Mod1Mask | ControlMask, KeyPress, handle_toggle_desktop, NULL, 0 },
- { None, 0, 0, NULL, NULL, 0 }
-};
-
-static MetaKeyBinding debug_bindings[] = {
- { XK_m, Mod1Mask | ControlMask | ShiftMask, KeyPress, handle_spew_mark, NULL, 0 },
- { None, 0, 0, NULL, NULL, 0 }
+static const MetaKeyHandler screen_handlers[] = {
+ { META_KEYBINDING_WORKSPACE_1, handle_activate_workspace,
+ GINT_TO_POINTER (0) },
+ { META_KEYBINDING_WORKSPACE_2, handle_activate_workspace,
+ GINT_TO_POINTER (1) },
+ { META_KEYBINDING_WORKSPACE_3, handle_activate_workspace,
+ GINT_TO_POINTER (2) },
+ { META_KEYBINDING_WORKSPACE_4, handle_activate_workspace,
+ GINT_TO_POINTER (3) },
+ { META_KEYBINDING_WORKSPACE_5, handle_activate_workspace,
+ GINT_TO_POINTER (4) },
+ { META_KEYBINDING_WORKSPACE_6, handle_activate_workspace,
+ GINT_TO_POINTER (5) },
+ { META_KEYBINDING_WORKSPACE_7, handle_activate_workspace,
+ GINT_TO_POINTER (6) },
+ { META_KEYBINDING_WORKSPACE_8, handle_activate_workspace,
+ GINT_TO_POINTER (7) },
+ { META_KEYBINDING_WORKSPACE_9, handle_activate_workspace,
+ GINT_TO_POINTER (8) },
+ { META_KEYBINDING_WORKSPACE_10, handle_activate_workspace,
+ GINT_TO_POINTER (9) },
+ { META_KEYBINDING_WORKSPACE_11, handle_activate_workspace,
+ GINT_TO_POINTER (10) },
+ { META_KEYBINDING_WORKSPACE_12, handle_activate_workspace,
+ GINT_TO_POINTER (11) },
+ { META_KEYBINDING_WORKSPACE_LEFT, handle_activate_workspace,
+ GINT_TO_POINTER (META_MOTION_LEFT) },
+ { META_KEYBINDING_WORKSPACE_RIGHT, handle_activate_workspace,
+ GINT_TO_POINTER (META_MOTION_RIGHT) },
+ { META_KEYBINDING_WORKSPACE_UP, handle_activate_workspace,
+ GINT_TO_POINTER (META_MOTION_UP) },
+ { META_KEYBINDING_WORKSPACE_DOWN, handle_activate_workspace,
+ GINT_TO_POINTER (META_MOTION_DOWN) },
+ { META_KEYBINDING_SWITCH_WINDOWS, handle_tab_forward,
+ GINT_TO_POINTER (META_TAB_LIST_NORMAL) },
+ { META_KEYBINDING_SWITCH_PANELS, handle_tab_forward,
+ GINT_TO_POINTER (META_TAB_LIST_DOCKS) },
+ { META_KEYBINDING_FOCUS_PREVIOUS, handle_focus_previous,
+ NULL },
+ { META_KEYBINDING_SHOW_DESKTOP, handle_toggle_desktop,
+ NULL },
+ { NULL, NULL, NULL }
};
-static MetaKeyBinding window_bindings[] = {
- { XK_space, Mod1Mask, KeyPress, handle_activate_menu, NULL, 0 },
- { XK_Tab, Mod1Mask, KeyPress, handle_tab_forward, NULL, 0 },
- { XK_ISO_Left_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, NULL, 0 },
- { XK_Tab, ShiftMask | Mod1Mask, KeyPress, handle_tab_backward, NULL, 0 },
- { XK_Escape, Mod1Mask, KeyPress, handle_focus_previous, NULL, 0 },
- /* Crack! */
- { XK_f, ControlMask | Mod1Mask, KeyPress, handle_toggle_fullscreen, NULL, 0 },
- { None, 0, 0, NULL, NULL, 0 }
+static const MetaKeyHandler window_handlers[] = {
+ { META_KEYBINDING_WINDOW_MENU, handle_activate_menu, NULL },
+ { META_KEYBINDING_TOGGLE_FULLSCREEN, handle_toggle_fullscreen, NULL },
+ { META_KEYBINDING_TOGGLE_MAXIMIZE, handle_toggle_maximize, NULL },
+ { META_KEYBINDING_TOGGLE_SHADE, handle_toggle_shade, NULL },
+ { META_KEYBINDING_CLOSE, handle_close_window, NULL },
+ { META_KEYBINDING_BEGIN_MOVE, handle_begin_move, },
+ { META_KEYBINDING_BEGIN_RESIZE, handle_begin_resize, },
+ { META_KEYBINDING_TOGGLE_STICKY, handle_toggle_sticky, },
+ { META_KEYBINDING_MOVE_WORKSPACE_1, handle_move_to_workspace,
+ GINT_TO_POINTER (0) },
+ { META_KEYBINDING_MOVE_WORKSPACE_2, handle_move_to_workspace,
+ GINT_TO_POINTER (1) },
+ { META_KEYBINDING_MOVE_WORKSPACE_3, handle_move_to_workspace,
+ GINT_TO_POINTER (2) },
+ { META_KEYBINDING_MOVE_WORKSPACE_4, handle_move_to_workspace,
+ GINT_TO_POINTER (3) },
+ { META_KEYBINDING_MOVE_WORKSPACE_5, handle_move_to_workspace,
+ GINT_TO_POINTER (4) },
+ { META_KEYBINDING_MOVE_WORKSPACE_6, handle_move_to_workspace,
+ GINT_TO_POINTER (5) },
+ { META_KEYBINDING_MOVE_WORKSPACE_7, handle_move_to_workspace,
+ GINT_TO_POINTER (6) },
+ { META_KEYBINDING_MOVE_WORKSPACE_8, handle_move_to_workspace,
+ GINT_TO_POINTER (7) },
+ { META_KEYBINDING_MOVE_WORKSPACE_9, handle_move_to_workspace,
+ GINT_TO_POINTER (8) },
+ { META_KEYBINDING_MOVE_WORKSPACE_10, handle_move_to_workspace,
+ GINT_TO_POINTER (9) },
+ { META_KEYBINDING_MOVE_WORKSPACE_11, handle_move_to_workspace,
+ GINT_TO_POINTER (10) },
+ { META_KEYBINDING_MOVE_WORKSPACE_12, handle_move_to_workspace,
+ GINT_TO_POINTER (11) },
+ { META_KEYBINDING_MOVE_WORKSPACE_LEFT, handle_move_to_workspace,
+ GINT_TO_POINTER (META_MOTION_LEFT) },
+ { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, handle_move_to_workspace,
+ GINT_TO_POINTER (META_MOTION_RIGHT) },
+ { META_KEYBINDING_MOVE_WORKSPACE_UP, handle_move_to_workspace,
+ GINT_TO_POINTER (META_MOTION_UP) },
+ { META_KEYBINDING_MOVE_WORKSPACE_DOWN, handle_move_to_workspace,
+ GINT_TO_POINTER (META_MOTION_DOWN) },
+ { NULL, NULL, NULL }
};
static void
-init_bindings (MetaDisplay *display,
- MetaKeyBinding *bindings)
+reload_keymap (MetaDisplay *display)
+{
+ if (display->keymap)
+ meta_XFree (display->keymap);
+
+ display->keymap = XGetKeyboardMapping (display->xdisplay,
+ display->min_keycode,
+ display->max_keycode -
+ display->min_keycode,
+ &display->keysyms_per_keycode);
+}
+
+static void
+reload_modmap (MetaDisplay *display)
{
+ XModifierKeymap *modmap;
+ int map_size;
int i;
+
+ if (display->modmap)
+ XFreeModifiermap (display->modmap);
- i = 0;
- while (bindings[i].keysym != None)
+ modmap = XGetModifierMapping (display->xdisplay);
+ display->modmap = modmap;
+
+ display->ignored_modifier_mask = 0;
+
+ /* Multiple bits may get set in each of these */
+ display->num_lock_mask = 0;
+ display->scroll_lock_mask = 0;
+ display->mode_switch_mask = 0;
+
+ /* there are 8 modifiers, and the first 3 are shift, shift lock,
+ * and control
+ */
+ map_size = 8 * modmap->max_keypermod;
+ i = 3 * modmap->max_keypermod;
+ while (i < map_size)
{
- bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
- bindings[i].keysym);
+ /* get the key code at this point in the map,
+ * see if its keysym is one we're interested in
+ */
+ int keycode = modmap->modifiermap[i];
+
+ if (keycode >= display->min_keycode &&
+ keycode <= display->max_keycode)
+ {
+ int j = 0;
+ KeySym *syms = display->keymap +
+ (keycode - display->min_keycode) * display->keysyms_per_keycode;
+
+ while (j < display->keysyms_per_keycode)
+ {
+ if (syms[j] == XK_Mode_switch)
+ {
+ /* This modifier swaps groups */
+
+ /* Mod1Mask is 1 << 3 for example, i.e. the
+ * fourth modifier, i / keyspermod is the modifier
+ * index
+ */
+
+ display->mode_switch_mask |= (1 << ( i / modmap->max_keypermod));
+ }
+ else if (syms[j] == XK_Num_Lock)
+ {
+ display->num_lock_mask |= (1 << ( i / modmap->max_keypermod));
+ }
+ else if (syms[j] == XK_Scroll_Lock)
+ {
+ display->scroll_lock_mask |= (1 << ( i / modmap->max_keypermod));
+ }
+
+ ++j;
+ }
+ }
++i;
}
-}
+
+ display->ignored_modifier_mask = (display->mode_switch_mask |
+ display->num_lock_mask |
+ display->scroll_lock_mask);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ignoring modmask 0x%x num lock 0x%x mode switch 0x%x scroll lock 0x%x\n",
+ display->ignored_modifier_mask,
+ display->num_lock_mask,
+ display->mode_switch_mask,
+ display->scroll_lock_mask);
+}
+
+static void
+reload_keycodes (MetaDisplay *display)
+{
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Reloading keycodes for binding tables\n");
+
+ if (display->screen_bindings)
+ {
+ int i;
+
+ i = 0;
+ while (display->screen_bindings[i].keysym != None)
+ {
+ display->screen_bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
+ display->screen_bindings[i].keysym);
+
+ ++i;
+ }
+ }
+
+ if (display->window_bindings)
+ {
+ int i;
+
+ i = 0;
+ while (display->window_bindings[i].keysym != None)
+ {
+ display->window_bindings[i].keycode = XKeysymToKeycode (display->xdisplay,
+ display->window_bindings[i].keysym);
+
+ ++i;
+ }
+ }
+}
+
+static void
+rebuild_screen_binding_table (MetaDisplay *display)
+{
+ const MetaKeyPref *prefs;
+ int n_bindings;
+ int src, dest;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Rebuilding screen binding table from preferences\n");
+
+ meta_prefs_get_screen_bindings (&prefs, &n_bindings);
+ g_free (display->screen_bindings);
+ display->screen_bindings = g_new0 (MetaKeyBinding, n_bindings);
+
+ src = 0;
+ dest = 0;
+ while (src < n_bindings)
+ {
+ if (prefs[src].keysym != None &&
+ prefs[src].mask != 0)
+ {
+ display->screen_bindings[dest].name = prefs[src].name;
+ display->screen_bindings[dest].keysym = prefs[src].keysym;
+ display->screen_bindings[dest].mask = prefs[src].mask;
+ ++dest;
+ }
+
+ ++src;
+ }
+
+ display->n_screen_bindings = dest;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "%d screen bindings in table\n",
+ display->n_screen_bindings);
+}
+
+static void
+rebuild_window_binding_table (MetaDisplay *display)
+{
+ const MetaKeyPref *prefs;
+ int n_bindings;
+ int src, dest;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Rebuilding window binding table from preferences\n");
+
+ meta_prefs_get_window_bindings (&prefs, &n_bindings);
+ g_free (display->window_bindings);
+ display->window_bindings = g_new0 (MetaKeyBinding, n_bindings);
+
+ src = 0;
+ dest = 0;
+ while (src < n_bindings)
+ {
+ if (prefs[src].keysym != None &&
+ prefs[src].mask != 0)
+ {
+ display->window_bindings[dest].name = prefs[src].name;
+ display->window_bindings[dest].keysym = prefs[src].keysym;
+ display->window_bindings[dest].mask = prefs[src].mask;
+ ++dest;
+ }
+
+ ++src;
+ }
+
+ display->n_window_bindings = dest;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "%d window bindings in table\n",
+ display->n_window_bindings);
+}
+
+static void
+regrab_screen_bindings (MetaDisplay *display)
+{
+ GSList *tmp;
+
+ tmp = display->screens;
+ while (tmp != NULL)
+ {
+ MetaScreen *screen = tmp->data;
+
+ meta_screen_ungrab_keys (screen);
+ meta_screen_grab_keys (screen);
+
+ tmp = tmp->next;
+ }
+}
+
+static void
+regrab_window_bindings (MetaDisplay *display)
+{
+ GSList *windows;
+ GSList *tmp;
+
+ windows = meta_display_list_windows (display);
+
+ tmp = windows;
+ while (tmp != NULL)
+ {
+ MetaWindow *w = tmp->data;
+
+ meta_window_ungrab_keys (w);
+ meta_window_grab_keys (w);
+
+ tmp = tmp->next;
+ }
+
+ g_slist_free (windows);
+}
+
+void
+meta_display_process_mapping_event (MetaDisplay *display,
+ XEvent *event)
+{
+ if (event->xmapping.request == MappingModifier)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Received MappingModifier event, will reload modmap and redo keybindings\n");
+
+ reload_modmap (display);
+
+ regrab_screen_bindings (display);
+ regrab_window_bindings (display);
+ }
+ else if (event->xmapping.request == MappingKeyboard)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Received MappingKeyboard event, will reload keycodes and redo keybindings\n");
+
+ reload_keymap (display);
+ reload_modmap (display);
+
+ reload_keycodes (display);
+
+ regrab_screen_bindings (display);
+ regrab_window_bindings (display);
+ }
+}
+
+static void
+bindings_changed_callback (MetaPreference pref,
+ void *data)
+{
+ MetaDisplay *display;
+
+ display = data;
+
+ switch (pref)
+ {
+ case META_PREF_SCREEN_KEYBINDINGS:
+ rebuild_screen_binding_table (display);
+ reload_keycodes (display);
+ regrab_screen_bindings (display);
+ break;
+ case META_PREF_WINDOW_KEYBINDINGS:
+ rebuild_window_binding_table (display);
+ reload_keycodes (display);
+ regrab_window_bindings (display);
+ break;
+ default:
+ break;
+ }
+}
+
void
meta_display_init_keys (MetaDisplay *display)
{
- init_bindings (display, screen_bindings);
- init_bindings (display, window_bindings);
- init_bindings (display, debug_bindings);
+ /* Keybindings */
+ display->keymap = NULL;
+ display->keysyms_per_keycode = 0;
+ display->modmap = NULL;
+ display->min_keycode = 0;
+ display->max_keycode = 0;
+ display->ignored_modifier_mask = 0;
+ display->num_lock_mask = 0;
+ display->scroll_lock_mask = 0;
+ display->mode_switch_mask = 0;
+ display->screen_bindings = NULL;
+ display->n_screen_bindings = 0;
+ display->window_bindings = NULL;
+ display->n_window_bindings = 0;
+
+ XDisplayKeycodes (display->xdisplay,
+ &display->min_keycode,
+ &display->max_keycode);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Display has keycode range %d to %d\n",
+ display->min_keycode,
+ display->max_keycode);
+
+ reload_keymap (display);
+ reload_modmap (display);
+
+ rebuild_window_binding_table (display);
+ rebuild_screen_binding_table (display);
+
+ reload_keycodes (display);
+
+ /* Keys are actually grabbed in meta_screen_grab_keys() */
+
+ meta_prefs_add_listener (bindings_changed_callback, display);
+}
+
+void
+meta_display_shutdown_keys (MetaDisplay *display)
+{
+ meta_prefs_remove_listener (bindings_changed_callback, display);
+
+ if (display->keymap)
+ meta_XFree (display->keymap);
+
+ if (display->modmap)
+ XFreeModifiermap (display->modmap);
+ g_free (display->screen_bindings);
+ g_free (display->window_bindings);
+}
+
+static const char*
+keysym_name (int keysym)
+{
+ const char *name;
+
+ name = XKeysymToString (keysym);
+ if (name == NULL)
+ name = "(unknown)";
+
+ return name;
}
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
@@ -188,23 +590,29 @@ meta_change_keygrab (MetaDisplay *display,
int ignored_mask;
/* Grab keycode/modmask, together with
- * all combinations of IGNORED_MODIFIERS.
+ * all combinations of ignored modifiers.
* X provides no better way to do this.
*/
- /* Instead of this hacky mess copied from fvwm, WindowMaker just
- * grabs with all numlock/scrolllock combinations and doesn't grab
- * for other weird bits.
- */
-
- /* modmask can't contain any non-interesting modifiers */
- g_return_if_fail ((modmask & INTERESTING_MODIFIERS) == modmask);
+
+ if ((modmask & ~(display->ignored_modifier_mask)) == 0)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Unable to grab/ungrab keybinding because it has no modifiers\n");
+ return;
+ }
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "%s keybinding %s mask 0x%x\n",
+ grab ? "Grabbing" : "Ungrabbing",
+ keysym_name (keysym),
+ modmask);
ignored_mask = 0;
- while (ignored_mask < IGNORED_MODIFIERS)
+ while (ignored_mask < (int) display->ignored_modifier_mask)
{
- if (ignored_mask & INTERESTING_MODIFIERS)
+ if (ignored_mask & ~(display->ignored_modifier_mask))
{
- /* Not a combination of IGNORED_MODIFIERS
+ /* Not a combination of ignored modifiers
* (it contains some non-ignored modifiers)
*/
++ignored_mask;
@@ -226,15 +634,9 @@ meta_change_keygrab (MetaDisplay *display,
result = meta_error_trap_pop (display);
if (grab && result != Success)
- {
- const char *name;
-
- name = XKeysymToString (keysym);
- if (name == NULL)
- name = "(unknown)";
-
+ {
if (result == BadAccess)
- meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), name, modmask | ignored_mask);
+ meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask);
}
++ignored_mask;
@@ -252,24 +654,17 @@ meta_grab_key (MetaDisplay *display,
}
static void
-meta_ungrab_key (MetaDisplay *display,
- Window xwindow,
- int keysym,
- int keycode,
- int modmask)
-{
- meta_change_keygrab (display, xwindow, FALSE, keysym, keycode, modmask);
-}
-
-static void
grab_keys (MetaKeyBinding *bindings,
+ int n_bindings,
MetaDisplay *display,
Window xwindow)
{
int i;
+ g_assert (n_bindings == 0 || bindings != NULL);
+
i = 0;
- while (bindings[i].keysym != None)
+ while (i < n_bindings)
{
if (bindings[i].keycode != 0)
{
@@ -284,41 +679,44 @@ grab_keys (MetaKeyBinding *bindings,
}
static void
-ungrab_keys (MetaKeyBinding *bindings,
- MetaDisplay *display,
- Window xwindow)
+ungrab_all_keys (MetaDisplay *display,
+ Window xwindow)
{
- int i;
+ int result;
+
+ meta_error_trap_push (display);
- i = 0;
- while (bindings[i].keysym != None)
- {
- if (bindings[i].keycode != 0)
- {
- meta_ungrab_key (display, xwindow,
- bindings[i].keysym,
- bindings[i].keycode,
- bindings[i].mask);
- }
+ XUngrabKey (display->xdisplay, AnyKey, AnyModifier,
+ xwindow);
- ++i;
- }
+ result = meta_error_trap_pop (display);
+
+ if (result != Success)
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ungrabbing all keys on 0x%lx failed\n", xwindow);
}
void
-meta_screen_grab_keys (MetaScreen *screen)
+meta_screen_grab_keys (MetaScreen *screen)
{
- grab_keys (screen_bindings, screen->display, screen->xroot);
- if (meta_is_debugging ())
- grab_keys (debug_bindings, screen->display, screen->xroot);
+ if (screen->keys_grabbed)
+ return;
+
+ grab_keys (screen->display->screen_bindings,
+ screen->display->n_screen_bindings,
+ screen->display, screen->xroot);
+
+ screen->keys_grabbed = TRUE;
}
void
meta_screen_ungrab_keys (MetaScreen *screen)
{
- ungrab_keys (screen_bindings, screen->display, screen->xroot);
- if (meta_is_debugging ())
- ungrab_keys (debug_bindings, screen->display, screen->xroot);
+ if (screen->keys_grabbed)
+ {
+ ungrab_all_keys (screen->display, screen->xroot);
+ screen->keys_grabbed = FALSE;
+ }
}
void
@@ -330,21 +728,17 @@ meta_window_grab_keys (MetaWindow *window)
if (window->keys_grabbed)
{
if (window->frame && !window->grab_on_frame)
- ungrab_keys (window_bindings, window->display,
- window->xwindow);
+ ungrab_all_keys (window->display, window->xwindow);
else if (window->frame == NULL &&
window->grab_on_frame)
; /* continue to regrab on client window */
else
return; /* already all good */
}
-
- /* no keybindings for Emacs ;-) */
- if (window->res_class &&
- g_strcasecmp (window->res_class, "Emacs") == 0)
- return;
- grab_keys (window_bindings, window->display,
+ grab_keys (window->display->window_bindings,
+ window->display->n_window_bindings,
+ window->display,
window->frame ? window->frame->xwindow : window->xwindow);
window->keys_grabbed = TRUE;
@@ -358,11 +752,11 @@ meta_window_ungrab_keys (MetaWindow *window)
{
if (window->grab_on_frame &&
window->frame != NULL)
- ungrab_keys (window_bindings, window->display,
- window->frame->xwindow);
+ ungrab_all_keys (window->display,
+ window->frame->xwindow);
else if (!window->grab_on_frame)
- ungrab_keys (window_bindings, window->display,
- window->xwindow);
+ ungrab_all_keys (window->display,
+ window->xwindow);
}
}
@@ -397,7 +791,8 @@ meta_window_grab_all_keys (MetaWindow *window)
result = meta_error_trap_pop (window->display);
if (result != Success)
{
- meta_verbose ("Global key grab failed for window %s\n", window->desc);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Global key grab failed for window %s\n", window->desc);
return FALSE;
}
else
@@ -415,12 +810,14 @@ meta_window_grab_all_keys (MetaWindow *window)
result = meta_error_trap_pop (window->display);
if (result != Success)
{
- meta_verbose ("XGrabKeyboard() failed for window %s\n",
- window->desc);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "XGrabKeyboard() failed for window %s\n",
+ window->desc);
return FALSE;
}
- meta_verbose ("Grabbed all keys on window %s\n", window->desc);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Grabbed all keys on window %s\n", window->desc);
window->keys_grabbed = FALSE;
window->all_keys_grabbed = TRUE;
@@ -447,8 +844,9 @@ meta_window_ungrab_all_keys (MetaWindow *window)
AnyKey, AnyModifier,
grabwindow);
- meta_verbose ("Ungrabbing keyboard with timestamp %lu\n",
- timestamp);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ungrabbing keyboard with timestamp %lu\n",
+ timestamp);
XUngrabKeyboard (window->display->xdisplay, timestamp);
meta_error_trap_pop (window->display);
@@ -467,18 +865,15 @@ is_modifier (MetaDisplay *display,
{
int i;
int map_size;
- XModifierKeymap *mod_keymap;
- gboolean retval = FALSE;
-
- /* FIXME this is ass-slow, cache the modmap */
-
- mod_keymap = XGetModifierMapping (display->xdisplay);
+ gboolean retval = FALSE;
+
+ g_assert (display->modmap);
- map_size = 8 * mod_keymap->max_keypermod;
+ map_size = 8 * display->modmap->max_keypermod;
i = 0;
while (i < map_size)
{
- if (keycode == mod_keymap->modifiermap[i])
+ if (keycode == display->modmap->modifiermap[i])
{
retval = TRUE;
break;
@@ -486,30 +881,52 @@ is_modifier (MetaDisplay *display,
++i;
}
- XFreeModifiermap (mod_keymap);
-
return retval;
}
-#define MOD1_INDEX 3 /* shift, lock, control, mod1 */
+/* Indexes:
+ * shift = 0
+ * lock = 1
+ * control = 2
+ * mod1 = 3
+ * mod2 = 4
+ * mod3 = 5
+ * mod4 = 6
+ * mod5 = 7
+ */
+
static gboolean
-is_mod1_key (MetaDisplay *display,
- unsigned int keycode)
+is_specific_modifier (MetaDisplay *display,
+ unsigned int keycode,
+ unsigned int mask)
{
int i;
int end;
- XModifierKeymap *mod_keymap;
gboolean retval = FALSE;
+ int mod_index;
- /* FIXME this is ass-slow, cache the modmap */
+ g_assert (display->modmap);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Checking whether code 0x%x is bound to modifier 0x%x\n",
+ keycode, mask);
- mod_keymap = XGetModifierMapping (display->xdisplay);
+ mod_index = 0;
+ mask = mask >> 1;
+ while (mask != 0)
+ {
+ mod_index += 1;
+ mask = mask >> 1;
+ }
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Modifier has index %d\n", mod_index);
- end = (MOD1_INDEX + 1) * mod_keymap->max_keypermod;
- i = MOD1_INDEX * mod_keymap->max_keypermod;
+ end = (mod_index + 1) * display->modmap->max_keypermod;
+ i = mod_index * display->modmap->max_keypermod;
while (i < end)
{
- if (keycode == mod_keymap->modifiermap[i])
+ if (keycode == display->modmap->modifiermap[i])
{
retval = TRUE;
break;
@@ -517,29 +934,94 @@ is_mod1_key (MetaDisplay *display,
++i;
}
- XFreeModifiermap (mod_keymap);
-
return retval;
}
+static gboolean
+keycode_is_primary_modifier (MetaDisplay *display,
+ unsigned int keycode,
+ unsigned int entire_binding_mask)
+{
+ /* The idea here is to see if the "main" modifier
+ * for Alt+Tab has been pressed/released. So if the binding
+ * is Alt+Shift+Tab then releasing Alt is the thing that
+ * ends the operation. It's pretty random how we order
+ * these.
+ */
+ unsigned int masks[] = { Mod5Mask, Mod4Mask, Mod3Mask,
+ Mod2Mask, Mod1Mask, ControlMask,
+ ShiftMask, LockMask };
+
+ int i;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Checking whether code 0x%x is the primary modifier of mask 0x%x\n",
+ keycode, entire_binding_mask);
+
+ i = 0;
+ while (i < (int) G_N_ELEMENTS (masks))
+ {
+ if (entire_binding_mask & masks[i])
+ return is_specific_modifier (display, keycode, masks[i]);
+ ++i;
+ }
+
+ return FALSE;
+}
+
+static const MetaKeyHandler*
+find_handler (const MetaKeyHandler *handlers,
+ const char *name)
+{
+ const MetaKeyHandler *iter;
+
+ iter = handlers;
+ while (iter->name)
+ {
+ if (strcmp (iter->name,
+ name) == 0)
+ return iter;
+
+ ++iter;
+ }
+
+ return NULL;
+}
+
static void
-process_event (MetaKeyBinding *bindings,
- MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- KeySym keysym)
+process_event (MetaKeyBinding *bindings,
+ int n_bindings,
+ const MetaKeyHandler *handlers,
+ MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ KeySym keysym)
{
int i;
i = 0;
- while (bindings[i].keysym != None)
+ while (i < n_bindings)
{
if (bindings[i].keysym == keysym &&
- ((event->xkey.state & INTERESTING_MODIFIERS) ==
+ ((event->xkey.state & ~(display->ignored_modifier_mask)) ==
bindings[i].mask) &&
- bindings[i].event_type == event->type)
+ event->type == KeyPress)
{
- (* bindings[i].handler) (display, window, event, bindings[i].data);
+ const MetaKeyHandler *handler;
+
+ if (bindings[i].handler)
+ handler = bindings[i].handler;
+ else
+ {
+ handler = find_handler (handlers, bindings[i].name);
+ bindings[i].handler = handler; /* cache */
+ }
+
+ if (handler == NULL)
+ meta_bug ("Binding %s has no handler\n", bindings[i].name);
+
+ (* handler->func) (display, window, event,
+ &bindings[i]);
break;
}
@@ -565,20 +1047,25 @@ meta_display_process_key_event (MetaDisplay *display,
keysym = XKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0);
- meta_verbose ("Processing key %s event, keysym: %s state: 0x%x window: %s\n",
- event->type == KeyPress ? "press" : "release",
- XKeysymToString (keysym), event->xkey.state,
- window ? window->desc : "(no window)");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Processing key %s event, keysym: %s state: 0x%x window: %s\n",
+ event->type == KeyPress ? "press" : "release",
+ XKeysymToString (keysym), event->xkey.state,
+ window ? window->desc : "(no window)");
if (window == NULL || !window->all_keys_grabbed)
{
/* Do the normal keybindings */
- process_event (screen_bindings, display, NULL, event, keysym);
- if (meta_is_debugging ())
- process_event (debug_bindings, display, NULL, event, keysym);
+ process_event (display->screen_bindings,
+ display->n_screen_bindings,
+ screen_handlers,
+ display, NULL, event, keysym);
if (window)
- process_event (window_bindings, display, window, event, keysym);
+ process_event (display->window_bindings,
+ display->n_window_bindings,
+ window_handlers,
+ display, window, event, keysym);
return;
}
@@ -598,12 +1085,14 @@ meta_display_process_key_event (MetaDisplay *display,
switch (display->grab_op)
{
case META_GRAB_OP_KEYBOARD_MOVING:
- meta_verbose ("Processing event for keyboard move\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Processing event for keyboard move\n");
handled = process_keyboard_move_grab (display, window, event, keysym);
break;
case META_GRAB_OP_KEYBOARD_TABBING_NORMAL:
case META_GRAB_OP_KEYBOARD_TABBING_DOCK:
- meta_verbose ("Processing event for keyboard tabbing\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Processing event for keyboard tabbing\n");
handled = process_tab_grab (display, window, event, keysym);
break;
default:
@@ -614,8 +1103,9 @@ meta_display_process_key_event (MetaDisplay *display,
/* end grab if a key that isn't used gets pressed */
if (!handled)
{
- meta_verbose ("Ending grab op %d on key event sym %s\n",
- display->grab_op, XKeysymToString (keysym));
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending grab op %d on key event sym %s\n",
+ display->grab_op, XKeysymToString (keysym));
meta_display_end_grab_op (display, event->xkey.time);
}
}
@@ -656,11 +1146,11 @@ process_keyboard_move_grab (MetaDisplay *display,
else
incr = NORMAL_INCREMENT;
- /* When moving by increments, we still snap to edges if the move
- * to the edge is smaller than the increment. This is because
- * Shift + arrow to snap is sort of a hidden feature. This way
- * people using just arrows shouldn't get too frustrated.
- */
+ /* When moving by increments, we still snap to edges if the move
+ * to the edge is smaller than the increment. This is because
+ * Shift + arrow to snap is sort of a hidden feature. This way
+ * people using just arrows shouldn't get too frustrated.
+ */
switch (keysym)
{
@@ -738,7 +1228,8 @@ process_tab_grab (MetaDisplay *display,
g_return_val_if_fail (screen->tab_popup != NULL, FALSE);
if (event->type == KeyRelease &&
- is_mod1_key (display, event->xkey.keycode))
+ keycode_is_primary_modifier (display, event->xkey.keycode,
+ display->grab_mask))
{
/* We're done, move to the new window. */
Window target_xwindow;
@@ -749,14 +1240,17 @@ process_tab_grab (MetaDisplay *display,
target_window =
meta_display_lookup_x_window (display, target_xwindow);
- meta_verbose ("Ending tab operation, Mod1 released\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending tab operation, primary modifier released\n");
if (target_window)
{
- meta_verbose ("Ending grab early so we can focus the target window\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending grab early so we can focus the target window\n");
meta_display_end_grab_op (display, event->xkey.time);
- meta_verbose ("Activating target window\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Activating target window\n");
meta_topic (META_DEBUG_FOCUS, "Activating %s due to tab popup selection\n",
target_window->desc);
@@ -786,7 +1280,8 @@ process_tab_grab (MetaDisplay *display,
meta_ui_tab_popup_forward (screen->tab_popup);
/* continue grab */
- meta_verbose ("Tab key pressed, moving tab focus in popup\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Tab key pressed, moving tab focus in popup\n");
return TRUE;
break;
@@ -795,7 +1290,8 @@ process_tab_grab (MetaDisplay *display,
}
/* end grab */
- meta_verbose ("Ending tabbing, uninteresting key pressed\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ending tabbing, uninteresting key pressed\n");
return FALSE;
}
@@ -841,79 +1337,34 @@ switch_to_workspace (MetaDisplay *display,
}
static void
-handle_activate_workspace (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- gpointer data)
+handle_activate_workspace (MetaDisplay *display,
+ MetaWindow *event_window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
int which;
MetaWorkspace *workspace;
- which = GPOINTER_TO_INT (data);
-
- workspace = meta_display_get_workspace_by_index (display, which);
-
- if (workspace)
- {
- switch_to_workspace (display, workspace);
- }
- else
- {
- /* We could offer to create it I suppose */
- }
-}
-
-static void
-handle_workspace_left (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data)
-{
- MetaWorkspace *workspace;
- MetaScreen *screen;
- int i;
-
- screen = meta_display_screen_for_root (display,
- event->xkey.root);
-
- if (screen == NULL)
- return;
-
- i = meta_workspace_index (screen->active_workspace);
- --i;
+ which = GPOINTER_TO_INT (binding->handler->data);
- workspace = meta_display_get_workspace_by_index (display, i);
-
- if (workspace)
+ workspace = NULL;
+ if (which < 0)
{
- switch_to_workspace (display, workspace);
+ MetaScreen *screen;
+
+ screen = meta_display_screen_for_root (display,
+ event->xkey.root);
+
+ if (screen == NULL)
+ return;
+
+ workspace = meta_workspace_get_neighbor (screen->active_workspace,
+ which);
}
else
{
- /* We could offer to create it I suppose */
+ workspace = meta_display_get_workspace_by_index (display, which);
}
-}
-
-static void
-handle_workspace_right (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data)
-{
- MetaWorkspace *workspace;
- MetaScreen *screen;
- int i;
-
- screen = meta_display_screen_for_root (display,
- event->xkey.root);
-
- if (screen == NULL)
- return;
-
- i = meta_workspace_index (screen->active_workspace);
- ++i;
-
- workspace = meta_display_get_workspace_by_index (display, i);
if (workspace)
{
@@ -926,10 +1377,10 @@ handle_workspace_right (MetaDisplay *display,
}
static void
-handle_toggle_desktop (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data)
+handle_toggle_desktop (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
if (display->showing_desktop)
meta_display_unshow_desktop (display);
@@ -938,10 +1389,10 @@ handle_toggle_desktop (MetaDisplay *display,
}
static void
-handle_activate_menu (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- gpointer data)
+handle_activate_menu (MetaDisplay *display,
+ MetaWindow *event_window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
if (display->focus_window)
{
@@ -974,83 +1425,22 @@ op_from_tab_type (MetaTabList type)
}
static void
-handle_tab_forward (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- gpointer data)
+handle_tab_forward (MetaDisplay *display,
+ MetaWindow *event_window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
MetaWindow *window;
MetaTabList type;
-
- type = GPOINTER_TO_INT (data);
+ gboolean backward;
- meta_verbose ("Tab forward type = %d\n", type);
+ type = GPOINTER_TO_INT (binding->handler->data);
- window = NULL;
-
- if (display->focus_window != NULL)
- {
- window = meta_display_get_tab_next (display,
- type,
- display->focus_window->screen->active_workspace,
- display->focus_window,
- FALSE);
- }
-
- if (window == NULL)
- {
- MetaScreen *screen;
-
- screen = meta_display_screen_for_root (display,
- event->xkey.root);
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Tab type = %d\n", type);
- /* We get the screen because event_window may be NULL,
- * in which case we can't use event_window->screen
- */
- if (screen)
- {
- window = meta_display_get_tab_next (screen->display,
- type,
- screen->active_workspace,
- NULL,
- FALSE);
- }
- }
-
- if (window)
- {
- meta_verbose ("Starting tab forward, showing popup\n");
-
- if (meta_display_begin_grab_op (window->display,
- display->focus_window ?
- display->focus_window : window,
- op_from_tab_type (type),
- FALSE,
- 0, 0,
- event->xkey.time,
- 0, 0))
- {
- meta_ui_tab_popup_select (window->screen->tab_popup,
- window->xwindow);
- /* only after selecting proper window */
- meta_ui_tab_popup_set_showing (window->screen->tab_popup,
- TRUE);
- }
- }
-}
-
-static void
-handle_tab_backward (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- gpointer data)
-{
- MetaWindow *window;
- MetaTabList type;
-
- type = GPOINTER_TO_INT (data);
-
- meta_verbose ("Tab backward type = %d\n", type);
+ /* backward if shift is down, this isn't configurable */
+ backward = (event->xkey.state & ShiftMask) != 0;
window = NULL;
@@ -1060,7 +1450,7 @@ handle_tab_backward (MetaDisplay *display,
type,
display->focus_window->screen->active_workspace,
display->focus_window,
- TRUE);
+ backward);
}
if (window == NULL)
@@ -1079,23 +1469,25 @@ handle_tab_backward (MetaDisplay *display,
type,
screen->active_workspace,
NULL,
- TRUE);
+ backward);
}
}
if (window)
{
- meta_verbose ("Starting tab backward, showing popup\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Starting tab between windows, showing popup\n");
if (meta_display_begin_grab_op (window->display,
display->focus_window ?
display->focus_window : window,
op_from_tab_type (type),
FALSE,
- 0, 0,
+ 0,
+ event->xkey.state & ~(display->ignored_modifier_mask),
event->xkey.time,
0, 0))
- {
+ {
meta_ui_tab_popup_select (window->screen->tab_popup,
window->xwindow);
/* only after selecting proper window */
@@ -1106,15 +1498,16 @@ handle_tab_backward (MetaDisplay *display,
}
static void
-handle_focus_previous (MetaDisplay *display,
- MetaWindow *event_window,
- XEvent *event,
- gpointer data)
+handle_focus_previous (MetaDisplay *display,
+ MetaWindow *event_window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
MetaWindow *window;
MetaScreen *screen;
- meta_verbose ("Focus previous window\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Focus previous window\n");
screen = meta_display_screen_for_root (display,
event->xkey.root);
@@ -1162,10 +1555,10 @@ handle_focus_previous (MetaDisplay *display,
}
static void
-handle_toggle_fullscreen (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data)
+handle_toggle_fullscreen (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
if (window)
{
@@ -1177,10 +1570,132 @@ handle_toggle_fullscreen (MetaDisplay *display,
}
static void
-handle_spew_mark (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event,
- gpointer data)
+handle_toggle_maximize (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ if (window)
+ {
+ if (window->maximized)
+ meta_window_unmaximize (window);
+ else
+ meta_window_maximize (window);
+ }
+}
+
+static void
+handle_toggle_shade (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ if (window)
+ {
+ if (window->shaded)
+ meta_window_unshade (window);
+ else
+ meta_window_shade (window);
+ }
+}
+
+static void
+handle_close_window (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ if (window)
+ meta_window_delete (window, event->xkey.time);
+}
+
+static void
+handle_begin_move (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ if (window)
+ {
+ meta_window_raise (window);
+ meta_display_begin_grab_op (window->display,
+ window,
+ META_GRAB_OP_KEYBOARD_MOVING,
+ FALSE, 0, 0,
+ event->xkey.time,
+ 0, 0);
+ }
+}
+
+static void
+handle_begin_resize (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ /* FIXME */
+}
+
+static void
+handle_toggle_sticky (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ if (window)
+ {
+ if (window->on_all_workspaces)
+ meta_window_unstick (window);
+ else
+ meta_window_stick (window);
+ }
+}
+
+static void
+handle_move_to_workspace (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
+{
+ int which;
+ MetaWorkspace *workspace;
+
+ which = GPOINTER_TO_INT (binding->handler->data);
+
+ workspace = NULL;
+ if (which < 0)
+ {
+ MetaScreen *screen;
+
+ screen = meta_display_screen_for_root (display,
+ event->xkey.root);
+
+ if (screen == NULL)
+ return;
+
+ workspace = meta_workspace_get_neighbor (screen->active_workspace,
+ which);
+ }
+ else
+ {
+ workspace = meta_display_get_workspace_by_index (display, which);
+ }
+
+ if (workspace)
+ {
+ meta_window_change_workspace (window, workspace);
+ }
+ else
+ {
+ /* We could offer to create it I suppose */
+ }
+}
+
+static void
+handle_spew_mark (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event,
+ MetaKeyBinding *binding)
{
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
@@ -1191,11 +1706,13 @@ meta_set_keybindings_disabled (gboolean setting)
if (meta_is_debugging ())
{
all_bindings_disabled = setting;
- meta_verbose ("Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
}
else
{
- meta_verbose ("Ignoring keybindings disable message, not in debug mode\n");
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Ignoring keybindings disable message, not in debug mode\n");
}
}