Avoid moving the window while it's maximized
Unlike X11, on Wayland, the window won't change its maximize mode until it renders a new buffer. This creates a problem for interactive move because if it's not careful and moves the window while it's still effectively maximized, it will look as if the window has leaked to other screens. This change fixes the problem by making Window::handleInteractiveMoveResize() avoid move() if the window needs to be unmaximized. As a bonus, it also allows to unmaximize the windows that are maximized along only one dimension by dragging them. Unfortunately, tiling stuff still suffers from the same issue. In order to fix it, Window::tile() has to be part of double buffered state, like Window::maximizeMode(). BUG: 449105 BUG: 459218 CCBUG: 482085
This commit is contained in:
parent
3e4c2b3ec8
commit
11a5513e78
6 changed files with 379 additions and 13 deletions
|
@ -702,6 +702,7 @@ std::unique_ptr<FractionalScaleV1> createFractionalScaleV1(KWayland::Client::Sur
|
|||
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface);
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, CreationSetup configureMode);
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, std::function<void(XdgToplevel *toplevel)> setup);
|
||||
|
||||
std::unique_ptr<XdgPositioner> createXdgPositioner();
|
||||
|
||||
|
|
|
@ -1004,6 +1004,24 @@ std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface
|
|||
return xdgToplevel;
|
||||
}
|
||||
|
||||
std::unique_ptr<XdgToplevel> createXdgToplevelSurface(KWayland::Client::Surface *surface, std::function<void(XdgToplevel *toplevel)> setup)
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
||||
if (!shell) {
|
||||
qWarning() << "Could not create an xdg_toplevel surface because xdg_wm_base global is not bound";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XdgSurface *xdgSurface = new XdgSurface(shell, surface);
|
||||
std::unique_ptr<XdgToplevel> xdgToplevel = std::make_unique<XdgToplevel>(xdgSurface);
|
||||
|
||||
setup(xdgToplevel.get());
|
||||
waitForConfigured(xdgSurface);
|
||||
|
||||
return xdgToplevel;
|
||||
}
|
||||
|
||||
std::unique_ptr<XdgPositioner> createXdgPositioner()
|
||||
{
|
||||
XdgShell *shell = s_waylandConnection.xdgShell;
|
||||
|
|
|
@ -68,6 +68,10 @@ private Q_SLOTS:
|
|||
void testMaximizedToFullscreen_data();
|
||||
void testMaximizedToFullscreen();
|
||||
void testSendMaximizedWindowToAnotherOutput();
|
||||
void testInteractiveMoveUnmaximizeFull();
|
||||
void testInteractiveMoveUnmaximizeInitiallyFull();
|
||||
void testInteractiveMoveUnmaximizeHorizontal();
|
||||
void testInteractiveMoveUnmaximizeVertical();
|
||||
void testFullscreenMultipleOutputs();
|
||||
void testHidden();
|
||||
void testDesktopFileName();
|
||||
|
@ -1795,6 +1799,314 @@ void TestXdgShellWindow::testSendMaximizedWindowToAnotherOutput()
|
|||
QCOMPARE(window->output(), outputs[1]);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeFull()
|
||||
{
|
||||
// This test verifies that a maximized xdg-toplevel is going to be properly unmaximized when it's dragged.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeFull);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Move the window to unmaximize it.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Move the window a tiny bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeInitiallyFull()
|
||||
{
|
||||
// This test verifies that an initially maximized xdg-toplevel will be properly unmaximized when it's dragged.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), [](Test::XdgToplevel *toplevel) {
|
||||
toplevel->set_maximized();
|
||||
}));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeFull);
|
||||
|
||||
// Move the window to unmaximize it.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Move the window a tiny bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 0);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeFull);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry);
|
||||
|
||||
// Render the window at the new size.
|
||||
const QSize restoredSize(100, 50);
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(0, 0));
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), restoredSize, Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(restoredSize.width() * xOffset, restoredSize.height() * yOffset), restoredSize));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeHorizontal()
|
||||
{
|
||||
// This test verifies that a maximized horizontally xdg-toplevel is going to be properly unmaximized when it's dragged horizontally.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeHorizontal);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
|
||||
// Move the window vertically, it's not going to be unmaximized.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Move the window horizontally.
|
||||
Test::pointerMotionRelative(QPointF(100, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Move the window to the right a bit more.
|
||||
Test::pointerMotionRelative(QPointF(10, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(0, 100));
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(10, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(10, 0));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testInteractiveMoveUnmaximizeVertical()
|
||||
{
|
||||
// This test verifies that a maximized vertically xdg-toplevel is going to be properly unmaximized when it's dragged vertically.
|
||||
|
||||
// Create the window.
|
||||
std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
|
||||
std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
|
||||
auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
|
||||
|
||||
// Wait for the compositor to send a configure event with the activated state.
|
||||
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
|
||||
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
|
||||
// Make the window maximized.
|
||||
const QRectF originalGeometry = window->frameGeometry();
|
||||
QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
|
||||
window->maximize(MaximizeVertical);
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
|
||||
// Start interactive move.
|
||||
QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
|
||||
QSignalSpy interactiveMoveResizeSteppedSpy(window, &Window::interactiveMoveResizeStepped);
|
||||
QSignalSpy interactiveMoveResizeFinishedSpy(window, &Window::interactiveMoveResizeFinished);
|
||||
const qreal xOffset = 0.25;
|
||||
const qreal yOffset = 0.5;
|
||||
quint32 timestamp = 0;
|
||||
Test::pointerMotion(QPointF(window->x() + window->width() * xOffset, window->y() + window->height() * yOffset), timestamp++);
|
||||
window->performMouseCommand(Options::MouseMove, input()->pointer()->pos());
|
||||
QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
|
||||
// Move the window to the right, it's not going to be unmaximized.
|
||||
const QRectF maximizedGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(100, 0), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Move the window vertically.
|
||||
Test::pointerMotionRelative(QPointF(0, 100), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Move the window down a bit more.
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), maximizedGeometry.translated(100, 0));
|
||||
|
||||
// Render the window at the new size.
|
||||
QVERIFY(surfaceConfigureRequestedSpy.wait());
|
||||
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
|
||||
Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), Qt::red);
|
||||
QVERIFY(frameGeometryChangedSpy.wait());
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), QRectF(input()->pointer()->pos() - QPointF(originalGeometry.width() * xOffset, originalGeometry.height() * yOffset), originalGeometry.size()));
|
||||
|
||||
// Move the window again.
|
||||
const QRectF normalGeometry = window->frameGeometry();
|
||||
Test::pointerMotionRelative(QPointF(0, 10), timestamp++);
|
||||
QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
|
||||
QCOMPARE(window->maximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(window->frameGeometry(), normalGeometry.translated(0, 10));
|
||||
|
||||
// Finish interactive move.
|
||||
window->keyPressEvent(Qt::Key_Enter);
|
||||
QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
|
||||
}
|
||||
|
||||
void TestXdgShellWindow::testMaximizeAndChangeDecorationModeAfterInitialCommit()
|
||||
{
|
||||
// Ideally, the app would initialize the xdg-toplevel surface before the initial commit, but
|
||||
|
|
|
@ -1450,16 +1450,24 @@ void Window::handleInteractiveMoveResize(const QPointF &local, const QPointF &gl
|
|||
|
||||
nextMoveResizeGeom = nextMoveGeometry();
|
||||
if (nextMoveResizeGeom != currentMoveResizeGeom) {
|
||||
GeometryUpdatesBlocker blocker(this);
|
||||
|
||||
if (!isRequestedFullScreen() && quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
|
||||
setQuickTileMode(QuickTileFlag::None);
|
||||
|
||||
const QRectF &geom_restore = geometryRestore();
|
||||
if (rules()->checkMaximize(MaximizeRestore) == MaximizeRestore) {
|
||||
setMoveResizeGeometry(geom_restore);
|
||||
if (!isRequestedFullScreen()) {
|
||||
if (maximizeMode() != MaximizeRestore) {
|
||||
if (maximizeMode() & MaximizeHorizontal) {
|
||||
if (nextMoveResizeGeom.x() != currentMoveResizeGeom.x() || nextMoveResizeGeom.width() != currentMoveResizeGeom.width()) {
|
||||
maximize(MaximizeRestore);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (maximizeMode() & MaximizeVertical) {
|
||||
if (nextMoveResizeGeom.y() != currentMoveResizeGeom.y() || nextMoveResizeGeom.height() != currentMoveResizeGeom.height()) {
|
||||
maximize(MaximizeRestore);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
|
||||
setQuickTileMode(QuickTileFlag::None);
|
||||
return;
|
||||
}
|
||||
nextMoveResizeGeom = nextMoveGeometry(); // fix position
|
||||
}
|
||||
|
||||
move(nextMoveResizeGeom.topLeft());
|
||||
|
@ -3562,11 +3570,18 @@ void Window::setQuickTileMode(QuickTileMode mode, bool keyboard)
|
|||
if (mode == QuickTileMode(QuickTileFlag::None)) {
|
||||
setTile(nullptr);
|
||||
m_quickTileMode = int(QuickTileFlag::None);
|
||||
// Untiling, so just restore geometry, and we're done.
|
||||
if (geometryRestore().isValid()) { // invalid if we started maximized and wait for placement
|
||||
moveResize(geometryRestore());
|
||||
|
||||
QRectF geometry = moveResizeGeometry();
|
||||
if (geometryRestore().isValid()) {
|
||||
geometry = geometryRestore();
|
||||
}
|
||||
checkWorkspacePosition(); // Just in case it's a different screen
|
||||
if (isInteractiveMove()) {
|
||||
const QPointF anchor = interactiveMoveResizeAnchor();
|
||||
const QPointF offset = interactiveMoveOffset();
|
||||
geometry.moveTopLeft(QPointF(anchor.x() - geometry.width() * offset.x(),
|
||||
anchor.y() - geometry.height() * offset.y()));
|
||||
}
|
||||
moveResize(geometry);
|
||||
} else if (mode == QuickTileMode(QuickTileFlag::Custom)) {
|
||||
Tile *tile = nullptr;
|
||||
if (keyboard) {
|
||||
|
|
|
@ -4583,6 +4583,15 @@ void X11Window::maximize(MaximizeMode mode)
|
|||
}
|
||||
|
||||
restore.setSize(constrainFrameSize(restore.size(), SizeModeAny));
|
||||
if (isInteractiveMove()) {
|
||||
if (!isFullScreen()) {
|
||||
const QPointF anchor = interactiveMoveResizeAnchor();
|
||||
const QPointF offset = interactiveMoveOffset();
|
||||
restore.moveTopLeft(QPointF(anchor.x() - offset.x() * restore.width(),
|
||||
anchor.y() - offset.y() * restore.height()));
|
||||
}
|
||||
}
|
||||
|
||||
moveResize(restore);
|
||||
|
||||
info->setState(NET::States(), NET::Max);
|
||||
|
|
|
@ -217,6 +217,17 @@ void XdgSurfaceWindow::handleNextWindowGeometry()
|
|||
// Both the compositor and the client can change the window geometry. If the client
|
||||
// sets a new window geometry, the compositor's move-resize geometry will be invalid.
|
||||
maybeUpdateMoveResizeGeometry(frameGeometry);
|
||||
} else if (isInteractiveMove()) {
|
||||
bool fullscreen = isFullScreen();
|
||||
if (const auto configureEvent = static_cast<XdgToplevelConfigure *>(lastAcknowledgedConfigure())) {
|
||||
fullscreen = configureEvent->states & XdgToplevelInterface::State::FullScreen;
|
||||
}
|
||||
if (!fullscreen) {
|
||||
const QPointF anchor = interactiveMoveResizeAnchor();
|
||||
const QPointF offset = interactiveMoveOffset();
|
||||
frameGeometry.moveTopLeft(QPointF(anchor.x() - offset.x() * frameGeometry.width(),
|
||||
anchor.y() - offset.y() * frameGeometry.height()));
|
||||
}
|
||||
}
|
||||
|
||||
updateGeometry(frameGeometry);
|
||||
|
|
Loading…
Reference in a new issue