[mutter] wayland: add inhibit shortcut mechanism



commit dd12f569d90c7d6b524bda72266bf91c5a61d9e4
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Fri Mar 17 13:34:52 2017 +0100

    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

 data/org.gnome.mutter.wayland.gschema.xml.in |    4 ++
 src/core/keybindings.c                       |   58 ++++++++++++++++++++-----
 src/core/window-private.h                    |    9 ++++
 src/core/window.c                            |   14 ++++++
 src/meta/prefs.h                             |    8 ++-
 src/wayland/meta-wayland-surface.c           |   47 +++++++++++++++++++++
 src/wayland/meta-wayland-surface.h           |   12 +++++
 src/wayland/meta-wayland.c                   |   37 ++++++++++++++++
 src/wayland/meta-wayland.h                   |    5 ++
 src/wayland/meta-window-wayland.c            |   20 +++++++++
 src/x11/window-x11.c                         |   23 ++++++++++
 11 files changed, 222 insertions(+), 15 deletions(-)
---
diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in
index 44334d6..e8ee1cc 100644
--- a/data/org.gnome.mutter.wayland.gschema.xml.in
+++ b/data/org.gnome.mutter.wayland.gschema.xml.in
@@ -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>
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 518416c..6972392 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 0b667fb..521682d 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 fa01e57..ec3083f 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 4394f74..df3cf6c 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 3d02a73..ddca18f 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 09a1dbc..e4eada9 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 b5ab1ec..d89cac5 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 af8b086..95e796e 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 efe299f..22da390 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -521,6 +521,24 @@ meta_window_wayland_init (MetaWindowWayland *wl_window)
 }
 
 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)
 {
   MetaWindowClass *window_class = META_WINDOW_CLASS (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 07f0922..ad5058b 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1505,6 +1505,27 @@ meta_window_x11_get_client_pid (MetaWindow *window)
 }
 
 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)
 {
   MetaWindowClass *window_class = META_WINDOW_CLASS (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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]