wayland: Implement maximized horizontal/vertical states
BUG: 407793
This commit is contained in:
parent
dd1b45d828
commit
378ecbc88c
2 changed files with 306 additions and 20 deletions
|
@ -72,6 +72,9 @@ private Q_SLOTS:
|
|||
void testUserCanSetFullscreen();
|
||||
void testUserSetFullscreen();
|
||||
|
||||
void testMaximizeHorizontal();
|
||||
void testMaximizeVertical();
|
||||
void testMaximizeFull();
|
||||
void testMaximizedToFullscreen_data();
|
||||
void testMaximizedToFullscreen();
|
||||
void testFullscreenMultipleOutputs();
|
||||
|
@ -1698,5 +1701,248 @@ void TestXdgShellClient::testDoubleMaximize()
|
|||
QVERIFY(states.testFlag(XdgShellSurface::State::Maximized));
|
||||
}
|
||||
|
||||
void TestXdgShellClient::testMaximizeHorizontal()
|
||||
{
|
||||
// Create the test client.
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(Test::createXdgShellStableSurface(surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
// Wait for the initial configure event.
|
||||
XdgShellSurface::States states;
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 1);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(0, 0));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Map the client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
AbstractClient *client = Test::renderAndWaitForShown(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
|
||||
// We should receive a configure event when the client becomes active.
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 2);
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Maximize the test client in horizontal direction.
|
||||
workspace()->slotWindowMaximizeHorizontal();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 3);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(1280, 600));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the maximized client.
|
||||
QSignalSpy geometryChangedSpy(client, &AbstractClient::geometryChanged);
|
||||
QVERIFY(geometryChangedSpy.isValid());
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(1280, 600), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(1280, 600));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeHorizontal);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeHorizontal);
|
||||
|
||||
// Restore the client.
|
||||
workspace()->slotWindowMaximizeHorizontal();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeHorizontal);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 4);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(800, 600));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the restored client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
void TestXdgShellClient::testMaximizeVertical()
|
||||
{
|
||||
// Create the test client.
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(Test::createXdgShellStableSurface(surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
// Wait for the initial configure event.
|
||||
XdgShellSurface::States states;
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 1);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(0, 0));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Map the client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
AbstractClient *client = Test::renderAndWaitForShown(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
|
||||
// We should receive a configure event when the client becomes active.
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 2);
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Maximize the test client in vertical direction.
|
||||
workspace()->slotWindowMaximizeVertical();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 3);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(800, 1024));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the maximized client.
|
||||
QSignalSpy geometryChangedSpy(client, &AbstractClient::geometryChanged);
|
||||
QVERIFY(geometryChangedSpy.isValid());
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(800, 1024), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(800, 1024));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeVertical);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeVertical);
|
||||
|
||||
// Restore the client.
|
||||
workspace()->slotWindowMaximizeVertical();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeVertical);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 4);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(800, 600));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the restored client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
void TestXdgShellClient::testMaximizeFull()
|
||||
{
|
||||
// Create the test client.
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(Test::createXdgShellStableSurface(surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
// Wait for the initial configure event.
|
||||
XdgShellSurface::States states;
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 1);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(0, 0));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Map the client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
AbstractClient *client = Test::renderAndWaitForShown(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
|
||||
// We should receive a configure event when the client becomes active.
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 2);
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Maximize the test client.
|
||||
workspace()->slotWindowMaximize();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeFull);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 3);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(1280, 1024));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the maximized client.
|
||||
QSignalSpy geometryChangedSpy(client, &AbstractClient::geometryChanged);
|
||||
QVERIFY(geometryChangedSpy.isValid());
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeFull);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeFull);
|
||||
|
||||
// Restore the client.
|
||||
workspace()->slotWindowMaximize();
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeFull);
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 4);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(800, 600));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
// Draw contents of the restored client.
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(800, 600), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(800, 600));
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeRestore);
|
||||
QCOMPARE(client->maximizeMode(), MaximizeRestore);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
WAYLANDTEST_MAIN(TestXdgShellClient)
|
||||
#include "xdgshellclient_test.moc"
|
||||
|
|
|
@ -1644,6 +1644,19 @@ void XdgToplevelClient::changeMaximize(bool horizontal, bool vertical, bool adju
|
|||
changeMaximizeRecursion = false;
|
||||
}
|
||||
|
||||
if (quickTileMode() == QuickTileMode(QuickTileFlag::None)) {
|
||||
QRect savedGeometry = geometryRestore();
|
||||
if (!adjust && !(oldMode & MaximizeVertical)) {
|
||||
savedGeometry.setTop(oldGeometry.top());
|
||||
savedGeometry.setBottom(oldGeometry.bottom());
|
||||
}
|
||||
if (!adjust && !(oldMode & MaximizeHorizontal)) {
|
||||
savedGeometry.setLeft(oldGeometry.left());
|
||||
savedGeometry.setRight(oldGeometry.right());
|
||||
}
|
||||
setGeometryRestore(savedGeometry);
|
||||
}
|
||||
|
||||
// Conditional quick tiling exit points
|
||||
const auto oldQuickTileMode = quickTileMode();
|
||||
if (quickTileMode() != QuickTileMode(QuickTileFlag::None)) {
|
||||
|
@ -1659,35 +1672,62 @@ void XdgToplevelClient::changeMaximize(bool horizontal, bool vertical, bool adju
|
|||
}
|
||||
}
|
||||
|
||||
const MaximizeMode delta = m_requestedMaximizeMode ^ oldMode;
|
||||
QRect geometry = oldGeometry;
|
||||
|
||||
if (adjust || (delta & MaximizeHorizontal)) {
|
||||
if (m_requestedMaximizeMode & MaximizeHorizontal) {
|
||||
// Stretch the window vertically to fit the size of the maximize area.
|
||||
geometry.setX(clientArea.x());
|
||||
geometry.setWidth(clientArea.width());
|
||||
} else if (geometryRestore().isValid()) {
|
||||
// The window is no longer maximized horizontally and the saved geometry is valid.
|
||||
geometry.setX(geometryRestore().x());
|
||||
geometry.setWidth(geometryRestore().width());
|
||||
} else {
|
||||
// The window is no longer maximized horizontally and the saved geometry is
|
||||
// invalid. This would happen if the window had been mapped in the maximized state.
|
||||
// We ask the client to resize the window horizontally to its preferred size.
|
||||
geometry.setX(clientArea.x());
|
||||
geometry.setWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (adjust || (delta & MaximizeVertical)) {
|
||||
if (m_requestedMaximizeMode & MaximizeVertical) {
|
||||
// Stretch the window horizontally to fit the size of the maximize area.
|
||||
geometry.setY(clientArea.y());
|
||||
geometry.setHeight(clientArea.height());
|
||||
} else if (geometryRestore().isValid()) {
|
||||
// The window is no longer maximized vertically and the saved geometry is valid.
|
||||
geometry.setY(geometryRestore().y());
|
||||
geometry.setHeight(geometryRestore().height());
|
||||
} else {
|
||||
// The window is no longer maximized vertically and the saved geometry is
|
||||
// invalid. This would happen if the window had been mapped in the maximized state.
|
||||
// We ask the client to resize the window vertically to its preferred size.
|
||||
geometry.setY(clientArea.y());
|
||||
geometry.setHeight(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_requestedMaximizeMode == MaximizeFull) {
|
||||
setGeometryRestore(oldGeometry);
|
||||
// TODO: Client has more checks
|
||||
if (options->electricBorderMaximize()) {
|
||||
updateQuickTileMode(QuickTileFlag::Maximize);
|
||||
} else {
|
||||
updateQuickTileMode(QuickTileFlag::None);
|
||||
}
|
||||
if (quickTileMode() != oldQuickTileMode) {
|
||||
doSetQuickTileMode();
|
||||
emit quickTileModeChanged();
|
||||
}
|
||||
setFrameGeometry(workspace()->clientArea(MaximizeArea, this));
|
||||
} else {
|
||||
if (m_requestedMaximizeMode == MaximizeRestore) {
|
||||
} else if (m_requestedMaximizeMode == MaximizeRestore) {
|
||||
updateQuickTileMode(QuickTileFlag::None);
|
||||
}
|
||||
if (quickTileMode() != oldQuickTileMode) {
|
||||
|
||||
setFrameGeometry(geometry);
|
||||
|
||||
if (oldQuickTileMode != quickTileMode()) {
|
||||
doSetQuickTileMode();
|
||||
emit quickTileModeChanged();
|
||||
}
|
||||
|
||||
if (geometryRestore().isValid()) {
|
||||
setFrameGeometry(geometryRestore());
|
||||
} else {
|
||||
setFrameGeometry(workspace()->clientArea(PlacementArea, this));
|
||||
}
|
||||
}
|
||||
|
||||
doSetMaximized();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue