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);