diff --git a/CMakeLists.txt b/CMakeLists.txt index 59ab473c..f1dea9a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,7 +204,6 @@ if (_GLFW_WAYLAND) list(APPEND glfw_PKG_DEPS "wayland-client") list(APPEND glfw_INCLUDE_DIRS "${Wayland_INCLUDE_DIRS}") - list(APPEND glfw_LIBRARIES "${Wayland_LINK_LIBRARIES}") include(CheckIncludeFiles) include(CheckFunctionExists) diff --git a/README.md b/README.md index 96f99acd..a47bff66 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ information on what to include when reporting a bug. reported (#1112,#1415,#1472,#1616) - [X11] Bugfix: Some window attributes were not applied on leaving fullscreen (#1863) + - [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f6e404f2..c6d1199b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,6 +48,7 @@ if (_GLFW_WAYLAND) find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols>=1.15) pkg_get_variable(WAYLAND_PROTOCOLS_BASE wayland-protocols pkgdatadir) + pkg_get_variable(WAYLAND_CLIENT_PKGDATADIR wayland-client pkgdatadir) macro(wayland_generate protocol_file output_file) add_custom_command(OUTPUT "${output_file}.h" @@ -55,14 +56,17 @@ if (_GLFW_WAYLAND) DEPENDS "${protocol_file}" VERBATIM) - add_custom_command(OUTPUT "${output_file}.c" - COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${protocol_file}" "${output_file}.c" + add_custom_command(OUTPUT "${output_file}-code.h" + COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${protocol_file}" "${output_file}-code.h" DEPENDS "${protocol_file}" VERBATIM) - target_sources(glfw PRIVATE "${output_file}.h" "${output_file}.c") + target_sources(glfw PRIVATE "${output_file}.h" "${output_file}-code.h") endmacro() + wayland_generate( + "${WAYLAND_CLIENT_PKGDATADIR}/wayland.xml" + "${GLFW_BINARY_DIR}/src/wayland-client-protocol") wayland_generate( "${WAYLAND_PROTOCOLS_BASE}/stable/xdg-shell/xdg-shell.xml" "${GLFW_BINARY_DIR}/src/wayland-xdg-shell-client-protocol") diff --git a/src/wl_init.c b/src/wl_init.c index 1ba497b7..333b0b85 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -41,7 +41,22 @@ #include #include #include -#include + +#include "wayland-client-protocol.h" +#include "wayland-xdg-shell-client-protocol.h" +#include "wayland-xdg-decoration-client-protocol.h" +#include "wayland-viewporter-client-protocol.h" +#include "wayland-relative-pointer-unstable-v1-client-protocol.h" +#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" +#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" + +#include "wayland-client-protocol-code.h" +#include "wayland-xdg-shell-client-protocol-code.h" +#include "wayland-xdg-decoration-client-protocol-code.h" +#include "wayland-viewporter-client-protocol-code.h" +#include "wayland-relative-pointer-unstable-v1-client-protocol-code.h" +#include "wayland-pointer-constraints-unstable-v1-client-protocol-code.h" +#include "wayland-idle-inhibit-unstable-v1-client-protocol-code.h" static inline int min(int n1, int n2) @@ -1039,6 +1054,69 @@ int _glfwPlatformInit(void) long cursorSizeLong; int cursorSize; + _glfw.wl.client.handle = _glfw_dlopen("libwayland-client.so.0"); + if (!_glfw.wl.client.handle) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to open libwayland-client"); + return GLFW_FALSE; + } + + _glfw.wl.client.display_flush = (PFN_wl_display_flush) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_flush"); + _glfw.wl.client.display_cancel_read = (PFN_wl_display_cancel_read) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_cancel_read"); + _glfw.wl.client.display_dispatch_pending = (PFN_wl_display_dispatch_pending) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_dispatch_pending"); + _glfw.wl.client.display_read_events = (PFN_wl_display_read_events) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_read_events"); + _glfw.wl.client.display_connect = (PFN_wl_display_connect) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_connect"); + _glfw.wl.client.display_disconnect = (PFN_wl_display_disconnect) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_disconnect"); + _glfw.wl.client.display_roundtrip = (PFN_wl_display_roundtrip) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_roundtrip"); + _glfw.wl.client.display_get_fd = (PFN_wl_display_get_fd) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_get_fd"); + _glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_prepare_read"); + _glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal"); + _glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_add_listener"); + _glfw.wl.client.proxy_destroy = (PFN_wl_proxy_destroy) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_destroy"); + _glfw.wl.client.proxy_marshal_constructor = (PFN_wl_proxy_marshal_constructor) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal_constructor"); + _glfw.wl.client.proxy_marshal_constructor_versioned = (PFN_wl_proxy_marshal_constructor_versioned) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_marshal_constructor_versioned"); + _glfw.wl.client.proxy_get_user_data = (PFN_wl_proxy_get_user_data) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_get_user_data"); + _glfw.wl.client.proxy_set_user_data = (PFN_wl_proxy_set_user_data) + _glfw_dlsym(_glfw.wl.client.handle, "wl_proxy_set_user_data"); + + if (!_glfw.wl.client.display_flush || + !_glfw.wl.client.display_cancel_read || + !_glfw.wl.client.display_dispatch_pending || + !_glfw.wl.client.display_read_events || + !_glfw.wl.client.display_connect || + !_glfw.wl.client.display_disconnect || + !_glfw.wl.client.display_roundtrip || + !_glfw.wl.client.display_get_fd || + !_glfw.wl.client.display_prepare_read || + !_glfw.wl.client.proxy_marshal || + !_glfw.wl.client.proxy_add_listener || + !_glfw.wl.client.proxy_destroy || + !_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) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to load libwayland-client entry point"); + return GLFW_FALSE; + } + _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); if (!_glfw.wl.cursor.handle) { diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 62037618..74907c79 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -34,6 +34,8 @@ #include #include +#include "wayland-client-protocol.h" + static void outputHandleGeometry(void* data, struct wl_output* output, diff --git a/src/wl_platform.h b/src/wl_platform.h index 966155fd..022a7ca6 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -24,7 +24,7 @@ // //======================================================================== -#include +#include #include #ifdef HAVE_XKBCOMMON_COMPOSE_H #include @@ -54,12 +54,40 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #endif #include "xkb_unicode.h" -#include "wayland-xdg-shell-client-protocol.h" -#include "wayland-xdg-decoration-client-protocol.h" -#include "wayland-viewporter-client-protocol.h" -#include "wayland-relative-pointer-unstable-v1-client-protocol.h" -#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" -#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" +typedef int (* PFN_wl_display_flush)(struct wl_display *display); +typedef void (* PFN_wl_display_cancel_read)(struct wl_display *display); +typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display *display); +typedef int (* PFN_wl_display_read_events)(struct wl_display *display); +typedef struct wl_display* (* PFN_wl_display_connect)(const char*); +typedef void (* PFN_wl_display_disconnect)(struct wl_display*); +typedef int (* PFN_wl_display_roundtrip)(struct wl_display*); +typedef int (* PFN_wl_display_get_fd)(struct wl_display*); +typedef int (* PFN_wl_display_prepare_read)(struct wl_display*); +typedef void (* PFN_wl_proxy_marshal)(struct wl_proxy*,uint32_t,...); +typedef int (* PFN_wl_proxy_add_listener)(struct wl_proxy*,void(**)(void),void*); +typedef void (* PFN_wl_proxy_destroy)(struct wl_proxy*); +typedef struct wl_proxy* (* PFN_wl_proxy_marshal_constructor)(struct wl_proxy*,uint32_t,const struct wl_interface*,...); +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*); +#define wl_display_flush _glfw.wl.client.display_flush +#define wl_display_cancel_read _glfw.wl.client.display_cancel_read +#define wl_display_dispatch_pending _glfw.wl.client.display_dispatch_pending +#define wl_display_read_events _glfw.wl.client.display_read_events +#define wl_display_connect _glfw.wl.client.display_connect +#define wl_display_disconnect _glfw.wl.client.display_disconnect +#define wl_display_roundtrip _glfw.wl.client.display_roundtrip +#define wl_display_get_fd _glfw.wl.client.display_get_fd +#define wl_display_prepare_read _glfw.wl.client.display_prepare_read +#define wl_proxy_marshal _glfw.wl.client.proxy_marshal +#define wl_proxy_add_listener _glfw.wl.client.proxy_add_listener +#define wl_proxy_destroy _glfw.wl.client.proxy_destroy +#define wl_proxy_marshal_constructor _glfw.wl.client.proxy_marshal_constructor +#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 + +struct wl_shm; #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlclose(handle) dlclose(handle) @@ -302,6 +330,26 @@ typedef struct _GLFWlibraryWayland _GLFWwindow* pointerFocus; _GLFWwindow* keyboardFocus; + struct { + void* handle; + PFN_wl_display_flush display_flush; + PFN_wl_display_cancel_read display_cancel_read; + PFN_wl_display_dispatch_pending display_dispatch_pending; + PFN_wl_display_read_events display_read_events; + PFN_wl_display_connect display_connect; + PFN_wl_display_disconnect display_disconnect; + PFN_wl_display_roundtrip display_roundtrip; + PFN_wl_display_get_fd display_get_fd; + PFN_wl_display_prepare_read display_prepare_read; + PFN_wl_proxy_marshal proxy_marshal; + PFN_wl_proxy_add_listener proxy_add_listener; + PFN_wl_proxy_destroy proxy_destroy; + PFN_wl_proxy_marshal_constructor proxy_marshal_constructor; + 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; + } client; + struct { void* handle; diff --git a/src/wl_window.c b/src/wl_window.c index 939f9c19..f8b50df1 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -40,6 +40,14 @@ #include #include +#include "wayland-client-protocol.h" +#include "wayland-xdg-shell-client-protocol.h" +#include "wayland-xdg-decoration-client-protocol.h" +#include "wayland-viewporter-client-protocol.h" +#include "wayland-relative-pointer-unstable-v1-client-protocol.h" +#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" +#include "wayland-idle-inhibit-unstable-v1-client-protocol.h" + static int createTmpfileCloexec(char* tmpname) {