diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c index ba4e5175b..7957399d0 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c @@ -31,6 +31,8 @@ #include "wayland/meta-wayland-private.h" +#include "compositor/region-utils.h" + struct _MetaSurfaceActorWaylandPrivate { MetaWaylandSurface *surface; @@ -126,12 +128,51 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor) } void -meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor) +meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self) { - MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (actor)); - double output_scale = meta_surface_actor_wayland_get_scale (actor); + MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self); + MetaShapedTexture *stex = + meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + double texture_scale; - clutter_actor_set_scale (CLUTTER_ACTOR (stex), output_scale, output_scale); + /* Given the surface's window type and what output the surface actor has the + * largest region, scale the actor with the determined scale. */ + texture_scale = meta_surface_actor_wayland_get_scale (self); + + /* Actor scale. */ + clutter_actor_set_scale (CLUTTER_ACTOR (stex), texture_scale, texture_scale); + + /* Input region */ + if (surface->input_region) + { + cairo_region_t *scaled_input_region; + int region_scale; + + /* The input region from the Wayland surface is in the Wayland surface + * coordinate space, while the surface actor input region is in the + * physical pixel coordinate space. */ + region_scale = (int)(surface->scale * texture_scale); + scaled_input_region = meta_region_scale (surface->input_region, + region_scale); + meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self), + scaled_input_region); + cairo_region_destroy (scaled_input_region); + } + + /* Opaque region */ + if (surface->opaque_region) + { + cairo_region_t *scaled_opaque_region; + + /* The opaque region from the Wayland surface is in Wayland surface + * coordinate space, while the surface actor opaque region is in the + * same coordinate space as the unscaled buffer texture. */ + scaled_opaque_region = meta_region_scale (surface->opaque_region, + surface->scale); + meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self), + scaled_opaque_region); + cairo_region_destroy (scaled_opaque_region); + } } static MetaWindow * diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h index ed129d7e1..8ef2b05cd 100644 --- a/src/compositor/meta-surface-actor-wayland.h +++ b/src/compositor/meta-surface-actor-wayland.h @@ -63,7 +63,8 @@ void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self, double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); -void meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor); +void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self); + G_END_DECLS #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ diff --git a/src/compositor/region-utils.c b/src/compositor/region-utils.c index a78321d11..1b970ba27 100644 --- a/src/compositor/region-utils.c +++ b/src/compositor/region-utils.c @@ -172,6 +172,35 @@ meta_region_iterator_next (MetaRegionIterator *iter) } } +cairo_region_t * +meta_region_scale (cairo_region_t *region, int scale) +{ + int n_rects, i; + cairo_rectangle_int_t *rects; + cairo_region_t *scaled_region; + + if (scale == 1) + return cairo_region_copy (region); + + n_rects = cairo_region_num_rectangles (region); + + rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects); + for (i = 0; i < n_rects; i++) + { + cairo_region_get_rectangle (region, i, &rects[i]); + rects[i].x *= scale; + rects[i].y *= scale; + rects[i].width *= scale; + rects[i].height *= scale; + } + + scaled_region = cairo_region_create_rectangles (rects, n_rects); + + g_free (rects); + + return scaled_region; +} + static void add_expanded_rect (MetaRegionBuilder *builder, int x, diff --git a/src/compositor/region-utils.h b/src/compositor/region-utils.h index 16304dc70..526e6ecc9 100644 --- a/src/compositor/region-utils.h +++ b/src/compositor/region-utils.h @@ -92,6 +92,8 @@ void meta_region_iterator_init (MetaRegionIterator *iter, gboolean meta_region_iterator_at_end (MetaRegionIterator *iter); void meta_region_iterator_next (MetaRegionIterator *iter); +cairo_region_t *meta_region_scale (cairo_region_t *region, int scale); + cairo_region_t *meta_make_border_region (cairo_region_t *region, int x_amount, int y_amount, diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 3a6f6b616..1ee1c6920 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -356,36 +356,6 @@ parent_surface_committed (gpointer data, gpointer user_data) subsurface_parent_surface_committed (data); } -static cairo_region_t* -scale_region (cairo_region_t *region, int scale) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *scaled_region; - - if (scale == 1) - return region; - - n_rects = cairo_region_num_rectangles (region); - - rects = g_malloc (sizeof(cairo_rectangle_int_t) * n_rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (region, i, &rects[i]); - rects[i].x *= scale; - rects[i].y *= scale; - rects[i].width *= scale; - rects[i].height *= scale; - } - - scaled_region = cairo_region_create_rectangles (rects, n_rects); - - g_free (rects); - cairo_region_destroy (region); - - return scaled_region; -} - static void commit_pending_state (MetaWaylandSurface *surface, MetaWaylandPendingState *pending) @@ -426,18 +396,20 @@ commit_pending_state (MetaWaylandSurface *surface, if (pending->opaque_region) { - pending->opaque_region = scale_region (pending->opaque_region, surface->scale); - meta_surface_actor_set_opaque_region (surface->surface_actor, pending->opaque_region); - } - if (pending->input_region) - { - pending->input_region = scale_region (pending->input_region, - meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor))); - meta_surface_actor_set_input_region (surface->surface_actor, pending->input_region); + if (surface->opaque_region) + cairo_region_destroy (surface->opaque_region); + surface->opaque_region = cairo_region_reference (pending->opaque_region); } - /* scale surface texture */ - meta_surface_actor_wayland_scale_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); + if (pending->input_region) + { + if (surface->input_region) + cairo_region_destroy (surface->input_region); + surface->input_region = cairo_region_reference (pending->input_region); + } + + meta_surface_actor_wayland_sync_state ( + META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)); /* wl_surface.frame */ wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list); @@ -692,6 +664,11 @@ wl_surface_destructor (struct wl_resource *resource) surface_set_buffer (surface, NULL); pending_state_destroy (&surface->pending); + if (surface->opaque_region) + cairo_region_destroy (surface->opaque_region); + if (surface->input_region) + cairo_region_destroy (surface->input_region); + g_object_unref (surface->surface_actor); if (surface->resource) diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 9f8b9de1a..5783a465a 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -81,6 +81,8 @@ struct _MetaWaylandSurface MetaWindow *window; MetaWaylandBuffer *buffer; struct wl_listener buffer_destroy_listener; + cairo_region_t *input_region; + cairo_region_t *opaque_region; int scale; int32_t offset_x, offset_y; GList *subsurfaces;