[mutter/wayland] Fix the input region not working properly



commit 1e6b3faa83323943cb45f4ef1b910f87b2c30d88
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Feb 18 21:27:20 2014 -0500

    Fix the input region not working properly
    
    The input region was set on the shaped texture, but the shaped texture
    was never picked properly, as it was never set to be reactive. Move the
    pick implementation and reactivity to the MetaSurfaceActor, and update
    the code everywhere else to expect a MetaSurfaceActor.

 src/compositor/meta-shaped-texture.c |  105 ----------------------------------
 src/compositor/meta-surface-actor.c  |   97 ++++++++++++++++++++++++++++++-
 src/compositor/meta-surface-actor.h  |    4 +-
 src/compositor/meta-window-actor.c   |    5 +-
 src/core/display.c                   |    8 ++-
 src/meta/meta-shaped-texture.h       |    3 -
 src/wayland/meta-wayland-seat.c      |    9 +--
 src/wayland/meta-wayland-surface.c   |    3 +-
 8 files changed, 108 insertions(+), 126 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index ae46b34..30697ee 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -42,8 +42,6 @@
 static void meta_shaped_texture_dispose  (GObject    *object);
 
 static void meta_shaped_texture_paint (ClutterActor       *actor);
-static void meta_shaped_texture_pick  (ClutterActor       *actor,
-                                      const ClutterColor *color);
 
 static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
                                                      gfloat        for_height,
@@ -73,8 +71,6 @@ struct _MetaShapedTexturePrivate
   CoglTexture *texture;
   CoglTexture *mask_texture;
 
-  cairo_region_t *input_shape_region;
-
   /* The region containing only fully opaque pixels */
   cairo_region_t *opaque_region;
 
@@ -98,7 +94,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
   actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
   actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
   actor_class->paint = meta_shaped_texture_paint;
-  actor_class->pick = meta_shaped_texture_pick;
   actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
 
   g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
@@ -464,71 +459,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
 }
 
 static void
