Made glfwGetCursorPos query system directly.

Fixes #103.
Fixes #153.
Fixes #193.
Fixes #355.
Fixes #381.
This commit is contained in:
Camilla Berglund 2014-02-11 18:24:01 +01:00
parent 641761ddb0
commit d459145d28
11 changed files with 177 additions and 131 deletions

View File

@ -92,6 +92,8 @@ GLFW bundles a number of dependencies in the `deps/` directory.
the default behavior
- Changed static library to build as position independent code for easier use
from the Rust language
- Changed `glfwGetCursorPos` to query the system directly for all cursor modes
except captured mode
- Bugfix: The debug context attribute was set from `GL_ARB_debug_output` even
when a debug context had not been requested
- Bugfix: The particles example was not linked against the threading library

View File

@ -228,10 +228,6 @@ double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
@endcode
This function only returns cached cursor positions. It does not poll the
system for the current position. Whenever you poll state, you risk missing the
state change you are looking for.
@subsection input_cursor_mode Cursor modes

View File

@ -81,6 +81,13 @@ The support for EGL is now stable, successfully running on PandaBoards, Mesa,
ANGLE, Wayland, AMD EGL and others.
@subsection news_31_getcursorpos Direct query for cursor position
GLFW now queries the system cursor position directly when you call @ref
glfwGetCursorPos instead of returning cached data, except for when the window is
in captured cursor mode.
@section news_30 New features in version 3.0
@subsection news_30_cmake CMake build system

View File

