Merge branch 'master' into single-GLRC

This commit is contained in:
Lukas Hermanns 2018-05-02 15:16:54 +02:00
commit c1b208d42c
11 changed files with 241 additions and 174 deletions

View File

@ -1,15 +1,9 @@
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 3.0)
project(GLFW C) project(GLFW C)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF) set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
# Until all major package systems have moved to CMake 3,
# we stick with the older INSTALL_NAME_DIR mechanism
cmake_policy(SET CMP0042 OLD)
endif()
if (NOT CMAKE_VERSION VERSION_LESS "3.1") if (NOT CMAKE_VERSION VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
endif() endif()

View File

@ -365,10 +365,10 @@ allow calls from any thread in future releases.
@subsection compatibility Version compatibility @subsection compatibility Version compatibility
GLFW guarantees source and binary backward compatibility with earlier minor GLFW uses [Semantic Versioning](https://semver.org/). This guarantees source
versions of the API. This means that you can drop in a newer version of the and binary backward compatibility with earlier minor versions of the API. This
library and existing programs will continue to compile and existing binaries means that you can drop in a newer version of the library and existing programs
will continue to run. will continue to compile and existing binaries will continue to run.
Once a function or constant has been added, the signature of that function or Once a function or constant has been added, the signature of that function or
value of that constant will remain unchanged until the next major version of value of that constant will remain unchanged until the next major version of

View File

@ -455,6 +455,7 @@ int main(int argc, char* argv[])
glfwPollEvents(); glfwPollEvents();
} }
glfwTerminate();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View File

@ -4697,7 +4697,7 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid);
* This function may be called from the joystick callback, even for a joystick * This function may be called from the joystick callback, even for a joystick
* that is being disconnected. * that is being disconnected.
* *
* @param[in] joystick The joystick whose pointer to set. * @param[in] jid The joystick whose pointer to set.
* @param[in] pointer The new value. * @param[in] pointer The new value.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
@ -4722,7 +4722,7 @@ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
* This function may be called from the joystick callback, even for a joystick * This function may be called from the joystick callback, even for a joystick
* that is being disconnected. * that is being disconnected.
* *
* @param[in] joystick The joystick whose pointer to return. * @param[in] jid The joystick whose pointer to return.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *

View File

@ -128,6 +128,32 @@ static void updateCursorImage(_GLFWwindow* window)
hideCursor(window); hideCursor(window);
} }
// Apply chosen cursor mode to a focused window
//
static void updateCursorMode(_GLFWwindow* window)
{
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
_glfw.ns.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
centerCursor(window);
CGAssociateMouseAndMouseCursorPosition(false);
}
else if (_glfw.ns.disabledCursorWindow == window)
{
_glfw.ns.disabledCursorWindow = NULL;
CGAssociateMouseAndMouseCursorPosition(true);
_glfwPlatformSetCursorPos(window,
_glfw.ns.restoreCursorPosX,
_glfw.ns.restoreCursorPosY);
}
if (cursorInClientArea(window))
updateCursorImage(window);
}
// Transforms the specified y-coordinate between the CG display and NS screen // Transforms the specified y-coordinate between the CG display and NS screen
// coordinate systems // coordinate systems
// //
@ -321,7 +347,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
centerCursor(window); centerCursor(window);
_glfwInputWindowFocus(window, GLFW_TRUE); _glfwInputWindowFocus(window, GLFW_TRUE);
_glfwPlatformSetCursorMode(window, window->cursorMode); updateCursorMode(window);
} }
- (void)windowDidResignKey:(NSNotification *)notification - (void)windowDidResignKey:(NSNotification *)notification
@ -1638,26 +1664,8 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{ {
if (mode == GLFW_CURSOR_DISABLED) if (_glfwPlatformWindowFocused(window))
{ updateCursorMode(window);
_glfw.ns.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.ns.restoreCursorPosX,
&_glfw.ns.restoreCursorPosY);
centerCursor(window);
CGAssociateMouseAndMouseCursorPosition(false);
}
else if (_glfw.ns.disabledCursorWindow == window)
{
_glfw.ns.disabledCursorWindow = NULL;
CGAssociateMouseAndMouseCursorPosition(true);
_glfwPlatformSetCursorPos(window,
_glfw.ns.restoreCursorPosX,
_glfw.ns.restoreCursorPosY);
}
if (cursorInClientArea(window))
updateCursorImage(window);
} }
const char* _glfwPlatformGetScancodeName(int scancode) const char* _glfwPlatformGetScancodeName(int scancode)

