[wayland] Fix window sizing when restoring a window that was initially fullscreen

Summary: When creating a surface and setting it as fullscreen before
attaching its buffer KWin does not know the original dimensions of the
surface and tries to use an invalid value when unsetting the fullscreen
flag. This patch fixes this by sending a configure with the size of 0,0
- which according to xdg-shell spec means that the client is requested
to set its size by itself.

Test Plan:
1. Create a fullscreen Wayland window.
2. Toggle fullscreen off.
3. KWin should send a configure event with size 0,0 instead of 1,1.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: zzag, graesslin, davidedmundson, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D16710
icc-effect-5.17.5
Sebastian Krzyszkowiak 2019-02-22 18:54:52 +00:00 committed by David Edmundson
parent cbbe94d769
commit 7bf2c1d73e
2 changed files with 57 additions and 3 deletions

View File

@ -72,6 +72,8 @@ private Q_SLOTS:
void testMinimizeActiveWindow();
void testFullscreen_data();
void testFullscreen();
void testFullscreenRestore_data();
void testFullscreenRestore();
void testUserCanSetFullscreen_data();
void testUserCanSetFullscreen();
void testUserSetFullscreenWlShell();
@ -524,6 +526,57 @@ void TestShellClient::testFullscreen()
QCOMPARE(c->isDecorated(), decoMode == ServerSideDecoration::Mode::Server);
}
void TestShellClient::testFullscreenRestore_data()
{
QTest::addColumn<Test::ShellSurfaceType>("type");
QTest::newRow("xdgShellV5") << Test::ShellSurfaceType::XdgShellV5;
QTest::newRow("xdgShellV6") << Test::ShellSurfaceType::XdgShellV6;
QTest::newRow("xdgShellWmBase") << Test::ShellSurfaceType::XdgShellStable;
}
void TestShellClient::testFullscreenRestore()
{
// this test verifies that windows created fullscreen can be later properly restored
QScopedPointer<Surface> surface(Test::createSurface());
QFETCH(Test::ShellSurfaceType, type);
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
XdgShellSurface *xdgShellSurface = nullptr;
// fullscreen the window
xdgShellSurface = qobject_cast<XdgShellSurface*>(shellSurface.data());
xdgShellSurface->setFullscreen(true);
auto c = Test::renderAndWaitForShown(surface.data(), QSize(screens()->size(0)), Qt::blue);
QVERIFY(c);
QVERIFY(c->isFullScreen());
QSignalSpy fullscreenChangedSpy(c, &ShellClient::fullScreenChanged);
QVERIFY(fullscreenChangedSpy.isValid());
QSignalSpy geometryChangedSpy(c, &ShellClient::geometryChanged);
QVERIFY(geometryChangedSpy.isValid());
QSignalSpy configureRequestedSpy(shellSurface.data(), SIGNAL(configureRequested(QSize, KWayland::Client::XdgShellSurface::States, quint32)));
QVERIFY(configureRequestedSpy.isValid());
// swap back to normal
xdgShellSurface->setFullscreen(false);
QVERIFY(fullscreenChangedSpy.wait());
QVERIFY(configureRequestedSpy.wait());
QCOMPARE(configureRequestedSpy.last().first().toSize(), QSize(0, 0));
QVERIFY(!c->isFullScreen());
for (const auto &it: configureRequestedSpy) {
xdgShellSurface->ackConfigure(it[2].toInt());
}
Test::render(surface.data(), QSize(100, 50), Qt::red);
QVERIFY(geometryChangedSpy.wait());
QCOMPARE(geometryChangedSpy.count(), 1);
QVERIFY(!c->isFullScreen());
QCOMPARE(c->geometry().size(), QSize(100, 50));
}
void TestShellClient::testUserCanSetFullscreen_data()
{
QTest::addColumn<Test::ShellSurfaceType>("type");

View File

@ -920,14 +920,15 @@ void ShellClient::setFullScreen(bool set, bool user)
if (isFullScreen()) {
setGeometry(workspace()->clientArea(FullScreenArea, this));
} else {
if (!m_geomFsRestore.isNull()) {
if (m_geomFsRestore.isValid()) {
int currentScreen = screen();
setGeometry(QRect(m_geomFsRestore.topLeft(), adjustedSize(m_geomFsRestore.size())));
if( currentScreen != screen())
workspace()->sendClientToScreen( this, currentScreen );
} else {
// does this ever happen?
setGeometry(workspace()->clientArea(MaximizeArea, this));
// this can happen when the window was first shown already fullscreen,
// so let the client set the size by itself
setGeometry(QRect(workspace()->clientArea(PlacementArea, this).topLeft(), QSize(0, 0)));
}
}
updateWindowRules(Rules::Fullscreen|Rules::Position|Rules::Size);