wayland: Use a viewport for pointer surfaces

This should give us more flexibility for buffer size vs surface
size.

Unfortunately, mutter doesn't play along currently, so this is
only useful for kwin, weston or sway.
This commit is contained in:
Matthias Clasen 2024-03-19 12:58:41 -04:00
parent 67a6f343a0
commit 1275a2cb8d
5 changed files with 36 additions and 11 deletions

View File

@ -155,15 +155,19 @@ static const struct wl_buffer_listener buffer_listener = {
struct wl_buffer * struct wl_buffer *
_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display, _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
GdkCursor *cursor, GdkCursor *cursor,
guint desired_scale, double desired_scale,
gboolean use_viewporter,
guint image_index, guint image_index,
int *hotspot_x, int *hotspot_x,
int *hotspot_y, int *hotspot_y,
int *width, int *width,
int *height, int *height,
int *scale) double *scale)
{ {
GdkTexture *texture; GdkTexture *texture;
int desired_scale_factor;
desired_scale_factor = (int) ceil (desired_scale);
if (gdk_cursor_get_name (cursor)) if (gdk_cursor_get_name (cursor))
{ {
@ -174,7 +178,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
c = gdk_wayland_cursor_load_for_name (display, c = gdk_wayland_cursor_load_for_name (display,
_gdk_wayland_display_get_cursor_theme (display), _gdk_wayland_display_get_cursor_theme (display),
desired_scale, desired_scale_factor,
gdk_cursor_get_name (cursor)); gdk_cursor_get_name (cursor));
if (c && c->image_count > 0) if (c && c->image_count > 0)
{ {
@ -191,7 +195,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
image = c->images[image_index]; image = c->images[image_index];
cursor_scale = desired_scale; cursor_scale = desired_scale_factor;
if ((image->width % cursor_scale != 0) || if ((image->width % cursor_scale != 0) ||
(image->height % cursor_scale != 0)) (image->height % cursor_scale != 0))
{ {
@ -252,11 +256,14 @@ from_texture:
} }
else else
{ {
*scale = desired_scale; if (!use_viewporter)
*scale = desired_scale_factor;
else
*scale = desired_scale;
texture = gdk_cursor_get_texture_for_size (cursor, texture = gdk_cursor_get_texture_for_size (cursor,
display->cursor_theme_size, display->cursor_theme_size,
desired_scale, *scale,
width, width,
height, height,
hotspot_x, hotspot_x,
@ -290,6 +297,7 @@ from_texture:
return _gdk_wayland_cursor_get_buffer (display, return _gdk_wayland_cursor_get_buffer (display,
gdk_cursor_get_fallback (cursor), gdk_cursor_get_fallback (cursor),
desired_scale, desired_scale,
use_viewporter,
image_index, image_index,
hotspot_x, hotspot_y, hotspot_x, hotspot_y,
width, height, width, height,

View File

@ -62,6 +62,7 @@ struct _GdkWaylandPointerData {
uint32_t grab_time; uint32_t grab_time;
struct wl_surface *pointer_surface; struct wl_surface *pointer_surface;
struct wp_viewport *pointer_surface_viewport;
guint cursor_is_default: 1; guint cursor_is_default: 1;
GdkCursor *cursor; GdkCursor *cursor;
guint cursor_timeout_id; guint cursor_timeout_id;

View File

@ -260,7 +260,8 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
GdkWaylandPointerData *pointer = GdkWaylandPointerData *pointer =
gdk_wayland_device_get_pointer (wayland_device); gdk_wayland_device_get_pointer (wayland_device);
struct wl_buffer *buffer; struct wl_buffer *buffer;
int x, y, w, h, scale; int x, y, w, h;
double scale;
guint next_image_index, next_image_delay; guint next_image_index, next_image_delay;
gboolean retval = G_SOURCE_REMOVE; gboolean retval = G_SOURCE_REMOVE;
GdkWaylandTabletData *tablet; GdkWaylandTabletData *tablet;
@ -271,7 +272,8 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
{ {
buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display), buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display),
pointer->cursor, pointer->cursor,
(int) ceil (pointer->current_output_scale), pointer->current_output_scale,
pointer->pointer_surface_viewport != NULL,
pointer->cursor_image_index, pointer->cursor_image_index,
&x, &y, &w, &h, &scale); &x, &y, &w, &h, &scale);
} }
@ -310,7 +312,16 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
if (buffer) if (buffer)
{ {
wl_surface_attach (pointer->pointer_surface, buffer, 0, 0); wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
if (wl_surface_get_version (pointer->pointer_surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) if (pointer->pointer_surface_viewport)
{
wp_viewport_set_source (pointer->pointer_surface_viewport,
wl_fixed_from_int (0),
wl_fixed_from_int (0),
wl_fixed_from_double (w * scale),
wl_fixed_from_double (h * scale));
wp_viewport_set_destination (pointer->pointer_surface_viewport, w, h);
}
else if (wl_surface_get_version (pointer->pointer_surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
wl_surface_set_buffer_scale (pointer->pointer_surface, scale); wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
wl_surface_damage (pointer->pointer_surface, 0, 0, w, h); wl_surface_damage (pointer->pointer_surface, 0, 0, w, h);
wl_surface_commit (pointer->pointer_surface); wl_surface_commit (pointer->pointer_surface);

View File

@ -116,13 +116,14 @@ void gdk_wayland_display_system_bell (GdkDisplay *display,
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display, struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
GdkCursor *cursor, GdkCursor *cursor,
guint desired_scale, double desired_scale,
gboolean use_viewporter,
guint image_index, guint image_index,
int *hotspot_x, int *hotspot_x,
int *hotspot_y, int *hotspot_y,
int *w, int *w,
int *h, int *h,
int *scale); double *scale);
guint _gdk_wayland_cursor_get_next_image_index (GdkWaylandDisplay *display, guint _gdk_wayland_cursor_get_next_image_index (GdkWaylandDisplay *display,
GdkCursor *cursor, GdkCursor *cursor,
guint scale, guint scale,

View File

@ -3878,6 +3878,7 @@ gdk_wayland_pointer_data_finalize (GdkWaylandPointerData *pointer)
g_clear_object (&pointer->cursor); g_clear_object (&pointer->cursor);
wl_surface_destroy (pointer->pointer_surface); wl_surface_destroy (pointer->pointer_surface);
g_slist_free (pointer->pointer_surface_outputs); g_slist_free (pointer->pointer_surface_outputs);
g_clear_pointer (&pointer->pointer_surface_viewport, wp_viewport_destroy);
} }
static void static void
@ -4241,6 +4242,9 @@ init_pointer_data (GdkWaylandPointerData *pointer_data,
wl_surface_add_listener (pointer_data->pointer_surface, wl_surface_add_listener (pointer_data->pointer_surface,
&pointer_surface_listener, &pointer_surface_listener,
logical_device); logical_device);
if (display_wayland->viewporter)
pointer_data->pointer_surface_viewport = wp_viewporter_get_viewport (display_wayland->viewporter, pointer_data->pointer_surface);
} }
void void