@ -2573,12 +2573,12 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
*/
GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
/*! @brief Retrieves the last reported cursor position, relative to the client
* area of the window.
/*! @brief Retrieves the position of the cursor relative to the client area of
* the window.
*
* This function returns the last reported position of the cursor, in screen
* coordinates, relative to the upper-left corner of the client area of the
* specified window.
* This function returns the position of the cursor, in screen coordinates,
* relative to the upper-left corner of the client area of the specified
* window.
*
* If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
* position is unbounded and limited only by the minimum and maximum values of

View File

@ -63,6 +63,11 @@ typedef struct _GLFWwindowNS
id view;
unsigned int modifierFlags;
// The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed
// This is kept to counteract Cocoa doing the same internally
double warpDeltaX, warpDeltaY;
} _GLFWwindowNS;

View File

@ -156,25 +156,31 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidResize:(NSNotification *)notification
{
if (_glfw.focusedWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
}
const NSRect contentRect = [window->ns.view frame];
const NSRect fbRect = convertRectToBacking(window, contentRect);
_glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
_glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
_glfwInputWindowDamage(window);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
centerCursor(window);
}
- (void)windowDidMove:(NSNotification *)notification
{
if (_glfw.focusedWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
}
int x, y;
_glfwPlatformGetWindowPos(window, &x, &y);
_glfwInputWindowPos(window, x, y);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
centerCursor(window);
}
- (void)windowDidMiniaturize:(NSNotification *)notification
@ -192,6 +198,12 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
if (window->monitor)
enterFullscreenMode(window);
if (_glfw.focusedWindow == window &&
window->cursorMode == GLFW_CURSOR_DISABLED)
{
centerCursor(window);
}
_glfwInputWindowFocus(window, GL_TRUE);
_glfwPlatformApplyCursorMode(window);
}
@ -366,14 +378,21 @@ static int translateKey(unsigned int key)
- (void)mouseMoved:(NSEvent *)event
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwInputCursorMotion(window, [event deltaX], [event deltaY]);
{
_glfwInputCursorMotion(window,
[event deltaX] - window->ns.warpDeltaX,
[event deltaY] - window->ns.warpDeltaY);
}
else
{
const NSRect contentRect = [window->ns.view frame];
const NSPoint p = [event locationInWindow];
const NSPoint pos = [event locationInWindow];
_glfwInputCursorMotion(window, p.x, contentRect.size.height - p.y);
_glfwInputCursorMotion(window, pos.x, contentRect.size.height - pos.y);
}
window->ns.warpDeltaX = 0;
window->ns.warpDeltaY = 0;
}
- (void)rightMouseDown:(NSEvent *)event
@ -563,11 +582,10 @@ static int translateKey(unsigned int key)
NSPasteboard* pasteboard = [sender draggingPasteboard];
NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
int height;
_glfwPlatformGetWindowSize(window, NULL, &height);
const NSRect contentRect = [window->ns.view frame];
_glfwInputCursorMotion(window,
[sender draggingLocation].x,
height - [sender draggingLocation].y);
contentRect.size.height - [sender draggingLocation].y);
const int count = [files count];
if (count)
@ -1098,10 +1116,27 @@ void _glfwPlatformPostEmptyEvent(void)
[pool drain];
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
const NSRect contentRect = [window->ns.view frame];
const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
if (xpos)
*xpos = pos.x;
if (ypos)
*ypos = contentRect.size.height - pos.y - 1;
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
updateModeCursor(window);
const NSRect contentRect = [window->ns.view frame];
const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
window->ns.warpDeltaX += x - pos.x;
window->ns.warpDeltaY += y - contentRect.size.height + pos.y;
if (window->monitor)
{
CGDisplayMoveCursorToPoint(window->monitor->ns.displayID,
@ -1109,7 +1144,6 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
}
else
{
const NSRect contentRect = [window->ns.view frame];
const NSPoint localPoint = NSMakePoint(x, contentRect.size.height - y - 1);
const NSPoint globalPoint = [window->ns.object convertBaseToScreen:localPoint];
@ -1123,10 +1157,7 @@ void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
updateModeCursor(window);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
CGAssociateMouseAndMouseCursorPosition(false);
centerCursor(window);
}
else
CGAssociateMouseAndMouseCursorPosition(true);
}
@ -1192,10 +1223,10 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
const NSPoint p = [window->ns.object mouseLocationOutsideOfEventStream];
const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
if (window->cursorMode == GLFW_CURSOR_NORMAL &&
[window->ns.view mouse:p inRect:[window->ns.view frame]])
[window->ns.view mouse:pos inRect:[window->ns.view frame]])
{
if (cursor)
[(NSCursor*) cursor->ns.object set];

View File

@ -59,20 +59,23 @@ static void setCursorMode(_GLFWwindow* window, int newMode)
{
if (oldMode == GLFW_CURSOR_DISABLED)
{
window->cursorPosX = _glfw.cursorPosX;
window->cursorPosY = _glfw.cursorPosY;
_glfwPlatformSetCursorPos(window, _glfw.cursorPosX, _glfw.cursorPosY);
_glfwPlatformSetCursorPos(window,
_glfw.cursorPosX,
_glfw.cursorPosY);
}
else if (newMode == GLFW_CURSOR_DISABLED)
{
int width, height;
_glfw.cursorPosX = window->cursorPosX;
_glfw.cursorPosY = window->cursorPosY;
_glfwPlatformGetCursorPos(window,
&_glfw.cursorPosX,
&_glfw.cursorPosY);
window->cursorPosX = _glfw.cursorPosX;
window->cursorPosY = _glfw.cursorPosY;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
}
_glfwPlatformApplyCursorMode(window);
@ -198,22 +201,13 @@ void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y)
window->cursorPosX += x;
window->cursorPosY += y;
}
else
{
if (window->cursorPosX == x && window->cursorPosY == y)
return;
window->cursorPosX = x;
window->cursorPosY = y;
x = window->cursorPosX;
y = window->cursorPosY;
}
if (window->callbacks.cursorPos)
{
window->callbacks.cursorPos((GLFWwindow*) window,
window->cursorPosX,
window->cursorPosY);
}
window->callbacks.cursorPos((GLFWwindow*) window, x, y);
}
void _glfwInputCursorEnter(_GLFWwindow* window, int entered)
@ -332,11 +326,16 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
_GLFW_REQUIRE_INIT();
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (xpos)
*xpos = window->cursorPosX;
if (ypos)
*ypos = window->cursorPosY;
}
else
_glfwPlatformGetCursorPos(window, xpos, ypos);
}
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
{
@ -347,21 +346,18 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
if (_glfw.focusedWindow != window)
return;
// Don't do anything if the cursor position did not change
if (xpos == window->cursorPosX && ypos == window->cursorPosY)
return;
// Set GLFW cursor position
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
// Only update the accumulated position if the cursor is disabled
window->cursorPosX = xpos;
window->cursorPosY = ypos;
// Do not move physical cursor if it is disabled
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
// Update physical cursor position
}
else
{
// Update system cursor position
_glfwPlatformSetCursorPos(window, xpos, ypos);
}
}
GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
{

View File

@ -410,6 +410,11 @@ void _glfwPlatformTerminate(void);
*/
const char* _glfwPlatformGetVersionString(void);
/*! @copydoc glfwGetCursorPos
* @ingroup platform
*/
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
/*! @copydoc glfwSetCursorPos
* @ingroup platform
*/

View File

@ -158,10 +158,10 @@ typedef struct _GLFWwindowWin32
DWORD dwStyle;
DWORD dwExStyle;
GLboolean cursorCentered;
GLboolean cursorInside;
GLboolean cursorHidden;
int oldCursorX, oldCursorY;
// The last received cursor position, regardless of source
int cursorPosX, cursorPosY;
} _GLFWwindowWin32;

View File

