mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 05:31:07 +00:00
Add background to subsurfaces
Make it possible for subsurfaces to have a black background on a secondary subsurface below the actual subsurface. Using a single-pixel buffer for that background increases the changes that the compositor will use direct scanout for the actual subsurface. This changes the private subsurface API. All callers have been updated to pass an empty background rect.
This commit is contained in:
parent
a70998aa50
commit
3f9bdaa4c8
@ -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);
|
||||
}
|
||||
|
222
gdk/gdksubsurface.c.orig
Normal file
222
gdk/gdksubsurface.c.orig
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
16
gdk/gdksubsurface.c.rej
Normal file
16
gdk/gdksubsurface.c.rej
Normal file
@ -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);
|
||||
+}
|
||||
+
|
@ -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
|
||||
|
107
gdk/gdksubsurfaceprivate.h.orig
Normal file
107
gdk/gdksubsurfaceprivate.h.orig
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Uninstalled header defining types and functions internal to GDK */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdksurface.h"
|
||||
#include <graphene.h>
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user