diff --git a/gdk/gdksubsurface.c b/gdk/gdksubsurface.c index ba275a6ec9..9f124639d2 100644 --- a/gdk/gdksubsurface.c +++ b/gdk/gdksubsurface.c @@ -114,6 +114,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface, const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + const graphene_rect_t *background, gboolean above, GdkSubsurface *sibling) { @@ -156,7 +157,14 @@ gdk_subsurface_attach (GdkSubsurface *subsurface, } } - return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, transform, above, sibling); + return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, + texture, + source, + dest, + transform, + background, + above, + sibling); } void @@ -213,3 +221,12 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface) return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface); } +void +gdk_subsurface_get_background (GdkSubsurface *subsurface, + graphene_rect_t *background) +{ + g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); + g_return_if_fail (background != NULL); + + GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background (subsurface, background); +} diff --git a/gdk/gdksubsurface.c.orig b/gdk/gdksubsurface.c.orig new file mode 100644 index 0000000000..3c0e303977 --- /dev/null +++ b/gdk/gdksubsurface.c.orig @@ -0,0 +1,222 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gdksubsurfaceprivate.h" +#include "gdksurfaceprivate.h" +#include "gdktexture.h" +#include "gsk/gskrectprivate.h" + +G_DEFINE_TYPE (GdkSubsurface, gdk_subsurface, G_TYPE_OBJECT) + +static void +gdk_subsurface_init (GdkSubsurface *self) +{ +} + +static void +gdk_subsurface_finalize (GObject *object) +{ + GdkSubsurface *subsurface = GDK_SUBSURFACE (object); + + g_ptr_array_remove (subsurface->parent->subsurfaces, subsurface); + g_clear_object (&subsurface->parent); + + G_OBJECT_CLASS (gdk_subsurface_parent_class)->finalize (object); +} + +static void +gdk_subsurface_class_init (GdkSubsurfaceClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = gdk_subsurface_finalize; +} + +GdkSurface * +gdk_subsurface_get_parent (GdkSubsurface *subsurface) +{ + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), NULL); + + return subsurface->parent; +} + +static void +remove_subsurface (GdkSubsurface *subsurface) +{ + GdkSurface *parent = subsurface->parent; + + if (parent->subsurfaces_above == subsurface) + parent->subsurfaces_above = subsurface->sibling_above; + if (parent->subsurfaces_below == subsurface) + parent->subsurfaces_below = subsurface->sibling_below; + + if (subsurface->sibling_above) + subsurface->sibling_above->sibling_below = subsurface->sibling_below; + if (subsurface->sibling_below) + subsurface->sibling_below->sibling_above = subsurface->sibling_above; + + subsurface->sibling_above = NULL; + subsurface->sibling_below = NULL; +} + +static void +insert_subsurface (GdkSubsurface *subsurface, + gboolean above, + GdkSubsurface *sibling) +{ + GdkSurface *parent = subsurface->parent; + + subsurface->above_parent = sibling->above_parent; + + if (above) + { + subsurface->sibling_above = sibling->sibling_above; + sibling->sibling_above = subsurface; + subsurface->sibling_below = sibling; + if (subsurface->sibling_above) + subsurface->sibling_above->sibling_below = subsurface; + + if (parent->subsurfaces_below == sibling) + parent->subsurfaces_below = subsurface; + } + else + { + subsurface->sibling_below = sibling->sibling_below; + sibling->sibling_below = subsurface; + subsurface->sibling_above = sibling; + if (subsurface->sibling_below) + subsurface->sibling_below->sibling_above = subsurface; + + if (parent->subsurfaces_above == sibling) + parent->subsurfaces_above = subsurface; + } +} + +gboolean +gdk_subsurface_attach (GdkSubsurface *subsurface, + GdkTexture *texture, + const graphene_rect_t *source, + const graphene_rect_t *dest, + GdkTextureTransform transform, + const graphene_rect_t *background, + gboolean above, + GdkSubsurface *sibling) +{ + GdkSurface *parent = subsurface->parent; + + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE); + g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE); + g_return_val_if_fail (source != NULL && + gsk_rect_contains_rect (&GRAPHENE_RECT_INIT (0, 0, + gdk_texture_get_width (texture), + gdk_texture_get_height (texture)), + source), FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + g_return_val_if_fail (sibling != subsurface, FALSE); + g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE); + g_return_val_if_fail (sibling == NULL || sibling->parent == subsurface->parent, FALSE); + + remove_subsurface (subsurface); + + if (sibling) + { + insert_subsurface (subsurface, above, sibling); + } + else + { + sibling = above ? parent->subsurfaces_above : parent->subsurfaces_below; + + if (sibling) + { + insert_subsurface (subsurface, !above, sibling); + } + else + { + subsurface->above_parent = above; + + if (above) + parent->subsurfaces_above = subsurface; + else + parent->subsurfaces_below = subsurface; + } + } + + return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, + texture, + source, + dest, + transform, + background, + above, + sibling); +} + +void +gdk_subsurface_detach (GdkSubsurface *subsurface) +{ + g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); + + remove_subsurface (subsurface); + + GDK_SUBSURFACE_GET_CLASS (subsurface)->detach (subsurface); +} + +GdkTexture * +gdk_subsurface_get_texture (GdkSubsurface *subsurface) +{ + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), NULL); + + return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_texture (subsurface); +} + +void +gdk_subsurface_get_source (GdkSubsurface *subsurface, + graphene_rect_t *source) +{ + g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); + g_return_if_fail (source != NULL); + + GDK_SUBSURFACE_GET_CLASS (subsurface)->get_source (subsurface, source); +} + +void +gdk_subsurface_get_dest (GdkSubsurface *subsurface, + graphene_rect_t *dest) +{ + g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); + g_return_if_fail (dest != NULL); + + GDK_SUBSURFACE_GET_CLASS (subsurface)->get_dest (subsurface, dest); +} + +gboolean +gdk_subsurface_is_above_parent (GdkSubsurface *subsurface) +{ + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), TRUE); + + return subsurface->above_parent; +} + +GdkTextureTransform +gdk_subsurface_get_transform (GdkSubsurface *subsurface) +{ + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), GDK_TEXTURE_TRANSFORM_NORMAL); + + return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface); +} diff --git a/gdk/gdksubsurface.c.rej b/gdk/gdksubsurface.c.rej new file mode 100644 index 0000000000..b68e718211 --- /dev/null +++ b/gdk/gdksubsurface.c.rej @@ -0,0 +1,16 @@ +--- gdk/gdksubsurface.c ++++ gdk/gdksubsurface.c +@@ -213,3 +213,13 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface) + return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface); + } + ++void ++gdk_subsurface_get_background (GdkSubsurface *subsurface, ++ graphene_rect_t *background) ++{ ++ g_return_if_fail (GDK_IS_SUBSURFACE (subsurface)); ++ g_return_if_fail (background != NULL); ++ ++ GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background (subsurface, background); ++} ++ diff --git a/gdk/gdksubsurfaceprivate.h b/gdk/gdksubsurfaceprivate.h index ea36af1bf5..f7efc5add5 100644 --- a/gdk/gdksubsurfaceprivate.h +++ b/gdk/gdksubsurfaceprivate.h @@ -67,6 +67,7 @@ struct _GdkSubsurfaceClass const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + const graphene_rect_t *bg, gboolean above, GdkSubsurface *sibling); void (* detach) (GdkSubsurface *subsurface); @@ -77,6 +78,8 @@ struct _GdkSubsurfaceClass graphene_rect_t *dest); GdkTextureTransform (* get_transform) (GdkSubsurface *subsurface); + void (* get_background) (GdkSubsurface *subsurface, + graphene_rect_t *background); }; GType gdk_subsurface_get_type (void) G_GNUC_CONST; @@ -88,6 +91,7 @@ gboolean gdk_subsurface_attach (GdkSubsurface *subsurfac const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + const graphene_rect_t *background, gboolean above, GdkSubsurface *sibling); void gdk_subsurface_detach (GdkSubsurface *subsurface); @@ -95,10 +99,12 @@ GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurfac void gdk_subsurface_get_source (GdkSubsurface *subsurface, graphene_rect_t *source); void gdk_subsurface_get_dest (GdkSubsurface *subsurface, - graphene_rect_t *dest); + graphene_rect_t *dest); gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface); GdkTextureTransform gdk_subsurface_get_transform (GdkSubsurface *subsurface); +void gdk_subsurface_get_background (GdkSubsurface *subsurface, + graphene_rect_t *background); G_END_DECLS diff --git a/gdk/gdksubsurfaceprivate.h.orig b/gdk/gdksubsurfaceprivate.h.orig new file mode 100644 index 0000000000..ad4204f542 --- /dev/null +++ b/gdk/gdksubsurfaceprivate.h.orig @@ -0,0 +1,107 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +/* Uninstalled header defining types and functions internal to GDK */ + +#pragma once + +#include "gdkenumtypes.h" +#include "gdksurface.h" +#include + +G_BEGIN_DECLS + +typedef struct _GdkSubsurface GdkSubsurface; +typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass; + +#define GDK_TYPE_SUBSURFACE (gdk_subsurface_get_type ()) +#define GDK_SUBSURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SUBSURFACE, GdkSubsurface)) +#define GDK_SUBSURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SUBSURFACE, GdkSubsurfaceClass)) +#define GDK_IS_SUBSURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SUBSURFACE)) +#define GDK_SUBSURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SUBSURFACE, GdkSubsurfaceClass)) + +struct _GdkSubsurface +{ + GObject parent_instance; + + GdkSurface *parent; + + int ref_count; + + gboolean above_parent; + GdkSubsurface *sibling_above; + GdkSubsurface *sibling_below; +}; + +typedef enum { + GDK_TEXTURE_TRANSFORM_NORMAL, + GDK_TEXTURE_TRANSFORM_90, + GDK_TEXTURE_TRANSFORM_180, + GDK_TEXTURE_TRANSFORM_270, + GDK_TEXTURE_TRANSFORM_FLIPPED, + GDK_TEXTURE_TRANSFORM_FLIPPED_90, + GDK_TEXTURE_TRANSFORM_FLIPPED_180, + GDK_TEXTURE_TRANSFORM_FLIPPED_270, +} GdkTextureTransform; + +struct _GdkSubsurfaceClass +{ + GObjectClass parent_class; + + gboolean (* attach) (GdkSubsurface *subsurface, + GdkTexture *texture, + const graphene_rect_t *source, + const graphene_rect_t *dest, + GdkTextureTransform transform, + const graphene_rect_t *bg, + gboolean above, + GdkSubsurface *sibling); + void (* detach) (GdkSubsurface *subsurface); + GdkTexture * (* get_texture) (GdkSubsurface *subsurface); + void (* get_source) (GdkSubsurface *subsurface, + graphene_rect_t *source); + void (* get_dest) (GdkSubsurface *subsurface, + graphene_rect_t *dest); + GdkTextureTransform + (* get_transform) (GdkSubsurface *subsurface); +}; + +GType gdk_subsurface_get_type (void) G_GNUC_CONST; + +GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface); + +gboolean gdk_subsurface_attach (GdkSubsurface *subsurface, + GdkTexture *texture, + const graphene_rect_t *source, + const graphene_rect_t *dest, + GdkTextureTransform transform, + const graphene_rect_t *background, + gboolean above, + GdkSubsurface *sibling); +void gdk_subsurface_detach (GdkSubsurface *subsurface); +GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface); +void gdk_subsurface_get_source (GdkSubsurface *subsurface, + graphene_rect_t *source); +void gdk_subsurface_get_dest (GdkSubsurface *subsurface, + graphene_rect_t *dest); +gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface); +GdkTextureTransform + gdk_subsurface_get_transform (GdkSubsurface *subsurface); + + +G_END_DECLS + diff --git a/gdk/wayland/gdksubsurface-wayland-private.h b/gdk/wayland/gdksubsurface-wayland-private.h index fb5c98a85a..9b8378ccc2 100644 --- a/gdk/wayland/gdksubsurface-wayland-private.h +++ b/gdk/wayland/gdksubsurface-wayland-private.h @@ -29,6 +29,12 @@ struct _GdkWaylandSubsurface struct wl_region *opaque_region; struct wl_callback *frame_callback; + + struct wl_surface *bg_surface; + struct wl_subsurface *bg_subsurface; + struct wp_viewport *bg_viewport; + cairo_rectangle_int_t bg_rect; + gboolean bg_attached; }; struct _GdkWaylandSubsurfaceClass diff --git a/gdk/wayland/gdksubsurface-wayland.c b/gdk/wayland/gdksubsurface-wayland.c index 45d03daeea..c27643f781 100644 --- a/gdk/wayland/gdksubsurface-wayland.c +++ b/gdk/wayland/gdksubsurface-wayland.c @@ -25,6 +25,8 @@ #include "gdkdmabuftextureprivate.h" #include "gdksurface-wayland-private.h" #include "gdksubsurfaceprivate.h" +#include "gdkdebugprivate.h" +#include "gsk/gskrectprivate.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" @@ -46,6 +48,9 @@ gdk_wayland_subsurface_finalize (GObject *object) g_clear_pointer (&self->viewport, wp_viewport_destroy); g_clear_pointer (&self->subsurface, wl_subsurface_destroy); g_clear_pointer (&self->surface, wl_surface_destroy); + g_clear_pointer (&self->bg_viewport, wp_viewport_destroy); + g_clear_pointer (&self->bg_subsurface, wl_subsurface_destroy); + g_clear_pointer (&self->bg_surface, wl_surface_destroy); G_OBJECT_CLASS (gdk_wayland_subsurface_parent_class)->finalize (object); } @@ -209,6 +214,33 @@ get_wl_buffer (GdkWaylandSubsurface *self, return buffer; } +static void +sp_buffer_release (void *data, + struct wl_buffer *buffer) +{ + wl_buffer_destroy (buffer); +} + +static const struct wl_buffer_listener sp_buffer_listener = { + sp_buffer_release, +}; + +static struct wl_buffer * +get_sp_buffer (GdkWaylandSubsurface *self) +{ + GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SUBSURFACE (self)->parent)); + struct wl_buffer *buffer = NULL; + + if (display->single_pixel_buffer) + buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_buffer, + 0, 0, 0, 0xffffffffU); + + if (buffer) + wl_buffer_add_listener (buffer, &sp_buffer_listener, self); + + return buffer; +} + static inline enum wl_output_transform gdk_texture_transform_to_wl (GdkTextureTransform transform) { @@ -221,12 +253,59 @@ wl_output_transform_to_gdk (enum wl_output_transform transform) return (GdkTextureTransform) transform; } +static void +ensure_bg_surface (GdkWaylandSubsurface *self) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (GDK_SUBSURFACE (self)->parent); + GdkDisplay *display = gdk_surface_get_display (GDK_SUBSURFACE (self)->parent); + GdkWaylandDisplay *disp = GDK_WAYLAND_DISPLAY (display); + struct wl_region *region; + + if (self->bg_surface) + return; + + self->bg_surface = wl_compositor_create_surface (disp->compositor); + self->bg_subsurface = wl_subcompositor_get_subsurface (disp->subcompositor, + self->bg_surface, + impl->display_server.wl_surface); + self->bg_viewport = wp_viewporter_get_viewport (disp->viewporter, self->bg_surface); + + /* We are opaque */ + wl_surface_set_opaque_region (self->bg_surface, self->opaque_region); + + /* No input, please */ + region = wl_compositor_create_region (disp->compositor); + wl_surface_set_input_region (self->bg_surface, region); + wl_region_destroy (region); +} + +static inline gboolean +scaled_rect_is_integral (const graphene_rect_t *rect, + float scale, + graphene_rect_t *device_rect) +{ + cairo_rectangle_int_t device_int; + + gsk_rect_scale (rect, scale, scale, device_rect); + + device_int.x = device_rect->origin.x; + device_int.y = device_rect->origin.y; + device_int.width = device_rect->size.width; + device_int.height = device_rect->size.height; + + return device_int.x == device_rect->origin.x && + device_int.y == device_rect->origin.y && + device_int.width == device_rect->size.width && + device_int.height == device_rect->size.height; +} + static gboolean gdk_wayland_subsurface_attach (GdkSubsurface *sub, GdkTexture *texture, const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + const graphene_rect_t *background, gboolean above, GdkSubsurface *sibling) { @@ -238,7 +317,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, gboolean will_be_above; double scale; graphene_rect_t device_rect; - cairo_rectangle_int_t device_dest; + gboolean has_background; if (sibling) will_be_above = sibling->above_parent; @@ -265,15 +344,22 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, scale = gdk_fractional_scale_to_double (&parent->scale); - device_rect.origin.x = dest->origin.x * scale; - device_rect.origin.y = dest->origin.y * scale; - device_rect.size.width = dest->size.width * scale; - device_rect.size.height = dest->size.height * scale; + if (background) + { + self->bg_rect.x = background->origin.x; + self->bg_rect.y = background->origin.y; + self->bg_rect.width = background->size.width; + self->bg_rect.height = background->size.height; + } + else + { + self->bg_rect.x = 0; + self->bg_rect.y = 0; + self->bg_rect.width = 0; + self->bg_rect.height = 0; + } - device_dest.x = device_rect.origin.x; - device_dest.y = device_rect.origin.y; - device_dest.width = device_rect.size.width; - device_dest.height = device_rect.size.height; + has_background = self->bg_rect.width > 0 && self->bg_rect.height > 0; if (self->dest.x != dest->origin.x || self->dest.y != dest->origin.y || @@ -288,15 +374,21 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, gdk_texture_get_height (texture), self); } - else if (device_dest.x != device_rect.origin.x || - device_dest.y != device_rect.origin.y || - device_dest.width != device_rect.size.width || - device_dest.height != device_rect.size.height) + else if (!scaled_rect_is_integral (dest, scale, &device_rect)) { GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD, "Non-integral device coordinates %g %g %g %g (fractional scale %.2f), hiding subsurface %p", device_rect.origin.x, device_rect.origin.y, - device_rect.size.width, device_rect.size.width, + device_rect.size.width, device_rect.size.height, + scale, + self); + } + else if (background && !scaled_rect_is_integral (background, scale, &device_rect)) + { + GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD, + "Non-integral background device coordinates %g %g %g %g (fractional scale %.2f), hiding background of subsurface %p", + device_rect.origin.x, device_rect.origin.y, + device_rect.size.width, device_rect.size.height, scale, self); } @@ -397,6 +489,38 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, } + if (has_background) + { + ensure_bg_surface (self); + + if (self->bg_surface) + { + wl_subsurface_set_position (self->bg_subsurface, self->bg_rect.x, self->bg_rect.y); + wp_viewport_set_destination (self->bg_viewport, self->bg_rect.width, self->bg_rect.height); + wp_viewport_set_source (self->bg_viewport, + wl_fixed_from_int (0), + wl_fixed_from_int (0), + wl_fixed_from_int (1), + wl_fixed_from_int (1)); + + if (!self->bg_attached) + { + self->bg_attached = TRUE; + + wl_surface_attach (self->bg_surface, get_sp_buffer (self), 0, 0); + wl_surface_damage_buffer (self->bg_surface, 0, 0, 1, 1); + } + } + } + else + { + if (self->bg_surface && self->bg_attached) + { + self->bg_attached = FALSE; + wl_surface_attach (self->bg_surface, NULL, 0, 0); + } + } + result = TRUE; } else @@ -404,6 +528,11 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, g_set_object (&self->texture, NULL); wl_surface_attach (self->surface, NULL, 0, 0); + if (self->bg_surface) + { + self->bg_attached = FALSE; + wl_surface_attach (self->bg_surface, NULL, 0, 0); + } } if (sib) @@ -423,7 +552,12 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, GDK_WAYLAND_SURFACE (sub->parent)->display_server.wl_surface); } + if (self->bg_attached) + wl_subsurface_place_below (self->bg_subsurface, self->surface); + wl_surface_commit (self->surface); + if (self->bg_surface) + wl_surface_commit (self->bg_surface); ((GdkWaylandSurface *)sub->parent)->has_pending_subsurface_commits = TRUE; GDK_WAYLAND_SURFACE (sub->parent)->opaque_region_dirty = TRUE; @@ -447,6 +581,13 @@ gdk_wayland_subsurface_detach (GdkSubsurface *sub) wl_surface_set_opaque_region (self->surface, self->opaque_region); wl_surface_commit (self->surface); + if (self->bg_attached) + { + wl_surface_attach (self->bg_surface, NULL, 0, 0); + wl_surface_commit (self->bg_surface); + self->bg_attached = FALSE; + } + ((GdkWaylandSurface *)sub->parent)->has_pending_subsurface_commits = TRUE; GDK_WAYLAND_SURFACE (sub->parent)->opaque_region_dirty = TRUE; } @@ -491,6 +632,18 @@ gdk_wayland_subsurface_get_transform (GdkSubsurface *sub) return wl_output_transform_to_gdk (self->transform); } +static void +gdk_wayland_subsurface_get_background (GdkSubsurface *sub, + graphene_rect_t *background) +{ + GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); + + background->origin.x = self->bg_rect.x; + background->origin.y = self->bg_rect.y; + background->size.width = self->bg_rect.width; + background->size.height = self->bg_rect.height; +} + static void gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class) { @@ -505,6 +658,7 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class) subsurface_class->get_source = gdk_wayland_subsurface_get_source; subsurface_class->get_dest = gdk_wayland_subsurface_get_dest; subsurface_class->get_transform = gdk_wayland_subsurface_get_transform; + subsurface_class->get_background = gdk_wayland_subsurface_get_background; }; static void diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index 0ef9323a7c..5892562e64 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -691,6 +691,7 @@ gsk_offload_new (GdkSurface *surface, &info->source, &info->dest, info->transform, + &GRAPHENE_RECT_INIT (0, 0, 0, 0), TRUE, NULL); else info->is_offloaded = gdk_subsurface_attach (info->subsurface, @@ -698,6 +699,7 @@ gsk_offload_new (GdkSurface *surface, &info->source, &info->dest, info->transform, + &GRAPHENE_RECT_INIT (0, 0, 0, 0), info->place_above != NULL, info->place_above); } diff --git a/testsuite/gdk/subsurface.c b/testsuite/gdk/subsurface.c index 37657e8049..4b80fb2023 100644 --- a/testsuite/gdk/subsurface.c +++ b/testsuite/gdk/subsurface.c @@ -42,9 +42,9 @@ test_subsurface_stacking (void) texture = gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/media-eject.png"); - gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); - gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); - gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); + gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL); + gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL); + gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL); g_assert_true (surface->subsurfaces_above == sub2); g_assert_true (sub2->sibling_below == NULL); @@ -67,7 +67,7 @@ test_subsurface_stacking (void) g_assert_true (sub0->sibling_above == NULL); g_assert_true (sub0->above_parent); - gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, NULL); + gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, FALSE, NULL); g_assert_true (surface->subsurfaces_above == sub0); g_assert_true (sub0->sibling_below == NULL); @@ -79,7 +79,7 @@ test_subsurface_stacking (void) g_assert_true (sub2->sibling_above == NULL); g_assert_false (sub2->above_parent); - gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, sub2); + gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, sub2); g_assert_true (surface->subsurfaces_below == sub1); g_assert_true (sub1->sibling_above == NULL);