https://bugs.kde.org/show_bug.cgi?id=517915
Tanner(Cyborgized With Claude) <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #7 from Tanner(Cyborgized With Claude) <[email protected]> --- Same root cause, with numbers and a tested patch, from a Plasma 6.7.5 Wayland session (Bazzite / Fedora 45): DP-2 2560x1440 primary at 0,0, HDMI-A-1 1920x1080 at 2560,0 (tops aligned), a 46 px panel at the bottom of each. $ xprop -root _NET_WORKAREA _NET_WORKAREA(CARDINAL) = 0, 0, 4480, 1034 1034 = 1080 - 46: the panel at the bottom of the *shorter* monitor, whose edge lies inside the virtual screen, clips the global work area for the taller primary too. Workspace::rearrange() does workArea &= adjustClientArea(window, m_geometry) for every strut; LayerShellV1Window::strutRect() is the exclusive zone, and adjustClientArea() applies it to the global area as soon as it intersects it, which a strut always does. Steam's desktop toasts (steam-for-linux #12468, https://github.com/ValveSoftware/steam-for-linux/issues/12468) are placed inside "primary bounds ∩ _NET_WORKAREA", so they rest 360 px above the primary's panel; the offset window positions in this report are the same rectangle at work (with top panels it is the y origin that moves). Agreed that one rectangle can't be right for everyone - but one of the two wrong choices is cheaper, and it is the one the X11 session makes: kwin-x11's hasOffscreenXineramaStrut() drops a strut that runs through the offscreen part of the virtual screen (which is what an X11 panel on a shorter monitor produces) from the global work area, while the per-output screen areas still honour it. The big X11 toolkits apply _NET_WORKAREA to the primary monitor only: GTK3 (gdk_x11_monitor_get_workarea: "we ignore the workarea for anything but the primary monitor"), Chromium/CEF (x11_display_util.cc ClipWorkArea: "intersect the work area with the primary display, like GTK does"), and Steam asks for the primary ("default") monitor's usable rect. For all of them a strut from a non-primary panel can never be honoured on its own monitor; its only possible effect is to cut a strip off the primary that nothing reserves. (Qt-xcb and SDL intersect the rectangle with every screen, so they are the ones the current rule helps on the secondary - and hurts on the primary just the same.) Patch against 6.7.5 (applies to current master with a 3-line offset): in Workspace::adjustClientArea() a strut only shrinks |area| if its output's edge coincides with |area|'s edge. For the per-output areas the condition always holds, so maximize/placement are untouched; only the global rectangle that becomes _NET_WORKAREA changes, and only for panels on outputs that don't reach the virtual-screen edge. --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -2397,16 +2397,24 @@ RectF Workspace::adjustClientArea(Window *window, const RectF &area) const strutTop.setTop(std::max(strutTop.top(), screenArea.top())); strutBottom.setBottom(std::min(strutBottom.bottom(), screenArea.bottom())); - if (strutLeft.intersects(area)) { + // A strut shrinks |area| only if the output edge it is reserved on is also an edge of |area|. For an output's + // own area that is always the case. For the whole virtual screen (the single X11 _NET_WORKAREA rectangle) it + // is not when the panel sits on an output whose edge lies inside the virtual screen, e.g. the bottom panel of a + // 1080p monitor placed next to a 1440p one: X11 clients apply _NET_WORKAREA to the primary output only (GTK3, + // Chromium/CEF, Steam), so such a strut could only ever cut into a monitor it does not belong to. The X11 + // session has the same rule (hasOffscreenXineramaStrut() in kwin-x11: an X11 strut from such a panel runs + // through the offscreen part of the virtual screen); layer-shell exclusive zones never extend offscreen and + // were therefore never exempted, which is why this only shows in the Wayland session. + if (strutLeft.intersects(area) && screenArea.left() <= area.left()) { adjustedArea.setLeft(strutLeft.right()); } - if (strutRight.intersects(area)) { + if (strutRight.intersects(area) && screenArea.right() >= area.right()) { adjustedArea.setRight(strutRight.left()); } - if (strutTop.intersects(area)) { + if (strutTop.intersects(area) && screenArea.top() <= area.top()) { adjustedArea.setTop(strutTop.bottom()); } - if (strutBottom.intersects(area)) { + if (strutBottom.intersects(area) && screenArea.bottom() >= area.bottom()) { adjustedArea.setBottom(strutBottom.top()); } Tested: kwin 6.7.5 rebuilt with this (Fedora srpm + the patch, installed via rpm-ostree override), running since 2026-10-17. With both panels visible and the monitors top-aligned, _NET_WORKAREA is now 0, 0, 4480, 1394; Steam's own SteamClient.Window.GetDefaultMonitorDimensions() (queried over its CEF debugging port) reports the usable rect as 2560x1394, which puts its toast anchor on the primary's panel (2544,1378 instead of 2544,1018); maximized windows and placement on both outputs unchanged. Happy to turn this into an MR if there is any appetite for it. Full disclosure: the investigation and the patch were done with an AI assistant (Claude) working on my machine; the measurements and the test are from the real session. -- You are receiving this mail because: You are watching all bug changes.
