wayland: add inhibit shortcut mechanism
Add a mechanism to MetaWaylandSurface that inhibits compositor's own shortcuts when the surface has input focus, so that clients can receive all key events regardless of the compositor own shortcuts. This will help with implementing "fake" active grabs in Wayland and XWayland clients. https://bugzilla.gnome.org/show_bug.cgi?id=783342
This commit is contained in:
parent
c54377e3ba
commit
dd12f569d9
11 changed files with 222 additions and 15 deletions
|
@ -49,5 +49,9 @@
|
|||
<default><![CDATA[['<Primary><Alt>F12']]]></default>
|
||||
<summary>Switch to VT 12</summary>
|
||||
</key>
|
||||
<key name="restore-shortcuts" type="as">
|
||||
<default><![CDATA[['<Shift><Control>Escape']]]></default>
|
||||
<summary>Re-enable shortcuts</summary>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue