[wayland] Implement maximize rules
Summary: There is still one small issue that has to be addressed in the future: xdg-toplevel doesn't have states like MAXIMIZED_VERT or MAXIMIZED_HORZ, thus Window Rules KCM should display only single maximize rule(not two) for wayland clients. Test Plan: The new tests pass. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D19414
This commit is contained in:
parent
bbe898243a
commit
702a4ff688
3 changed files with 632 additions and 3 deletions
|
@ -75,6 +75,19 @@ private Q_SLOTS:
|
|||
void testSizeForceTemporarily_data();
|
||||
void testSizeForceTemporarily();
|
||||
|
||||
void testMaximizeDontAffect_data();
|
||||
void testMaximizeDontAffect();
|
||||
void testMaximizeApply_data();
|
||||
void testMaximizeApply();
|
||||
void testMaximizeRemember_data();
|
||||
void testMaximizeRemember();
|
||||
void testMaximizeForce_data();
|
||||
void testMaximizeForce();
|
||||
void testMaximizeApplyNow_data();
|
||||
void testMaximizeApplyNow();
|
||||
void testMaximizeForceTemporarily_data();
|
||||
void testMaximizeForceTemporarily();
|
||||
|
||||
void testDesktopDontAffect_data();
|
||||
void testDesktopDontAffect();
|
||||
void testDesktopApply_data();
|
||||
|
@ -1248,6 +1261,603 @@ void TestShellClientRules::testSizeForceTemporarily()
|
|||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeDontAffect)
|
||||
|
||||
void TestShellClientRules::testMaximizeDontAffect()
|
||||
{
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::DontAffect));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::DontAffect));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
|
||||
// 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));
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeApply)
|
||||
|
||||
void TestShellClientRules::testMaximizeApply()
|
||||
{
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::Apply));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::Apply));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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(1280, 1024));
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
// 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));
|
||||
|
||||
// One should still be able to change the maximized state of the client.
|
||||
workspace()->slotWindowMaximize();
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 3);
|
||||
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));
|
||||
|
||||
QSignalSpy geometryChangedSpy(client, &AbstractClient::geometryChanged);
|
||||
QVERIFY(geometryChangedSpy.isValid());
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
|
||||
// If we create the client again, it should be initially maximized.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
surface.reset(Test::createSurface());
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 1);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(1280, 1024));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
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));
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeRemember)
|
||||
|
||||
void TestShellClientRules::testMaximizeRemember()
|
||||
{
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::Remember));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::Remember));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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(1280, 1024));
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
// 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));
|
||||
|
||||
// One should still be able to change the maximized state of the client.
|
||||
workspace()->slotWindowMaximize();
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 3);
|
||||
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));
|
||||
|
||||
QSignalSpy geometryChangedSpy(client, &AbstractClient::geometryChanged);
|
||||
QVERIFY(geometryChangedSpy.isValid());
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
|
||||
// If we create the client again, it should not be maximized (because last time it wasn't).
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
surface.reset(Test::createSurface());
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
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));
|
||||
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
|
||||
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));
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeForce)
|
||||
|
||||
void TestShellClientRules::testMaximizeForce()
|
||||
{
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::Force));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::Force));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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(1280, 1024));
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(!client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
// 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));
|
||||
|
||||
// Any attempt to change the maximized state should not succeed.
|
||||
const QRect oldGeometry = client->geometry();
|
||||
workspace()->slotWindowMaximize();
|
||||
QVERIFY(!configureRequestedSpy->wait(100));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->geometry(), oldGeometry);
|
||||
|
||||
// If we create the client again, the maximized state should still be forced.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
surface.reset(Test::createSurface());
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 1);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(1280, 1024));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(!client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
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));
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeApplyNow)
|
||||
|
||||
void TestShellClientRules::testMaximizeApplyNow()
|
||||
{
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
|
||||
// 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));
|
||||
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::ApplyNow));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::ApplyNow));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// We should receive a configure event with a new surface size.
|
||||
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::Activated));
|
||||
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->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
|
||||
// The client still has to be maximizeable.
|
||||
QVERIFY(client->isMaximizable());
|
||||
|
||||
// Restore the client.
|
||||
workspace()->slotWindowMaximize();
|
||||
QVERIFY(configureRequestedSpy->wait());
|
||||
QCOMPARE(configureRequestedSpy->count(), 4);
|
||||
QCOMPARE(configureRequestedSpy->last().at(0).toSize(), QSize(100, 50));
|
||||
states = configureRequestedSpy->last().at(1).value<XdgShellSurface::States>();
|
||||
QVERIFY(states.testFlag(XdgShellSurface::State::Activated));
|
||||
QVERIFY(!states.testFlag(XdgShellSurface::State::Maximized));
|
||||
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
Test::render(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(geometryChangedSpy.wait());
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
|
||||
// The rule should be discarded after it's been applied.
|
||||
const QRect oldGeometry = client->geometry();
|
||||
client->evaluateWindowRules();
|
||||
QVERIFY(!configureRequestedSpy->wait(100));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->geometry(), oldGeometry);
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testMaximizeForceTemporarily)
|
||||
|
||||
void TestShellClientRules::testMaximizeForceTemporarily()
|
||||
{
|
||||
// Initialize RuleBook with the test rule.
|
||||
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
|
||||
config->group("General").writeEntry("count", 1);
|
||||
KConfigGroup group = config->group("1");
|
||||
group.writeEntry("maximizehoriz", true);
|
||||
group.writeEntry("maximizehorizrule", int(Rules::ForceTemporarily));
|
||||
group.writeEntry("maximizevert", true);
|
||||
group.writeEntry("maximizevertrule", int(Rules::ForceTemporarily));
|
||||
group.writeEntry("wmclass", "org.kde.foo");
|
||||
group.writeEntry("wmclasscomplete", false);
|
||||
group.writeEntry("wmclassmatch", int(Rules::ExactMatch));
|
||||
group.sync();
|
||||
RuleBook::self()->setConfig(config);
|
||||
workspace()->slotReconfigure();
|
||||
|
||||
// Create the test client.
|
||||
QFETCH(Test::ShellSurfaceType, type);
|
||||
QScopedPointer<Surface> surface;
|
||||
surface.reset(Test::createSurface());
|
||||
QScopedPointer<XdgShellSurface> shellSurface;
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
QScopedPointer<QSignalSpy> configureRequestedSpy;
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
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(1280, 1024));
|
||||
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>());
|
||||
ShellClient *client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(!client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->size(), QSize(1280, 1024));
|
||||
|
||||
// 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));
|
||||
|
||||
// Any attempt to change the maximized state should not succeed.
|
||||
const QRect oldGeometry = client->geometry();
|
||||
workspace()->slotWindowMaximize();
|
||||
QVERIFY(!configureRequestedSpy->wait(100));
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeFull);
|
||||
QCOMPARE(client->geometry(), oldGeometry);
|
||||
|
||||
// The rule should be discarded if we close the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
surface.reset(Test::createSurface());
|
||||
shellSurface.reset(createXdgShellSurface(type, surface.data(), surface.data(), Test::CreationSetup::CreateOnly));
|
||||
configureRequestedSpy.reset(new QSignalSpy(shellSurface.data(), &XdgShellSurface::configureRequested));
|
||||
shellSurface->setAppId("org.kde.foo");
|
||||
surface->commit(Surface::CommitFlag::None);
|
||||
|
||||
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));
|
||||
|
||||
shellSurface->ackConfigure(configureRequestedSpy->last().at(2).value<quint32>());
|
||||
client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue);
|
||||
QVERIFY(client);
|
||||
QVERIFY(client->isActive());
|
||||
QVERIFY(client->isMaximizable());
|
||||
QCOMPARE(client->maximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->requestedMaximizeMode(), MaximizeMode::MaximizeRestore);
|
||||
QCOMPARE(client->size(), QSize(100, 50));
|
||||
|
||||
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));
|
||||
|
||||
// Destroy the client.
|
||||
shellSurface.reset();
|
||||
surface.reset();
|
||||
QVERIFY(Test::waitForWindowDestroyed(client));
|
||||
}
|
||||
|
||||
TEST_DATA(testDesktopDontAffect)
|
||||
|
||||
void TestShellClientRules::testDesktopDontAffect()
|
||||
|
|
|
@ -194,6 +194,12 @@ void ShellClient::initSurface(T *shellSurface)
|
|||
// ignore for wl_shell - there it is mutual exclusive and messes with the geometry
|
||||
return;
|
||||
}
|
||||
|
||||
// If the maximized state of the client hasn't been changed due to a window
|
||||
// rule or because the requested state is the same as the current, then the
|
||||
// compositor still has to send a configure event.
|
||||
RequestGeometryBlocker blocker(this);
|
||||
|
||||
maximize(maximized ? MaximizeFull : MaximizeRestore);
|
||||
}
|
||||
);
|
||||
|
@ -366,6 +372,8 @@ void ShellClient::finishInit() {
|
|||
setGeometry(ruledGeometry);
|
||||
}
|
||||
|
||||
maximize(rules()->checkMaximize(maximizeMode(), true));
|
||||
|
||||
setDesktop(rules()->checkDesktop(desktop(), true));
|
||||
setDesktopFileName(rules()->checkDesktopFile(desktopFileName(), true).toUtf8());
|
||||
if (rules()->checkMinimize(isMinimized(), true)) {
|
||||
|
@ -384,6 +392,11 @@ void ShellClient::finishInit() {
|
|||
needsPlacement = false;
|
||||
}
|
||||
|
||||
// Don't place the client if the maximize state is set by a rule.
|
||||
if (requestedMaximizeMode() != MaximizeRestore) {
|
||||
needsPlacement = false;
|
||||
}
|
||||
|
||||
discardTemporaryRules();
|
||||
RuleBook::self()->discardUsed(this, false); // Remove Apply Now rules.
|
||||
updateWindowRules(Rules::All);
|
||||
|
@ -777,6 +790,9 @@ bool ShellClient::isMaximizable() const
|
|||
if (!isResizable()) {
|
||||
return false;
|
||||
}
|
||||
if (rules()->checkMaximize(MaximizeRestore) != MaximizeRestore || rules()->checkMaximize(MaximizeFull) != MaximizeFull) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -876,9 +892,9 @@ void ShellClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
|
|||
if (horizontal)
|
||||
m_requestedMaximizeMode = MaximizeMode(m_requestedMaximizeMode ^ MaximizeHorizontal);
|
||||
}
|
||||
// TODO: add more checks as in Client
|
||||
|
||||
if (m_requestedMaximizeMode == oldMode) {
|
||||
m_requestedMaximizeMode = rules()->checkMaximize(m_requestedMaximizeMode);
|
||||
if (!adjust && m_requestedMaximizeMode == oldMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -924,7 +940,6 @@ void ShellClient::changeMaximize(bool horizontal, bool vertical, bool adjust)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: check rules
|
||||
if (m_requestedMaximizeMode == MaximizeFull) {
|
||||
m_geomMaximizeRestore = oldGeometry;
|
||||
// TODO: Client has more checks
|
||||
|
@ -1485,6 +1500,7 @@ void ShellClient::updateMaximizeMode(MaximizeMode maximizeMode)
|
|||
}
|
||||
|
||||
m_maximizeMode = maximizeMode;
|
||||
updateWindowRules(Rules::MaximizeHoriz | Rules::MaximizeVert | Rules::Position | Rules::Size);
|
||||
|
||||
emit clientMaximizedStateChanged(this, m_maximizeMode);
|
||||
emit clientMaximizedStateChanged(this, m_maximizeMode & MaximizeHorizontal, m_maximizeMode & MaximizeVertical);
|
||||
|
|
|
@ -301,6 +301,9 @@ void Workspace::init()
|
|||
if (c->isFullScreen()) {
|
||||
placementDone = true;
|
||||
}
|
||||
if (c->maximizeMode() == MaximizeMode::MaximizeFull) {
|
||||
placementDone = true;
|
||||
}
|
||||
if (c->rules()->checkPosition(invalidPoint, true) != invalidPoint) {
|
||||
placementDone = true;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue