diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in
index 7bea9d66a..e0a784a01 100644
--- a/data/org.gnome.mutter.gschema.xml.in
+++ b/data/org.gnome.mutter.gschema.xml.in
@@ -127,6 +127,14 @@
+
+ 'Control_L'
+ Modifier to use to locate the pointer
+
+ This key will initiate the “locate pointer” action.
+
+
+
diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h
index d686e6caf..fd1c14212 100644
--- a/src/core/keybindings-private.h
+++ b/src/core/keybindings-private.h
@@ -113,6 +113,9 @@ typedef struct
MetaKeyCombo overlay_key_combo;
MetaResolvedKeyCombo overlay_resolved_key_combo;
gboolean overlay_key_only_pressed;
+ MetaKeyCombo locate_pointer_key_combo;
+ MetaResolvedKeyCombo locate_pointer_resolved_key_combo;
+ gboolean locate_pointer_key_only_pressed;
MetaResolvedKeyCombo iso_next_group_combo[2];
int n_iso_next_group_combos;
@@ -149,6 +152,7 @@ gboolean meta_prefs_remove_keybinding (const char *name);
GList *meta_prefs_get_keybindings (void);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
+void meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
void meta_x11_display_grab_keys (MetaX11Display *x11_display);
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index a99899f80..8e73ce921 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -33,6 +33,7 @@
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#include "backends/x11/meta-backend-x11.h"
+#include "compositor/compositor-private.h"
#include "core/edge-resistance.h"
#include "core/frame.h"
#include "core/keybindings-private.h"
@@ -780,6 +781,10 @@ reload_combos (MetaKeyBindingManager *keys)
&keys->overlay_key_combo,
&keys->overlay_resolved_key_combo);
+ resolve_key_combo (keys,
+ &keys->locate_pointer_key_combo,
+ &keys->locate_pointer_resolved_key_combo);
+
reload_iso_next_group_combos (keys);
g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
@@ -871,6 +876,9 @@ rebuild_special_bindings (MetaKeyBindingManager *keys)
meta_prefs_get_overlay_binding (&combo);
keys->overlay_key_combo = combo;
+
+ meta_prefs_get_locate_pointer_binding (&combo);
+ keys->locate_pointer_key_combo = combo;
}
static void
@@ -1062,6 +1070,10 @@ get_keybinding_action (MetaKeyBindingManager *keys,
&keys->overlay_resolved_key_combo))
return META_KEYBINDING_ACTION_OVERLAY_KEY;
+ if (resolved_key_combo_intersect (resolved_combo,
+ &keys->locate_pointer_resolved_key_combo))
+ return META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
+
binding = get_keybinding (keys, resolved_combo);
if (binding)
{
@@ -1487,6 +1499,10 @@ meta_x11_display_change_keygrabs (MetaX11Display *x11_display,
meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->overlay_resolved_key_combo);
+ if (keys->locate_pointer_resolved_key_combo.len != 0)
+ meta_change_keygrab (keys, x11_display->xroot,
+ grab, &keys->locate_pointer_resolved_key_combo);
+
for (i = 0; i < keys->n_iso_next_group_combos; i++)
meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->iso_next_group_combo[i]);
@@ -1952,37 +1968,31 @@ process_event (MetaDisplay *display,
}
static gboolean
-process_overlay_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window)
+process_special_modifier_key (MetaDisplay *display,
+ ClutterKeyEvent *event,
+ MetaWindow *window,
+ gboolean *modifier_press_only,
+ MetaResolvedKeyCombo *resolved_key_combo,
+ GFunc trigger_callback)
{
MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaBackend *backend = keys->backend;
Display *xdisplay;
- if (display->focus_window && !keys->overlay_key_only_pressed)
- {
- ClutterInputDevice *source;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
- if (meta_window_shortcuts_inhibited (display->focus_window, source))
- return FALSE;
- }
-
if (META_IS_BACKEND_X11 (backend))
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
else
xdisplay = NULL;
- if (keys->overlay_key_only_pressed)
+ if (*modifier_press_only)
{
- if (! resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
+ if (! resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{
- keys->overlay_key_only_pressed = FALSE;
+ *modifier_press_only = FALSE;
/* OK, the user hit modifier+key rather than pressing and
- * releasing the ovelay key. We want to handle the key
+ * releasing the modifier key alone. We want to handle the key
* sequence "normally". Unfortunately, using
* XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
* work, since global keybindings won't be activated ("this
@@ -2021,7 +2031,7 @@ process_overlay_key (MetaDisplay *display,
{
MetaKeyBinding *binding;
- keys->overlay_key_only_pressed = FALSE;
+ *modifier_press_only = FALSE;
/* We want to unfreeze events, but keep the grab so that if the user
* starts typing into the overlay we get all the keys */
@@ -2030,11 +2040,11 @@ process_overlay_key (MetaDisplay *display,
clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time);
- binding = get_keybinding (keys, &keys->overlay_resolved_key_combo);
+ binding = get_keybinding (keys, resolved_key_combo);
if (binding &&
meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE;
- meta_display_overlay_key_activate (display);
+ trigger_callback (display, NULL);
}
else
{
@@ -2044,7 +2054,7 @@ process_overlay_key (MetaDisplay *display,
* while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease.
*
- * In this case, keys->overlay_key_only_pressed might be wrong.
+ * In this case, modifier_press_only might be wrong.
* Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events.
*
@@ -2059,12 +2069,12 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
}
else if (event->type == CLUTTER_KEY_PRESS &&
- resolved_key_combo_has_keycode (&keys->overlay_resolved_key_combo,
+ resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{
- keys->overlay_key_only_pressed = TRUE;
+ *modifier_press_only = TRUE;
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
- * on the next event if it's not the release of the overlay key */
+ * on the next event if it's not the release of the modifier key */
if (xdisplay)
XIAllowEvents (xdisplay,
clutter_input_device_get_device_id (event->device),
@@ -2076,6 +2086,43 @@ process_overlay_key (MetaDisplay *display,
return FALSE;
}
+
+static gboolean
+process_overlay_key (MetaDisplay *display,
+ ClutterKeyEvent *event,
+ MetaWindow *window)
+{
+ MetaKeyBindingManager *keys = &display->key_binding_manager;
+
+ return process_special_modifier_key (display,
+ event,
+ window,
+ &keys->overlay_key_only_pressed,
+ &keys->overlay_resolved_key_combo,
+ (GFunc) meta_display_overlay_key_activate);
+}
+
+static void
+handle_locate_pointer (MetaDisplay *display)
+{
+ meta_compositor_locate_pointer (display->compositor);
+}
+
+static gboolean
+process_locate_pointer_key (MetaDisplay *display,
+ ClutterKeyEvent *event,
+ MetaWindow *window)
+{
+ MetaKeyBindingManager *keys = &display->key_binding_manager;
+
+ return process_special_modifier_key (display,
+ event,
+ window,
+ &keys->locate_pointer_key_only_pressed,
+ &keys->locate_pointer_resolved_key_combo,
+ (GFunc) handle_locate_pointer);
+}
+
static gboolean
process_iso_next_group (MetaDisplay *display,
ClutterKeyEvent *event)
@@ -2129,6 +2176,10 @@ process_key_event (MetaDisplay *display,
if (handled)
return TRUE;
+ handled = process_locate_pointer_key (display, event, window);
+ if (handled) /* Continue with the event even if handled */
+ return FALSE;
+
handled = process_iso_next_group (display, event);
if (handled)
return TRUE;
@@ -2217,6 +2268,7 @@ meta_keybindings_process_event (MetaDisplay *display,
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_END:
keys->overlay_key_only_pressed = FALSE;
+ keys->locate_pointer_key_only_pressed = FALSE;
return FALSE;
case CLUTTER_KEY_PRESS:
@@ -4405,6 +4457,12 @@ meta_display_init_keys (MetaDisplay *display)
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
+ handler = g_new0 (MetaKeyHandler, 1);
+ handler->name = g_strdup ("locate-pointer-key");
+ handler->flags = META_KEY_BINDING_BUILTIN;
+
+ g_hash_table_insert (key_handlers, g_strdup ("locate-pointer-key"), handler);
+
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("iso-next-group");
handler->flags = META_KEY_BINDING_BUILTIN;
diff --git a/src/core/prefs.c b/src/core/prefs.c
index 3f0db8afc..9f11a2842 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -81,6 +81,7 @@ static gboolean use_system_font = FALSE;
static PangoFontDescription *titlebar_font = NULL;
static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
+static MetaKeyCombo locate_pointer_key_combo = { 0, 0, 0 };
static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE;
@@ -145,6 +146,7 @@ static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
+static gboolean locate_pointer_key_handler (GVariant*, gpointer*, gpointer);
static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer);
static void init_bindings (void);
@@ -427,6 +429,14 @@ static MetaStringPreference preferences_string[] =
overlay_key_handler,
NULL,
},
+ {
+ { "locate-pointer-key",
+ SCHEMA_MUTTER,
+ META_PREF_KEYBINDINGS,
+ },
+ locate_pointer_key_handler,
+ NULL,
+ },
{ { NULL, 0, 0 }, NULL },
};
@@ -1475,6 +1485,36 @@ overlay_key_handler (GVariant *value,
return TRUE;
}
+static gboolean
+locate_pointer_key_handler (GVariant *value,
+ gpointer *result,
+ gpointer data)
+{
+ MetaKeyCombo combo;
+ const gchar *string_value;
+
+ *result = NULL; /* ignored */
+ string_value = g_variant_get_string (value, NULL);
+
+ if (!string_value || !meta_parse_accelerator (string_value, &combo))
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Failed to parse value for locate-pointer-key\n");
+ return FALSE;
+ }
+
+ combo.modifiers = 0;
+
+ if (locate_pointer_key_combo.keysym != combo.keysym ||
+ locate_pointer_key_combo.keycode != combo.keycode)
+ {
+ locate_pointer_key_combo = combo;
+ queue_changed (META_PREF_KEYBINDINGS);
+ }
+
+ return TRUE;
+}
+
static gboolean
iso_next_group_handler (GVariant *value,
gpointer *result,
@@ -1689,6 +1729,14 @@ init_bindings (void)
pref->builtin = 1;
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
+
+ pref = g_new0 (MetaKeyPref, 1);
+ pref->name = g_strdup ("locate-pointer-key");
+ pref->action = META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
+ pref->combos = g_slist_prepend (pref->combos, &locate_pointer_key_combo);
+ pref->builtin = 1;
+
+ g_hash_table_insert (key_bindings, g_strdup ("locate-pointer-key"), pref);
}
static gboolean
@@ -1966,6 +2014,12 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
*combo = overlay_key_combo;
}
+void
+meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo)
+{
+ *combo = locate_pointer_key_combo;
+}
+
const char *
meta_prefs_get_iso_next_group_option (void)
{
diff --git a/src/meta/prefs.h b/src/meta/prefs.h
index 9664b5c07..9db540453 100644
--- a/src/meta/prefs.h
+++ b/src/meta/prefs.h
@@ -322,6 +322,7 @@ int meta_prefs_get_drag_threshold (void);
* @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME
* @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME
* @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME
+ * @META_KEYBINDING_ACTION_LOCATE_POINTER_KEY: FILLME
* @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME
* @META_KEYBINDING_ACTION_LAST: FILLME
*/
@@ -419,6 +420,7 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
META_KEYBINDING_ACTION_MOVE_TO_CENTER,
META_KEYBINDING_ACTION_OVERLAY_KEY,
+ META_KEYBINDING_ACTION_LOCATE_POINTER_KEY,
META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
META_KEYBINDING_ACTION_SWITCH_MONITOR,