https://bugs.kde.org/show_bug.cgi?id=522547
[email protected] changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #13 from [email protected] --- Root cause found, with a deterministic reproducer (client side, KWindowSystem). Environment: Plasma 6.7.5, KWin 6.7.5, KWindowSystem 6.30.0, Qt 6.11.2, Wayland, widget style Kvantum 1.1.8 (through qt6ct-style) with translucent, blurred menus. REPRODUCER (plasmashell dies every time) 1. Put the stock Global Menu widget in full view (not compact) on a panel. 2. Open KWrite and leave it on its Welcome page: its Edit menu then has only hidden entries. 3. Click "File" in the Global Menu, move the pointer to "Edit" (the applet shows its shared proxy menu with no visible entries, a 9x9 frame), click outside to close the menu, click "File" again. 4. plasmashell is disconnected with "tried to set blur region on destroyed surface". WAYLAND_DEBUG=client of plasmashell (object ids from one run): -> ext_background_effect_surface_v1#236.destroy() -> ext_background_effect_manager_v1#43.get_background_effect(new id ext_background_effect_surface_v1#250, wl_surface#228) -> ext_background_effect_surface_v1#250.set_blur_region(nil) ... the menu is closed, which destroys its QWindow's platform window: -> wl_surface#228.destroy() (#250 is never destroyed) ... the menu is shown again: -> ext_background_effect_surface_v1#250.set_blur_region(wl_region#240) wl_display#1.error(ext_background_effect_surface_v1#250, 0, "tried to set blur region on destroyed surface") The first three lines are one KWindowEffects::enableBlurBehind(window, false) call. Kvantum makes it when a menu has no blur region left (BlurHelper::update() -> clear(), in Kvantum/style/blur/blurhelper.cpp), which is the case for the empty 9x9 menu. In src/platforms/wayland/windoweffects.cpp: void WindowEffects::enableBlurBehind(QWindow *window, bool enable, const QRegion ®ion) { if (enable) { ... } else { if (!m_blurRegions.remove(window)) { return; } resetBlur(window); // destroys the old ext_background_effect_surface_v1 (#236) releaseWindow(window); // stops watching the window and its surfaceDestroyed() } installBlur(window, enable, region); } With the ext_background_effect manager, installBlur(window, false, ...) does `auto &effect = m_backgroundEffects[window]; if (!effect) effect = ...get_background_effect(surface);` and sets a NULL region: it creates a new object (#250) and keeps it in m_backgroundEffects for a window that is no longer tracked. When that window's surface is destroyed (QWindow::close() destroys the platform window: a menu closed by Escape, by an activated item or by the compositor), no surfaceDestroyed watcher resets it. The next enableBlurBehind(window, true, ...) tracks the window again, finds the stale object in m_backgroundEffects and calls set_blur_region on it, which is the fatal error. This also explains the other triggers in this report: any code that switches the blur of a window off (Kvantum does it for menus without a blur region and, with "blur only the active window", for inactive windows) and then closes and reopens the same QWindow. No pointer reuse is needed for it. Possible fix: do not create an object just to remove the blur. Destroying the old object already removes it ("The effect regions will be removed on the next commit"): --- a/src/platforms/wayland/windoweffects.cpp +++ b/src/platforms/wayland/windoweffects.cpp @@ void WindowEffects::installBlur(QWindow *window, bool enable, const QRegion ®ion) if (m_backgroundEffectManager->isActive()) { replaceValue(m_blurs, window, nullptr); + if (!enable) { + m_backgroundEffects.erase(window); + return; + } if (!m_backgroundEffectManager->supportsBlur) { This is also why the client-side attempt in comment 10 did not help: the object is created for the window's surface while that surface is still alive, and becomes stale only when the surface is destroyed, which nothing observes any more. The reopened window's new surface can get the same address, so comparing surface pointers cannot tell them apart. The KWin change from comment 11 (https://invent.kde.org/plasma/kwin/-/merge_requests/10004) stops the disconnects, and the change above removes the stale object on the client side, so the reopened popup gets a new, working object and keeps its blur. Workaround for code that owns the menus: hide popups instead of letting QWindow::close() destroy their platform window (ignore the QCloseEvent of the QMenu and hide() it), so their surface lives as long as the QWindow. The Application Title Bar with App Menu widget (https://github.com/uselessfire/application-title-bar-appmenu) does that and survives the reproducer above. -- You are receiving this mail because: You are watching all bug changes.
