window: make setQuickTileMode more sane
...by removing the keyboard flag, moving keyboard shortcut handling into a separate method and making the position to tile the window at explicit This also means KWin doesn't do as many intermediary changes to window geometry on output hotplugs, which may work around some clients not always reacting to no-op changes. CCBUG: 479694
This commit is contained in:
parent
16ff6d777a
commit
370c9c8953
7 changed files with 81 additions and 94 deletions
|
@ -819,7 +819,7 @@ void MoveResizeWindowTest::testCancelInteractiveMoveResize()
|
|||
if (maximizeMode) {
|
||||
window->setMaximize(maximizeMode & MaximizeMode::MaximizeVertical, maximizeMode & MaximizeMode::MaximizeHorizontal);
|
||||
} else {
|
||||
window->setQuickTileMode(quickTileMode, true);
|
||||
window->setQuickTileModeAtCurrentPosition(quickTileMode);
|
||||
}
|
||||
if (quickTileMode == QuickTileFlag::Maximize) {
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileFlag::None);
|
||||
|
|
|
@ -491,7 +491,7 @@ void OutputChangesTest::testQuickTiledWindowRestoredAfterEnablingOutput()
|
|||
// Move the window to the right monitor and tile it to the right.
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->move(QPointF(1280 + 50, 100));
|
||||
window->setQuickTileMode(QuickTileFlag::Right, true);
|
||||
window->setQuickTileModeAtCurrentPosition(QuickTileFlag::Right);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280 / 2, 1024));
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
|
@ -587,7 +587,7 @@ void OutputChangesTest::testCustomTiledWindowRestoredAfterEnablingOutput()
|
|||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->move(customTileGeom.topLeft() + QPointF(50, 50));
|
||||
const auto geomBeforeTiling = window->moveResizeGeometry();
|
||||
window->setQuickTileMode(QuickTileFlag::Custom, true);
|
||||
window->setQuickTileModeAtCurrentPosition(QuickTileFlag::Custom);
|
||||
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), customTileGeom.size().toSize());
|
||||
|
|
|
@ -174,7 +174,7 @@ void QuickTilingTest::testQuickTiling()
|
|||
QFETCH(QuickTileMode, mode);
|
||||
QFETCH(QRectF, expectedGeometry);
|
||||
const QuickTileMode oldQuickTileMode = window->quickTileMode();
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->handleQuickTileShortcut(mode);
|
||||
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
|
@ -223,7 +223,7 @@ void QuickTilingTest::testQuickTiling()
|
|||
QCOMPARE(window->tile(), mode == QuickTileFlag::Maximize ? nullptr : tile);
|
||||
|
||||
// now try to toggle again
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->handleQuickTileShortcut(mode);
|
||||
QTEST(window->requestedQuickTileMode(), "expectedModeAfterToggle");
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
|
||||
|
@ -278,7 +278,7 @@ void QuickTilingTest::testQuickMaximizing()
|
|||
QSignalSpy maximizeChangedSpy(window, &Window::maximizedChanged);
|
||||
|
||||
const QuickTileMode oldQuickTileMode = window->quickTileMode();
|
||||
window->setQuickTileMode(QuickTileFlag::Maximize, true);
|
||||
window->setQuickTileModeAtCurrentPosition(QuickTileFlag::Maximize);
|
||||
|
||||
// at this point the geometry did not yet change
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
|
||||
|
@ -310,7 +310,7 @@ void QuickTilingTest::testQuickMaximizing()
|
|||
|
||||
// go back to quick tile none
|
||||
QFETCH(QuickTileMode, mode);
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->setQuickTileModeAtCurrentPosition(mode);
|
||||
QCOMPARE(window->requestedQuickTileMode(), QuickTileMode(QuickTileFlag::None));
|
||||
// geometry not yet changed
|
||||
QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
|
||||
|
@ -637,7 +637,7 @@ void QuickTilingTest::testX11QuickTiling()
|
|||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
const QRectF origGeo = window->frameGeometry();
|
||||
QFETCH(QuickTileMode, mode);
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->handleQuickTileShortcut(mode);
|
||||
if (mode == QuickTileFlag::Maximize) {
|
||||
QCOMPARE(quickTileChangedSpy.count(), 0);
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::None);
|
||||
|
@ -652,7 +652,7 @@ void QuickTilingTest::testX11QuickTiling()
|
|||
// if screen is on the same edge
|
||||
const auto outputs = workspace()->outputs();
|
||||
QCOMPARE(window->output(), outputs[0]);
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->handleQuickTileShortcut(mode);
|
||||
QFETCH(int, screenId);
|
||||
QCOMPARE(window->output(), outputs[screenId]);
|
||||
QTEST(window->quickTileMode(), "modeAfterToggle");
|
||||
|
@ -728,7 +728,7 @@ void QuickTilingTest::testX11QuickTilingAfterVertMaximize()
|
|||
// now quick tile
|
||||
QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
|
||||
QFETCH(QuickTileMode, mode);
|
||||
window->setQuickTileMode(mode, true);
|
||||
window->setQuickTileModeAtCurrentPosition(mode);
|
||||
if (mode == QuickTileFlag::Maximize) {
|
||||
QCOMPARE(window->quickTileMode(), QuickTileFlag::None);
|
||||
QCOMPARE(quickTileChangedSpy.count(), 0);
|
||||
|
|
|
@ -872,7 +872,7 @@ void Workspace::quickTileWindow(QuickTileMode mode)
|
|||
m_quickTileCombineTimer->stop();
|
||||
}
|
||||
|
||||
m_activeWindow->setQuickTileMode(mode, true);
|
||||
m_activeWindow->handleQuickTileShortcut(mode);
|
||||
}
|
||||
|
||||
qreal Workspace::packPositionLeft(const Window *window, qreal oldX, bool leftEdge) const
|
||||
|
|
|
@ -115,19 +115,10 @@ void PlacementTracker::restore(const QString &key)
|
|||
}
|
||||
}
|
||||
if (restore) {
|
||||
// to work around setQuickTileMode having unexpected side effects, make sure the window isn't tiled before
|
||||
// setting the desired quick tile mode
|
||||
// TODO fix this more properly
|
||||
window->setQuickTileMode(QuickTileFlag::None, true);
|
||||
if (newData.quickTile != QuickTileFlag::Custom) {
|
||||
window->setQuickTileMode(newData.quickTile, true);
|
||||
}
|
||||
window->setQuickTileMode(newData.quickTile, newData.geometry.center());
|
||||
window->setMaximize(newData.maximize & MaximizeMode::MaximizeVertical, newData.maximize & MaximizeMode::MaximizeHorizontal);
|
||||
window->setFullScreen(newData.fullscreen);
|
||||
window->moveResize(newData.geometry);
|
||||
if (newData.quickTile == QuickTileFlag::Custom) {
|
||||
window->setQuickTileMode(QuickTileFlag::Custom, true);
|
||||
}
|
||||
window->setGeometryRestore(newData.geometryRestore);
|
||||
window->setFullscreenGeometryRestore(newData.fullscreenGeometryRestore);
|
||||
m_lastRestoreData[window] = dataForWindow(window);
|
||||
|
|
132
src/window.cpp
132
src/window.cpp
|
@ -1221,7 +1221,7 @@ bool Window::startInteractiveMoveResize()
|
|||
}
|
||||
|
||||
if (isInteractiveResize() && m_tile && !m_tile->supportsResizeGravity(interactiveMoveResizeGravity())) {
|
||||
setQuickTileMode(QuickTileFlag::None);
|
||||
setQuickTileModeAtCurrentPosition(QuickTileFlag::None);
|
||||
}
|
||||
|
||||
updateElectricGeometryRestore();
|
||||
|
@ -1246,7 +1246,7 @@ void Window::finishInteractiveMoveResize(bool cancel)
|
|||
setMaximize(m_interactiveMoveResize.initialMaximizeMode & MaximizeMode::MaximizeVertical, m_interactiveMoveResize.initialMaximizeMode & MaximizeMode::MaximizeHorizontal);
|
||||
setGeometryRestore(m_interactiveMoveResize.initialGeometryRestore);
|
||||
} else if (m_interactiveMoveResize.initialQuickTileMode) {
|
||||
setQuickTileMode(m_interactiveMoveResize.initialQuickTileMode, true);
|
||||
setQuickTileMode(m_interactiveMoveResize.initialQuickTileMode, m_interactiveMoveResize.initialGeometry.center());
|
||||
setGeometryRestore(m_interactiveMoveResize.initialGeometryRestore);
|
||||
}
|
||||
} else if (moveResizeOutput() != interactiveMoveResizeStartOutput()) {
|
||||
|
@ -1257,10 +1257,10 @@ void Window::finishInteractiveMoveResize(bool cancel)
|
|||
}
|
||||
|
||||
if (isElectricBorderMaximizing()) {
|
||||
setQuickTileMode(electricBorderMode());
|
||||
setQuickTileMode(electricBorderMode(), m_interactiveMoveResize.anchor);
|
||||
setElectricBorderMaximizing(false);
|
||||
} else if (wasMove && (m_interactiveMoveResize.modifiers & Qt::ShiftModifier)) {
|
||||
setQuickTileMode(QuickTileFlag::Custom);
|
||||
setQuickTileMode(QuickTileFlag::Custom, m_interactiveMoveResize.anchor);
|
||||
}
|
||||
setElectricBorderMode(QuickTileMode(QuickTileFlag::None));
|
||||
workspace()->outline()->hide();
|
||||
|
@ -1403,7 +1403,7 @@ void Window::updateInteractiveMoveResize(const QPointF &global, Qt::KeyboardModi
|
|||
}
|
||||
}
|
||||
} else if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
|
||||
setQuickTileMode(QuickTileFlag::None);
|
||||
setQuickTileModeAtCurrentPosition(QuickTileFlag::None);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3454,64 +3454,17 @@ QRectF Window::quickTileGeometryRestore() const
|
|||
}
|
||||
}
|
||||
|
||||
void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
||||
void Window::handleQuickTileShortcut(QuickTileMode mode)
|
||||
{
|
||||
// Only allow quick tile on a regular window.
|
||||
if (!isResizable()) {
|
||||
if (!isResizable() || isAppletPopup()) {
|
||||
return;
|
||||
}
|
||||
if (isAppletPopup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
workspace()->updateFocusMousePosition(Cursors::self()->mouse()->pos()); // may cause leave event
|
||||
|
||||
const QuickTileMode oldMode = requestedQuickTileMode();
|
||||
QPointF whichScreen = keyboard ? moveResizeGeometry().center() : Cursors::self()->mouse()->pos();
|
||||
|
||||
if (mode == QuickTileMode(QuickTileFlag::Maximize)) {
|
||||
if (requestedMaximizeMode() == MaximizeFull) {
|
||||
m_requestedQuickTileMode = QuickTileFlag::None;
|
||||
setMaximize(false, false);
|
||||
} else {
|
||||
QRectF effectiveGeometryRestore = quickTileGeometryRestore();
|
||||
m_requestedQuickTileMode = QuickTileFlag::Maximize;
|
||||
setMaximize(true, true);
|
||||
setGeometryRestore(effectiveGeometryRestore);
|
||||
}
|
||||
doSetQuickTileMode();
|
||||
return;
|
||||
}
|
||||
|
||||
// sanitize the mode, ie. simplify "invalid" combinations
|
||||
if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Horizontal)) {
|
||||
mode &= ~QuickTileMode(QuickTileFlag::Horizontal);
|
||||
}
|
||||
if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Vertical)) {
|
||||
mode &= ~QuickTileMode(QuickTileFlag::Vertical);
|
||||
}
|
||||
|
||||
// restore from maximized so that it is possible to tile maximized windows with one hit or by dragging
|
||||
if (requestedMaximizeMode() != MaximizeRestore) {
|
||||
if (mode != QuickTileMode(QuickTileFlag::None)) {
|
||||
m_requestedQuickTileMode = QuickTileFlag::None;
|
||||
setMaximize(false, false);
|
||||
moveResize(quickTileGeometry(mode, keyboard ? moveResizeGeometry().center() : Cursors::self()->mouse()->pos()));
|
||||
// Store the mode change
|
||||
m_requestedQuickTileMode = mode;
|
||||
} else {
|
||||
m_requestedQuickTileMode = mode;
|
||||
setMaximize(false, false);
|
||||
}
|
||||
|
||||
doSetQuickTileMode();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode != QuickTileMode(QuickTileFlag::None)) {
|
||||
QPointF tileAtPoint = moveResizeGeometry().center();
|
||||
if (mode != QuickTileFlag::None) {
|
||||
// If trying to tile to the side that the window is already tiled to move the window to the next
|
||||
// screen near the tile if it exists and swap the tile side, otherwise toggle the mode (set QuickTileFlag::None)
|
||||
const QuickTileMode oldMode = requestedQuickTileMode();
|
||||
if (oldMode == mode) {
|
||||
Output *currentOutput = moveResizeOutput();
|
||||
Output *nextOutput = currentOutput;
|
||||
|
@ -3535,8 +3488,7 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
|||
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();
|
||||
tileAtPoint = nextOutput->geometry().center();
|
||||
|
||||
// Swap sides
|
||||
if (shiftHorizontal) {
|
||||
|
@ -3546,17 +3498,66 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
|||
mode = (~mode & QuickTileFlag::Vertical) | (mode & QuickTileFlag::Horizontal);
|
||||
}
|
||||
}
|
||||
} else if (oldMode == QuickTileMode(QuickTileFlag::None)) {
|
||||
} else if (oldMode == QuickTileMode(QuickTileFlag::None) && requestedMaximizeMode() == MaximizeMode::MaximizeRestore) {
|
||||
// Not coming out of an existing tile, not shifting monitors, we're setting a brand new tile.
|
||||
// Store geometry first, so we can go out of this tile later.
|
||||
setGeometryRestore(quickTileGeometryRestore());
|
||||
}
|
||||
m_requestedQuickTileMode = mode;
|
||||
}
|
||||
setQuickTileMode(mode, tileAtPoint);
|
||||
}
|
||||
|
||||
if (mode == QuickTileMode(QuickTileFlag::None)) {
|
||||
m_requestedQuickTileMode = QuickTileFlag::None;
|
||||
void Window::setQuickTileModeAtCurrentPosition(QuickTileMode mode)
|
||||
{
|
||||
setQuickTileMode(mode, m_moveResizeGeometry.center());
|
||||
}
|
||||
|
||||
void Window::setQuickTileMode(QuickTileMode mode, const QPointF &tileAtPoint)
|
||||
{
|
||||
// Only allow quick tile on a regular window.
|
||||
if (!isResizable() || isAppletPopup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
workspace()->updateFocusMousePosition(Cursors::self()->mouse()->pos()); // may cause leave event
|
||||
|
||||
const QuickTileMode oldMode = requestedQuickTileMode();
|
||||
|
||||
if (mode == QuickTileMode(QuickTileFlag::Maximize)) {
|
||||
if (requestedMaximizeMode() == MaximizeFull) {
|
||||
m_requestedQuickTileMode = QuickTileFlag::None;
|
||||
setMaximize(false, false);
|
||||
} else {
|
||||
const QRectF effectiveGeometryRestore = quickTileGeometryRestore();
|
||||
m_requestedQuickTileMode = QuickTileFlag::Maximize;
|
||||
setMaximize(true, true);
|
||||
setGeometryRestore(effectiveGeometryRestore);
|
||||
}
|
||||
doSetQuickTileMode();
|
||||
return;
|
||||
}
|
||||
|
||||
// sanitize the mode, ie. simplify "invalid" combinations
|
||||
if ((mode & QuickTileFlag::Horizontal) == QuickTileMode(QuickTileFlag::Horizontal)) {
|
||||
mode &= ~QuickTileMode(QuickTileFlag::Horizontal);
|
||||
}
|
||||
if ((mode & QuickTileFlag::Vertical) == QuickTileMode(QuickTileFlag::Vertical)) {
|
||||
mode &= ~QuickTileMode(QuickTileFlag::Vertical);
|
||||
}
|
||||
m_requestedQuickTileMode = mode;
|
||||
|
||||
// restore from maximized so that it is possible to tile maximized windows with one hit or by dragging
|
||||
if (requestedMaximizeMode() != MaximizeRestore) {
|
||||
m_requestedQuickTileMode = QuickTileFlag::None;
|
||||
setMaximize(false, false);
|
||||
setQuickTileMode(mode, tileAtPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldMode == QuickTileFlag::None) {
|
||||
setGeometryRestore(quickTileGeometryRestore());
|
||||
}
|
||||
if (mode == QuickTileMode(QuickTileFlag::None)) {
|
||||
QRectF geometry = moveResizeGeometry();
|
||||
if (geometryRestore().isValid()) {
|
||||
geometry = geometryRestore();
|
||||
|
@ -3575,12 +3576,11 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
|||
}
|
||||
} else if (mode == QuickTileMode(QuickTileFlag::Custom)) {
|
||||
// Custom tileMode is the only one that gets immediately assigned without a roundtrip
|
||||
m_requestedQuickTileMode = mode;
|
||||
setTile(workspace()->tileManager(workspace()->outputAt(whichScreen))->bestTileForPosition(whichScreen));
|
||||
setTile(workspace()->tileManager(workspace()->outputAt(tileAtPoint))->bestTileForPosition(tileAtPoint));
|
||||
// Don't go into setTileMode as custom tiles don't go trough configure events
|
||||
return;
|
||||
} else {
|
||||
Tile *newTile = workspace()->tileManager(workspace()->outputAt(whichScreen))->quickTile(m_requestedQuickTileMode);
|
||||
Tile *newTile = workspace()->tileManager(workspace()->outputAt(tileAtPoint))->quickTile(m_requestedQuickTileMode);
|
||||
if (newTile) {
|
||||
moveResize(newTile->absoluteGeometry());
|
||||
} else if (tile()) {
|
||||
|
|
10
src/window.h
10
src/window.h
|
@ -1090,13 +1090,9 @@ public:
|
|||
Tile *tile() const;
|
||||
void setTile(Tile *tile);
|
||||
|
||||
/**
|
||||
* Sets the quick tile mode ("snap") of this window.
|
||||
* This will also handle preserving and restoring of window geometry as necessary.
|
||||
* @param mode The tile mode (left/right) to give this window.
|
||||
* @param keyboard Defines whether to take keyboard cursor into account.
|
||||
*/
|
||||
void setQuickTileMode(QuickTileMode mode, bool keyboard = false);
|
||||
void handleQuickTileShortcut(QuickTileMode mode);
|
||||
void setQuickTileModeAtCurrentPosition(QuickTileMode mode);
|
||||
void setQuickTileMode(QuickTileMode mode, const QPointF &tileAtPoint);
|
||||
QuickTileMode quickTileMode() const;
|
||||
QuickTileMode requestedQuickTileMode() const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue