[mutter] Add support for a "meta key" which initiates extended WM operations



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>&lt;Super_L&gt;</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]