Compare commits

...

6 Commits

Author SHA1 Message Date
Mārtiņš Možeiko
fd6bb332be
Merge 11d96a4ab4 into dbadda2683 2025-12-05 13:52:26 -05:00
Camilla Löwy
dbadda2683 Formatting 2025-12-05 13:33:10 +01:00
Camilla Löwy
08449b7183 Linux: Add missing header for ioctl
Fixes #2778
2025-12-04 20:30:12 +01:00
Camilla Löwy
1ce855b0b1 Wayland: Fix missing checks for optional protocol 2025-12-04 20:30:12 +01:00
Camilla Löwy
ebff6606ee Simplify test for shared library build 2025-11-17 22:57:23 +01:00
Mārtiņš Možeiko
11d96a4ab4 Win32: Do the event processing during window resize/move 2025-01-30 01:34:18 -08:00
16 changed files with 212 additions and 51 deletions

View File

@ -38,11 +38,7 @@ set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)") "Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
if (GLFW_LIBRARY_TYPE) if (GLFW_LIBRARY_TYPE)
if (GLFW_LIBRARY_TYPE STREQUAL "SHARED") string(COMPARE EQUAL "${GLFW_LIBRARY_TYPE}" "SHARED" GLFW_BUILD_SHARED_LIBRARY)
set(GLFW_BUILD_SHARED_LIBRARY TRUE)
else()
set(GLFW_BUILD_SHARED_LIBRARY FALSE)
endif()
else() else()
set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS})
endif() endif()

View File

@ -162,6 +162,7 @@ video tutorials.
- Marcel Metz - Marcel Metz
- Liam Middlebrook - Liam Middlebrook
- mightgoyardstill - mightgoyardstill
- Mihail
- Ave Milia - Ave Milia
- Icyllis Milica - Icyllis Milica
- Jonathan Miller - Jonathan Miller

View File

