core: defer wl_surface.leave until frame callbacks complete

fixes chromium/brave crash when moving window between visible monitors by ensuring frame callbacks are sent before leave events
This commit is contained in:
tempox777 2025-10-08 11:16:29 -05:00
parent ba24547d3d
commit 735e44c0a4
2 changed files with 30 additions and 0 deletions

View file

@ -300,6 +300,12 @@ void CWLSurfaceResource::leave(PHLMONITOR monitor) {
return;
}
if (!m_current.callbacks.empty()) {
if (std::ranges::find(m_pendingLeaveOutputs, monitor) == m_pendingLeaveOutputs.end())
m_pendingLeaveOutputs.emplace_back(monitor);
return;
}
std::erase(m_enteredOutputs, monitor);
m_resource->sendLeave(output->getResource().get());
@ -327,6 +333,26 @@ void CWLSurfaceResource::frame(const Time::steady_tp& now) {
}
m_current.callbacks.clear();
if (!m_pendingLeaveOutputs.empty()) {
for (auto const& monitor : m_pendingLeaveOutputs) {
if UNLIKELY (std::ranges::find(m_enteredOutputs, monitor) == m_enteredOutputs.end())
continue;
if UNLIKELY (!PROTO::outputs.contains(monitor->m_name))
continue;
auto output = PROTO::outputs.at(monitor->m_name)->outputResourceFrom(m_client);
if UNLIKELY (!output)
continue;
std::erase(m_enteredOutputs, monitor);
m_resource->sendLeave(output->getResource().get());
m_events.leave.emit(monitor);
}
m_pendingLeaveOutputs.clear();
}
}
void CWLSurfaceResource::resetRole() {
@ -447,6 +473,8 @@ void CWLSurfaceResource::unmap() {
m_mapped = false;
m_pendingLeaveOutputs.clear();
// release the buffers.
// this is necessary for XWayland to function correctly,
// as it does not unmap via the traditional commit(null buffer) method, but via the X11 protocol.

View file

@ -131,6 +131,8 @@ class CWLSurfaceResource {
SP<CWlSurface> m_resource;
wl_client* m_client = nullptr;
std::vector<PHLMONITORREF> m_pendingLeaveOutputs;
void destroy();
void releaseBuffers(bool onlyCurrent = true);
void dropPendingBuffer();