From 98a949f997f96687e6977b8b30644d535fe92446 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 Jul 2025 04:56:39 +0000 Subject: [PATCH 1/2] Fix #141846: Successive calls to change the cursor exits on Wayland Calling wm.progress_update() from Python in a loop would exit under Wayland. Resolve by calling wl_display_dispatch after changing the cursor. --- intern/ghost/intern/GHOST_WindowWayland.cc | 42 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cc b/intern/ghost/intern/GHOST_WindowWayland.cc index c6ccf61e7e1..4584a456607 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cc +++ b/intern/ghost/intern/GHOST_WindowWayland.cc @@ -56,6 +56,22 @@ /* Logging, use `ghost.wl.*` prefix. */ #include "CLG_log.h" +/** + * Note that for almost all cases a call to `wl_display_dispatch` is *not* needed. + * Without the dispatch though, calls to set the cursor while the event loop is + * not being processed causes a resource allocation failure - disconnecting the + * WAYLAND compositor (effectively crashing). + * While this only happens when many calls are made, that's exactly what happens in the + * case of the "progress" feature which uses the cursor to display a number. + * See: #141846. + * + * Observed behavior when changing cursors without a dispatch: + * - Eventually exits with an error on all compositors tested (KDE/GNOME/WLROOTS based). + * - Won't re-display at all (on KDE 6.4). + * Note that this could be a bug in KDE as it works in GNOME & WLROOTS based compositors. + */ +#define USE_CURSOR_IMMEDIATE_DISPATCH + /** * LIBDECOR support committing a window-configuration in the main-thread that was * handled in a non-main-thread. @@ -2242,10 +2258,18 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor s ok_test = system_->cursor_shape_set(m_cursorShape); } - if (ok_test == GHOST_kFailure) { - /* For the cursor to display when the event queue isn't being handled. */ - wl_display_flush(system_->wl_display_get()); + wl_display *display = system_->wl_display_get(); +#ifdef USE_CURSOR_IMMEDIATE_DISPATCH + if (ok == GHOST_kSuccess || ok_test == GHOST_kSuccess) { + wl_display_flush(display); + wl_display_dispatch(display); } + else +#endif /* USE_CURSOR_IMMEDIATE_DISPATCH */ + if (ok_test == GHOST_kFailure) { + /* For the cursor to display when the event queue isn't being handled. */ + wl_display_flush(display); + } } else { /* Set later when activating the window. */ @@ -2291,8 +2315,12 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape( ok_test = system_->cursor_shape_set(m_cursorShape); } if (ok_test == GHOST_kSuccess) { + wl_display *display = system_->wl_display_get(); /* For the cursor to display when the event queue isn't being handled. */ - wl_display_flush(system_->wl_display_get()); + wl_display_flush(display); +#ifdef USE_CURSOR_IMMEDIATE_DISPATCH + wl_display_dispatch(display); +#endif } } else { @@ -2405,8 +2433,12 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) #endif const GHOST_TSuccess ok = system_->cursor_visibility_set(visible); if (ok == GHOST_kSuccess) { + wl_display *display = system_->wl_display_get(); /* For the cursor to display when the event queue isn't being handled. */ - wl_display_flush(system_->wl_display_get()); + wl_display_flush(display); +#ifdef USE_CURSOR_IMMEDIATE_DISPATCH + wl_display_dispatch(display); +#endif } return ok; } From 601b5f49f0cb4291c1b808a3e1ddb545c0fc356e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 13 Jul 2025 15:43:22 +1000 Subject: [PATCH 2/2] Disable fix for #141846 While this works in 4.5x it could lock the UI in some cases in main. Avoid possible regressions & disable for now. --- intern/ghost/intern/GHOST_WindowWayland.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cc b/intern/ghost/intern/GHOST_WindowWayland.cc index 4584a456607..9845304a9c9 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cc +++ b/intern/ghost/intern/GHOST_WindowWayland.cc @@ -56,8 +56,11 @@ /* Logging, use `ghost.wl.*` prefix. */ #include "CLG_log.h" + +/* Disable, as this can "lock" the GUI even with the *pending* version of dispatch is used. */ +#if 0 /** - * Note that for almost all cases a call to `wl_display_dispatch` is *not* needed. + * Note that for almost all cases a call to `wl_display_dispatch_pending` is *not* needed. * Without the dispatch though, calls to set the cursor while the event loop is * not being processed causes a resource allocation failure - disconnecting the * WAYLAND compositor (effectively crashing). @@ -71,6 +74,7 @@ * Note that this could be a bug in KDE as it works in GNOME & WLROOTS based compositors. */ #define USE_CURSOR_IMMEDIATE_DISPATCH +#endif /** * LIBDECOR support committing a window-configuration in the main-thread that was @@ -2262,7 +2266,7 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor s #ifdef USE_CURSOR_IMMEDIATE_DISPATCH if (ok == GHOST_kSuccess || ok_test == GHOST_kSuccess) { wl_display_flush(display); - wl_display_dispatch(display); + wl_display_dispatch_pending(display); } else #endif /* USE_CURSOR_IMMEDIATE_DISPATCH */ @@ -2319,7 +2323,7 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape( /* For the cursor to display when the event queue isn't being handled. */ wl_display_flush(display); #ifdef USE_CURSOR_IMMEDIATE_DISPATCH - wl_display_dispatch(display); + wl_display_dispatch_pending(display); #endif } } @@ -2437,7 +2441,7 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible) /* For the cursor to display when the event queue isn't being handled. */ wl_display_flush(display); #ifdef USE_CURSOR_IMMEDIATE_DISPATCH - wl_display_dispatch(display); + wl_display_dispatch_pending(display); #endif } return ok;