[wayland] Syncronise pending geometry with acked configure requests
Summary: When we want to change a client's size and position together we have to request the client becomes a new size and only then move the window to the new location. Currently we process the new position the next time the buffer updates, but with no guarantee that it has actually tried to resize/whatever yet. The client could be providing a new buffer just because the contents have changed. XDGShell has an acked serial designed to keep everything precisely in sync. A surface represents the last configure that was acked. This patch tracks the pending position for each configure and applies it accordingly. WL_shell does not have this mechanism, so behaviour is kept the same as before. ---- This is a pre-requisite to syncing maximisedState/isFullScreen with the configure request. Potentially we could remove the isWaitingForResizeSync checks when resizing and it will still resize smoothly. Test Plan: Relevant unit test still passes with the client responding Resized a window from the left edge with WLShell and XDGShellV6 Reviewers: #kwin, romangg Reviewed By: #kwin, romangg Subscribers: romangg, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D15135
This commit is contained in:
parent
413bd53aac
commit
65b8ba1770
3 changed files with 130 additions and 60 deletions
|
@ -405,6 +405,24 @@ void TestShellClient::testFullscreen()
|
||||||
QFETCH(Test::ShellSurfaceType, type);
|
QFETCH(Test::ShellSurfaceType, type);
|
||||||
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
||||||
|
|
||||||
|
ShellSurface* wlShellSurface = nullptr;
|
||||||
|
XdgShellSurface *xdgShellSurface = nullptr;
|
||||||
|
// fullscreen the window
|
||||||
|
switch (type) {
|
||||||
|
case Test::ShellSurfaceType::WlShell:
|
||||||
|
wlShellSurface = qobject_cast<ShellSurface*>(shellSurface.data());
|
||||||
|
break;
|
||||||
|
case Test::ShellSurfaceType::XdgShellV5:
|
||||||
|
case Test::ShellSurfaceType::XdgShellV6:
|
||||||
|
xdgShellSurface = qobject_cast<XdgShellSurface*>(shellSurface.data());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QVERIFY(wlShellSurface || xdgShellSurface);
|
||||||
|
QVERIFY(!(wlShellSurface && xdgShellSurface));
|
||||||
|
|
||||||
// create deco
|
// create deco
|
||||||
QScopedPointer<ServerSideDecoration> deco(Test::waylandServerSideDecoration()->create(surface.data()));
|
QScopedPointer<ServerSideDecoration> deco(Test::waylandServerSideDecoration()->create(surface.data()));
|
||||||
QSignalSpy decoSpy(deco.data(), &ServerSideDecoration::modeChanged);
|
QSignalSpy decoSpy(deco.data(), &ServerSideDecoration::modeChanged);
|
||||||
|
@ -429,20 +447,18 @@ void TestShellClient::testFullscreen()
|
||||||
QVERIFY(geometryChangedSpy.isValid());
|
QVERIFY(geometryChangedSpy.isValid());
|
||||||
QSignalSpy sizeChangeRequestedSpy(shellSurface.data(), SIGNAL(sizeChanged(QSize)));
|
QSignalSpy sizeChangeRequestedSpy(shellSurface.data(), SIGNAL(sizeChanged(QSize)));
|
||||||
QVERIFY(sizeChangeRequestedSpy.isValid());
|
QVERIFY(sizeChangeRequestedSpy.isValid());
|
||||||
|
QSignalSpy configureRequestedSpy(shellSurface.data(), SIGNAL(configureRequested(QSize, KWayland::Client::XdgShellSurface::States, quint32)));
|
||||||
// fullscreen the window
|
if (xdgShellSurface) {
|
||||||
switch (type) {
|
QVERIFY(configureRequestedSpy.isValid());
|
||||||
case Test::ShellSurfaceType::WlShell:
|
|
||||||
qobject_cast<ShellSurface*>(shellSurface.data())->setFullscreen();
|
|
||||||
break;
|
|
||||||
case Test::ShellSurfaceType::XdgShellV5:
|
|
||||||
case Test::ShellSurfaceType::XdgShellV6:
|
|
||||||
qobject_cast<XdgShellSurface*>(shellSurface.data())->setFullscreen(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlShellSurface) {
|
||||||
|
wlShellSurface->setFullscreen();
|
||||||
|
}
|
||||||
|
if (xdgShellSurface) {
|
||||||
|
xdgShellSurface->setFullscreen(true);
|
||||||
|
}
|
||||||
|
|
||||||
QVERIFY(fullscreenChangedSpy.wait());
|
QVERIFY(fullscreenChangedSpy.wait());
|
||||||
QVERIFY(sizeChangeRequestedSpy.wait());
|
QVERIFY(sizeChangeRequestedSpy.wait());
|
||||||
QCOMPARE(sizeChangeRequestedSpy.count(), 1);
|
QCOMPARE(sizeChangeRequestedSpy.count(), 1);
|
||||||
|
@ -452,7 +468,12 @@ void TestShellClient::testFullscreen()
|
||||||
QCOMPARE(c->clientSize(), QSize(100, 50));
|
QCOMPARE(c->clientSize(), QSize(100, 50));
|
||||||
QVERIFY(geometryChangedSpy.isEmpty());
|
QVERIFY(geometryChangedSpy.isEmpty());
|
||||||
|
|
||||||
// render at the new size
|
if (xdgShellSurface) {
|
||||||
|
for (const auto &it: configureRequestedSpy) {
|
||||||
|
xdgShellSurface->ackConfigure(it[2].toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Test::render(surface.data(), sizeChangeRequestedSpy.first().first().toSize(), Qt::red);
|
Test::render(surface.data(), sizeChangeRequestedSpy.first().first().toSize(), Qt::red);
|
||||||
QVERIFY(geometryChangedSpy.wait());
|
QVERIFY(geometryChangedSpy.wait());
|
||||||
QCOMPARE(geometryChangedSpy.count(), 1);
|
QCOMPARE(geometryChangedSpy.count(), 1);
|
||||||
|
@ -462,17 +483,11 @@ void TestShellClient::testFullscreen()
|
||||||
QCOMPARE(c->layer(), ActiveLayer);
|
QCOMPARE(c->layer(), ActiveLayer);
|
||||||
|
|
||||||
// swap back to normal
|
// swap back to normal
|
||||||
switch (type) {
|
if (wlShellSurface) {
|
||||||
case Test::ShellSurfaceType::WlShell:
|
wlShellSurface->setToplevel();
|
||||||
qobject_cast<ShellSurface*>(shellSurface.data())->setToplevel();
|
}
|
||||||
break;
|
if (xdgShellSurface) {
|
||||||
case Test::ShellSurfaceType::XdgShellV5:
|
xdgShellSurface->setFullscreen(false);
|
||||||
case Test::ShellSurfaceType::XdgShellV6:
|
|
||||||
qobject_cast<XdgShellSurface*>(shellSurface.data())->setFullscreen(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
QVERIFY(fullscreenChangedSpy.wait());
|
QVERIFY(fullscreenChangedSpy.wait());
|
||||||
QVERIFY(sizeChangeRequestedSpy.wait());
|
QVERIFY(sizeChangeRequestedSpy.wait());
|
||||||
|
@ -602,6 +617,24 @@ void TestShellClient::testMaximizedToFullscreen()
|
||||||
QFETCH(Test::ShellSurfaceType, type);
|
QFETCH(Test::ShellSurfaceType, type);
|
||||||
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
QScopedPointer<QObject> shellSurface(Test::createShellSurface(type, surface.data()));
|
||||||
|
|
||||||
|
ShellSurface* wlShellSurface = nullptr;
|
||||||
|
XdgShellSurface *xdgShellSurface = nullptr;
|
||||||
|
// fullscreen the window
|
||||||
|
switch (type) {
|
||||||
|
case Test::ShellSurfaceType::WlShell:
|
||||||
|
wlShellSurface = qobject_cast<ShellSurface*>(shellSurface.data());
|
||||||
|
break;
|
||||||
|
case Test::ShellSurfaceType::XdgShellV5:
|
||||||
|
case Test::ShellSurfaceType::XdgShellV6:
|
||||||
|
xdgShellSurface = qobject_cast<XdgShellSurface*>(shellSurface.data());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QVERIFY(wlShellSurface || xdgShellSurface);
|
||||||
|
QVERIFY(!(wlShellSurface && xdgShellSurface));
|
||||||
|
|
||||||
// create deco
|
// create deco
|
||||||
QScopedPointer<ServerSideDecoration> deco(Test::waylandServerSideDecoration()->create(surface.data()));
|
QScopedPointer<ServerSideDecoration> deco(Test::waylandServerSideDecoration()->create(surface.data()));
|
||||||
QSignalSpy decoSpy(deco.data(), &ServerSideDecoration::modeChanged);
|
QSignalSpy decoSpy(deco.data(), &ServerSideDecoration::modeChanged);
|
||||||
|
@ -624,19 +657,17 @@ void TestShellClient::testMaximizedToFullscreen()
|
||||||
QVERIFY(geometryChangedSpy.isValid());
|
QVERIFY(geometryChangedSpy.isValid());
|
||||||
QSignalSpy sizeChangeRequestedSpy(shellSurface.data(), SIGNAL(sizeChanged(QSize)));
|
QSignalSpy sizeChangeRequestedSpy(shellSurface.data(), SIGNAL(sizeChanged(QSize)));
|
||||||
QVERIFY(sizeChangeRequestedSpy.isValid());
|
QVERIFY(sizeChangeRequestedSpy.isValid());
|
||||||
|
QSignalSpy configureRequestedSpy(shellSurface.data(), SIGNAL(configureRequested(QSize, KWayland::Client::XdgShellSurface::States, quint32)));
|
||||||
|
if (xdgShellSurface) {
|
||||||
|
QVERIFY(configureRequestedSpy.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
// change to maximize
|
// change to maximize
|
||||||
switch (type) {
|
if (wlShellSurface) {
|
||||||
case Test::ShellSurfaceType::WlShell:
|
wlShellSurface->setMaximized();
|
||||||
qobject_cast<ShellSurface*>(shellSurface.data())->setMaximized();
|
}
|
||||||
break;
|
if (xdgShellSurface) {
|
||||||
case Test::ShellSurfaceType::XdgShellV5:
|
xdgShellSurface->setMaximized(true);
|
||||||
case Test::ShellSurfaceType::XdgShellV6:
|
|
||||||
qobject_cast<XdgShellSurface*>(shellSurface.data())->setMaximized(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
QVERIFY(sizeChangeRequestedSpy.wait());
|
QVERIFY(sizeChangeRequestedSpy.wait());
|
||||||
QCOMPARE(sizeChangeRequestedSpy.count(), 1);
|
QCOMPARE(sizeChangeRequestedSpy.count(), 1);
|
||||||
|
@ -645,17 +676,11 @@ void TestShellClient::testMaximizedToFullscreen()
|
||||||
geometryChangedSpy.clear();
|
geometryChangedSpy.clear();
|
||||||
|
|
||||||
// fullscreen the window
|
// fullscreen the window
|
||||||
switch (type) {
|
if (wlShellSurface) {
|
||||||
case Test::ShellSurfaceType::WlShell:
|
wlShellSurface->setFullscreen();
|
||||||
qobject_cast<ShellSurface*>(shellSurface.data())->setFullscreen();
|
}
|
||||||
break;
|
if (xdgShellSurface) {
|
||||||
case Test::ShellSurfaceType::XdgShellV5:
|
xdgShellSurface->setFullscreen(true);
|
||||||
case Test::ShellSurfaceType::XdgShellV6:
|
|
||||||
qobject_cast<XdgShellSurface*>(shellSurface.data())->setFullscreen(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
QVERIFY(fullscreenChangedSpy.wait());
|
QVERIFY(fullscreenChangedSpy.wait());
|
||||||
if (decoMode == ServerSideDecoration::Mode::Server) {
|
if (decoMode == ServerSideDecoration::Mode::Server) {
|
||||||
|
@ -668,6 +693,12 @@ void TestShellClient::testMaximizedToFullscreen()
|
||||||
QCOMPARE(c->clientSize(), QSize(100, 50));
|
QCOMPARE(c->clientSize(), QSize(100, 50));
|
||||||
QVERIFY(geometryChangedSpy.isEmpty());
|
QVERIFY(geometryChangedSpy.isEmpty());
|
||||||
|
|
||||||
|
if (xdgShellSurface) {
|
||||||
|
for (const auto &it: configureRequestedSpy) {
|
||||||
|
xdgShellSurface->ackConfigure(it[2].toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// render at the new size
|
// render at the new size
|
||||||
Test::render(surface.data(), sizeChangeRequestedSpy.last().first().toSize(), Qt::red);
|
Test::render(surface.data(), sizeChangeRequestedSpy.last().first().toSize(), Qt::red);
|
||||||
QVERIFY(geometryChangedSpy.wait());
|
QVERIFY(geometryChangedSpy.wait());
|
||||||
|
|
|
@ -261,6 +261,10 @@ void ShellClient::init()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_xdgShellSurface, &XdgShellSurfaceInterface::configureAcknowledged, this, [this](int serial) {
|
||||||
|
m_lastAckedConfigureRequest = serial;
|
||||||
|
});
|
||||||
|
|
||||||
connect(global, &XdgShellInterface::pingTimeout,
|
connect(global, &XdgShellInterface::pingTimeout,
|
||||||
this, [this](qint32 serial) {
|
this, [this](qint32 serial) {
|
||||||
auto it = m_pingSerials.find(serial);
|
auto it = m_pingSerials.find(serial);
|
||||||
|
@ -322,6 +326,10 @@ void ShellClient::init()
|
||||||
m_hasPopupGrab = true;
|
m_hasPopupGrab = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(m_xdgShellSurface, &XdgShellSurfaceInterface::configureAcknowledged, this, [this](int serial) {
|
||||||
|
m_lastAckedConfigureRequest = serial;
|
||||||
|
});
|
||||||
|
|
||||||
QRect position = QRect(m_xdgShellPopup->transientOffset(), m_xdgShellPopup->initialSize());
|
QRect position = QRect(m_xdgShellPopup->transientOffset(), m_xdgShellPopup->initialSize());
|
||||||
m_xdgShellPopup->configure(position);
|
m_xdgShellPopup->configure(position);
|
||||||
|
|
||||||
|
@ -485,13 +493,7 @@ void ShellClient::addDamage(const QRegion &damage)
|
||||||
auto s = surface();
|
auto s = surface();
|
||||||
if (s->size().isValid()) {
|
if (s->size().isValid()) {
|
||||||
m_clientSize = s->size();
|
m_clientSize = s->size();
|
||||||
QPoint position = geom.topLeft();
|
updatePendingGeometry();
|
||||||
if (m_positionAfterResize.isValid()) {
|
|
||||||
addLayerRepaint(geometry());
|
|
||||||
position = m_positionAfterResize.point();
|
|
||||||
m_positionAfterResize.clear();
|
|
||||||
}
|
|
||||||
doSetGeometry(QRect(position, m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
|
||||||
}
|
}
|
||||||
markAsMapped();
|
markAsMapped();
|
||||||
setDepth((s->buffer()->hasAlphaChannel() && !isDesktop()) ? 32 : 24);
|
setDepth((s->buffer()->hasAlphaChannel() && !isDesktop()) ? 32 : 24);
|
||||||
|
@ -601,7 +603,7 @@ void ShellClient::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
|
||||||
geom = geometryBeforeUpdateBlocking();
|
geom = geometryBeforeUpdateBlocking();
|
||||||
}
|
}
|
||||||
// TODO: better merge with Client's implementation
|
// TODO: better merge with Client's implementation
|
||||||
if (QSize(w, h) == geom.size() && !m_positionAfterResize.isValid()) {
|
if (QSize(w, h) == geom.size() && !isWaitingForMoveResizeSync()) {
|
||||||
// size didn't change, update directly
|
// size didn't change, update directly
|
||||||
doSetGeometry(QRect(x, y, w, h));
|
doSetGeometry(QRect(x, y, w, h));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1170,29 +1172,55 @@ void ShellClient::requestGeometry(const QRect &rect)
|
||||||
m_blockedRequestGeometry = rect;
|
m_blockedRequestGeometry = rect;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_positionAfterResize.setPoint(rect.topLeft());
|
PendingConfigureRequest configureRequest;
|
||||||
|
configureRequest.positionAfterResize = rect.topLeft();
|
||||||
|
|
||||||
const QSize size = rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom());
|
const QSize size = rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom());
|
||||||
if (m_shellSurface) {
|
if (m_shellSurface) {
|
||||||
m_shellSurface->requestSize(size);
|
m_shellSurface->requestSize(size);
|
||||||
}
|
}
|
||||||
if (m_xdgShellSurface) {
|
if (m_xdgShellSurface) {
|
||||||
m_xdgShellSurface->configure(xdgSurfaceStates(), size);
|
configureRequest.serialId = m_xdgShellSurface->configure(xdgSurfaceStates(), size);
|
||||||
}
|
}
|
||||||
if (m_xdgShellPopup) {
|
if (m_xdgShellPopup) {
|
||||||
auto parent = transientFor();
|
auto parent = transientFor();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
const QPoint globalClientContentPos = parent->geometry().topLeft() + parent->clientPos();
|
const QPoint globalClientContentPos = parent->geometry().topLeft() + parent->clientPos();
|
||||||
const QPoint relativeOffset = rect.topLeft() -globalClientContentPos;
|
const QPoint relativeOffset = rect.topLeft() -globalClientContentPos;
|
||||||
m_xdgShellPopup->configure(QRect(relativeOffset, rect.size()));
|
configureRequest.serialId = m_xdgShellPopup->configure(QRect(relativeOffset, rect.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_pendingConfigureRequests.append(configureRequest);
|
||||||
|
|
||||||
m_blockedRequestGeometry = QRect();
|
m_blockedRequestGeometry = QRect();
|
||||||
if (m_internal) {
|
if (m_internal) {
|
||||||
m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
m_internalWindow->setGeometry(QRect(rect.topLeft() + QPoint(borderLeft(), borderTop()), rect.size() - QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShellClient::updatePendingGeometry()
|
||||||
|
{
|
||||||
|
QPoint position = geom.topLeft();
|
||||||
|
for (auto it = m_pendingConfigureRequests.begin(); it != m_pendingConfigureRequests.end(); it++) {
|
||||||
|
if (it->serialId > m_lastAckedConfigureRequest) {
|
||||||
|
//this serial is not acked yet, therefore we know all future serials are not
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (it->serialId == m_lastAckedConfigureRequest) {
|
||||||
|
if (position != it->positionAfterResize) {
|
||||||
|
addLayerRepaint(geometry());
|
||||||
|
}
|
||||||
|
position = it->positionAfterResize;
|
||||||
|
|
||||||
|
m_pendingConfigureRequests.erase(m_pendingConfigureRequests.begin(), ++it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//else serialId < m_lastAckedConfigureRequest and the state is now irrelevant and can be ignored
|
||||||
|
}
|
||||||
|
doSetGeometry(QRect(position, m_clientSize + QSize(borderLeft() + borderRight(), borderTop() + borderBottom())));
|
||||||
|
}
|
||||||
|
|
||||||
void ShellClient::clientFullScreenChanged(bool fullScreen)
|
void ShellClient::clientFullScreenChanged(bool fullScreen)
|
||||||
{
|
{
|
||||||
setFullScreen(fullScreen, false);
|
setFullScreen(fullScreen, false);
|
||||||
|
@ -1534,7 +1562,7 @@ QPoint ShellClient::transientPlacementHint() const
|
||||||
|
|
||||||
bool ShellClient::isWaitingForMoveResizeSync() const
|
bool ShellClient::isWaitingForMoveResizeSync() const
|
||||||
{
|
{
|
||||||
return m_positionAfterResize.isValid();
|
return !m_pendingConfigureRequests.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellClient::doResizeSync()
|
void ShellClient::doResizeSync()
|
||||||
|
|
|
@ -202,6 +202,8 @@ private:
|
||||||
void updateClientOutputs();
|
void updateClientOutputs();
|
||||||
KWayland::Server::XdgShellSurfaceInterface::States xdgSurfaceStates() const;
|
KWayland::Server::XdgShellSurfaceInterface::States xdgSurfaceStates() const;
|
||||||
void updateShowOnScreenEdge();
|
void updateShowOnScreenEdge();
|
||||||
|
// called on surface commit and processes all m_pendingConfigureRequests up to m_lastAckedConfigureReqest
|
||||||
|
void updatePendingGeometry();
|
||||||
static void deleteClient(ShellClient *c);
|
static void deleteClient(ShellClient *c);
|
||||||
|
|
||||||
KWayland::Server::ShellSurfaceInterface *m_shellSurface;
|
KWayland::Server::ShellSurfaceInterface *m_shellSurface;
|
||||||
|
@ -209,7 +211,16 @@ private:
|
||||||
KWayland::Server::XdgShellPopupInterface *m_xdgShellPopup;
|
KWayland::Server::XdgShellPopupInterface *m_xdgShellPopup;
|
||||||
QSize m_clientSize;
|
QSize m_clientSize;
|
||||||
|
|
||||||
ClearablePoint m_positionAfterResize; // co-ordinates saved from a requestGeometry call, real geometry will be updated after the next damage event when the client has resized
|
struct PendingConfigureRequest {
|
||||||
|
//note for wl_shell we have no serial, so serialId and m_lastAckedConfigureRequest will always be 0
|
||||||
|
//meaning we treat a surface commit as having processed all requests
|
||||||
|
quint32 serialId = 0;
|
||||||
|
// position to apply after a resize operation has been completed
|
||||||
|
QPoint positionAfterResize;
|
||||||
|
};
|
||||||
|
QVector<PendingConfigureRequest> m_pendingConfigureRequests;
|
||||||
|
quint32 m_lastAckedConfigureRequest = 0;
|
||||||
|
|
||||||
QRect m_geomFsRestore; //size and position of the window before it was set to fullscreen
|
QRect m_geomFsRestore; //size and position of the window before it was set to fullscreen
|
||||||
bool m_closing = false;
|
bool m_closing = false;
|
||||||
quint32 m_windowId = 0;
|
quint32 m_windowId = 0;
|
||||||
|
|
Loading…
Reference in a new issue