1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2025-02-24 14:18:50 -05:00

Move all cursor positioning to platform code

Due to Wayland, shared code cannot rely on cursor positioning being
supported by the underlying platform.

This implicitly fixes  as it moves cursor centering into
_glfwPlatformSetCursorMode, thus separating it from the stale value of
_glfw.cursorWindow.

Fixes .
This commit is contained in:
Camilla Berglund 2016-05-25 14:06:02 +02:00
parent 0e846883bf
commit 797ee8d8e3
12 changed files with 205 additions and 182 deletions

View File

@ -99,6 +99,8 @@ typedef struct _GLFWlibraryNS
short int publicKeys[256];
short int nativeKeys[GLFW_KEY_LAST + 1];
char* clipboardString;
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
struct {
CFBundleRef bundle;

View File

@ -85,6 +85,21 @@ static void centerCursor(_GLFWwindow *window)
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
// Updates the cursor image according to the specified cursor mode
//
static void updateCursorImage(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
[(NSCursor*) window->cursor->ns.object set];
else
[[NSCursor arrowCursor] set];
}
else
[(NSCursor*) _glfw.ns.cursor set];
}
// Transforms the specified y-coordinate between the CG display and NS screen
// coordinate systems
//
@ -394,7 +409,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)cursorUpdate:(NSEvent *)event
{
_glfwPlatformSetCursorMode(window, window->cursorMode);
updateCursorImage(window, window->cursorMode);
}
- (void)mouseDown:(NSEvent *)event
@ -422,16 +437,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
_glfwInputCursorMotion(window,
[event deltaX] - window->ns.cursorWarpDeltaX,
[event deltaY] - window->ns.cursorWarpDeltaY);
const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;
const double dy = [event deltaY] - window->ns.cursorWarpDeltaY;
_glfwInputCursorPos(window,
window->virtualCursorPosX + dx,
window->virtualCursorPosY + dy);
}
else
{
const NSRect contentRect = [window->ns.view frame];
const NSPoint pos = [event locationInWindow];
_glfwInputCursorMotion(window, pos.x, contentRect.size.height - pos.y);
_glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
}
window->ns.cursorWarpDeltaX = 0;
@ -607,9 +625,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
const NSRect contentRect = [window->ns.view frame];
_glfwInputCursorMotion(window,
[sender draggingLocation].x,
contentRect.size.height - [sender draggingLocation].y);
_glfwInputCursorPos(window,
[sender draggingLocation].x,
contentRect.size.height - [sender draggingLocation].y);
const int count = [files count];
if (count)
@ -1033,6 +1051,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
centerCursor(window);
}
return GLFW_TRUE;
@ -1397,7 +1417,7 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
_glfwPlatformSetCursorMode(window, window->cursorMode);
updateCursorImage(window, window->cursorMode);
const NSRect contentRect = [window->ns.view frame];
const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
@ -1423,20 +1443,23 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
[(NSCursor*) window->cursor->ns.object set];
else
[[NSCursor arrowCursor] set];
}
else
[(NSCursor*) _glfw.ns.cursor set];
if (mode == GLFW_CURSOR_DISABLED)
{
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
centerCursor(window);
CGAssociateMouseAndMouseCursorPosition(false);
else
}
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
CGAssociateMouseAndMouseCursorPosition(true);
_glfwPlatformSetCursorPos(window,
_glfw.ns.restoreCursorPosX,
_glfw.ns.restoreCursorPosY);
}
updateCursorImage(window, mode);
}
const char* _glfwPlatformGetKeyName(int key, int scancode)

View File

