diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index d6fbffe3..1703ae48 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -101,6 +101,8 @@ typedef struct _GLFWlibraryNS char* clipboardString; // Where to place the cursor when re-enabled double restoreCursorPosX, restoreCursorPosY; + // The window whose disabled cursor mode is active + _GLFWwindow* disabledCursorWindow; struct { CFBundleRef bundle; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 67174c48..31d6474f 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -85,11 +85,19 @@ static void centerCursor(_GLFWwindow *window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } -// Updates the cursor image according to the specified cursor mode +// Returns whether the cursor is in the client area of the specified window // -static void updateCursorImage(_GLFWwindow* window, int mode) +static GLFWbool cursorInClientArea(_GLFWwindow* window) { - if (mode == GLFW_CURSOR_NORMAL) + const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; + return [window->ns.view mouse:pos inRect:[window->ns.view frame]]; +} + +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) { if (window->cursor) [(NSCursor*) window->cursor->ns.object set]; @@ -227,11 +235,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } const NSRect contentRect = [window->ns.view frame]; const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; @@ -245,11 +250,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } int x, y; _glfwPlatformGetWindowPos(window, &x, &y); @@ -274,11 +276,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidBecomeKey:(NSNotification *)notification { - if (_glfw.cursorWindow == window && - window->cursorMode == GLFW_CURSOR_DISABLED) - { + if (_glfw.ns.disabledCursorWindow == window) centerCursor(window); - } _glfwInputWindowFocus(window, GLFW_TRUE); _glfwPlatformSetCursorMode(window, window->cursorMode); @@ -409,7 +408,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)cursorUpdate:(NSEvent *)event { - updateCursorImage(window, window->cursorMode); + updateCursorImage(window); } - (void)mouseDown:(NSEvent *)event @@ -1060,6 +1059,9 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, void _glfwPlatformDestroyWindow(_GLFWwindow* window) { + if (_glfw.ns.disabledCursorWindow == window) + _glfw.ns.disabledCursorWindow = NULL; + [window->ns.object orderOut:nil]; if (window->monitor) @@ -1417,7 +1419,7 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) { - updateCursorImage(window, window->cursorMode); + updateCursorImage(window); const NSRect contentRect = [window->ns.view frame]; const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; @@ -1445,21 +1447,24 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { if (mode == GLFW_CURSOR_DISABLED) { + _glfw.ns.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, &_glfw.ns.restoreCursorPosX, &_glfw.ns.restoreCursorPosY); centerCursor(window); CGAssociateMouseAndMouseCursorPosition(false); } - else if (window->cursorMode == GLFW_CURSOR_DISABLED) + else if (_glfw.ns.disabledCursorWindow == window) { + _glfw.ns.disabledCursorWindow = NULL; CGAssociateMouseAndMouseCursorPosition(true); _glfwPlatformSetCursorPos(window, _glfw.ns.restoreCursorPosX, _glfw.ns.restoreCursorPosY); } - updateCursorImage(window, mode); + if (cursorInClientArea(window)) + updateCursorImage(window); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -1572,16 +1577,8 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { - const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; - - if (window->cursorMode == GLFW_CURSOR_NORMAL && - [window->ns.view mouse:pos inRect:[window->ns.view frame]]) - { - if (cursor) - [(NSCursor*) cursor->ns.object set]; - else - [[NSCursor arrowCursor] set]; - } + if (cursorInClientArea(window)) + updateCursorImage(window); } void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) diff --git a/src/input.c b/src/input.c index b38be87c..5e70c75d 100644 --- a/src/input.c +++ b/src/input.c @@ -192,14 +192,15 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) if (window->cursorMode == value) return; + window->cursorMode = value; + _glfwPlatformGetCursorPos(window, &window->virtualCursorPosX, &window->virtualCursorPosY); - if (_glfw.cursorWindow == window) + if (_glfwPlatformWindowFocused(window)) _glfwPlatformSetCursorMode(window, value); - window->cursorMode = value; return; } @@ -340,7 +341,7 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) return; } - if (_glfw.cursorWindow != window) + if (!_glfwPlatformWindowFocused(window)) return; if (window->cursorMode == GLFW_CURSOR_DISABLED) diff --git a/src/internal.h b/src/internal.h index de813e0e..290d9017 100644 --- a/src/internal.h +++ b/src/internal.h @@ -440,7 +440,6 @@ struct _GLFWlibrary _GLFWcursor* cursorListHead; _GLFWwindow* windowListHead; - _GLFWwindow* cursorWindow; _GLFWmonitor** monitors; int monitorCount; diff --git a/src/win32_platform.h b/src/win32_platform.h index ed7a5a7c..d1b712ed 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -254,6 +254,8 @@ typedef struct _GLFWlibraryWin32 short int nativeKeys[GLFW_KEY_LAST + 1]; // Where to place the cursor when re-enabled double restoreCursorPosX, restoreCursorPosY; + // The window whose disabled cursor mode is active + _GLFWwindow* disabledCursorWindow; struct { HINSTANCE instance; diff --git a/src/win32_window.c b/src/win32_window.c index ed22ef01..95a258a2 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -227,7 +227,7 @@ static void centerCursor(_GLFWwindow* window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } -// +// Returns whether the cursor is in the client area of the specified window // static GLFWbool cursorInClientArea(_GLFWwindow* window) { @@ -247,11 +247,11 @@ static GLFWbool cursorInClientArea(_GLFWwindow* window) return PtInRect(&area, pos); } -// Updates the cursor image according to the specified cursor mode +// Updates the cursor image according to its cursor mode // -static void updateCursorImage(_GLFWwindow* window, int mode) +static void updateCursorImage(_GLFWwindow* window) { - if (mode == GLFW_CURSOR_NORMAL) + if (window->cursorMode == GLFW_CURSOR_NORMAL) { if (window->cursor) SetCursor(window->cursor->win32.handle); @@ -259,12 +259,7 @@ static void updateCursorImage(_GLFWwindow* window, int mode) SetCursor(LoadCursorW(NULL, IDC_ARROW)); } else - { - if (mode == GLFW_CURSOR_DISABLED && _glfw.cursorWindow != window) - SetCursor(LoadCursorW(NULL, IDC_ARROW)); - else - SetCursor(NULL); - } + SetCursor(NULL); } // Updates the cursor clip rect @@ -430,7 +425,7 @@ static void releaseMonitor(_GLFWwindow* window) static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - _GLFWwindow* window = (_GLFWwindow*) GetPropW(hWnd, L"GLFW"); + _GLFWwindow* window = GetPropW(hWnd, L"GLFW"); if (!window) { // This is the message handling for the hidden helper window @@ -623,7 +618,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, if (window->cursorMode == GLFW_CURSOR_DISABLED) { - if (_glfw.cursorWindow != window) + if (_glfw.win32.disabledCursorWindow != window) break; const int dx = x - window->win32.lastCursorPosX; @@ -684,11 +679,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, window->win32.iconified && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED); - if (_glfw.cursorWindow == window) - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - updateClipRect(window); - } + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); if (iconified) _glfwInputWindowIconify(window, GLFW_TRUE); @@ -716,11 +708,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MOVE: { - if (_glfw.cursorWindow == window) - { - if (window->cursorMode == GLFW_CURSOR_DISABLED) - updateClipRect(window); - } + if (_glfw.win32.disabledCursorWindow == window) + updateClipRect(window); // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly @@ -785,7 +774,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { if (LOWORD(lParam) == HTCLIENT) { - updateCursorImage(window, window->cursorMode); + updateCursorImage(window); return TRUE; } @@ -925,6 +914,9 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) // static void destroyWindow(_GLFWwindow* window) { + if (_glfw.win32.disabledCursorWindow == window) + _glfw.win32.disabledCursorWindow = NULL; + if (window->win32.handle) { RemovePropW(window->win32.handle, L"GLFW"); @@ -1384,6 +1376,8 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window) void _glfwPlatformPollEvents(void) { MSG msg; + HWND handle; + _GLFWwindow* window; while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { @@ -1393,7 +1387,7 @@ void _glfwPlatformPollEvents(void) // While GLFW does not itself post WM_QUIT, other processes may post // it to this one, for example Task Manager - _GLFWwindow* window = _glfw.windowListHead; + window = _glfw.windowListHead; while (window) { _glfwInputWindowCloseRequest(window); @@ -1407,13 +1401,14 @@ void _glfwPlatformPollEvents(void) } } - if (_glfw.cursorWindow) + handle = GetActiveWindow(); + if (handle) { - _GLFWwindow* window = _glfw.cursorWindow; - // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix) // This is the only async event handling in GLFW, but it solves some // nasty problems + window = GetPropW(handle, L"GLFW"); + if (window) { const int mods = getAsyncKeyMods(); @@ -1429,19 +1424,20 @@ void _glfwPlatformPollEvents(void) if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1) _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods); } + } - if (window->cursorMode == GLFW_CURSOR_DISABLED) + window = _glfw.win32.disabledCursorWindow; + if (window) + { + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + + // NOTE: Re-center the cursor only if it has moved since the last call, + // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE + if (window->win32.lastCursorPosX != width / 2 || + window->win32.lastCursorPosY != height / 2) { - int width, height; - _glfwPlatformGetWindowSize(window, &width, &height); - - // NOTE: Re-center the cursor only if it has moved since the last - // call, to avoid breaking glfwWaitEvents with WM_MOUSEMOVE - if (window->win32.lastCursorPosX != width / 2 || - window->win32.lastCursorPosY != height / 2) - { - _glfwPlatformSetCursorPos(window, width / 2, height / 2); - } + _glfwPlatformSetCursorPos(window, width / 2, height / 2); } } } @@ -1497,14 +1493,16 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { if (mode == GLFW_CURSOR_DISABLED) { + _glfw.win32.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, &_glfw.win32.restoreCursorPosX, &_glfw.win32.restoreCursorPosY); centerCursor(window); updateClipRect(window); } - else if (window->cursorMode == GLFW_CURSOR_DISABLED) + else if (_glfw.win32.disabledCursorWindow == window) { + _glfw.win32.disabledCursorWindow = NULL; updateClipRect(NULL); _glfwPlatformSetCursorPos(window, _glfw.win32.restoreCursorPosX, @@ -1512,7 +1510,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) } if (cursorInClientArea(window)) - updateCursorImage(window, mode); + updateCursorImage(window); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -1573,7 +1571,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { if (cursorInClientArea(window)) - updateCursorImage(window, window->cursorMode); + updateCursorImage(window); } void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) diff --git a/src/window.c b/src/window.c index ed0a22d6..74c0b601 100644 --- a/src/window.c +++ b/src/window.c @@ -42,8 +42,6 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (focused) { - _glfw.cursorWindow = window; - if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); } @@ -51,8 +49,6 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { int i; - _glfw.cursorWindow = NULL; - if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); @@ -394,10 +390,6 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) if (window == _glfwPlatformGetCurrentContext()) glfwMakeContextCurrent(NULL); - // Clear the focused window pointer if this is the focused window - if (_glfw.cursorWindow == window) - _glfw.cursorWindow = NULL; - _glfwPlatformDestroyWindow(window); // Unlink window from global linked list diff --git a/src/x11_platform.h b/src/x11_platform.h index cdcfa96d..386714f7 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -157,6 +157,8 @@ typedef struct _GLFWlibraryX11 short int nativeKeys[GLFW_KEY_LAST + 1]; // Where to place the cursor when re-enabled double restoreCursorPosX, restoreCursorPosY; + // The window whose disabled cursor mode is active + _GLFWwindow* disabledCursorWindow; // Window manager atoms Atom WM_PROTOCOLS; diff --git a/src/x11_window.c b/src/x11_window.c index 34fb1819..5b202899 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -396,6 +396,24 @@ static void centerCursor(_GLFWwindow* window) _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) + { + if (window->cursor) + { + XDefineCursor(_glfw.x11.display, window->x11.handle, + window->cursor->x11.handle); + } + else + XUndefineCursor(_glfw.x11.display, window->x11.handle); + } + else + XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor); +} + // Create the X11 window (and its colormap) // static GLFWbool createWindow(_GLFWwindow* window, @@ -1164,7 +1182,7 @@ static void processEvent(XEvent *event) if (window->cursorMode == GLFW_CURSOR_DISABLED) { - if (_glfw.cursorWindow != window) + if (_glfw.x11.disabledCursorWindow != window) return; const int dx = x - window->x11.lastCursorPosX; @@ -1538,6 +1556,9 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, void _glfwPlatformDestroyWindow(_GLFWwindow* window) { + if (_glfw.x11.disabledCursorWindow == window) + _glfw.x11.disabledCursorWindow = NULL; + if (window->monitor) releaseMonitor(window); @@ -2011,9 +2032,8 @@ void _glfwPlatformPollEvents(void) processEvent(&event); } - _GLFWwindow* window = _glfw.cursorWindow; - if (window && window->cursorMode == GLFW_CURSOR_DISABLED) - centerCursor(window); + if (_glfw.x11.disabledCursorWindow) + centerCursor(_glfw.x11.disabledCursorWindow); } void _glfwPlatformWaitEvents(void) @@ -2092,6 +2112,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { if (mode == GLFW_CURSOR_DISABLED) { + _glfw.x11.disabledCursorWindow = window; _glfwPlatformGetCursorPos(window, &_glfw.x11.restoreCursorPosX, &_glfw.x11.restoreCursorPosY); @@ -2101,26 +2122,16 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) GrabModeAsync, GrabModeAsync, window->x11.handle, _glfw.x11.cursor, CurrentTime); } - else if (window->cursorMode == GLFW_CURSOR_DISABLED) + else if (_glfw.x11.disabledCursorWindow == window) { + _glfw.x11.disabledCursorWindow = NULL; XUngrabPointer(_glfw.x11.display, CurrentTime); _glfwPlatformSetCursorPos(window, _glfw.x11.restoreCursorPosX, _glfw.x11.restoreCursorPosY); } - if (mode == GLFW_CURSOR_NORMAL) - { - if (window->cursor) - { - XDefineCursor(_glfw.x11.display, window->x11.handle, - window->cursor->x11.handle); - } - else - XUndefineCursor(_glfw.x11.display, window->x11.handle); - } - else - XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor); + updateCursorImage(window); } const char* _glfwPlatformGetKeyName(int key, int scancode) @@ -2186,11 +2197,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { if (window->cursorMode == GLFW_CURSOR_NORMAL) { - if (cursor) - XDefineCursor(_glfw.x11.display, window->x11.handle, cursor->x11.handle); - else - XUndefineCursor(_glfw.x11.display, window->x11.handle); - + updateCursorImage(window); XFlush(_glfw.x11.display); } }