diff --git a/autotests/integration/xdgshellclient_test.cpp b/autotests/integration/xdgshellclient_test.cpp index 53f698f1f5..36e64ddc03 100644 --- a/autotests/integration/xdgshellclient_test.cpp +++ b/autotests/integration/xdgshellclient_test.cpp @@ -68,9 +68,7 @@ private Q_SLOTS: void testFullscreen_data(); void testFullscreen(); - void testFullscreenRestore(); void testUserCanSetFullscreen(); - void testUserSetFullscreen(); void testMaximizeHorizontal(); void testMaximizeVertical(); @@ -432,13 +430,8 @@ void TestXdgShellClient::testFullscreen() shellSurface->ackConfigure(configureRequestedSpy.last().at(2).value()); Test::render(surface.data(), configureRequestedSpy.last().at(0).value(), Qt::red); -#if 0 // TODO: Uncomment when full screen state updates are truly asynchronous. QVERIFY(fullScreenChangedSpy.wait()); QCOMPARE(fullScreenChangedSpy.count(), 1); -#else - QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(fullScreenChangedSpy.count(), 1); -#endif QVERIFY(client->isFullScreen()); QVERIFY(!client->isDecorated()); QCOMPARE(client->layer(), ActiveLayer); @@ -455,13 +448,8 @@ void TestXdgShellClient::testFullscreen() shellSurface->ackConfigure(configureRequestedSpy.last().at(2).value()); Test::render(surface.data(), configureRequestedSpy.last().at(0).value(), Qt::blue); -#if 0 // TODO: Uncomment when full screen state updates are truly asynchronous. QVERIFY(fullScreenChangedSpy.wait()); QCOMPARE(fullScreenChangedSpy.count(), 2); -#else - QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(fullScreenChangedSpy.count(), 2); -#endif QCOMPARE(client->clientSize(), QSize(100, 50)); QVERIFY(!client->isFullScreen()); QCOMPARE(client->isDecorated(), decoMode == ServerSideDecoration::Mode::Server); @@ -472,58 +460,6 @@ void TestXdgShellClient::testFullscreen() QVERIFY(Test::waitForWindowDestroyed(client)); } -void TestXdgShellClient::testFullscreenRestore() -{ - // this test verifies that windows created fullscreen can be later properly restored - QScopedPointer surface(Test::createSurface()); - XdgShellSurface *xdgShellSurface = Test::createXdgShellStableSurface(surface.data(), surface.data(), Test::CreationSetup::CreateOnly); - QSignalSpy configureRequestedSpy(xdgShellSurface, &XdgShellSurface::configureRequested); - - // fullscreen the window - xdgShellSurface->setFullscreen(true); - surface->commit(Surface::CommitFlag::None); - - configureRequestedSpy.wait(); - QCOMPARE(configureRequestedSpy.count(), 1); - - const auto size = configureRequestedSpy.first()[0].value(); - const auto state = configureRequestedSpy.first()[1].value(); - - QCOMPARE(size, screens()->size(0)); - QVERIFY(state & KWayland::Client::XdgShellSurface::State::Fullscreen); - xdgShellSurface->ackConfigure(configureRequestedSpy.first()[2].toUInt()); - - auto c = Test::renderAndWaitForShown(surface.data(), size, Qt::blue); - QVERIFY(c); - QVERIFY(c->isFullScreen()); - - configureRequestedSpy.wait(100); - - QSignalSpy fullscreenChangedSpy(c, &AbstractClient::fullScreenChanged); - QVERIFY(fullscreenChangedSpy.isValid()); - QSignalSpy frameGeometryChangedSpy(c, &AbstractClient::frameGeometryChanged); - QVERIFY(frameGeometryChangedSpy.isValid()); - - // swap back to normal - configureRequestedSpy.clear(); - 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].toUInt()); - } - - Test::render(surface.data(), QSize(100, 50), Qt::red); - QVERIFY(frameGeometryChangedSpy.wait()); - QCOMPARE(frameGeometryChangedSpy.count(), 1); - QVERIFY(!c->isFullScreen()); - QCOMPARE(c->frameGeometry().size(), QSize(100, 50)); -} - void TestXdgShellClient::testUserCanSetFullscreen() { QScopedPointer surface(Test::createSurface()); @@ -535,59 +471,6 @@ void TestXdgShellClient::testUserCanSetFullscreen() QVERIFY(c->userCanSetFullScreen()); } -void TestXdgShellClient::testUserSetFullscreen() -{ - QScopedPointer surface(Test::createSurface()); - QScopedPointer shellSurface(Test::createXdgShellStableSurface( - surface.data(), surface.data(), Test::CreationSetup::CreateOnly)); - QVERIFY(!shellSurface.isNull()); - - // wait for the initial configure event - QSignalSpy configureRequestedSpy(shellSurface.data(), &XdgShellSurface::configureRequested); - QVERIFY(configureRequestedSpy.isValid()); - surface->commit(Surface::CommitFlag::None); - QVERIFY(configureRequestedSpy.wait()); - QCOMPARE(configureRequestedSpy.count(), 1); - - shellSurface->ackConfigure(configureRequestedSpy.last().at(2).value()); - auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); - QVERIFY(c); - QVERIFY(c->isActive()); - QVERIFY(!c->isFullScreen()); - - // The client gets activated, which gets another configure event. Though that's not relevant to the test - configureRequestedSpy.wait(10); - - QSignalSpy fullscreenChangedSpy(c, &AbstractClient::fullScreenChanged); - QVERIFY(fullscreenChangedSpy.isValid()); - c->setFullScreen(true); - QCOMPARE(c->isFullScreen(), true); - configureRequestedSpy.clear(); - QVERIFY(configureRequestedSpy.wait()); - QCOMPARE(configureRequestedSpy.count(), 1); - QCOMPARE(configureRequestedSpy.first().at(0).toSize(), screens()->size(0)); - const auto states = configureRequestedSpy.first().at(1).value(); - QVERIFY(states.testFlag(KWayland::Client::XdgShellSurface::State::Fullscreen)); - QVERIFY(states.testFlag(KWayland::Client::XdgShellSurface::State::Activated)); - QVERIFY(!states.testFlag(KWayland::Client::XdgShellSurface::State::Maximized)); - QVERIFY(!states.testFlag(KWayland::Client::XdgShellSurface::State::Resizing)); - QCOMPARE(fullscreenChangedSpy.count(), 1); - QVERIFY(c->isFullScreen()); - - shellSurface->ackConfigure(configureRequestedSpy.first().at(2).value()); - - // unset fullscreen again - c->setFullScreen(false); - QCOMPARE(c->isFullScreen(), false); - configureRequestedSpy.clear(); - QVERIFY(configureRequestedSpy.wait()); - QCOMPARE(configureRequestedSpy.count(), 1); - QCOMPARE(configureRequestedSpy.first().at(0).toSize(), QSize(100, 50)); - QVERIFY(!configureRequestedSpy.first().at(1).value().testFlag(KWayland::Client::XdgShellSurface::State::Fullscreen)); - QCOMPARE(fullscreenChangedSpy.count(), 2); - QVERIFY(!c->isFullScreen()); -} - void TestXdgShellClient::testMaximizedToFullscreen_data() { QTest::addColumn("decoMode"); @@ -660,12 +543,8 @@ void TestXdgShellClient::testMaximizedToFullscreen() shellSurface->ackConfigure(configureRequestedSpy.last().at(2).value()); Test::render(surface.data(), configureRequestedSpy.last().at(0).value(), Qt::red); -#if 0 // TODO: Uncomment when full screen changes are truly asynchronous. - QVERIFY(fullScreenChangedSpy.wait()); - QCOMPARE(fullScreenChangedSpy.count(), 1); -#else - QTRY_COMPARE(fullscreenChangedSpy.count(), 1); -#endif + QVERIFY(fullscreenChangedSpy.wait()); + QCOMPARE(fullscreenChangedSpy.count(), 1); QCOMPARE(client->maximizeMode(), MaximizeFull); QVERIFY(client->isFullScreen()); QVERIFY(!client->isDecorated()); diff --git a/src/abstract_client.cpp b/src/abstract_client.cpp index 4d14fbbabd..720b3e215b 100644 --- a/src/abstract_client.cpp +++ b/src/abstract_client.cpp @@ -3615,6 +3615,11 @@ bool AbstractClient::isFullScreen() const return false; } +bool AbstractClient::isRequestedFullScreen() const +{ + return isFullScreen(); +} + /** * Returns whether requests initiated by the user to enter or leave full screen mode are honored. * diff --git a/src/abstract_client.h b/src/abstract_client.h index 7be88fdcc2..55ffe7c639 100644 --- a/src/abstract_client.h +++ b/src/abstract_client.h @@ -419,6 +419,7 @@ public: virtual void hideClient(bool hide) = 0; virtual bool isFullScreenable() const; virtual bool isFullScreen() const; + virtual bool isRequestedFullScreen() const; // TODO: remove boolean trap virtual AbstractClient *findModal(bool allow_itself = false) = 0; virtual bool isTransient() const; diff --git a/src/workspace.cpp b/src/workspace.cpp index 4924072784..78a865e8f9 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -718,7 +718,7 @@ void Workspace::addShellClient(AbstractClient *client) if (client->isPlaceable()) { const QRect area = clientArea(PlacementArea, Screens::self()->current(), client->desktop()); bool placementDone = false; - if (client->isFullScreen()) { + if (client->isRequestedFullScreen()) { placementDone = true; } if (client->maximizeMode() == MaximizeMode::MaximizeFull) { diff --git a/src/xdgshellclient.cpp b/src/xdgshellclient.cpp index 02f5c7775a..f1468284f0 100644 --- a/src/xdgshellclient.cpp +++ b/src/xdgshellclient.cpp @@ -457,9 +457,14 @@ bool XdgToplevelClient::isFullScreen() const return m_isFullScreen; } +bool XdgToplevelClient::isRequestedFullScreen() const +{ + return m_isRequestedFullScreen; +} + bool XdgToplevelClient::isMovable() const { - if (isFullScreen()) { + if (isRequestedFullScreen()) { return false; } if (isSpecialWindow() && !isSplash() && !isToolbar()) { @@ -484,7 +489,7 @@ bool XdgToplevelClient::isMovableAcrossScreens() const bool XdgToplevelClient::isResizable() const { - if (isFullScreen()) { + if (isRequestedFullScreen()) { return false; } if (isSpecialWindow() || isSplash() || isToolbar()) { @@ -577,7 +582,7 @@ bool XdgToplevelClient::noBorder() const if (m_serverDecoration) { switch (m_serverDecoration->mode()) { case ServerSideDecorationManagerInterface::Mode::Server: - return m_userNoBorder || isFullScreen(); + return m_userNoBorder || isRequestedFullScreen(); case ServerSideDecorationManagerInterface::Mode::Client: case ServerSideDecorationManagerInterface::Mode::None: return true; @@ -587,7 +592,7 @@ bool XdgToplevelClient::noBorder() const switch (m_xdgDecoration->preferredMode()) { case XdgToplevelDecorationV1Interface::Mode::Server: case XdgToplevelDecorationV1Interface::Mode::Undefined: - return !Decoration::DecorationBridge::hasPlugin() || m_userNoBorder || isFullScreen(); + return !Decoration::DecorationBridge::hasPlugin() || m_userNoBorder || isRequestedFullScreen(); case XdgToplevelDecorationV1Interface::Mode::Client: return true; } @@ -791,7 +796,7 @@ void XdgToplevelClient::doSetActive() void XdgToplevelClient::doSetFullScreen() { - if (isFullScreen()) { + if (isRequestedFullScreen()) { m_requestedStates |= XdgToplevelInterface::State::FullScreen; } else { m_requestedStates &= ~XdgToplevelInterface::State::FullScreen; @@ -1223,7 +1228,7 @@ void XdgToplevelClient::initialize() RuleBook::self()->discardUsed(this, false); // Remove Apply Now rules. updateWindowRules(Rules::All); } - if (isFullScreen()) { + if (isRequestedFullScreen()) { needsPlacement = false; } if (needsPlacement) { @@ -1253,7 +1258,9 @@ void XdgToplevelClient::updateFullScreenMode(bool set) if (m_isFullScreen == set) { return; } + StackingUpdatesBlocker blocker1(workspace()); m_isFullScreen = set; + updateLayer(); updateWindowRules(Rules::Fullscreen); emit fullScreenChanged(); } @@ -1527,7 +1534,7 @@ void XdgToplevelClient::setFullScreen(bool set, bool user) { set = rules()->checkFullScreen(set); - const bool wasFullscreen = isFullScreen(); + const bool wasFullscreen = isRequestedFullScreen(); if (wasFullscreen == set) { return; } @@ -1543,18 +1550,16 @@ void XdgToplevelClient::setFullScreen(bool set, bool user) } else { setFullscreenGeometryRestore(frameGeometry()); } - m_isFullScreen = set; + m_isRequestedFullScreen = set; if (set) { workspace()->raiseClient(this); } - StackingUpdatesBlocker blocker1(workspace()); GeometryUpdatesBlocker blocker2(this); if (set) { dontMoveResize(); } - workspace()->updateClientLayer(this); // active fullscreens get different layer updateDecoration(false, false); if (set) { @@ -1576,9 +1581,6 @@ void XdgToplevelClient::setFullScreen(bool set, bool user) } doSetFullScreen(); - - updateWindowRules(Rules::Fullscreen|Rules::Position|Rules::Size); - emit fullScreenChanged(); } /** diff --git a/src/xdgshellclient.h b/src/xdgshellclient.h index 752cf2a3a2..233d3c91ca 100644 --- a/src/xdgshellclient.h +++ b/src/xdgshellclient.h @@ -126,6 +126,7 @@ public: QSize minSize() const override; QSize maxSize() const override; bool isFullScreen() const override; + bool isRequestedFullScreen() const override; bool isMovableAcrossScreens() const override; bool isMovable() const override; bool isResizable() const override; @@ -215,6 +216,7 @@ private: MaximizeMode m_maximizeMode = MaximizeRestore; MaximizeMode m_requestedMaximizeMode = MaximizeRestore; bool m_isFullScreen = false; + bool m_isRequestedFullScreen = false; bool m_isInitialized = false; bool m_userNoBorder = false; bool m_isTransient = false;