Merge branch 'glfw:master' into drag-window-dev

This commit is contained in:
Naveen Karuthedath 2023-03-28 22:00:05 +05:30 committed by GitHub
commit 36987271f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 811 additions and 188 deletions

View File

@ -3,6 +3,7 @@ on:
pull_request:
push:
branches: [ ci, master, latest, 3.3-stable ]
workflow_dispatch:
permissions:
statuses: write
contents: read
@ -15,7 +16,7 @@ jobs:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt update
@ -38,7 +39,7 @@ jobs:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt update
@ -61,7 +62,7 @@ jobs:
CFLAGS: -Werror
MACOSX_DEPLOYMENT_TARGET: 10.8
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Configure static library
run: cmake -S . -B build-static
@ -79,7 +80,7 @@ jobs:
env:
CFLAGS: /WX
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Configure static library
run: cmake -S . -B build-static -G "Visual Studio 17 2022"

View File

@ -2,12 +2,6 @@ cmake_minimum_required(VERSION 3.4...3.20 FATAL_ERROR)
project(GLFW VERSION 3.4.0 LANGUAGES C)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
if (POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
@ -18,9 +12,7 @@ endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(GLFW_STANDALONE TRUE)
endif()
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} GLFW_STANDALONE)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ${GLFW_STANDALONE})

View File

@ -8,6 +8,7 @@ video tutorials.
- Bobyshev Alexander
- Laurent Aphecetche
- Matt Arsenault
- Takuro Ashie
- ashishgamedev
- David Avedissian
- Luca Bacci
@ -187,6 +188,7 @@ video tutorials.
- pthom
- Martin Pulec
- Guillaume Racicot
- Juan Ramos
- Christian Rauch
- Philip Rideout
- Eddie Ringle
@ -199,6 +201,7 @@ video tutorials.
- Aleksey Rybalkin
- Mikko Rytkönen
- Riku Salminen
- Yoshinori Sano
- Brandon Schaefer
- Sebastian Schuberth
- Christian Sdunek

View File

@ -312,6 +312,7 @@ information on what to include when reporting a bug.
- [X11] Bugfix: The OSMesa libray was not unloaded on termination
- [X11] Bugfix: A malformed response during selection transfer could cause a segfault
- [X11] Bugfix: Some calls would reset Xlib to the default error handler (#2108)
- [Wayland] Added improved fallback window decorations via libdecor (#1639,#1693)
- [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon
- [Wayland] Added support for file path drop events (#2040)

View File

@ -128,6 +128,14 @@ wayland-protocols 1.6, and mandatory at build time. If the running compositor
does not support this protocol, the screensaver may start even for full screen
windows.
GLFW uses the [libdecor library](https://gitlab.freedesktop.org/libdecor/libdecor)
for window decorations, where available. This in turn provides good quality
client-side decorations (drawn by the application) on desktop systems that do
not support server-side decorations (drawn by the window manager). On systems
that do not provide either libdecor or xdg-decoration, very basic window
decorations are provided. These do not include the window title or any caption
buttons.
GLFW uses the [xdg-decoration
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
to request decorations to be drawn around its windows. This protocol is part

View File

@ -144,6 +144,15 @@ the `VK_KHR_xlib_surface` extension. Possible values are `GLFW_TRUE` and
`GLFW_FALSE`. This is ignored on other platforms.
@subsubsection init_hints_wayland Wayland specific init hints
@anchor GLFW_WAYLAND_LIBDECOR_hint
__GLFW_WAYLAND_LIBDECOR__ specifies whether to use
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) for window
decorations where available. Possible values are `GLFW_WAYLAND_PREFER_LIBDECOR`
and `GLFW_WAYLAND_DISABLE_LIBDECOR`. This is ignored on other platforms.
@subsubsection init_hints_values Supported and default values
Initialization hint | Default value | Supported values
@ -154,6 +163,7 @@ Initialization hint | Default value | Supported v
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_X11_XCB_VULKAN_SURFACE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
@subsection platform Runtime platform selection

View File

@ -43,6 +43,16 @@ to whatever window is behind it. This can also be changed after window
creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
@subsubsection wayland_libdecor_34 Wayland libdecor decorations
GLFW now supports improved fallback window decorations via
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor).
Support for libdecor can be toggled before GLFW is initialized with the
[GLFW_WAYLAND_LIBDECOR](@ref GLFW_WAYLAND_LIBDECOR_hint) init hint. It is
enabled by default.
@subsubsection wayland_app_id_34 Wayland app_id specification
GLFW now supports specifying the app_id for a Wayland window using the
@ -267,6 +277,9 @@ then GLFW will fail to initialize.
- @ref GLFW_POSITION_X
- @ref GLFW_POSITION_Y
- @ref GLFW_ANY_POSITION
- @ref GLFW_WAYLAND_LIBDECOR
- @ref GLFW_WAYLAND_PREFER_LIBDECOR
- @ref GLFW_WAYLAND_DISABLE_LIBDECOR
@section news_archive Release notes for earlier versions

View File

@ -1164,6 +1164,9 @@ extern "C" {
#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002
#define GLFW_ANY_POSITION 0x80000000
/*! @defgroup shapes Standard cursor shapes
@ -1307,6 +1310,11 @@ extern "C" {
* X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint).
*/
#define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001
/*! @brief Wayland specific init hint.
*
* Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
*/
#define GLFW_WAYLAND_LIBDECOR 0x00053001
/*! @} */
/*! @addtogroup init

View File

@ -62,6 +62,9 @@ static _GLFWinitconfig _glfwInitHints =
{
GLFW_TRUE, // X11 XCB Vulkan surface
},
{
GLFW_WAYLAND_PREFER_LIBDECOR // Wayland libdecor mode
},
};
// The allocation function used when no custom allocator is set
@ -479,6 +482,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
case GLFW_X11_XCB_VULKAN_SURFACE:
_glfwInitHints.x11.xcbVulkanSurface = value;
return;
case GLFW_WAYLAND_LIBDECOR:
_glfwInitHints.wl.libdecorMode = value;
return;
}
_glfwInputError(GLFW_INVALID_ENUM,

View File

@ -379,6 +379,9 @@ struct _GLFWinitconfig
struct {
GLFWbool xcbVulkanSurface;
} x11;
struct {
int libdecorMode;
} wl;
};
// Window configuration

View File

@ -384,7 +384,7 @@ static GLFWbool createHelperWindow(void)
if (!_glfw.win32.helperWindowClass)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WIn32: Failed to register helper window class");
"Win32: Failed to register helper window class");
return GLFW_FALSE;
}

View File

@ -102,10 +102,9 @@ static void registryHandleGlobal(void* userData,
{
if (strcmp(interface, "wl_compositor") == 0)
{
_glfw.wl.compositorVersion = _glfw_min(3, version);
_glfw.wl.compositor =
wl_registry_bind(registry, name, &wl_compositor_interface,
_glfw.wl.compositorVersion);
_glfw_min(3, version));
}
else if (strcmp(interface, "wl_subcompositor") == 0)
{
@ -125,10 +124,9 @@ static void registryHandleGlobal(void* userData,
{
if (!_glfw.wl.seat)
{
_glfw.wl.seatVersion = _glfw_min(4, version);
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw.wl.seatVersion);
_glfw_min(4, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
}
}
@ -204,6 +202,20 @@ static const struct wl_registry_listener registryListener =
registryHandleGlobalRemove
};
void libdecorHandleError(struct libdecor* context,
enum libdecor_error error,
const char* message)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: libdecor error %u: %s",
error, message);
}
static const struct libdecor_interface libdecorInterface =
{
libdecorHandleError
};
// Create key code translation tables
//
static void createKeyTables(void)
@ -339,7 +351,7 @@ static void createKeyTables(void)
static GLFWbool loadCursorTheme(void)
{
int cursorSize = 32;
int cursorSize = 16;
const char* sizeString = getenv("XCURSOR_SIZE");
if (sizeString)
@ -394,7 +406,7 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
_glfwGetKeyScancodeWayland,
_glfwSetClipboardStringWayland,
_glfwGetClipboardStringWayland,
#if defined(_GLFW_LINUX_JOYSTICK)
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
_glfwInitJoysticksLinux,
_glfwTerminateJoysticksLinux,
_glfwPollJoystickLinux,
@ -510,6 +522,8 @@ int _glfwInitWayland(void)
_glfw.wl.keyRepeatTimerfd = -1;
_glfw.wl.cursorTimerfd = -1;
_glfw.wl.tag = glfwGetVersionString();
_glfw.wl.client.display_flush = (PFN_wl_display_flush)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_flush");
_glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read)
@ -540,6 +554,10 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_user_data");
_glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_user_data");
_glfw.wl.client.proxy_get_tag = (PFN_wl_proxy_get_tag)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_tag");
_glfw.wl.client.proxy_set_tag = (PFN_wl_proxy_set_tag)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_tag");
_glfw.wl.client.proxy_get_version = (PFN_wl_proxy_get_version)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version");
_glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags)
@ -559,7 +577,9 @@ int _glfwInitWayland(void)
!_glfw.wl.client.proxy_marshal_constructor ||
!_glfw.wl.client.proxy_marshal_constructor_versioned ||
!_glfw.wl.client.proxy_get_user_data ||
!_glfw.wl.client.proxy_set_user_data)
!_glfw.wl.client.proxy_set_user_data ||
!_glfw.wl.client.proxy_get_tag ||
!_glfw.wl.client.proxy_set_tag)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load libwayland-client entry point");
@ -647,6 +667,93 @@ int _glfwInitWayland(void)
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)
_glfw.wl.libdecor.handle = _glfwPlatformLoadModule("libdecor-0.so.0");
if (_glfw.wl.libdecor.handle)
{
_glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_new");
_glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_unref");
_glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_get_fd");
_glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_dispatch");
_glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_decorate");
_glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unref");
_glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");
_glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");
_glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");
_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");
_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");
_glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_map");
_glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_commit");
_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");
_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");
_glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");
_glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");
_glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");
_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");
_glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");
_glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_new");
_glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_state_free");
if (!_glfw.wl.libdecor.libdecor_new_ ||
!_glfw.wl.libdecor.libdecor_unref_ ||
!_glfw.wl.libdecor.libdecor_get_fd_ ||
!_glfw.wl.libdecor.libdecor_dispatch_ ||
!_glfw.wl.libdecor.libdecor_decorate_ ||
!_glfw.wl.libdecor.libdecor_frame_unref_ ||
!_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||
!_glfw.wl.libdecor.libdecor_frame_set_title_ ||
!_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||
!_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||
!_glfw.wl.libdecor.libdecor_frame_map_ ||
!_glfw.wl.libdecor.libdecor_frame_commit_ ||
!_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||
!_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||
!_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
!_glfw.wl.libdecor.libdecor_state_new_ ||
!_glfw.wl.libdecor.libdecor_state_free_)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));
}
}
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
@ -666,8 +773,17 @@ int _glfwInitWayland(void)
// Sync so we got all initial output events
wl_display_roundtrip(_glfw.wl.display);
if (_glfw.wl.libdecor.handle)
{
_glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
// Allow libdecor to receive its globals before proceeding
if (_glfw.wl.libdecor.context)
libdecor_dispatch(_glfw.wl.libdecor.context, 1);
}
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
@ -707,6 +823,15 @@ void _glfwTerminateWayland(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
if (_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);

View File

@ -114,14 +114,15 @@ static void outputHandleScale(void* userData,
{
struct _GLFWmonitor* monitor = userData;
monitor->wl.scale = factor;
monitor->wl.contentScale = factor;
for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
{
for (int i = 0; i < window->wl.monitorsCount; i++)
for (int i = 0; i < window->wl.scaleCount; i++)
{
if (window->wl.monitors[i] == monitor)
if (window->wl.scales[i].output == monitor->wl.output)
{
window->wl.scales[i].factor = monitor->wl.contentScale;
_glfwUpdateContentScaleWayland(window);
break;
}
@ -187,10 +188,11 @@ void _glfwAddOutputWayland(uint32_t name, uint32_t version)
// The actual name of this output will be set in the geometry handler
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
monitor->wl.scale = 1;
monitor->wl.contentScale = 1;
monitor->wl.output = output;
monitor->wl.name = name;
wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag);
wl_output_add_listener(output, &outputListener, monitor);
}
@ -217,9 +219,9 @@ void _glfwGetMonitorContentScaleWayland(_GLFWmonitor* monitor,
float* xscale, float* yscale)
{
if (xscale)
*xscale = (float) monitor->wl.scale;
*xscale = (float) monitor->wl.contentScale;
if (yscale)
*yscale = (float) monitor->wl.scale;
*yscale = (float) monitor->wl.contentScale;
}
void _glfwGetMonitorWorkareaWayland(_GLFWmonitor* monitor,

View File

@ -28,6 +28,8 @@
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-compose.h>
#include <stdbool.h>
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
typedef struct VkWaylandSurfaceCreateInfoKHR
@ -61,6 +63,8 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor)(struct wl_proxy*,u
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor_versioned)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,...);
typedef void* (* PFN_wl_proxy_get_user_data)(struct wl_proxy*);
typedef void (* PFN_wl_proxy_set_user_data)(struct wl_proxy*,void*);
typedef void (* PFN_wl_proxy_set_tag)(struct wl_proxy*,const char*const*);
typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*);
typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*);
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...);
#define wl_display_flush _glfw.wl.client.display_flush
@ -78,10 +82,13 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_proxy_marshal_constructor_versioned _glfw.wl.client.proxy_marshal_constructor_versioned
#define wl_proxy_get_user_data _glfw.wl.client.proxy_get_user_data
#define wl_proxy_set_user_data _glfw.wl.client.proxy_set_user_data
#define wl_proxy_get_tag _glfw.wl.client.proxy_get_tag
#define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag
#define wl_proxy_get_version _glfw.wl.client.proxy_get_version
#define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags
struct wl_shm;
struct wl_output;
#define wl_display_interface _glfw_wl_display_interface
#define wl_subcompositor_interface _glfw_wl_subcompositor_interface
@ -198,13 +205,129 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
struct libdecor;
struct libdecor_frame;
struct libdecor_state;
struct libdecor_configuration;
enum libdecor_error
{
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
};
enum libdecor_window_state
{
LIBDECOR_WINDOW_STATE_NONE = 0,
LIBDECOR_WINDOW_STATE_ACTIVE = 1,
LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
};
enum libdecor_capabilities
{
LIBDECOR_ACTION_MOVE = 1,
LIBDECOR_ACTION_RESIZE = 2,
LIBDECOR_ACTION_MINIMIZE = 4,
LIBDECOR_ACTION_FULLSCREEN = 8,
LIBDECOR_ACTION_CLOSE = 16
};
struct libdecor_interface
{
void (* error)(struct libdecor*,enum libdecor_error,const char*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
struct libdecor_frame_interface
{
void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
void (* close)(struct libdecor_frame*,void*);
void (* commit)(struct libdecor_frame*,void*);
void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);
typedef void (* PFN_libdecor_unref)(struct libdecor*);
typedef int (* PFN_libdecor_get_fd)(struct libdecor*);
typedef int (* PFN_libdecor_dispatch)(struct libdecor*,int);
typedef struct libdecor_frame* (* PFN_libdecor_decorate)(struct libdecor*,struct wl_surface*,const struct libdecor_frame_interface*,void*);
typedef void (* PFN_libdecor_frame_unref)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_app_id)(struct libdecor_frame*,const char*);
typedef void (* PFN_libdecor_frame_set_title)(struct libdecor_frame*,const char*);
typedef void (* PFN_libdecor_frame_set_minimized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_fullscreen)(struct libdecor_frame*,struct wl_output*);
typedef void (* PFN_libdecor_frame_unset_fullscreen)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_map)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_commit)(struct libdecor_frame*,struct libdecor_state*,struct libdecor_configuration*);
typedef void (* PFN_libdecor_frame_set_min_content_size)(struct libdecor_frame*,int,int);
typedef void (* PFN_libdecor_frame_set_max_content_size)(struct libdecor_frame*,int,int);
typedef void (* PFN_libdecor_frame_set_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
typedef struct libdecor_state* (* PFN_libdecor_state_new)(int,int);
typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
#define libdecor_new _glfw.wl.libdecor.libdecor_new_
#define libdecor_unref _glfw.wl.libdecor.libdecor_unref_
#define libdecor_get_fd _glfw.wl.libdecor.libdecor_get_fd_
#define libdecor_dispatch _glfw.wl.libdecor.libdecor_dispatch_
#define libdecor_decorate _glfw.wl.libdecor.libdecor_decorate_
#define libdecor_frame_unref _glfw.wl.libdecor.libdecor_frame_unref_
#define libdecor_frame_set_app_id _glfw.wl.libdecor.libdecor_frame_set_app_id_
#define libdecor_frame_set_title _glfw.wl.libdecor.libdecor_frame_set_title_
#define libdecor_frame_set_minimized _glfw.wl.libdecor.libdecor_frame_set_minimized_
#define libdecor_frame_set_fullscreen _glfw.wl.libdecor.libdecor_frame_set_fullscreen_
#define libdecor_frame_unset_fullscreen _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_
#define libdecor_frame_map _glfw.wl.libdecor.libdecor_frame_map_
#define libdecor_frame_commit _glfw.wl.libdecor.libdecor_frame_commit_
#define libdecor_frame_set_min_content_size _glfw.wl.libdecor.libdecor_frame_set_min_content_size_
#define libdecor_frame_set_max_content_size _glfw.wl.libdecor.libdecor_frame_set_max_content_size_
#define libdecor_frame_set_maximized _glfw.wl.libdecor.libdecor_frame_set_maximized_
#define libdecor_frame_unset_maximized _glfw.wl.libdecor.libdecor_frame_unset_maximized_
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
typedef enum _GLFWdecorationSideWayland
{
mainWindow,
topDecoration,
leftDecoration,
rightDecoration,
bottomDecoration,
GLFW_MAIN_WINDOW,
GLFW_TOP_DECORATION,
GLFW_LEFT_DECORATION,
GLFW_RIGHT_DECORATION,
GLFW_BOTTOM_DECORATION
} _GLFWdecorationSideWayland;
typedef struct _GLFWdecorationWayland
@ -221,6 +344,12 @@ typedef struct _GLFWofferWayland
GLFWbool text_uri_list;
} _GLFWofferWayland;
typedef struct _GLFWscaleWayland
{
struct wl_output* output;
int factor;
} _GLFWscaleWayland;
// Wayland-specific per-window data
//
typedef struct _GLFWwindowWayland
@ -254,6 +383,11 @@ typedef struct _GLFWwindowWayland
uint32_t decorationMode;
} xdg;
struct {
struct libdecor_frame* frame;
int mode;
} libdecor;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
@ -262,10 +396,10 @@ typedef struct _GLFWwindowWayland
// We need to track the monitors the window spans on to calculate the
// optimal scaling factor.
int scale;
_GLFWmonitor** monitors;
int monitorsCount;
int monitorsSize;
int contentScale;
_GLFWscaleWayland* scales;
int scaleCount;
int scaleSize;
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
@ -311,8 +445,7 @@ typedef struct _GLFWlibraryWayland
_GLFWwindow* dragFocus;
uint32_t dragSerial;
int compositorVersion;
int seatVersion;
const char* tag;
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
@ -391,6 +524,8 @@ typedef struct _GLFWlibraryWayland
PFN_wl_proxy_marshal_constructor_versioned proxy_marshal_constructor_versioned;
PFN_wl_proxy_get_user_data proxy_get_user_data;
PFN_wl_proxy_set_user_data proxy_set_user_data;
PFN_wl_proxy_get_tag proxy_get_tag;
PFN_wl_proxy_set_tag proxy_set_tag;
PFN_wl_proxy_get_version proxy_get_version;
PFN_wl_proxy_marshal_flags proxy_marshal_flags;
} client;
@ -411,6 +546,36 @@ typedef struct _GLFWlibraryWayland
PFN_wl_egl_window_destroy window_destroy;
PFN_wl_egl_window_resize window_resize;
} egl;
struct {
void* handle;
struct libdecor* context;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
PFN_libdecor_get_fd libdecor_get_fd_;
PFN_libdecor_dispatch libdecor_dispatch_;
PFN_libdecor_decorate libdecor_decorate_;
PFN_libdecor_frame_unref libdecor_frame_unref_;
PFN_libdecor_frame_set_app_id libdecor_frame_set_app_id_;
PFN_libdecor_frame_set_title libdecor_frame_set_title_;
PFN_libdecor_frame_set_minimized libdecor_frame_set_minimized_;
PFN_libdecor_frame_set_fullscreen libdecor_frame_set_fullscreen_;
PFN_libdecor_frame_unset_fullscreen libdecor_frame_unset_fullscreen_;
PFN_libdecor_frame_map libdecor_frame_map_;
PFN_libdecor_frame_commit libdecor_frame_commit_;
PFN_libdecor_frame_set_min_content_size libdecor_frame_set_min_content_size_;
PFN_libdecor_frame_set_max_content_size libdecor_frame_set_max_content_size_;
PFN_libdecor_frame_set_maximized libdecor_frame_set_maximized_;
PFN_libdecor_frame_unset_maximized libdecor_frame_unset_maximized_;
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
PFN_libdecor_state_new libdecor_state_new_;
PFN_libdecor_state_free libdecor_state_free_;
} libdecor;
} _GLFWlibraryWayland;
// Wayland-specific per-monitor data
@ -423,7 +588,7 @@ typedef struct _GLFWmonitorWayland
int x;
int y;
int scale;
int contentScale;
} _GLFWmonitorWayland;
// Wayland-specific per-cursor data

View File

@ -192,13 +192,16 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return buffer;
}
static void createFallbackDecoration(_GLFWdecorationWayland* decoration,
static void createFallbackDecoration(_GLFWwindow* window,
_GLFWdecorationWayland* decoration,
struct wl_surface* parent,
struct wl_buffer* buffer,
int x, int y,
int width, int height)
{
decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
wl_surface_set_user_data(decoration->surface, window);
wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag);
decoration->subsurface =
wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
decoration->surface, parent);
@ -228,19 +231,19 @@ static void createFallbackDecorations(_GLFWwindow* window)
if (!window->wl.decorations.buffer)
return;
createFallbackDecoration(&window->wl.decorations.top, window->wl.surface,
createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface,
window->wl.decorations.buffer,
0, -GLFW_CAPTION_HEIGHT,
window->wl.width, GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.left, window->wl.surface,
createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface,
window->wl.decorations.buffer,
-GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT,
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.right, window->wl.surface,
createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface,
window->wl.decorations.buffer,
window->wl.width, -GLFW_CAPTION_HEIGHT,
GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
createFallbackDecoration(&window->wl.decorations.bottom, window->wl.surface,
createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface,
window->wl.decorations.buffer,
-GLFW_BORDER_SIZE, window->wl.height,
window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
@ -306,7 +309,7 @@ static void setContentAreaOpaque(_GLFWwindow* window)
static void resizeWindow(_GLFWwindow* window)
{
int scale = window->wl.scale;
int scale = window->wl.contentScale;
int scaledWidth = window->wl.width * scale;
int scaledHeight = window->wl.height * scale;
@ -342,22 +345,28 @@ static void resizeWindow(_GLFWwindow* window)
void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
{
if (_glfw.wl.compositorVersion < WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
if (wl_compositor_get_version(_glfw.wl.compositor) <
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
{
return;
}
// Get the scale factor from the highest scale monitor.
int maxScale = 1;
for (int i = 0; i < window->wl.monitorsCount; i++)
maxScale = _glfw_max(window->wl.monitors[i]->wl.scale, maxScale);
for (int i = 0; i < window->wl.scaleCount; i++)
maxScale = _glfw_max(window->wl.scales[i].factor, maxScale);
// Only change the framebuffer size if the scale changed.
if (window->wl.scale != maxScale)
if (window->wl.contentScale != maxScale)
{
window->wl.scale = maxScale;
window->wl.contentScale = maxScale;
wl_surface_set_buffer_scale(window->wl.surface, maxScale);
_glfwInputWindowContentScale(window, maxScale, maxScale);
resizeWindow(window);
if (window->wl.visible)
_glfwInputWindowDamage(window);
}
}
@ -365,18 +374,25 @@ static void surfaceHandleEnter(void* userData,
struct wl_surface* surface,
struct wl_output* output)
{
if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
return;
_GLFWwindow* window = userData;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
if (!window || !monitor)
return;
if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)
if (window->wl.scaleCount + 1 > window->wl.scaleSize)
{
++window->wl.monitorsSize;
window->wl.monitors =
_glfw_realloc(window->wl.monitors,
window->wl.monitorsSize * sizeof(_GLFWmonitor*));
window->wl.scaleSize++;
window->wl.scales =
_glfw_realloc(window->wl.scales,
window->wl.scaleSize * sizeof(_GLFWscaleWayland));
}
window->wl.monitors[window->wl.monitorsCount++] = monitor;
window->wl.scaleCount++;
window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale;
window->wl.scales[window->wl.scaleCount - 1].output = output;
_glfwUpdateContentScaleWayland(window);
}
@ -385,18 +401,20 @@ static void surfaceHandleLeave(void* userData,
struct wl_surface* surface,
struct wl_output* output)
{
_GLFWwindow* window = userData;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
GLFWbool found = GLFW_FALSE;
if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
return;
for (int i = 0; i < window->wl.monitorsCount - 1; ++i)
_GLFWwindow* window = userData;
for (int i = 0; i < window->wl.scaleCount; i++)
{
if (monitor == window->wl.monitors[i])
found = GLFW_TRUE;
if (found)
window->wl.monitors[i] = window->wl.monitors[i + 1];
if (window->wl.scales[i].output == output)
{
window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1];
window->wl.scaleCount--;
break;
}
}
window->wl.monitors[--window->wl.monitorsCount] = NULL;
_glfwUpdateContentScaleWayland(window);
}
@ -429,7 +447,12 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
//
static void acquireMonitor(_GLFWwindow* window)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
{
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
window->monitor->wl.output);
}
else if (window->wl.xdg.toplevel)
{
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
window->monitor->wl.output);
@ -445,12 +468,15 @@ static void acquireMonitor(_GLFWwindow* window)
//
static void releaseMonitor(_GLFWwindow* window)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE);
if (window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
if (!window->wl.libdecor.frame &&
window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
{
if (window->decorated)
createFallbackDecorations(window);
@ -593,7 +619,190 @@ static const struct xdg_surface_listener xdgSurfaceListener =
xdgSurfaceHandleConfigure
};
static GLFWbool createShellObjects(_GLFWwindow* window)
void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
struct libdecor_configuration* config,
void* userData)
{
_GLFWwindow* window = userData;
int width, height;
enum libdecor_window_state windowState;
GLFWbool fullscreen, activated, maximized;
if (libdecor_configuration_get_window_state(config, &windowState))
{
fullscreen = (windowState & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
activated = (windowState & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
maximized = (windowState & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
}
else
{
fullscreen = window->wl.fullscreen;
activated = window->wl.activated;
maximized = window->wl.maximized;
}
if (!libdecor_configuration_get_content_size(config, frame, &width, &height))
{
width = window->wl.width;
height = window->wl.height;
}
if (!maximized && !fullscreen)
{
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
{
const float aspectRatio = (float) width / (float) height;
const float targetRatio = (float) window->numer / (float) window->denom;
if (aspectRatio < targetRatio)
height = width / targetRatio;
else if (aspectRatio > targetRatio)
width = height * targetRatio;
}
}
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(frame, frameState, config);
libdecor_state_free(frameState);
if (window->wl.activated != activated)
{
window->wl.activated = activated;
if (!window->wl.activated)
{
if (window->monitor && window->autoIconify)
libdecor_frame_set_minimized(window->wl.libdecor.frame);
}
}
if (window->wl.maximized != maximized)
{
window->wl.maximized = maximized;
_glfwInputWindowMaximize(window, window->wl.maximized);
}
window->wl.fullscreen = fullscreen;
GLFWbool damaged = GLFW_FALSE;
if (!window->wl.visible)
{
window->wl.visible = GLFW_TRUE;
damaged = GLFW_TRUE;
}
if (width != window->wl.width || height != window->wl.height)
{
window->wl.width = width;
window->wl.height = height;
resizeWindow(window);
_glfwInputWindowSize(window, width, height);
damaged = GLFW_TRUE;
}
if (damaged)
_glfwInputWindowDamage(window);
else
wl_surface_commit(window->wl.surface);
}
void libdecorFrameHandleClose(struct libdecor_frame* frame, void* userData)
{
_GLFWwindow* window = userData;
_glfwInputWindowCloseRequest(window);
}
void libdecorFrameHandleCommit(struct libdecor_frame* frame, void* userData)
{
_GLFWwindow* window = userData;
wl_surface_commit(window->wl.surface);
}
void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,
const char* seatName,
void* userData)
{
}
static const struct libdecor_frame_interface libdecorFrameInterface =
{
libdecorFrameHandleConfigure,
libdecorFrameHandleClose,
libdecorFrameHandleCommit,
libdecorFrameHandleDismissPopup
};
static GLFWbool createLibdecorFrame(_GLFWwindow* window)
{
window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
window->wl.surface,
&libdecorFrameInterface,
window);
if (!window->wl.libdecor.frame)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create libdecor frame");
return GLFW_FALSE;
}
if (strlen(window->wl.appId))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
if (strlen(window->wl.title))
libdecor_frame_set_title(window->wl.libdecor.frame, window->wl.title);
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
}
if (!window->resizable)
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
if (window->monitor)
{
// HACK: Allow libdecor to finish initialization of itself and its
// plugin so it will create the xdg_toplevel for the frame
// This needs to exist when setting the frame to fullscreen
while (!libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame))
_glfwWaitEventsWayland();
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
window->monitor->wl.output);
setIdleInhibitor(window, GLFW_TRUE);
}
else
{
if (window->wl.maximized)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
if (!window->decorated)
libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
setIdleInhibitor(window, GLFW_FALSE);
}
libdecor_frame_map(window->wl.libdecor.frame);
wl_display_roundtrip(_glfw.wl.display);
return GLFW_TRUE;
}
static GLFWbool createXdgShellObjects(_GLFWwindow* window)
{
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
window->wl.surface);
@ -633,6 +842,7 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE);
}
if (_glfw.wl.decorationManager)
{
@ -654,10 +864,9 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
}
else
{
if (window->decorated)
if (window->decorated && !window->monitor)
createFallbackDecorations(window);
}
}
if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
{
@ -689,14 +898,27 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
wl_surface_commit(window->wl.surface);
wl_display_roundtrip(_glfw.wl.display);
return GLFW_TRUE;
}
static GLFWbool createShellObjects(_GLFWwindow* window)
{
if (_glfw.wl.libdecor.context)
{
if (createLibdecorFrame(window))
return GLFW_TRUE;
}
return createXdgShellObjects(window);
}
static void destroyShellObjects(_GLFWwindow* window)
{
destroyFallbackDecorations(window);
if (window->wl.libdecor.frame)
libdecor_frame_unref(window->wl.libdecor.frame);
if (window->wl.xdg.decoration)
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
@ -706,6 +928,7 @@ static void destroyShellObjects(_GLFWwindow* window)
if (window->wl.xdg.surface)
xdg_surface_destroy(window->wl.xdg.surface);
window->wl.libdecor.frame = NULL;
window->wl.xdg.decoration = NULL;
window->wl.xdg.decorationMode = 0;
window->wl.xdg.toplevel = NULL;
@ -723,15 +946,14 @@ static GLFWbool createNativeSurface(_GLFWwindow* window,
return GLFW_FALSE;
}
wl_proxy_set_tag((struct wl_proxy*) window->wl.surface, &_glfw.wl.tag);
wl_surface_add_listener(window->wl.surface,
&surfaceListener,
window);
wl_surface_set_user_data(window->wl.surface, window);
window->wl.width = wndconfig->width;
window->wl.height = wndconfig->height;
window->wl.scale = 1;
window->wl.contentScale = 1;
window->wl.title = _glfw_strdup(wndconfig->title);
window->wl.appId = _glfw_strdup(wndconfig->wl.appId);
@ -758,7 +980,7 @@ static void setCursorImage(_GLFWwindow* window,
buffer = cursorWayland->buffer;
else
{
if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI)
{
wlCursor = cursorWayland->cursorHiDPI;
scale = 2;
@ -794,7 +1016,7 @@ static void incrementCursorImage(_GLFWwindow* window)
{
_GLFWcursor* cursor;
if (!window || window->wl.decorations.focus != mainWindow)
if (!window || window->wl.decorations.focus != GLFW_MAIN_WINDOW)
return;
cursor = window->wl.currentCursor;
@ -874,13 +1096,17 @@ static void inputText(_GLFWwindow* window, uint32_t scancode)
static void handleEvents(double* timeout)
{
GLFWbool event = GLFW_FALSE;
struct pollfd fds[] =
struct pollfd fds[4] =
{
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
{ _glfw.wl.keyRepeatTimerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN },
{ -1, POLLIN }
};
if (_glfw.wl.libdecor.context)
fds[3].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
while (!event)
{
while (wl_display_prepare_read(_glfw.wl.display) != 0)
@ -902,7 +1128,7 @@ static void handleEvents(double* timeout)
return;
}
if (!_glfwPollPOSIX(fds, 3, timeout))
if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return;
@ -947,6 +1173,9 @@ static void handleEvents(double* timeout)
event = GLFW_TRUE;
}
}
if (fds[3].revents & POLLIN)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
}
}
@ -1014,40 +1243,6 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
return string;
}
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
_GLFWdecorationSideWayland* which)
{
_GLFWdecorationSideWayland focus;
_GLFWwindow* window = _glfw.windowListHead;
if (!which)
which = &focus;
while (window)
{
if (surface == window->wl.decorations.top.surface)
{
*which = topDecoration;
break;
}
if (surface == window->wl.decorations.left.surface)
{
*which = leftDecoration;
break;
}
if (surface == window->wl.decorations.right.surface)
{
*which = rightDecoration;
break;
}
if (surface == window->wl.decorations.bottom.surface)
{
*which = bottomDecoration;
break;
}
window = window->next;
}
return window;
}
static void pointerHandleEnter(void* userData,
struct wl_pointer* pointer,
uint32_t serial,
@ -1059,16 +1254,22 @@ static void pointerHandleEnter(void* userData,
if (!surface)
return;
_GLFWdecorationSideWayland focus = mainWindow;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window)
{
window = findWindowFromDecorationSurface(surface, &focus);
if (!window)
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
}
window->wl.decorations.focus = focus;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (surface == window->wl.decorations.top.surface)
window->wl.decorations.focus = GLFW_TOP_DECORATION;
else if (surface == window->wl.decorations.left.surface)
window->wl.decorations.focus = GLFW_LEFT_DECORATION;
else if (surface == window->wl.decorations.right.surface)
window->wl.decorations.focus = GLFW_RIGHT_DECORATION;
else if (surface == window->wl.decorations.bottom.surface)
window->wl.decorations.focus = GLFW_BOTTOM_DECORATION;
else
window->wl.decorations.focus = GLFW_MAIN_WINDOW;
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window;
@ -1084,8 +1285,13 @@ static void pointerHandleLeave(void* userData,
uint32_t serial,
struct wl_surface* surface)
{
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!surface)
return;
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = _glfw.wl.pointerFocus;
if (!window)
return;
@ -1106,7 +1312,7 @@ static void setCursor(_GLFWwindow* window, const char* name)
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1;
if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI)
{
// We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size.
@ -1164,29 +1370,29 @@ static void pointerHandleMotion(void* userData,
switch (window->wl.decorations.focus)
{
case mainWindow:
case GLFW_MAIN_WINDOW:
_glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, x, y);
return;
case topDecoration:
case GLFW_TOP_DECORATION:
if (y < GLFW_BORDER_SIZE)
cursorName = "n-resize";
else
cursorName = "left_ptr";
break;
case leftDecoration:
case GLFW_LEFT_DECORATION:
if (y < GLFW_BORDER_SIZE)
cursorName = "nw-resize";
else
cursorName = "w-resize";
break;
case rightDecoration:
case GLFW_RIGHT_DECORATION:
if (y < GLFW_BORDER_SIZE)
cursorName = "ne-resize";
else
cursorName = "e-resize";
break;
case bottomDecoration:
case GLFW_BOTTOM_DECORATION:
if (x < GLFW_BORDER_SIZE)
cursorName = "sw-resize";
else if (x > window->wl.width + GLFW_BORDER_SIZE)
@ -1218,27 +1424,27 @@ static void pointerHandleButton(void* userData,
{
switch (window->wl.decorations.focus)
{
case mainWindow:
case GLFW_MAIN_WINDOW:
break;
case topDecoration:
case GLFW_TOP_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
break;
case leftDecoration:
case GLFW_LEFT_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
break;
case rightDecoration:
case GLFW_RIGHT_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
break;
case bottomDecoration:
case GLFW_BOTTOM_DECORATION:
if (window->wl.cursorPosX < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)
@ -1258,7 +1464,8 @@ static void pointerHandleButton(void* userData,
}
else if (button == BTN_RIGHT)
{
if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
if (window->wl.decorations.focus != GLFW_MAIN_WINDOW &&
window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
@ -1269,7 +1476,7 @@ static void pointerHandleButton(void* userData,
}
// Dont pass the button to the user if it was related to a decoration.
if (window->wl.decorations.focus != mainWindow)
if (window->wl.decorations.focus != GLFW_MAIN_WINDOW)
return;
_glfw.wl.serial = serial;
@ -1423,13 +1630,12 @@ static void keyboardHandleEnter(void* userData,
if (!surface)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (!window)
{
window = findWindowFromDecorationSurface(surface, NULL);
if (!window)
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (surface != window->wl.surface)
return;
}
_glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = window;
@ -1640,7 +1846,8 @@ static void dataDeviceHandleDataOffer(void* userData,
struct wl_data_offer* offer)
{
_GLFWofferWayland* offers =
_glfw_realloc(_glfw.wl.offers, _glfw.wl.offerCount + 1);
_glfw_realloc(_glfw.wl.offers,
sizeof(_GLFWofferWayland) * (_glfw.wl.offerCount + 1));
if (!offers)
{
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
@ -1676,9 +1883,12 @@ static void dataDeviceHandleEnter(void* userData,
_GLFWwindow* window = NULL;
if (surface)
{
if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
window = wl_surface_get_user_data(surface);
}
if (window && _glfw.wl.offers[i].text_uri_list)
if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list)
{
_glfw.wl.dragOffer = offer;
_glfw.wl.dragFocus = window;
@ -1691,6 +1901,9 @@ static void dataDeviceHandleEnter(void* userData,
}
}
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
if (_glfw.wl.dragOffer)
wl_data_offer_accept(offer, serial, "text/uri-list");
else
@ -1881,7 +2094,7 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
_glfw_free(window->wl.title);
_glfw_free(window->wl.appId);
_glfw_free(window->wl.monitors);
_glfw_free(window->wl.scales);
}
void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
@ -1890,7 +2103,9 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
_glfw_free(window->wl.title);
window->wl.title = copy;
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
libdecor_frame_set_title(window->wl.libdecor.frame, title);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
}
@ -1937,6 +2152,16 @@ void _glfwSetWindowSizeWayland(_GLFWwindow* window, int width, int height)
window->wl.width = width;
window->wl.height = height;
resizeWindow(window);
if (window->wl.libdecor.frame)
{
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
}
if (window->wl.visible)
_glfwInputWindowDamage(window);
}
}
@ -1944,7 +2169,20 @@ void _glfwSetWindowSizeLimitsWayland(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
{
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
minwidth = minheight = 0;
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
maxwidth = maxheight = 0;
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
minwidth, minheight);
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
maxwidth, maxheight);
}
else if (window->wl.xdg.toplevel)
{
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
minwidth = minheight = 0;
@ -1979,16 +2217,35 @@ void _glfwSetWindowAspectRatioWayland(_GLFWwindow* window, int numer, int denom)
if (window->wl.maximized || window->wl.fullscreen)
return;
int width = window->wl.width, height = window->wl.height;
if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
{
const float aspectRatio = (float) window->wl.width / (float) window->wl.height;
const float aspectRatio = (float) width / (float) height;
const float targetRatio = (float) numer / (float) denom;
if (aspectRatio < targetRatio)
window->wl.height = window->wl.width / targetRatio;
height /= targetRatio;
else if (aspectRatio > targetRatio)
window->wl.width = window->wl.height * targetRatio;
width *= targetRatio;
}
if (width != window->wl.width || height != window->wl.height)
{
window->wl.width = width;
window->wl.height = height;
resizeWindow(window);
if (window->wl.libdecor.frame)
{
struct libdecor_state* frameState = libdecor_state_new(width, height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
}
_glfwInputWindowSize(window, width, height);
if (window->wl.visible)
_glfwInputWindowDamage(window);
}
}
@ -1996,16 +2253,16 @@ void _glfwGetFramebufferSizeWayland(_GLFWwindow* window, int* width, int* height
{
_glfwGetWindowSizeWayland(window, width, height);
if (width)
*width *= window->wl.scale;
*width *= window->wl.contentScale;
if (height)
*height *= window->wl.scale;
*height *= window->wl.contentScale;
}
void _glfwGetWindowFrameSizeWayland(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
if (window->decorated && !window->monitor && window->wl.decorations.top.surface)
if (window->wl.decorations.top.surface)
{
if (top)
*top = GLFW_CAPTION_HEIGHT;
@ -2022,14 +2279,16 @@ void _glfwGetWindowContentScaleWayland(_GLFWwindow* window,
float* xscale, float* yscale)
{
if (xscale)
*xscale = (float) window->wl.scale;
*xscale = (float) window->wl.contentScale;
if (yscale)
*yscale = (float) window->wl.scale;
*yscale = (float) window->wl.contentScale;
}
void _glfwIconifyWindowWayland(_GLFWwindow* window)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
libdecor_frame_set_minimized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
}
@ -2046,7 +2305,9 @@ void _glfwRestoreWindowWayland(_GLFWwindow* window)
if (window->wl.maximized)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
libdecor_frame_unset_maximized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
else
window->wl.maximized = GLFW_FALSE;
@ -2056,7 +2317,9 @@ void _glfwRestoreWindowWayland(_GLFWwindow* window)
void _glfwMaximizeWindowWayland(_GLFWwindow* window)
{
if (window->wl.xdg.toplevel)
if (window->wl.libdecor.frame)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
else if (window->wl.xdg.toplevel)
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
else
window->wl.maximized = GLFW_TRUE;
@ -2064,7 +2327,7 @@ void _glfwMaximizeWindowWayland(_GLFWwindow* window)
void _glfwShowWindowWayland(_GLFWwindow* window)
{
if (!window->wl.xdg.toplevel)
if (!window->wl.libdecor.frame && !window->wl.xdg.toplevel)
{
// NOTE: The XDG surface and role are created here so command-line applications
// with off-screen windows do not appear in for example the Unity dock
@ -2161,14 +2424,34 @@ GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window)
void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled)
{
if (window->wl.libdecor.frame)
{
if (enabled)
{
libdecor_frame_set_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
else
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
}
}
else
{
// TODO
_glfwInputError(GLFW_FEATURE_UNIMPLEMENTED,
"Wayland: Window attribute setting not implemented yet");
}
}
void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled)
{
if (window->wl.xdg.decoration)
if (window->wl.libdecor.frame)
{
libdecor_frame_set_visibility(window->wl.libdecor.frame, enabled);
}
else if (window->wl.xdg.decoration)
{
uint32_t mode;
@ -2179,7 +2462,7 @@ void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled)
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
}
else
else if (window->wl.xdg.toplevel)
{
if (enabled)
createFallbackDecorations(window);
@ -2589,8 +2872,11 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* cursor)
// If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
if (window != _glfw.wl.pointerFocus ||
window->wl.decorations.focus != GLFW_MAIN_WINDOW)
{
return;
}
// Update pointer lock to match cursor mode
if (window->cursorMode == GLFW_CURSOR_DISABLED)

View File

@ -1184,7 +1184,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
_glfwGetKeyScancodeX11,
_glfwSetClipboardStringX11,
_glfwGetClipboardStringX11,
#if defined(_GLFW_LINUX_JOYSTICK)
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
_glfwInitJoysticksLinux,
_glfwTerminateJoysticksLinux,
_glfwPollJoystickLinux,

View File

@ -89,7 +89,7 @@ static GLFWbool waitForAnyEvent(double* timeout)
{ _glfw.x11.emptyEventPipe[0], POLLIN }
};
#if defined(_GLFW_LINUX_JOYSTICK)
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
if (_glfw.joysticksInitialized)
fds[count++] = (struct pollfd) { _glfw.linjs.inotify, POLLIN };
#endif
@ -2806,7 +2806,7 @@ void _glfwPollEventsX11(void)
{
drainEmptyEvents();
#if defined(_GLFW_LINUX_JOYSTICK)
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
if (_glfw.joysticksInitialized)
_glfwDetectJoystickConnectionLinux();
#endif