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
This commit is contained in:
parent
c4a4de0056
commit
514d00698d
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
@ -421,6 +428,19 @@ rebuild_key_binding_table (MetaDisplay *display)
|
||||
prefs, n_prefs);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -3,6 +3,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>
|
||||
|
Loading…
Reference in New Issue
Block a user