summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--README32
-rw-r--r--src/display.c22
-rw-r--r--src/display.h31
-rw-r--r--src/keybindings.c1295
-rw-r--r--src/keybindings.h25
-rw-r--r--src/metacity.schemas1034
-rw-r--r--src/prefs.c304
-rw-r--r--src/prefs.h64
-rw-r--r--src/screen.c3
-rw-r--r--src/screen.h2
-rw-r--r--src/ui.c46
-rw-r--r--src/ui.h3
-rw-r--r--src/util.c2
-rw-r--r--src/util.h3
-rw-r--r--src/window.c7
-rw-r--r--src/workspace.c28
-rw-r--r--src/workspace.h14
18 files changed, 2479 insertions, 457 deletions
diff --git a/ChangeLog b/ChangeLog
index f506569d..7dd0f71a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2002-04-28 Havoc Pennington <hp@pobox.com>
+
+ * README: remove caveats about keybindings
+
+ * src/metacity.schemas: add schemas for all the keybindings.
+
+ * src/window.c (meta_window_activate): if in "show desktop" mode
+ when a window is activated, leave show desktop mode. So e.g.
+ when you click on a task in the task list, show desktop mode
+ will be turned off.
+
+ * src/workspace.c (meta_workspace_get_neighbor): new function
+ that doesn't quite work yet (needs support for getting
+ workspace layout from the pager)
+
+ * src/prefs.c: keybindings stuff
+
+ * src/keybindings.c: make keybindings configurable
+
+ * src/ui.c (meta_ui_parse_accelerator): new function
+
2002-04-25 Havoc Pennington <hp@redhat.com>
* metacity.spec: fix to install gconf schemas
diff --git a/README b/README
index c31882d5..d1fc30f3 100644
--- a/README
+++ b/README
@@ -51,19 +51,25 @@ METACITY FEATURES
gconftool-2 --type=string --set /apps/metacity/general/focus_mode sloppy
gconftool-2 --type=string --set /apps/metacity/general/focus_mode click
- - Global keybindings:
- Alt-F1 to Alt-F6 switch workspaces
- Alt-1 to Alt-6 switch workspaces
+ - Global keybinding defaults:
+
Alt-Tab forward cycle window focus
Alt-Shift-Tab backward cycle focus
Alt-Ctrl-Tab forward cycle focus among panels
Alt-Ctrl-Shift-Tab backward cycle focus among panels
Alt-Escape focus previous window
- Ctrl-Alt-Left Arrow previous workspace
- Ctrl-Alt-Right Arrow next workspace
+ Alt-Left Arrow previous workspace
+ Alt-Right Arrow next workspace
Ctrl-Alt-D minimize/unminimize all, to show desktop
+ Change keybindings for example:
+
+ unst gconftool-2 --type=string --set /apps/metacity/global_keybindings/switch_to_workspace_1 '<Alt>F1'
+
+ See metacity.schemas for available bindings.
+
- Window keybindings:
+
Alt-space window menu
Mnemonics work in the menu. That is, Alt-space then underlined
@@ -77,6 +83,9 @@ METACITY FEATURES
Choose Resize from menu, and nothing happens yet, but
eventually I might implement something.
+ Keybindings for things like maximize window, etc. can be bound,
+ but don't exist by default. See metacity.schemas.
+
- Window mouse bindings:
Clicking anywhere on frame with button 1 will raise/focus window
@@ -130,23 +139,10 @@ METACITY FEATURES
METACITY BUGS, NON-FEATURES, AND CAVEATS
===
- - If you want keybindings which are not the ones mentioned above
- as features, you have to edit keybindings.c and recompile.
-
- - Some of the default keybindings (notable Alt+number) are total
- crackrock. This is just because I like those keybindings and
- things aren't configurable yet. Once bindings are configurable
- the dumb defaults will go away.
-
- You need an EWMH-spec compliant pager/tasklist to be able
to navigate graphically; this does NOT include GNOME 1.x,
but should include GNOME 2 and KDE 3.
- - Metacity turns off its keybindings for Emacs, because I use
- Alt-space in Emacs, and getting a window menu annoys me.
- This is a broken feature that will go away when keybindings are
- configurable.
-
- I haven't even read the ICCCM section about colormaps. So if you
have an 8-bit display you are probably screwed.
diff --git a/src/display.c b/src/display.c
index f1a9c646..bd6fc9bc 100644
--- a/src/display.c
+++ b/src/display.c
@@ -552,6 +552,8 @@ meta_display_close (MetaDisplay *display)
all_displays = g_slist_remove (all_displays, display);
+ meta_display_shutdown_keys (display);
+
g_free (display);
if (all_displays == NULL)
@@ -1308,6 +1310,10 @@ event_callback (XEvent *event,
}
break;
case MappingNotify:
+ /* Let XLib know that there is a new keyboard mapping.
+ */
+ XRefreshKeyboardMapping (&event->xmapping);
+ meta_display_process_mapping_event (display, event);
break;
default:
break;
@@ -2027,6 +2033,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_window = window;
display->grab_xwindow = grab_xwindow;
display->grab_button = button;
+ display->grab_mask = modmask;
display->grab_root_x = root_x;
display->grab_root_y = root_y;
display->grab_initial_window_pos = display->grab_window->rect;
@@ -2108,9 +2115,6 @@ meta_display_end_grab_op (MetaDisplay *display,
}
}
-#define IGNORED_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
-#define INTERESTING_MODIFIERS (~IGNORED_MODIFIERS)
-
static void
meta_change_button_grab (MetaDisplay *display,
Window xwindow,
@@ -2119,22 +2123,16 @@ meta_change_button_grab (MetaDisplay *display,
int button,
int modmask)
{
- /* Instead of this hacky mess copied from fvwm, WindowMaker just
- * grabs with all numlock/scrolllock combinations and doesn't grab
- * for other weird bits.
- */
int ignored_mask;
- g_return_if_fail ((modmask & INTERESTING_MODIFIERS) == modmask);
-
ignored_mask = 0;
- while (ignored_mask < IGNORED_MODIFIERS)
+ while (ignored_mask < (int) display->ignored_modifier_mask)
{
int result;
- 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;
diff --git a/src/display.h b/src/display.h
index 9de86b5d..9bf2945b 100644
--- a/src/display.h
+++ b/src/display.h
@@ -40,13 +40,14 @@ struct _MetaRectangle
int height;
};
-typedef struct _MetaDisplay MetaDisplay;
-typedef struct _MetaFrame MetaFrame;
-typedef struct _MetaScreen MetaScreen;
-typedef struct _MetaStack MetaStack;
-typedef struct _MetaUISlave MetaUISlave;
-typedef struct _MetaWindow MetaWindow;
-typedef struct _MetaWorkspace MetaWorkspace;
+typedef struct _MetaDisplay MetaDisplay;
+typedef struct _MetaFrame MetaFrame;
+typedef struct _MetaKeyBinding MetaKeyBinding;
+typedef struct _MetaScreen MetaScreen;
+typedef struct _MetaStack MetaStack;
+typedef struct _MetaUISlave MetaUISlave;
+typedef struct _MetaWindow MetaWindow;
+typedef struct _MetaWorkspace MetaWorkspace;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
@@ -188,6 +189,22 @@ struct _MetaDisplay
guint grab_have_keyboard : 1;
MetaRectangle grab_initial_window_pos;
MetaResizePopup *grab_resize_popup;
+
+
+ /* Keybindings stuff */
+ MetaKeyBinding *screen_bindings;
+ int n_screen_bindings;
+ MetaKeyBinding *window_bindings;
+ int n_window_bindings;
+ int min_keycode;
+ int max_keycode;
+ KeySym *keymap;
+ int keysyms_per_keycode;
+ XModifierKeymap *modmap;
+ unsigned int ignored_modifier_mask;
+ unsigned int num_lock_mask;
+ unsigned int scroll_lock_mask;
+ unsigned int mode_switch_mask;
};
gboolean meta_display_open (const char *name);
diff --git a/src/keybindings.c b/src/keybindings.c
index b259cf24..7181e971 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");
}
}
diff --git a/src/keybindings.h b/src/keybindings.h
index 85255a78..20187e07 100644
--- a/src/keybindings.h
+++ b/src/keybindings.h
@@ -25,17 +25,20 @@
#include "display.h"
#include "window.h"
-void meta_display_init_keys (MetaDisplay *display);
-void meta_screen_grab_keys (MetaScreen *screen);
-void meta_screen_ungrab_keys (MetaScreen *screen);
-void meta_window_grab_keys (MetaWindow *window);
-void meta_window_ungrab_keys (MetaWindow *window);
-gboolean meta_window_grab_all_keys (MetaWindow *window);
-void meta_window_ungrab_all_keys (MetaWindow *window);
-void meta_display_process_key_event (MetaDisplay *display,
- MetaWindow *window,
- XEvent *event);
-void meta_set_keybindings_disabled (gboolean setting);
+void meta_display_init_keys (MetaDisplay *display);
+void meta_display_shutdown_keys (MetaDisplay *display);
+void meta_screen_grab_keys (MetaScreen *screen);
+void meta_screen_ungrab_keys (MetaScreen *screen);
+void meta_window_grab_keys (MetaWindow *window);
+void meta_window_ungrab_keys (MetaWindow *window);
+gboolean meta_window_grab_all_keys (MetaWindow *window);
+void meta_window_ungrab_all_keys (MetaWindow *window);
+void meta_display_process_key_event (MetaDisplay *display,
+ MetaWindow *window,
+ XEvent *event);
+void meta_set_keybindings_disabled (gboolean setting);
+void meta_display_process_mapping_event (MetaDisplay *display,
+ XEvent *event);
#endif
diff --git a/src/metacity.schemas b/src/metacity.schemas
index e8aa7b34..e7724180 100644
--- a/src/metacity.schemas
+++ b/src/metacity.schemas
@@ -107,11 +107,11 @@
</locale>
</schema>
- <!-- Keybindings -->
+ <!-- Window Keybindings -->
<schema>
- <key>/schemas/apps/metacity/keybindings/activate_window_menu</key>
- <applyto>/apps/metacity/keybindings/activate_window_menu</applyto>
+ <key>/schemas/apps/metacity/window_keybindings/activate_window_menu</key>
+ <applyto>/apps/metacity/window_keybindings/activate_window_menu</applyto>
<owner>metacity</owner>
<type>string</type>
<default>&lt;Alt&gt;space</default>
@@ -119,18 +119,1034 @@
<short>Activate window menu</short>
<long>
The keybinding used to activate the window menu.
- The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
- "&lt;Release&gt;z" (the last one is for key release). The parser is
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
fairly liberal and allows lower or upper case, and also
- abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". This option can be
- set to a single string, or a list of strings; if a list,
- all of the given keybindings will be present. If you set
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
the option to the special string "disabled", then there
will be no keybinding for this action.
</long>
</locale>
</schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/toggle_fullscreen</key>
+ <applyto>/apps/metacity/window_keybindings/toggle_fullscreen</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Toggle fullscreen mode</short>
+ <long>
+ The keybinding used to toggle fullscreen mode.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/toggle_maximized</key>
+ <applyto>/apps/metacity/window_keybindings/toggle_maximized</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Toggle maximization state</short>
+ <long>
+ The keybinding used to toggle maximization.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/toggle_shaded</key>
+ <applyto>/apps/metacity/window_keybindings/toggle_shaded</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Toggle shaded state</short>
+ <long>
+ The keybinding used to toggle shaded/unshaded state.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/close</key>
+ <applyto>/apps/metacity/window_keybindings/close</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Close a window</short>
+ <long>
+ The keybinding used to close a window.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/begin_move</key>
+ <applyto>/apps/metacity/window_keybindings/begin_move</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move a window</short>
+ <long>
+ The keybinding used to enter "move mode" and begin moving a
+ window using the keyboard.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/begin_resize</key>
+ <applyto>/apps/metacity/window_keybindings/begin_resize</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move a window</short>
+ <long>
+ The keybinding used to enter "resize mode" and begin resizing a
+ window using the keyboard.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/toggle_on_all_workspaces</key>
+ <applyto>/apps/metacity/window_keybindings/toggle_on_all_workspaces</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Toggle whether the window is on all workspaces</short>
+ <long>
+ The keybinding used to toggle whether the window is on all
+ workspaces or just one.
+ The format looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1.
+ The parser is
+ fairly liberal and allows lower or upper case, and also
+ abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If
+you set
+ the option to the special string "disabled", then there
+ will be no keybinding for this action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_1</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_1</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 1</short>
+ <long>
+ The keybinding used to move a window to workspace 1.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_2</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_2</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 2</short>
+ <long>
+ The keybinding used to move a window to workspace 2.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_3</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_3</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 3</short>
+ <long>
+ The keybinding used to move a window to workspace 3.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_4</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_4</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 4</short>
+ <long>
+ The keybinding used to move a window to workspace 4.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_5</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_5</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 5</short>
+ <long>
+ The keybinding used to move a window to workspace 5.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_6</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_6</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 6</short>
+ <long>
+ The keybinding used to move a window to workspace 6.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_7</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_7</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 7</short>
+ <long>
+ The keybinding used to move a window to workspace 7.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_8</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_8</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 8</short>
+ <long>
+ The keybinding used to move a window to workspace 8.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_9</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_9</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 9</short>
+ <long>
+ The keybinding used to move a window to workspace 9.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_10</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_10</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 10</short>
+ <long>
+ The keybinding used to move a window to workspace 10.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_11</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_11</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 11</short>
+ <long>
+ The keybinding used to move a window to workspace 11.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_12</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_12</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window to workspace 6</short>
+ <long>
+ The keybinding used to move a window to workspace 6.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_left</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_left</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window one workspace to the left</short>
+ <long>
+ The keybinding used to move a window one workspace to the left.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_right</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_right</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window one workspace to the right</short>
+ <long>
+ The keybinding used to move a window one workspace to the right.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_up</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_up</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window one workspace up</short>
+ <long>
+ The keybinding used to move a window one workspace up.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/window_keybindings/move_to_workspace_down</key>
+ <applyto>/apps/metacity/window_keybindings/move_to_workspace_down</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Move window one workspace down</short>
+ <long>
+ The keybinding used to move a window one workspace down.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <!-- Global Keybindings -->
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_windows</key>
+ <applyto>/apps/metacity/global_keybindings/switch_windows</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Tab</default>
+ <locale name="C">
+ <short>Move focus between windows</short>
+ <long>
+ The keybinding used to move focus between windows.
+ (Traditionally &lt;Alt&gt;Tab)
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_panels</key>
+ <applyto>/apps/metacity/global_keybindings/switch_panels</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Control&gt;&lt;Alt&gt;Tab</default>
+ <locale name="C">
+ <short>Move focus between panels and the desktop</short>
+ <long>
+ The keybinding used to move focus between panels and
+ the desktop.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/focus_previous_window</key>
+ <applyto>/apps/metacity/global_keybindings/focus_previous_window</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Escape</default>
+ <locale name="C">
+ <short>Move focus to the previously-focused window</short>
+ <long>
+ The keybinding used to move focus back to the window which last
+ had the focus.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/show_desktop</key>
+ <applyto>/apps/metacity/global_keybindings/show_desktop</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Control&gt;&lt;Alt&gt;d</default>
+ <locale name="C">
+ <short>Hide all windows and focus desktop</short>
+ <long>
+ The keybinding used to hide all normal windows and set the
+ focus to the desktop background.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_1</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_1</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 1</short>
+ <long>
+ The keybinding that switches to workspace 1.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_2</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_2</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 2</short>
+ <long>
+ The keybinding that switches to workspace 2.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_3</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_3</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 3</short>
+ <long>
+ The keybinding that switches to workspace 3.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_4</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_4</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 4</short>
+ <long>
+ The keybinding that switches to workspace 4.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_5</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_5</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 5</short>
+ <long>
+ The keybinding that switches to workspace 5.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_6</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_6</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 6</short>
+ <long>
+ The keybinding that switches to workspace 6.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_7</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_7</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 7</short>
+ <long>
+ The keybinding that switches to workspace 7.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_8</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_8</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 8</short>
+ <long>
+ The keybinding that switches to workspace 8.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_9</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_9</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 9</short>
+ <long>
+ The keybinding that switches to workspace 9.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_10</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_10</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 10</short>
+ <long>
+ The keybinding that switches to workspace 10.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_11</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_11</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 11</short>
+ <long>
+ The keybinding that switches to workspace 11.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_12</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_12</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>disabled</default>
+ <locale name="C">
+ <short>Switch to workspace 12</short>
+ <long>
+ The keybinding that switches to workspace 12.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_left</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_left</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Left</default>
+ <locale name="C">
+ <short>Switch to workspace on the left</short>
+ <long>
+ The keybinding that switches to the workspace on the left
+ of the current workspace.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_right</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_right</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Right</default>
+ <locale name="C">
+ <short>Switch to workspace on the right</short>
+ <long>
+ The keybinding that switches to the workspace on the right
+ of the current workspace.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_up</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_up</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Up</default>
+ <locale name="C">
+ <short>Switch to workspace above the current space</short>
+ <long>
+ The keybinding that switches to the workspace above
+ the current workspace.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <schema>
+ <key>/schemas/apps/metacity/global_keybindings/switch_to_workspace_down</key>
+ <applyto>/apps/metacity/global_keybindings/switch_to_workspace_down</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>&lt;Alt&gt;Down</default>
+ <locale name="C">
+ <short>Switch to workspace below the current space</short>
+ <long>
+ The keybinding that switches to the workspace below
+ the current workspace.
+
+ The format looks like "&lt;Control&gt;a" or
+ "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+ The parser is fairly liberal and allows lower or upper case,
+ and also abbreviations such as "&lt;Ctl&gt;" and
+ "&lt;Ctrl&gt;". If you set the option to the special string
+ "disabled", then there will be no keybinding for this
+ action.
+ </long>
+ </locale>
+ </schema>
+
+
+ <!-- Not used and/or crackrock -->
+
<schema>
<key>/schemas/apps/metacity/general/application_based</key>
<applyto>/apps/metacity/general/application_based</applyto>
@@ -138,7 +1154,7 @@
<type>bool</type>
<default>false</default>
<locale name="C">
- <short>Navigation works in terms of applications not windows</short>
+ <short>(Not implemented) Navigation works in terms of applications not windows</short>
<long>
If true, then Metacity works in terms of applications rather
than windows. The concept is a bit abstract, but
diff --git a/src/prefs.c b/src/prefs.c
index ba898f58..def0f07d 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -21,6 +21,7 @@
#include <config.h>
#include "prefs.h"
+#include "ui.h"
#include "util.h"
#include <gconf/gconf-client.h>
#include <string.h>
@@ -36,6 +37,9 @@
#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces"
#define KEY_APPLICATION_BASED "/apps/metacity/general/application_based"
+#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
+#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
+
static GConfClient *default_client = NULL;
static GList *listeners = NULL;
static GList *changes = NULL;
@@ -55,6 +59,13 @@ static gboolean update_focus_mode (const char *value);
static gboolean update_theme (const char *value);
static gboolean update_num_workspaces (int value);
static gboolean update_application_based (gboolean value);
+static gboolean update_window_binding (const char *name,
+ const char *value);
+static gboolean update_screen_binding (const char *name,
+ const char *value);
+static void init_bindings (void);
+static gboolean update_binding (MetaKeyPref *binding,
+ const char *value);
static void queue_changed (MetaPreference pref);
static void change_notify (GConfClient *client,
@@ -173,9 +184,11 @@ queue_changed (MetaPreference pref)
else
meta_verbose ("Change of pref %s was already pending\n",
meta_preference_to_string (pref));
-
+
+ /* add idle at priority below the gconf notify idle */
if (changed_idle == 0)
- changed_idle = g_idle_add (changed_idle_handler, NULL);
+ changed_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 10,
+ changed_idle_handler, NULL, NULL);
}
static void
@@ -251,6 +264,9 @@ meta_prefs_init (void)
&err);
cleanup_error (&err);
update_application_based (bool_val);
+
+ /* Load keybindings prefs */
+ init_bindings ();
gconf_client_notify_add (default_client, "/apps/metacity",
change_notify,
@@ -260,6 +276,27 @@ meta_prefs_init (void)
cleanup_error (&err);
}
+/* from eel */
+static gboolean
+str_has_prefix (const char *haystack, const char *needle)
+{
+ const char *h, *n;
+
+ /* Eat one character at a time. */
+ h = haystack == NULL ? "" : haystack;
+ n = needle == NULL ? "" : needle;
+ do
+ {
+ if (*n == '\0')
+ return TRUE;
+ if (*h == '\0')
+ return FALSE;
+ }
+ while (*h++ == *n++);
+
+ return FALSE;
+}
+
static void
change_notify (GConfClient *client,
guint cnxn_id,
@@ -388,6 +425,38 @@ change_notify (GConfClient *client,
if (update_application_based (b))
queue_changed (META_PREF_APPLICATION_BASED);
}
+ else if (str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
+ {
+ const char *str;
+
+ if (value && value->type != GCONF_VALUE_STRING)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
+
+ str = value ? gconf_value_get_string (value) : NULL;
+
+ if (update_window_binding (key, str))
+ queue_changed (META_PREF_WINDOW_KEYBINDINGS);
+ }
+ else if (str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
+ {
+ const char *str;
+
+ if (value && value->type != GCONF_VALUE_STRING)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
+
+ str = value ? gconf_value_get_string (value) : NULL;
+
+ if (update_screen_binding (key, str))
+ queue_changed (META_PREF_SCREEN_KEYBINDINGS);
+ }
else
{
meta_verbose ("Key %s doesn't mean anything to Metacity\n",
@@ -589,27 +658,27 @@ meta_preference_to_string (MetaPreference pref)
{
case META_PREF_FOCUS_MODE:
return "FOCUS_MODE";
- break;
case META_PREF_THEME:
return "THEME";
- break;
case META_PREF_TITLEBAR_FONT:
return "TITLEBAR_FONT";
- break;
case META_PREF_TITLEBAR_FONT_SIZE:
return "TITLEBAR_FONT_SIZE";
- break;
case META_PREF_NUM_WORKSPACES:
return "NUM_WORKSPACES";
- break;
case META_PREF_APPLICATION_BASED:
return "APPLICATION_BASED";
- break;
+
+ case META_PREF_SCREEN_KEYBINDINGS:
+ return "SCREEN_KEYBINDINGS";
+
+ case META_PREF_WINDOW_KEYBINDINGS:
+ return "WINDOW_KEYBINDINGS";
}
return "(unknown)";
@@ -642,3 +711,222 @@ meta_prefs_set_num_workspaces (int n_workspaces)
g_error_free (err);
}
}
+
+static MetaKeyPref screen_bindings[] = {
+ { META_KEYBINDING_WORKSPACE_1, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_2, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_3, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_4, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_5, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_6, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_7, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_8, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_9, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_10, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_11, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_12, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_LEFT, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_RIGHT, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_UP, 0, 0 },
+ { META_KEYBINDING_WORKSPACE_DOWN, 0, 0 },
+ { META_KEYBINDING_SWITCH_WINDOWS, 0, 0 },
+ { META_KEYBINDING_SWITCH_PANELS, 0, 0 },
+ { META_KEYBINDING_FOCUS_PREVIOUS, 0, 0 },
+ { META_KEYBINDING_SHOW_DESKTOP, 0, 0 },
+ { NULL, 0, 0 }
+};
+
+static MetaKeyPref window_bindings[] = {
+ { META_KEYBINDING_WINDOW_MENU, 0, 0 },
+ { META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0 },
+ { META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0 },
+ { META_KEYBINDING_TOGGLE_SHADE, 0, 0 },
+ { META_KEYBINDING_CLOSE, 0, 0 },
+ { META_KEYBINDING_BEGIN_MOVE, 0, 0 },
+ { META_KEYBINDING_BEGIN_RESIZE, 0, 0 },
+ { META_KEYBINDING_TOGGLE_STICKY, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0 },
+ { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0 },
+ { NULL, 0, 0 }
+};
+
+static void
+init_bindings (void)
+{
+ int i;
+ GError *err;
+
+ i = 0;
+ while (window_bindings[i].name)
+ {
+ char *str_val;
+ char *key;
+
+ key = g_strconcat (KEY_WINDOW_BINDINGS_PREFIX, "/",
+ window_bindings[i].name, NULL);
+
+ err = NULL;
+ str_val = gconf_client_get_string (default_client, key, &err);
+ cleanup_error (&err);
+
+ update_binding (&window_bindings[i], str_val);
+
+ g_free (str_val);
+ g_free (key);
+
+ ++i;
+ }
+
+ i = 0;
+ while (screen_bindings[i].name)
+ {
+ char *str_val;
+ char *key;
+
+ key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
+ screen_bindings[i].name, NULL);
+
+ err = NULL;
+ str_val = gconf_client_get_string (default_client, key, &err);
+ cleanup_error (&err);
+
+ update_binding (&screen_bindings[i], str_val);
+
+ g_free (str_val);
+ g_free (key);
+
+ ++i;
+ }
+}
+
+static gboolean
+update_binding (MetaKeyPref *binding,
+ const char *value)
+{
+ unsigned int keysym;
+ unsigned long mask;
+ gboolean changed;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Binding \"%s\" has new gconf value \"%s\"\n",
+ binding->name, value ? value : "none");
+
+ keysym = 0;
+ mask = 0;
+ if (value)
+ {
+ if (!meta_ui_parse_accelerator (value, &keysym, &mask))
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Failed to parse new gconf value\n");
+ meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\""),
+ value, binding->name);
+ }
+ }
+
+ changed = FALSE;
+ if (keysym != binding->keysym ||
+ mask != binding->mask)
+ {
+ changed = TRUE;
+
+ binding->keysym = keysym;
+ binding->mask = mask;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "New keybinding for \"%s\" is keysym = 0x%x mask = 0x%lx\n",
+ binding->name, binding->keysym, binding->mask);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Keybinding for \"%s\" is unchanged\n", binding->name);
+ }
+
+ return changed;
+}
+
+static const gchar*
+relative_key (const gchar* key)
+{
+ const gchar* end;
+
+ end = strrchr (key, '/');
+
+ ++end;
+
+ return end;
+}
+
+/* Return value is TRUE if a preference changed and we need to
+ * notify
+ */
+static gboolean
+find_and_update_binding (MetaKeyPref *bindings,
+ const char *name,
+ const char *value)
+{
+ const char *key;
+ int i;
+
+ if (*name == '/')
+ key = relative_key (name);
+ else
+ key = name;
+
+ i = 0;
+ while (bindings[i].name &&
+ strcmp (key, bindings[i].name) != 0)
+ ++i;
+
+ if (bindings[i].name)
+ return update_binding (&bindings[i], value);
+ else
+ return FALSE;
+}
+
+static gboolean
+update_window_binding (const char *name,
+ const char *value)
+{
+ return find_and_update_binding (window_bindings, name, value);
+}
+
+static gboolean
+update_screen_binding (const char *name,
+ const char *value)
+{
+ return find_and_update_binding (screen_bindings, name, value);
+}
+
+void
+meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
+ int *n_bindings)
+{
+
+ *bindings = screen_bindings;
+ *n_bindings = (int) G_N_ELEMENTS (screen_bindings) - 1;
+}
+
+void
+meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
+ int *n_bindings)
+{
+ *bindings = window_bindings;
+ *n_bindings = (int) G_N_ELEMENTS (window_bindings) - 1;
+}
+
diff --git a/src/prefs.h b/src/prefs.h
index 0684dd2c..2b94ee77 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -33,7 +33,9 @@ typedef enum
META_PREF_TITLEBAR_FONT,
META_PREF_TITLEBAR_FONT_SIZE,
META_PREF_NUM_WORKSPACES,
- META_PREF_APPLICATION_BASED
+ META_PREF_APPLICATION_BASED,
+ META_PREF_WINDOW_KEYBINDINGS,
+ META_PREF_SCREEN_KEYBINDINGS
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -58,6 +60,66 @@ gboolean meta_prefs_get_application_based (void);
void meta_prefs_set_num_workspaces (int n_workspaces);
+/* Screen bindings */
+#define META_KEYBINDING_WORKSPACE_1 "switch_to_workspace_1"
+#define META_KEYBINDING_WORKSPACE_2 "switch_to_workspace_2"
+#define META_KEYBINDING_WORKSPACE_3 "switch_to_workspace_3"
+#define META_KEYBINDING_WORKSPACE_4 "switch_to_workspace_4"
+#define META_KEYBINDING_WORKSPACE_5 "switch_to_workspace_5"
+#define META_KEYBINDING_WORKSPACE_6 "switch_to_workspace_6"
+#define META_KEYBINDING_WORKSPACE_7 "switch_to_workspace_7"
+#define META_KEYBINDING_WORKSPACE_8 "switch_to_workspace_8"
+#define META_KEYBINDING_WORKSPACE_9 "switch_to_workspace_9"
+#define META_KEYBINDING_WORKSPACE_10 "switch_to_workspace_10"
+#define META_KEYBINDING_WORKSPACE_11 "switch_to_workspace_11"
+#define META_KEYBINDING_WORKSPACE_12 "switch_to_workspace_12"
+#define META_KEYBINDING_WORKSPACE_LEFT "switch_to_workspace_left"
+#define META_KEYBINDING_WORKSPACE_RIGHT "switch_to_workspace_right"
+#define META_KEYBINDING_WORKSPACE_UP "switch_to_workspace_up"
+#define META_KEYBINDING_WORKSPACE_DOWN "switch_to_workspace_down"
+#define META_KEYBINDING_SWITCH_WINDOWS "switch_windows"
+#define META_KEYBINDING_SWITCH_PANELS "switch_panels"
+#define META_KEYBINDING_FOCUS_PREVIOUS "focus_previous_window"
+#define META_KEYBINDING_SHOW_DESKTOP "show_desktop"
+
+/* Window bindings */
+#define META_KEYBINDING_WINDOW_MENU "activate_window_menu"
+#define META_KEYBINDING_TOGGLE_FULLSCREEN "toggle_fullscreen"
+#define META_KEYBINDING_TOGGLE_MAXIMIZE "toggle_maximized"
+#define META_KEYBINDING_TOGGLE_SHADE "toggle_shaded"
+#define META_KEYBINDING_CLOSE "close"
+#define META_KEYBINDING_BEGIN_MOVE "begin_move"
+#define META_KEYBINDING_BEGIN_RESIZE "begin_resize"
+#define META_KEYBINDING_TOGGLE_STICKY "toggle_on_all_workspaces"
+#define META_KEYBINDING_MOVE_WORKSPACE_1 "move_to_workspace_1"
+#define META_KEYBINDING_MOVE_WORKSPACE_2 "move_to_workspace_2"
+#define META_KEYBINDING_MOVE_WORKSPACE_3 "move_to_workspace_3"
+#define META_KEYBINDING_MOVE_WORKSPACE_4 "move_to_workspace_4"
+#define META_KEYBINDING_MOVE_WORKSPACE_5 "move_to_workspace_5"
+#define META_KEYBINDING_MOVE_WORKSPACE_6 "move_to_workspace_6"
+#define META_KEYBINDING_MOVE_WORKSPACE_7 "move_to_workspace_7"
+#define META_KEYBINDING_MOVE_WORKSPACE_8 "move_to_workspace_8"
+#define META_KEYBINDING_MOVE_WORKSPACE_9 "move_to_workspace_9"
+#define META_KEYBINDING_MOVE_WORKSPACE_10 "move_to_workspace_10"
+#define META_KEYBINDING_MOVE_WORKSPACE_11 "move_to_workspace_11"
+#define META_KEYBINDING_MOVE_WORKSPACE_12 "move_to_workspace_12"
+#define META_KEYBINDING_MOVE_WORKSPACE_LEFT "move_to_workspace_left"
+#define META_KEYBINDING_MOVE_WORKSPACE_RIGHT "move_to_workspace_right"
+#define META_KEYBINDING_MOVE_WORKSPACE_UP "move_to_workspace_up"
+#define META_KEYBINDING_MOVE_WORKSPACE_DOWN "move_to_workspace_down"
+
+typedef struct
+{
+ const char *name;
+ unsigned int keysym;
+ unsigned long mask;
+} MetaKeyPref;
+
+void meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
+ int *n_bindings);
+void meta_prefs_get_window_bindings (const MetaKeyPref **bindings,
+ int *n_bindings);
+
#endif
diff --git a/src/screen.c b/src/screen.c
index f02e99d2..9a5f2d56 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -312,7 +312,8 @@ meta_screen_new (MetaDisplay *display,
*/
screen->active_workspace = meta_workspace_new (screen);
update_num_workspaces (screen);
-
+
+ screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
screen->ui = meta_ui_new (screen->display->xdisplay,
diff --git a/src/screen.h b/src/screen.h
index 6b8c3549..12915e7b 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -62,6 +62,8 @@ struct _MetaScreen
MetaXineramaScreenInfo *xinerama_infos;
int n_xinerama_infos;
+
+ guint keys_grabbed : 1;
};
MetaScreen* meta_screen_new (MetaDisplay *display,
diff --git a/src/ui.c b/src/ui.c
index 5a512ec3..1dbd662a 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -31,6 +31,8 @@
#include <pango/pangox.h>
+#include <string.h>
+
struct _MetaUI
{
Display *xdisplay;
@@ -592,3 +594,47 @@ meta_ui_have_a_theme (void)
{
return meta_theme_get_current () != NULL;
}
+
+gboolean
+meta_ui_parse_accelerator (const char *accel,
+ unsigned int *keysym,
+ unsigned long *mask)
+{
+ GdkModifierType gdk_mask = 0;
+ guint gdk_sym = 0;
+
+ *keysym = 0;
+ *mask = 0;
+
+ if (strcmp (accel, "disabled") == 0)
+ return TRUE;
+
+ gtk_accelerator_parse (accel, &gdk_sym, &gdk_mask);
+
+ if (gdk_sym == None)
+ return FALSE;
+
+ if (gdk_mask & GDK_RELEASE_MASK) /* we don't allow this */
+ return FALSE;
+
+ *keysym = gdk_sym;
+
+ if (gdk_mask & GDK_SHIFT_MASK)
+ *mask |= ShiftMask;
+ if (gdk_mask & GDK_LOCK_MASK)
+ *mask |= LockMask;
+ if (gdk_mask & GDK_CONTROL_MASK)
+ *mask |= ControlMask;
+ if (gdk_mask & GDK_MOD1_MASK)
+ *mask |= Mod1Mask;
+ if (gdk_mask & GDK_MOD2_MASK)
+ *mask |= Mod2Mask;
+ if (gdk_mask & GDK_MOD3_MASK)
+ *mask |= Mod3Mask;
+ if (gdk_mask & GDK_MOD4_MASK)
+ *mask |= Mod4Mask;
+ if (gdk_mask & GDK_MOD5_MASK)
+ *mask |= Mod5Mask;
+
+ return TRUE;
+}
diff --git a/src/ui.h b/src/ui.h
index 1e63f66a..f0f38c5a 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -145,6 +145,9 @@ void meta_ui_set_current_theme (const char *name,
gboolean force_reload);
gboolean meta_ui_have_a_theme (void);
+gboolean meta_ui_parse_accelerator (const char *accel,
+ unsigned int *keysym,
+ unsigned long *mask);
#include "tabpopup.h"
diff --git a/src/util.c b/src/util.c
index e90c7afa..a48edf44 100644
--- a/src/util.c
+++ b/src/util.c
@@ -192,6 +192,8 @@ topic_name (MetaDebugTopic topic)
return "PING";
case META_DEBUG_XINERAMA:
return "XINERAMA";
+ case META_DEBUG_KEYBINDINGS:
+ return "KEYBINDINGS";
}
return "Window manager";
diff --git a/src/util.h b/src/util.h
index fa651aa9..52b87c97 100644
--- a/src/util.h
+++ b/src/util.h
@@ -56,7 +56,8 @@ typedef enum
META_DEBUG_GEOMETRY = 1 << 8,
META_DEBUG_PLACEMENT = 1 << 9,
META_DEBUG_PING = 1 << 10,
- META_DEBUG_XINERAMA = 1 << 11
+ META_DEBUG_XINERAMA = 1 << 11,
+ META_DEBUG_KEYBINDINGS = 1 << 12
} MetaDebugTopic;
diff --git a/src/window.c b/src/window.c
index 3cbf700e..e27f61ac 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1569,6 +1569,12 @@ void
meta_window_activate (MetaWindow *window,
guint32 timestamp)
{
+ /* disable show desktop mode unless we're a desktop component */
+ if (window->display->showing_desktop &&
+ window->type != META_WINDOW_DESKTOP &&
+ window->type != META_WINDOW_DOCK)
+ meta_display_unshow_desktop (window->display);
+
/* Get window on current workspace */
if (!meta_window_visible_on_workspace (window,
window->screen->active_workspace))
@@ -5104,6 +5110,7 @@ menu_callback (MetaWindowMenu *menu,
break;
case META_MENU_OP_RESIZE:
+ /* FIXME */
break;
case 0:
diff --git a/src/workspace.c b/src/workspace.c
index e88a976c..a673deba 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -441,3 +441,31 @@ meta_workspace_get_work_area (MetaWorkspace *workspace,
*area = workspace->work_area;
}
+
+MetaWorkspace*
+meta_workspace_get_neighbor (MetaWorkspace *workspace,
+ MetaMotionDirection direction)
+{
+ /* FIXME this isn't using any sane layout, just assuming
+ * the spaces are in a big row
+ */
+ int i;
+
+ i = meta_workspace_index (workspace);
+
+ switch (direction)
+ {
+ case META_MOTION_LEFT:
+ --i;
+ break;
+ case META_MOTION_RIGHT:
+ ++i;
+ break;
+ case META_MOTION_UP:
+ case META_MOTION_DOWN:
+ return NULL;
+ }
+
+ return meta_display_get_workspace_by_index (workspace->screen->display,
+ i);
+}
diff --git a/src/workspace.h b/src/workspace.h
index 46439d24..c55af458 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -24,6 +24,17 @@
#include "window.h"
+/* Negative to avoid conflicting with real workspace
+ * numbers
+ */
+typedef enum
+{
+ META_MOTION_UP = -1,
+ META_MOTION_DOWN = -2,
+ META_MOTION_LEFT = -3,
+ META_MOTION_RIGHT = -4
+} MetaMotionDirection;
+
struct _MetaWorkspace
{
MetaScreen *screen;
@@ -55,6 +66,9 @@ void meta_workspace_get_work_area (MetaWorkspace *workspace,
MetaRectangle *area);
+MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace,
+ MetaMotionDirection direction);
+
#endif