[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