From f41d85a2099ac11a04dd79d8a96716c2d6447823 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 4 Apr 2013 16:48:58 +0200 Subject: [PATCH] Added initial XInput2 cursor motion. --- CMakeLists.txt | 5 ++++ src/x11_init.c | 17 +++++++++++++ src/x11_platform.h | 14 ++++++++++- src/x11_window.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56e31736..1c292ed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,6 +166,11 @@ if (_GLFW_X11) message(FATAL_ERROR "The RandR library and headers were not found") endif() + if (X11_Xinput_FOUND) + list(APPEND glfw_INCLUDE_DIRS ${X11_Xinput_INCLUDE_PATH}) + list(APPEND glfw_LIBRARIES ${X11_Xinput_LIB}) + endif() + list(APPEND glfw_INCLUDE_DIRS ${X11_Xrandr_INCLUDE_PATH}) list(APPEND glfw_LIBRARIES ${X11_Xrandr_LIB}) set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} xrandr") diff --git a/src/x11_init.c b/src/x11_init.c index 9f131851..c3824487 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -474,6 +474,23 @@ static GLboolean initDisplay(void) } } + if (XQueryExtension(_glfw.x11.display, + "XInputExtension", + &_glfw.x11.xi2.majorOpcode, + &_glfw.x11.xi2.eventBase, + &_glfw.x11.xi2.errorBase)) + { + _glfw.x11.xi2.versionMajor = 2; + _glfw.x11.xi2.versionMinor = 0; + + if (XIQueryVersion(_glfw.x11.display, + &_glfw.x11.xi2.versionMajor, + &_glfw.x11.xi2.versionMinor) != BadRequest) + { + _glfw.x11.xi2.available = GL_TRUE; + } + } + // Check if Xkb is supported on this display _glfw.x11.xkb.versionMajor = 1; _glfw.x11.xkb.versionMinor = 0; diff --git a/src/x11_platform.h b/src/x11_platform.h index e7c78011..81bdcc8f 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -44,6 +44,9 @@ // The XRandR extension provides mode setting and gamma control #include +// The XInput2 extension provides improved input events +#include + // The Xkb extension provides improved keyboard support #include @@ -94,7 +97,7 @@ typedef struct _GLFWwindowX11 GLboolean cursorGrabbed; // True if cursor is currently grabbed GLboolean cursorHidden; // True if cursor is currently hidden GLboolean cursorCentered; // True if cursor was moved since last poll - int cursorPosX, cursorPosY; + double cursorPosX, cursorPosY; } _GLFWwindowX11; @@ -153,6 +156,15 @@ typedef struct _GLFWlibraryX11 int versionMinor; } xkb; + struct { + GLboolean available; + int majorOpcode; + int eventBase; + int errorBase; + int versionMajor; + int versionMinor; + } xi2; + // LUT for mapping X11 key codes to GLFW key codes int keyCodeLUT[256]; diff --git a/src/x11_window.c b/src/x11_window.c index 74fa3093..00e9d42b 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -213,6 +213,21 @@ static GLboolean createWindow(_GLFWwindow* window, XFree(hints); } + if (_glfw.x11.xi2.available) + { + // Select for XInput2 events + + XIEventMask eventmask; + unsigned char mask[] = { 0 }; + + eventmask.deviceid = 2; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + XISetMask(mask, XI_Motion); + + XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1); + } + _glfwPlatformSetWindowTitle(window, wndconfig->title); XRRSelectInput(_glfw.x11.display, window->x11.handle, @@ -699,6 +714,53 @@ static void processEvent(XEvent *event) case DestroyNotify: return; + case GenericEvent: + { + if (event->xcookie.extension == _glfw.x11.xi2.majorOpcode && + XGetEventData(_glfw.x11.display, &event->xcookie)) + { + if (event->xcookie.evtype == XI_Motion) + { + XIDeviceEvent* data = (XIDeviceEvent*) event->xcookie.data; + + window = _glfwFindWindowByHandle(data->event); + if (window) + { + if (data->event_x != window->x11.cursorPosX || + data->event_y != window->x11.cursorPosY) + { + // The cursor was moved by something other than GLFW + + double x, y; + + if (window->cursorMode == GLFW_CURSOR_CAPTURED) + { + if (_glfw.focusedWindow != window) + break; + + x = data->event_x - window->x11.cursorPosX; + y = data->event_y - window->x11.cursorPosY; + } + else + { + x = data->event_x; + y = data->event_y; + } + + window->x11.cursorPosX = data->event_x; + window->x11.cursorPosY = data->event_y; + window->x11.cursorCentered = GL_FALSE; + + _glfwInputCursorMotion(window, x, y); + } + } + } + } + + XFreeEventData(_glfw.x11.display, &event->xcookie); + break; + } + default: { switch (event->type - _glfw.x11.randr.eventBase)