View File

@ -57,37 +57,6 @@ static _GLFWinitconfig _glfwInitHints =
} }
}; };
// Returns a generic string representation of the specified error
//
static const char* getErrorString(int code)
{
switch (code)
{
case GLFW_NOT_INITIALIZED:
return "The GLFW library is not initialized";
case GLFW_NO_CURRENT_CONTEXT:
return "There is no current context";
case GLFW_INVALID_ENUM:
return "Invalid argument for enum parameter";
case GLFW_INVALID_VALUE:
return "Invalid value for parameter";
case GLFW_OUT_OF_MEMORY:
return "Out of memory";
case GLFW_API_UNAVAILABLE:
return "The requested API is unavailable";
case GLFW_VERSION_UNAVAILABLE:
return "The requested API version is unavailable";
case GLFW_PLATFORM_ERROR:
return "An undocumented platform-specific error occurred";
case GLFW_FORMAT_UNAVAILABLE:
return "The requested format is unavailable";
case GLFW_NO_WINDOW_CONTEXT:
return "The specified window has no context";
default:
return "ERROR: UNKNOWN GLFW ERROR";
}
}
// Terminate the library // Terminate the library
// //
static void terminate(void) static void terminate(void)
@ -173,7 +142,30 @@ void _glfwInputError(int code, const char* format, ...)
description[sizeof(description) - 1] = '\0'; description[sizeof(description) - 1] = '\0';
} }
else else
strcpy(description, getErrorString(code)); {
if (code == GLFW_NOT_INITIALIZED)
strcpy(description, "The GLFW library is not initialized");
else if (code == GLFW_NO_CURRENT_CONTEXT)
strcpy(description, "There is no current context");
else if (code == GLFW_INVALID_ENUM)
strcpy(description, "Invalid argument for enum parameter");
else if (code == GLFW_INVALID_VALUE)
strcpy(description, "Invalid value for parameter");
else if (code == GLFW_OUT_OF_MEMORY)
strcpy(description, "Out of memory");
else if (code == GLFW_API_UNAVAILABLE)
strcpy(description, "The requested API is unavailable");
else if (code == GLFW_VERSION_UNAVAILABLE)
strcpy(description, "The requested API version is unavailable");
else if (code == GLFW_PLATFORM_ERROR)
strcpy(description, "A platform-specific error occurred");
else if (code == GLFW_FORMAT_UNAVAILABLE)
strcpy(description, "The requested format is unavailable");
else if (code == GLFW_NO_WINDOW_CONTEXT)
strcpy(description, "The specified window has no context");
else
strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
}
if (_glfw.initialized) if (_glfw.initialized)
{ {

View File

@ -509,9 +509,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
_glfwPlatformGetCursorPos(window, _glfwPlatformGetCursorPos(window,
&window->virtualCursorPosX, &window->virtualCursorPosX,
&window->virtualCursorPosY); &window->virtualCursorPosY);
_glfwPlatformSetCursorMode(window, value);
if (_glfwPlatformWindowFocused(window))
_glfwPlatformSetCursorMode(window, value);
} }
else if (mode == GLFW_STICKY_KEYS) else if (mode == GLFW_STICKY_KEYS)
{ {

View File

@ -120,6 +120,8 @@ typedef struct
HRGN hRgnBlur; HRGN hRgnBlur;
BOOL fTransitionOnMaximized; BOOL fTransitionOnMaximized;
} DWM_BLURBEHIND; } DWM_BLURBEHIND;
#else
#include <dwmapi.h>
#endif /*Windows Vista*/ #endif /*Windows Vista*/
#ifndef DPI_ENUMS_DECLARED #ifndef DPI_ENUMS_DECLARED

View File

@ -235,26 +235,6 @@ static void centerCursor(_GLFWwindow* window)
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); _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)
{
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 its cursor mode // Updates the cursor image according to its cursor mode
// //
static void updateCursorImage(_GLFWwindow* window) static void updateCursorImage(_GLFWwindow* window)
@ -286,6 +266,67 @@ static void updateClipRect(_GLFWwindow* window)
ClipCursor(NULL); ClipCursor(NULL);
} }
// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
_glfw.win32.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
updateCursorImage(window);
centerCursor(window);
updateClipRect(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register raw input device");
}
}
// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
_glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
updateCursorImage(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to remove raw input device");
}
}
// Returns whether the cursor is in the client area of the specified window
//
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);
}
// Update native window styles to match attributes // Update native window styles to match attributes
// //
static void updateWindowStyles(const _GLFWwindow* window) static void updateWindowStyles(const _GLFWwindow* window)
@ -575,7 +616,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (lParam == 0 && window->win32.frameAction) if (lParam == 0 && window->win32.frameAction)
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); disableCursor(window);
window->win32.frameAction = GLFW_FALSE; window->win32.frameAction = GLFW_FALSE;
} }
@ -593,7 +634,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break; break;
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); disableCursor(window);
return 0; return 0;
} }
@ -601,7 +642,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_KILLFOCUS: case WM_KILLFOCUS:
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); enableCursor(window);
if (window->monitor && window->autoIconify) if (window->monitor && window->autoIconify)
_glfwPlatformIconifyWindow(window); _glfwPlatformIconifyWindow(window);
@ -857,10 +898,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
case WM_ENTERMENULOOP: case WM_ENTERMENULOOP:
{ {
// HACK: Postpone cursor disabling while the user is moving or // HACK: Enable the cursor while the user is moving or
// resizing the window or using the menu // resizing the window or using the window menu
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); enableCursor(window);
break; break;
} }
@ -871,7 +912,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
// HACK: Disable the cursor once the user is done moving or // HACK: Disable the cursor once the user is done moving or
// resizing the window or using the menu // resizing the window or using the menu
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); disableCursor(window);
break; break;
} }
@ -1772,39 +1813,12 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{ {
if (mode == GLFW_CURSOR_DISABLED) if (mode == GLFW_CURSOR_DISABLED)
{ {
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle }; if (_glfwPlatformWindowFocused(window))
disableCursor(window);
_glfw.win32.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.win32.restoreCursorPosX,
&_glfw.win32.restoreCursorPosY);
centerCursor(window);
updateClipRect(window);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register raw input device");
}
} }
else if (_glfw.win32.disabledCursorWindow == window) else if (_glfw.win32.disabledCursorWindow == window)
{ enableCursor(window);
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL }; else if (cursorInClientArea(window))
_glfw.win32.disabledCursorWindow = NULL;
updateClipRect(NULL);
_glfwPlatformSetCursorPos(window,
_glfw.win32.restoreCursorPosX,
_glfw.win32.restoreCursorPosY);
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to remove raw input device");
}
}
if (cursorInClientArea(window))
updateCursorImage(window); updateCursorImage(window);
} }

View File

@ -479,7 +479,11 @@ static GLFWbool initExtensions(void)
&_glfw.x11.vidmode.errorBase); &_glfw.x11.vidmode.errorBase);
} }
#if defined(__CYGWIN__)
_glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
#else
_glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
#endif
if (_glfw.x11.xi.handle) if (_glfw.x11.xi.handle)
{ {
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
@ -505,7 +509,11 @@ static GLFWbool initExtensions(void)
} }
} }
#if defined(__CYGWIN__)
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
#else
_glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
#endif
if (_glfw.x11.randr.handle) if (_glfw.x11.randr.handle)
{ {
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
@ -593,7 +601,11 @@ static GLFWbool initExtensions(void)
RROutputChangeNotifyMask); RROutputChangeNotifyMask);
} }
#if defined(__CYGWIN__)
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
#else
_glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
#endif
if (_glfw.x11.xcursor.handle) if (_glfw.x11.xcursor.handle)
{ {
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
@ -604,7 +616,11 @@ static GLFWbool initExtensions(void)
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
} }
#if defined(__CYGWIN__)
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
#else
_glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
#endif
if (_glfw.x11.xinerama.handle) if (_glfw.x11.xinerama.handle)
{ {
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
@ -644,14 +660,22 @@ static GLFWbool initExtensions(void)
} }
} }
#if defined(__CYGWIN__)
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
#else
_glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
#endif
if (_glfw.x11.x11xcb.handle) if (_glfw.x11.x11xcb.handle)
{ {
_glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
_glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
} }
#if defined(__CYGWIN__)
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
#else
_glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
#endif
if (_glfw.x11.xrender.handle) if (_glfw.x11.xrender.handle)
{ {
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
@ -1024,6 +1048,24 @@ void _glfwPlatformTerminate(void)
_glfw.x11.xinerama.handle = NULL; _glfw.x11.xinerama.handle = NULL;
} }
if (_glfw.x11.xrender.handle)
{
_glfw_dlclose(_glfw.x11.xrender.handle);
_glfw.x11.xrender.handle = NULL;
}
if (_glfw.x11.vidmode.handle)
{
_glfw_dlclose(_glfw.x11.vidmode.handle);
_glfw.x11.vidmode.handle = NULL;
}
if (_glfw.x11.xi.handle)
{
_glfw_dlclose(_glfw.x11.xi.handle);
_glfw.x11.xi.handle = NULL;
}
// NOTE: These need to be unloaded after XCloseDisplay, as they register // NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function // cleanup callbacks that get called by that function
_glfwTerminateEGL(); _glfwTerminateEGL();

