From 966e65393560fea6db84fb42019fa27127975cdc Mon Sep 17 00:00:00 2001
From: Ilia Mirkin <imirkin@alum.mit.edu>
Date: Sun, 17 Jan 2021 18:05:38 -0500
Subject: backend/x11: set a blank cursor rather than hiding globally

This actually simplifies the logic since we no longer have to wait for
enter/leave events, and also improves the UX when e.g. handling a crash
with gdb attached.

See #2659
---
 backend/x11/backend.c      | 17 +++++++++++++++++
 backend/x11/input_device.c | 30 ------------------------------
 backend/x11/output.c       |  6 +++---
 3 files changed, 20 insertions(+), 33 deletions(-)

(limited to 'backend')

diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index 5d8179f3..127f003c 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -613,6 +613,23 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
 	x11->display_destroy.notify = handle_display_destroy;
 	wl_display_add_destroy_listener(display, &x11->display_destroy);
 
+	// Create an empty pixmap to be used as the cursor. The
+	// default GC foreground is 0, and that is what it will be
+	// filled with.
+	xcb_pixmap_t blank = xcb_generate_id(x11->xcb);
+	xcb_create_pixmap(x11->xcb, 1, blank, x11->screen->root, 1, 1);
+	xcb_gcontext_t gc = xcb_generate_id(x11->xcb);
+	xcb_create_gc(x11->xcb, gc, blank, 0, NULL);
+	xcb_rectangle_t rect = { .x = 0, .y = 0, .width = 1, .height = 1 };
+	xcb_poly_fill_rectangle(x11->xcb, blank, gc, 1, &rect);
+
+	x11->cursor = xcb_generate_id(x11->xcb);
+	xcb_create_cursor(x11->xcb, x11->cursor, blank, blank,
+		0, 0, 0, 0, 0, 0, 0, 0);
+
+	xcb_free_gc(x11->xcb, gc);
+	xcb_free_pixmap(x11->xcb, blank);
+
 	return &x11->backend;
 
 error_event:
diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c
index 1bcd3060..a085b046 100644
--- a/backend/x11/input_device.c
+++ b/backend/x11/input_device.c
@@ -212,36 +212,6 @@ void handle_x11_xinput_event(struct wlr_x11_backend *x11,
 		x11->time = ev->time;
 		break;
 	}
-	case XCB_INPUT_ENTER: {
-		xcb_input_enter_event_t *ev = (xcb_input_enter_event_t *)event;
-
-		output = get_x11_output_from_window_id(x11, ev->event);
-		if (!output) {
-			return;
-		}
-
-		if (!output->cursor_hidden) {
-			xcb_xfixes_hide_cursor(x11->xcb, output->win);
-			xcb_flush(x11->xcb);
-			output->cursor_hidden = true;
-		}
-		break;
-	}
-	case XCB_INPUT_LEAVE: {
-		xcb_input_leave_event_t *ev = (xcb_input_leave_event_t *)event;
-
-		output = get_x11_output_from_window_id(x11, ev->event);
-		if (!output) {
-			return;
-		}
-
-		if (output->cursor_hidden) {
-			xcb_xfixes_show_cursor(x11->xcb, output->win);
-			xcb_flush(x11->xcb);
-			output->cursor_hidden = false;
-		}
-		break;
-	}
 	case XCB_INPUT_TOUCH_BEGIN: {
 		xcb_input_touch_begin_event_t *ev = (xcb_input_touch_begin_event_t *)event;
 
diff --git a/backend/x11/output.c b/backend/x11/output.c
index fabe9e98..fe178b72 100644
--- a/backend/x11/output.c
+++ b/backend/x11/output.c
@@ -381,11 +381,13 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
 
 	// The X11 protocol requires us to set a colormap and border pixel if the
 	// depth doesn't match the root window's
-	uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
+	uint32_t mask = XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK |
+		XCB_CW_COLORMAP | XCB_CW_CURSOR;
 	uint32_t values[] = {
 		0,
 		XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
 		x11->colormap,
+		x11->cursor,
 	};
 	output->win = xcb_generate_id(x11->xcb);
 	xcb_create_window(x11->xcb, x11->depth->depth, output->win,
@@ -402,8 +404,6 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
 			XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS |
 			XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE |
 			XCB_INPUT_XI_EVENT_MASK_MOTION |
-			XCB_INPUT_XI_EVENT_MASK_ENTER |
-			XCB_INPUT_XI_EVENT_MASK_LEAVE |
 			XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN |
 			XCB_INPUT_XI_EVENT_MASK_TOUCH_END |
 			XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE,
-- 
cgit v1.2.3