Browse Source

Simplify cursor window logic

Camilla Berglund 9 năm trước cách đây
mục cha
commit
2d2756cbad
9 tập tin đã thay đổi với 104 bổ sung104 xóa
  1. 2 0
      src/cocoa_platform.h
  2. 26 29
      src/cocoa_window.m
  3. 4 3
      src/input.c
  4. 0 1
      src/internal.h
  5. 2 0
      src/win32_platform.h
  6. 39 41
      src/win32_window.c
  7. 0 8
      src/window.c
  8. 2 0
      src/x11_platform.h
  9. 29 22
      src/x11_window.c

+ 2 - 0
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;

+ 26 - 29
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)

+ 4 - 3
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)

+ 0 - 1
src/internal.h

@@ -440,7 +440,6 @@ struct _GLFWlibrary
     _GLFWcursor*        cursorListHead;
 
     _GLFWwindow*        windowListHead;
-    _GLFWwindow*        cursorWindow;
 
     _GLFWmonitor**      monitors;
     int                 monitorCount;

+ 2 - 0
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;

+ 39 - 41
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)
-        {
-            int width, height;
-            _glfwPlatformGetWindowSize(window, &width, &height);
+    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)
-            {
-                _glfwPlatformSetCursorPos(window, width / 2, height / 2);
-            }
+        // 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);
         }
     }
 }
@@ -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)

+ 0 - 8
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

+ 2 - 0
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;

+ 29 - 22
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);
     }
 }