From 274922caafb440af41c4add2c5047c52f97e3217 Mon Sep 17 00:00:00 2001 From: Natalie Clarius Date: Wed, 14 Sep 2022 00:46:04 +0200 Subject: [PATCH] placement: cascade if window would completely overlap another window BUG: 58063 --- src/placement.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/placement.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/src/placement.cpp b/src/placement.cpp index df27643956..827f5289a5 100644 --- a/src/placement.cpp +++ b/src/placement.cpp @@ -5,6 +5,7 @@ SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich SPDX-FileCopyrightText: 1997-2002 Cristian Tibirna SPDX-FileCopyrightText: 2003 Lubos Lunak + SPDX-FileCopyrightText: 2022 Natalie Clarius SPDX-License-Identifier: GPL-2.0-or-later */ @@ -585,6 +586,44 @@ void Placement::placeMaximizing(Window *c, const QRect &area, PlacementPolicy ne } } +/** + * Cascade the window until it no longer fully overlaps any other window + */ +void Placement::cascadeIfCovering(Window *window, const QRectF &area) +{ + const QPoint offset = workspace()->cascadeOffset(window); + + VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front(); + + QRectF possibleGeo = window->frameGeometry(); + bool noOverlap = false; + + // cascade until confirmed no total overlap or not enough space to cascade + while (!noOverlap) { + noOverlap = true; + // check current position candidate for overlaps with other windows + for (auto l = workspace()->stackingOrder().crbegin(); l != workspace()->stackingOrder().crend(); ++l) { + auto other = *l; + if (isIrrelevant(other, window, desktop)) { + continue; + } + + if (possibleGeo.contains(other->frameGeometry())) { + // placed window would completely overlap the other window: try to cascade it from the topleft of that other window + noOverlap = false; + possibleGeo.moveTopLeft(other->pos() + offset); + if (possibleGeo.right() > area.right() || possibleGeo.bottom() > area.bottom()) { + // new cascaded geometry would be out of the bounds of the placement area: abort the cascading and keep the window in the original position + return; + } + break; + } + } + } + + window->move(possibleGeo.topLeft()); +} + void Placement::cascadeDesktop() { Workspace *ws = Workspace::self(); diff --git a/src/placement.h b/src/placement.h index 28b8288af7..defd2825aa 100644 --- a/src/placement.h +++ b/src/placement.h @@ -37,6 +37,8 @@ public: void reinitCascading(int desktop); + void cascadeIfCovering(Window *c, const QRectF &area); + /** * Cascades all clients on the current desktop */