@ -37,48 +37,27 @@
// Sets the cursor mode for the specified window
//
static void setCursorMode(_GLFWwindow* window, int newMode)
static void setCursorMode(_GLFWwindow* window, int mode)
{
const int oldMode = window->cursorMode;
if (newMode != GLFW_CURSOR_NORMAL &&
newMode != GLFW_CURSOR_HIDDEN &&
newMode != GLFW_CURSOR_DISABLED)
if (mode != GLFW_CURSOR_NORMAL &&
mode != GLFW_CURSOR_HIDDEN &&
mode != GLFW_CURSOR_DISABLED)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode %i", newMode);
_glfwInputError(GLFW_INVALID_ENUM, "Invalid cursor mode %i", mode);
return;
}
if (oldMode == newMode)
if (window->cursorMode == mode)
return;
window->cursorMode = newMode;
_glfwPlatformGetCursorPos(window,
&window->virtualCursorPosX,
&window->virtualCursorPosY);
if (_glfw.cursorWindow == window)
{
if (oldMode == GLFW_CURSOR_DISABLED)
{
_glfwPlatformSetCursorPos(window,
_glfw.restoreCursorPosX,
_glfw.restoreCursorPosY);
}
else if (newMode == GLFW_CURSOR_DISABLED)
{
int width, height;
_glfwPlatformSetCursorMode(window, mode);
_glfwPlatformGetCursorPos(window,
&_glfw.restoreCursorPosX,
&_glfw.restoreCursorPosY);
window->virtualCursorPosX = _glfw.restoreCursorPosX;
window->virtualCursorPosY = _glfw.restoreCursorPosY;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
}
_glfwPlatformSetCursorMode(window, window->cursorMode);
}
window->cursorMode = mode;
}
// Set sticky keys mode for the specified window
@ -191,19 +170,13 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
}
void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y)
void _glfwInputCursorPos(_GLFWwindow* window, double x, double y)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (x == 0.0 && y == 0.0)
return;
if (window->virtualCursorPosX == x && window->virtualCursorPosY == y)
return;
window->virtualCursorPosX += x;
window->virtualCursorPosY += y;
x = window->virtualCursorPosX;
y = window->virtualCursorPosY;
}
window->virtualCursorPosX = x;
window->virtualCursorPosY = y;
if (window->callbacks.cursorPos)
window->callbacks.cursorPos((GLFWwindow*) window, x, y);
@ -490,9 +463,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
_GLFW_REQUIRE_INIT();
_glfwPlatformSetCursor(window, cursor);
window->cursor = cursor;
_glfwPlatformSetCursor(window, cursor);
}
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)

View File

@ -437,9 +437,6 @@ struct _GLFWlibrary
int refreshRate;
} hints;
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
_GLFWcursor* cursorListHead;
_GLFWwindow* windowListHead;
@ -906,7 +903,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
* of the client area of the window.
* @ingroup event
*/
void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y);
void _glfwInputCursorPos(_GLFWwindow* window, double x, double y);
/*! @brief Notifies shared code of a cursor enter/leave event.
* @param[in] window The window that received the event.

View File

@ -208,8 +208,7 @@ static void handlePointerMotion(_GLFWwindow* window,
int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
if (current_x != x || current_y != y)
_glfwInputCursorMotion(window, x, y);
_glfwInputCursorPos(window, x, y);
if (dx != 0 || dy != 0)
_glfwInputScroll(window, dx, dy);
}

View File

@ -252,6 +252,8 @@ typedef struct _GLFWlibraryWin32
char keyName[64];
short int publicKeys[512];
short int nativeKeys[GLFW_KEY_LAST + 1];
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
struct {
HINSTANCE instance;

View File

@ -218,15 +218,69 @@ static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
}
}
// Centers the cursor over the window client area
//
static void centerCursor(_GLFWwindow* window)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
//
//
static GLFWbool cursorInClientArea(_GLFWwindow* window)
{
RECT area;
POINT pos;
if (!GetCursorPos(&pos))
return GLFW_FALSE;
if (WindowFromPoint(pos) != window->win32.handle)
return GLFW_FALSE;
GetClientRect(window->win32.handle, &area);
ClientToScreen(window->win32.handle, (POINT*) &area.left);
ClientToScreen(window->win32.handle, (POINT*) &area.right);
return PtInRect(&area, pos);
}
// Updates the cursor image according to the specified cursor mode
//
static void updateCursorImage(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
SetCursor(window->cursor->win32.handle);
else
SetCursor(LoadCursorW(NULL, IDC_ARROW));
}
else
{
if (mode == GLFW_CURSOR_DISABLED && _glfw.cursorWindow != window)
SetCursor(LoadCursorW(NULL, IDC_ARROW));
else
SetCursor(NULL);
}
}
// Updates the cursor clip rect
//
static void updateClipRect(_GLFWwindow* window)
{
RECT clipRect;
GetClientRect(window->win32.handle, &clipRect);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
ClipCursor(&clipRect);
if (window)
{
RECT clipRect;
GetClientRect(window->win32.handle, &clipRect);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
ClipCursor(&clipRect);
}
else
ClipCursor(NULL);
}
// Translates a GLFW standard cursor to a resource ID
@ -420,10 +474,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{
case WM_SETFOCUS:
{
_glfwInputWindowFocus(window, GLFW_TRUE);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
_glfwInputWindowFocus(window, GLFW_TRUE);
return 0;
}
@ -571,12 +626,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (_glfw.cursorWindow != window)
break;
_glfwInputCursorMotion(window,
x - window->win32.lastCursorPosX,
y - window->win32.lastCursorPosY);
const int dx = x - window->win32.lastCursorPosX;
const int dy = y - window->win32.lastCursorPosY;
_glfwInputCursorPos(window,
window->virtualCursorPosX + dx,
window->virtualCursorPosY + dy);
}
else
_glfwInputCursorMotion(window, x, y);
_glfwInputCursorPos(window, x, y);
window->win32.lastCursorPosX = x;
window->win32.lastCursorPosY = y;
@ -725,19 +783,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SETCURSOR:
{
if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT)
if (LOWORD(lParam) == HTCLIENT)
{
if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
window->cursorMode == GLFW_CURSOR_DISABLED)
{
SetCursor(NULL);
return TRUE;
}
else if (window->cursor)
{
SetCursor(window->cursor->win32.handle);
return TRUE;
}
updateCursorImage(window, window->cursorMode);
return TRUE;
}
break;
@ -767,7 +816,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// Move the mouse to the position of the drop
DragQueryPoint(drop, &pt);
_glfwInputCursorMotion(window, pt.x, pt.y);
_glfwInputCursorPos(window, pt.x, pt.y);
for (i = 0; i < count; i++)
{
@ -1007,6 +1056,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
centerCursor(window);
}
return GLFW_TRUE;
@ -1444,28 +1495,24 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
POINT pos;
if (mode == GLFW_CURSOR_DISABLED)
updateClipRect(window);
else
ClipCursor(NULL);
if (!GetCursorPos(&pos))
return;
if (WindowFromPoint(pos) != window->win32.handle)
return;
if (mode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
SetCursor(window->cursor->win32.handle);
else
SetCursor(LoadCursorW(NULL, IDC_ARROW));
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
centerCursor(window);
updateClipRect(window);
}
else
SetCursor(NULL);
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
}
if (cursorInClientArea(window))
updateCursorImage(window, mode);
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
@ -1525,32 +1572,8 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
RECT area;
POINT pos;
if (_glfw.cursorWindow != window)
return;
if (window->cursorMode != GLFW_CURSOR_NORMAL)
return;
if (!GetCursorPos(&pos))
return;
if (WindowFromPoint(pos) != window->win32.handle)
return;
GetClientRect(window->win32.handle, &area);
ClientToScreen(window->win32.handle, (POINT*) &area.left);
ClientToScreen(window->win32.handle, (POINT*) &area.right);
if (!PtInRect(&area, pos))
return;
if (cursor)
SetCursor(cursor->win32.handle);
else
SetCursor(LoadCursorW(NULL, IDC_ARROW));
if (cursorInClientArea(window))
updateCursorImage(window, window->cursorMode);
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)

View File

@ -219,19 +219,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
glfwMakeContextCurrent((GLFWwindow*) previous);
}
if (window->monitor)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
window->virtualCursorPosX = width / 2;
window->virtualCursorPosY = height / 2;
_glfwPlatformSetCursorPos(window,
window->virtualCursorPosX,
window->virtualCursorPosY);
}
else
if (!window->monitor)
{
if (wndconfig.visible)
{

View File

@ -91,9 +91,9 @@ static void pointerHandleMotion(void* data,
window->wl.cursorPosY = wl_fixed_to_double(sy);
}
_glfwInputCursorMotion(window,
wl_fixed_to_double(sx),
wl_fixed_to_double(sy));
_glfwInputCursorPos(window,
wl_fixed_to_double(sx),
wl_fixed_to_double(sy));
}
static void pointerHandleButton(void* data,

View File

@ -784,9 +784,9 @@ static void handleRelativeMotion(void* data,
if (window->cursorMode != GLFW_CURSOR_DISABLED)
return;
_glfwInputCursorMotion(window,
wl_fixed_to_double(dxUnaccel),
wl_fixed_to_double(dyUnaccel));
_glfwInputCursorPos(window,
window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel),
window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel));
}
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {

View File

@ -118,7 +118,7 @@ typedef struct _GLFWwindowX11
int xpos, ypos;
// The last received cursor position, regardless of source
double lastCursorPosX, lastCursorPosY;
int lastCursorPosX, lastCursorPosY;
// The last position the cursor was warped to by GLFW
int warpCursorPosX, warpCursorPosY;
@ -155,6 +155,8 @@ typedef struct _GLFWlibraryX11
short int publicKeys[256];
// GLFW key to X11 keycode LUT
short int nativeKeys[GLFW_KEY_LAST + 1];
// Where to place the cursor when re-enabled
double restoreCursorPosX, restoreCursorPosY;
// Window manager atoms
Atom WM_PROTOCOLS;

View File

@ -387,6 +387,15 @@ static char** parseUriList(char* text, int* count)
return paths;
}
// Centers the cursor over the window client area
//
static void centerCursor(_GLFWwindow* window)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
// Create the X11 window (and its colormap)
//
static GLFWbool createWindow(_GLFWwindow* window,
@ -1158,12 +1167,15 @@ static void processEvent(XEvent *event)
if (_glfw.cursorWindow != window)
return;
_glfwInputCursorMotion(window,
x - window->x11.lastCursorPosX,
y - window->x11.lastCursorPosY);
const int dx = x - window->x11.lastCursorPosX;
const int dy = y - window->x11.lastCursorPosY;
_glfwInputCursorPos(window,
window->virtualCursorPosX + dx,
window->virtualCursorPosY + dy);
}
else
_glfwInputCursorMotion(window, x, y);
_glfwInputCursorPos(window, x, y);
}
window->x11.lastCursorPosX = x;
@ -1265,7 +1277,7 @@ static void processEvent(XEvent *event)
int x, y;
_glfwPlatformGetWindowPos(window, &x, &y);
_glfwInputCursorMotion(window, absX - x, absY - y);
_glfwInputCursorPos(window, absX - x, absY - y);
// Reply that we are ready to copy the dragged data
XEvent reply;
@ -1517,6 +1529,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
updateWindowMode(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
centerCursor(window);
}
return GLFW_TRUE;
@ -1999,11 +2013,7 @@ void _glfwPlatformPollEvents(void)
_GLFWwindow* window = _glfw.cursorWindow;
if (window && window->cursorMode == GLFW_CURSOR_DISABLED)
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2, height / 2);
}
centerCursor(window);
}
void _glfwPlatformWaitEvents(void)
@ -2082,31 +2092,35 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
_glfwPlatformGetCursorPos(window,
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
centerCursor(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle, _glfw.x11.cursor, CurrentTime);
}
else
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
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
if (mode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
{
XDefineCursor(_glfw.x11.display, window->x11.handle,
_glfw.x11.cursor);
window->cursor->x11.handle);
}
else
XUndefineCursor(_glfw.x11.display, window->x11.handle);
}
else
XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor);
}
const char* _glfwPlatformGetKeyName(int key, int scancode)