Refactor cursor mode paths

This is the refactoring part of adding GLFW_CURSOR_CAPTURED, separated
out to help keep 3.3-stable similar to the main branch.

Related to #58.

(cherry picked from commit a46f829de8)
This commit is contained in:
Camilla Löwy 2019-07-08 14:45:31 +02:00
parent 632d35e0d4
commit 5f3e5542cf
4 changed files with 120 additions and 43 deletions

View File

@ -347,6 +347,8 @@ typedef struct _GLFWlibraryWin32
double restoreCursorPosX, restoreCursorPosY; double restoreCursorPosX, restoreCursorPosY;
// The window whose disabled cursor mode is active // The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// The window the cursor is captured in
_GLFWwindow* capturedCursorWindow;
RAWINPUT* rawInput; RAWINPUT* rawInput;
int rawInputSize; int rawInputSize;
UINT mouseTrailSize; UINT mouseTrailSize;

View File

@ -251,20 +251,24 @@ static void updateCursorImage(_GLFWwindow* window)
SetCursor(NULL); SetCursor(NULL);
} }
// Updates the cursor clip rect // Sets the cursor clip rect to the window content area
// //
static void updateClipRect(_GLFWwindow* window) static void captureCursor(_GLFWwindow* window)
{
if (window)
{ {
RECT clipRect; RECT clipRect;
GetClientRect(window->win32.handle, &clipRect); GetClientRect(window->win32.handle, &clipRect);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left); ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right); ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
ClipCursor(&clipRect); ClipCursor(&clipRect);
_glfw.win32.capturedCursorWindow = window;
} }
else
// Disabled clip cursor
//
static void releaseCursor(void)
{
ClipCursor(NULL); ClipCursor(NULL);
_glfw.win32.capturedCursorWindow = NULL;
} }
// Enables WM_INPUT messages for the mouse for the specified window // Enables WM_INPUT messages for the mouse for the specified window
@ -303,7 +307,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.win32.restoreCursorPosY); &_glfw.win32.restoreCursorPosY);
updateCursorImage(window); updateCursorImage(window);
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
updateClipRect(window); captureCursor(window);
if (window->rawMouseMotion) if (window->rawMouseMotion)
enableRawMouseMotion(window); enableRawMouseMotion(window);
@ -317,7 +321,7 @@ static void enableCursor(_GLFWwindow* window)
disableRawMouseMotion(window); disableRawMouseMotion(window);
_glfw.win32.disabledCursorWindow = NULL; _glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL); releaseCursor();
_glfwPlatformSetCursorPos(window, _glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX, _glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY); _glfw.win32.restoreCursorPosY);
@ -1033,8 +1037,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
(window->win32.maximized && (window->win32.maximized &&
wParam != SIZE_RESTORED); wParam != SIZE_RESTORED);
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.capturedCursorWindow == window)
updateClipRect(window); captureCursor(window);
if (window->win32.iconified != iconified) if (window->win32.iconified != iconified)
_glfwInputWindowIconify(window, iconified); _glfwInputWindowIconify(window, iconified);
@ -1069,8 +1073,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOVE: case WM_MOVE:
{ {
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.capturedCursorWindow == window)
updateClipRect(window); captureCursor(window);
// NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
// those macros do not handle negative window positions correctly // those macros do not handle negative window positions correctly
@ -1540,7 +1544,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(window); window->context.destroy(window);
if (_glfw.win32.disabledCursorWindow == window) if (_glfw.win32.disabledCursorWindow == window)
_glfw.win32.disabledCursorWindow = NULL; enableCursor(window);
if (_glfw.win32.capturedCursorWindow == window)
releaseCursor();
if (window->win32.handle) if (window->win32.handle)
{ {
@ -2155,15 +2162,41 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
} }
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (_glfwPlatformWindowFocused(window))
{ {
if (mode == GLFW_CURSOR_DISABLED) if (mode == GLFW_CURSOR_DISABLED)
{ {
if (_glfwPlatformWindowFocused(window)) _glfwPlatformGetCursorPos(window,
disableCursor(window); &_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
_glfwCenterCursorInContentArea(window);
if (window->rawMouseMotion)
enableRawMouseMotion(window);
} }
else if (_glfw.win32.disabledCursorWindow == window) else if (_glfw.win32.disabledCursorWindow == window)
enableCursor(window); {
else if (cursorInContentArea(window)) if (window->rawMouseMotion)
disableRawMouseMotion(window);
}
if (mode == GLFW_CURSOR_DISABLED)
captureCursor(window);
else
releaseCursor();
if (mode == GLFW_CURSOR_DISABLED)
_glfw.win32.disabledCursorWindow = window;
else if (_glfw.win32.disabledCursorWindow == window)
{
_glfw.win32.disabledCursorWindow = NULL;
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
}
}
if (cursorInContentArea(window))
updateCursorImage(window); updateCursorImage(window);
} }

View File

@ -2527,7 +2527,8 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
if (!window->wl.lockedPointer) if (!window->wl.lockedPointer)
lockPointer(window); lockPointer(window);
} }
else else if (window->cursorMode == GLFW_CURSOR_NORMAL ||
window->cursorMode == GLFW_CURSOR_HIDDEN)
{ {
if (window->wl.lockedPointer) if (window->wl.lockedPointer)
unlockPointer(window); unlockPointer(window);
@ -2568,9 +2569,12 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
setCursorImage(window, &cursorWayland); setCursorImage(window, &cursorWayland);
} }
} }
else else if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
window->cursorMode == GLFW_CURSOR_DISABLED)
{
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0); wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);
} }
}
static void dataSourceHandleTarget(void* userData, static void dataSourceHandleTarget(void* userData,
struct wl_data_source* source, struct wl_data_source* source,

View File

@ -523,6 +523,25 @@ static void updateCursorImage(_GLFWwindow* window)
} }
} }
// Grabs the cursor and confines it to the window
//
static void captureCursor(_GLFWwindow* window)
{
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
None,
CurrentTime);
}
// Ungrabs the cursor
//
static void releaseCursor(void)
{
XUngrabPointer(_glfw.x11.display, CurrentTime);
}
// Enable XI2 raw mouse motion events // Enable XI2 raw mouse motion events
// //
static void enableRawMouseMotion(_GLFWwindow* window) static void enableRawMouseMotion(_GLFWwindow* window)
@ -565,12 +584,7 @@ static void disableCursor(_GLFWwindow* window)
&_glfw.x11.restoreCursorPosY); &_glfw.x11.restoreCursorPosY);
updateCursorImage(window); updateCursorImage(window);
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True, captureCursor(window);
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
} }
// Exit disabled cursor mode for the specified window // Exit disabled cursor mode for the specified window
@ -581,7 +595,7 @@ static void enableCursor(_GLFWwindow* window)
disableRawMouseMotion(window); disableRawMouseMotion(window);
_glfw.x11.disabledCursorWindow = NULL; _glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime); releaseCursor();
_glfwPlatformSetCursorPos(window, _glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX, _glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY); _glfw.x11.restoreCursorPosY);
@ -2044,7 +2058,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
void _glfwPlatformDestroyWindow(_GLFWwindow* window) void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{ {
if (_glfw.x11.disabledCursorWindow == window) if (_glfw.x11.disabledCursorWindow == window)
_glfw.x11.disabledCursorWindow = NULL; enableCursor(window);
if (window->monitor) if (window->monitor)
releaseMonitor(window); releaseMonitor(window);
@ -2850,17 +2864,41 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
} }
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (_glfwPlatformWindowFocused(window))
{ {
if (mode == GLFW_CURSOR_DISABLED) if (mode == GLFW_CURSOR_DISABLED)
{ {
if (_glfwPlatformWindowFocused(window)) _glfwPlatformGetCursorPos(window,
disableCursor(window); &_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
_glfwCenterCursorInContentArea(window);
if (window->rawMouseMotion)
enableRawMouseMotion(window);
} }
else if (_glfw.x11.disabledCursorWindow == window) else if (_glfw.x11.disabledCursorWindow == window)
enableCursor(window); {
else if (window->rawMouseMotion)
updateCursorImage(window); disableRawMouseMotion(window);
}
if (mode == GLFW_CURSOR_DISABLED)
captureCursor(window);
else
releaseCursor();
if (mode == GLFW_CURSOR_DISABLED)
_glfw.x11.disabledCursorWindow = window;
else if (_glfw.x11.disabledCursorWindow == window)
{
_glfw.x11.disabledCursorWindow = NULL;
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
}
}
updateCursorImage(window);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }