diff --git a/src/useractions.cpp b/src/useractions.cpp index 1ce973faff..0cc81648b0 100644 --- a/src/useractions.cpp +++ b/src/useractions.cpp @@ -1325,20 +1325,6 @@ static bool screenSwitchImpossible() return true; } -Output *Workspace::nextOutput(Output *reference) const -{ - const int index = m_outputs.indexOf(reference); - Q_ASSERT(index != -1); - return m_outputs[(index + 1) % m_outputs.count()]; -} - -Output *Workspace::previousOutput(Output *reference) const -{ - const int index = m_outputs.indexOf(reference); - Q_ASSERT(index != -1); - return m_outputs[(index + m_outputs.count() - 1) % m_outputs.count()]; -} - void Workspace::slotSwitchToScreen(Output *output) { if (!screenSwitchImpossible()) { diff --git a/src/workspace.cpp b/src/workspace.cpp index e46e5662fb..acbc8893a2 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -5,6 +5,7 @@ SPDX-FileCopyrightText: 1999, 2000 Matthias Ettrich SPDX-FileCopyrightText: 2003 Lubos Lunak SPDX-FileCopyrightText: 2019 Vlad Zahorodnii + SPDX-FileCopyrightText: 2022 Natalie Clarius SPDX-License-Identifier: GPL-2.0-or-later */ @@ -1407,6 +1408,59 @@ Output *Workspace::outputAt(const QPointF &pos) const return bestOutput; } +Output *Workspace::outputFrom(Output *reference, Direction direction, bool wrapAround) const +{ + QList relevantOutputs; + std::copy_if(m_outputs.begin(), m_outputs.end(), std::back_inserter(relevantOutputs), [reference, direction](Output *output) { + switch (direction) { + case DirectionEast: + case DirectionWest: + // filter for outputs on same horizontal line + return output->geometry().top() <= reference->geometry().bottom() && output->geometry().bottom() >= reference->geometry().top(); + case DirectionSouth: + case DirectionNorth: + // filter for outputs on same vertical line + return output->geometry().left() <= reference->geometry().right() && output->geometry().right() >= reference->geometry().left(); + default: + // take all outputs + return true; + } + }); + + std::sort(relevantOutputs.begin(), relevantOutputs.end(), [direction](const Output *o1, const Output *o2) { + switch (direction) { + case DirectionEast: + case DirectionWest: + // order outputs from left to right + return o1->geometry().center().x() < o2->geometry().center().x(); + case DirectionSouth: + case DirectionNorth: + // order outputs from top to bottom + return o1->geometry().center().y() < o2->geometry().center().y(); + default: + // order outputs from top to bottom, then left to right + return (o1->geometry().center().y() < o2->geometry().center().y() || (o1->geometry().center().y() == o2->geometry().center().y() && o1->geometry().center().x() < o2->geometry().center().x())); + } + }); + + const int index = relevantOutputs.indexOf(reference); + Q_ASSERT(index != -1); + switch (direction) { + case DirectionEast: + case DirectionSouth: + case DirectionNext: + // go forward in the list + return relevantOutputs[wrapAround ? (index + 1) % relevantOutputs.count() : std::min(index + 1, (int)relevantOutputs.count() - 1)]; + case DirectionWest: + case DirectionNorth: + case DirectionPrev: + // go backward in the list + return relevantOutputs[wrapAround ? (index + relevantOutputs.count() - 1) % relevantOutputs.count() : std::max(index - 1, 0)]; + default: + Q_UNREACHABLE(); + } +} + void Workspace::slotOutputBackendOutputsQueried() { if (waylandServer()) { diff --git a/src/workspace.h b/src/workspace.h index 4d9b85533a..fb094183fe 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -6,6 +6,7 @@ SPDX-FileCopyrightText: 2003 Lubos Lunak SPDX-FileCopyrightText: 2009 Lucas Murray SPDX-FileCopyrightText: 2019 Vlad Zahorodnii + SPDX-FileCopyrightText: 2022 Natalie Clarius SPDX-License-Identifier: GPL-2.0-or-later */ @@ -354,8 +355,15 @@ public: // D-Bus interface QString supportInformation() const; - Output *nextOutput(Output *reference) const; - Output *previousOutput(Output *reference) const; + enum Direction { + DirectionNorth, + DirectionEast, + DirectionSouth, + DirectionWest, + DirectionPrev, + DirectionNext + }; + Output *outputFrom(Output *reference, Direction direction, bool wrapAround = false) const; void switchToOutput(Output *output); QList outputs() const;