@ -146,11 +146,14 @@ information on what to include when reporting a bug.
from a modal to the content area from a modal to the content area
- [Wayland] Bugfix: free modules at end of terminate function to resolve - [Wayland] Bugfix: free modules at end of terminate function to resolve
potential segmentation fault (#2744) potential segmentation fault (#2744)
- [Wayland] Bugfix: Confining or disabling the cursor could segfault on
compositors without `pointer-constraints-unstable-v1`
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631) - [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766) - [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale - [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
less than 1 (#2754) less than 1 (#2754)
- [X11] Bugfix: Clamp width and height to >= 1 to prevent BadValue error and app exit - [X11] Bugfix: Clamp width and height to >= 1 to prevent BadValue error and app exit
- [Linux] Bugfix: The header for `ioctl` was only implicitly included (#2778)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface` - [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to

View File

@ -153,10 +153,23 @@ the `VK_KHR_xlib_surface` extension. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms. `GLFW_FALSE`. This is ignored on other platforms.
#### Windows specific init hints {#init_hints_windows}
@anchor GLFW_WIN32_MESSAGES_IN_FIBER_hint
__GLFW_WIN32_MESSAGES_IN_FIBER__ specifies whether to use separate fiber for
processing Windows message, and not the main thread. This allows to unblock
window move and resize operations, and application can do updates and rendering
in its main loop. __Warning__ - setting this hint is not safe for environments
or frameworks where stack inspection is required (for example, moving garbage
collected languages such as Java or C#). Set this with @ref glfwInitHint.
#### Supported and default values {#init_hints_values} #### Supported and default values {#init_hints_values}
Initialization hint | Default value | Supported values Initialization hint | Default value | Supported values
-------------------------------- | ------------------------------- | ---------------- --------------------------------- | ------------------------------- | ----------------
--------------------------------- | ------------------------------- | ----------------
@ref GLFW_PLATFORM | `GLFW_ANY_PLATFORM` | `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL` @ref GLFW_PLATFORM | `GLFW_ANY_PLATFORM` | `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_ANGLE_PLATFORM_TYPE | `GLFW_ANGLE_PLATFORM_TYPE_NONE` | `GLFW_ANGLE_PLATFORM_TYPE_NONE`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGL`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGLES`, `GLFW_ANGLE_PLATFORM_TYPE_D3D9`, `GLFW_ANGLE_PLATFORM_TYPE_D3D11`, `GLFW_ANGLE_PLATFORM_TYPE_VULKAN` or `GLFW_ANGLE_PLATFORM_TYPE_METAL` @ref GLFW_ANGLE_PLATFORM_TYPE | `GLFW_ANGLE_PLATFORM_TYPE_NONE` | `GLFW_ANGLE_PLATFORM_TYPE_NONE`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGL`, `GLFW_ANGLE_PLATFORM_TYPE_OPENGLES`, `GLFW_ANGLE_PLATFORM_TYPE_D3D9`, `GLFW_ANGLE_PLATFORM_TYPE_D3D11`, `GLFW_ANGLE_PLATFORM_TYPE_VULKAN` or `GLFW_ANGLE_PLATFORM_TYPE_METAL`
@ -164,6 +177,7 @@ Initialization hint | Default value | Supported v
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR` @ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
@ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` @ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WIN32_MESSAGES_IN_FIBER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
### Runtime platform selection {#platform} ### Runtime platform selection {#platform}

View File

@ -1328,6 +1328,11 @@ extern "C" {
* Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint). * Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
*/ */
#define GLFW_WAYLAND_LIBDECOR 0x00053001 #define GLFW_WAYLAND_LIBDECOR 0x00053001
/*! @brief Windows specific init hint.
*
* Windows specific [init hint](@ref GLFW_WIN32_MESSAGES_IN_FIBER_hint).
*/
#define GLFW_WIN32_MESSAGES_IN_FIBER 0x00054001
/*! @} */ /*! @} */
/*! @addtogroup init /*! @addtogroup init
@ -1604,6 +1609,10 @@ typedef void (* GLFWerrorfun)(int error_code, const char* description);
* @param[in] ypos The new y-coordinate, in screen coordinates, of the * @param[in] ypos The new y-coordinate, in screen coordinates, of the
* upper-left corner of the content area of the window. * upper-left corner of the content area of the window.
* *
* @remark @win32 On Windows moving or resizing of window will block event
* processing. Workaround for this is @ref GLFW_WIN32_MESSAGES_IN_FIBER init
* hint.
*
* @sa @ref window_pos * @sa @ref window_pos
* @sa @ref glfwSetWindowPosCallback * @sa @ref glfwSetWindowPosCallback
* *
@ -1625,6 +1634,10 @@ typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);
* @param[in] width The new width, in screen coordinates, of the window. * @param[in] width The new width, in screen coordinates, of the window.
* @param[in] height The new height, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window.
* *
* @remark @win32 On Windows moving or resizing of window will block event
* processing. Workaround for this is @ref GLFW_WIN32_MESSAGES_IN_FIBER init
* hint.
*
* @sa @ref window_size * @sa @ref window_size
* @sa @ref glfwSetWindowSizeCallback * @sa @ref glfwSetWindowSizeCallback
* *

View File

@ -66,6 +66,10 @@ static _GLFWinitconfig _glfwInitHints =
{ {
.libdecorMode = GLFW_WAYLAND_PREFER_LIBDECOR .libdecorMode = GLFW_WAYLAND_PREFER_LIBDECOR
}, },
.win32 =
{
.msgInFiber = GLFW_FALSE,
}
}; };
// The allocation function used when no custom allocator is set // The allocation function used when no custom allocator is set
@ -462,6 +466,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
case GLFW_WAYLAND_LIBDECOR: case GLFW_WAYLAND_LIBDECOR:
_glfwInitHints.wl.libdecorMode = value; _glfwInitHints.wl.libdecorMode = value;
return; return;
case GLFW_WIN32_MESSAGES_IN_FIBER:
_glfwInitHints.win32.msgInFiber = value;
return;
} }
_glfwInputError(GLFW_INVALID_ENUM, _glfwInputError(GLFW_INVALID_ENUM,

View File

@ -388,6 +388,9 @@ struct _GLFWinitconfig
struct { struct {
int libdecorMode; int libdecorMode;
} wl; } wl;
struct {
GLFWbool msgInFiber;
} win32;
}; };
// Window configuration // Window configuration

View File

@ -32,6 +32,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/ioctl.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>

View File

@ -366,7 +366,6 @@ static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
// //
static GLFWbool createHelperWindow(void) static GLFWbool createHelperWindow(void)
{ {
MSG msg;
WNDCLASSEXW wc = { sizeof(wc) }; WNDCLASSEXW wc = { sizeof(wc) };
wc.style = CS_OWNDC; wc.style = CS_OWNDC;
@ -417,11 +416,19 @@ static GLFWbool createHelperWindow(void)
DEVICE_NOTIFY_WINDOW_HANDLE); DEVICE_NOTIFY_WINDOW_HANDLE);
} }
if (_glfw.hints.init.win32.msgInFiber)
{
SwitchToFiber(_glfw.win32.messageFiber);
}
else
{
MSG msg;
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessageW(&msg); DispatchMessageW(&msg);
} }
}
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -528,7 +535,8 @@ void _glfwUpdateKeyNamesWin32(void)
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
{ {
const UINT vks[] = { const UINT vks[] =
{
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
@ -594,6 +602,45 @@ BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
} }
void _glfwPollMessageLoopWin32(void)
{
_GLFWwindow* window;
MSG msg;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
}
// Windows message dispatch fiber
void CALLBACK messageFiberProc(LPVOID lpFiberParameter)
{
(void)lpFiberParameter;
for (;;)
{
_glfwPollMessageLoopWin32();
SwitchToFiber(_glfw.win32.mainFiber);
}
}
GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
{ {
const _GLFWplatform win32 = const _GLFWplatform win32 =
@ -691,6 +738,17 @@ int _glfwInitWin32(void)
else else
SetProcessDPIAware(); SetProcessDPIAware();
if (_glfw.hints.init.win32.msgInFiber)
{
_glfw.win32.mainFiber = ConvertThreadToFiber(NULL);
if (!_glfw.win32.mainFiber)
return GLFW_FALSE;
_glfw.win32.messageFiber = CreateFiber(0, &messageFiberProc, NULL);
if (!_glfw.win32.messageFiber)
return GLFW_FALSE;
}
if (!createHelperWindow()) if (!createHelperWindow())
return GLFW_FALSE; return GLFW_FALSE;
@ -713,6 +771,12 @@ void _glfwTerminateWin32(void)
if (_glfw.win32.mainWindowClass) if (_glfw.win32.mainWindowClass)
UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance); UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance);
if (_glfw.hints.init.win32.msgInFiber)
{
DeleteFiber(_glfw.win32.messageFiber);
ConvertFiberToThread();
}
_glfw_free(_glfw.win32.clipboardString); _glfw_free(_glfw.win32.clipboardString);
_glfw_free(_glfw.win32.rawInput); _glfw_free(_glfw.win32.rawInput);

View File

@ -375,6 +375,11 @@ typedef struct _GLFWwindowWin32
int lastCursorPosX, lastCursorPosY; int lastCursorPosX, lastCursorPosY;
// The last received high surrogate when decoding pairs of UTF-16 messages // The last received high surrogate when decoding pairs of UTF-16 messages
WCHAR highSurrogate; WCHAR highSurrogate;
// If user pressed mouse button on window title bar
UINT ncMouseButton;
LPARAM ncMousePos;
} _GLFWwindowWin32; } _GLFWwindowWin32;
// Win32-specific global data // Win32-specific global data
@ -403,6 +408,9 @@ typedef struct _GLFWlibraryWin32
// The cursor handle to use to hide the cursor (NULL or a transparent cursor) // The cursor handle to use to hide the cursor (NULL or a transparent cursor)
HCURSOR blankCursor; HCURSOR blankCursor;
LPVOID messageFiber;
LPVOID mainFiber;
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_DirectInput8Create Create; PFN_DirectInput8Create Create;
@ -519,6 +527,7 @@ void _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity);
void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled); void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedWin32(void); GLFWbool _glfwRawMouseMotionSupportedWin32(void);
void _glfwPollMessageLoopWin32(void);
void _glfwPollEventsWin32(void); void _glfwPollEventsWin32(void);
void _glfwWaitEventsWin32(void); void _glfwWaitEventsWin32(void);
void _glfwWaitEventsTimeoutWin32(double timeout); void _glfwWaitEventsTimeoutWin32(double timeout);

View File

@ -853,11 +853,46 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
return 0; return 0;
} }
case WM_NCLBUTTONDOWN:
{
if (wParam == HTCAPTION)
{
window->win32.ncMouseButton = uMsg;
window->win32.ncMousePos = lParam;
return 0;
}
break;
}
case WM_NCMOUSEMOVE:
{
if (window->win32.ncMouseButton)
{
if (GET_X_LPARAM(window->win32.ncMousePos) != GET_X_LPARAM(lParam) ||
GET_Y_LPARAM(window->win32.ncMousePos) != GET_Y_LPARAM(lParam))
{
DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos);
window->win32.ncMouseButton = 0;
}
}
break;
}
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{ {
const int x = GET_X_LPARAM(lParam); const int x = GET_X_LPARAM(lParam);
const int y = GET_Y_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam);
if (window->win32.ncMouseButton)
{
if (GET_X_LPARAM(window->win32.ncMousePos) != x ||
GET_Y_LPARAM(window->win32.ncMousePos) != y)
{
DefWindowProcW(hWnd, window->win32.ncMouseButton, HTCAPTION, window->win32.ncMousePos);
window->win32.ncMouseButton = 0;
}
}
if (!window->win32.cursorTracked) if (!window->win32.cursorTracked)
{ {
TRACKMOUSEEVENT tme; TRACKMOUSEEVENT tme;
@ -998,6 +1033,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
else if (window->cursorMode == GLFW_CURSOR_CAPTURED) else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
releaseCursor(); releaseCursor();
if (_glfw.hints.init.win32.msgInFiber)
SetTimer(hWnd, 1, 1, NULL);
break; break;
} }
@ -1014,6 +1051,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
else if (window->cursorMode == GLFW_CURSOR_CAPTURED) else if (window->cursorMode == GLFW_CURSOR_CAPTURED)
captureCursor(window); captureCursor(window);
if (_glfw.hints.init.win32.msgInFiber)
KillTimer(hWnd, 1);
break;
}
case WM_TIMER:
{
if (_glfw.hints.init.win32.msgInFiber && wParam == 1)
SwitchToFiber(_glfw.win32.mainFiber);
break; break;
} }
@ -2088,31 +2134,13 @@ GLFWbool _glfwRawMouseMotionSupportedWin32(void)
void _glfwPollEventsWin32(void) void _glfwPollEventsWin32(void)
{ {
MSG msg;
HWND handle; HWND handle;
_GLFWwindow* window; _GLFWwindow* window;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) if (_glfw.hints.init.win32.msgInFiber)
{ SwitchToFiber(_glfw.win32.messageFiber);
if (msg.message == WM_QUIT)
{
// NOTE: While GLFW does not itself post WM_QUIT, other processes
// may post it to this one, for example Task Manager
// HACK: Treat WM_QUIT as a close on all windows
window = _glfw.windowListHead;
while (window)
{
_glfwInputWindowCloseRequest(window);
window = window->next;
}
}
else else
{ _glfwPollMessageLoopWin32();
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
// HACK: Release modifier keys that the system did not emit KEYUP for // HACK: Release modifier keys that the system did not emit KEYUP for
// NOTE: Shift keys on Windows tend to "stick" when both are pressed as // NOTE: Shift keys on Windows tend to "stick" when both are pressed as

View File

@ -979,7 +979,8 @@ void _glfwTerminateWayland(void)
if (_glfw.wl.cursorTimerfd >= 0) if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd); close(_glfw.wl.cursorTimerfd);
// Free modules only after all wayland termination functions are called // Free modules only after all Wayland termination functions are called
if (_glfw.egl.handle) if (_glfw.egl.handle)
{ {
_glfwPlatformFreeModule(_glfw.egl.handle); _glfwPlatformFreeModule(_glfw.egl.handle);
@ -1003,6 +1004,7 @@ void _glfwTerminateWayland(void)
_glfwPlatformFreeModule(_glfw.wl.xkb.handle); _glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL; _glfw.wl.xkb.handle = NULL;
} }
if (_glfw.wl.cursor.handle) if (_glfw.wl.cursor.handle)
{ {
_glfwPlatformFreeModule(_glfw.wl.cursor.handle); _glfwPlatformFreeModule(_glfw.wl.cursor.handle);

View File

@ -136,18 +136,22 @@ struct wl_output;
#define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl; #define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl;
#define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl; #define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl;
struct wl_cursor_image { struct wl_cursor_image
{
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t hotspot_x; uint32_t hotspot_x;
uint32_t hotspot_y; uint32_t hotspot_y;
uint32_t delay; uint32_t delay;
}; };
struct wl_cursor {
struct wl_cursor
{
unsigned int image_count; unsigned int image_count;
struct wl_cursor_image** images; struct wl_cursor_image** images;
char* name; char* name;
}; };
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*); typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*); typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*); typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);

View File

@ -1692,7 +1692,8 @@ static void keyboardHandleKeymap(void* userData,
} }
mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (mapStr == MAP_FAILED) { if (mapStr == MAP_FAILED)
{
close(fd); close(fd);
return; return;
} }
@ -1838,7 +1839,9 @@ static void keyboardHandleKey(void* userData,
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000; timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
} }
} else if (scancode == _glfw.wl.keyRepeatScancode) { }
else if (scancode == _glfw.wl.keyRepeatScancode)
{
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
} }
@ -2974,10 +2977,16 @@ static void lockPointer(_GLFWwindow* window)
if (!_glfw.wl.relativePointerManager) if (!_glfw.wl.relativePointerManager)
{ {
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support pointer locking"); "Wayland: The compositor does not support relative pointer motion");
return; return;
} }
if (!_glfw.wl.pointerConstraints)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support locking the pointer");
}
window->wl.relativePointer = window->wl.relativePointer =
zwp_relative_pointer_manager_v1_get_relative_pointer( zwp_relative_pointer_manager_v1_get_relative_pointer(
_glfw.wl.relativePointerManager, _glfw.wl.relativePointerManager,
@ -3025,6 +3034,12 @@ static const struct zwp_confined_pointer_v1_listener confinedPointerListener =
static void confinePointer(_GLFWwindow* window) static void confinePointer(_GLFWwindow* window)
{ {
if (!_glfw.wl.pointerConstraints)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE,
"Wayland: The compositor does not support confining the pointer");
}
window->wl.confinedPointer = window->wl.confinedPointer =
zwp_pointer_constraints_v1_confine_pointer( zwp_pointer_constraints_v1_confine_pointer(
_glfw.wl.pointerConstraints, _glfw.wl.pointerConstraints,

View File

@ -151,7 +151,8 @@ void _glfwPollMonitorsX11(void)
} }
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
if (!ci) { if (!ci)
{
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
continue; continue;
} }

View File

@ -2207,7 +2207,7 @@ void _glfwGetWindowSizeX11(_GLFWwindow* window, int* width, int* height)
void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height) void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height)
{ {
// The dimensions must be nonzero, or a BadValue error results. // The dimensions must be nonzero, or a BadValue error results
width = _glfw_max(1, width); width = _glfw_max(1, width);
height = _glfw_max(1, height); height = _glfw_max(1, height);