From 275b92f88721ecc69b15bad2d07fa87a0e77de0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 7 Feb 2024 00:31:19 +0100 Subject: [PATCH] Win32: Clean up RDP hidden cursor workaround --- src/win32_platform.h | 2 +- src/win32_window.c | 40 +++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/win32_platform.h b/src/win32_platform.h index 366674fe..43ab3232 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -460,7 +460,7 @@ typedef struct _GLFWlibraryWin32 UINT mouseTrailSize; // Indicate if the process was started behind Remote Destop BOOL isRemoteSession; - // An invisible cursor, needed for special cases (see WM_INPUT handler) + // The cursor handle to use to hide the cursor (NULL or a transparent cursor) HCURSOR blankCursor; struct { diff --git a/src/win32_window.c b/src/win32_window.c index 1a856713..d522e788 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -232,10 +232,12 @@ static void updateCursorImage(_GLFWwindow* window) SetCursor(LoadCursorW(NULL, IDC_ARROW)); } else - //Connected via Remote Desktop, NULL cursor will present SetCursorPos the move the cursor. - //using a blank cursor fix that. - //When not via Remote Desktop, win32.blankCursor should be NULL + { + // NOTE: Via Remote Desktop, setting the cursor to NULL does not hide it. + // HACK: When running locally, it is set to NULL, but when connected via Remote + // Desktop, this is a transparent cursor. SetCursor(_glfw.win32.blankCursor); + } } // Sets the cursor clip rect to the window content area @@ -900,8 +902,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l HRAWINPUT ri = (HRAWINPUT) lParam; RAWINPUT* data = NULL; int dx, dy; - int width, height; - POINT pos; if (_glfw.win32.disabledCursorWindow != window) break; @@ -928,18 +928,29 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l data = _glfw.win32.rawInput; if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) - { + { if (_glfw.win32.isRemoteSession) { - //Remote Desktop Mode... - // As per https://github.com/Microsoft/DirectXTK/commit/ef56b63f3739381e451f7a5a5bd2c9779d2a7555 - // MOUSE_MOVE_ABSOLUTE is a range from 0 through 65535, based on the screen size. - // As far as I can tell, absolute mode only occurs over RDP though. - width = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); - height = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + // NOTE: According to DirectXTK, when running via Remote Desktop, raw + // mouse motion is provided as MOUSE_MOVE_ABSOLUTE and + // MOUSE_VIRTUAL_DESKTOP. - pos.x = (int)((data->data.mouse.lLastX / 65535.0f) * width); - pos.y = (int)((data->data.mouse.lLastY / 65535.0f) * height); + int width, height; + + if (data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) + { + width = GetSystemMetrics(SM_CXVIRTUALSCREEN); + height = GetSystemMetrics(SM_CYVIRTUALSCREEN); + } + else + { + width = GetSystemMetrics(SM_CXSCREEN); + height = GetSystemMetrics(SM_CYSCREEN); + } + + POINT pos; + pos.x = (int) ((data->data.mouse.lLastX / 65535.f) * width); + pos.y = (int) ((data->data.mouse.lLastY / 65535.f) * height); ScreenToClient(window->win32.handle, &pos); dx = pos.x - window->win32.lastCursorPosX; @@ -947,7 +958,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } else { - //Normal mode... We should have the right absolute coords in data.mouse dx = data->data.mouse.lLastX - window->win32.lastCursorPosX; dy = data->data.mouse.lLastY - window->win32.lastCursorPosY; }