From 48c41795fe5f02f7f4051b0e0849e36a2fb8edee Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Fri, 23 Sep 2022 17:24:12 +0800
Subject: [PATCH 77/79] HACK: Honour cursor-size config

By scaling the cursor surface.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 compositor/main.c             |  4 ++++
 include/libweston/libweston.h |  4 ++++
 libweston/backend-drm/drm.c   |  3 +++
 libweston/compositor.c        | 36 +++++++++++++++++++++-------
 libweston/input.c             | 44 +++++++++++++++++++++++++++++++----
 5 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/compositor/main.c b/compositor/main.c
index 558537e..039307b 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -3542,6 +3542,10 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
 	wet.compositor->exit = handle_exit;
 	wet.compositor->warm_up = warm_up;
 
+	section = weston_config_get_section(config, "shell", NULL, NULL);
+	weston_config_section_get_int(section, "cursor-size",
+				      &wet.compositor->cursor_size, 0);
+
 	weston_compositor_log_capabilities(wet.compositor);
 
 	server_socket = getenv("WAYLAND_SERVER_SOCKET");
diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h
index 26804e2..2d15924 100644
--- a/include/libweston/libweston.h
+++ b/include/libweston/libweston.h
@@ -578,6 +578,8 @@ struct weston_pointer {
 	struct wl_listener output_destroy_listener;
 
 	struct wl_list timestamps_list;
+
+	float scale;
 };
 
 /** libinput style calibration matrix
@@ -1210,6 +1212,8 @@ struct weston_compositor {
 
 	bool warm_up;
 	uint32_t pending_fade_out;
+
+	int cursor_size;
 };
 
 struct weston_buffer {
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
index ed28956..d632a27 100644
--- a/libweston/backend-drm/drm.c
+++ b/libweston/backend-drm/drm.c
@@ -4226,6 +4226,9 @@ drm_backend_create(struct weston_compositor *compositor,
 		goto err_udev_dev;
 	}
 
+	if (compositor->cursor_size)
+		b->cursor_width = b->cursor_height = compositor->cursor_size;
+
 	wl_list_init(&b->plane_list);
 	create_sprites(b);
 
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 79a72bd..6e917f3 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -757,8 +757,14 @@ weston_transformed_coord(int width, int height,
 		break;
 	}
 
-	*bx *= scale;
-	*by *= scale;
+	/* HACK: Use -scale as 1/scale */
+	if (scale < 0) {
+		*bx /= -scale;
+		*by /= -scale;
+	} else {
+		*bx *= scale;
+		*by *= scale;
+	}
 }
 
 /** Transform a rectangle to buffer coordinates
@@ -2143,22 +2149,31 @@ convert_size_by_transform_scale(int32_t *width_out, int32_t *height_out,
 				uint32_t transform,
 				int32_t scale)
 {
-	assert(scale > 0);
+	assert(scale);
+
+	/* HACK: Use -scale as 1/scale */
+	if (scale < 0) {
+		width *= -scale;
+		height *= -scale;
+	} else {
+		width /= scale;
+		height /= scale;
+	}
 
 	switch (transform) {
 	case WL_OUTPUT_TRANSFORM_NORMAL:
 	case WL_OUTPUT_TRANSFORM_180:
 	case WL_OUTPUT_TRANSFORM_FLIPPED:
 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-		*width_out = width / scale;
-		*height_out = height / scale;
+		*width_out = width;
+		*height_out = height;
 		break;
 	case WL_OUTPUT_TRANSFORM_90:
 	case WL_OUTPUT_TRANSFORM_270:
 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-		*width_out = height / scale;
-		*height_out = width / scale;
+		*width_out = height;
+		*height_out = width;
 		break;
 	default:
 		assert(0 && "invalid transform");
@@ -3734,6 +3749,7 @@ weston_surface_build_buffer_matrix(const struct weston_surface *surface,
 {
 	const struct weston_buffer_viewport *vp = &surface->buffer_viewport;
 	double src_width, src_height, dest_width, dest_height;
+	float scale = vp->buffer.scale;
 
 	weston_matrix_init(matrix);
 
@@ -3801,7 +3817,11 @@ weston_surface_build_buffer_matrix(const struct weston_surface *surface,
 		break;
 	}
 
-	weston_matrix_scale(matrix, vp->buffer.scale, vp->buffer.scale, 1);
+	/* HACK: Use -scale as 1/scale */
+	if (scale < 0)
+		scale = 1.0 / -scale;
+
+	weston_matrix_scale(matrix, scale, scale, 1);
 }
 
 /**
diff --git a/libweston/input.c b/libweston/input.c
index 6438b52..9c140aa 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -1723,8 +1723,8 @@ weston_pointer_move_to(struct weston_pointer *pointer,
 
 	if (pointer->sprite) {
 		weston_view_set_position(pointer->sprite,
-					 ix - pointer->hotspot_x,
-					 iy - pointer->hotspot_y);
+					 ix - pointer->hotspot_x * pointer->scale,
+					 iy - pointer->hotspot_y * pointer->scale);
 		weston_view_schedule_repaint(pointer->sprite);
 	}
 
@@ -2677,6 +2677,36 @@ pointer_cursor_surface_get_label(struct weston_surface *surface,
 	return snprintf(buf, len, "cursor");
 }
 
+static void
+pointer_cursor_scale(struct weston_pointer *pointer,
+		     struct weston_surface *surface)
+{
+	struct weston_compositor *compositor = surface->compositor;
+	float scale;
+
+	if (!compositor->cursor_size || !surface->width ||
+	    surface->width == compositor->cursor_size)
+		return;
+
+	if (surface->buffer_viewport.buffer.scale != 1)
+		return;
+
+	if (compositor->cursor_size > surface->width) {
+		scale = compositor->cursor_size / surface->width;
+
+		/* HACK: Use -scale as 1/scale */
+		surface->buffer_viewport.buffer.scale = -scale;
+	} else {
+		scale = 1.0 / (surface->width / compositor->cursor_size);
+		surface->buffer_viewport.buffer.scale = 1 / scale;
+	}
+
+	surface->width *= scale;
+	surface->height *= scale;
+
+	pointer->scale = scale;
+}
+
 static void
 pointer_cursor_surface_committed(struct weston_surface *es,
 				 int32_t dx, int32_t dy)
@@ -2689,11 +2719,13 @@ pointer_cursor_surface_committed(struct weston_surface *es,
 
 	assert(es == pointer->sprite->surface);
 
+	pointer_cursor_scale(pointer, es);
+
 	pointer->hotspot_x -= dx;
 	pointer->hotspot_y -= dy;
 
-	x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x;
-	y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y;
+	x = wl_fixed_to_int(pointer->x) - pointer->hotspot_x * pointer->scale;
+	y = wl_fixed_to_int(pointer->y) - pointer->hotspot_y * pointer->scale;
 
 	weston_view_set_position(pointer->sprite, x, y);
 
@@ -2764,6 +2796,8 @@ pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
 		pointer->sprite = weston_view_create(surface);
 	}
 
+	pointer_cursor_scale(pointer, surface);
+
 	pointer->hotspot_x = x;
 	pointer->hotspot_y = y;
 
@@ -3374,6 +3408,8 @@ weston_seat_init_pointer(struct weston_seat *seat)
 
 	seat_send_updated_caps(seat);
 
+	pointer->scale = 1.0;
+
 	return 0;
 }
 
-- 
2.20.1

