Compare commits

...

11 Commits

Author SHA1 Message Date
halx99
46d9699cc4
Merge f1284eb884 into dbadda2683 2025-12-12 08:22:10 -06: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
Doug Binks
162896e5b9
Wayland: free modules at end of terminate function
- Fixes #2744
2025-11-14 16:35:47 +00:00
Doug Binks
936307558e X11: Clamp w,h in glfwSetWindowSize to >= 1
-  prevents BadValue error and program exit
2025-11-08 10:37:52 +00:00
Drew Weymouth
4df5129529 X11: check crtcInfo for NULL when polling monitors 2025-11-07 17:39:26 +00:00
Ivor Wanders
6de70d8252 X11: Prevent BadWindow when creating small windows
The glfwCreateWindow function ensures that the width and height are
at least greater or equal than zero, but on X11 it is invalid to
create a window with dimensions that equal zero, see [1].

This change ensures that the dimensions passed to XCreateWindow are
at least 1 by 1.

This issue was detected in [2], where a call to glfwCreateWindow
was done to request a 1x1 window, with a _glfw.x11.contentScaleX of
less than 1.0 (0.958333) this results in a request for a 0x0 window
which then causes an BadWindow error from X11.

[1]: e003f52661/specs/libX11/CH03.xml (L1333-1337)
[2]: https://github.com/WerWolv/ImHex/pull/2390
2025-11-07 17:24:35 +00:00
halx99
f1284eb884 Fix create as child window style 2024-03-01 21:49:49 +08:00
halx99
a94c9782d5 Add create glfw window as child support for win32 2024-03-01 21:49:49 +08:00
16 changed files with 127 additions and 43 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
@ -282,10 +283,12 @@ video tutorials.
- Corentin Wallez - Corentin Wallez
- Torsten Walluhn - Torsten Walluhn
- Patrick Walton - Patrick Walton
- Ivor Wanders
- Jim Wang - Jim Wang
- Xo Wang - Xo Wang
- Andre Weissflog - Andre Weissflog
- Jay Weisskopf - Jay Weisskopf
- Drew Weymouth
- Frank Wille - Frank Wille
- Andy Williams - Andy Williams
- Joel Winarske - Joel Winarske

View File

