Compare commits
	
		
			4 Commits
		
	
	
		
			3.30.1
			...
			wip/waylan
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 10fbaf7695 | ||
|   | ef73402654 | ||
|   | 22cdf2d650 | ||
|   | 284b497b4c | 
| @@ -930,8 +930,8 @@ is_grabbed_event (MetaDisplay *display, | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_compositor_window_x11_shape_changed (MetaCompositor *compositor, | ||||
|                                           MetaWindow     *window) | ||||
| meta_compositor_window_shape_changed (MetaCompositor *compositor, | ||||
|                                       MetaWindow     *window) | ||||
| { | ||||
|   MetaWindowActor *window_actor; | ||||
|   window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); | ||||
|   | ||||
| @@ -91,11 +91,10 @@ struct _MetaShapedTexturePrivate | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   CoglTexture *mask_texture; | ||||
|   CoglPipeline *pipeline; | ||||
|   CoglPipeline *pipeline_unshaped; | ||||
|  | ||||
|   cairo_region_t *clip_region; | ||||
|   cairo_region_t *input_shape_region; | ||||
|   cairo_region_t *opaque_region; | ||||
|  | ||||
|   guint tex_width, tex_height; | ||||
|  | ||||
| @@ -145,8 +144,6 @@ meta_shaped_texture_dispose (GObject *object) | ||||
|     meta_texture_tower_free (priv->paint_tower); | ||||
|   priv->paint_tower = NULL; | ||||
|  | ||||
|   g_clear_pointer (&priv->pipeline, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->texture, cogl_object_unref); | ||||
|  | ||||
|   meta_shaped_texture_set_mask_texture (self, NULL); | ||||
| @@ -155,6 +152,76 @@ meta_shaped_texture_dispose (GObject *object) | ||||
|   G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| get_unmasked_pipeline (CoglContext *ctx) | ||||
| { | ||||
|   return cogl_pipeline_new (ctx); | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| get_masked_pipeline (CoglContext *ctx) | ||||
| { | ||||
|   static CoglPipeline *template = NULL; | ||||
|   if (G_UNLIKELY (template == NULL)) | ||||
|     { | ||||
|       template = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_layer_combine (template, 1, | ||||
|                                        "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", | ||||
|                                        NULL); | ||||
|     } | ||||
|  | ||||
|   return cogl_pipeline_copy (template); | ||||
| } | ||||
|  | ||||
| static CoglPipeline * | ||||
| get_unblended_pipeline (CoglContext *ctx) | ||||
| { | ||||
|   static CoglPipeline *template = NULL; | ||||
|   if (G_UNLIKELY (template == NULL)) | ||||
|     { | ||||
|       CoglColor color; | ||||
|       template = cogl_pipeline_new (ctx); | ||||
|       cogl_color_init_from_4ub (&color, 255, 255, 255, 255); | ||||
|       cogl_pipeline_set_blend (template, | ||||
|                                "RGBA = ADD (SRC_COLOR, 0)", | ||||
|                                NULL); | ||||
|       cogl_pipeline_set_color (template, &color); | ||||
|     } | ||||
|  | ||||
|   return cogl_pipeline_copy (template); | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_clipped_rectangle (CoglFramebuffer       *fb, | ||||
|                          CoglPipeline          *pipeline, | ||||
|                          cairo_rectangle_int_t *rect, | ||||
|                          ClutterActorBox       *alloc) | ||||
| { | ||||
|   float coords[8]; | ||||
|   float x1, y1, x2, y2; | ||||
|  | ||||
|   x1 = rect->x; | ||||
|   y1 = rect->y; | ||||
|   x2 = rect->x + rect->width; | ||||
|   y2 = rect->y + rect->height; | ||||
|  | ||||
|   coords[0] = rect->x / (alloc->x2 - alloc->x1); | ||||
|   coords[1] = rect->y / (alloc->y2 - alloc->y1); | ||||
|   coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1); | ||||
|   coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1); | ||||
|  | ||||
|   coords[4] = coords[0]; | ||||
|   coords[5] = coords[1]; | ||||
|   coords[6] = coords[2]; | ||||
|   coords[7] = coords[3]; | ||||
|  | ||||
|   cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline, | ||||
|                                                  x1, y1, x2, y2, | ||||
|                                                  &coords[0], 8); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| set_cogl_texture (MetaShapedTexture *stex, | ||||
|                   CoglTexture       *cogl_tex) | ||||
| @@ -171,12 +238,6 @@ set_cogl_texture (MetaShapedTexture *stex, | ||||
|  | ||||
|   priv->texture = cogl_tex; | ||||
|  | ||||
|   if (priv->pipeline != NULL) | ||||
|     cogl_pipeline_set_layer_texture (priv->pipeline, 0, COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
|   if (priv->pipeline_unshaped != NULL) | ||||
|     cogl_pipeline_set_layer_texture (priv->pipeline_unshaped, 0, COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
|   if (cogl_tex != NULL) | ||||
|     { | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); | ||||
| @@ -210,14 +271,14 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaShapedTexture *stex = (MetaShapedTexture *) actor; | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|   CoglTexture *paint_tex; | ||||
|   guint tex_width, tex_height; | ||||
|   guchar opacity; | ||||
|   CoglContext *ctx; | ||||
|   CoglFramebuffer *fb; | ||||
|   CoglPipeline *pipeline = NULL; | ||||
|   CoglTexture *paint_tex; | ||||
|   ClutterActorBox alloc; | ||||
|  | ||||
|   static CoglPipeline *pipeline_template = NULL; | ||||
|   static CoglPipeline *pipeline_unshaped_template = NULL; | ||||
|  | ||||
|   CoglPipeline *pipeline; | ||||
|   cairo_region_t *blended_region = NULL; | ||||
|  | ||||
|   if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) | ||||
|     return; | ||||
| @@ -254,38 +315,67 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|   if (tex_width == 0 || tex_height == 0) /* no contents yet */ | ||||
|     return; | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|   opacity = clutter_actor_get_paint_opacity (actor); | ||||
|   clutter_actor_get_allocation_box (actor, &alloc); | ||||
|  | ||||
|   if (priv->opaque_region != NULL && opacity == 255) | ||||
|     { | ||||
|       CoglPipeline *opaque_pipeline; | ||||
|       cairo_region_t *region; | ||||
|       int n_rects; | ||||
|       int i; | ||||
|  | ||||
|       region = cairo_region_copy (priv->clip_region); | ||||
|       cairo_region_intersect (region, priv->opaque_region); | ||||
|  | ||||
|       if (cairo_region_is_empty (region)) | ||||
|         goto paint_blended; | ||||
|  | ||||
|       opaque_pipeline = get_unblended_pipeline (ctx); | ||||
|       cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (region); | ||||
|       for (i = 0; i < n_rects; i++) | ||||
|         { | ||||
|           cairo_rectangle_int_t rect; | ||||
|           cairo_region_get_rectangle (region, i, &rect); | ||||
|           paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc); | ||||
|         } | ||||
|  | ||||
|       cogl_object_unref (opaque_pipeline); | ||||
|  | ||||
|       if (priv->clip_region != NULL) | ||||
|         { | ||||
|           blended_region = cairo_region_copy (priv->clip_region); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height }; | ||||
|           blended_region = cairo_region_create_rectangle (&rect); | ||||
|         } | ||||
|  | ||||
|       cairo_region_subtract (blended_region, priv->opaque_region); | ||||
|  | ||||
|     paint_blended: | ||||
|       cairo_region_destroy (region); | ||||
|     } | ||||
|  | ||||
|   if (blended_region == NULL && priv->clip_region != NULL) | ||||
|     blended_region = cairo_region_reference (priv->clip_region); | ||||
|  | ||||
|   if (blended_region != NULL && cairo_region_is_empty (blended_region)) | ||||
|     goto out; | ||||
|  | ||||
|   if (priv->mask_texture == NULL) | ||||
|     { | ||||
|       /* Use a single-layer texture if we don't have a mask. */ | ||||
|  | ||||
|       if (priv->pipeline_unshaped == NULL) | ||||
|         { | ||||
|           if (G_UNLIKELY (pipeline_unshaped_template == NULL)) | ||||
|             { | ||||
|               CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|               pipeline_unshaped_template = cogl_pipeline_new (ctx); | ||||
|             } | ||||
|  | ||||
|           priv->pipeline_unshaped = cogl_pipeline_copy (pipeline_unshaped_template); | ||||
|         } | ||||
|         pipeline = priv->pipeline_unshaped; | ||||
|       pipeline = get_unmasked_pipeline (ctx); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (priv->pipeline == NULL) | ||||
| 	{ | ||||
| 	   if (G_UNLIKELY (pipeline_template == NULL)) | ||||
| 	    { | ||||
|               CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
| 	      pipeline_template =  cogl_pipeline_new (ctx); | ||||
| 	      cogl_pipeline_set_layer_combine (pipeline_template, 1, | ||||
| 					   "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", | ||||
| 					   NULL); | ||||
| 	    } | ||||
| 	  priv->pipeline = cogl_pipeline_copy (pipeline_template); | ||||
| 	} | ||||
|       pipeline = priv->pipeline; | ||||
|  | ||||
|       pipeline = get_masked_pipeline (ctx); | ||||
|       cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture); | ||||
|     } | ||||
|  | ||||
| @@ -293,20 +383,13 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|  | ||||
|   { | ||||
|     CoglColor color; | ||||
|     guchar opacity = clutter_actor_get_paint_opacity (actor); | ||||
|     cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|     cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|     cogl_pipeline_set_color (pipeline, &color); | ||||
|   } | ||||
|  | ||||
|   cogl_set_source (pipeline); | ||||
|  | ||||
|   clutter_actor_get_allocation_box (actor, &alloc); | ||||
|  | ||||
|   if (priv->clip_region) | ||||
|   if (blended_region != NULL) | ||||
|     { | ||||
|       int n_rects; | ||||
|       int i; | ||||
|       cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height }; | ||||
|  | ||||
|       /* Limit to how many separate rectangles we'll draw; beyond this just | ||||
|        * fall back and draw the whole thing */ | ||||
| @@ -315,8 +398,8 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|       n_rects = cairo_region_num_rectangles (priv->clip_region); | ||||
|       if (n_rects <= MAX_RECTS) | ||||
| 	{ | ||||
| 	  float coords[8]; | ||||
|           float x1, y1, x2, y2; | ||||
|           int i; | ||||
|           cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height }; | ||||
|  | ||||
| 	  for (i = 0; i < n_rects; i++) | ||||
| 	    { | ||||
| @@ -327,32 +410,23 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
| 	      if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) | ||||
| 		continue; | ||||
|  | ||||
| 	      x1 = rect.x; | ||||
| 	      y1 = rect.y; | ||||
| 	      x2 = rect.x + rect.width; | ||||
| 	      y2 = rect.y + rect.height; | ||||
|  | ||||
| 	      coords[0] = rect.x / (alloc.x2 - alloc.x1); | ||||
| 	      coords[1] = rect.y / (alloc.y2 - alloc.y1); | ||||
| 	      coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1); | ||||
| 	      coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1); | ||||
|  | ||||
|               coords[4] = coords[0]; | ||||
|               coords[5] = coords[1]; | ||||
|               coords[6] = coords[2]; | ||||
|               coords[7] = coords[3]; | ||||
|  | ||||
|               cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2, | ||||
|                                                        &coords[0], 8); | ||||
|               paint_clipped_rectangle (fb, pipeline, &rect, &alloc); | ||||
|             } | ||||
|  | ||||
| 	  return; | ||||
|           goto out; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   cogl_rectangle (0, 0, | ||||
| 		  alloc.x2 - alloc.x1, | ||||
| 		  alloc.y2 - alloc.y1); | ||||
|   cogl_framebuffer_draw_rectangle (fb, pipeline, | ||||
|                                    0, 0, | ||||
|                                    alloc.x2 - alloc.x1, | ||||
|                                    alloc.y2 - alloc.y1); | ||||
|  | ||||
|  out: | ||||
|   if (pipeline != NULL) | ||||
|     cogl_object_unref (pipeline); | ||||
|   if (blended_region != NULL) | ||||
|     cairo_region_destroy (blended_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -368,13 +442,17 @@ meta_shaped_texture_pick (ClutterActor       *actor, | ||||
|  | ||||
|   /* 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); | ||||
|     CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color); | ||||
|   else | ||||
|     { | ||||
|       int n_rects; | ||||
|       float *rectangles; | ||||
|       int i; | ||||
|       ClutterActorBox alloc; | ||||
|       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 | ||||
| @@ -403,12 +481,17 @@ meta_shaped_texture_pick (ClutterActor       *actor, | ||||
|           rectangles[pos + 3] = rect.y + rect.height; | ||||
|         } | ||||
|  | ||||
|       cogl_set_source_color4ub (color->red, | ||||
|                                 color->green, | ||||
|                                 color->blue, | ||||
|                                 color->alpha); | ||||
|       ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|       cogl_rectangles (rectangles, n_rects); | ||||
|       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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -845,6 +928,36 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, | ||||
|     priv->clip_region = NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_opaque_region: | ||||
|  * @stex: a #MetaShapedTexture | ||||
|  * @opaque_region: (transfer full): the region of the texture that | ||||
|  *   can have blending turned off. | ||||
|  * | ||||
|  * As most windows have a large portion that does not require blending, | ||||
|  * we can easily turn off blending if we know the areas that do not | ||||
|  * require blending. This sets the region where we will not blend for | ||||
|  * optimization purposes. | ||||
|  */ | ||||
| void | ||||
| meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex, | ||||
|                                        cairo_region_t    *opaque_region) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->opaque_region) | ||||
|     cairo_region_destroy (priv->opaque_region); | ||||
|  | ||||
|   if (opaque_region) | ||||
|     priv->opaque_region = cairo_region_reference (opaque_region); | ||||
|   else | ||||
|     priv->opaque_region = NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_get_image: | ||||
|  * @stex: A #MetaShapedTexture | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
|  | ||||
| #include <math.h> | ||||
|  | ||||
| #include <X11/extensions/shape.h> | ||||
| #include <X11/extensions/Xcomposite.h> | ||||
| #include <X11/extensions/Xdamage.h> | ||||
| #include <X11/extensions/Xrender.h> | ||||
| @@ -71,7 +70,7 @@ struct _MetaWindowActorPrivate | ||||
|   /* A region that matches the shape of the window, including frame bounds */ | ||||
|   cairo_region_t   *shape_region; | ||||
|   /* If the window has an input shape, a region that matches the shape */ | ||||
|   cairo_region_t   *input_shape_region; | ||||
|   cairo_region_t   *input_region; | ||||
|   /* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with | ||||
|    * the shape region. */ | ||||
|   cairo_region_t   *opaque_region; | ||||
| @@ -407,8 +406,8 @@ meta_window_actor_constructed (GObject *object) | ||||
|  | ||||
|   /* Start off with empty regions to maintain the invariant that | ||||
|      these regions are always set */ | ||||
|   priv->shape_region = cairo_region_create(); | ||||
|   priv->input_shape_region = cairo_region_create(); | ||||
|   priv->shape_region = cairo_region_create (); | ||||
|   priv->input_region = cairo_region_create (); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -438,7 +437,7 @@ meta_window_actor_dispose (GObject *object) | ||||
|     } | ||||
|  | ||||
|   g_clear_pointer (&priv->shape_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->input_shape_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->input_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->shadow_clip, cairo_region_destroy); | ||||
|  | ||||
| @@ -1260,7 +1259,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self) | ||||
|   if (priv->opacity != 0xff) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (metaWindow->has_shape) | ||||
|   if (metaWindow->shape_region != NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow)) | ||||
| @@ -2171,85 +2170,21 @@ build_and_scan_frame_mask (MetaWindowActor       *self, | ||||
|   g_free (mask_data); | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| region_create_from_x_rectangles (const XRectangle *rects, | ||||
|                                  int n_rects, | ||||
|                                  int dx, | ||||
|                                  int dy) | ||||
| { | ||||
|   int i; | ||||
|   cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects); | ||||
|  | ||||
|   for (i = 0; i < n_rects; i ++) | ||||
|     { | ||||
|       cairo_rects[i].x = rects[i].x + dx; | ||||
|       cairo_rects[i].y = rects[i].y + dy; | ||||
|       cairo_rects[i].width = rects[i].width; | ||||
|       cairo_rects[i].height = rects[i].height; | ||||
|     } | ||||
|  | ||||
|   return cairo_region_create_rectangles (cairo_rects, n_rects); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_actor_update_x11_shape_region (MetaWindowActor *self, | ||||
|                                            cairo_rectangle_int_t *client_area) | ||||
| meta_window_actor_update_shape_region (MetaWindowActor       *self, | ||||
|                                        cairo_rectangle_int_t *client_area) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   cairo_region_t *region = NULL; | ||||
|   gboolean needs_mask; | ||||
|  | ||||
|   if (priv->shadow_shape != NULL) | ||||
|   if (priv->window->frame != NULL && priv->window->shape_region != NULL) | ||||
|     { | ||||
|       meta_window_shape_unref (priv->shadow_shape); | ||||
|       priv->shadow_shape = NULL; | ||||
|       region = cairo_region_copy (priv->window->shape_region); | ||||
|       cairo_region_translate (region, client_area->x, client_area->y); | ||||
|     } | ||||
|  | ||||
|   meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL); | ||||
|   g_clear_pointer (&priv->shape_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|  | ||||
| #ifdef HAVE_SHAPE | ||||
|   if (priv->window->has_shape) | ||||
|   else if (priv->window->shape_region != NULL) | ||||
|     { | ||||
|       /* Translate the set of XShape rectangles that we | ||||
|        * get from the X server to a cairo_region. */ | ||||
|       MetaScreen *screen = priv->screen; | ||||
|       MetaDisplay *display = meta_screen_get_display (screen); | ||||
|       Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|       XRectangle *rects; | ||||
|       int n_rects, ordering; | ||||
|  | ||||
|       meta_error_trap_push (display); | ||||
|       rects = XShapeGetRectangles (xdisplay, | ||||
|                                    priv->window->xwindow, | ||||
|                                    ShapeBounding, | ||||
|                                    &n_rects, | ||||
|                                    &ordering); | ||||
|       meta_error_trap_pop (display); | ||||
|  | ||||
|       if (rects) | ||||
|         { | ||||
|           region = region_create_from_x_rectangles (rects, n_rects, | ||||
|                                                     client_area->x, | ||||
|                                                     client_area->y); | ||||
|           XFree (rects); | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   needs_mask = (region != NULL) || (priv->window->frame != NULL); | ||||
|  | ||||
|   if (region != NULL) | ||||
|     { | ||||
|       /* The shape we get back from the client may have coordinates | ||||
|        * outside of the frame. The X SHAPE Extension requires that | ||||
|        * the overall shape the client provides never exceeds the | ||||
|        * "bounding rectangle" of the window -- the shape that the | ||||
|        * window would have gotten if it was unshaped. In our case, | ||||
|        * this is simply the client area. | ||||
|        */ | ||||
|       cairo_region_intersect_rectangle (region, client_area); | ||||
|       region = cairo_region_reference (priv->window->shape_region); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -2259,11 +2194,70 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self, | ||||
|       region = cairo_region_create_rectangle (client_area); | ||||
|     } | ||||
|  | ||||
|   /* The region at this point should be constrained to the | ||||
|    * bounds of the client rectangle. */ | ||||
|   meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL); | ||||
|   if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL)) | ||||
|     build_and_scan_frame_mask (self, client_area, region); | ||||
|  | ||||
|   g_clear_pointer (&priv->shape_region, cairo_region_destroy); | ||||
|   priv->shape_region = region; | ||||
|  | ||||
|   if (priv->shadow_shape != NULL) | ||||
|     { | ||||
|       meta_window_shape_unref (priv->shadow_shape); | ||||
|       priv->shadow_shape = NULL; | ||||
|     } | ||||
|  | ||||
|   meta_window_actor_invalidate_shadow (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_actor_update_input_region (MetaWindowActor       *self, | ||||
|                                        cairo_rectangle_int_t *client_area) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor); | ||||
|   cairo_region_t *region = NULL; | ||||
|  | ||||
|   if (priv->window->frame != NULL && priv->window->shape_region != NULL) | ||||
|     { | ||||
|       cairo_region_t *client_region = cairo_region_copy (priv->window->input_region); | ||||
|  | ||||
|       region = meta_frame_get_frame_bounds (priv->window->frame); | ||||
|  | ||||
|       cairo_region_subtract_rectangle (region, client_area); | ||||
|       cairo_region_translate (client_region, client_area->x, client_area->y); | ||||
|       cairo_region_union (region, client_region); | ||||
|       cairo_region_destroy (client_region); | ||||
|     } | ||||
|   else if (priv->window->shape_region != NULL) | ||||
|     { | ||||
|       region = cairo_region_reference (priv->window->input_region); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* If we don't have a shape on the server, that means that | ||||
|        * we have an implicit shape of one rectangle covering the | ||||
|        * entire window. */ | ||||
|       region = cairo_region_create_rectangle (client_area); | ||||
|     } | ||||
|  | ||||
|   meta_shaped_texture_set_input_shape_region (stex, region); | ||||
|   cairo_region_destroy (region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_actor_update_opaque_region (MetaWindowActor *self) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|  | ||||
|   if (priv->argb32 && priv->window->opaque_region != NULL) | ||||
|     { | ||||
|       MetaFrameBorders borders; | ||||
|  | ||||
|       meta_frame_calc_borders (priv->window->frame, &borders); | ||||
|  | ||||
|       /* The opaque region is defined to be a part of the | ||||
|        * window which ARGB32 will always paint with opaque | ||||
|        * pixels. For these regions, we want to avoid painting | ||||
| @@ -2275,91 +2269,16 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self, | ||||
|        * case, graphical glitches will occur. | ||||
|        */ | ||||
|       priv->opaque_region = cairo_region_copy (priv->window->opaque_region); | ||||
|       cairo_region_translate (priv->opaque_region, client_area->x, client_area->y); | ||||
|       cairo_region_intersect (priv->opaque_region, region); | ||||
|       cairo_region_translate (priv->opaque_region, borders.total.left, borders.total.top); | ||||
|       cairo_region_intersect (priv->opaque_region, priv->shape_region); | ||||
|     } | ||||
|   else if (priv->argb32) | ||||
|     priv->opaque_region = NULL; | ||||
|   else | ||||
|     priv->opaque_region = cairo_region_reference (region); | ||||
|     priv->opaque_region = cairo_region_reference (priv->shape_region); | ||||
|  | ||||
|   if (needs_mask) | ||||
|     { | ||||
|       /* This takes the region, generates a mask using GTK+ | ||||
|        * and scans the mask looking for all opaque pixels, | ||||
|        * adding it to region. | ||||
|        */ | ||||
|       build_and_scan_frame_mask (self, client_area, region); | ||||
|     } | ||||
|  | ||||
|   priv->shape_region = region; | ||||
|  | ||||
|   meta_window_actor_invalidate_shadow (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_window_actor_update_x11_input_shape_region (MetaWindowActor *self, | ||||
|                                                  cairo_rectangle_int_t *client_area) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = self->priv; | ||||
|   cairo_region_t *region = NULL; | ||||
|  | ||||
|   g_clear_pointer (&priv->input_shape_region, cairo_region_destroy); | ||||
|  | ||||
| #ifdef HAVE_SHAPE | ||||
|   /* Note: we currently assume that mutter never sets an input region | ||||
|    * when there is a frame. */ | ||||
|   if (priv->window->frame == NULL && priv->window->has_input_shape) | ||||
|     { | ||||
|       MetaScreen *screen = priv->screen; | ||||
|       MetaDisplay *display = meta_screen_get_display (screen); | ||||
|       Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|       XRectangle *rects; | ||||
|       int n_rects, ordering; | ||||
|  | ||||
|       /* Note we only actually query the ShapeInput shape of a window | ||||
|        * when we don't have a frame because we assume currently that | ||||
|        * mutter never sets an ShapeInput shape on a frame. */ | ||||
|       meta_error_trap_push (display); | ||||
|       rects = XShapeGetRectangles (xdisplay, | ||||
|                                    priv->window->xwindow, | ||||
|                                    ShapeInput, | ||||
|                                    &n_rects, | ||||
|                                    &ordering); | ||||
|       meta_error_trap_pop (display); | ||||
|       if (rects) | ||||
|         { | ||||
|           region = region_create_from_x_rectangles (rects, n_rects, | ||||
|                                                     client_area->x, | ||||
|                                                     client_area->y); | ||||
|           XFree (rects); | ||||
|         } | ||||
|     } | ||||
| #endif /* HAVE_SHAPE */ | ||||
|  | ||||
|   if (region != NULL) | ||||
|     { | ||||
|       /* The X shape extension requires us to intersect the input | ||||
|        * region with the effective bounding shape to determine the | ||||
|        * effective input region. | ||||
|        */ | ||||
|       if (priv->shape_region) | ||||
|         cairo_region_intersect (region, priv->shape_region); | ||||
|       else | ||||
|         cairo_region_intersect_rectangle (region, client_area); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* If we don't have a shape on the server, that means that we | ||||
|        * have an implicit shape of one rectangle covering the entire | ||||
|        * window. */ | ||||
|       region = cairo_region_create_rectangle (client_area); | ||||
|     } | ||||
|  | ||||
|   priv->input_shape_region = region; | ||||
|  | ||||
|   meta_shaped_texture_set_input_shape_region (META_SHAPED_TEXTURE (priv->actor), | ||||
|                                               priv->input_shape_region); | ||||
|   meta_shaped_texture_set_opaque_region (META_SHAPED_TEXTURE (priv->actor), | ||||
|                                          priv->opaque_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -2385,24 +2304,9 @@ check_needs_reshape (MetaWindowActor *self) | ||||
|   else | ||||
|     client_area.height = priv->window->rect.height; | ||||
|  | ||||
|   if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11) | ||||
|     { | ||||
|       meta_window_actor_update_x11_shape_region (self, &client_area); | ||||
|       meta_window_actor_update_x11_input_shape_region (self, &client_area); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* TODO: properly support setting an input region as specified | ||||
|        * via the wayland protocol */ | ||||
|  | ||||
|       g_clear_pointer (&priv->shape_region, cairo_region_destroy); | ||||
|       g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|       g_clear_pointer (&priv->input_shape_region, cairo_region_destroy); | ||||
|  | ||||
|       priv->shape_region = cairo_region_create_rectangle (&client_area); | ||||
|       priv->opaque_region = cairo_region_reference (priv->shape_region); | ||||
|       priv->input_shape_region = cairo_region_reference (priv->shape_region); | ||||
|     } | ||||
|   meta_window_actor_update_shape_region (self, &client_area); | ||||
|   meta_window_actor_update_input_region (self, &client_area); | ||||
|   meta_window_actor_update_opaque_region (self); | ||||
|  | ||||
|   priv->needs_reshape = FALSE; | ||||
| } | ||||
| @@ -2463,6 +2367,8 @@ meta_window_actor_set_wayland_surface (MetaWindowActor *self, | ||||
|                                            surface); | ||||
|   if (surface && surface->buffer_ref.buffer) | ||||
|     maybe_emit_size_changed (self, surface->buffer_ref.buffer); | ||||
|  | ||||
|   meta_window_actor_invalidate_shadow (self); | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
| @@ -186,7 +186,6 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|  | ||||
|       if (META_IS_WINDOW_ACTOR (child)) | ||||
|         { | ||||
|           MetaWindow *meta_window; | ||||
|           MetaWindowActor *window_actor = META_WINDOW_ACTOR (child); | ||||
|           int x, y; | ||||
|  | ||||
| @@ -201,14 +200,7 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|  | ||||
|           meta_window_actor_set_visible_region (window_actor, visible_region); | ||||
|  | ||||
|           /* TODO: Track the opaque regions of wayland clients. | ||||
|            * Although wayland clients can report opaque window | ||||
|            * regions, for now we assume that all wayland clients are | ||||
|            * transparent... */ | ||||
|           meta_window = meta_window_actor_get_meta_window (window_actor); | ||||
|  | ||||
|           if (meta_window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND && | ||||
|               clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff) | ||||
|           if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff) | ||||
|             { | ||||
|               cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor); | ||||
|               if (obscured_region) | ||||
|   | ||||
| @@ -2336,59 +2336,9 @@ meta_display_handle_event (MetaDisplay *display, | ||||
|           XShapeEvent *sev = (XShapeEvent*) event; | ||||
|  | ||||
|           if (sev->kind == ShapeBounding) | ||||
|             { | ||||
|               if (sev->shaped && !window->has_shape) | ||||
|                 { | ||||
|                   window->has_shape = TRUE;                   | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s now has a shape\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|               else if (!sev->shaped && window->has_shape) | ||||
|                 { | ||||
|                   window->has_shape = FALSE; | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s no longer has a shape\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|               else | ||||
|                 { | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s shape changed\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|  | ||||
|               if (display->compositor) | ||||
|                 meta_compositor_window_x11_shape_changed (display->compositor, | ||||
|                                                           window); | ||||
|             } | ||||
|             meta_window_update_shape_region_x11 (window); | ||||
|           else if (sev->kind == ShapeInput) | ||||
|             { | ||||
|               if (sev->shaped && !window->has_input_shape) | ||||
|                 { | ||||
|                   window->has_input_shape = TRUE;                   | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s now has an input shape\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|               else if (!sev->shaped && window->has_input_shape) | ||||
|                 { | ||||
|                   window->has_input_shape = FALSE; | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s no longer has an input shape\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|               else | ||||
|                 { | ||||
|                   meta_topic (META_DEBUG_SHAPES, | ||||
|                               "Window %s input shape changed\n", | ||||
|                               window->desc); | ||||
|                 } | ||||
|  | ||||
|               if (display->compositor) | ||||
|                 meta_compositor_window_x11_shape_changed (display->compositor, | ||||
|                                                           window); | ||||
|             } | ||||
|             meta_window_update_input_region_x11 (window); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|   | ||||
| @@ -339,11 +339,6 @@ struct _MetaWindow | ||||
|   guint using_net_wm_icon_name         : 1; /* vs. plain wm_icon_name */ | ||||
|   guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */ | ||||
|  | ||||
|   /* has a bounding shape mask */ | ||||
|   guint has_shape : 1; | ||||
|   /* has an input shape mask */ | ||||
|   guint has_input_shape : 1; | ||||
|  | ||||
|   /* icon props have changed */ | ||||
|   guint need_reread_icon : 1; | ||||
|    | ||||
| @@ -365,9 +360,15 @@ struct _MetaWindow | ||||
|   /* if non-NULL, the bounds of the window frame */ | ||||
|   cairo_region_t *frame_bounds; | ||||
|  | ||||
|   /* if non-NULL, the bounding shape region of the window */ | ||||
|   cairo_region_t *shape_region; | ||||
|  | ||||
|   /* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */ | ||||
|   cairo_region_t *opaque_region; | ||||
|  | ||||
|   /* the input shape region for picking */ | ||||
|   cairo_region_t *input_region; | ||||
|  | ||||
|   /* if TRUE, the we have the new form of sync request counter which | ||||
|    * also handles application frames */ | ||||
|   guint extended_sync_request_counter : 1; | ||||
| @@ -685,7 +686,6 @@ void meta_window_update_icon_now (MetaWindow *window); | ||||
|  | ||||
| void meta_window_update_role (MetaWindow *window); | ||||
| void meta_window_update_net_wm_type (MetaWindow *window); | ||||
| void meta_window_update_opaque_region (MetaWindow *window); | ||||
| void meta_window_update_for_monitors_changed (MetaWindow *window); | ||||
| void meta_window_update_on_all_workspaces (MetaWindow *window); | ||||
|  | ||||
| @@ -699,4 +699,16 @@ void meta_window_compute_tile_match (MetaWindow *window); | ||||
|  | ||||
| gboolean meta_window_updates_are_frozen (MetaWindow *window); | ||||
|  | ||||
| void meta_window_set_opaque_region        (MetaWindow     *window, | ||||
|                                            cairo_region_t *region); | ||||
| void meta_window_update_opaque_region_x11 (MetaWindow *window); | ||||
|  | ||||
| void meta_window_set_input_region         (MetaWindow     *window, | ||||
|                                            cairo_region_t *region); | ||||
| void meta_window_update_input_region_x11  (MetaWindow *window); | ||||
|  | ||||
| void meta_window_set_shape_region         (MetaWindow     *window, | ||||
|                                            cairo_region_t *region); | ||||
| void meta_window_update_shape_region_x11  (MetaWindow *window); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -565,7 +565,7 @@ reload_opaque_region (MetaWindow    *window, | ||||
|                       MetaPropValue *value, | ||||
|                       gboolean       initial) | ||||
| { | ||||
|   meta_window_update_opaque_region (window); | ||||
|   meta_window_update_opaque_region_x11 (window); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -822,8 +822,6 @@ meta_window_new_shared (MetaDisplay         *display, | ||||
|                         Window               xwindow, | ||||
|                         gboolean             must_be_viewable, | ||||
|                         gulong               existing_wm_state, | ||||
|                         gboolean             has_shape, | ||||
|                         gboolean             has_input_shape, | ||||
|                         MetaCompEffect       effect, | ||||
|                         XWindowAttributes   *attrs) | ||||
| { | ||||
| @@ -876,9 +874,6 @@ meta_window_new_shared (MetaDisplay         *display, | ||||
|   /* avoid tons of stack updates */ | ||||
|   meta_stack_freeze (window->screen->stack); | ||||
|  | ||||
|   window->has_shape = has_shape; | ||||
|   window->has_input_shape = has_input_shape; | ||||
|  | ||||
|   window->rect.x = attrs->x; | ||||
|   window->rect.y = attrs->y; | ||||
|   window->rect.width = attrs->width; | ||||
| @@ -1059,6 +1054,8 @@ meta_window_new_shared (MetaDisplay         *display, | ||||
|         } | ||||
|  | ||||
|       meta_display_register_x_window (display, &window->xwindow, window); | ||||
|       meta_window_update_shape_region_x11 (window); | ||||
|       meta_window_update_input_region_x11 (window); | ||||
|     } | ||||
|  | ||||
|   /* assign the window to its group, or create a new group if needed | ||||
| @@ -1425,8 +1422,6 @@ meta_window_new_for_wayland (MetaDisplay        *display, | ||||
|                                    None, | ||||
|                                    TRUE, | ||||
|                                    WithdrawnState, | ||||
|                                    FALSE, /* has shape */ | ||||
|                                    FALSE, /* has input shape */ | ||||
|                                    META_COMP_EFFECT_NONE, | ||||
|                                    &attrs); | ||||
|  | ||||
| @@ -1455,8 +1450,6 @@ meta_window_new_with_attrs (MetaDisplay       *display, | ||||
|   gulong existing_wm_state; | ||||
|   MetaWindow *window; | ||||
|   gulong event_mask; | ||||
|   gboolean has_shape = FALSE; | ||||
|   gboolean has_input_shape = FALSE; | ||||
|  | ||||
|   meta_verbose ("Attempting to manage 0x%lx\n", xwindow); | ||||
|  | ||||
| @@ -1576,53 +1569,6 @@ meta_window_new_with_attrs (MetaDisplay       *display, | ||||
|       XISelectEvents (display->xdisplay, xwindow, &mask, 1); | ||||
|     } | ||||
|  | ||||
| #ifdef HAVE_SHAPE | ||||
|   if (META_DISPLAY_HAS_SHAPE (display)) | ||||
|     { | ||||
|       int x_bounding, y_bounding, x_clip, y_clip; | ||||
|       unsigned w_bounding, h_bounding, w_clip, h_clip; | ||||
|       int bounding_shaped, clip_shaped; | ||||
|       XRectangle *input_rectangles; | ||||
|       int n_rects, ordering; | ||||
|  | ||||
|       XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask); | ||||
|  | ||||
|       XShapeQueryExtents (display->xdisplay, xwindow, | ||||
|                           &bounding_shaped, &x_bounding, &y_bounding, | ||||
|                           &w_bounding, &h_bounding, | ||||
|                           &clip_shaped, &x_clip, &y_clip, | ||||
|                           &w_clip, &h_clip); | ||||
|  | ||||
|       has_shape = bounding_shaped != FALSE; | ||||
|  | ||||
|       /* XXX: The x shape extension doesn't provide a way to only test if an | ||||
|        * input shape has been specified, so we have to query and throw away the | ||||
|        * rectangles. */ | ||||
|       meta_error_trap_push (display); | ||||
|       input_rectangles = XShapeGetRectangles (display->xdisplay, xwindow, | ||||
|                                               ShapeInput, &n_rects, &ordering); | ||||
|       meta_error_trap_pop (display); | ||||
|       if (input_rectangles) | ||||
|         { | ||||
|           if (n_rects > 1 || | ||||
|               (n_rects == 1 && | ||||
|                (input_rectangles[0].x != x_bounding || | ||||
|                 input_rectangles[1].y != y_bounding || | ||||
|                 input_rectangles[2].width != w_bounding || | ||||
|                 input_rectangles[3].height != h_bounding))) | ||||
|             { | ||||
|               has_input_shape = TRUE; | ||||
|             } | ||||
|           XFree (input_rectangles); | ||||
|         } | ||||
|  | ||||
|       meta_topic (META_DEBUG_SHAPES, | ||||
|                   "Window has_shape = %d extents %d,%d %u x %u\n", | ||||
|                   has_shape, x_bounding, y_bounding, | ||||
|                   w_bounding, h_bounding); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   /* Get rid of any borders */ | ||||
|   if (attrs->border_width != 0) | ||||
|     XSetWindowBorderWidth (display->xdisplay, xwindow, 0); | ||||
| @@ -1656,8 +1602,6 @@ meta_window_new_with_attrs (MetaDisplay       *display, | ||||
|                                    xwindow, | ||||
|                                    must_be_viewable, | ||||
|                                    existing_wm_state, | ||||
|                                    has_shape, | ||||
|                                    has_input_shape, | ||||
|                                    effect, | ||||
|                                    attrs); | ||||
|  | ||||
| @@ -7810,14 +7754,25 @@ meta_window_update_net_wm_type (MetaWindow *window) | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_update_opaque_region (MetaWindow *window) | ||||
| meta_window_set_opaque_region (MetaWindow     *window, | ||||
|                                cairo_region_t *region) | ||||
| { | ||||
|   g_clear_pointer (&window->opaque_region, cairo_region_destroy); | ||||
|  | ||||
|   if (region != NULL) | ||||
|     window->opaque_region = cairo_region_reference (region); | ||||
|  | ||||
|   if (window->display->compositor) | ||||
|     meta_compositor_window_shape_changed (window->display->compositor, window); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_update_opaque_region_x11 (MetaWindow *window) | ||||
| { | ||||
|   cairo_region_t *opaque_region = NULL; | ||||
|   gulong *region = NULL; | ||||
|   int nitems; | ||||
|  | ||||
|   g_clear_pointer (&window->opaque_region, cairo_region_destroy); | ||||
|  | ||||
|   if (meta_prop_get_cardinal_list (window->display, | ||||
|                                    window->xwindow, | ||||
|                                    window->display->atom__NET_WM_OPAQUE_REGION, | ||||
| @@ -7860,11 +7815,191 @@ meta_window_update_opaque_region (MetaWindow *window) | ||||
|     } | ||||
|  | ||||
|  out: | ||||
|   window->opaque_region = opaque_region; | ||||
|   meta_XFree (region); | ||||
|  | ||||
|   meta_window_set_opaque_region (window, opaque_region); | ||||
|   cairo_region_destroy (opaque_region); | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| region_create_from_x_rectangles (const XRectangle *rects, | ||||
|                                  int n_rects) | ||||
| { | ||||
|   int i; | ||||
|   cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects); | ||||
|  | ||||
|   for (i = 0; i < n_rects; i ++) | ||||
|     { | ||||
|       cairo_rects[i].x = rects[i].x; | ||||
|       cairo_rects[i].y = rects[i].y; | ||||
|       cairo_rects[i].width = rects[i].width; | ||||
|       cairo_rects[i].height = rects[i].height; | ||||
|     } | ||||
|  | ||||
|   return cairo_region_create_rectangles (cairo_rects, n_rects); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_set_input_region (MetaWindow     *window, | ||||
|                               cairo_region_t *region) | ||||
| { | ||||
|   g_clear_pointer (&window->input_region, cairo_region_destroy); | ||||
|  | ||||
|   if (region != NULL) | ||||
|     window->input_region = cairo_region_reference (region); | ||||
|  | ||||
|   if (window->display->compositor) | ||||
|     meta_compositor_window_x11_shape_changed (window->display->compositor, window); | ||||
|     meta_compositor_window_shape_changed (window->display->compositor, window); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_update_input_region_x11 (MetaWindow *window) | ||||
| { | ||||
|   cairo_region_t *region = NULL; | ||||
|  | ||||
| #ifdef HAVE_SHAPE | ||||
|   if (META_DISPLAY_HAS_SHAPE (window->display)) | ||||
|     { | ||||
|       /* Translate the set of XShape rectangles that we | ||||
|        * get from the X server to a cairo_region. */ | ||||
|       XRectangle *rects = NULL; | ||||
|       int n_rects, ordering; | ||||
|  | ||||
|       int x_bounding, y_bounding, x_clip, y_clip; | ||||
|       unsigned w_bounding, h_bounding, w_clip, h_clip; | ||||
|       int bounding_shaped, clip_shaped; | ||||
|  | ||||
|       meta_error_trap_push (window->display); | ||||
|       XShapeQueryExtents (window->display->xdisplay, window->xwindow, | ||||
|                           &bounding_shaped, &x_bounding, &y_bounding, | ||||
|                           &w_bounding, &h_bounding, | ||||
|                           &clip_shaped, &x_clip, &y_clip, | ||||
|                           &w_clip, &h_clip); | ||||
|  | ||||
|       rects = XShapeGetRectangles (window->display->xdisplay, | ||||
|                                    window->xwindow, | ||||
|                                    ShapeInput, | ||||
|                                    &n_rects, | ||||
|                                    &ordering); | ||||
|       meta_error_trap_pop (window->display); | ||||
|  | ||||
|       /* XXX: The x shape extension doesn't provide a way to only test if an | ||||
|        * input shape has been specified, so we have to query and throw away the | ||||
|        * rectangles. */ | ||||
|       if (rects) | ||||
|         { | ||||
|           if (n_rects > 1 || | ||||
|               (n_rects == 1 && | ||||
|                (rects[0].x != x_bounding || | ||||
|                 rects[1].y != y_bounding || | ||||
|                 rects[2].width != w_bounding || | ||||
|                 rects[3].height != h_bounding))) | ||||
|             region = region_create_from_x_rectangles (rects, n_rects); | ||||
|  | ||||
|           XFree (rects); | ||||
|         } | ||||
|     } | ||||
| #endif /* HAVE_SHAPE */ | ||||
|  | ||||
|   if (region != NULL) | ||||
|     { | ||||
|       cairo_rectangle_int_t client_area; | ||||
|  | ||||
|       client_area.x = 0; | ||||
|       client_area.y = 0; | ||||
|       client_area.width = window->rect.width; | ||||
|       client_area.height = window->rect.height; | ||||
|  | ||||
|       /* The shape we get back from the client may have coordinates | ||||
|        * outside of the frame. The X SHAPE Extension requires that | ||||
|        * the overall shape the client provides never exceeds the | ||||
|        * "bounding rectangle" of the window -- the shape that the | ||||
|        * window would have gotten if it was unshaped. In our case, | ||||
|        * this is simply the client area. | ||||
|        */ | ||||
|       cairo_region_intersect_rectangle (region, &client_area); | ||||
|     } | ||||
|  | ||||
|   meta_window_set_input_region (window, region); | ||||
|   cairo_region_destroy (region); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_set_shape_region (MetaWindow     *window, | ||||
|                               cairo_region_t *region) | ||||
| { | ||||
|   g_clear_pointer (&window->shape_region, cairo_region_destroy); | ||||
|  | ||||
|   if (region != NULL) | ||||
|     window->shape_region = cairo_region_reference (region); | ||||
|  | ||||
|   if (window->display->compositor) | ||||
|     meta_compositor_window_shape_changed (window->display->compositor, window); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_update_shape_region_x11 (MetaWindow *window) | ||||
| { | ||||
|   cairo_region_t *region = NULL; | ||||
|  | ||||
| #ifdef HAVE_SHAPE | ||||
|   if (META_DISPLAY_HAS_SHAPE (window->display)) | ||||
|     { | ||||
|       /* Translate the set of XShape rectangles that we | ||||
|        * get from the X server to a cairo_region. */ | ||||
|       XRectangle *rects = NULL; | ||||
|       int n_rects, ordering; | ||||
|  | ||||
|       int x_bounding, y_bounding, x_clip, y_clip; | ||||
|       unsigned w_bounding, h_bounding, w_clip, h_clip; | ||||
|       int bounding_shaped, clip_shaped; | ||||
|  | ||||
|       meta_error_trap_push (window->display); | ||||
|       XShapeQueryExtents (window->display->xdisplay, window->xwindow, | ||||
|                           &bounding_shaped, &x_bounding, &y_bounding, | ||||
|                           &w_bounding, &h_bounding, | ||||
|                           &clip_shaped, &x_clip, &y_clip, | ||||
|                           &w_clip, &h_clip); | ||||
|  | ||||
|       if (bounding_shaped) | ||||
|         { | ||||
|           rects = XShapeGetRectangles (window->display->xdisplay, | ||||
|                                        window->xwindow, | ||||
|                                        ShapeBounding, | ||||
|                                        &n_rects, | ||||
|                                        &ordering); | ||||
|         } | ||||
|       meta_error_trap_pop (window->display); | ||||
|  | ||||
|       if (rects) | ||||
|         { | ||||
|           region = region_create_from_x_rectangles (rects, n_rects); | ||||
|           XFree (rects); | ||||
|         } | ||||
|     } | ||||
| #endif /* HAVE_SHAPE */ | ||||
|  | ||||
|   if (region != NULL) | ||||
|     { | ||||
|       cairo_rectangle_int_t client_area; | ||||
|  | ||||
|       client_area.x = 0; | ||||
|       client_area.y = 0; | ||||
|       client_area.width = window->rect.width; | ||||
|       client_area.height = window->rect.height; | ||||
|  | ||||
|       /* The shape we get back from the client may have coordinates | ||||
|        * outside of the frame. The X SHAPE Extension requires that | ||||
|        * the overall shape the client provides never exceeds the | ||||
|        * "bounding rectangle" of the window -- the shape that the | ||||
|        * window would have gotten if it was unshaped. In our case, | ||||
|        * this is simply the client area. | ||||
|        */ | ||||
|       cairo_region_intersect_rectangle (region, &client_area); | ||||
|     } | ||||
|  | ||||
|   meta_window_set_shape_region (window, region); | ||||
|   cairo_region_destroy (region); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -64,8 +64,8 @@ void meta_compositor_manage_screen   (MetaCompositor *compositor, | ||||
| void meta_compositor_unmanage_screen (MetaCompositor *compositor, | ||||
|                                       MetaScreen     *screen); | ||||
|  | ||||
| void meta_compositor_window_x11_shape_changed (MetaCompositor *compositor, | ||||
|                                                MetaWindow     *window); | ||||
| void meta_compositor_window_shape_changed (MetaCompositor *compositor, | ||||
|                                            MetaWindow     *window); | ||||
|  | ||||
| gboolean meta_compositor_process_event (MetaCompositor *compositor, | ||||
|                                         XEvent         *event, | ||||
|   | ||||
| @@ -84,6 +84,9 @@ void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex, | ||||
| void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, | ||||
| 					  cairo_region_t    *clip_region); | ||||
|  | ||||
| void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex, | ||||
|                                             cairo_region_t    *opaque_region); | ||||
|  | ||||
| cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture     *stex, | ||||
|                                                  cairo_rectangle_int_t *clip); | ||||
|  | ||||
|   | ||||
| @@ -324,18 +324,34 @@ meta_wayland_surface_frame (struct wl_client *client, | ||||
|  | ||||
| static void | ||||
| meta_wayland_surface_set_opaque_region (struct wl_client *client, | ||||
|                                         struct wl_resource *resource, | ||||
|                                         struct wl_resource *region) | ||||
|                                         struct wl_resource *surface_resource, | ||||
|                                         struct wl_resource *region_resource) | ||||
| { | ||||
|   g_warning ("TODO: support set_opaque_region request"); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|   MetaWaylandRegion *region = wl_resource_get_user_data (region_resource); | ||||
|  | ||||
|   /* X11 unmanaged window */ | ||||
|   if (!surface) | ||||
|     return; | ||||
|  | ||||
|   if (surface->window) | ||||
|     meta_window_set_opaque_region (surface->window, cairo_region_copy (region->region)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_wayland_surface_set_input_region (struct wl_client *client, | ||||
|                                        struct wl_resource *resource, | ||||
|                                        struct wl_resource *region) | ||||
|                                        struct wl_resource *surface_resource, | ||||
|                                        struct wl_resource *region_resource) | ||||
| { | ||||
|   g_warning ("TODO: support set_input_region request"); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|   MetaWaylandRegion *region = wl_resource_get_user_data (region_resource); | ||||
|  | ||||
|   /* X11 unmanaged window */ | ||||
|   if (!surface) | ||||
|     return; | ||||
|  | ||||
|   if (surface->window) | ||||
|     meta_window_set_input_region (surface->window, cairo_region_copy (region->region)); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
		Reference in New Issue
	
	Block a user