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
remotes/origin/work/zzag/restricted-move
Vlad Zahorodnii 4 years ago
parent 8f941e5250
commit b9b7357086
  1. 34
      autotests/integration/xdgshellclient_test.cpp
  2. 18
      src/xdgshellclient.cpp
  3. 3
      src/xdgshellclient.h

@ -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;
};

Loading…
Cancel
Save