@ -144,7 +144,16 @@ information on what to include when reporting a bug.
a modal to a fallback decoration a modal to a fallback decoration
- [Wayland] Bugfix: The cursor position was not updated when clicking through - [Wayland] Bugfix: The cursor position was not updated when clicking through
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
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: Prevent BadWindow when creating small windows with a content scale
less than 1 (#2754)
- [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

@ -1129,6 +1129,7 @@ extern "C" {
/*! @brief Win32 specific [window hint](@ref GLFW_WIN32_SHOWDEFAULT_hint). /*! @brief Win32 specific [window hint](@ref GLFW_WIN32_SHOWDEFAULT_hint).
*/ */
#define GLFW_WIN32_SHOWDEFAULT 0x00025002 #define GLFW_WIN32_SHOWDEFAULT 0x00025002
#define GLFW_WIN32_HWND_PARENT 0x00025003
/*! @brief Wayland specific /*! @brief Wayland specific
* [window hint](@ref GLFW_WAYLAND_APP_ID_hint). * [window hint](@ref GLFW_WAYLAND_APP_ID_hint).
* *
@ -3053,6 +3054,14 @@ GLFWAPI void glfwDefaultWindowHints(void);
*/ */
GLFWAPI void glfwWindowHint(int hint, int value); GLFWAPI void glfwWindowHint(int hint, int value);
/*! @brief Sets the specified window hint to the desired value.
*
* @since Added in version 3.4.x.
*
* @ingroup window
*/
GLFWAPI void glfwWindowHintPointer(int hint, void* value);
/*! @brief Sets the specified window hint to the desired value. /*! @brief Sets the specified window hint to the desired value.
* *
* This function sets hints for the next call to @ref glfwCreateWindow. The * This function sets hints for the next call to @ref glfwCreateWindow. The

View File

@ -555,7 +555,8 @@ void _glfwTerminateEGL(void)
_glfw.egl.display = EGL_NO_DISPLAY; _glfw.egl.display = EGL_NO_DISPLAY;
} }
if (_glfw.egl.handle) // Free modules only after all wayland termination functions are called
if (_glfw.egl.handle && _glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
{ {
_glfwPlatformFreeModule(_glfw.egl.handle); _glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL; _glfw.egl.handle = NULL;

View File

@ -424,6 +424,7 @@ struct _GLFWwndconfig
struct { struct {
GLFWbool keymenu; GLFWbool keymenu;
GLFWbool showDefault; GLFWbool showDefault;
void* handleParent;
} win32; } win32;
struct { struct {
char appId[256]; char appId[256];

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

@ -528,7 +528,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,

View File

@ -355,6 +355,7 @@ typedef struct _GLFWlibraryWGL
typedef struct _GLFWwindowWin32 typedef struct _GLFWwindowWin32
{ {
HWND handle; HWND handle;
HWND handleParent;
HICON bigIcon; HICON bigIcon;
HICON smallIcon; HICON smallIcon;

View File

@ -46,17 +46,22 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
style |= WS_POPUP; style |= WS_POPUP;
else else
{ {
style |= WS_SYSMENU | WS_MINIMIZEBOX; if (!window->win32.handleParent)
if (window->decorated)
{ {
style |= WS_CAPTION; style |= WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable) if (window->decorated)
style |= WS_MAXIMIZEBOX | WS_THICKFRAME; {
style |= WS_CAPTION;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
}
else
style |= WS_POPUP;
} }
else else
style |= WS_POPUP; style |= WS_CHILD;
} }
return style; return style;
@ -1387,7 +1392,7 @@ static int createNativeWindow(_GLFWwindow* window,
style, style,
frameX, frameY, frameX, frameY,
frameWidth, frameHeight, frameWidth, frameHeight,
NULL, // No parent window (HWND)wndconfig->win32.handleParent,
NULL, // No window menu NULL, // No window menu
_glfw.win32.instance, _glfw.win32.instance,
(LPVOID) wndconfig); (LPVOID) wndconfig);
@ -1487,6 +1492,8 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
{ {
window->win32.handleParent = wndconfig->win32.handleParent;
if (!createNativeWindow(window, wndconfig, fbconfig)) if (!createNativeWindow(window, wndconfig, fbconfig))
return GLFW_FALSE; return GLFW_FALSE;

View File

@ -435,6 +435,18 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
} }
GLFWAPI void glfwWindowHintPointer(int hint, void* value)
{
_GLFW_REQUIRE_INIT();
switch (hint)
{
case GLFW_WIN32_HWND_PARENT:
_glfw.hints.window.win32.handleParent = value;
break;
}
}
GLFWAPI void glfwWindowHintString(int hint, const char* value) GLFWAPI void glfwWindowHintString(int hint, const char* value)
{ {
assert(value != NULL); assert(value != NULL);

View File

@ -907,18 +907,6 @@ void _glfwTerminateWayland(void)
libdecor_unref(_glfw.wl.libdecor.context); libdecor_unref(_glfw.wl.libdecor.context);
} }
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle)
{
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
if (_glfw.wl.xkb.composeState) if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState); xkb_compose_state_unref(_glfw.wl.xkb.composeState);
if (_glfw.wl.xkb.keymap) if (_glfw.wl.xkb.keymap)
@ -927,21 +915,11 @@ void _glfwTerminateWayland(void)
xkb_state_unref(_glfw.wl.xkb.state); xkb_state_unref(_glfw.wl.xkb.state);
if (_glfw.wl.xkb.context) if (_glfw.wl.xkb.context)
xkb_context_unref(_glfw.wl.xkb.context); xkb_context_unref(_glfw.wl.xkb.context);
if (_glfw.wl.xkb.handle)
{
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursorTheme) if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme); wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorThemeHiDPI) if (_glfw.wl.cursorThemeHiDPI)
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI); wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
if (_glfw.wl.cursor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
wl_data_offer_destroy(_glfw.wl.offers[i].offer); wl_data_offer_destroy(_glfw.wl.offers[i].offer);
@ -1001,6 +979,38 @@ 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
if (_glfw.egl.handle)
{
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL;
}
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle)
{
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
if (_glfw.wl.xkb.handle)
{
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
_glfw_free(_glfw.wl.clipboardString); _glfw_free(_glfw.wl.clipboardString);
} }

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

@ -1413,7 +1413,7 @@ static void handleEvents(double* timeout)
if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8) if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8)
{ {
if(_glfw.wl.keyboardFocus) if (_glfw.wl.keyboardFocus)
{ {
for (uint64_t i = 0; i < repeats; i++) for (uint64_t i = 0; i < repeats; i++)
{ {
@ -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,6 +151,12 @@ void _glfwPollMonitorsX11(void)
} }
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
if (!ci)
{
XRRFreeOutputInfo(oi);
continue;
}
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{ {
widthMM = oi->mm_height; widthMM = oi->mm_height;

View File

@ -576,6 +576,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
height *= _glfw.x11.contentScaleY; height *= _glfw.x11.contentScaleY;
} }
// The dimensions must be nonzero, or a BadValue error results.
width = _glfw_max(1, width);
height = _glfw_max(1, height);
int xpos = 0, ypos = 0; int xpos = 0, ypos = 0;
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION) if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
@ -2203,6 +2207,10 @@ 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
width = _glfw_max(1, width);
height = _glfw_max(1, height);
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)