[mutter] wayland: manually activate/deactivate stage when taking/dropping grab



commit 9f17c05a156f9b0d21a1534d1da59d136457bf56
Author: Ray Strode <rstrode redhat com>
Date:   Tue Mar 24 12:40:10 2015 -0400

    wayland: manually activate/deactivate stage when taking/dropping grab
    
    clutter currently never emits activated or deactivated signals on
    the stage object when using the EGL backend. Since the stage never
    gets activated, accessibility tools, like orca, don't work.
    
    This commit makes mutter take on the responsibility, by tracking
    when the stage gains/loses focus, and then synthesizing stage
    CLUTTER_STAGE_STATE_ACTIVATED state events.
    
    A limitation of this approach is that clutter's own notion of
    the stage activeness won't reflect mutter's notion of the
    stage activeness.  This isn't a problem, in practice, and can
    be addressed in the medium-term after making changes to
    clutter.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=746670

 src/backends/meta-stage.c |   66 +++++++++++++++++++++++++++++++++++++++++++++
 src/backends/meta-stage.h |    3 ++
 src/core/display.c        |    4 +++
 3 files changed, 73 insertions(+), 0 deletions(-)
---
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index e304441..37f1771 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -41,6 +41,7 @@ typedef struct {
 
 struct _MetaStagePrivate {
   MetaOverlay cursor_overlay;
+  gboolean is_active;
 };
 typedef struct _MetaStagePrivate MetaStagePrivate;
 
@@ -127,14 +128,40 @@ meta_stage_paint (ClutterActor *actor)
 }
 
 static void
+meta_stage_activate (ClutterStage *actor)
+{
+  MetaStage *stage = META_STAGE (actor);
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+
+  CLUTTER_STAGE_CLASS (meta_stage_parent_class)->activate (actor);
+
+  priv->is_active = TRUE;
+}
+
+static void
+meta_stage_deactivate (ClutterStage *actor)
+{
+  MetaStage *stage = META_STAGE (actor);
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+
+  CLUTTER_STAGE_CLASS (meta_stage_parent_class)->deactivate (actor);
+
+  priv->is_active = FALSE;
+}
+
+static void
 meta_stage_class_init (MetaStageClass *klass)
 {
+  ClutterStageClass *stage_class = (ClutterStageClass *) klass;
   ClutterActorClass *actor_class = (ClutterActorClass *) klass;
   GObjectClass *object_class = (GObjectClass *) klass;
 
   object_class->finalize = meta_stage_finalize;
 
   actor_class->paint = meta_stage_paint;
+
+  stage_class->activate = meta_stage_activate;
+  stage_class->deactivate = meta_stage_deactivate;
 }
 
 static void
@@ -195,3 +222,42 @@ meta_stage_set_cursor (MetaStage     *stage,
   meta_overlay_set (&priv->cursor_overlay, texture, rect);
   queue_redraw_for_overlay (stage, &priv->cursor_overlay);
 }
+
+void
+meta_stage_set_active (MetaStage *stage,
+                       gboolean   is_active)
+{
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  ClutterEvent event = { 0 };
+
+  /* Used by the native backend to inform accessibility technologies
+   * about when the stage loses and gains input focus.
+   *
+   * For the X11 backend, clutter transparently takes care of this
+   * for us.
+   */
+
+  if (priv->is_active == is_active)
+    return;
+
+  clutter_event_set_stage (&event, CLUTTER_STAGE (stage));
+  event.stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
+
+  if (is_active)
+    event.stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED;
+
+  /* Emitting this StageState event will result in the stage getting
+   * activated or deactivated (with the activated or deactivated signal
+   * getting emitted from the stage)
+   *
+   * FIXME: This won't update ClutterStage's own notion of its
+   * activeness. For that we would need to somehow trigger a
+   * _clutter_stage_update_state call, which will probably
+   * require new API in clutter. In practice, nothing relies
+   * on the ClutterStage's own notion of activeness when using
+   * the EGL backend.
+   *
+   * See http://bugzilla.gnome.org/746670
+   */
+  clutter_stage_event (CLUTTER_STAGE (stage), &event);
+}
diff --git a/src/backends/meta-stage.h b/src/backends/meta-stage.h
index 742d14f..262d68f 100644
--- a/src/backends/meta-stage.h
+++ b/src/backends/meta-stage.h
@@ -54,6 +54,9 @@ ClutterActor     *meta_stage_new                     (void);
 void meta_stage_set_cursor (MetaStage     *stage,
                             CoglTexture   *texture,
                             MetaRectangle *rect);
+
+void meta_stage_set_active (MetaStage *stage,
+                            gboolean   is_active);
 G_END_DECLS
 
 #endif /* META_STAGE_H */
diff --git a/src/core/display.c b/src/core/display.c
index a99c7f6..53cec6f 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -52,6 +52,7 @@
 #include <meta/meta-backend.h>
 #include "backends/native/meta-backend-native.h"
 #include "backends/x11/meta-backend-x11.h"
+#include "backends/meta-stage.h"
 #include <clutter/x11/clutter-x11.h>
 
 #ifdef HAVE_RANDR
@@ -1411,6 +1412,8 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
 #ifdef HAVE_WAYLAND
   MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
   MetaWindow *focus_window = NULL;
+  MetaBackend *backend = meta_get_backend ();
+  MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
 
   if (!meta_display_windows_are_interactable (display))
     focus_window = NULL;
@@ -1421,6 +1424,7 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
   else
     meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland 
surface");
 
+  meta_stage_set_active (stage, focus_window == NULL);
   meta_wayland_compositor_set_input_focus (compositor, focus_window);
 
   meta_wayland_seat_repick (compositor->seat);


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