[x11] Make geometry updates in X11Client more comprehensible

Summary:
This change makes geometry updates in the X11Client class simpler and
also fixes a bug in the move() method.

Test Plan: All tests pass.

Reviewers: #kwin

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D25710
This commit is contained in:
Vlad Zahorodnii 2019-12-03 09:33:14 +02:00
parent d3da912d72
commit f14adfe545
3 changed files with 43 additions and 94 deletions

View file

@ -1968,11 +1968,11 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for
if (!areGeometryUpdatesBlocked() && frameGeometry != rules()->checkGeometry(frameGeometry)) {
qCDebug(KWIN_CORE) << "forced geometry fail:" << frameGeometry << ":" << rules()->checkGeometry(frameGeometry);
}
if (!canUpdateGeometry(frameGeometry, bufferGeometry, force)) {
geom = frameGeometry;
if (force == NormalGeometrySet && m_bufferGeometry == bufferGeometry && pendingGeometryUpdate() == PendingGeometryNone) {
return;
}
m_bufferGeometry = bufferGeometry;
geom = frameGeometry;
if (areGeometryUpdatesBlocked()) {
if (pendingGeometryUpdate() == PendingGeometryForced)
{} // maximum, nothing needed
@ -1982,35 +1982,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for
setPendingGeometryUpdate(PendingGeometryNormal);
return;
}
const QRect oldBufferGeometry = bufferGeometryBeforeUpdateBlocking();
bool resized = (oldBufferGeometry.size() != m_bufferGeometry.size() || pendingGeometryUpdate() == PendingGeometryForced);
if (resized) {
resizeDecoration();
m_frame.setGeometry(m_bufferGeometry);
if (!isShade()) {
QSize cs = clientSize();
m_wrapper.setGeometry(QRect(clientPos(), cs));
if (!isResize() || syncRequest.counter == XCB_NONE)
m_client.setGeometry(0, 0, cs.width(), cs.height());
// SELI - won't this be too expensive?
// THOMAS - yes, but gtk+ clients will not resize without ...
sendSyntheticConfigureNotify();
}
updateShape();
} else {
if (isMoveResize()) {
if (compositing()) // Defer the X update until we leave this mode
needsXWindowMove = true;
else
m_frame.move(m_bufferGeometry.topLeft()); // sendSyntheticConfigureNotify() on finish shall be sufficient
} else {
m_frame.move(m_bufferGeometry.topLeft());
sendSyntheticConfigureNotify();
}
// Unconditionally move the input window: it won't affect rendering
m_decoInputExtent.move(QPoint(x, y) + inputPos());
}
updateServerGeometry();
updateWindowRules(Rules::Position|Rules::Size);
// keep track of old maximize mode
@ -2019,7 +1991,7 @@ void X11Client::setFrameGeometry(int x, int y, int w, int h, ForceGeometry_t for
workspace()->updateStackingOrder();
// Need to regenerate decoration pixmaps when the buffer size is changed.
if (oldBufferGeometry.size() != m_bufferGeometry.size()) {
if (bufferGeometryBeforeUpdateBlocking().size() != m_bufferGeometry.size()) {
discardWindowPixmap();
}
emit geometryShapeChanged(this, frameGeometryBeforeUpdateBlocking());
@ -2055,13 +2027,13 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force)
if (!areGeometryUpdatesBlocked() && frameSize != rules()->checkSize(frameSize)) {
qCDebug(KWIN_CORE) << "forced size fail:" << frameSize << ":" << rules()->checkSize(frameSize);
}
geom.setSize(frameSize);
// resuming geometry updates is handled only in setGeometry()
Q_ASSERT(pendingGeometryUpdate() == PendingGeometryNone || areGeometryUpdatesBlocked());
if (!canUpdateSize(frameSize, bufferSize, force)) {
if (force == NormalGeometrySet && m_bufferGeometry.size() == bufferSize) {
return;
}
m_bufferGeometry.setSize(bufferSize);
geom.setSize(frameSize);
if (areGeometryUpdatesBlocked()) {
if (pendingGeometryUpdate() == PendingGeometryForced)
{} // maximum, nothing needed
@ -2071,16 +2043,7 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force)
setPendingGeometryUpdate(PendingGeometryNormal);
return;
}
resizeDecoration();
m_frame.resize(m_bufferGeometry.size());
if (!isShade()) {
QSize cs = clientSize();
m_wrapper.setGeometry(QRect(clientPos(), cs));
m_client.setGeometry(0, 0, cs.width(), cs.height());
}
updateShape();
sendSyntheticConfigureNotify();
updateServerGeometry();
updateWindowRules(Rules::Position|Rules::Size);
screens()->setCurrent(this);
workspace()->updateStackingOrder();
@ -2094,6 +2057,38 @@ void X11Client::plainResize(int w, int h, ForceGeometry_t force)
emit geometryChanged();
}
void X11Client::updateServerGeometry()
{
if (m_frame.geometry().size() != m_bufferGeometry.size() || pendingGeometryUpdate() == PendingGeometryForced) {
resizeDecoration();
m_frame.setGeometry(m_bufferGeometry);
if (!isShade()) {
QSize cs = clientSize();
m_wrapper.setGeometry(QRect(clientPos(), cs));
if (!isResize() || syncRequest.counter == XCB_NONE) {
m_client.setGeometry(0, 0, cs.width(), cs.height());
}
// SELI - won't this be too expensive?
// THOMAS - yes, but gtk+ clients will not resize without ...
sendSyntheticConfigureNotify();
}
updateShape();
} else {
if (isMoveResize()) {
if (compositing()) { // Defer the X update until we leave this mode
needsXWindowMove = true;
} else {
m_frame.move(m_bufferGeometry.topLeft()); // sendSyntheticConfigureNotify() on finish shall be sufficient
}
} else {
m_frame.move(m_bufferGeometry.topLeft());
sendSyntheticConfigureNotify();
}
// Unconditionally move the input window: it won't affect rendering
m_decoInputExtent.move(pos() + inputPos());
}
}
/**
* Reimplemented to inform the client about the new window position.
*/

View file

@ -2864,49 +2864,6 @@ void X11Client::handleSync()
addRepaintFull();
}
bool X11Client::canUpdatePosition(const QPoint &frame, const QPoint &buffer, ForceGeometry_t force) const
{
// Obey forced geometry updates.
if (force != NormalGeometrySet) {
return true;
}
// Server-side geometry and our geometry are out of sync.
if (bufferGeometry().topLeft() != buffer) {
return true;
}
if (frameGeometry().topLeft() != frame) {
return true;
}
return false;
}
bool X11Client::canUpdateSize(const QSize &frame, const QSize &buffer, ForceGeometry_t force) const
{
// Obey forced geometry updates.
if (force != NormalGeometrySet) {
return true;
}
// Server-side geometry and our geometry are out of sync.
if (bufferGeometry().size() != buffer) {
return true;
}
if (frameGeometry().size() != frame) {
return true;
}
return false;
}
bool X11Client::canUpdateGeometry(const QRect &frame, const QRect &buffer, ForceGeometry_t force) const
{
if (canUpdatePosition(frame.topLeft(), buffer.topLeft(), force)) {
return true;
}
if (canUpdateSize(frame.size(), buffer.size(), force)) {
return true;
}
return pendingGeometryUpdate() != PendingGeometryNone;
}
void X11Client::move(int x, int y, ForceGeometry_t force)
{
const QPoint framePosition(x, y);
@ -2917,11 +2874,11 @@ void X11Client::move(int x, int y, ForceGeometry_t force)
if (!areGeometryUpdatesBlocked() && framePosition != rules()->checkPosition(framePosition)) {
qCDebug(KWIN_CORE) << "forced position fail:" << framePosition << ":" << rules()->checkPosition(framePosition);
}
if (!canUpdatePosition(framePosition, bufferPosition, force)) {
geom.moveTopLeft(framePosition);
if (force == NormalGeometrySet && m_bufferGeometry.topLeft() == bufferPosition) {
return;
}
m_bufferGeometry.moveTopLeft(bufferPosition);
geom.moveTopLeft(framePosition);
if (areGeometryUpdatesBlocked()) {
if (pendingGeometryUpdate() == PendingGeometryForced) {
// Maximum, nothing needed.
@ -2932,8 +2889,7 @@ void X11Client::move(int x, int y, ForceGeometry_t force)
}
return;
}
m_frame.move(m_bufferGeometry.topLeft());
sendSyntheticConfigureNotify();
updateServerGeometry();
updateWindowRules(Rules::Position);
screens()->setCurrent(this);
workspace()->updateStackingOrder();

View file

@ -446,9 +446,6 @@ private:
void destroyDecoration() override;
void updateFrameExtents();
void setClientFrameExtents(const NETStrut &strut);
bool canUpdatePosition(const QPoint &frame, const QPoint &buffer, ForceGeometry_t force) const;
bool canUpdateSize(const QSize &frame, const QSize &buffer, ForceGeometry_t force) const;
bool canUpdateGeometry(const QRect &frame, const QRect &buffer, ForceGeometry_t force) const;
void internalShow();
void internalHide();
@ -458,6 +455,7 @@ private:
void updateHiddenPreview();
void updateInputShape();
void updateServerGeometry();
xcb_timestamp_t readUserTimeMapTimestamp(const KStartupInfoId* asn_id, const KStartupInfoData* asn_data,
bool session) const;