From 7c357e7da5dbe873278a39e0aae9ce915b5a2d75 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 19 Mar 2024 23:06:24 -0400 Subject: [PATCH] cursor: Add private convenience api Add function that either returns the texture, or converts the paintable to a texture at its intrinsic size, and returns that. This allows for quick fallback implementations that minimally handle the paintable cursor case. --- gdk/gdkcursor.c | 74 ++++++++++++++++++++++++++++++++++++++++++ gdk/gdkcursorprivate.h | 3 ++ 2 files changed, 77 insertions(+) diff --git a/gdk/gdkcursor.c b/gdk/gdkcursor.c index 2d4c021a4e..c3b6fe3c17 100644 --- a/gdk/gdkcursor.c +++ b/gdk/gdkcursor.c @@ -30,11 +30,14 @@ #include "gdkcursor.h" #include "gdkcursorprivate.h" #include "gdktexture.h" +#include "gdkdisplay.h" #include #include #include +#include + /** * GdkCursor: * @@ -555,3 +558,74 @@ gdk_cursor_get_hotspot_y (GdkCursor *cursor) return cursor->hotspot_y; } + +/* Hack. We don't include gsk/gsk.h here to avoid a build order problem + * with the generated header gskenumtypes.h, so we need to hack around + * a bit to access the gsk and gtk api we need. + */ + +typedef struct _GskRenderer GskRenderer; +typedef struct _GskRenderNode GskRenderNode; +typedef struct _GdkSnapshot GtkSnapshot; + +extern GskRenderer * gsk_cairo_renderer_new (void); +extern gboolean gsk_renderer_realize_for_display (GskRenderer *renderer, + GdkDisplay *display, + GError **error); +extern void gsk_renderer_unrealize (GskRenderer *renderer); +extern GdkTexture * gsk_renderer_render_texture (GskRenderer *renderer, + GskRenderNode *root, + const graphene_rect_t *viewport); + +extern void gsk_render_node_get_bounds (GskRenderNode *node, + graphene_rect_t *bounds); + +extern void gsk_render_node_unref (GskRenderNode *node); + +extern GtkSnapshot * gtk_snapshot_new (void); +extern GskRenderNode * gtk_snapshot_free_to_node (GtkSnapshot *snapshot); + +static GdkTexture * +paintable_to_texture (GdkPaintable *paintable, + double scale) +{ + GtkSnapshot *snapshot; + GskRenderNode *node; + GskRenderer *renderer; + int width, height; + GdkTexture *texture; + graphene_rect_t bounds; + + width = gdk_paintable_get_intrinsic_width (paintable); + height = gdk_paintable_get_intrinsic_height (paintable); + + snapshot = gtk_snapshot_new (); + gdk_paintable_snapshot (paintable, snapshot, width * scale, height * scale); + node = gtk_snapshot_free_to_node (snapshot); + + /* FIXME: use a proper renderer, and cache it */ + renderer = gsk_cairo_renderer_new (); + gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), NULL); + + gsk_render_node_get_bounds (node, &bounds); + texture = gsk_renderer_render_texture (renderer, node, &bounds); + + gsk_renderer_unrealize (renderer); + g_object_unref (renderer); + + gsk_render_node_unref (node); + + return texture; +} + +GdkTexture * +gdk_cursor_create_texture (GdkCursor *cursor, + double scale) +{ + if (cursor->texture) + return g_object_ref (cursor->texture); + else if (cursor->paintable) + return paintable_to_texture (cursor->paintable, scale); + else + return NULL; +} diff --git a/gdk/gdkcursorprivate.h b/gdk/gdkcursorprivate.h index 3b5cbde2d0..2caa96822d 100644 --- a/gdk/gdkcursorprivate.h +++ b/gdk/gdkcursorprivate.h @@ -56,5 +56,8 @@ guint gdk_cursor_hash (gconstpointer gboolean gdk_cursor_equal (gconstpointer a, gconstpointer b); +GdkTexture * gdk_cursor_create_texture (GdkCursor *cursor, + double scale); + G_END_DECLS