Blob Blame History Raw
From d46870cf38db0c53eeb204191f44d18a66691493 Mon Sep 17 00:00:00 2001
From: Simon Ser <contact@emersion.fr>
Date: Tue, 30 Nov 2021 18:33:08 +0100
Subject: [PATCH] output: don't leave dangling cursor_front_buffer

Sometimes we were calling wlr_output_impl.set_cursor with a NULL
buffer, but we weren't clearing wlr_output.cursor_front_buffer.
Avoid leaving a dangling buffer behind.

Introduce a helper function output_set_hardware_cursor which calls
wlr_output_impl.set_cursor and keeps cursor_front_buffer in sync.

(cherry picked from commit 2540de494e66c6fa056e9608755bfa7474d4ee47)
---
 types/wlr_output.c | 43 +++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/types/wlr_output.c b/types/wlr_output.c
index c6676105..24258010 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -961,6 +961,26 @@ void wlr_output_lock_attach_render(struct wlr_output *output, bool lock) {
 		output->attach_render_locks);
 }
 
+static bool output_set_hardware_cursor(struct wlr_output *output,
+		struct wlr_buffer *buffer, int hotspot_x, int hotspot_y) {
+	if (!output->impl->set_cursor) {
+		return false;
+	}
+
+	if (!output->impl->set_cursor(output, buffer, hotspot_x, hotspot_y)) {
+		return false;
+	}
+
+	wlr_buffer_unlock(output->cursor_front_buffer);
+	output->cursor_front_buffer = NULL;
+
+	if (buffer != NULL) {
+		output->cursor_front_buffer = wlr_buffer_lock(buffer);
+	}
+
+	return true;
+}
+
 static void output_cursor_damage_whole(struct wlr_output_cursor *cursor);
 
 void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
@@ -975,8 +995,7 @@ void wlr_output_lock_software_cursors(struct wlr_output *output, bool lock) {
 		output->software_cursor_locks);
 
 	if (output->software_cursor_locks > 0 && output->hardware_cursor != NULL) {
-		assert(output->impl->set_cursor);
-		output->impl->set_cursor(output, NULL, 0, 0);
+		output_set_hardware_cursor(output, NULL, 0, 0);
 		output_cursor_damage_whole(output->hardware_cursor);
 		output->hardware_cursor = NULL;
 	}
@@ -1352,14 +1371,10 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
 		wlr_output_transform_invert(output->transform),
 		buffer ? buffer->width : 0, buffer ? buffer->height : 0);
 
-	bool ok = output->impl->set_cursor(cursor->output, buffer,
-		hotspot.x, hotspot.y);
+	bool ok = output_set_hardware_cursor(cursor->output, buffer, hotspot.x, hotspot.y);
+	wlr_buffer_unlock(buffer);
 	if (ok) {
-		wlr_buffer_unlock(output->cursor_front_buffer);
-		output->cursor_front_buffer = buffer;
 		output->hardware_cursor = cursor;
-	} else {
-		wlr_buffer_unlock(buffer);
 	}
 	return ok;
 }
@@ -1473,9 +1488,8 @@ void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
 				wlr_output_transform_invert(cursor->output->transform),
 				buffer ? buffer->width : 0, buffer ? buffer->height : 0);
 
-			assert(cursor->output->impl->set_cursor);
-			cursor->output->impl->set_cursor(cursor->output,
-				buffer, hotspot.x, hotspot.y);
+			output_set_hardware_cursor(cursor->output, buffer,
+				hotspot.x, hotspot.y);
 		}
 		return;
 	}
@@ -1498,8 +1512,7 @@ void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor,
 		cursor->height = 0;
 
 		if (cursor->output->hardware_cursor == cursor) {
-			assert(cursor->output->impl->set_cursor);
-			cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0);
+			output_set_hardware_cursor(cursor->output, NULL, 0, 0);
 		}
 	}
 }
@@ -1560,9 +1573,7 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
 	wlr_signal_emit_safe(&cursor->events.destroy, cursor);
 	if (cursor->output->hardware_cursor == cursor) {
 		// If this cursor was the hardware cursor, disable it
-		if (cursor->output->impl->set_cursor) {
-			cursor->output->impl->set_cursor(cursor->output, NULL, 0, 0);
-		}
+		output_set_hardware_cursor(cursor->output, NULL, 0, 0);
 		cursor->output->hardware_cursor = NULL;
 	}
 	wlr_texture_destroy(cursor->texture);
-- 
2.33.1