diff --git a/CMakeLists.txt b/CMakeLists.txt index 398b36eb1..063533c4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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)") if (GLFW_LIBRARY_TYPE) - if (GLFW_LIBRARY_TYPE STREQUAL "SHARED") - set(GLFW_BUILD_SHARED_LIBRARY TRUE) - else() - set(GLFW_BUILD_SHARED_LIBRARY FALSE) - endif() + string(COMPARE EQUAL "${GLFW_LIBRARY_TYPE}" "SHARED" GLFW_BUILD_SHARED_LIBRARY) else() set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) endif() diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index cfb4f42ca..031962ecd 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -162,6 +162,7 @@ video tutorials. - Marcel Metz - Liam Middlebrook - mightgoyardstill + - Mihail - Ave Milia - Icyllis Milica - Jonathan Miller @@ -282,10 +283,12 @@ video tutorials. - Corentin Wallez - Torsten Walluhn - Patrick Walton + - Ivor Wanders - Jim Wang - Xo Wang - Andre Weissflog - Jay Weisskopf + - Drew Weymouth - Frank Wille - Andy Williams - Joel Winarske diff --git a/README.md b/README.md index 1c7ced36e..b27ea51dd 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,16 @@ information on what to include when reporting a bug. a modal to a fallback decoration - [Wayland] Bugfix: The cursor position was not updated when clicking through 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: 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 EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to diff --git a/src/egl_context.c b/src/egl_context.c index 0ef7f7295..921d5c6eb 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -555,7 +555,8 @@ void _glfwTerminateEGL(void) _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); _glfw.egl.handle = NULL; diff --git a/src/linux_joystick.c b/src/linux_joystick.c index d8a916b08..e4d2852b3 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/src/win32_init.c b/src/win32_init.c index 1a66b976f..48417fe47 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -528,7 +528,8 @@ void _glfwUpdateKeyNamesWin32(void) 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_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, diff --git a/src/wl_init.c b/src/wl_init.c index f6490c913..169869c22 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -908,18 +908,6 @@ void _glfwTerminateWayland(void) 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) xkb_compose_state_unref(_glfw.wl.xkb.composeState); if (_glfw.wl.xkb.keymap) @@ -928,21 +916,11 @@ void _glfwTerminateWayland(void) xkb_state_unref(_glfw.wl.xkb.state); if (_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) wl_cursor_theme_destroy(_glfw.wl.cursorTheme); if (_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++) wl_data_offer_destroy(_glfw.wl.offers[i].offer); @@ -1002,6 +980,38 @@ void _glfwTerminateWayland(void) if (_glfw.wl.cursorTimerfd >= 0) 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); } diff --git a/src/wl_platform.h b/src/wl_platform.h index 1f910319a..7a1561206 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -136,18 +136,22 @@ struct wl_output; #define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl; #define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl; -struct wl_cursor_image { +struct wl_cursor_image +{ uint32_t width; uint32_t height; uint32_t hotspot_x; uint32_t hotspot_y; uint32_t delay; }; -struct wl_cursor { + +struct wl_cursor +{ unsigned int image_count; struct wl_cursor_image** images; char* name; }; + 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 struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*); diff --git a/src/wl_window.c b/src/wl_window.c index 86e4e062c..5745ad4da 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1413,7 +1413,7 @@ static void handleEvents(double* timeout) 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++) { @@ -1692,7 +1692,8 @@ static void keyboardHandleKeymap(void* userData, } mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (mapStr == MAP_FAILED) { + if (mapStr == MAP_FAILED) + { close(fd); return; } @@ -1838,7 +1839,9 @@ static void keyboardHandleKey(void* userData, timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000; 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); } @@ -2974,10 +2977,16 @@ static void lockPointer(_GLFWwindow* window) if (!_glfw.wl.relativePointerManager) { _glfwInputError(GLFW_FEATURE_UNAVAILABLE, - "Wayland: The compositor does not support pointer locking"); + "Wayland: The compositor does not support relative pointer motion"); return; } + if (!_glfw.wl.pointerConstraints) + { + _glfwInputError(GLFW_FEATURE_UNAVAILABLE, + "Wayland: The compositor does not support locking the pointer"); + } + window->wl.relativePointer = zwp_relative_pointer_manager_v1_get_relative_pointer( _glfw.wl.relativePointerManager, @@ -3025,6 +3034,12 @@ static const struct zwp_confined_pointer_v1_listener confinedPointerListener = 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 = zwp_pointer_constraints_v1_confine_pointer( _glfw.wl.pointerConstraints, diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 3af827520..abf9cbff5 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -151,6 +151,12 @@ void _glfwPollMonitorsX11(void) } 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) { widthMM = oi->mm_height; diff --git a/src/x11_window.c b/src/x11_window.c index 77274ce36..64b25223a 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -576,6 +576,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, 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; 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) { + // 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->window == window)