[mutter] Add support for a "meta key" which initiates extended WM operations
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Subject: [mutter] Add support for a "meta key" which initiates extended WM operations
- Date: Fri, 24 Apr 2009 09:57:04 -0400 (EDT)
commit 514d00698d1ba0bf8d8c3bee07b19e2acf01289e
Author: Colin Walters <walters verbum org>
Date: Tue Dec 2 18:13:11 2008 -0500
Add support for a "meta key" which initiates extended WM operations
This patch adds the concept of a special key for WM operations, and
the default is Super_L, which on extended PC hardware is the
"Windows key". What we do is handle the special case of a press
and release of this key (without any other intervening keys).
Super_L+<key> should still be passed to applications. In the future
we may want to also take some of these keybindings (e.g. Super+TAB)
though.
http://bugzilla.gnome.org/show_bug.cgi?id=563047
---
src/core/display-private.h | 5 +++
src/core/display.c | 23 ++++++++++++++
src/core/keybindings.c | 69 ++++++++++++++++++++++++++++++++++++++++---
src/core/prefs.c | 48 ++++++++++++++++++++++++++++++
src/core/screen.c | 7 ++++
src/include/prefs.h | 2 +
src/metacity.schemas.in.in | 19 ++++++++++++
7 files changed, 168 insertions(+), 5 deletions(-)
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 8b10e7e..2f75063 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -38,6 +38,7 @@
#include "boxes.h"
#include "display.h"
#include "keybindings-private.h"
+#include "prefs.h"
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@@ -214,6 +215,8 @@ struct _MetaDisplay
unsigned int hyper_mask;
unsigned int super_mask;
unsigned int meta_mask;
+ MetaKeyCombo overlay_key_combo;
+ gboolean overlay_key_only_pressed;
/* Xinerama cache */
unsigned int xinerama_cache_invalidated : 1;
@@ -434,4 +437,6 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
MetaWindow *window);
void meta_display_remove_autoraise_callback (MetaDisplay *display);
+void meta_display_overlay_key_activate (MetaDisplay *display);
+
#endif
diff --git a/src/core/display.c b/src/core/display.c
index 8442d1e..d627b5c 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -129,6 +129,15 @@ typedef struct
G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
+/* Signals */
+enum
+{
+ OVERLAY_KEY,
+ LAST_SIGNAL
+};
+
+static guint display_signals [LAST_SIGNAL] = { 0 };
+
/**
* The display we're managing. This is a singleton object. (Historically,
* this was a list of displays, but there was never any way to add more
@@ -168,6 +177,14 @@ MetaGroup* get_focussed_group (MetaDisplay *display);
static void
meta_display_class_init (MetaDisplayClass *klass)
{
+ display_signals[OVERLAY_KEY] =
+ g_signal_new ("overlay-key",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
/**
@@ -5167,6 +5184,12 @@ meta_display_remove_autoraise_callback (MetaDisplay *display)
}
}
+void
+meta_display_overlay_key_activate (MetaDisplay *display)
+{
+ g_signal_emit (display, display_signals[OVERLAY_KEY], 0);
+}
+
#ifdef HAVE_COMPOSITE_EXTENSIONS
void
meta_display_get_compositor_version (MetaDisplay *display,
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 045cd7e..0fe62e4 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -234,7 +234,14 @@ reload_keycodes (MetaDisplay *display)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Reloading keycodes for binding tables\n");
-
+
+ if (display->overlay_key_combo.keysym
+ && display->overlay_key_combo.keycode == 0)
+ {
+ display->overlay_key_combo.keycode = XKeysymToKeycode (
+ display->xdisplay, display->overlay_key_combo.keysym);
+ }
+
if (display->key_bindings)
{
int i;
@@ -422,6 +429,19 @@ rebuild_key_binding_table (MetaDisplay *display)
}
static void
+rebuild_special_bindings (MetaDisplay *display)
+{
+ MetaKeyCombo combo;
+
+ meta_prefs_get_overlay_binding (&combo);
+
+ if (combo.keysym != None || combo.keycode != 0)
+ {
+ display->overlay_key_combo = combo;
+ }
+}
+
+static void
regrab_key_bindings (MetaDisplay *display)
{
GSList *tmp;
@@ -521,6 +541,7 @@ bindings_changed_callback (MetaPreference pref,
{
case META_PREF_KEYBINDINGS:
rebuild_key_binding_table (display);
+ rebuild_special_bindings (display);
reload_keycodes (display);
reload_modifiers (display);
regrab_key_bindings (display);
@@ -562,6 +583,7 @@ meta_display_init_keys (MetaDisplay *display)
reload_modmap (display);
rebuild_key_binding_table (display);
+ rebuild_special_bindings (display);
reload_keycodes (display);
reload_modifiers (display);
@@ -742,11 +764,18 @@ ungrab_all_keys (MetaDisplay *display,
void
meta_screen_grab_keys (MetaScreen *screen)
{
+ MetaDisplay *display = screen->display;
if (screen->all_keys_grabbed)
return;
if (screen->keys_grabbed)
return;
+
+ if (display->overlay_key_combo.keycode != 0)
+ meta_grab_key (display, screen->xroot,
+ display->overlay_key_combo.keysym,
+ display->overlay_key_combo.keycode,
+ display->overlay_key_combo.modifiers);
grab_keys (screen->display->key_bindings,
screen->display->n_key_bindings,
@@ -1140,6 +1169,31 @@ primary_modifier_still_pressed (MetaDisplay *display,
return TRUE;
}
+static gboolean
+process_overlay_key (MetaDisplay *display,
+ MetaScreen *Screen,
+ XEvent *event,
+ KeySym keysym)
+{
+ if (event->xkey.keycode != display->overlay_key_combo.keycode)
+ {
+ display->overlay_key_only_pressed = FALSE;
+ return FALSE;
+ }
+
+ if (event->xkey.type == KeyPress)
+ {
+ display->overlay_key_only_pressed = TRUE;
+ }
+ else if (event->xkey.type == KeyRelease && display->overlay_key_only_pressed)
+ {
+ display->overlay_key_only_pressed = FALSE;
+ meta_display_overlay_key_activate (display);
+ }
+
+ return TRUE;
+}
+
/* now called from only one place, may be worth merging */
static gboolean
process_event (MetaKeyBinding *bindings,
@@ -1238,6 +1292,7 @@ meta_display_process_key_event (MetaDisplay *display,
KeySym keysym;
gboolean keep_grab;
gboolean all_keys_grabbed;
+ gboolean handled;
const char *str;
MetaScreen *screen;
@@ -1361,11 +1416,15 @@ meta_display_process_key_event (MetaDisplay *display,
return;
}
}
+
+ handled = process_overlay_key (display, screen, event, keysym);
+
/* Do the normal keybindings */
- process_event (display->key_bindings,
- display->n_key_bindings,
- display, screen, window, event, keysym,
- !all_keys_grabbed && window);
+ if (!handled)
+ process_event (display->key_bindings,
+ display->n_key_bindings,
+ display, screen, window, event, keysym,
+ !all_keys_grabbed && window);
}
static gboolean
diff --git a/src/core/prefs.c b/src/core/prefs.c
index 3633680..6968ab5 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -57,6 +57,7 @@
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
#define KEY_TERMINAL_COMMAND KEY_TERMINAL_DIR "/exec"
+#define KEY_OVERLAY_KEY "/apps/metacity/general/overlay_key"
#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
#define KEY_LIST_BINDINGS_SUFFIX "_list"
@@ -1217,6 +1218,10 @@ change_notify (GConfClient *client,
if (update_workspace_name (key, str))
queue_changed (META_PREF_WORKSPACE_NAMES);
}
+ else if (g_str_equal (key, KEY_OVERLAY_KEY))
+ {
+ queue_changed (META_PREF_KEYBINDINGS);
+ }
#ifdef WITH_CLUTTER
else if (g_str_equal (key, KEY_CLUTTER_PLUGINS) && !clutter_plugins_overridden)
{
@@ -1873,6 +1878,8 @@ static MetaKeyPref key_bindings[] = {
};
#undef keybind
+static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
+
#ifndef HAVE_GCONF
/**
@@ -1906,6 +1913,37 @@ static MetaSimpleKeyMapping key_string_bindings[] = {
#endif /* NOT HAVE_GCONF */
+/* These bindings are for modifiers alone, so they need special handling */
+static void
+init_special_bindings (void)
+{
+#ifdef HAVE_GCONF
+ char *val;
+ GError *err = NULL;
+#endif
+
+ /* Default values for bindings which are global, but take special handling */
+ meta_ui_parse_accelerator ("Super_L", &overlay_key_combo.keysym,
+ &overlay_key_combo.keycode,
+ &overlay_key_combo.modifiers);
+
+#ifdef HAVE_GCONF
+ val = gconf_client_get_string (default_client, KEY_OVERLAY_KEY, &err);
+ cleanup_error (&err);
+
+ if (val && meta_ui_parse_accelerator (val, &overlay_key_combo.keysym,
+ &overlay_key_combo.keycode,
+ &overlay_key_combo.modifiers))
+ ;
+ else
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Failed to parse value for overlay_key\n");
+ }
+ g_free (val);
+#endif
+}
+
static void
init_bindings (void)
{
@@ -1959,9 +1997,11 @@ init_bindings (void)
++i;
}
+
#else /* HAVE_GCONF */
int i = 0;
int which = 0;
+
while (key_string_bindings[i].name)
{
if (key_string_bindings[i].keybinding == NULL) {
@@ -1980,6 +2020,8 @@ init_bindings (void)
++i;
}
#endif /* HAVE_GCONF */
+
+ init_special_bindings ();
}
static void
@@ -2688,6 +2730,12 @@ meta_prefs_get_key_bindings (const MetaKeyPref **bindings,
*n_bindings = (int) G_N_ELEMENTS (key_bindings) - 1;
}
+void
+meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
+{
+ *combo = overlay_key_combo;
+}
+
MetaActionTitlebar
meta_prefs_get_action_double_click_titlebar (void)
{
diff --git a/src/core/screen.c b/src/core/screen.c
index 1769a31..d400775 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -2980,6 +2980,13 @@ meta_screen_get_screen_number (MetaScreen *screen)
return screen->number;
}
+/**
+ * meta_screen_get_display:
+ * Retrieve the display associated with screen.
+ * @screen: A #MetaScreen
+ *
+ * Returns: (transfer none): Display
+ */
MetaDisplay *
meta_screen_get_display (MetaScreen *screen)
{
diff --git a/src/include/prefs.h b/src/include/prefs.h
index 2ef6403..ed419db 100644
--- a/src/include/prefs.h
+++ b/src/include/prefs.h
@@ -247,6 +247,8 @@ void meta_prefs_get_window_binding (const char *name,
unsigned int *keysym,
MetaVirtualModifier *modifiers);
+void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
+
typedef enum
{
META_VISUAL_BELL_INVALID = 0,
diff --git a/src/metacity.schemas.in.in b/src/metacity.schemas.in.in
index 16d486b..29759c9 100644
--- a/src/metacity.schemas.in.in
+++ b/src/metacity.schemas.in.in
@@ -4,6 +4,25 @@
<!-- General preferences -->
<schema>
+ <key>/schemas/apps/metacity/general/overlay_key</key>
+ <applyto>/apps/metacity/general/overlay_key</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default><Super_L></default>
+ <locale name="C">
+ <short>Modifier to use for extended window management operations</short>
+ <long>
+ This key will initiate the "overlay", which is a combination window
+ overview and application launching system. The default is intended
+ to be the "Windows key" on PC hardware.
+
+ It's expected that this binding either the default or set to
+ the empty string.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/metacity/general/mouse_button_modifier</key>
<applyto>/apps/metacity/general/mouse_button_modifier</applyto>
<owner>metacity</owner>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]