Replaced GLFW_MOUSE_CURSOR enable with glfwSetCursorMode.

This commit is contained in:
Camilla Berglund 2011-09-06 13:55:29 +02:00
parent 4fb55781f1
commit b1656d7323
14 changed files with 221 additions and 184 deletions

View File

@ -465,7 +465,7 @@ int main(void)
glfwEnable(window, GLFW_STICKY_KEYS); glfwEnable(window, GLFW_STICKY_KEYS);
// Enable mouse cursor (only needed for fullscreen mode) // Enable mouse cursor (only needed for fullscreen mode)
glfwEnable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_NORMAL);
// Set callback functions // Set callback functions
glfwSetWindowSizeCallback(windowSizeFun); glfwSetWindowSizeCallback(windowSizeFun);

View File

@ -309,13 +309,13 @@ void mouse_button_callback(GLFWwindow window, int button, int action)
if (action == GLFW_PRESS) if (action == GLFW_PRESS)
{ {
glfwDisable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_CAPTURED);
locked = GL_TRUE; locked = GL_TRUE;
} }
else else
{ {
locked = GL_FALSE; locked = GL_FALSE;
glfwEnable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_NORMAL);
} }
} }

8
include/GL/glfw3.h Executable file → Normal file
View File

@ -430,12 +430,16 @@ extern "C" {
#define GLFW_OPENGL_ES2_PROFILE 0x00000004 #define GLFW_OPENGL_ES2_PROFILE 0x00000004
/* glfwEnable/glfwDisable tokens */ /* glfwEnable/glfwDisable tokens */
#define GLFW_MOUSE_CURSOR 0x00030001
#define GLFW_STICKY_KEYS 0x00030002 #define GLFW_STICKY_KEYS 0x00030002
#define GLFW_STICKY_MOUSE_BUTTONS 0x00030003 #define GLFW_STICKY_MOUSE_BUTTONS 0x00030003
#define GLFW_SYSTEM_KEYS 0x00030004 #define GLFW_SYSTEM_KEYS 0x00030004
#define GLFW_KEY_REPEAT 0x00030005 #define GLFW_KEY_REPEAT 0x00030005
/* glfwSetCursorMode tokens */
#define GLFW_CURSOR_NORMAL 0x00040001
#define GLFW_CURSOR_HIDDEN 0x00040002
#define GLFW_CURSOR_CAPTURED 0x00040003
/* glfwGetJoystickParam tokens */ /* glfwGetJoystickParam tokens */
#define GLFW_PRESENT 0x00050001 #define GLFW_PRESENT 0x00050001
#define GLFW_AXES 0x00050002 #define GLFW_AXES 0x00050002
@ -451,6 +455,7 @@ extern "C" {
#define GLFW_OPENGL_UNAVAILABLE 0x00070006 #define GLFW_OPENGL_UNAVAILABLE 0x00070006
#define GLFW_VERSION_UNAVAILABLE 0x00070007 #define GLFW_VERSION_UNAVAILABLE 0x00070007
#define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_PLATFORM_ERROR 0x00070008
#define GLFW_WINDOW_NOT_ACTIVE 0x00070009
/* Gamma ramps */ /* Gamma ramps */
#define GLFW_GAMMA_RAMP_SIZE 256 #define GLFW_GAMMA_RAMP_SIZE 256
@ -564,6 +569,7 @@ GLFWAPI int glfwGetKey(GLFWwindow window, int key);
GLFWAPI int glfwGetMouseButton(GLFWwindow window, int button); GLFWAPI int glfwGetMouseButton(GLFWwindow window, int button);
GLFWAPI void glfwGetMousePos(GLFWwindow window, int* xpos, int* ypos); GLFWAPI void glfwGetMousePos(GLFWwindow window, int* xpos, int* ypos);
GLFWAPI void glfwSetMousePos(GLFWwindow window, int xpos, int ypos); GLFWAPI void glfwSetMousePos(GLFWwindow window, int xpos, int ypos);
GLFWAPI void glfwSetCursorMode(GLFWwindow window, int mode);
GLFWAPI void glfwGetScrollOffset(GLFWwindow window, int* xoffset, int* yoffset); GLFWAPI void glfwGetScrollOffset(GLFWwindow window, int* xoffset, int* yoffset);
GLFWAPI void glfwSetKeyCallback(GLFWkeyfun cbfun); GLFWAPI void glfwSetKeyCallback(GLFWkeyfun cbfun);
GLFWAPI void glfwSetCharCallback(GLFWcharfun cbfun); GLFWAPI void glfwSetCharCallback(GLFWcharfun cbfun);

View File

@ -274,6 +274,7 @@ version of GLFW.</p>
<li>Added <code>glfwGetCurrentContext</code> function for retrieving the window whose OpenGL context is current</li> <li>Added <code>glfwGetCurrentContext</code> function for retrieving the window whose OpenGL context is current</li>
<li>Added <code>glfwInitWithModels</code> function and <code>GLFWallocator</code> and <code>GLFWthreadmodel</code> types for pluggable memory allocation and threading models</li> <li>Added <code>glfwInitWithModels</code> function and <code>GLFWallocator</code> and <code>GLFWthreadmodel</code> types for pluggable memory allocation and threading models</li>
<li>Added <code>glfwCopyContext</code> function for copying OpenGL state categories between contexts</li> <li>Added <code>glfwCopyContext</code> function for copying OpenGL state categories between contexts</li>
<li>Added <code>glfwSetCursorMode</code> function for controlling per-window cursor mode, replacing <code>GLFW_MOUSE_CURSOR</code></li>
<li>Added <code>GLFW_OPENGL_ES2_PROFILE</code> profile for creating OpenGL ES 2.0 contexts using the <code>GLX_EXT_create_context_es2_profile</code> and <code>WGL_EXT_create_context_es2_profile</code> extensions</li> <li>Added <code>GLFW_OPENGL_ES2_PROFILE</code> profile for creating OpenGL ES 2.0 contexts using the <code>GLX_EXT_create_context_es2_profile</code> and <code>WGL_EXT_create_context_es2_profile</code> extensions</li>
<li>Added <code>GLFW_OPENGL_ROBUSTNESS</code> window hint and associated strategy tokens for <code>GL_ARB_robustness</code> support</li> <li>Added <code>GLFW_OPENGL_ROBUSTNESS</code> window hint and associated strategy tokens for <code>GL_ARB_robustness</code> support</li>
<li>Added <code>GLFW_OPENGL_REVISION</code> window parameter to make up for removal of <code>glfwGetGLVersion</code></li> <li>Added <code>GLFW_OPENGL_REVISION</code> window parameter to make up for removal of <code>glfwGetGLVersion</code></li>

View File

@ -348,7 +348,7 @@ static int convertMacKeyCode(unsigned int macKeyCode)
- (void)mouseMoved:(NSEvent *)event - (void)mouseMoved:(NSEvent *)event
{ {
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
window->mousePosX += [event deltaX]; window->mousePosX += [event deltaX];
window->mousePosY += [event deltaY]; window->mousePosY += [event deltaY];

View File

@ -31,58 +31,6 @@
#include "internal.h" #include "internal.h"
//========================================================================
// Enable and disable locked cursor mode
//========================================================================
static void enableMouseCursor(_GLFWwindow* window)
{
int centerPosX, centerPosY;
if (_glfwLibrary.cursorLockWindow != window)
return;
_glfwPlatformShowMouseCursor(window);
centerPosX = window->width / 2;
centerPosY = window->height / 2;
if (centerPosX != window->mousePosX || centerPosY != window->mousePosY)
{
_glfwPlatformSetMouseCursorPos(window, centerPosX, centerPosY);
window->mousePosX = centerPosX;
window->mousePosY = centerPosY;
if (_glfwLibrary.mousePosCallback)
{
_glfwLibrary.mousePosCallback(window,
window->mousePosX,
window->mousePosY);
}
}
// From now on the mouse is unlocked
_glfwLibrary.cursorLockWindow = NULL;
}
static void disableMouseCursor(_GLFWwindow* window)
{
if (_glfwLibrary.cursorLockWindow)
return;
_glfwPlatformHideMouseCursor(window);
// Move cursor to the middle of the window
_glfwPlatformSetMouseCursorPos(window,
window->width / 2,
window->height / 2);
// From now on the mouse is locked
_glfwLibrary.cursorLockWindow = window;
}
//======================================================================== //========================================================================
// Enable and disable sticky keys mode // Enable and disable sticky keys mode
//======================================================================== //========================================================================
@ -191,9 +139,6 @@ GLFWAPI void glfwEnable(GLFWwindow window, int token)
switch (token) switch (token)
{ {
case GLFW_MOUSE_CURSOR:
enableMouseCursor(window);
break;
case GLFW_STICKY_KEYS: case GLFW_STICKY_KEYS:
enableStickyKeys(window); enableStickyKeys(window);
break; break;
@ -226,9 +171,6 @@ GLFWAPI void glfwDisable(GLFWwindow window, int token)
switch (token) switch (token)
{ {
case GLFW_MOUSE_CURSOR:
disableMouseCursor(window);
break;
case GLFW_STICKY_KEYS: case GLFW_STICKY_KEYS:
disableStickyKeys(window); disableStickyKeys(window);
break; break;

View File

@ -140,6 +140,12 @@ GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos)
return; return;
} }
if (_glfwLibrary.activeWindow != window)
{
_glfwSetError(GLFW_WINDOW_NOT_ACTIVE, NULL);
return;
}
// Don't do anything if the mouse position did not change // Don't do anything if the mouse position did not change
if (xpos == window->mousePosX && ypos == window->mousePosY) if (xpos == window->mousePosX && ypos == window->mousePosY)
return; return;
@ -148,8 +154,8 @@ GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos)
window->mousePosX = xpos; window->mousePosX = xpos;
window->mousePosY = ypos; window->mousePosY = ypos;
// If we have a locked mouse, do not change cursor position // Do not move physical cursor in locked cursor mode
if (_glfwLibrary.cursorLockWindow == window) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
return; return;
// Update physical cursor position // Update physical cursor position
@ -179,6 +185,62 @@ GLFWAPI void glfwGetScrollOffset(GLFWwindow handle, int* xoffset, int* yoffset)
} }
//========================================================================
// Sets the cursor mode for the specified window
//========================================================================
GLFWAPI void glfwSetCursorMode(GLFWwindow handle, int mode)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return;
}
if (mode != GLFW_CURSOR_NORMAL &&
mode != GLFW_CURSOR_HIDDEN &&
mode != GLFW_CURSOR_CAPTURED)
{
_glfwSetError(GLFW_INVALID_ENUM, NULL);
return;
}
if (window->cursorMode == mode)
return;
int centerPosX = window->width / 2;
int centerPosY = window->height / 2;
if (mode == GLFW_CURSOR_CAPTURED)
{
_glfwPlatformSetMouseCursorPos(window, centerPosX, centerPosY);
}
else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{
if (centerPosX != window->mousePosX || centerPosY != window->mousePosY)
{
_glfwPlatformSetMouseCursorPos(window, centerPosX, centerPosY);
window->mousePosX = centerPosX;
window->mousePosY = centerPosY;
if (_glfwLibrary.mousePosCallback)
{
_glfwLibrary.mousePosCallback(window,
window->mousePosX,
window->mousePosY);
}
}
}
_glfwPlatformSetCursorMode(window, mode);
window->cursorMode = mode;
}
//======================================================================== //========================================================================
// Set callback function for keyboard input // Set callback function for keyboard input
//======================================================================== //========================================================================

