From 829158f830555c031755c6d4348e684779264342 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Mon, 8 Feb 2016 18:56:59 -0800 Subject: [PATCH 101/105] Check whether there is any BadWindow error before monitor the event The tray window itself may be destroyed before we start monitor the event of it. Check the returned error and skip this window if BadWindow happens. FIXED-IN: 5.6.0 BUG: 358719 REVIEW: 127014 --- xembed-sni-proxy/fdoselectionmanager.cpp | 28 +++++++++++++++++++++++----- xembed-sni-proxy/fdoselectionmanager.h | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/xembed-sni-proxy/fdoselectionmanager.cpp b/xembed-sni-proxy/fdoselectionmanager.cpp index ab91044..9c7163d 100644 --- a/xembed-sni-proxy/fdoselectionmanager.cpp +++ b/xembed-sni-proxy/fdoselectionmanager.cpp @@ -83,7 +83,7 @@ void FdoSelectionManager::init() m_selectionOwner->claim(false); } -void FdoSelectionManager::addDamageWatch(xcb_window_t client) +bool FdoSelectionManager::addDamageWatch(xcb_window_t client) { qCDebug(SNIPROXY) << "adding damage watch for " << client; @@ -94,15 +94,27 @@ void FdoSelectionManager::addDamageWatch(xcb_window_t client) m_damageWatches[client] = damageId; xcb_damage_create(c, damageId, client, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); - QScopedPointer attr(xcb_get_window_attributes_reply(c, attribsCookie, Q_NULLPTR)); + xcb_generic_error_t *error = Q_NULLPTR; + QScopedPointer attr(xcb_get_window_attributes_reply(c, attribsCookie, &error)); + QScopedPointer getAttrError(error); uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY; if (!attr.isNull()) { events = events | attr->your_event_mask; } + // if window is already gone, there is no need to handle it. + if (getAttrError && getAttrError->error_code == XCB_WINDOW) { + return false; + } // the event mask will not be removed again. We cannot track whether another component also needs STRUCTURE_NOTIFY (e.g. KWindowSystem). // if we would remove the event mask again, other areas will break. - xcb_change_window_attributes(c, client, XCB_CW_EVENT_MASK, &events); + const auto changeAttrCookie = xcb_change_window_attributes_checked(c, client, XCB_CW_EVENT_MASK, &events); + QScopedPointer changeAttrError(xcb_request_check(c, changeAttrCookie)); + // if window is gone by this point, it will be catched by eventFilter, so no need to check later errors. + if (changeAttrError && changeAttrError->error_code == XCB_WINDOW) { + return false; + } + return true; } bool FdoSelectionManager::nativeEventFilter(const QByteArray& eventType, void* message, long int* result) @@ -130,6 +142,11 @@ bool FdoSelectionManager::nativeEventFilter(const QByteArray& eventType, void* m if (m_proxies[unmappedWId]) { undock(unmappedWId); } + } else if (responseType == XCB_DESTROY_NOTIFY) { + const auto destroyedWId = reinterpret_cast(ev)->window; + if (m_proxies[destroyedWId]) { + undock(destroyedWId); + } } else if (responseType == m_damageEventBase + XCB_DAMAGE_NOTIFY) { const auto damagedWId = reinterpret_cast(ev)->drawable; const auto sniProx = m_proxies[damagedWId]; @@ -153,8 +170,9 @@ void FdoSelectionManager::dock(xcb_window_t winId) return; } - addDamageWatch(winId); - m_proxies[winId] = new SNIProxy(winId, this); + if (addDamageWatch(winId)) { + m_proxies[winId] = new SNIProxy(winId, this); + } } void FdoSelectionManager::undock(xcb_window_t winId) diff --git a/xembed-sni-proxy/fdoselectionmanager.h b/xembed-sni-proxy/fdoselectionmanager.h index 650d52f..f70256d 100644 --- a/xembed-sni-proxy/fdoselectionmanager.h +++ b/xembed-sni-proxy/fdoselectionmanager.h @@ -48,7 +48,7 @@ private Q_SLOTS: private: void init(); - void addDamageWatch(xcb_window_t client); + bool addDamageWatch(xcb_window_t client); void dock(xcb_window_t embed_win); void undock(xcb_window_t client); void compositingChanged(); -- 2.5.0