[Bf-blender-cvs] [00aa57594c7] master: Fix dropping files in Wayland

Campbell Barton noreply at git.blender.org
Fri Jun 10 10:44:22 CEST 2022


Commit: 00aa57594c74c69d53ba326e48d2d1339ab99b75
Author: Campbell Barton
Date:   Fri Jun 10 16:32:22 2022 +1000
Branches: master
https://developer.blender.org/rB00aa57594c74c69d53ba326e48d2d1339ab99b75

Fix dropping files in Wayland

There were two problems dropping files into blender:

- The inputs `focus_pointer` was NULL, causing a crash.
- The wl_data_device_manager version was set to 1, causing the Blender
  window to close (when dropping files in gnome-shell 42).

Resolve by storing the drop surface separately from the pointer surface
and bump the device manager version to 3.

===================================================================

M	intern/ghost/intern/GHOST_SystemWayland.cpp

===================================================================

diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index c446963c082..b9696ab6354 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -38,6 +38,8 @@
 
 #include <cstring>
 
+static GHOST_IWindow *get_window(struct wl_surface *surface);
+
 /* -------------------------------------------------------------------- */
 /** \name Private Types & Defines
  * \{ */
@@ -131,6 +133,7 @@ struct input_t {
 
   struct wl_surface *focus_pointer = nullptr;
   struct wl_surface *focus_keyboard = nullptr;
+  struct wl_surface *focus_dnd = nullptr;
 
   struct wl_data_device *data_device = nullptr;
   /** Drag & Drop. */
@@ -508,7 +511,7 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event)
 {
   const uint64_t time = input->system->getMilliSeconds();
   GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>(
-      wl_surface_get_user_data(input->focus_pointer));
+      wl_surface_get_user_data(input->focus_dnd));
   for (const std::string &type : mime_preference_order) {
     input->system->pushEvent(new GHOST_EventDragnDrop(time,
                                                       event,
@@ -670,7 +673,7 @@ static void data_device_data_offer(void * /*data*/,
 static void data_device_enter(void *data,
                               struct wl_data_device * /*wl_data_device*/,
                               uint32_t serial,
-                              struct wl_surface * /*surface*/,
+                              struct wl_surface *surface,
                               wl_fixed_t x,
                               wl_fixed_t y,
                               struct wl_data_offer *id)
@@ -692,6 +695,7 @@ static void data_device_enter(void *data,
     wl_data_offer_accept(id, serial, type.c_str());
   }
 
+  input->focus_dnd = surface;
   dnd_events(input, GHOST_kEventDraggingEntered);
 }
 
@@ -700,6 +704,7 @@ static void data_device_leave(void *data, struct wl_data_device * /*wl_data_devi
   input_t *input = static_cast<input_t *>(data);
 
   dnd_events(input, GHOST_kEventDraggingExited);
+  input->focus_dnd = nullptr;
 
   if (input->data_offer_dnd && !input->data_offer_dnd->in_use.load()) {
     wl_data_offer_destroy(input->data_offer_dnd->id);
@@ -732,6 +737,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
 
   auto read_uris = [](input_t *const input,
                       data_offer_t *data_offer,
+                      wl_surface *surface,
                       const std::string mime_receive) {
     const int x = data_offer->dnd.x;
     const int y = data_offer->dnd.y;
@@ -750,6 +756,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
       static constexpr const char *file_proto = "file://";
       static constexpr const char *crlf = "\r\n";
 
+      GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(surface));
+      GHOST_ASSERT(win != nullptr, "Unable to find window for drop event from surface");
+
       std::vector<std::string> uris;
 
       size_t pos = 0;
@@ -773,8 +782,6 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
         flist->strings[i] = static_cast<uint8_t *>(malloc((uris[i].size() + 1) * sizeof(uint8_t)));
         memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
       }
-      GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
-          wl_surface_get_user_data(input->focus_pointer));
       system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
                                                  GHOST_kEventDraggingDropDone,
                                                  GHOST_kDragnDropTypeFilenames,
@@ -790,7 +797,9 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
     wl_display_roundtrip(system->display());
   };
 
-  std::thread read_thread(read_uris, input, data_offer, mime_receive);
+  /* Pass in `input->focus_dnd` instead of accessing it from `input` since the leave callback
+   * (#data_device_leave) will clear the value once this function starts. */
+  std::thread read_thread(read_uris, input, data_offer, input->focus_dnd, mime_receive);
   read_thread.detach();
 }
 
@@ -1480,7 +1489,7 @@ static void global_add(void *data,
   }
   else if (!strcmp(interface, wl_data_device_manager_interface.name)) {
     display->data_device_manager = static_cast<wl_data_device_manager *>(
-        wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 1));
+        wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3));
   }
   else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name)) {
     display->relative_pointer_manager = static_cast<zwp_relative_pointer_manager_v1 *>(



More information about the Bf-blender-cvs mailing list