View File

@ -181,6 +181,7 @@ struct _GLFWwindow
GLboolean keyRepeat; GLboolean keyRepeat;
GLboolean sysKeysDisabled; // system keys disabled flag GLboolean sysKeysDisabled; // system keys disabled flag
int mousePosX, mousePosY; int mousePosX, mousePosY;
int cursorMode;
int scrollX, scrollY; int scrollX, scrollY;
char mouseButton[GLFW_MOUSE_BUTTON_LAST + 1]; char mouseButton[GLFW_MOUSE_BUTTON_LAST + 1];
char key[GLFW_KEY_LAST + 1]; char key[GLFW_KEY_LAST + 1];
@ -224,7 +225,6 @@ struct _GLFWlibrary
_GLFWwindow* windowListHead; _GLFWwindow* windowListHead;
_GLFWwindow* currentWindow; _GLFWwindow* currentWindow;
_GLFWwindow* activeWindow; _GLFWwindow* activeWindow;
_GLFWwindow* cursorLockWindow;
GLFWerrorfun errorCallback; GLFWerrorfun errorCallback;
GLFWwindowsizefun windowSizeCallback; GLFWwindowsizefun windowSizeCallback;
@ -302,9 +302,8 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y); void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y);
void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformIconifyWindow(_GLFWwindow* window);
void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window);
void _glfwPlatformHideMouseCursor(_GLFWwindow* window);
void _glfwPlatformShowMouseCursor(_GLFWwindow* window);
void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y); void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y);
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
// Event management // Event management
void _glfwPlatformPollEvents(void); void _glfwPlatformPollEvents(void);

