mirror of
https://github.com/glfw/glfw.git
synced 2025-12-19 05:31:57 +00:00
Compare commits
8 Commits
b3b9085132
...
3e05648c66
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e05648c66 | ||
|
|
b39236c11a | ||
|
|
a1777976be | ||
|
|
dbadda2683 | ||
|
|
08449b7183 | ||
|
|
1ce855b0b1 | ||
|
|
ebff6606ee | ||
|
|
162896e5b9 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libwayland-dev libxkbcommon-dev
|
sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libwayland-dev libxkbcommon-dev libdbus-1-dev
|
||||||
|
|
||||||
- name: Configure Null shared library
|
- name: Configure Null shared library
|
||||||
run: cmake -B build-null-shared -D GLFW_BUILD_WAYLAND=OFF -D GLFW_BUILD_X11=OFF -D BUILD_SHARED_LIBS=ON
|
run: cmake -B build-null-shared -D GLFW_BUILD_WAYLAND=OFF -D GLFW_BUILD_X11=OFF -D BUILD_SHARED_LIBS=ON
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -144,11 +144,17 @@ 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`
|
||||||
|
- [Wayland]: Add support for dropping files when sandboxed
|
||||||
- [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
|
||||||
@ -169,4 +175,3 @@ request, please file it in the
|
|||||||
|
|
||||||
Finally, if you're interested in helping out with the development of GLFW or
|
Finally, if you're interested in helping out with the development of GLFW or
|
||||||
porting it to your favorite platform, join us on the forum or GitHub.
|
porting it to your favorite platform, join us on the forum or GitHub.
|
||||||
|
|
||||||
|
|||||||
@ -161,6 +161,8 @@ if (GLFW_BUILD_WAYLAND)
|
|||||||
wayland-egl>=0.2.7
|
wayland-egl>=0.2.7
|
||||||
xkbcommon>=0.5.0)
|
xkbcommon>=0.5.0)
|
||||||
|
|
||||||
|
set(DBUS_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||||
|
|
||||||
target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS})
|
target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS})
|
||||||
|
|
||||||
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
121
src/wl_init.c
121
src/wl_init.c
@ -829,6 +829,73 @@ int _glfwInitWayland(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_glfw.wl.dbus.handle = _glfwPlatformLoadModule("libdbus-1.so.3");
|
||||||
|
|
||||||
|
if (_glfw.wl.dbus.handle)
|
||||||
|
{
|
||||||
|
_glfw.wl.dbus.dbus_error_init_ = (PFN_dbus_error_init)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_init");
|
||||||
|
_glfw.wl.dbus.dbus_error_free_ = (PFN_dbus_error_free)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_free");
|
||||||
|
_glfw.wl.dbus.dbus_error_is_set_ = (PFN_dbus_error_is_set)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_is_set");
|
||||||
|
_glfw.wl.dbus.dbus_bus_get_ = (PFN_dbus_bus_get)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_bus_get");
|
||||||
|
_glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_ = (PFN_dbus_connection_set_exit_on_disconnect)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_connection_set_exit_on_disconnect");
|
||||||
|
_glfw.wl.dbus.dbus_connection_send_with_reply_and_block_ = (PFN_dbus_connection_send_with_reply_and_block)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_connection_send_with_reply_and_block");
|
||||||
|
_glfw.wl.dbus.dbus_message_new_method_call_ = (PFN_dbus_message_new_method_call)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_new_method_call");
|
||||||
|
_glfw.wl.dbus.dbus_message_unref_ = (PFN_dbus_message_unref)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_unref");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_init_ = (PFN_dbus_message_iter_init)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_init");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_init_append_ = (PFN_dbus_message_iter_init_append)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_init_append");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_append_basic_ = (PFN_dbus_message_iter_append_basic)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_append_basic");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_open_container_ = (PFN_dbus_message_iter_open_container)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_open_container");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_close_container_ = (PFN_dbus_message_iter_close_container)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_close_container");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_get_arg_type_ = (PFN_dbus_message_iter_get_arg_type)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_arg_type");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_get_element_type_ = (PFN_dbus_message_iter_get_element_type)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_element_type");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_recurse_ = (PFN_dbus_message_iter_recurse)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_recurse");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_get_element_count_ = (PFN_dbus_message_iter_get_element_count)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_element_count");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_get_basic_ = (PFN_dbus_message_iter_get_basic)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_basic");
|
||||||
|
_glfw.wl.dbus.dbus_message_iter_next_ = (PFN_dbus_message_iter_next)
|
||||||
|
_glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_next");
|
||||||
|
if (!_glfw.wl.dbus.dbus_error_init_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_error_free_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_error_is_set_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_bus_get_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_connection_send_with_reply_and_block_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_new_method_call_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_unref_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_init_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_init_append_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_append_basic_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_open_container_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_close_container_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_get_arg_type_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_get_element_type_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_recurse_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_get_element_count_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_get_basic_ ||
|
||||||
|
!_glfw.wl.dbus.dbus_message_iter_next_)
|
||||||
|
{
|
||||||
|
_glfwPlatformFreeModule(_glfw.wl.dbus.handle);
|
||||||
|
memset(&_glfw.wl.dbus, 0, sizeof(_glfw.wl.dbus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
@ -907,18 +974,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 +982,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 +1046,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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*);
|
||||||
@ -326,6 +330,97 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
|
|||||||
#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
|
#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
|
||||||
#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
|
#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
|
||||||
|
|
||||||
|
#define DBUS_FALSE 0
|
||||||
|
#define DBUS_TYPE_STRING ((int) 's')
|
||||||
|
#define DBUS_TYPE_ARRAY ((int) 'a')
|
||||||
|
#define DBUS_TIMEOUT_INFINITE ((int) 0x7fffffff)
|
||||||
|
|
||||||
|
typedef uint32_t dbus_bool_t;
|
||||||
|
|
||||||
|
typedef struct DBusError
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *message;
|
||||||
|
unsigned int dummy1 : 1;
|
||||||
|
unsigned int dummy2 : 1;
|
||||||
|
unsigned int dummy3 : 1;
|
||||||
|
unsigned int dummy4 : 1;
|
||||||
|
unsigned int dummy5 : 1;
|
||||||
|
void *padding1;
|
||||||
|
} DBusError;
|
||||||
|
|
||||||
|
typedef struct DBusConnection DBusConnection;
|
||||||
|
|
||||||
|
typedef enum DBusBusType
|
||||||
|
{
|
||||||
|
DBUS_BUS_SESSION,
|
||||||
|
DBUS_BUS_SYSTEM,
|
||||||
|
DBUS_BUS_STARTER,
|
||||||
|
} DBusBusType;
|
||||||
|
|
||||||
|
typedef struct DBusMessage DBusMessage;
|
||||||
|
|
||||||
|
typedef struct DBusMessageIter
|
||||||
|
{
|
||||||
|
#if DBUS_SIZEOF_VOID_P > 8
|
||||||
|
void *dummy[16];
|
||||||
|
#else
|
||||||
|
void *dummy1;
|
||||||
|
void *dummy2;
|
||||||
|
uint32_t dummy3;
|
||||||
|
int dummy4;
|
||||||
|
int dummy5;
|
||||||
|
int dummy6;
|
||||||
|
int dummy7;
|
||||||
|
int dummy8;
|
||||||
|
int dummy9;
|
||||||
|
int dummy10;
|
||||||
|
int dummy11;
|
||||||
|
int pad1;
|
||||||
|
void *pad2;
|
||||||
|
void *pad3;
|
||||||
|
#endif
|
||||||
|
} DBusMessageIter;
|
||||||
|
|
||||||
|
typedef void (* PFN_dbus_error_init) (DBusError*);
|
||||||
|
typedef void (* PFN_dbus_error_free) (DBusError*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_error_is_set) (const DBusError*);
|
||||||
|
typedef DBusConnection* (* PFN_dbus_bus_get) (enum DBusBusType, DBusError*);
|
||||||
|
typedef void (* PFN_dbus_connection_set_exit_on_disconnect) (DBusConnection*, dbus_bool_t);
|
||||||
|
typedef DBusMessage* (* PFN_dbus_connection_send_with_reply_and_block) (DBusConnection*, DBusMessage*, int, DBusError*);
|
||||||
|
typedef DBusMessage* (* PFN_dbus_message_new_method_call) (const char*, const char*, const char*, const char*);
|
||||||
|
typedef void (* PFN_dbus_message_unref) (DBusMessage*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_init) (DBusMessage*, DBusMessageIter*);
|
||||||
|
typedef void (* PFN_dbus_message_iter_init_append) (DBusMessage*, DBusMessageIter*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_append_basic) (DBusMessageIter*, int, const void*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_open_container) (DBusMessageIter*, int, const char*, DBusMessageIter*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_close_container) (DBusMessageIter*, DBusMessageIter*);
|
||||||
|
typedef int (* PFN_dbus_message_iter_get_arg_type) (DBusMessageIter*);
|
||||||
|
typedef int (* PFN_dbus_message_iter_get_element_type) (DBusMessageIter*);
|
||||||
|
typedef void (* PFN_dbus_message_iter_recurse) (DBusMessageIter*, DBusMessageIter*);
|
||||||
|
typedef int (* PFN_dbus_message_iter_get_element_count) (DBusMessageIter*);
|
||||||
|
typedef void (* PFN_dbus_message_iter_get_basic) (DBusMessageIter*, void*);
|
||||||
|
typedef dbus_bool_t (* PFN_dbus_message_iter_next) (DBusMessageIter*);
|
||||||
|
#define dbus_error_init _glfw.wl.dbus.dbus_error_init_
|
||||||
|
#define dbus_error_free _glfw.wl.dbus.dbus_error_free_
|
||||||
|
#define dbus_error_is_set _glfw.wl.dbus.dbus_error_is_set_
|
||||||
|
#define dbus_bus_get _glfw.wl.dbus.dbus_bus_get_
|
||||||
|
#define dbus_connection_set_exit_on_disconnect _glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_
|
||||||
|
#define dbus_connection_send_with_reply_and_block _glfw.wl.dbus.dbus_connection_send_with_reply_and_block_
|
||||||
|
#define dbus_message_new_method_call _glfw.wl.dbus.dbus_message_new_method_call_
|
||||||
|
#define dbus_message_unref _glfw.wl.dbus.dbus_message_unref_
|
||||||
|
#define dbus_message_iter_init _glfw.wl.dbus.dbus_message_iter_init_
|
||||||
|
#define dbus_message_iter_init_append _glfw.wl.dbus.dbus_message_iter_init_append_
|
||||||
|
#define dbus_message_iter_append_basic _glfw.wl.dbus.dbus_message_iter_append_basic_
|
||||||
|
#define dbus_message_iter_open_container _glfw.wl.dbus.dbus_message_iter_open_container_
|
||||||
|
#define dbus_message_iter_close_container _glfw.wl.dbus.dbus_message_iter_close_container_
|
||||||
|
#define dbus_message_iter_get_arg_type _glfw.wl.dbus.dbus_message_iter_get_arg_type_
|
||||||
|
#define dbus_message_iter_get_element_type _glfw.wl.dbus.dbus_message_iter_get_element_type_
|
||||||
|
#define dbus_message_iter_recurse _glfw.wl.dbus.dbus_message_iter_recurse_
|
||||||
|
#define dbus_message_iter_get_element_count _glfw.wl.dbus.dbus_message_iter_get_element_count_
|
||||||
|
#define dbus_message_iter_get_basic _glfw.wl.dbus.dbus_message_iter_get_basic_
|
||||||
|
#define dbus_message_iter_next _glfw.wl.dbus.dbus_message_iter_next_
|
||||||
|
|
||||||
typedef struct _GLFWfallbackEdgeWayland
|
typedef struct _GLFWfallbackEdgeWayland
|
||||||
{
|
{
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
@ -338,6 +433,7 @@ typedef struct _GLFWofferWayland
|
|||||||
struct wl_data_offer* offer;
|
struct wl_data_offer* offer;
|
||||||
GLFWbool text_plain_utf8;
|
GLFWbool text_plain_utf8;
|
||||||
GLFWbool text_uri_list;
|
GLFWbool text_uri_list;
|
||||||
|
GLFWbool portal_file_transfer;
|
||||||
} _GLFWofferWayland;
|
} _GLFWofferWayland;
|
||||||
|
|
||||||
typedef struct _GLFWscaleWayland
|
typedef struct _GLFWscaleWayland
|
||||||
@ -450,6 +546,7 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_data_offer* dragOffer;
|
struct wl_data_offer* dragOffer;
|
||||||
_GLFWwindow* dragFocus;
|
_GLFWwindow* dragFocus;
|
||||||
uint32_t dragSerial;
|
uint32_t dragSerial;
|
||||||
|
GLFWbool dragUsePortal;
|
||||||
|
|
||||||
const char* tag;
|
const char* tag;
|
||||||
|
|
||||||
@ -585,6 +682,29 @@ typedef struct _GLFWlibraryWayland
|
|||||||
PFN_libdecor_state_new libdecor_state_new_;
|
PFN_libdecor_state_new libdecor_state_new_;
|
||||||
PFN_libdecor_state_free libdecor_state_free_;
|
PFN_libdecor_state_free libdecor_state_free_;
|
||||||
} libdecor;
|
} libdecor;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
PFN_dbus_error_init dbus_error_init_;
|
||||||
|
PFN_dbus_error_free dbus_error_free_;
|
||||||
|
PFN_dbus_error_is_set dbus_error_is_set_;
|
||||||
|
PFN_dbus_bus_get dbus_bus_get_;
|
||||||
|
PFN_dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_;
|
||||||
|
PFN_dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_;
|
||||||
|
PFN_dbus_message_new_method_call dbus_message_new_method_call_;
|
||||||
|
PFN_dbus_message_unref dbus_message_unref_;
|
||||||
|
PFN_dbus_message_iter_init dbus_message_iter_init_;
|
||||||
|
PFN_dbus_message_iter_init_append dbus_message_iter_init_append_;
|
||||||
|
PFN_dbus_message_iter_append_basic dbus_message_iter_append_basic_;
|
||||||
|
PFN_dbus_message_iter_open_container dbus_message_iter_open_container_;
|
||||||
|
PFN_dbus_message_iter_close_container dbus_message_iter_close_container_;
|
||||||
|
PFN_dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_;
|
||||||
|
PFN_dbus_message_iter_get_element_type dbus_message_iter_get_element_type_;
|
||||||
|
PFN_dbus_message_iter_recurse dbus_message_iter_recurse_;
|
||||||
|
PFN_dbus_message_iter_get_element_count dbus_message_iter_get_element_count_;
|
||||||
|
PFN_dbus_message_iter_get_basic dbus_message_iter_get_basic_;
|
||||||
|
PFN_dbus_message_iter_next dbus_message_iter_next_;
|
||||||
|
} dbus;
|
||||||
} _GLFWlibraryWayland;
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
// Wayland-specific per-monitor data
|
// Wayland-specific per-monitor data
|
||||||
|
|||||||
148
src/wl_window.c
148
src/wl_window.c
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#define GLFW_BORDER_SIZE 4
|
#define GLFW_BORDER_SIZE 4
|
||||||
#define GLFW_CAPTION_HEIGHT 24
|
#define GLFW_CAPTION_HEIGHT 24
|
||||||
|
#define FILE_TRANSFER_PORTAL_MIME_TYPE "application/vnd.portal.filetransfer"
|
||||||
|
|
||||||
static int createTmpfileCloexec(char* tmpname)
|
static int createTmpfileCloexec(char* tmpname)
|
||||||
{
|
{
|
||||||
@ -1692,7 +1693,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 +1840,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1969,6 +1973,8 @@ static void dataOfferHandleOffer(void* userData,
|
|||||||
_glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE;
|
_glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE;
|
||||||
else if (strcmp(mimeType, "text/uri-list") == 0)
|
else if (strcmp(mimeType, "text/uri-list") == 0)
|
||||||
_glfw.wl.offers[i].text_uri_list = GLFW_TRUE;
|
_glfw.wl.offers[i].text_uri_list = GLFW_TRUE;
|
||||||
|
else if (strcmp(mimeType, FILE_TRANSFER_PORTAL_MIME_TYPE) == 0)
|
||||||
|
_glfw.wl.offers[i].portal_file_transfer = GLFW_TRUE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2031,16 +2037,22 @@ static void dataDeviceHandleEnter(void* userData,
|
|||||||
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
_GLFWwindow* window = wl_surface_get_user_data(surface);
|
||||||
if (window->wl.surface == surface)
|
if (window->wl.surface == surface)
|
||||||
{
|
{
|
||||||
if (_glfw.wl.offers[i].text_uri_list)
|
GLFWbool portal = _glfw.wl.offers[i].portal_file_transfer && _glfw.wl.dbus.handle;
|
||||||
|
if (_glfw.wl.offers[i].text_uri_list || portal)
|
||||||
{
|
{
|
||||||
_glfw.wl.dragOffer = offer;
|
_glfw.wl.dragOffer = offer;
|
||||||
_glfw.wl.dragFocus = window;
|
_glfw.wl.dragFocus = window;
|
||||||
_glfw.wl.dragSerial = serial;
|
_glfw.wl.dragSerial = serial;
|
||||||
|
_glfw.wl.dragUsePortal = portal;
|
||||||
|
|
||||||
|
if (portal) {
|
||||||
|
wl_data_offer_accept(offer, serial, FILE_TRANSFER_PORTAL_MIME_TYPE);
|
||||||
|
} else {
|
||||||
wl_data_offer_accept(offer, serial, "text/uri-list");
|
wl_data_offer_accept(offer, serial, "text/uri-list");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_glfw.wl.dragOffer)
|
if (!_glfw.wl.dragOffer)
|
||||||
{
|
{
|
||||||
@ -2071,12 +2083,128 @@ static void dataDeviceHandleMotion(void* userData,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receives a dropped file that was sent using the
|
||||||
|
// [File Transfer](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.FileTransfer.html) portal.
|
||||||
|
// This enables us to receive files when running as a Flatpak or Snap.
|
||||||
|
static void dataDeviceHandleFileTransferPortalDrop(void* userData,
|
||||||
|
struct wl_data_device* device)
|
||||||
|
{
|
||||||
|
assert(_glfw.wl.dbus.handle != NULL);
|
||||||
|
|
||||||
|
char* key = readDataOfferAsString(_glfw.wl.dragOffer, FILE_TRANSFER_PORTAL_MIME_TYPE);
|
||||||
|
if (!key)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DBusError error;
|
||||||
|
dbus_error_init(&error);
|
||||||
|
DBusConnection* connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||||
|
if (dbus_error_is_set(&error))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "DBus: %s", error.message);
|
||||||
|
dbus_error_free(&error);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dbus_connection_set_exit_on_disconnect(connection, DBUS_FALSE);
|
||||||
|
|
||||||
|
DBusMessage* message = dbus_message_new_method_call(
|
||||||
|
"org.freedesktop.portal.Documents",
|
||||||
|
"/org/freedesktop/portal/documents",
|
||||||
|
"org.freedesktop.portal.FileTransfer",
|
||||||
|
"RetrieveFiles"
|
||||||
|
);
|
||||||
|
if (!message)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBusMessageIter args, options;
|
||||||
|
dbus_message_iter_init_append(message, &args);
|
||||||
|
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &key))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &options))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dbus_message_iter_close_container(&args, &options))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBusMessage* reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_INFINITE, &error);
|
||||||
|
if (dbus_error_is_set(&error))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "DBus: %s", error.message);
|
||||||
|
dbus_error_free(&error);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBusMessageIter out, array;
|
||||||
|
if (!dbus_message_iter_init(reply, &out))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dbus_message_iter_get_arg_type(&out) != DBUS_TYPE_ARRAY
|
||||||
|
|| dbus_message_iter_get_element_type(&out) != DBUS_TYPE_STRING) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "DBus: Reply is not an array of strings");
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dbus_message_iter_recurse(&out, &array);
|
||||||
|
int elements = dbus_message_iter_get_element_count(&out);
|
||||||
|
char** paths = _glfw_calloc(elements, sizeof(char*));
|
||||||
|
if (!paths) {
|
||||||
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
dbus_message_iter_get_basic(&array, &paths[i++]);
|
||||||
|
} while (dbus_message_iter_next(&array));
|
||||||
|
|
||||||
|
_glfwInputDrop(_glfw.wl.dragFocus, elements, (const char**) paths);
|
||||||
|
|
||||||
|
_glfw_free(paths);
|
||||||
|
dbus_message_unref(reply);
|
||||||
|
dbus_message_unref(message);
|
||||||
|
_glfw_free(key);
|
||||||
|
}
|
||||||
|
|
||||||
static void dataDeviceHandleDrop(void* userData,
|
static void dataDeviceHandleDrop(void* userData,
|
||||||
struct wl_data_device* device)
|
struct wl_data_device* device)
|
||||||
{
|
{
|
||||||
if (!_glfw.wl.dragOffer)
|
if (!_glfw.wl.dragOffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (_glfw.wl.dragUsePortal)
|
||||||
|
{
|
||||||
|
dataDeviceHandleFileTransferPortalDrop(userData, device);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list");
|
char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list");
|
||||||
if (string)
|
if (string)
|
||||||
{
|
{
|
||||||
@ -2974,10 +3102,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 +3159,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,
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user