From 88e98243ca78650d1d739789963578ef7f5fb2dc Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Fri, 5 Jan 2018 22:11:03 +0100 Subject: [PATCH] WIP: Load libwayland-client at runtime Fixes #1174. --- CMake/modules/FindWaylandProtocols.cmake | 9 ++++ src/CMakeLists.txt | 4 ++ src/wl_init.c | 32 +++++++++++- src/wl_platform.h | 65 +++++++++++++++++++++++- 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/CMake/modules/FindWaylandProtocols.cmake b/CMake/modules/FindWaylandProtocols.cmake index 8eb83f27e..98bfe0793 100644 --- a/CMake/modules/FindWaylandProtocols.cmake +++ b/CMake/modules/FindWaylandProtocols.cmake @@ -2,6 +2,13 @@ find_package(PkgConfig) pkg_check_modules(WaylandProtocols QUIET wayland-protocols>=${WaylandProtocols_FIND_VERSION}) +execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-client + OUTPUT_VARIABLE Wayland_PKGDATADIR + RESULT_VARIABLE _pkgconfig_failed) +if (_pkgconfig_failed) + message(FATAL_ERROR "Missing wayland-client pkgdatadir") +endif() + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols OUTPUT_VARIABLE WaylandProtocols_PKGDATADIR RESULT_VARIABLE _pkgconfig_failed) @@ -10,6 +17,7 @@ if (_pkgconfig_failed) endif() string(REGEX REPLACE "[\r\n]" "" WaylandProtocols_PKGDATADIR "${WaylandProtocols_PKGDATADIR}") +string(REGEX REPLACE "[\r\n]" "" Wayland_PKGDATADIR "${Wayland_PKGDATADIR}") find_package_handle_standard_args(WaylandProtocols FOUND_VAR @@ -22,5 +30,6 @@ find_package_handle_standard_args(WaylandProtocols ) set(WAYLAND_PROTOCOLS_FOUND ${WaylandProtocols_FOUND}) +set(WAYLAND_PKGDATADIR ${Wayland_PKGDATADIR}) set(WAYLAND_PROTOCOLS_PKGDATADIR ${WaylandProtocols_PKGDATADIR}) set(WAYLAND_PROTOCOLS_VERSION ${WaylandProtocols_VERSION}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22ce68f1b..13c5816db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,10 @@ elseif (_GLFW_WAYLAND) posix_time.c posix_thread.c xkb_unicode.c egl_context.c osmesa_context.c) + ecm_add_wayland_client_protocol(glfw_SOURCES + PROTOCOL + "${WAYLAND_PKGDATADIR}/wayland.xml" + BASENAME base) ecm_add_wayland_client_protocol(glfw_SOURCES PROTOCOL "${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml" diff --git a/src/wl_init.c b/src/wl_init.c index c14a099de..c5ca72ea6 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -34,7 +34,6 @@ #include #include #include -#include static inline int min(int n1, int n2) @@ -951,6 +950,37 @@ static void createKeyTables(void) int _glfwPlatformInit(void) { + _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.cancel_read = (PFN_wl_display_cancel_read) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_cancel_read"); + _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.dispatch_pending = (PFN_wl_display_dispatch_pending) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_dispatch_pending"); + _glfw.wl.client.display.flush = (PFN_wl_display_flush) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_flush"); + _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.display.read_events = (PFN_wl_display_read_events) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_read_events"); + _glfw.wl.client.display.roundtrip = (PFN_wl_display_roundtrip) + _glfw_dlsym(_glfw.wl.client.handle, "wl_display_roundtrip"); + + // TODO: + //_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.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); if (!_glfw.wl.cursor.handle) { diff --git a/src/wl_platform.h b/src/wl_platform.h index 108942416..819533353 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -24,7 +24,6 @@ // //======================================================================== -#include #include #ifdef HAVE_XKBCOMMON_COMPOSE_H #include @@ -56,6 +55,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #include "egl_context.h" #include "osmesa_context.h" +#include "wayland-base-client-protocol.h" #include "wayland-xdg-shell-client-protocol.h" #include "wayland-viewporter-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h" @@ -77,6 +77,42 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #define _GLFW_PLATFORM_CONTEXT_STATE #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE +typedef void (* PFN_wl_display_cancel_read)(struct wl_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_dispatch_pending)(struct wl_display*); +typedef int (* PFN_wl_display_flush)(struct wl_display*); +typedef int (* PFN_wl_display_get_fd)(struct wl_display*); +typedef int (* PFN_wl_display_prepare_read)(struct wl_display*); +typedef int (* PFN_wl_display_read_events)(struct wl_display*); +typedef int (* PFN_wl_display_roundtrip)(struct wl_display*); +#define wl_display_cancel_read _glfw.wl.client.display.cancel_read +#define wl_display_connect _glfw.wl.client.display.connect +#define wl_display_disconnect _glfw.wl.client.display.disconnect +#define wl_display_dispatch_pending _glfw.wl.client.display.dispatch_pending +#define wl_display_flush _glfw.wl.client.display.flush +#define wl_display_get_fd _glfw.wl.client.display.get_fd +#define wl_display_prepare_read _glfw.wl.client.display.prepare_read +#define wl_display_read_events _glfw.wl.client.display.read_events +#define wl_display_roundtrip _glfw.wl.client.display.roundtrip + +typedef void (* PFN_wl_proxy_marshal)(struct wl_proxy*, uint32_t, ...); +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_destroy)(struct wl_proxy*); +typedef int (* PFN_wl_proxy_add_listener)(struct wl_proxy*, void(**)(void), void*); +typedef void (* PFN_wl_proxy_set_user_data)(struct wl_proxy*, void*); +typedef void* (* PFN_wl_proxy_get_user_data)(struct wl_proxy*); +typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*); +#define wl_proxy_marshal _glfw.wl.client.proxy.marshal +#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_destroy _glfw.wl.client.proxy.destroy +#define wl_proxy_add_listener _glfw.wl.client.proxy.add_listener +#define wl_proxy_set_user_data _glfw.wl.client.proxy.set_user_data +#define wl_proxy_get_user_data _glfw.wl.client.proxy.get_user_data +#define wl_proxy_get_version _glfw.wl.client.proxy.get_version + struct wl_cursor_image { uint32_t width; uint32_t height; @@ -297,6 +333,33 @@ typedef struct _GLFWlibraryWayland _GLFWwindow* pointerFocus; _GLFWwindow* keyboardFocus; + struct { + void* handle; + + struct { + PFN_wl_display_cancel_read cancel_read; + PFN_wl_display_connect connect; + PFN_wl_display_disconnect disconnect; + PFN_wl_display_dispatch_pending dispatch_pending; + PFN_wl_display_flush flush; + PFN_wl_display_get_fd get_fd; + PFN_wl_display_prepare_read prepare_read; + PFN_wl_display_read_events read_events; + PFN_wl_display_roundtrip roundtrip; + } display; + + struct { + PFN_wl_proxy_marshal marshal; + PFN_wl_proxy_marshal_constructor marshal_constructor; + PFN_wl_proxy_marshal_constructor_versioned marshal_constructor_versioned; + PFN_wl_proxy_destroy destroy; + PFN_wl_proxy_add_listener add_listener; + PFN_wl_proxy_set_user_data set_user_data; + PFN_wl_proxy_get_user_data get_user_data; + PFN_wl_proxy_get_version get_version; + } proxy; + } client; + struct { void* handle;