From 3c3981a4f00cdee0f20be6866305715a29b94125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 10 Apr 2019 21:19:40 +0200 Subject: [PATCH] Cocoa: Fix coordinate transformations Window relative mouse locations provided via NSWindow and NSEvent are based at 0,1 while screen relative locations use 0,0. Incorrect handling of this had crept into other coordinate transformations. Note that most of these errors canceled each other out, so the reported positions of windows, monitors and work areas are unaffected. This corrects the cursor position for glfwGetCursorPos and glfwSetCursorPos. Fixes #1461. --- README.md | 2 ++ src/cocoa_monitor.m | 2 +- src/cocoa_window.m | 29 +++++++++++++++-------------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8255d7dc..d328b4b5 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,8 @@ information on what to include when reporting a bug. - [Cocoa] Bugfix: OpenGL swap interval was ignored for occluded windows (#680) - [Cocoa] Bugfix: OpenGL swap interval was ignored on early macOS 10.14 (#1337,#1417,#1435) +- [Cocoa] Bugfix: The y-coordinate was incorrect for `glfwGetCursorPos` and + `glfwSetCursorPos` (#1461) - [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts - [WGL] Added support for `WGL_ARB_create_context_no_error` - [GLX] Added support for `GLX_ARB_create_context_no_error` diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index a5138572..e06fc905 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -430,7 +430,7 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, if (xpos) *xpos = frameRect.origin.x; if (ypos) - *ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height); + *ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1); if (width) *width = frameRect.size.width; if (height) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index bf6f6f28..e8e40a55 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -130,7 +130,7 @@ static void acquireMonitor(_GLFWwindow* window) _glfwSetVideoModeNS(window->monitor, &window->videoMode); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const NSRect frame = NSMakeRect(bounds.origin.x, - _glfwTransformYNS(bounds.origin.y + bounds.size.height), + _glfwTransformYNS(bounds.origin.y + bounds.size.height - 1), bounds.size.width, bounds.size.height); @@ -445,6 +445,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; else { const NSRect contentRect = [window->ns.view frame]; + // NOTE: The returned location uses base 0,1 not 0,0 const NSPoint pos = [event locationInWindow]; _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y); @@ -634,9 +635,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (BOOL)performDragOperation:(id )sender { const NSRect contentRect = [window->ns.view frame]; - _glfwInputCursorPos(window, - [sender draggingLocation].x, - contentRect.size.height - [sender draggingLocation].y); + // NOTE: The returned location uses base 0,1 not 0,0 + const NSPoint pos = [sender draggingLocation]; + _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y); NSPasteboard* pasteboard = [sender draggingPasteboard]; NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES}; @@ -713,10 +714,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange { - int xpos, ypos; - _glfwPlatformGetWindowPos(window, &xpos, &ypos); - const NSRect contentRect = [window->ns.view frame]; - return NSMakeRect(xpos, _glfwTransformYNS(ypos + contentRect.size.height), 0.0, 0.0); + const NSRect frame = [window->ns.view frame]; + return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0); } - (void)insertText:(id)string replacementRange:(NSRange)replacementRange @@ -878,7 +877,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, // float _glfwTransformYNS(float y) { - return CGDisplayBounds(CGMainDisplayID()).size.height - y; + return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1; } @@ -993,7 +992,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) if (xpos) *xpos = contentRect.origin.x; if (ypos) - *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height); + *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height - 1); } // autoreleasepool } @@ -1003,7 +1002,7 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y) @autoreleasepool { const NSRect contentRect = [window->ns.view frame]; - const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height), 0, 0); + const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height - 1), 0, 0); const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect]; [window->ns.object setFrameOrigin:frameRect.origin]; @@ -1198,7 +1197,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, else { const NSRect contentRect = - NSMakeRect(xpos, _glfwTransformYNS(ypos + height), width, height); + NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height); const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect styleMask:getStyleMask(window)]; @@ -1232,7 +1231,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, } else { - NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height), + NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height); NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect styleMask:styleMask]; @@ -1451,12 +1450,13 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) @autoreleasepool { const NSRect contentRect = [window->ns.view frame]; + // NOTE: The returned location uses base 0,1 not 0,0 const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; if (xpos) *xpos = pos.x; if (ypos) - *ypos = contentRect.size.height - pos.y - 1; + *ypos = contentRect.size.height - pos.y; } // autoreleasepool } @@ -1468,6 +1468,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) updateCursorImage(window); const NSRect contentRect = [window->ns.view frame]; + // NOTE: The returned location uses base 0,1 not 0,0 const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; window->ns.cursorWarpDeltaX += x - pos.x;