View File

@ -571,6 +571,61 @@ static void updateCursorImage(_GLFWwindow* window)
} }
} }
// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISetMask(mask, XI_RawMotion);
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = window;
_glfwPlatformGetCursorPos(window,
&_glfw.x11.restoreCursorPosX,
&_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
centerCursor(window);
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
window->x11.handle,
_glfw.x11.hiddenCursorHandle,
CurrentTime);
}
// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
if (_glfw.x11.xi.available)
{
XIEventMask em;
unsigned char mask[] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime);
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
updateCursorImage(window);
}
// Create the X11 window (and its colormap) // Create the X11 window (and its colormap)
// //
static GLFWbool createNativeWindow(_GLFWwindow* window, static GLFWbool createNativeWindow(_GLFWwindow* window,
@ -1432,7 +1487,7 @@ static void processEvent(XEvent *event)
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
// ignore the defined cursor for hidden cursor mode // ignore the defined cursor for hidden cursor mode
if (window->cursorMode == GLFW_CURSOR_HIDDEN) if (window->cursorMode == GLFW_CURSOR_HIDDEN)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_HIDDEN); updateCursorImage(window);
_glfwInputCursorEnter(window, GLFW_TRUE); _glfwInputCursorEnter(window, GLFW_TRUE);
return; return;
@ -1725,7 +1780,7 @@ static void processEvent(XEvent *event)
case FocusIn: case FocusIn:
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); disableCursor(window);
if (event->xfocus.mode == NotifyGrab || if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab) event->xfocus.mode == NotifyUngrab)
@ -1745,7 +1800,7 @@ static void processEvent(XEvent *event)
case FocusOut: case FocusOut:
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
_glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); enableCursor(window);
if (event->xfocus.mode == NotifyGrab || if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab) event->xfocus.mode == NotifyUngrab)
@ -2708,53 +2763,14 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{ {
if (mode == GLFW_CURSOR_DISABLED) if (mode == GLFW_CURSOR_DISABLED)
{ {
if (_glfw.x11.xi.available) if (_glfwPlatformWindowFocused(window))
{ disableCursor(window);
XIEventMask em;
unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISetMask(mask, XI_RawMotion);
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = window;
_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.hiddenCursorHandle,
CurrentTime);
} }
else if (_glfw.x11.disabledCursorWindow == window) else if (_glfw.x11.disabledCursorWindow == window)
{ enableCursor(window);
if (_glfw.x11.xi.available) else
{ updateCursorImage(window);
XIEventMask em;
unsigned char mask[] = { 0 };
em.deviceid = XIAllMasterDevices;
em.mask_len = sizeof(mask);
em.mask = mask;
XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
}
_glfw.x11.disabledCursorWindow = NULL;
XUngrabPointer(_glfw.x11.display, CurrentTime);
_glfwPlatformSetCursorPos(window,
_glfw.x11.restoreCursorPosX,
_glfw.x11.restoreCursorPosY);
}
updateCursorImage(window);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }