Commit b9b73570 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

wayland: Fix getting the last configure event

If there's only one configure event that changes the position of the
window and it gets acknowledged but no buffer is attached yet, and a new
configure is sent, then the ConfigurePosition flag won't be inherited
by the new configure event and the window will be misplaced.

In order to fix that, this change makes XdgSurfaceClient pop the last
acknowledged configure event from the m_configureEvents list only when
it's about to be applied for sure.

BUG: 448856
parent 8f941e52
Pipeline #128238 passed with stage
in 14 minutes and 51 seconds
......@@ -103,6 +103,7 @@ private Q_SLOTS:
void testPointerInputTransform();
void testReentrantSetFrameGeometry();
void testDoubleMaximize();
void testDoubleFullscreenSeparatedByCommit();
void testMaximizeAndChangeDecorationModeAfterInitialCommit();
void testFullScreenAndChangeDecorationModeAfterInitialCommit();
void testChangeDecorationModeAfterInitialCommit();
......@@ -1565,6 +1566,39 @@ void TestXdgShellClient::testDoubleMaximize()
QVERIFY(states.testFlag(Test::XdgToplevel::State::Maximized));
}
void TestXdgShellClient::testDoubleFullscreenSeparatedByCommit()
{
// Some applications do weird things at startup and this is one of them. This test verifies
// that the window will have good frame geometry if the client has issued several
// xdg_toplevel.set_fullscreen requests and they are separated by a surface commit with
// no attached buffer.
QScopedPointer<KWayland::Client::Surface> surface(Test::createSurface());
QScopedPointer<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.data()));
QSignalSpy toplevelConfigureRequestedSpy(shellSurface.data(), &Test::XdgToplevel::configureRequested);
QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
// Tell the compositor that we want the window to be shown in fullscreen mode.
shellSurface->set_fullscreen(nullptr);
QVERIFY(surfaceConfigureRequestedSpy.wait());
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280, 1024));
QVERIFY(toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>() & Test::XdgToplevel::State::Fullscreen);
// Ask again.
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
surface->commit(KWayland::Client::Surface::CommitFlag::None);
shellSurface->set_fullscreen(nullptr);
QVERIFY(surfaceConfigureRequestedSpy.wait());
QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).value<QSize>(), QSize(1280, 1024));
QVERIFY(toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>() & Test::XdgToplevel::State::Fullscreen);
// Map the window.
shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
auto client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::blue);
QVERIFY(client->isFullScreen());
QCOMPARE(client->frameGeometry(), QRect(0, 0, 1280, 1024));
}
void TestXdgShellClient::testMaximizeHorizontal()
{
// Create the test client.
......
......@@ -146,12 +146,7 @@ void XdgSurfaceClient::sendConfigure()
void XdgSurfaceClient::handleConfigureAcknowledged(quint32 serial)
{
while (!m_configureEvents.isEmpty()) {
if (serial < m_configureEvents.first()->serial) {
break;
}
m_lastAcknowledgedConfigure.reset(m_configureEvents.takeFirst());
}
m_lastAcknowledgedConfigureSerial = serial;
}
void XdgSurfaceClient::handleCommit()
......@@ -160,6 +155,16 @@ void XdgSurfaceClient::handleCommit()
return;
}
if (m_lastAcknowledgedConfigureSerial.has_value()) {
const quint32 serial = m_lastAcknowledgedConfigureSerial.value();
while (!m_configureEvents.isEmpty()) {
if (serial < m_configureEvents.constFirst()->serial) {
break;
}
m_lastAcknowledgedConfigure.reset(m_configureEvents.takeFirst());
}
}
handleRolePrecommit();
if (haveNextWindowGeometry()) {
handleNextWindowGeometry();
......@@ -168,6 +173,7 @@ void XdgSurfaceClient::handleCommit()
handleRoleCommit();
m_lastAcknowledgedConfigure.reset();
m_lastAcknowledgedConfigureSerial.reset();
setReadyForPainting();
updateDepth();
......
......@@ -18,6 +18,8 @@
#include <QQueue>
#include <QTimer>
#include <optional>
namespace KWaylandServer
{
class AppMenuInterface;
......@@ -96,6 +98,7 @@ private:
XdgSurfaceConfigure::ConfigureFlags m_configureFlags;
QQueue<XdgSurfaceConfigure *> m_configureEvents;
QScopedPointer<XdgSurfaceConfigure> m_lastAcknowledgedConfigure;
std::optional<quint32> m_lastAcknowledgedConfigureSerial;
QRect m_windowGeometry;
bool m_haveNextWindowGeometry = false;
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment