From a1777976be86a56b5c2d64d532a7eb5ada123cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Sun, 31 Aug 2025 14:30:35 +0200 Subject: [PATCH 1/2] Wayland: Add support for dropping files when sandboxed Adds support for receiving drops that make use of the [File Transfer][1] portal. This is the case in sandboxed environments such as Flatpak or Snap. [1]: https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.FileTransfer.html --- .github/workflows/build.yml | 2 +- README.md | 2 +- src/CMakeLists.txt | 4 ++ src/wl_platform.h | 2 + src/wl_window.c | 128 +++++++++++++++++++++++++++++++++++- 5 files changed, 134 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8ef9ed793..d7e3c5303 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: - name: Install dependencies run: | sudo apt update - sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libwayland-dev libxkbcommon-dev + sudo apt install libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev libwayland-dev libxkbcommon-dev libdbus-1-dev - name: Configure Null shared library run: cmake -B build-null-shared -D GLFW_BUILD_WAYLAND=OFF -D GLFW_BUILD_X11=OFF -D BUILD_SHARED_LIBS=ON diff --git a/README.md b/README.md index b27ea51dd..b51c0a350 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,7 @@ information on what to include when reporting a bug. potential segmentation fault (#2744) - [Wayland] Bugfix: Confining or disabling the cursor could segfault on compositors without `pointer-constraints-unstable-v1` + - [Wayland]: Add support for dropping files when sandboxed - [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631) - [X11] Bugfix: Occasional crash when an idle display awakes (#2766) - [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale @@ -174,4 +175,3 @@ request, please file it in the Finally, if you're interested in helping out with the development of GLFW or porting it to your favorite platform, join us on the forum or GitHub. - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2cbe8a733..63d51304c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -161,6 +161,10 @@ if (GLFW_BUILD_WAYLAND) wayland-egl>=0.2.7 xkbcommon>=0.5.0) + pkg_check_modules(DBUS REQUIRED dbus-1) + target_include_directories(glfw PRIVATE ${DBUS_INCLUDE_DIRS}) + target_link_libraries(glfw PRIVATE ${DBUS_LIBRARIES}) + target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/src/wl_platform.h b/src/wl_platform.h index bdadb657e..682b2ce79 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -342,6 +342,7 @@ typedef struct _GLFWofferWayland struct wl_data_offer* offer; GLFWbool text_plain_utf8; GLFWbool text_uri_list; + GLFWbool portal_file_transfer; } _GLFWofferWayland; typedef struct _GLFWscaleWayland @@ -454,6 +455,7 @@ typedef struct _GLFWlibraryWayland struct wl_data_offer* dragOffer; _GLFWwindow* dragFocus; uint32_t dragSerial; + GLFWbool dragUsePortal; const char* tag; diff --git a/src/wl_window.c b/src/wl_window.c index ad39b2e0e..8d9d3865c 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "wayland-client-protocol.h" #include "xdg-shell-client-protocol.h" @@ -54,6 +55,7 @@ #define GLFW_BORDER_SIZE 4 #define GLFW_CAPTION_HEIGHT 24 +#define FILE_TRANSFER_PORTAL_MIME_TYPE "application/vnd.portal.filetransfer" static int createTmpfileCloexec(char* tmpname) { @@ -1972,6 +1974,8 @@ static void dataOfferHandleOffer(void* userData, _glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE; else if (strcmp(mimeType, "text/uri-list") == 0) _glfw.wl.offers[i].text_uri_list = GLFW_TRUE; + else if (strcmp(mimeType, FILE_TRANSFER_PORTAL_MIME_TYPE) == 0) + _glfw.wl.offers[i].portal_file_transfer = GLFW_TRUE; break; } @@ -2034,13 +2038,19 @@ static void dataDeviceHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); if (window->wl.surface == surface) { - if (_glfw.wl.offers[i].text_uri_list) + GLFWbool portal = _glfw.wl.offers[i].portal_file_transfer; + if (_glfw.wl.offers[i].text_uri_list || portal) { _glfw.wl.dragOffer = offer; _glfw.wl.dragFocus = window; _glfw.wl.dragSerial = serial; + _glfw.wl.dragUsePortal = portal; - wl_data_offer_accept(offer, serial, "text/uri-list"); + if (portal) { + wl_data_offer_accept(offer, serial, FILE_TRANSFER_PORTAL_MIME_TYPE); + } else { + wl_data_offer_accept(offer, serial, "text/uri-list"); + } } } } @@ -2074,12 +2084,126 @@ static void dataDeviceHandleMotion(void* userData, { } +// Receives a dropped file that was sent using the +// [File Transfer](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.FileTransfer.html) portal. +// This enables us to receive files when running as a Flatpak or Snap. +static void dataDeviceHandleFileTransferPortalDrop(void* userData, + struct wl_data_device* device) +{ + char* key = readDataOfferAsString(_glfw.wl.dragOffer, FILE_TRANSFER_PORTAL_MIME_TYPE); + if (!key) + return; + + DBusError error; + dbus_error_init(&error); + DBusConnection* connection = dbus_bus_get(DBUS_BUS_SESSION, &error); + if (dbus_error_is_set(&error)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "DBus: %s", error.message); + dbus_error_free(&error); + _glfw_free(key); + return; + } + dbus_connection_set_exit_on_disconnect(connection, FALSE); + + DBusMessage* message = dbus_message_new_method_call( + "org.freedesktop.portal.Documents", + "/org/freedesktop/portal/documents", + "org.freedesktop.portal.FileTransfer", + "RetrieveFiles" + ); + if (!message) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + _glfw_free(key); + return; + } + DBusMessageIter args, options; + dbus_message_iter_init_append(message, &args); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &key)) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + dbus_message_unref(message); + _glfw_free(key); + return; + } + if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &options)) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + dbus_message_unref(message); + _glfw_free(key); + return; + } + if (!dbus_message_iter_close_container(&args, &options)) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + dbus_message_unref(message); + _glfw_free(key); + return; + } + + DBusMessage* reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_INFINITE, &error); + if (dbus_error_is_set(&error)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "DBus: %s", error.message); + dbus_error_free(&error); + dbus_message_unref(message); + _glfw_free(key); + return; + } + + DBusMessageIter out, array; + if (!dbus_message_iter_init(reply, &out)) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + dbus_message_unref(reply); + dbus_message_unref(message); + _glfw_free(key); + return; + } + if (dbus_message_iter_get_arg_type(&out) != DBUS_TYPE_ARRAY + || dbus_message_iter_get_element_type(&out) != DBUS_TYPE_STRING) { + _glfwInputError(GLFW_PLATFORM_ERROR, "DBus: Reply is not an array of strings"); + dbus_message_unref(reply); + dbus_message_unref(message); + _glfw_free(key); + return; + } + dbus_message_iter_recurse(&out, &array); + int elements = dbus_message_iter_get_element_count(&out); + char** paths = _glfw_calloc(elements, sizeof(char*)); + if (!paths) { + _glfwInputError(GLFW_OUT_OF_MEMORY, NULL); + dbus_message_unref(reply); + dbus_message_unref(message); + _glfw_free(key); + return; + } + int i = 0; + do { + dbus_message_iter_get_basic(&array, &paths[i++]); + } while (dbus_message_iter_next(&array)); + + _glfwInputDrop(_glfw.wl.dragFocus, elements, (const char**) paths); + + _glfw_free(paths); + dbus_message_unref(reply); + dbus_message_unref(message); + _glfw_free(key); +} + static void dataDeviceHandleDrop(void* userData, struct wl_data_device* device) { if (!_glfw.wl.dragOffer) return; + if (_glfw.wl.dragUsePortal) + { + dataDeviceHandleFileTransferPortalDrop(userData, device); + return; + } + char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list"); if (string) { From b39236c11a93392f22ec799fdd08994cfd81a0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Thu, 4 Sep 2025 13:02:02 +0200 Subject: [PATCH 2/2] Load DBus at runtime --- src/CMakeLists.txt | 4 +- src/wl_init.c | 67 ++++++++++++++++++++++++++ src/wl_platform.h | 114 +++++++++++++++++++++++++++++++++++++++++++++ src/wl_window.c | 7 +-- 4 files changed, 186 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 63d51304c..cdb5facfa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -161,9 +161,7 @@ if (GLFW_BUILD_WAYLAND) wayland-egl>=0.2.7 xkbcommon>=0.5.0) - pkg_check_modules(DBUS REQUIRED dbus-1) - target_include_directories(glfw PRIVATE ${DBUS_INCLUDE_DIRS}) - target_link_libraries(glfw PRIVATE ${DBUS_LIBRARIES}) + set(DBUS_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) diff --git a/src/wl_init.c b/src/wl_init.c index d32c4adf4..65484fea3 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -829,6 +829,73 @@ int _glfwInitWayland(void) } } + _glfw.wl.dbus.handle = _glfwPlatformLoadModule("libdbus-1.so.3"); + + if (_glfw.wl.dbus.handle) + { + _glfw.wl.dbus.dbus_error_init_ = (PFN_dbus_error_init) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_init"); + _glfw.wl.dbus.dbus_error_free_ = (PFN_dbus_error_free) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_free"); + _glfw.wl.dbus.dbus_error_is_set_ = (PFN_dbus_error_is_set) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_error_is_set"); + _glfw.wl.dbus.dbus_bus_get_ = (PFN_dbus_bus_get) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_bus_get"); + _glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_ = (PFN_dbus_connection_set_exit_on_disconnect) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_connection_set_exit_on_disconnect"); + _glfw.wl.dbus.dbus_connection_send_with_reply_and_block_ = (PFN_dbus_connection_send_with_reply_and_block) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_connection_send_with_reply_and_block"); + _glfw.wl.dbus.dbus_message_new_method_call_ = (PFN_dbus_message_new_method_call) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_new_method_call"); + _glfw.wl.dbus.dbus_message_unref_ = (PFN_dbus_message_unref) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_unref"); + _glfw.wl.dbus.dbus_message_iter_init_ = (PFN_dbus_message_iter_init) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_init"); + _glfw.wl.dbus.dbus_message_iter_init_append_ = (PFN_dbus_message_iter_init_append) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_init_append"); + _glfw.wl.dbus.dbus_message_iter_append_basic_ = (PFN_dbus_message_iter_append_basic) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_append_basic"); + _glfw.wl.dbus.dbus_message_iter_open_container_ = (PFN_dbus_message_iter_open_container) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_open_container"); + _glfw.wl.dbus.dbus_message_iter_close_container_ = (PFN_dbus_message_iter_close_container) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_close_container"); + _glfw.wl.dbus.dbus_message_iter_get_arg_type_ = (PFN_dbus_message_iter_get_arg_type) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_arg_type"); + _glfw.wl.dbus.dbus_message_iter_get_element_type_ = (PFN_dbus_message_iter_get_element_type) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_element_type"); + _glfw.wl.dbus.dbus_message_iter_recurse_ = (PFN_dbus_message_iter_recurse) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_recurse"); + _glfw.wl.dbus.dbus_message_iter_get_element_count_ = (PFN_dbus_message_iter_get_element_count) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_element_count"); + _glfw.wl.dbus.dbus_message_iter_get_basic_ = (PFN_dbus_message_iter_get_basic) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_get_basic"); + _glfw.wl.dbus.dbus_message_iter_next_ = (PFN_dbus_message_iter_next) + _glfwPlatformGetModuleSymbol(_glfw.wl.dbus.handle, "dbus_message_iter_next"); + if (!_glfw.wl.dbus.dbus_error_init_ || + !_glfw.wl.dbus.dbus_error_free_ || + !_glfw.wl.dbus.dbus_error_is_set_ || + !_glfw.wl.dbus.dbus_bus_get_ || + !_glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_ || + !_glfw.wl.dbus.dbus_connection_send_with_reply_and_block_ || + !_glfw.wl.dbus.dbus_message_new_method_call_ || + !_glfw.wl.dbus.dbus_message_unref_ || + !_glfw.wl.dbus.dbus_message_iter_init_ || + !_glfw.wl.dbus.dbus_message_iter_init_append_ || + !_glfw.wl.dbus.dbus_message_iter_append_basic_ || + !_glfw.wl.dbus.dbus_message_iter_open_container_ || + !_glfw.wl.dbus.dbus_message_iter_close_container_ || + !_glfw.wl.dbus.dbus_message_iter_get_arg_type_ || + !_glfw.wl.dbus.dbus_message_iter_get_element_type_ || + !_glfw.wl.dbus.dbus_message_iter_recurse_ || + !_glfw.wl.dbus.dbus_message_iter_get_element_count_ || + !_glfw.wl.dbus.dbus_message_iter_get_basic_ || + !_glfw.wl.dbus.dbus_message_iter_next_) + { + _glfwPlatformFreeModule(_glfw.wl.dbus.handle); + memset(&_glfw.wl.dbus, 0, sizeof(_glfw.wl.dbus)); + } + } + _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); diff --git a/src/wl_platform.h b/src/wl_platform.h index 682b2ce79..23db070be 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -330,6 +330,97 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*); #define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_ #define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_ +#define DBUS_FALSE 0 +#define DBUS_TYPE_STRING ((int) 's') +#define DBUS_TYPE_ARRAY ((int) 'a') +#define DBUS_TIMEOUT_INFINITE ((int) 0x7fffffff) + +typedef uint32_t dbus_bool_t; + +typedef struct DBusError +{ + const char *name; + const char *message; + unsigned int dummy1 : 1; + unsigned int dummy2 : 1; + unsigned int dummy3 : 1; + unsigned int dummy4 : 1; + unsigned int dummy5 : 1; + void *padding1; +} DBusError; + +typedef struct DBusConnection DBusConnection; + +typedef enum DBusBusType +{ + DBUS_BUS_SESSION, + DBUS_BUS_SYSTEM, + DBUS_BUS_STARTER, +} DBusBusType; + +typedef struct DBusMessage DBusMessage; + +typedef struct DBusMessageIter +{ +#if DBUS_SIZEOF_VOID_P > 8 + void *dummy[16]; +#else + void *dummy1; + void *dummy2; + uint32_t dummy3; + int dummy4; + int dummy5; + int dummy6; + int dummy7; + int dummy8; + int dummy9; + int dummy10; + int dummy11; + int pad1; + void *pad2; + void *pad3; +#endif +} DBusMessageIter; + +typedef void (* PFN_dbus_error_init) (DBusError*); +typedef void (* PFN_dbus_error_free) (DBusError*); +typedef dbus_bool_t (* PFN_dbus_error_is_set) (const DBusError*); +typedef DBusConnection* (* PFN_dbus_bus_get) (enum DBusBusType, DBusError*); +typedef void (* PFN_dbus_connection_set_exit_on_disconnect) (DBusConnection*, dbus_bool_t); +typedef DBusMessage* (* PFN_dbus_connection_send_with_reply_and_block) (DBusConnection*, DBusMessage*, int, DBusError*); +typedef DBusMessage* (* PFN_dbus_message_new_method_call) (const char*, const char*, const char*, const char*); +typedef void (* PFN_dbus_message_unref) (DBusMessage*); +typedef dbus_bool_t (* PFN_dbus_message_iter_init) (DBusMessage*, DBusMessageIter*); +typedef void (* PFN_dbus_message_iter_init_append) (DBusMessage*, DBusMessageIter*); +typedef dbus_bool_t (* PFN_dbus_message_iter_append_basic) (DBusMessageIter*, int, const void*); +typedef dbus_bool_t (* PFN_dbus_message_iter_open_container) (DBusMessageIter*, int, const char*, DBusMessageIter*); +typedef dbus_bool_t (* PFN_dbus_message_iter_close_container) (DBusMessageIter*, DBusMessageIter*); +typedef int (* PFN_dbus_message_iter_get_arg_type) (DBusMessageIter*); +typedef int (* PFN_dbus_message_iter_get_element_type) (DBusMessageIter*); +typedef void (* PFN_dbus_message_iter_recurse) (DBusMessageIter*, DBusMessageIter*); +typedef int (* PFN_dbus_message_iter_get_element_count) (DBusMessageIter*); +typedef void (* PFN_dbus_message_iter_get_basic) (DBusMessageIter*, void*); +typedef dbus_bool_t (* PFN_dbus_message_iter_next) (DBusMessageIter*); +#define dbus_error_init _glfw.wl.dbus.dbus_error_init_ +#define dbus_error_free _glfw.wl.dbus.dbus_error_free_ +#define dbus_error_is_set _glfw.wl.dbus.dbus_error_is_set_ +#define dbus_bus_get _glfw.wl.dbus.dbus_bus_get_ +#define dbus_connection_set_exit_on_disconnect _glfw.wl.dbus.dbus_connection_set_exit_on_disconnect_ +#define dbus_connection_send_with_reply_and_block _glfw.wl.dbus.dbus_connection_send_with_reply_and_block_ +#define dbus_message_new_method_call _glfw.wl.dbus.dbus_message_new_method_call_ +#define dbus_message_unref _glfw.wl.dbus.dbus_message_unref_ +#define dbus_message_iter_init _glfw.wl.dbus.dbus_message_iter_init_ +#define dbus_message_iter_init_append _glfw.wl.dbus.dbus_message_iter_init_append_ +#define dbus_message_iter_append_basic _glfw.wl.dbus.dbus_message_iter_append_basic_ +#define dbus_message_iter_open_container _glfw.wl.dbus.dbus_message_iter_open_container_ +#define dbus_message_iter_close_container _glfw.wl.dbus.dbus_message_iter_close_container_ +#define dbus_message_iter_get_arg_type _glfw.wl.dbus.dbus_message_iter_get_arg_type_ +#define dbus_message_iter_get_element_type _glfw.wl.dbus.dbus_message_iter_get_element_type_ +#define dbus_message_iter_recurse _glfw.wl.dbus.dbus_message_iter_recurse_ +#define dbus_message_iter_get_element_count _glfw.wl.dbus.dbus_message_iter_get_element_count_ +#define dbus_message_iter_get_basic _glfw.wl.dbus.dbus_message_iter_get_basic_ +#define dbus_message_iter_next _glfw.wl.dbus.dbus_message_iter_next_ + typedef struct _GLFWfallbackEdgeWayland { struct wl_surface* surface; @@ -591,6 +682,29 @@ typedef struct _GLFWlibraryWayland PFN_libdecor_state_new libdecor_state_new_; PFN_libdecor_state_free libdecor_state_free_; } libdecor; + + struct { + void* handle; + PFN_dbus_error_init dbus_error_init_; + PFN_dbus_error_free dbus_error_free_; + PFN_dbus_error_is_set dbus_error_is_set_; + PFN_dbus_bus_get dbus_bus_get_; + PFN_dbus_connection_set_exit_on_disconnect dbus_connection_set_exit_on_disconnect_; + PFN_dbus_connection_send_with_reply_and_block dbus_connection_send_with_reply_and_block_; + PFN_dbus_message_new_method_call dbus_message_new_method_call_; + PFN_dbus_message_unref dbus_message_unref_; + PFN_dbus_message_iter_init dbus_message_iter_init_; + PFN_dbus_message_iter_init_append dbus_message_iter_init_append_; + PFN_dbus_message_iter_append_basic dbus_message_iter_append_basic_; + PFN_dbus_message_iter_open_container dbus_message_iter_open_container_; + PFN_dbus_message_iter_close_container dbus_message_iter_close_container_; + PFN_dbus_message_iter_get_arg_type dbus_message_iter_get_arg_type_; + PFN_dbus_message_iter_get_element_type dbus_message_iter_get_element_type_; + PFN_dbus_message_iter_recurse dbus_message_iter_recurse_; + PFN_dbus_message_iter_get_element_count dbus_message_iter_get_element_count_; + PFN_dbus_message_iter_get_basic dbus_message_iter_get_basic_; + PFN_dbus_message_iter_next dbus_message_iter_next_; + } dbus; } _GLFWlibraryWayland; // Wayland-specific per-monitor data diff --git a/src/wl_window.c b/src/wl_window.c index 8d9d3865c..74dd1e8d6 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -41,7 +41,6 @@ #include #include #include -#include #include "wayland-client-protocol.h" #include "xdg-shell-client-protocol.h" @@ -2038,7 +2037,7 @@ static void dataDeviceHandleEnter(void* userData, _GLFWwindow* window = wl_surface_get_user_data(surface); if (window->wl.surface == surface) { - GLFWbool portal = _glfw.wl.offers[i].portal_file_transfer; + GLFWbool portal = _glfw.wl.offers[i].portal_file_transfer && _glfw.wl.dbus.handle; if (_glfw.wl.offers[i].text_uri_list || portal) { _glfw.wl.dragOffer = offer; @@ -2090,6 +2089,8 @@ static void dataDeviceHandleMotion(void* userData, static void dataDeviceHandleFileTransferPortalDrop(void* userData, struct wl_data_device* device) { + assert(_glfw.wl.dbus.handle != NULL); + char* key = readDataOfferAsString(_glfw.wl.dragOffer, FILE_TRANSFER_PORTAL_MIME_TYPE); if (!key) return; @@ -2104,7 +2105,7 @@ static void dataDeviceHandleFileTransferPortalDrop(void* userData, _glfw_free(key); return; } - dbus_connection_set_exit_on_disconnect(connection, FALSE); + dbus_connection_set_exit_on_disconnect(connection, DBUS_FALSE); DBusMessage* message = dbus_message_new_method_call( "org.freedesktop.portal.Documents",