keybindings: Trigger locate-pointer on key modifier

We trigger the "locate-pointer" mechanism when a special key modifier
(defaults to Control_L) key is pressed and released.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
This commit is contained in:
Olivier Fourdan 2019-02-20 11:53:54 +01:00 committed by Carlos Garnacho
parent b4c78726cf
commit 851b7d0639
5 changed files with 149 additions and 23 deletions

View File

@ -127,6 +127,14 @@
</description> </description>
</key> </key>
<key name="locate-pointer-key" type="s">
<default>'Control_L'</default>
<summary>Modifier to use to locate the pointer</summary>
<description>
This key will initiate the “locate pointer” action.
</description>
</key>
<child name="keybindings" schema="org.gnome.mutter.keybindings"/> <child name="keybindings" schema="org.gnome.mutter.keybindings"/>
</schema> </schema>

View File

@ -113,6 +113,9 @@ typedef struct
MetaKeyCombo overlay_key_combo; MetaKeyCombo overlay_key_combo;
MetaResolvedKeyCombo overlay_resolved_key_combo; MetaResolvedKeyCombo overlay_resolved_key_combo;
gboolean overlay_key_only_pressed; 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]; MetaResolvedKeyCombo iso_next_group_combo[2];
int n_iso_next_group_combos; int n_iso_next_group_combos;
@ -149,6 +152,7 @@ gboolean meta_prefs_remove_keybinding (const char *name);
GList *meta_prefs_get_keybindings (void); GList *meta_prefs_get_keybindings (void);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo); 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); const char *meta_prefs_get_iso_next_group_option (void);
void meta_x11_display_grab_keys (MetaX11Display *x11_display); void meta_x11_display_grab_keys (MetaX11Display *x11_display);

View File