@ -55,15 +55,8 @@ static void hideCursor(_GLFWwindow* window)
{
POINT pos;
ReleaseCapture();
ClipCursor(NULL);
if (window->win32.cursorHidden)
{
ShowCursor(TRUE);
window->win32.cursorHidden = GL_FALSE;
}
if (GetCursorPos(&pos))
{
if (WindowFromPoint(pos) == window->win32.handle)
@ -75,14 +68,15 @@ static void hideCursor(_GLFWwindow* window)
//
static void disableCursor(_GLFWwindow* window)
{
if (!window->win32.cursorHidden)
{
ShowCursor(FALSE);
window->win32.cursorHidden = GL_TRUE;
}
POINT pos;
updateClipRect(window);
SetCapture(window->win32.handle);
if (GetCursorPos(&pos))
{
if (WindowFromPoint(pos) == window->win32.handle)
SetCursor(NULL);
}
}
// Restores the mouse cursor
@ -91,15 +85,8 @@ static void restoreCursor(_GLFWwindow* window)
{
POINT pos;
ReleaseCapture();
ClipCursor(NULL);
if (window->win32.cursorHidden)
{
ShowCursor(TRUE);
window->win32.cursorHidden = GL_FALSE;
}
if (GetCursorPos(&pos))
{
if (WindowFromPoint(pos) == window->win32.handle)
@ -439,34 +426,23 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_MOUSEMOVE:
{
const int newCursorX = GET_X_LPARAM(lParam);
const int newCursorY = GET_Y_LPARAM(lParam);
if (newCursorX != window->win32.oldCursorX ||
newCursorY != window->win32.oldCursorY)
{
int x, y;
const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.focusedWindow != window)
return 0;
break;
x = newCursorX - window->win32.oldCursorX;
y = newCursorY - window->win32.oldCursorY;
_glfwInputCursorMotion(window,
x - window->win32.cursorPosX,
y - window->win32.cursorPosY);
}
else
{
x = newCursorX;
y = newCursorY;
}
window->win32.oldCursorX = newCursorX;
window->win32.oldCursorY = newCursorY;
window->win32.cursorCentered = GL_FALSE;
_glfwInputCursorMotion(window, x, y);
}
window->win32.cursorPosX = x;
window->win32.cursorPosY = y;
if (!window->win32.cursorInside)
{
@ -1058,13 +1034,11 @@ void _glfwPlatformPollEvents(void)
}
// Did the cursor move in an focused window that has disabled the cursor
if (window->cursorMode == GLFW_CURSOR_DISABLED &&
!window->win32.cursorCentered)
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
window->win32.cursorCentered = GL_TRUE;
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
}
}
}
@ -1082,14 +1056,31 @@ void _glfwPlatformPostEmptyEvent(void)
PostMessage(window->win32.handle, WM_NULL, 0, 0);
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
POINT pos;
if (GetCursorPos(&pos))
{
ScreenToClient(window->win32.handle, &pos);
if (xpos)
*xpos = pos.x;
if (ypos)
*ypos = pos.y;
}
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
POINT pos = { (int) xpos, (int) ypos };
// Store the new position so it can be recognized later
window->win32.cursorPosX = pos.x;
window->win32.cursorPosY = pos.y;
ClientToScreen(window->win32.handle, &pos);
SetCursorPos(pos.x, pos.y);
window->win32.oldCursorX = (int) xpos;
window->win32.oldCursorY = (int) ypos;
}
void _glfwPlatformApplyCursorMode(_GLFWwindow* window)

View File

@ -1066,32 +1066,28 @@ static void processEvent(XEvent *event)
case MotionNotify:
{
if (event->xmotion.x != window->x11.warpPosX ||
event->xmotion.y != window->x11.warpPosY)
const int x = event->xmotion.x;
const int y = event->xmotion.y;
if (x != window->x11.warpPosX || y != window->x11.warpPosY)
{
// The cursor was moved by something other than GLFW
int x, y;
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.focusedWindow != window)
break;
x = event->xmotion.x - window->x11.cursorPosX;
y = event->xmotion.y - window->x11.cursorPosY;
_glfwInputCursorMotion(window,
x - window->x11.cursorPosX,
y - window->x11.cursorPosY);
}
else
{
x = event->xmotion.x;
y = event->xmotion.y;
}
_glfwInputCursorMotion(window, x, y);
}
window->x11.cursorPosX = event->xmotion.x;
window->x11.cursorPosY = event->xmotion.y;
window->x11.cursorPosX = x;
window->x11.cursorPosY = y;
break;
}
@ -1744,6 +1740,23 @@ void _glfwPlatformPostEmptyEvent(void)
XFlush(_glfw.x11.display);
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
Window root, child;
int rootX, rootY, childX, childY;
unsigned int mask;
XQueryPointer(_glfw.x11.display, window->x11.handle,
&root, &child,
&rootX, &rootY, &childX, &childY,
&mask);
if (xpos)
*xpos = childX;
if (ypos)
*ypos = childY;
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
// Store the new position so it can be recognized later