diff --git a/autotests/integration/quick_tiling_test.cpp b/autotests/integration/quick_tiling_test.cpp index efbdfe2444..60ed17f81b 100644 --- a/autotests/integration/quick_tiling_test.cpp +++ b/autotests/integration/quick_tiling_test.cpp @@ -14,6 +14,7 @@ #include "decorations/decorationbridge.h" #include "decorations/settings.h" #include "scripting/scripting.h" +#include "utils/common.h" #include "wayland_server.h" #include "window.h" #include "workspace.h" @@ -130,9 +131,9 @@ void QuickTilingTest::testQuickTiling_data() #define FLAG(name) QuickTileMode(QuickTileFlag::name) QTest::newRow("left") << FLAG(Left) << QRectF(0, 0, 640, 1024) << QRectF(1280, 0, 640, 1024) << FLAG(Right); - QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << QRectF(1280, 0, 1280, 512) << FLAG(Top); + QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << QRectF(1280, 0, 1280, 512) << QuickTileMode(); QTest::newRow("right") << FLAG(Right) << QRectF(640, 0, 640, 1024) << QRectF(1920, 0, 640, 1024) << QuickTileMode(); - QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << QRectF(1280, 512, 1280, 512) << FLAG(Bottom); + QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << QRectF(1280, 512, 1280, 512) << QuickTileMode(); QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRectF(0, 0, 640, 512) << QRectF(1280, 0, 640, 512) << (FLAG(Right) | FLAG(Top)); QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRectF(640, 0, 640, 512) << QRectF(1920, 0, 640, 512) << QuickTileMode(); @@ -535,9 +536,9 @@ void QuickTilingTest::testX11QuickTiling_data() #define FLAG(name) QuickTileMode(QuickTileFlag::name) QTest::newRow("left") << FLAG(Left) << QRectF(0, 0, 640, 1024) << 0 << QuickTileMode(); - QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << 1 << FLAG(Top); + QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << 0 << QuickTileMode(); QTest::newRow("right") << FLAG(Right) << QRectF(640, 0, 640, 1024) << 1 << FLAG(Left); - QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << 1 << FLAG(Bottom); + QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << 0 << QuickTileMode(); QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRectF(0, 0, 640, 512) << 0 << QuickTileMode(); QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRectF(640, 0, 640, 512) << 1 << (FLAG(Left) | FLAG(Top)); @@ -587,6 +588,7 @@ void QuickTilingTest::testX11QuickTiling() QCOMPARE(quickTileChangedSpy.count(), 1); // quick tile to same edge again should also act like send to screen + // if screen is on the same edge const auto outputs = workspace()->outputs(); QCOMPARE(window->output(), outputs[0]); window->setQuickTileMode(mode, true); diff --git a/src/useractions.cpp b/src/useractions.cpp index 4b96bdce49..bc37f2d955 100644 --- a/src/useractions.cpp +++ b/src/useractions.cpp @@ -1353,42 +1353,42 @@ void Workspace::slotSwitchToScreen(Output *output) void Workspace::slotSwitchToLeftScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionWest, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionWest, true)); } } void Workspace::slotSwitchToRightScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionEast, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionEast, true)); } } void Workspace::slotSwitchToAboveScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionNorth, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionNorth, true)); } } void Workspace::slotSwitchToBelowScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionSouth, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionSouth, true)); } } void Workspace::slotSwitchToPrevScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionPrev, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionPrev, true)); } } void Workspace::slotSwitchToNextScreen() { if (!screenSwitchImpossible()) { - switchToOutput(outputFrom(activeOutput(), Direction::DirectionNext, true)); + switchToOutput(findOutput(activeOutput(), Direction::DirectionNext, true)); } } @@ -1402,42 +1402,42 @@ void Workspace::slotWindowToScreen(Output *output) void Workspace::slotWindowToLeftScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionWest, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionWest, true)); } } void Workspace::slotWindowToRightScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionEast, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionEast, true)); } } void Workspace::slotWindowToAboveScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionNorth, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionNorth, true)); } } void Workspace::slotWindowToBelowScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionSouth, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionSouth, true)); } } void Workspace::slotWindowToPrevScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionPrev, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionPrev, true)); } } void Workspace::slotWindowToNextScreen() { if (USABLE_ACTIVE_WINDOW) { - sendWindowToOutput(m_activeWindow, outputFrom(m_activeWindow->output(), Direction::DirectionNext, true)); + sendWindowToOutput(m_activeWindow, findOutput(m_activeWindow->output(), Direction::DirectionNext, true)); } } diff --git a/src/window.cpp b/src/window.cpp index 38fd188447..ed14e1e4ba 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -11,6 +11,7 @@ #include "core/output.h" #include "tiles/tilemanager.h" +#include "utils/common.h" #if KWIN_BUILD_ACTIVITIES #include "activities.h" @@ -3860,49 +3861,40 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard) QPointF whichScreen = keyboard ? moveResizeGeometry().center() : Cursors::self()->mouse()->pos(); if (mode != QuickTileMode(QuickTileFlag::None)) { // If trying to tile to the side that the window is already tiled to move the window to the next - // screen if it exists, otherwise toggle the mode (set QuickTileFlag::None) + // screen near the tile if it exists and swap the tile side, otherwise toggle the mode (set QuickTileFlag::None) if (quickTileMode() == mode) { - const QList outputs = workspace()->outputs(); - const Output *currentOutput = moveResizeOutput(); - const Output *nextOutput = currentOutput; - - for (const Output *output : outputs) { - if (output == currentOutput) { - continue; - } - - if (output->geometry().bottom() <= currentOutput->geometry().top() - || output->geometry().top() >= currentOutput->geometry().bottom()) { - continue; // not in horizontal line - } - - const int x = output->geometry().center().x(); - if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Left)) { - if (x >= currentOutput->geometry().center().x() - || (currentOutput != nextOutput && x <= nextOutput->geometry().center().x())) { - continue; // not left of current or more left then found next - } - } else if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Right)) { - if (x <= currentOutput->geometry().center().x() - || (currentOutput != nextOutput && x >= nextOutput->geometry().center().x())) { - continue; // not right of current or more right then found next - } - } - - nextOutput = output; + Output *currentOutput = moveResizeOutput(); + Output *nextOutput = currentOutput; + Output *candidateOutput = currentOutput; + if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Left)) { + candidateOutput = workspace()->findOutput(nextOutput, Workspace::DirectionWest); + } else if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Right)) { + candidateOutput = workspace()->findOutput(nextOutput, Workspace::DirectionEast); + } + bool shiftHorizontal = candidateOutput != nextOutput; + nextOutput = candidateOutput; + if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Top)) { + candidateOutput = workspace()->findOutput(nextOutput, Workspace::DirectionNorth); + } else if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Bottom)) { + candidateOutput = workspace()->findOutput(nextOutput, Workspace::DirectionSouth); } + bool shiftVertical = candidateOutput != nextOutput; + nextOutput = candidateOutput; if (nextOutput == currentOutput) { - mode = QuickTileFlag::None; // No other screens, toggle tiling + mode = QuickTileFlag::None; // No other screens in the tile direction, toggle tiling } else { // Move to other screen moveResize(geometryRestore().translated(nextOutput->geometry().topLeft() - currentOutput->geometry().topLeft())); whichScreen = nextOutput->geometry().center(); // Swap sides - if (mode & QuickTileFlag::Horizontal) { + if (shiftHorizontal) { mode = (~mode & QuickTileFlag::Horizontal) | (mode & QuickTileFlag::Vertical); } + if (shiftVertical) { + mode = (~mode & QuickTileFlag::Vertical) | (mode & QuickTileFlag::Horizontal); + } } } else if (quickTileMode() == QuickTileMode(QuickTileFlag::None)) { // Not coming out of an existing tile, not shifting monitors, we're setting a brand new tile. diff --git a/src/workspace.cpp b/src/workspace.cpp index acbc8893a2..1736dc1ddc 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -1408,7 +1408,7 @@ Output *Workspace::outputAt(const QPointF &pos) const return bestOutput; } -Output *Workspace::outputFrom(Output *reference, Direction direction, bool wrapAround) const +Output *Workspace::findOutput(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) { diff --git a/src/workspace.h b/src/workspace.h index 4c6273cb38..83eefdc036 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -363,7 +363,7 @@ public: DirectionPrev, DirectionNext }; - Output *outputFrom(Output *reference, Direction direction, bool wrapAround = false) const; + Output *findOutput(Output *reference, Direction direction, bool wrapAround = false) const; void switchToOutput(Output *output); QList outputs() const;