diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in index 44334d664..e8ee1cca7 100644 --- a/data/org.gnome.mutter.wayland.gschema.xml.in +++ b/data/org.gnome.mutter.wayland.gschema.xml.in @@ -49,5 +49,9 @@ F12']]]> Switch to VT 12 + + Escape']]]> + Re-enable shortcuts + diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 518416ce2..697239232 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1716,6 +1716,16 @@ process_event (MetaDisplay *display, (!window && binding->flags & META_KEY_BINDING_PER_WINDOW)) goto not_found; + if (display->focus_window && + !(binding->handler->flags & META_KEY_BINDING_NON_MASKABLE)) + { + ClutterInputDevice *source; + + source = clutter_event_get_source_device ((ClutterEvent *) event); + if (meta_window_shortcuts_inhibited (display->focus_window, source)) + goto not_found; + } + /* If the compositor filtered out the keybindings, that * means they don't want the binding to trigger, so we do * the same thing as if the binding didn't exist. */ @@ -3364,6 +3374,23 @@ handle_rotate_monitor (MetaDisplay *display, meta_monitor_manager_rotate_monitor (monitor_manager); } +static void +handle_restore_shortcuts (MetaDisplay *display, + MetaScreen *screen, + MetaWindow *window, + ClutterKeyEvent *event, + MetaKeyBinding *binding, + gpointer dummy) +{ + ClutterInputDevice *source; + + source = clutter_event_get_source_device ((ClutterEvent *) event); + + meta_topic (META_DEBUG_KEYBINDINGS, "Restoring normal keyboard shortcuts\n"); + + meta_window_force_restore_shortcuts (display->focus_window, source); +} + /** * meta_keybindings_set_custom_handler: * @name: The name of the keybinding to set @@ -3674,89 +3701,96 @@ init_builtin_key_bindings (MetaDisplay *display) add_builtin_keybinding (display, "switch-to-session-1", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 1); add_builtin_keybinding (display, "switch-to-session-2", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 2); add_builtin_keybinding (display, "switch-to-session-3", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 3); add_builtin_keybinding (display, "switch-to-session-4", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 4); add_builtin_keybinding (display, "switch-to-session-5", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 5); add_builtin_keybinding (display, "switch-to-session-6", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 6); add_builtin_keybinding (display, "switch-to-session-7", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 7); add_builtin_keybinding (display, "switch-to-session-8", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 8); add_builtin_keybinding (display, "switch-to-session-9", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 9); add_builtin_keybinding (display, "switch-to-session-10", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 10); add_builtin_keybinding (display, "switch-to-session-11", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 11); add_builtin_keybinding (display, "switch-to-session-12", mutter_wayland_keybindings, - META_KEY_BINDING_NONE, + META_KEY_BINDING_NON_MASKABLE, META_KEYBINDING_ACTION_NONE, handle_switch_vt, 12); } #endif /* HAVE_NATIVE_BACKEND */ + add_builtin_keybinding (display, + "restore-shortcuts", + mutter_wayland_keybindings, + META_KEY_BINDING_NON_MASKABLE, + META_KEYBINDING_ACTION_NONE, + handle_restore_shortcuts, 0); + /************************ PER WINDOW BINDINGS ************************/ /* These take a window as an extra parameter; they have no effect diff --git a/src/core/window-private.h b/src/core/window-private.h index 0b667fb8f..521682d0a 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -535,6 +535,10 @@ struct _MetaWindowClass gboolean user_op); void (*main_monitor_changed) (MetaWindow *window, const MetaLogicalMonitor *old); + void (*force_restore_shortcuts) (MetaWindow *window, + ClutterInputDevice *source); + gboolean (*shortcuts_inhibited) (MetaWindow *window, + ClutterInputDevice *source); }; /* These differ from window->has_foo_func in that they consider @@ -763,4 +767,9 @@ MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window); void meta_window_force_placement (MetaWindow *window); +void meta_window_force_restore_shortcuts (MetaWindow *window, + ClutterInputDevice *source); + +gboolean meta_window_shortcuts_inhibited (MetaWindow *window, + ClutterInputDevice *source); #endif diff --git a/src/core/window.c b/src/core/window.c index fa01e57c1..ec3083f80 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -8066,3 +8066,17 @@ meta_window_get_placement_rule (MetaWindow *window) { return window->placement_rule; } + +void +meta_window_force_restore_shortcuts (MetaWindow *window, + ClutterInputDevice *source) +{ + META_WINDOW_GET_CLASS (window)->force_restore_shortcuts (window, source); +} + +gboolean +meta_window_shortcuts_inhibited (MetaWindow *window, + ClutterInputDevice *source) +{ + return META_WINDOW_GET_CLASS (window)->shortcuts_inhibited (window, source); +} diff --git a/src/meta/prefs.h b/src/meta/prefs.h index 4394f74d1..df3cf6c97 100644 --- a/src/meta/prefs.h +++ b/src/meta/prefs.h @@ -370,13 +370,15 @@ typedef enum _MetaKeyBindingAction * @META_KEY_BINDING_PER_WINDOW: per-window * @META_KEY_BINDING_BUILTIN: built-in * @META_KEY_BINDING_IS_REVERSED: is reversed + * @META_KEY_BINDING_NON_MASKABLE: always active */ typedef enum { META_KEY_BINDING_NONE, - META_KEY_BINDING_PER_WINDOW = 1 << 0, - META_KEY_BINDING_BUILTIN = 1 << 1, - META_KEY_BINDING_IS_REVERSED = 1 << 2, + META_KEY_BINDING_PER_WINDOW = 1 << 0, + META_KEY_BINDING_BUILTIN = 1 << 1, + META_KEY_BINDING_IS_REVERSED = 1 << 2, + META_KEY_BINDING_NON_MASKABLE = 1 << 3, } MetaKeyBindingFlags; /** diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 3d02a7301..ddca18f8d 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -130,6 +130,8 @@ enum { SURFACE_DESTROY, SURFACE_UNMAPPED, SURFACE_CONFIGURE, + SURFACE_SHORTCUTS_INHIBITED, + SURFACE_SHORTCUTS_RESTORED, N_SURFACE_SIGNALS }; @@ -1334,6 +1336,8 @@ wl_surface_destructor (struct wl_resource *resource) if (surface->wl_subsurface) wl_resource_destroy (surface->wl_subsurface); + g_hash_table_destroy (surface->shortcut_inhibited_seats); + g_object_unref (surface); meta_wayland_compositor_repick (compositor); @@ -1385,6 +1389,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor, sync_drag_dest_funcs (surface); surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL); + surface->shortcut_inhibited_seats = g_hash_table_new (NULL, NULL); return surface; } @@ -1881,6 +1886,22 @@ meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass) 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + surface_signals[SURFACE_SHORTCUTS_INHIBITED] = + g_signal_new ("shortcuts-inhibited", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + surface_signals[SURFACE_SHORTCUTS_RESTORED] = + g_signal_new ("shortcuts-restored", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -2219,3 +2240,29 @@ meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface) return region; } + +void +meta_wayland_surface_inhibit_shortcuts (MetaWaylandSurface *surface, + MetaWaylandSeat *seat) +{ + g_hash_table_add (surface->shortcut_inhibited_seats, seat); + g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_INHIBITED], 0); +} + +void +meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *surface, + MetaWaylandSeat *seat) +{ + g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_RESTORED], 0); + g_hash_table_remove (surface->shortcut_inhibited_seats, seat); +} + +gboolean +meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, + MetaWaylandSeat *seat) +{ + if (surface->shortcut_inhibited_seats == NULL) + return FALSE; + + return g_hash_table_contains (surface->shortcut_inhibited_seats, seat); +} diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 09a1dbce2..e4eada963 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -240,6 +240,9 @@ struct _MetaWaylandSurface gboolean pending_pos; GSList *pending_placement_ops; } sub; + + /* table of seats for which shortcuts are inhibited */ + GHashTable *shortcut_inhibited_seats; }; void meta_wayland_shell_init (MetaWaylandCompositor *compositor); @@ -326,4 +329,13 @@ gboolean meta_wayland_surface_begin_grab_op (MetaWaylandSurface *surf void meta_wayland_surface_window_managed (MetaWaylandSurface *surface, MetaWindow *window); +void meta_wayland_surface_inhibit_shortcuts (MetaWaylandSurface *surface, + MetaWaylandSeat *seat); + +void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *surface, + MetaWaylandSeat *seat); + +gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, + MetaWaylandSeat *seat); + #endif diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index b5ab1ecf6..d89cac540 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -404,3 +404,40 @@ meta_wayland_finalize (void) meta_xwayland_stop (&compositor->xwayland_manager); } + +void +meta_wayland_compositor_restore_shortcuts (MetaWaylandCompositor *compositor, + ClutterInputDevice *source) +{ + MetaWaylandKeyboard *keyboard; + + /* Clutter is not multi-seat aware yet, use the default seat instead */ + keyboard = compositor->seat->keyboard; + if (!keyboard || !keyboard->focus_surface) + return; + + if (!meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface, + compositor->seat)) + return; + + meta_wayland_surface_restore_shortcuts (keyboard->focus_surface, + compositor->seat); +} + +gboolean +meta_wayland_compositor_is_shortcuts_inhibited (MetaWaylandCompositor *compositor, + ClutterInputDevice *source) +{ + MetaWaylandKeyboard *keyboard; + + if (clutter_input_device_get_device_type (source) != CLUTTER_KEYBOARD_DEVICE) + return FALSE; + + /* Clutter is not multi-seat aware yet, use the default seat instead */ + keyboard = compositor->seat->keyboard; + if (keyboard && keyboard->focus_surface != NULL) + return meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface, + compositor->seat); + + return FALSE; +} diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h index af8b086f0..95e796ecd 100644 --- a/src/wayland/meta-wayland.h +++ b/src/wayland/meta-wayland.h @@ -58,5 +58,10 @@ void meta_wayland_compositor_destroy_frame_callbacks (MetaWay const char *meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor); const char *meta_wayland_get_xwayland_display_name (MetaWaylandCompositor *compositor); +void meta_wayland_compositor_restore_shortcuts (MetaWaylandCompositor *compositor, + ClutterInputDevice *source); +gboolean meta_wayland_compositor_is_shortcuts_inhibited (MetaWaylandCompositor *compositor, + ClutterInputDevice *source); + #endif diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index efe299fe3..22da3901d 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -520,6 +520,24 @@ meta_window_wayland_init (MetaWindowWayland *wl_window) G_CALLBACK (appears_focused_changed), NULL); } +static void +meta_window_wayland_force_restore_shortcuts (MetaWindow *window, + ClutterInputDevice *source) +{ + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + + meta_wayland_compositor_restore_shortcuts (compositor, source); +} + +static gboolean +meta_window_wayland_shortcuts_inhibited (MetaWindow *window, + ClutterInputDevice *source) +{ + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + + return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source); +} + static void meta_window_wayland_class_init (MetaWindowWaylandClass *klass) { @@ -537,6 +555,8 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass) window_class->update_main_monitor = meta_window_wayland_update_main_monitor; window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed; window_class->get_client_pid = meta_window_wayland_get_client_pid; + window_class->force_restore_shortcuts = meta_window_wayland_force_restore_shortcuts; + window_class->shortcuts_inhibited = meta_window_wayland_shortcuts_inhibited; } MetaWindow * diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 07f09223e..ad5058b8a 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -1504,6 +1504,27 @@ meta_window_x11_get_client_pid (MetaWindow *window) return pid; } +static void +meta_window_x11_force_restore_shortcuts (MetaWindow *window, + ClutterInputDevice *source) +{ + /* + * Not needed on X11 because clients can use a keyboard grab + * to bypass the compositor shortcuts. + */ +} + +static gboolean +meta_window_x11_shortcuts_inhibited (MetaWindow *window, + ClutterInputDevice *source) +{ + /* + * On X11, we don't use a shortcuts inhibitor, clients just grab + * the keyboard. + */ + return FALSE; +} + static void meta_window_x11_class_init (MetaWindowX11Class *klass) { @@ -1525,6 +1546,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass) window_class->update_main_monitor = meta_window_x11_update_main_monitor; window_class->main_monitor_changed = meta_window_x11_main_monitor_changed; window_class->get_client_pid = meta_window_x11_get_client_pid; + window_class->force_restore_shortcuts = meta_window_x11_force_restore_shortcuts; + window_class->shortcuts_inhibited = meta_window_x11_shortcuts_inhibited; } void