mirror of
https://github.com/glfw/glfw.git
synced 2025-10-04 13:46:37 +00:00
Fix disabled cursor mode over remote desktop
There were two major issues: - RDP uses MOUSE_MOVE_ABSOLUTE for its input events, and the implementation of this was incorrect. Although poorly documented, the values actually range from 0-65535 and represent monitor positions, instead of being positions beforehand. The equally poorly documented MOUSE_VIRTUAL_DESKTOP flag specifies whether or not to use the SCREEN or VIRTUALSCREEN system metrics. - Using `SetCursor(NULL)` causes `SetCursorPos` to behave incorrectly over RDP; it doesn't actually move it on the connected machine. This has been fixed by creating an invisible cursor, which does get moved correctly. Aside from that, the center of the window is now cached and the cursor test now supports pressing M to move the cursor to the center. Fixes #1276.
This commit is contained in:
parent
bf6551a3ca
commit
49914ab15b
@ -219,6 +219,7 @@ information on what to include when reporting a bug.
|
|||||||
- [Win32] Bugfix: The HID device notification was not unregistered (#1170)
|
- [Win32] Bugfix: The HID device notification was not unregistered (#1170)
|
||||||
- [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED`
|
- [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED`
|
||||||
hint set to false (#1179,#1180)
|
hint set to false (#1179,#1180)
|
||||||
|
- [Win32] Bugfix: Disabled cursor mode did not work over remote desktop (#1276)
|
||||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||||
@ -458,6 +459,7 @@ skills.
|
|||||||
- Santi Zupancic
|
- Santi Zupancic
|
||||||
- Jonas Ådahl
|
- Jonas Ådahl
|
||||||
- Lasse Öörni
|
- Lasse Öörni
|
||||||
|
- Pokechu22
|
||||||
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
- All the unmentioned and anonymous contributors in the GLFW community, for bug
|
||||||
reports, patches, feedback, testing and encouragement
|
reports, patches, feedback, testing and encouragement
|
||||||
|
|
||||||
|
@ -279,6 +279,10 @@ typedef struct _GLFWwindowWin32
|
|||||||
|
|
||||||
// The last received cursor position, regardless of source
|
// The last received cursor position, regardless of source
|
||||||
int lastCursorPosX, lastCursorPosY;
|
int lastCursorPosX, lastCursorPosY;
|
||||||
|
// Cached center positions
|
||||||
|
int centerX, centerY;
|
||||||
|
// An invisible cursor, needed for special cases (see WM_INPUT handler)
|
||||||
|
HCURSOR blankCursor;
|
||||||
|
|
||||||
} _GLFWwindowWin32;
|
} _GLFWwindowWin32;
|
||||||
|
|
||||||
|
@ -230,9 +230,7 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
|
|||||||
//
|
//
|
||||||
static void centerCursor(_GLFWwindow* window)
|
static void centerCursor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int width, height;
|
_glfwPlatformSetCursorPos(window, window->win32.centerX, window->win32.centerY);
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
|
||||||
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the cursor image according to its cursor mode
|
// Updates the cursor image according to its cursor mode
|
||||||
@ -247,7 +245,7 @@ static void updateCursorImage(_GLFWwindow* window)
|
|||||||
SetCursor(LoadCursorW(NULL, IDC_ARROW));
|
SetCursor(LoadCursorW(NULL, IDC_ARROW));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetCursor(NULL);
|
SetCursor(window->win32.blankCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the cursor clip rect
|
// Updates the cursor clip rect
|
||||||
@ -856,11 +854,32 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
data = _glfw.win32.rawInput;
|
data = _glfw.win32.rawInput;
|
||||||
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
|
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
|
||||||
{
|
{
|
||||||
dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
|
// As per https://github.com/Microsoft/DirectXTK/commit/ef56b63f3739381e451f7a5a5bd2c9779d2a7555
|
||||||
dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
|
// 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.
|
||||||
|
const int width = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
|
||||||
|
const int height = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
|
||||||
|
POINT pos;
|
||||||
|
pos.x = (int) ((data->data.mouse.lLastX / 65535.0f) * width);
|
||||||
|
pos.y = (int) ((data->data.mouse.lLastY / 65535.0f) * height);
|
||||||
|
ScreenToClient(window->win32.handle, &pos);
|
||||||
|
|
||||||
|
// One other unfortunate thing is that re-centering the cursor will still fire an
|
||||||
|
// input event; assume that any motion to the center is our re-centering and ignore it
|
||||||
|
if (pos.x == window->win32.centerX && pos.y == window->win32.centerY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dx = pos.x - window->win32.lastCursorPosX;
|
||||||
|
dy = pos.y - window->win32.lastCursorPosY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Unexpected raw input combination MOUSE_VIRTUAL_DESKTOP but not MOUSE_MOVE_ABSOLUTE");
|
||||||
|
break;
|
||||||
|
}
|
||||||
dx = data->data.mouse.lLastX;
|
dx = data->data.mouse.lLastX;
|
||||||
dy = data->data.mouse.lLastY;
|
dy = data->data.mouse.lLastY;
|
||||||
}
|
}
|
||||||
@ -923,6 +942,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
|
const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
|
||||||
(window->win32.maximized &&
|
(window->win32.maximized &&
|
||||||
wParam != SIZE_RESTORED);
|
wParam != SIZE_RESTORED);
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
|
||||||
if (_glfw.win32.disabledCursorWindow == window)
|
if (_glfw.win32.disabledCursorWindow == window)
|
||||||
updateClipRect(window);
|
updateClipRect(window);
|
||||||
@ -949,6 +970,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
window->win32.iconified = iconified;
|
window->win32.iconified = iconified;
|
||||||
window->win32.maximized = maximized;
|
window->win32.maximized = maximized;
|
||||||
|
|
||||||
|
window->win32.centerX = width / 2;
|
||||||
|
window->win32.centerY = height / 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1176,6 +1200,19 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
window->win32.transparent = GLFW_TRUE;
|
window->win32.transparent = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK: Create a transparent cursor as using the NULL cursor breaks
|
||||||
|
// using SetCursorPos when connected over RDP
|
||||||
|
int cursorWidth = GetSystemMetrics(SM_CXCURSOR);
|
||||||
|
int cursorHeight = GetSystemMetrics(SM_CYCURSOR);
|
||||||
|
unsigned char* andMask = calloc(cursorWidth * cursorHeight / 8, sizeof(unsigned char));
|
||||||
|
memset(andMask, 0xFF, cursorWidth * cursorHeight / 8);
|
||||||
|
unsigned char* xorMask = calloc(cursorWidth * cursorHeight / 8, sizeof(unsigned char));
|
||||||
|
// Cursor creation might fail, but that's fine as we get NULL in that case,
|
||||||
|
// which serves as an acceptable fallback blank cursor (other than on RDP)
|
||||||
|
window->win32.blankCursor = CreateCursor(NULL, 0, 0, cursorWidth, cursorHeight, andMask, xorMask);
|
||||||
|
free(andMask);
|
||||||
|
free(xorMask);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1313,6 +1350,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
if (window->win32.smallIcon)
|
if (window->win32.smallIcon)
|
||||||
DestroyIcon(window->win32.smallIcon);
|
DestroyIcon(window->win32.smallIcon);
|
||||||
|
|
||||||
|
if (window->win32.blankCursor)
|
||||||
|
DestroyCursor(window->win32.blankCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||||
@ -1750,15 +1790,12 @@ void _glfwPlatformPollEvents(void)
|
|||||||
window = _glfw.win32.disabledCursorWindow;
|
window = _glfw.win32.disabledCursorWindow;
|
||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
int width, height;
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
|
||||||
|
|
||||||
// NOTE: Re-center the cursor only if it has moved since the last call,
|
// NOTE: Re-center the cursor only if it has moved since the last call,
|
||||||
// to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
|
// to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
|
||||||
if (window->win32.lastCursorPosX != width / 2 ||
|
if (window->win32.lastCursorPosX != window->win32.centerX ||
|
||||||
window->win32.lastCursorPosY != height / 2)
|
window->win32.lastCursorPosY != window->win32.centerY)
|
||||||
{
|
{
|
||||||
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
|
centerCursor(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1806,7 +1843,11 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
|||||||
window->win32.lastCursorPosY = pos.y;
|
window->win32.lastCursorPosY = pos.y;
|
||||||
|
|
||||||
ClientToScreen(window->win32.handle, &pos);
|
ClientToScreen(window->win32.handle, &pos);
|
||||||
SetCursorPos(pos.x, pos.y);
|
if (!SetCursorPos(pos.x, pos.y))
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to set cursor position");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||||
|
@ -205,6 +205,14 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
case GLFW_KEY_6:
|
case GLFW_KEY_6:
|
||||||
glfwSetCursor(window, standard_cursors[5]);
|
glfwSetCursor(window, standard_cursors[5]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GLFW_KEY_M:
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
glfwGetWindowSize(window, &width, &height);
|
||||||
|
glfwSetCursorPos(window, width / 2, height / 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user