@ -33,6 +33,7 @@
#include "backends/meta-logical-monitor.h" #include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor-manager-private.h" #include "backends/meta-monitor-manager-private.h"
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#include "compositor/compositor-private.h"
#include "core/edge-resistance.h" #include "core/edge-resistance.h"
#include "core/frame.h" #include "core/frame.h"
#include "core/keybindings-private.h" #include "core/keybindings-private.h"
@ -780,6 +781,10 @@ reload_combos (MetaKeyBindingManager *keys)
&keys->overlay_key_combo, &keys->overlay_key_combo,
&keys->overlay_resolved_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); reload_iso_next_group_combos (keys);
g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, 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); meta_prefs_get_overlay_binding (&combo);
keys->overlay_key_combo = combo; keys->overlay_key_combo = combo;
meta_prefs_get_locate_pointer_binding (&combo);
keys->locate_pointer_key_combo = combo;
} }
static void static void
@ -1062,6 +1070,10 @@ get_keybinding_action (MetaKeyBindingManager *keys,
&keys->overlay_resolved_key_combo)) &keys->overlay_resolved_key_combo))
return META_KEYBINDING_ACTION_OVERLAY_KEY; 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); binding = get_keybinding (keys, resolved_combo);
if (binding) if (binding)
{ {
@ -1487,6 +1499,10 @@ meta_x11_display_change_keygrabs (MetaX11Display *x11_display,
meta_change_keygrab (keys, x11_display->xroot, meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->overlay_resolved_key_combo); 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++) for (i = 0; i < keys->n_iso_next_group_combos; i++)
meta_change_keygrab (keys, x11_display->xroot, meta_change_keygrab (keys, x11_display->xroot,
grab, &keys->iso_next_group_combo[i]); grab, &keys->iso_next_group_combo[i]);
@ -1952,37 +1968,31 @@ process_event (MetaDisplay *display,
} }
static gboolean static gboolean
process_overlay_key (MetaDisplay *display, process_special_modifier_key (MetaDisplay *display,
ClutterKeyEvent *event, ClutterKeyEvent *event,
MetaWindow *window) MetaWindow *window,
gboolean *modifier_press_only,
MetaResolvedKeyCombo *resolved_key_combo,
GFunc trigger_callback)
{ {
MetaKeyBindingManager *keys = &display->key_binding_manager; MetaKeyBindingManager *keys = &display->key_binding_manager;
MetaBackend *backend = keys->backend; MetaBackend *backend = keys->backend;
Display *xdisplay; 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)) if (META_IS_BACKEND_X11 (backend))
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
else else
xdisplay = NULL; 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)) event->hardware_keycode))
{ {
keys->overlay_key_only_pressed = FALSE; *modifier_press_only = FALSE;
/* OK, the user hit modifier+key rather than pressing and /* 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 * sequence "normally". Unfortunately, using
* XAllowEvents(..., ReplayKeyboard, ...) doesn't quite * XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
* work, since global keybindings won't be activated ("this * work, since global keybindings won't be activated ("this
@ -2021,7 +2031,7 @@ process_overlay_key (MetaDisplay *display,
{ {
MetaKeyBinding *binding; 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 /* We want to unfreeze events, but keep the grab so that if the user
* starts typing into the overlay we get all the keys */ * 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), clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time); XIAsyncDevice, event->time);
binding = get_keybinding (keys, &keys->overlay_resolved_key_combo); binding = get_keybinding (keys, resolved_key_combo);
if (binding && if (binding &&
meta_compositor_filter_keybinding (display->compositor, binding)) meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE; return TRUE;
meta_display_overlay_key_activate (display); trigger_callback (display, NULL);
} }
else else
{ {
@ -2044,7 +2054,7 @@ process_overlay_key (MetaDisplay *display,
* while the key is still down * while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease. * - 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 * Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events. * will not send the next events.
* *
@ -2059,12 +2069,12 @@ process_overlay_key (MetaDisplay *display,
return TRUE; return TRUE;
} }
else if (event->type == CLUTTER_KEY_PRESS && 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)) event->hardware_keycode))
{ {
keys->overlay_key_only_pressed = TRUE; *modifier_press_only = TRUE;
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard /* 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) if (xdisplay)
XIAllowEvents (xdisplay, XIAllowEvents (xdisplay,
clutter_input_device_get_device_id (event->device), clutter_input_device_get_device_id (event->device),
@ -2076,6 +2086,43 @@ process_overlay_key (MetaDisplay *display,
return FALSE; 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 static gboolean
process_iso_next_group (MetaDisplay *display, process_iso_next_group (MetaDisplay *display,
ClutterKeyEvent *event) ClutterKeyEvent *event)
@ -2129,6 +2176,10 @@ process_key_event (MetaDisplay *display,
if (handled) if (handled)
return TRUE; 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); handled = process_iso_next_group (display, event);
if (handled) if (handled)
return TRUE; return TRUE;
@ -2217,6 +2268,7 @@ meta_keybindings_process_event (MetaDisplay *display,
case CLUTTER_TOUCH_BEGIN: case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_END: case CLUTTER_TOUCH_END:
keys->overlay_key_only_pressed = FALSE; keys->overlay_key_only_pressed = FALSE;
keys->locate_pointer_key_only_pressed = FALSE;
return FALSE; return FALSE;
case CLUTTER_KEY_PRESS: 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); 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 = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("iso-next-group"); handler->name = g_strdup ("iso-next-group");
handler->flags = META_KEY_BINDING_BUILTIN; handler->flags = META_KEY_BINDING_BUILTIN;

View File

@ -81,6 +81,7 @@ static gboolean use_system_font = FALSE;
static PangoFontDescription *titlebar_font = NULL; static PangoFontDescription *titlebar_font = NULL;
static MetaVirtualModifier mouse_button_mods = Mod1Mask; static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static MetaKeyCombo overlay_key_combo = { 0, 0, 0 }; 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 GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART; static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE; 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 mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
static gboolean button_layout_handler (GVariant*, gpointer*, gpointer); static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
static gboolean overlay_key_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 gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer);
static void init_bindings (void); static void init_bindings (void);
@ -427,6 +429,14 @@ static MetaStringPreference preferences_string[] =
overlay_key_handler, overlay_key_handler,
NULL, NULL,
}, },
{
{ "locate-pointer-key",
SCHEMA_MUTTER,
META_PREF_KEYBINDINGS,
},
locate_pointer_key_handler,
NULL,
},
{ { NULL, 0, 0 }, NULL }, { { NULL, 0, 0 }, NULL },
}; };
@ -1475,6 +1485,36 @@ overlay_key_handler (GVariant *value,
return TRUE; 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 static gboolean
iso_next_group_handler (GVariant *value, iso_next_group_handler (GVariant *value,
gpointer *result, gpointer *result,
@ -1689,6 +1729,14 @@ init_bindings (void)
pref->builtin = 1; pref->builtin = 1;
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref); 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 static gboolean
@ -1966,6 +2014,12 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
*combo = overlay_key_combo; *combo = overlay_key_combo;
} }
void
meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo)
{
*combo = locate_pointer_key_combo;
}
const char * const char *
meta_prefs_get_iso_next_group_option (void) meta_prefs_get_iso_next_group_option (void)
{ {

View File

@ -322,6 +322,7 @@ int meta_prefs_get_drag_threshold (void);
* @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME * @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME
* @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME * @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME
* @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME * @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME
* @META_KEYBINDING_ACTION_LOCATE_POINTER_KEY: FILLME
* @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME * @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME
* @META_KEYBINDING_ACTION_LAST: 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_SIDE_W,
META_KEYBINDING_ACTION_MOVE_TO_CENTER, META_KEYBINDING_ACTION_MOVE_TO_CENTER,
META_KEYBINDING_ACTION_OVERLAY_KEY, META_KEYBINDING_ACTION_OVERLAY_KEY,
META_KEYBINDING_ACTION_LOCATE_POINTER_KEY,
META_KEYBINDING_ACTION_ISO_NEXT_GROUP, META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP, META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
META_KEYBINDING_ACTION_SWITCH_MONITOR, META_KEYBINDING_ACTION_SWITCH_MONITOR,