[Bf-blender-cvs] [cbd12e730af] master: Fix T103586: Crash removing monitor under Wayland & WLROOTS compositors

Campbell Barton noreply at git.blender.org
Wed Jan 4 06:12:46 CET 2023


Commit: cbd12e730af55d16dfcf3c9aa8ff5f3e6bc8d0ec
Author: Campbell Barton
Date:   Wed Jan 4 15:57:38 2023 +1100
Branches: master
https://developer.blender.org/rBcbd12e730af55d16dfcf3c9aa8ff5f3e6bc8d0ec

Fix T103586: Crash removing monitor under Wayland & WLROOTS compositors

WLROOTS compositors don't run surface leave callbacks,
while this may be considered a bug in WLROOTS, neither GTK/SDL crash
so workaround the crash too.

This also fixes a minor glitch where the cursor scale wasn't updated
when changing monitor scale at run-time.

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

M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h

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

diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 8cd7cde79b9..42e56aa74ab 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -4535,18 +4535,7 @@ static void output_handle_scale(void *data, struct wl_output * /*wl_output*/, co
   CLOG_INFO(LOG, 2, "scale");
   GWL_Output *output = static_cast<GWL_Output *>(data);
   output->scale = factor;
-
-  GHOST_WindowManager *window_manager = output->system->getWindowManager();
-  if (window_manager) {
-    for (GHOST_IWindow *iwin : window_manager->getWindows()) {
-      GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
-      const std::vector<GWL_Output *> &outputs = win->outputs();
-      if (std::find(outputs.begin(), outputs.end(), output) == outputs.cend()) {
-        continue;
-      }
-      win->outputs_changed_update_scale();
-    }
-  }
+  output->system->output_scale_update_maybe_leave(output, false);
 }
 
 static const struct wl_output_listener output_listener = {
@@ -4736,11 +4725,21 @@ static void gwl_registry_wl_output_update(GWL_Display *display,
 }
 static void gwl_registry_wl_output_remove(GWL_Display *display,
                                           void *user_data,
-                                          const bool /*on_exit*/)
+                                          const bool on_exit)
 {
   /* While windows & cursors hold references to outputs, there is no need to manually remove
-   * these references as the compositor will remove references via #wl_surface_listener.leave. */
+   * these references as the compositor will remove references via #wl_surface_listener.leave.
+   *
+   * WARNING: this is not the case for WLROOTS based compositors which have a (bug?)
+   * where surface leave events don't run. So `system->output_leave(..)` is needed
+   * until the issue is resolved in WLROOTS. */
   GWL_Output *output = static_cast<GWL_Output *>(user_data);
+
+  if (!on_exit) {
+    /* Needed for WLROOTS, does nothing if surface leave callbacks have already run. */
+    output->system->output_scale_update_maybe_leave(output, true);
+  }
+
   if (output->xdg_output) {
     zxdg_output_v1_destroy(output->xdg_output);
   }
@@ -6765,6 +6764,49 @@ void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface)
 #undef SURFACE_CLEAR_PTR
 }
 
+void GHOST_SystemWayland::output_scale_update_maybe_leave(GWL_Output *output, bool leave)
+{
+  /* Update scale, optionally leaving the outputs beforehand. */
+  GHOST_WindowManager *window_manager = output->system->getWindowManager();
+  if (window_manager) {
+    for (GHOST_IWindow *iwin : window_manager->getWindows()) {
+      GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
+      const std::vector<GWL_Output *> &outputs = win->outputs();
+      bool found = leave ? win->outputs_leave(output) :
+                           !(std::find(outputs.begin(), outputs.end(), output) == outputs.cend());
+      if (found) {
+        win->outputs_changed_update_scale();
+      }
+    }
+  }
+
+  for (GWL_Seat *seat : display_->seats) {
+    bool found;
+
+    found = leave ? seat->pointer.outputs.erase(output) : seat->pointer.outputs.count(output);
+    if (found) {
+      if (seat->cursor.wl_surface_cursor != nullptr) {
+        update_cursor_scale(
+            seat->cursor, seat->system->wl_shm(), &seat->pointer, seat->cursor.wl_surface_cursor);
+      }
+    }
+
+    found = leave ? seat->tablet.outputs.erase(output) : seat->tablet.outputs.count(output);
+    if (found) {
+      for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
+        GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
+            zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
+        if (tablet_tool->wl_surface_cursor != nullptr) {
+          update_cursor_scale(seat->cursor,
+                              seat->system->wl_shm(),
+                              &seat->pointer,
+                              tablet_tool->wl_surface_cursor);
+        }
+      }
+    }
+  }
+}
+
 bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mode,
                                                  const GHOST_TGrabCursorMode mode_current,
                                                  int32_t init_grab_xy[2],
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index c762b4817c6..c102a3d7a12 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -194,6 +194,8 @@ class GHOST_SystemWayland : public GHOST_System {
   /** Set this seat to be active. */
   void seat_active_set(const struct GWL_Seat *seat);
 
+  void output_scale_update_maybe_leave(GWL_Output *output, bool leave);
+
   /** Clear all references to this surface to prevent accessing NULL pointers. */
   void window_surface_unref(const wl_surface *wl_surface);



More information about the Bf-blender-cvs mailing list