瀏覽代碼

Wayland: Make libwayland-client dynamically loaded

The insight to use wayland.xml to resolve the difficult-to-redirect
interface symbols was gleaned from SDL.

Instead of compiling the code output of wayland-scanner separately it is
made part of the wl_init compilation unit.  This lets us do things like
transparently rename our copies of Wayland globals.

The OS version of wayland-client-protocol.h is no longer used by GLFW,
but it is presumably ABI compatible with the output of wayland-scanner.

Closes #1174.
Closes #1338.
Related to #1655.
Closes #1943.
Camilla Löwy 4 年之前
父節點
當前提交
dffe203c17
共有 7 個文件被更改,包括 192 次插入12 次删除
  1. 0 1
      CMakeLists.txt
  2. 1 0
      README.md
  3. 7 3
      src/CMakeLists.txt
  4. 79 1
      src/wl_init.c
  5. 2 0
      src/wl_monitor.c
  6. 95 7
      src/wl_platform.h
  7. 8 0
      src/wl_window.c

+ 0 - 1
CMakeLists.txt

@@ -205,7 +205,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)

+ 1 - 0
README.md

@@ -226,6 +226,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

+ 7 - 3
src/CMakeLists.txt

@@ -57,6 +57,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"
@@ -64,14 +65,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")

+ 79 - 1
src/wl_init.c

@@ -39,7 +39,22 @@
 #include <sys/timerfd.h>
 #include <unistd.h>
 #include <time.h>
-#include <wayland-client.h>
+
+#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)
@@ -1037,6 +1052,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)
     {

+ 2 - 0
src/wl_monitor.c

@@ -34,6 +34,8 @@
 #include <errno.h>
 #include <math.h>
 
+#include "wayland-client-protocol.h"
+
 
 static void outputHandleGeometry(void* data,
                                  struct wl_output* output,

+ 95 - 7
src/wl_platform.h

@@ -24,7 +24,7 @@
 //
 //========================================================================
 
-#include <wayland-client.h>
+#include <wayland-client-core.h>
 #include <xkbcommon/xkbcommon.h>
 #ifdef HAVE_XKBCOMMON_COMPOSE_H
 #include <xkbcommon/xkbcommon-compose.h>
@@ -54,12 +54,80 @@ 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 wl_display_interface _glfw_wl_display_interface
+#define wl_subcompositor_interface _glfw_wl_subcompositor_interface
+#define wl_compositor_interface _glfw_wl_compositor_interface
+#define wl_shm_interface _glfw_wl_shm_interface
+#define wl_data_device_manager_interface _glfw_wl_data_device_manager_interface
+#define wl_shell_interface _glfw_wl_shell_interface
+#define wl_buffer_interface _glfw_wl_buffer_interface
+#define wl_callback_interface _glfw_wl_callback_interface
+#define wl_data_device_interface _glfw_wl_data_device_interface
+#define wl_data_offer_interface _glfw_wl_data_offer_interface
+#define wl_data_source_interface _glfw_wl_data_source_interface
+#define wl_keyboard_interface _glfw_wl_keyboard_interface
+#define wl_output_interface _glfw_wl_output_interface
+#define wl_pointer_interface _glfw_wl_pointer_interface
+#define wl_region_interface _glfw_wl_region_interface
+#define wl_registry_interface _glfw_wl_registry_interface
+#define wl_seat_interface _glfw_wl_seat_interface
+#define wl_shell_surface_interface _glfw_wl_shell_surface_interface
+#define wl_shm_pool_interface _glfw_wl_shm_pool_interface
+#define wl_subsurface_interface _glfw_wl_subsurface_interface
+#define wl_surface_interface _glfw_wl_surface_interface
+#define wl_touch_interface _glfw_wl_touch_interface
+#define zwp_idle_inhibitor_v1_interface _glfw_zwp_idle_inhibitor_v1_interface
+#define zwp_idle_inhibit_manager_v1_interface _glfw_zwp_idle_inhibit_manager_v1_interface
+#define zwp_confined_pointer_v1_interface _glfw_zwp_confined_pointer_v1_interface
+#define zwp_locked_pointer_v1_interface _glfw_zwp_locked_pointer_v1_interface
+#define zwp_pointer_constraints_v1_interface _glfw_zwp_pointer_constraints_v1_interface
+#define zwp_relative_pointer_v1_interface _glfw_zwp_relative_pointer_v1_interface
+#define zwp_relative_pointer_manager_v1_interface _glfw_zwp_relative_pointer_manager_v1_interface
+#define wp_viewport_interface _glfw_wp_viewport_interface
+#define wp_viewporter_interface _glfw_wp_viewporter_interface
+#define xdg_toplevel_interface _glfw_xdg_toplevel_interface
+#define zxdg_toplevel_decoration_v1_interface _glfw_zxdg_toplevel_decoration_v1_interface
+#define zxdg_decoration_manager_v1_interface _glfw_zxdg_decoration_manager_v1_interface
+#define xdg_popup_interface _glfw_xdg_popup_interface
+#define xdg_positioner_interface _glfw_xdg_positioner_interface
+#define xdg_surface_interface _glfw_xdg_surface_interface
+#define xdg_toplevel_interface _glfw_xdg_toplevel_interface
+#define xdg_wm_base_interface _glfw_xdg_wm_base_interface
 
 #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
 #define _glfw_dlclose(handle) dlclose(handle)
@@ -302,6 +370,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;
 

+ 8 - 0
src/wl_window.c

@@ -40,6 +40,14 @@
 #include <sys/timerfd.h>
 #include <poll.h>
 
+#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)
 {