x11: Handle late sync request
X11Client implicitly relied on the finishInteractiveMoveResize() function to call moveResize() to synchronize the move resize geometry with the server geometry. However, after removing that moveResize(), X11Client got slightly broken. A resize sync request may arrive shortly after finishing resize. In order to properly handle it, this change makes X11Client handle late sync requests. It also makes handling interactive resize on x11 similar to how it's done on wayland. The main problem with not letting X11Client finish interactive resize is that the Toplevel::bufferGeometry() may end up with an outdated value and SurfacePixmapX11 will fail to create due to a mismatch between Toplevel::bufferGeometry() and the server side geometry of the frame window.
This commit is contained in:
parent
b4f2bc3898
commit
9a4a960886
2 changed files with 25 additions and 19 deletions
|
@ -193,6 +193,7 @@ X11Client::X11Client()
|
|||
m_syncRequest.timeout = m_syncRequest.failsafeTimeout = nullptr;
|
||||
m_syncRequest.lastTimestamp = xTime();
|
||||
m_syncRequest.isPending = false;
|
||||
m_syncRequest.interactiveResize = false;
|
||||
|
||||
// Set the initial mapping state
|
||||
mapping_state = Withdrawn;
|
||||
|
@ -2290,6 +2291,7 @@ void X11Client::sendSyncRequest()
|
|||
}
|
||||
// failed during resize
|
||||
m_syncRequest.isPending = false;
|
||||
m_syncRequest.interactiveResize = false;
|
||||
m_syncRequest.counter = XCB_NONE;
|
||||
m_syncRequest.alarm = XCB_NONE;
|
||||
delete m_syncRequest.timeout;
|
||||
|
@ -2321,6 +2323,7 @@ void X11Client::sendSyncRequest()
|
|||
sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_sync_request,
|
||||
m_syncRequest.value.lo, m_syncRequest.value.hi);
|
||||
m_syncRequest.isPending = true;
|
||||
m_syncRequest.interactiveResize = isInteractiveResize();
|
||||
m_syncRequest.lastTimestamp = xTime();
|
||||
}
|
||||
|
||||
|
@ -2766,21 +2769,21 @@ void X11Client::handleSync()
|
|||
if (m_syncRequest.failsafeTimeout) {
|
||||
m_syncRequest.failsafeTimeout->stop();
|
||||
}
|
||||
if (isInteractiveResize()) {
|
||||
|
||||
// Sync request can be acknowledged shortly after finishing resize.
|
||||
if (m_syncRequest.interactiveResize) {
|
||||
m_syncRequest.interactiveResize = false;
|
||||
if (m_syncRequest.timeout) {
|
||||
m_syncRequest.timeout->stop();
|
||||
}
|
||||
performInteractiveResize();
|
||||
updateWindowPixmap();
|
||||
} else // setReadyForPainting does as well, but there's a small chance for resize syncs after the resize ended
|
||||
addRepaintFull();
|
||||
}
|
||||
}
|
||||
|
||||
void X11Client::performInteractiveResize()
|
||||
{
|
||||
if (isInteractiveResize()) {
|
||||
resize(moveResizeGeometry().size());
|
||||
}
|
||||
resize(moveResizeGeometry().size());
|
||||
}
|
||||
|
||||
bool X11Client::belongToSameApplication(const X11Client *c1, const X11Client *c2, SameApplicationChecks checks)
|
||||
|
@ -4544,17 +4547,12 @@ void X11Client::leaveInteractiveMoveResize()
|
|||
move_resize_has_keyboard_grab = false;
|
||||
xcb_ungrab_pointer(connection(), xTime());
|
||||
m_moveResizeGrabWindow.reset();
|
||||
if (m_syncRequest.counter == XCB_NONE) { // don't forget to sanitize since the timeout will no more fire
|
||||
m_syncRequest.isPending = false;
|
||||
}
|
||||
delete m_syncRequest.timeout;
|
||||
m_syncRequest.timeout = nullptr;
|
||||
AbstractClient::leaveInteractiveMoveResize();
|
||||
}
|
||||
|
||||
bool X11Client::isWaitingForInteractiveMoveResizeSync() const
|
||||
{
|
||||
return m_syncRequest.isPending && isInteractiveResize();
|
||||
return m_syncRequest.isPending && m_syncRequest.interactiveResize;
|
||||
}
|
||||
|
||||
void X11Client::doInteractiveResizeSync()
|
||||
|
@ -4564,13 +4562,19 @@ void X11Client::doInteractiveResizeSync()
|
|||
connect(m_syncRequest.timeout, &QTimer::timeout, this, &X11Client::handleSyncTimeout);
|
||||
m_syncRequest.timeout->setSingleShot(true);
|
||||
}
|
||||
|
||||
if (m_syncRequest.counter != XCB_NONE) {
|
||||
m_syncRequest.timeout->start(250);
|
||||
sendSyncRequest();
|
||||
} else { // for clients not supporting the XSYNC protocol, we
|
||||
m_syncRequest.isPending = true; // limit the resizes to 30Hz to take pointless load from X11
|
||||
m_syncRequest.timeout->start(33); // and the client, the mouse is still moved at full speed
|
||||
} // and no human can control faster resizes anyway
|
||||
} else {
|
||||
// For clients not supporting the XSYNC protocol, we limit the resizes to 30Hz
|
||||
// to take pointless load from X11 and the client, the mouse is still moved at
|
||||
// full speed and no human can control faster resizes anyway.
|
||||
m_syncRequest.isPending = true;
|
||||
m_syncRequest.interactiveResize = true;
|
||||
m_syncRequest.timeout->start(33);
|
||||
}
|
||||
|
||||
const QRect moveResizeClientGeometry = frameRectToClientRect(moveResizeGeometry());
|
||||
const QRect moveResizeBufferGeometry = frameRectToBufferRect(moveResizeGeometry());
|
||||
|
||||
|
@ -4585,9 +4589,10 @@ void X11Client::doInteractiveResizeSync()
|
|||
|
||||
void X11Client::handleSyncTimeout()
|
||||
{
|
||||
if (m_syncRequest.counter == XCB_NONE) { // client w/o XSYNC support. allow the next resize event
|
||||
m_syncRequest.isPending = false; // NEVER do this for clients with a valid counter
|
||||
} // (leads to sync request races in some clients)
|
||||
if (m_syncRequest.counter == XCB_NONE) { // client w/o XSYNC support. allow the next resize event
|
||||
m_syncRequest.isPending = false; // NEVER do this for clients with a valid counter
|
||||
m_syncRequest.interactiveResize = false; // (leads to sync request races in some clients)
|
||||
}
|
||||
performInteractiveResize();
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,7 @@ public:
|
|||
xcb_timestamp_t lastTimestamp;
|
||||
QTimer *timeout, *failsafeTimeout;
|
||||
bool isPending;
|
||||
bool interactiveResize;
|
||||
};
|
||||
const SyncRequest &syncRequest() const {
|
||||
return m_syncRequest;
|
||||
|
|
Loading…
Reference in a new issue