View File

@ -766,8 +766,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{ {
// The window was deactivated (or iconified, see above) // The window was deactivated (or iconified, see above)
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
_glfwPlatformShowMouseCursor(window); showMouseCursor(window);
if (window->mode == GLFW_FULLSCREEN) if (window->mode == GLFW_FULLSCREEN)
{ {
@ -789,8 +789,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
{ {
// The window was activated // The window was activated
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
_glfwPlatformHideMouseCursor(window); captureMouseCursor(window);
if (window->mode == GLFW_FULLSCREEN) if (window->mode == GLFW_FULLSCREEN)
{ {
@ -962,8 +962,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (newMouseX != window->Win32.oldMouseX || if (newMouseX != window->Win32.oldMouseX ||
newMouseY != window->Win32.oldMouseY) newMouseY != window->Win32.oldMouseY)
{ {
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
if (_glfwLibrary.activeWindow != window)
return 0;
window->mousePosX += newMouseX - window->mousePosX += newMouseX -
window->Win32.oldMouseX; window->Win32.oldMouseX;
window->mousePosY += newMouseY - window->mousePosY += newMouseY -
@ -977,7 +980,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->Win32.oldMouseX = newMouseX; window->Win32.oldMouseX = newMouseX;
window->Win32.oldMouseY = newMouseY; window->Win32.oldMouseY = newMouseY;
window->Win32.mouseMoved = GL_TRUE; window->Win32.cursorCentered = GL_FALSE;
if (_glfwLibrary.mousePosCallback) if (_glfwLibrary.mousePosCallback)
{ {
@ -1009,8 +1012,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->width = LOWORD(lParam); window->width = LOWORD(lParam);
window->height = HIWORD(lParam); window->height = HIWORD(lParam);
// If the mouse is locked, update the clipping rect // If window is in cursor capture mode, update clipping rect
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
RECT ClipWindowRect; RECT ClipWindowRect;
if (GetWindowRect(window->Win32.handle, &ClipWindowRect)) if (GetWindowRect(window->Win32.handle, &ClipWindowRect))
@ -1032,8 +1035,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->positionX = LOWORD(lParam); window->positionX = LOWORD(lParam);
window->positionY = HIWORD(lParam); window->positionY = HIWORD(lParam);
// If the mouse is locked, update the clipping rect // If window is in cursor capture mode, update clipping rect
if (window == _glfwLibrary.cursorLockWindow) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
RECT ClipWindowRect; RECT ClipWindowRect;
if (GetWindowRect(window->Win32.handle, &ClipWindowRect)) if (GetWindowRect(window->Win32.handle, &ClipWindowRect))
@ -1755,7 +1758,7 @@ void _glfwPlatformPollEvents(void)
MSG msg; MSG msg;
_GLFWwindow* window; _GLFWwindow* window;
window = _glfwLibrary.cursorLockWindow; window = _glfwLibrary.activeWindow;
if (window) if (window)
{ {
window->Win32.mouseMoved = GL_FALSE; window->Win32.mouseMoved = GL_FALSE;
@ -1815,13 +1818,18 @@ void _glfwPlatformPollEvents(void)
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE); _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, GLFW_RELEASE);
} }
// Did we have mouse movement in locked cursor mode? // Did the cursor move in an active window that has captured the cursor
window = _glfwLibrary.cursorLockWindow; window = _glfwLibrary.activeWindow;
if (window && window->Win32.mouseMoved) if (window)
{ {
_glfwPlatformSetMouseCursorPos(window, if (window->cursorMode == GLFW_CURSOR_CAPTURED &&
window->width / 2, !window->Win32.cursorCentered)
window->height / 2); {
_glfwPlatformSetMouseCursorPos(window,
window->width / 2,
window->height / 2);
window->Win32.cursorCentered = GL_TRUE;
}
} }
} }

View File

@ -326,9 +326,10 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height,
_glfwLibrary.windowListHead = window; _glfwLibrary.windowListHead = window;
// Remember window settings // Remember window settings
window->width = width; window->width = width;
window->height = height; window->height = height;
window->mode = mode; window->mode = mode;
window->cursorMode = GLFW_CURSOR_NORMAL;
// Open the actual window and create its context // Open the actual window and create its context
if (!_glfwPlatformOpenWindow(window, &wndconfig, &fbconfig)) if (!_glfwPlatformOpenWindow(window, &wndconfig, &fbconfig))
@ -348,9 +349,9 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height,
} }
// The GLFW specification states that fullscreen windows have the cursor // The GLFW specification states that fullscreen windows have the cursor
// locked by default // captured by default
if (mode == GLFW_FULLSCREEN) if (mode == GLFW_FULLSCREEN)
glfwDisable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_CAPTURED);
// Clearing the front buffer to black to avoid garbage pixels left over // Clearing the front buffer to black to avoid garbage pixels left over
// from previous uses of our bit of VRAM // from previous uses of our bit of VRAM
@ -490,10 +491,6 @@ GLFWAPI void glfwCloseWindow(GLFWwindow handle)
if (window == NULL) if (window == NULL)
return; return;
// Show mouse pointer again (if hidden)
if (window == _glfwLibrary.cursorLockWindow)
glfwEnable(window, GLFW_MOUSE_CURSOR);
// Clear the current context if this window's context is current // Clear the current context if this window's context is current
if (window == _glfwLibrary.currentWindow) if (window == _glfwLibrary.currentWindow)
glfwMakeContextCurrent(NULL); glfwMakeContextCurrent(NULL);

View File

@ -131,9 +131,9 @@ typedef struct _GLFWwindowX11
GLboolean hasEWMH; // True if window manager supports EWMH GLboolean hasEWMH; // True if window manager supports EWMH
GLboolean overrideRedirect; // True if window is OverrideRedirect GLboolean overrideRedirect; // True if window is OverrideRedirect
GLboolean keyboardGrabbed; // True if keyboard is currently grabbed GLboolean keyboardGrabbed; // True if keyboard is currently grabbed
GLboolean pointerGrabbed; // True if pointer is currently grabbed GLboolean cursorGrabbed; // True if cursor is currently grabbed
GLboolean pointerHidden; // True if pointer is currently hidden GLboolean cursorHidden; // True if cursor is currently hidden
GLboolean mouseMoved; GLboolean cursorCentered; // True if cursor was moved since last poll
int cursorPosX, cursorPosY; int cursorPosX, cursorPosY;
} _GLFWwindowX11; } _GLFWwindowX11;

View File

@ -828,6 +828,69 @@ static GLboolean createWindow(_GLFWwindow* window,
} }
//========================================================================
// Hide mouse cursor
//========================================================================
static void hideMouseCursor(_GLFWwindow* window)
{
if (!window->X11.cursorHidden)
{
XDefineCursor(_glfwLibrary.X11.display,
window->X11.handle,
_glfwLibrary.X11.cursor);
window->X11.cursorHidden = GL_TRUE;
}
}
//========================================================================
// Capture mouse cursor
//========================================================================
static void captureMouseCursor(_GLFWwindow* window)
{
hideMouseCursor(window);
if (!window->X11.cursorGrabbed)
{
if (XGrabPointer(_glfwLibrary.X11.display, window->X11.handle, True,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync, GrabModeAsync,
window->X11.handle, None, CurrentTime) ==
GrabSuccess)
{
window->X11.cursorGrabbed = GL_TRUE;
window->X11.cursorCentered = GL_FALSE;
}
}
}
//========================================================================
// Show mouse cursor
//========================================================================
static void showMouseCursor(_GLFWwindow* window)
{
// Un-grab cursor (only in windowed mode: in fullscreen mode we still
// want the mouse grabbed in order to confine the cursor to the window
// area)
if (window->X11.cursorGrabbed)
{
XUngrabPointer(_glfwLibrary.X11.display, CurrentTime);
window->X11.cursorGrabbed = GL_FALSE;
}
// Show cursor
if (window->X11.cursorHidden)
{
XUndefineCursor(_glfwLibrary.X11.display, window->X11.handle);
window->X11.cursorHidden = GL_FALSE;
}
}
//======================================================================== //========================================================================
// Enter fullscreen mode // Enter fullscreen mode
//======================================================================== //========================================================================
@ -916,9 +979,6 @@ static void enterFullscreenMode(_GLFWwindow* window)
window->width, window->height); window->width, window->height);
} }
if (_glfwLibrary.cursorLockWindow == window)
_glfwPlatformHideMouseCursor(window);
// HACK: Try to get window inside viewport (for virtual displays) by moving // HACK: Try to get window inside viewport (for virtual displays) by moving
// the mouse cursor to the upper left corner (and then to the center) // the mouse cursor to the upper left corner (and then to the center)
// This hack should be harmless on saner systems as well // This hack should be harmless on saner systems as well
@ -973,9 +1033,6 @@ static void leaveFullscreenMode(_GLFWwindow* window)
SubstructureNotifyMask | SubstructureRedirectMask, SubstructureNotifyMask | SubstructureRedirectMask,
&event); &event);
} }
if (_glfwLibrary.cursorLockWindow == window)
_glfwPlatformShowMouseCursor(window);
} }
@ -1149,15 +1206,15 @@ static void processSingleEvent(void)
{ {
// The mouse cursor was moved and we didn't do it // The mouse cursor was moved and we didn't do it
if (_glfwLibrary.cursorLockWindow == window) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
{ {
if (window->X11.pointerHidden) if (_glfwLibrary.activeWindow != window)
{ break;
window->mousePosX += event.xmotion.x -
window->X11.cursorPosX; window->mousePosX += event.xmotion.x -
window->mousePosY += event.xmotion.y - window->X11.cursorPosX;
window->X11.cursorPosY; window->mousePosY += event.xmotion.y -
} window->X11.cursorPosY;
} }
else else
{ {
@ -1167,7 +1224,7 @@ static void processSingleEvent(void)
window->X11.cursorPosX = event.xmotion.x; window->X11.cursorPosX = event.xmotion.x;
window->X11.cursorPosY = event.xmotion.y; window->X11.cursorPosY = event.xmotion.y;
window->X11.mouseMoved = GL_TRUE; window->X11.cursorCentered = GL_FALSE;
if (_glfwLibrary.mousePosCallback) if (_glfwLibrary.mousePosCallback)
{ {
@ -1176,6 +1233,7 @@ static void processSingleEvent(void)
window->mousePosY); window->mousePosY);
} }
} }
break; break;
} }
@ -1296,8 +1354,8 @@ static void processSingleEvent(void)
_glfwInputWindowFocus(window, GL_TRUE); _glfwInputWindowFocus(window, GL_TRUE);
if (_glfwLibrary.cursorLockWindow == window) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
_glfwPlatformHideMouseCursor(window); captureMouseCursor(window);
break; break;
} }
@ -1314,8 +1372,8 @@ static void processSingleEvent(void)
_glfwInputWindowFocus(window, GL_FALSE); _glfwInputWindowFocus(window, GL_FALSE);
if (_glfwLibrary.cursorLockWindow == window) if (window->cursorMode == GLFW_CURSOR_CAPTURED)
_glfwPlatformShowMouseCursor(window); showMouseCursor(window);
break; break;
} }
@ -1704,24 +1762,21 @@ void _glfwPlatformPollEvents(void)
{ {
_GLFWwindow* window; _GLFWwindow* window;
// Flag that the cursor has not moved
window = _glfwLibrary.cursorLockWindow;
if (window)
window->X11.mouseMoved = GL_FALSE;
// Process all pending events // Process all pending events
while (XPending(_glfwLibrary.X11.display)) while (XPending(_glfwLibrary.X11.display))
processSingleEvent(); processSingleEvent();
// Did we get mouse movement in fully enabled hidden cursor mode? // Did the cursor move in an active window that has captured the cursor
window = _glfwLibrary.cursorLockWindow; window = _glfwLibrary.activeWindow;
if (window) if (window)
{ {
if (window->X11.mouseMoved && window->X11.pointerHidden) if (window->cursorMode == GLFW_CURSOR_CAPTURED &&
!window->X11.cursorCentered)
{ {
_glfwPlatformSetMouseCursorPos(window, _glfwPlatformSetMouseCursorPos(window,
window->width / 2, window->width / 2,
window->height / 2); window->height / 2);
window->X11.cursorCentered = GL_TRUE;
} }
} }
} }
@ -1743,60 +1798,6 @@ void _glfwPlatformWaitEvents(void)
} }
//========================================================================
// Hide mouse cursor (lock it)
//========================================================================
void _glfwPlatformHideMouseCursor(_GLFWwindow* window)
{
// Hide cursor
if (!window->X11.pointerHidden)
{
XDefineCursor(_glfwLibrary.X11.display,
window->X11.handle,
_glfwLibrary.X11.cursor);
window->X11.pointerHidden = GL_TRUE;
}
// Grab cursor to user window
if (!window->X11.pointerGrabbed)
{
if (XGrabPointer(_glfwLibrary.X11.display, window->X11.handle, True,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync, GrabModeAsync,
window->X11.handle, None, CurrentTime) ==
GrabSuccess)
{
window->X11.pointerGrabbed = GL_TRUE;
}
}
}
//========================================================================
// Show mouse cursor (unlock it)
//========================================================================
void _glfwPlatformShowMouseCursor(_GLFWwindow* window)
{
// Un-grab cursor (only in windowed mode: in fullscreen mode we still
// want the mouse grabbed in order to confine the cursor to the window
// area)
if (window->X11.pointerGrabbed)
{
XUngrabPointer(_glfwLibrary.X11.display, CurrentTime);
window->X11.pointerGrabbed = GL_FALSE;
}
// Show cursor
if (window->X11.pointerHidden)
{
XUndefineCursor(_glfwLibrary.X11.display, window->X11.handle);
window->X11.pointerHidden = GL_FALSE;
}
}
//======================================================================== //========================================================================
// Set physical mouse cursor position // Set physical mouse cursor position
//======================================================================== //========================================================================
@ -1810,3 +1811,24 @@ void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y)
XWarpPointer(_glfwLibrary.X11.display, None, window->X11.handle, 0,0,0,0, x, y); XWarpPointer(_glfwLibrary.X11.display, None, window->X11.handle, 0,0,0,0, x, y);
} }
//========================================================================
// Set physical mouse cursor mode
//========================================================================
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
switch (mode)
{
case GLFW_CURSOR_NORMAL:
showMouseCursor(window);
break;
case GLFW_CURSOR_HIDDEN:
hideMouseCursor(window);
break;
case GLFW_CURSOR_CAPTURED:
captureMouseCursor(window);
break;
}
}

View File

@ -91,7 +91,7 @@ int main(void)
} }
glfwSwapInterval(1); glfwSwapInterval(1);
glfwEnable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_NORMAL);
glfwSetWindowFocusCallback(window_focus_callback); glfwSetWindowFocusCallback(window_focus_callback);
glfwSetKeyCallback(window_key_callback); glfwSetKeyCallback(window_key_callback);

View File

@ -35,19 +35,19 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static GLboolean cursor_enabled = GL_TRUE; static GLboolean cursor_captured = GL_FALSE;
static GLFWwindow window_handle = NULL; static GLFWwindow window_handle = NULL;
static GLboolean open_window(void); static GLboolean open_window(void);
static void toggle_mouse_cursor(GLFWwindow window) static void toggle_mouse_cursor(GLFWwindow window)
{ {
if (cursor_enabled) if (cursor_captured)
glfwDisable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_NORMAL);
else else
glfwEnable(window, GLFW_MOUSE_CURSOR); glfwSetCursorMode(window, GLFW_CURSOR_CAPTURED);
cursor_enabled = !cursor_enabled; cursor_captured = !cursor_captured;
} }
static void mouse_position_callback(GLFWwindow window, int x, int y) static void mouse_position_callback(GLFWwindow window, int x, int y)