Ver Fonte

Win32: Move to WM_INPUT for disabled cursor motion

Related to #125.
Camilla Löwy há 8 anos atrás
pai
commit
918b4e81d2
5 ficheiros alterados com 79 adições e 12 exclusões
  1. 1 0
      README.md
  2. 6 0
      docs/news.dox
  3. 1 0
      src/win32_init.c
  4. 2 0
      src/win32_platform.h
  5. 69 12
      src/win32_window.c

+ 1 - 0
README.md

@@ -144,6 +144,7 @@ information on what to include when reporting a bug.
 - Bugfix: Invalid library paths were used in test and example CMake files (#930)
 - Bugfix: The scancode for synthetic key release events was always zero
 - [Win32] Added system error strings to relevant GLFW error descriptions (#733)
+- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
 - [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
 - [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
 - [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)

+ 6 - 0
docs/news.dox

@@ -32,6 +32,12 @@ full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
 window hint.
 
 
+@subsection news_33_rawmotion Support for raw mouse motion
+
+GLFW now supports raw mouse motion in disabled cursor mode on platforms where
+this is available.
+
+
 @subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
 
 GLFW now supports the `VK_MVK_macos_surface` window surface creation extension

+ 1 - 0
src/win32_init.c

@@ -483,6 +483,7 @@ void _glfwPlatformTerminate(void)
                           SPIF_SENDCHANGE);
 
     free(_glfw.win32.clipboardString);
+    free(_glfw.win32.rawInput);
 
     _glfwTerminateWGL();
     _glfwTerminateEGL();

+ 2 - 0
src/win32_platform.h

@@ -257,6 +257,8 @@ typedef struct _GLFWlibraryWin32
     double              restoreCursorPosX, restoreCursorPosY;
     // The window whose disabled cursor mode is active
     _GLFWwindow*        disabledCursorWindow;
+    RAWINPUT*           rawInput;
+    int                 rawInputSize;
 
     struct {
         HINSTANCE                       instance;

+ 69 - 12
src/win32_window.c

@@ -666,20 +666,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
             const int x = GET_X_LPARAM(lParam);
             const int y = GET_Y_LPARAM(lParam);
 
+            // Disabled cursor motion input is provided by WM_INPUT
             if (window->cursorMode == GLFW_CURSOR_DISABLED)
-            {
-                const int dx = x - window->win32.lastCursorPosX;
-                const int dy = y - window->win32.lastCursorPosY;
-
-                if (_glfw.win32.disabledCursorWindow != window)
-                    break;
+                break;
 
-                _glfwInputCursorPos(window,
-                                    window->virtualCursorPosX + dx,
-                                    window->virtualCursorPosY + dy);
-            }
-            else
-                _glfwInputCursorPos(window, x, y);
+            _glfwInputCursorPos(window, x, y);
 
             window->win32.lastCursorPosX = x;
             window->win32.lastCursorPosY = y;
@@ -700,6 +691,56 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
             return 0;
         }
 
+        case WM_INPUT:
+        {
+            UINT size;
+            HRAWINPUT ri = (HRAWINPUT) lParam;
+            RAWINPUT* data;
+            int dx, dy;
+
+            // Only process input when disabled cursor mode is applied
+            if (_glfw.win32.disabledCursorWindow != window)
+                break;
+
+            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
+            if (size > _glfw.win32.rawInputSize)
+            {
+                free(_glfw.win32.rawInput);
+                _glfw.win32.rawInput = calloc(size, 1);
+                _glfw.win32.rawInputSize = size;
+            }
+
+            size = _glfw.win32.rawInputSize;
+            if (GetRawInputData(ri, RID_INPUT,
+                                _glfw.win32.rawInput, &size,
+                                sizeof(RAWINPUTHEADER)) == (UINT) -1)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Win32: Failed to retrieve raw input data");
+                break;
+            }
+
+            data = _glfw.win32.rawInput;
+            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+            {
+                dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
+                dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
+            }
+            else
+            {
+                dx = data->data.mouse.lLastX;
+                dy = data->data.mouse.lLastY;
+            }
+
+            _glfwInputCursorPos(window,
+                                window->virtualCursorPosX + dx,
+                                window->virtualCursorPosY + dy);
+
+            window->win32.lastCursorPosX += dx;
+            window->win32.lastCursorPosY += dy;
+            break;
+        }
+
         case WM_MOUSELEAVE:
         {
             window->win32.cursorTracked = GLFW_FALSE;
@@ -1527,20 +1568,36 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
 {
     if (mode == GLFW_CURSOR_DISABLED)
     {
+        const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
+
         _glfw.win32.disabledCursorWindow = window;
         _glfwPlatformGetCursorPos(window,
                                   &_glfw.win32.restoreCursorPosX,
                                   &_glfw.win32.restoreCursorPosY);
         centerCursor(window);
         updateClipRect(window);
+
+        if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "Win32: Failed to register raw input device");
+        }
     }
     else if (_glfw.win32.disabledCursorWindow == window)
     {
+        const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
+
         _glfw.win32.disabledCursorWindow = NULL;
         updateClipRect(NULL);
         _glfwPlatformSetCursorPos(window,
                                   _glfw.win32.restoreCursorPosX,
                                   _glfw.win32.restoreCursorPosY);
+
+        if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "Win32: Failed to remove raw input device");
+        }
     }
 
     if (cursorInClientArea(window))