From 851b7d0639fbff491f8c48836752fb344ca18a11 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Wed, 20 Feb 2019 11:53:54 +0100 Subject: [PATCH] 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 --- data/org.gnome.mutter.gschema.xml.in | 8 +++ src/core/keybindings-private.h | 4 ++ src/core/keybindings.c | 104 +++++++++++++++++++++------ src/core/prefs.c | 54 ++++++++++++++ src/meta/prefs.h | 2 + 5 files changed, 149 insertions(+), 23 deletions(-) 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,