From e674c7e454ce8defffa3fc26a33fbc06562d79ad Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Sun, 30 Jun 2024 23:18:39 +0200 Subject: [PATCH] cursor-sprite: Add API for viewports [jadahl] Rework hotspot calculations. Part-of: --- src/backends/meta-cursor.c | 101 ++++++++++++++++++++++ src/backends/meta-cursor.h | 17 ++++ src/wayland/meta-wayland-cursor-surface.c | 69 ++++++++++++++- 3 files changed, 183 insertions(+), 4 deletions(-) diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c index 0d256e6b1..73746151d 100644 --- a/src/backends/meta-cursor.c +++ b/src/backends/meta-cursor.c @@ -56,6 +56,11 @@ typedef struct _MetaCursorSpritePrivate CoglTexture2D *texture; float texture_scale; MtkMonitorTransform texture_transform; + gboolean has_viewport_src_rect; + graphene_rect_t viewport_src_rect; + gboolean has_viewport_dst_size; + int viewport_dst_width; + int viewport_dst_height; int hot_x, hot_y; ClutterColorState *color_state; @@ -151,6 +156,74 @@ meta_cursor_sprite_set_texture_transform (MetaCursorSprite *sprite, meta_cursor_sprite_invalidate (sprite); } +void +meta_cursor_sprite_set_viewport_src_rect (MetaCursorSprite *sprite, + const graphene_rect_t *src_rect) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (priv->has_viewport_src_rect && + G_APPROX_VALUE (priv->viewport_src_rect.origin.x, + src_rect->origin.x, FLT_EPSILON) && + G_APPROX_VALUE (priv->viewport_src_rect.origin.y, + src_rect->origin.y, FLT_EPSILON) && + G_APPROX_VALUE (priv->viewport_src_rect.size.width, + src_rect->size.width, FLT_EPSILON) && + G_APPROX_VALUE (priv->viewport_src_rect.size.height, + src_rect->size.height, FLT_EPSILON)) + return; + + priv->has_viewport_src_rect = TRUE; + priv->viewport_src_rect = *src_rect; + meta_cursor_sprite_invalidate (sprite); +} + +void +meta_cursor_sprite_reset_viewport_src_rect (MetaCursorSprite *sprite) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (!priv->has_viewport_src_rect) + return; + + priv->has_viewport_src_rect = FALSE; + meta_cursor_sprite_invalidate (sprite); +} + +void +meta_cursor_sprite_set_viewport_dst_size (MetaCursorSprite *sprite, + int dst_width, + int dst_height) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (priv->has_viewport_dst_size && + priv->viewport_dst_width == dst_width && + priv->viewport_dst_height == dst_height) + return; + + priv->has_viewport_dst_size = TRUE; + priv->viewport_dst_width = dst_width; + priv->viewport_dst_height = dst_height; + meta_cursor_sprite_invalidate (sprite); +} + +void +meta_cursor_sprite_reset_viewport_dst_size (MetaCursorSprite *sprite) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (!priv->has_viewport_dst_size) + return; + + priv->has_viewport_dst_size = FALSE; + meta_cursor_sprite_invalidate (sprite); +} + CoglTexture * meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite) { @@ -208,6 +281,34 @@ meta_cursor_sprite_get_texture_transform (MetaCursorSprite *sprite) return priv->texture_transform; } +const graphene_rect_t * +meta_cursor_sprite_get_viewport_src_rect (MetaCursorSprite *sprite) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (!priv->has_viewport_src_rect) + return NULL; + + return &priv->viewport_src_rect; +} + +gboolean +meta_cursor_sprite_get_viewport_dst_size (MetaCursorSprite *sprite, + int *dst_width, + int *dst_height) +{ + MetaCursorSpritePrivate *priv = + meta_cursor_sprite_get_instance_private (sprite); + + if (!priv->has_viewport_dst_size) + return FALSE; + + *dst_width = priv->viewport_dst_width; + *dst_height = priv->viewport_dst_height; + return TRUE; +} + void meta_cursor_sprite_set_prepare_func (MetaCursorSprite *sprite, MetaCursorPrepareFunc func, diff --git a/src/backends/meta-cursor.h b/src/backends/meta-cursor.h index 6b9401544..ec221620e 100644 --- a/src/backends/meta-cursor.h +++ b/src/backends/meta-cursor.h @@ -75,6 +75,17 @@ void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite, void meta_cursor_sprite_set_texture_transform (MetaCursorSprite *sprite, MtkMonitorTransform transform); +void meta_cursor_sprite_set_viewport_src_rect (MetaCursorSprite *sprite, + const graphene_rect_t *src_rect); + +void meta_cursor_sprite_reset_viewport_src_rect (MetaCursorSprite *sprite); + +void meta_cursor_sprite_set_viewport_dst_size (MetaCursorSprite *sprite, + int dst_width, + int dst_height); + +void meta_cursor_sprite_reset_viewport_dst_size (MetaCursorSprite *sprite); + CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite); void meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, @@ -89,6 +100,12 @@ float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite); MtkMonitorTransform meta_cursor_sprite_get_texture_transform (MetaCursorSprite *sprite); +const graphene_rect_t * meta_cursor_sprite_get_viewport_src_rect (MetaCursorSprite *sprite); + +gboolean meta_cursor_sprite_get_viewport_dst_size (MetaCursorSprite *sprite, + int *dst_width, + int *dst_height); + gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *sprite); void meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite); diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c index 859f466b6..18a20e905 100644 --- a/src/wayland/meta-wayland-cursor-surface.c +++ b/src/wayland/meta-wayland-cursor-surface.c @@ -68,12 +68,33 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface) if (texture && meta_multi_texture_is_simple (texture)) { - int surface_scale = surface->applied_state.scale; + float hotspot_scale_x; + float hotspot_scale_y; + + if (surface->viewport.has_dst_size) + { + int dst_width; + int dst_height; + int tex_width; + int tex_height; + + tex_width = meta_multi_texture_get_width (texture); + tex_height = meta_multi_texture_get_height (texture); + dst_width = surface->viewport.dst_width; + dst_height = surface->viewport.dst_height; + hotspot_scale_x = (float) tex_width / dst_width; + hotspot_scale_y = (float) tex_height / dst_height; + } + else + { + hotspot_scale_x = surface->applied_state.scale; + hotspot_scale_y = surface->applied_state.scale; + } meta_cursor_sprite_set_texture (cursor_sprite, meta_multi_texture_get_plane (texture, 0), - priv->hot_x * surface_scale, - priv->hot_y * surface_scale); + (int) roundf (priv->hot_x * hotspot_scale_x), + (int) roundf (priv->hot_y * hotspot_scale_y)); } else { @@ -117,7 +138,9 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, #endif /* HAVE_XWAYLAND */ surface_scale = surface->applied_state.scale; - if (meta_backend_is_stage_views_scaled (backend)) + if (surface->viewport.has_dst_size) + texture_scale = 1.0f; + else if (meta_backend_is_stage_views_scaled (backend)) texture_scale = 1.0f / surface_scale; else texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / @@ -126,6 +149,44 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); meta_cursor_sprite_set_texture_transform (cursor_sprite, surface->buffer_transform); + + if (surface->viewport.has_src_rect) + { + meta_cursor_sprite_set_viewport_src_rect (cursor_sprite, + &surface->viewport.src_rect); + } + else + { + meta_cursor_sprite_reset_viewport_src_rect (cursor_sprite); + } + + if (surface->viewport.has_dst_size) + { + int dst_width; + int dst_height; + + if (meta_backend_is_stage_views_scaled (backend)) + { + dst_width = surface->viewport.dst_width; + dst_height = surface->viewport.dst_height; + } + else + { + float monitor_scale = + meta_logical_monitor_get_scale (logical_monitor); + + dst_width = (int) (surface->viewport.dst_width * monitor_scale); + dst_height = (int) (surface->viewport.dst_height * monitor_scale); + } + + meta_cursor_sprite_set_viewport_dst_size (cursor_sprite, + dst_width, + dst_height); + } + else + { + meta_cursor_sprite_reset_viewport_dst_size (cursor_sprite); + } } meta_wayland_surface_set_main_monitor (surface, logical_monitor);