mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 09:30:45 -05:00
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 "boxes.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "keybindings-private.h"
|
#include "keybindings-private.h"
|
||||||
|
#include "prefs.h"
|
||||||
|
|
||||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
@ -214,6 +215,8 @@ struct _MetaDisplay
|
|||||||
unsigned int hyper_mask;
|
unsigned int hyper_mask;
|
||||||
unsigned int super_mask;
|
unsigned int super_mask;
|
||||||
unsigned int meta_mask;
|
unsigned int meta_mask;
|
||||||
|
MetaKeyCombo overlay_key_combo;
|
||||||
|
gboolean overlay_key_only_pressed;
|
||||||
|
|
||||||
/* Xinerama cache */
|
/* Xinerama cache */
|
||||||
unsigned int xinerama_cache_invalidated : 1;
|
unsigned int xinerama_cache_invalidated : 1;
|
||||||
@ -434,4 +437,6 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
|
|||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
||||||
|
|
||||||
|
void meta_display_overlay_key_activate (MetaDisplay *display);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,6 +129,15 @@ typedef struct
|
|||||||
|
|
||||||
G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
|
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,
|
* 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
|
* 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
|
static void
|
||||||
meta_display_class_init (MetaDisplayClass *klass)
|
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
|
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||||
void
|
void
|
||||||
meta_display_get_compositor_version (MetaDisplay *display,
|
meta_display_get_compositor_version (MetaDisplay *display,
|
||||||
|
@ -234,7 +234,14 @@ reload_keycodes (MetaDisplay *display)
|
|||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||||
"Reloading keycodes for binding tables\n");
|
"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)
|
if (display->key_bindings)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -421,6 +428,19 @@ rebuild_key_binding_table (MetaDisplay *display)
|
|||||||
prefs, n_prefs);
|
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
|
static void
|
||||||
regrab_key_bindings (MetaDisplay *display)
|
regrab_key_bindings (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
@ -521,6 +541,7 @@ bindings_changed_callback (MetaPreference pref,
|
|||||||
{
|
{
|
||||||
case META_PREF_KEYBINDINGS:
|
case META_PREF_KEYBINDINGS:
|
||||||
rebuild_key_binding_table (display);
|
rebuild_key_binding_table (display);
|
||||||
|
rebuild_special_bindings (display);
|
||||||
reload_keycodes (display);
|
reload_keycodes (display);
|
||||||
reload_modifiers (display);
|
reload_modifiers (display);
|
||||||
regrab_key_bindings (display);
|
regrab_key_bindings (display);
|
||||||
@ -562,6 +583,7 @@ meta_display_init_keys (MetaDisplay *display)
|
|||||||
reload_modmap (display);
|
reload_modmap (display);
|
||||||
|
|
||||||
rebuild_key_binding_table (display);
|
rebuild_key_binding_table (display);
|
||||||
|
rebuild_special_bindings (display);
|
||||||
|
|
||||||
reload_keycodes (display);
|
reload_keycodes (display);
|
||||||
reload_modifiers (display);
|
reload_modifiers (display);
|
||||||
@ -742,11 +764,18 @@ ungrab_all_keys (MetaDisplay *display,
|
|||||||
void
|
void
|
||||||
meta_screen_grab_keys (MetaScreen *screen)
|
meta_screen_grab_keys (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = screen->display;
|
||||||
if (screen->all_keys_grabbed)
|
if (screen->all_keys_grabbed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (screen->keys_grabbed)
|
if (screen->keys_grabbed)
|
||||||
return;
|
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,
|
grab_keys (screen->display->key_bindings,
|
||||||
screen->display->n_key_bindings,
|
screen->display->n_key_bindings,
|
||||||
@ -1140,6 +1169,31 @@ primary_modifier_still_pressed (MetaDisplay *display,
|
|||||||
return TRUE;
|
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 */
|
/* now called from only one place, may be worth merging */
|
||||||
static gboolean
|
static gboolean
|
||||||
process_event (MetaKeyBinding *bindings,
|
process_event (MetaKeyBinding *bindings,
|
||||||
@ -1238,6 +1292,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
gboolean keep_grab;
|
gboolean keep_grab;
|
||||||
gboolean all_keys_grabbed;
|
gboolean all_keys_grabbed;
|
||||||
|
gboolean handled;
|
||||||
const char *str;
|
const char *str;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
|
|
||||||
@ -1361,11 +1416,15 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handled = process_overlay_key (display, screen, event, keysym);
|
||||||
|
|
||||||
/* Do the normal keybindings */
|
/* Do the normal keybindings */
|
||||||
process_event (display->key_bindings,
|
if (!handled)
|
||||||
display->n_key_bindings,
|
process_event (display->key_bindings,
|
||||||
display, screen, window, event, keysym,
|
display->n_key_bindings,
|
||||||
!all_keys_grabbed && window);
|
display, screen, window, event, keysym,
|
||||||
|
!all_keys_grabbed && window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
|
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
|
||||||
#define KEY_TERMINAL_COMMAND KEY_TERMINAL_DIR "/exec"
|
#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_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
|
||||||
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
|
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
|
||||||
#define KEY_LIST_BINDINGS_SUFFIX "_list"
|
#define KEY_LIST_BINDINGS_SUFFIX "_list"
|
||||||
@ -1217,6 +1218,10 @@ change_notify (GConfClient *client,
|
|||||||
if (update_workspace_name (key, str))
|
if (update_workspace_name (key, str))
|
||||||
queue_changed (META_PREF_WORKSPACE_NAMES);
|
queue_changed (META_PREF_WORKSPACE_NAMES);
|
||||||
}
|
}
|
||||||
|
else if (g_str_equal (key, KEY_OVERLAY_KEY))
|
||||||
|
{
|
||||||
|
queue_changed (META_PREF_KEYBINDINGS);
|
||||||
|
}
|
||||||
#ifdef WITH_CLUTTER
|
#ifdef WITH_CLUTTER
|
||||||
else if (g_str_equal (key, KEY_CLUTTER_PLUGINS) && !clutter_plugins_overridden)
|
else if (g_str_equal (key, KEY_CLUTTER_PLUGINS) && !clutter_plugins_overridden)
|
||||||
{
|
{
|
||||||
@ -1873,6 +1878,8 @@ static MetaKeyPref key_bindings[] = {
|
|||||||
};
|
};
|
||||||
#undef keybind
|
#undef keybind
|
||||||
|
|
||||||
|
static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
|
||||||
|
|
||||||
#ifndef HAVE_GCONF
|
#ifndef HAVE_GCONF
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1906,6 +1913,37 @@ static MetaSimpleKeyMapping key_string_bindings[] = {
|
|||||||
|
|
||||||
#endif /* NOT HAVE_GCONF */
|
#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
|
static void
|
||||||
init_bindings (void)
|
init_bindings (void)
|
||||||
{
|
{
|
||||||
@ -1959,9 +1997,11 @@ init_bindings (void)
|
|||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* HAVE_GCONF */
|
#else /* HAVE_GCONF */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int which = 0;
|
int which = 0;
|
||||||
|
|
||||||
while (key_string_bindings[i].name)
|
while (key_string_bindings[i].name)
|
||||||
{
|
{
|
||||||
if (key_string_bindings[i].keybinding == NULL) {
|
if (key_string_bindings[i].keybinding == NULL) {
|
||||||
@ -1980,6 +2020,8 @@ init_bindings (void)
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_GCONF */
|
#endif /* HAVE_GCONF */
|
||||||
|
|
||||||
|
init_special_bindings ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2688,6 +2730,12 @@ meta_prefs_get_key_bindings (const MetaKeyPref **bindings,
|
|||||||
*n_bindings = (int) G_N_ELEMENTS (key_bindings) - 1;
|
*n_bindings = (int) G_N_ELEMENTS (key_bindings) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
|
||||||
|
{
|
||||||
|
*combo = overlay_key_combo;
|
||||||
|
}
|
||||||
|
|
||||||
MetaActionTitlebar
|
MetaActionTitlebar
|
||||||
meta_prefs_get_action_double_click_titlebar (void)
|
meta_prefs_get_action_double_click_titlebar (void)
|
||||||
{
|
{
|
||||||
|
@ -2980,6 +2980,13 @@ meta_screen_get_screen_number (MetaScreen *screen)
|
|||||||
return screen->number;
|
return screen->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_screen_get_display:
|
||||||
|
* Retrieve the display associated with screen.
|
||||||
|
* @screen: A #MetaScreen
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): Display
|
||||||
|
*/
|
||||||
MetaDisplay *
|
MetaDisplay *
|
||||||
meta_screen_get_display (MetaScreen *screen)
|
meta_screen_get_display (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
|
@ -247,6 +247,8 @@ void meta_prefs_get_window_binding (const char *name,
|
|||||||
unsigned int *keysym,
|
unsigned int *keysym,
|
||||||
MetaVirtualModifier *modifiers);
|
MetaVirtualModifier *modifiers);
|
||||||
|
|
||||||
|
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
META_VISUAL_BELL_INVALID = 0,
|
META_VISUAL_BELL_INVALID = 0,
|
||||||
|
@ -3,6 +3,25 @@
|
|||||||
|
|
||||||
<!-- General preferences -->
|
<!-- 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>
|
<schema>
|
||||||
<key>/schemas/apps/metacity/general/mouse_button_modifier</key>
|
<key>/schemas/apps/metacity/general/mouse_button_modifier</key>
|
||||||
<applyto>/apps/metacity/general/mouse_button_modifier</applyto>
|
<applyto>/apps/metacity/general/mouse_button_modifier</applyto>
|
||||||
|
Loading…
Reference in New Issue
Block a user