-meta_shaped_texture_pick (ClutterActor       *actor,
-                         const ClutterColor *color)
-{
-  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
-  MetaShapedTexturePrivate *priv = stex->priv;
-
-  if (!clutter_actor_should_pick_paint (actor) ||
-      (priv->clip_region && cairo_region_is_empty (priv->clip_region)))
-    return;
-
-  /* If there is no region then use the regular pick */
-  if (priv->input_shape_region == NULL)
-    CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
-  else
-    {
-      int n_rects;
-      float *rectangles;
-      int i;
-      CoglPipeline *pipeline;
-      CoglContext *ctx;
-      CoglFramebuffer *fb;
-      CoglColor cogl_color;
-
-      /* Note: We don't bother trying to intersect the pick and clip regions
-       * since needing to copy the region, do the intersection, and probably
-       * increase the number of rectangles seems more likely to have a negative
-       * effect.
-       *
-       * NB: Most of the time when just using rectangles for picking then
-       * picking shouldn't involve any rendering, and minimizing the number of
-       * rectangles has more benefit than reducing the area of the pick
-       * region.
-       */
-
-      n_rects = cairo_region_num_rectangles (priv->input_shape_region);
-      rectangles = g_alloca (sizeof (float) * 4 * n_rects);
-
-      for (i = 0; i < n_rects; i++)
-        {
-          cairo_rectangle_int_t rect;
-          int pos = i * 4;
-
-          cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
-
-          rectangles[pos] = rect.x;
-          rectangles[pos + 1] = rect.y;
-          rectangles[pos + 2] = rect.x + rect.width;
-          rectangles[pos + 3] = rect.y + rect.height;
-        }
-
-      ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
-      fb = cogl_get_draw_framebuffer ();
-
-      cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
-
-      pipeline = cogl_pipeline_new (ctx);
-      cogl_pipeline_set_color (pipeline, &cogl_color);
-
-      cogl_framebuffer_draw_rectangles (fb, pipeline,
-                                        rectangles, n_rects);
-      cogl_object_unref (pipeline);
-    }
-}
-
-static void
 meta_shaped_texture_get_preferred_width (ClutterActor *self,
                                          gfloat        for_height,
                                          gfloat       *min_width_p,
@@ -765,41 +695,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
 }
 
 /**
- * meta_shaped_texture_set_input_shape_region:
- * @stex: a #MetaShapedTexture
- * @shape_region: the region of the texture that should respond to
- *    input.
- *
- * Determines what region of the texture should accept input. For
- * X based windows this is defined by the ShapeInput region of the
- * window.
- */
-void
-meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
-                                            cairo_region_t    *shape_region)
-{
-  MetaShapedTexturePrivate *priv;
-
-  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
-
-  priv = stex->priv;
-
-  if (priv->input_shape_region != NULL)
-    {
-      cairo_region_destroy (priv->input_shape_region);
-      priv->input_shape_region = NULL;
-    }
-
-  if (shape_region != NULL)
-    {
-      cairo_region_reference (shape_region);
-      priv->input_shape_region = shape_region;
-    }
-
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
-}
-
-/**
  * meta_shaped_texture_set_opaque_region:
  * @stex: a #MetaShapedTexture
  * @opaque_region: (transfer full): the region of the texture that
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 541094c..5afa4d7 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -22,8 +22,12 @@
 
 struct _MetaSurfaceActorPrivate
 {
+  MetaWaylandSurface *surface;
+
   MetaShapedTexture *texture;
   MetaWaylandBuffer *buffer;
+
+  cairo_region_t *input_region;
 };
 
 static void cullable_iface_init (MetaCullableInterface *iface);
@@ -40,8 +44,76 @@ meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
 }
 
 static void
+meta_surface_actor_pick (ClutterActor       *actor,
+                         const ClutterColor *color)
+{
+  MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
+  MetaSurfaceActorPrivate *priv = self->priv;
+
+  if (!clutter_actor_should_pick_paint (actor))
+    return;
+
+  /* If there is no region then use the regular pick */
+  if (priv->input_region == NULL)
+    CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
+  else
+    {
+      int n_rects;
+      float *rectangles;
+      int i;
+      CoglPipeline *pipeline;
+      CoglContext *ctx;
+      CoglFramebuffer *fb;
+      CoglColor cogl_color;
+
+      n_rects = cairo_region_num_rectangles (priv->input_region);
+      rectangles = g_alloca (sizeof (float) * 4 * n_rects);
+
+      for (i = 0; i < n_rects; i++)
+        {
+          cairo_rectangle_int_t rect;
+          int pos = i * 4;
+
+          cairo_region_get_rectangle (priv->input_region, i, &rect);
+
+          rectangles[pos + 0] = rect.x;
+          rectangles[pos + 1] = rect.y;
+          rectangles[pos + 2] = rect.x + rect.width;
+          rectangles[pos + 3] = rect.y + rect.height;
+        }
+
+      ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+      fb = cogl_get_draw_framebuffer ();
+
+      cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
+
+      pipeline = cogl_pipeline_new (ctx);
+      cogl_pipeline_set_color (pipeline, &cogl_color);
+      cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
+      cogl_object_unref (pipeline);
+    }
+}
+
+static void
+meta_surface_actor_dispose (GObject *object)
+{
+  MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
+  MetaSurfaceActorPrivate *priv = self->priv;
+
+  g_clear_pointer (&priv->input_region, cairo_region_destroy);
+
+  G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
+}
+
+static void
 meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+
+  object_class->dispose = meta_surface_actor_dispose;
+  actor_class->pick = meta_surface_actor_pick;
+
   g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
 }
 
@@ -172,7 +244,14 @@ meta_surface_actor_set_input_region (MetaSurfaceActor *self,
                                      cairo_region_t   *region)
 {
   MetaSurfaceActorPrivate *priv = self->priv;
-  meta_shaped_texture_set_input_shape_region (priv->texture, region);
+
+  if (priv->input_region)
+    cairo_region_destroy (priv->input_region);
+
+  if (region)
+    priv->input_region = cairo_region_reference (region);
+  else
+    priv->input_region = NULL;
 }
 
 void
@@ -183,8 +262,20 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
   meta_shaped_texture_set_opaque_region (priv->texture, region);
 }
 
+MetaWaylandSurface *
+meta_surface_actor_get_surface (MetaSurfaceActor *self)
+{
+  MetaSurfaceActorPrivate *priv = self->priv;
+  return priv->surface;
+}
+
 MetaSurfaceActor *
