From 88b2d6fe25f77b2140bb76d5d3c8ae037cad31e5 Mon Sep 17 00:00:00 2001
From: Scott Anderson <scott@anderso.nz>
Date: Sun, 11 Nov 2018 12:30:37 +1300
Subject: backend/x11: Check for xinput extension

---
 README.md               |  1 +
 backend/x11/backend.c   | 27 +++++++++++++++++++++++++++
 backend/x11/meson.build |  3 ++-
 include/backend/x11.h   |  2 ++
 4 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 1519d0b3..9357cc59 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ If you choose to enable X11 support:
 * xcb
 * xcb-composite
 * xcb-xfixes
+* xcb-xinput
 * xcb-image
 * xcb-render
 * x11-xcb
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index 89e2b867..d4e228b1 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -12,6 +12,7 @@
 #include <X11/Xlib-xcb.h>
 #include <wayland-server.h>
 #include <xcb/xcb.h>
+#include <xcb/xinput.h>
 #if WLR_HAS_XCB_XKB
 #include <xcb/xkb.h>
 #endif
@@ -74,6 +75,12 @@ static void handle_x11_event(struct wlr_x11_backend *x11,
 		}
 		break;
 	}
+	case XCB_GE_GENERIC: {
+		xcb_ge_generic_event_t *ev = (xcb_ge_generic_event_t *)event;
+		if (ev->extension == x11->xinput_opcode) {
+			handle_x11_xinput_event(x11, ev);
+		}
+	}
 	}
 }
 
@@ -259,6 +266,26 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
 		}
 	}
 
+	const xcb_query_extension_reply_t *ext =
+		xcb_get_extension_data(x11->xcb, &xcb_input_id);
+	if (!ext || !ext->present) {
+		wlr_log(WLR_ERROR, "X11 does not support Xinput extension");
+		goto error_display;
+	}
+	x11->xinput_opcode = ext->major_opcode;
+
+	xcb_input_xi_query_version_cookie_t xi_cookie =
+		xcb_input_xi_query_version(x11->xcb, 2, 0);
+	xcb_input_xi_query_version_reply_t *xi_reply =
+		xcb_input_xi_query_version_reply(x11->xcb, xi_cookie, NULL);
+
+	if (!xi_reply || xi_reply->major_version < 2) {
+		wlr_log(WLR_ERROR, "X11 does not support required Xinput version");
+		free(xi_reply);
+		goto error_display;
+	}
+	free(xi_reply);
+
 	int fd = xcb_get_file_descriptor(x11->xcb);
 	struct wl_event_loop *ev = wl_display_get_event_loop(display);
 	uint32_t events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
diff --git a/backend/x11/meson.build b/backend/x11/meson.build
index fa51e3d7..04111a13 100644
--- a/backend/x11/meson.build
+++ b/backend/x11/meson.build
@@ -1,7 +1,8 @@
 x11_libs = []
 x11_required = [
-	'xcb',
 	'x11-xcb',
+	'xcb',
+	'xcb-xinput',
 ]
 x11_optional = [
 	'xcb-xkb',
diff --git a/include/backend/x11.h b/include/backend/x11.h
index eccb422b..935c427e 100644
--- a/include/backend/x11.h
+++ b/include/backend/x11.h
@@ -67,6 +67,8 @@ struct wlr_x11_backend {
 	// A blank cursor
 	xcb_cursor_t cursor;
 
+	uint8_t xinput_opcode;
+
 #if WLR_HAS_XCB_XKB
 	bool xkb_supported;
 	uint8_t xkb_base_event;
-- 
cgit v1.2.3