quick tiling: find target output by direction

master
Natalie Clarius 2 years ago committed by Vlad Zahorodnii
parent 67c558286f
commit 0053c782a1

@ -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);

@ -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));
}
}

@ -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<Output *> 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.

@ -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<Output *> relevantOutputs;
std::copy_if(m_outputs.begin(), m_outputs.end(), std::back_inserter(relevantOutputs), [reference, direction](Output *output) {

@ -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<Output *> outputs() const;

Loading…
Cancel
Save