-meta_surface_actor_new (void)
+meta_surface_actor_new (MetaWaylandSurface *surface)
 {
-  return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
+  MetaSurfaceActor *self = g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
+  MetaSurfaceActorPrivate *priv = self->priv;
+
+  priv->surface = surface;
+
+  return self;
 }
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h
index fa7f0c3..e42deb4 100644
--- a/src/compositor/meta-surface-actor.h
+++ b/src/compositor/meta-surface-actor.h
@@ -36,7 +36,7 @@ struct _MetaSurfaceActor
 
 GType meta_surface_actor_get_type (void);
 
-MetaSurfaceActor *meta_surface_actor_new (void);
+MetaSurfaceActor *meta_surface_actor_new (MetaWaylandSurface *surface);
 
 cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor      *self,
                                                cairo_rectangle_int_t *clip);
@@ -63,6 +63,8 @@ void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
 void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
                                            cairo_region_t   *region);
 
+MetaWaylandSurface *meta_surface_actor_get_surface (MetaSurfaceActor *surface);
+
 G_END_DECLS
 
 #endif /* META_SURFACE_ACTOR_PRIVATE_H */
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index f9568f3..c607197 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -353,7 +353,7 @@ meta_window_actor_constructed (GObject *object)
       if (window->surface)
         priv->surface = window->surface->surface_actor;
       else
-        priv->surface = meta_surface_actor_new ();
+        priv->surface = meta_surface_actor_new (NULL);
       g_object_ref_sink (priv->surface);
 
       clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
@@ -1424,7 +1424,6 @@ meta_window_actor_hide (MetaWindowActor *self,
   g_return_if_fail (priv->visible);
 
   priv->visible = FALSE;
-  clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
 
   /* If a plugin is animating a workspace transition, we have to
    * hold off on hiding the window, and do it after the workspace
@@ -1557,8 +1556,6 @@ meta_window_actor_new (MetaWindow *window)
 
   clutter_actor_hide (CLUTTER_ACTOR (self));
 
-  clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
-
   /* Initial position in the stack is arbitrary; stacking will be synced
    * before we first paint.
    */
diff --git a/src/core/display.c b/src/core/display.c
index 749938f..907f1a5 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1682,8 +1682,12 @@ get_window_for_event (MetaDisplay        *display,
     return display->grab_window;
 
   source = clutter_event_get_source (event);
-  if (META_IS_WINDOW_ACTOR (source))
-    return meta_window_actor_get_meta_window (META_WINDOW_ACTOR (source));
+  if (META_IS_SURFACE_ACTOR (source))
+    {
+      MetaWaylandSurface *surface = meta_surface_actor_get_surface (META_SURFACE_ACTOR (source));
+      g_assert (surface != NULL);
+      return surface->window;
+    }
 
   return NULL;
 }
diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
index b0870bf..80b23f2 100644
--- a/src/meta/meta-shaped-texture.h
+++ b/src/meta/meta-shaped-texture.h
@@ -75,9 +75,6 @@ CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
 
 void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
                                            CoglTexture       *mask_texture);
-void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
-                                                 cairo_region_t    *shape_region);
-
 void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
                                             cairo_region_t    *opaque_region);
 
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index ff6f57d..df8e781 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -420,13 +420,8 @@ meta_wayland_seat_repick (MetaWaylandSeat    *seat,
   else
     seat->current_stage = NULL;
 
-  if (META_IS_WINDOW_ACTOR (actor))
-    {
-      MetaWindow *window =
-        meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
-
-      surface = window->surface;
-    }
+  if (META_IS_SURFACE_ACTOR (actor))
+    surface = meta_surface_actor_get_surface (META_SURFACE_ACTOR (actor));
 
   pointer->current = surface;
   if (surface != pointer->focus_surface)
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 2ae212d..10767cf 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -645,7 +645,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
   wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, 
wl_surface_destructor);
 
   surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
-  surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
+  surface->surface_actor = g_object_ref_sink (meta_surface_actor_new (surface));
+  clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
 
   double_buffered_state_init (&surface->pending);
 


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