cursor-sprite: Add API for viewports

[jadahl] Rework hotspot calculations.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3859>
This commit is contained in:
Robert Mader 2024-06-30 23:18:39 +02:00 committed by Sebastian Wick
parent e402eaa950
commit e674c7e454
3 changed files with 183 additions and 4 deletions

View File

@ -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,

View File

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

View File

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