From 5afe5f810e2a76dc6fff4088746f2728c8a6a93d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 3 May 2013 08:53:35 +0200 Subject: [PATCH] Port Client::transient_for handling to XCB The type of the transient_for related variables are changed to xcb_window_t. They cannot be Xcb::Window as we don't take ownership over the transient for window. Variables are renamed to m_camelCase to follow naming scheme. A wrapper for retrieving the TransientFor hint is added to the Xcb Wrappers. --- client.cpp | 4 ++-- client.h | 16 ++++++------- group.cpp | 67 ++++++++++++++++++++++++++---------------------------- xcbutils.h | 22 ++++++++++++++++++ 4 files changed, 64 insertions(+), 45 deletions(-) diff --git a/client.cpp b/client.cpp index b85b5c0138..5ecd29efbc 100644 --- a/client.cpp +++ b/client.cpp @@ -99,8 +99,8 @@ Client::Client() , move_resize_has_keyboard_grab(false) , m_managed(false) , transient_for (NULL) - , transient_for_id(None) - , original_transient_for_id(None) + , m_transientForId(XCB_WINDOW_NONE) + , m_originalTransientForId(XCB_WINDOW_NONE) , shade_below(NULL) , skip_switcher(false) , blocks_compositing(false) diff --git a/client.h b/client.h index 174c541ab6..b346c785f8 100644 --- a/client.h +++ b/client.h @@ -283,7 +283,7 @@ public: ClientList allMainClients() const; // Call once before loop , is indirect bool hasTransient(const Client* c, bool indirect) const; const ClientList& transients() const; // Is not indirect - void checkTransient(Window w); + void checkTransient(xcb_window_t w); Client* findModal(bool allow_itself = false); const Group* group() const; Group* group(); @@ -869,16 +869,16 @@ private: int quick_tile_mode; void readTransient(); - Window verifyTransientFor(Window transient_for, bool set); + xcb_window_t verifyTransientFor(xcb_window_t transient_for, bool set); void addTransient(Client* cl); void removeTransient(Client* cl); void removeFromMainClients(); void cleanGrouping(); void checkGroupTransients(); - void setTransient(Window new_transient_for_id); + void setTransient(xcb_window_t new_transient_for_id); Client* transient_for; - Window transient_for_id; - Window original_transient_for_id; + xcb_window_t m_transientForId; + xcb_window_t m_originalTransientForId; ClientList transients_list; // SELI TODO: Make this ordered in stacking order? ShadeMode shade_mode; Client *shade_below; @@ -1033,19 +1033,19 @@ inline Client* Client::transientFor() inline bool Client::groupTransient() const { - return transient_for_id == rootWindow(); + return m_transientForId == rootWindow(); } // Needed because verifyTransientFor() may set transient_for_id to root window, // if the original value has a problem (window doesn't exist, etc.) inline bool Client::wasOriginallyGroupTransient() const { - return original_transient_for_id == rootWindow(); + return m_originalTransientForId == rootWindow(); } inline bool Client::isTransient() const { - return transient_for_id != None; + return m_transientForId != XCB_WINDOW_NONE; } inline const ClientList& Client::transients() const diff --git a/group.cpp b/group.cpp index afb122ed5a..18b442eeeb 100644 --- a/group.cpp +++ b/group.cpp @@ -588,26 +588,27 @@ bool Client::sameAppWindowRoleMatch(const Client* c1, const Client* c2, bool act void Client::readTransient() { TRANSIENCY_CHECK(this); - Window new_transient_for_id; - if (XGetTransientForHint(display(), window(), &new_transient_for_id)) { - original_transient_for_id = new_transient_for_id; + Xcb::TransientFor transientFor(window()); + xcb_window_t new_transient_for_id = XCB_WINDOW_NONE; + if (transientFor.getTransientFor(&new_transient_for_id)) { + m_originalTransientForId = new_transient_for_id; new_transient_for_id = verifyTransientFor(new_transient_for_id, true); } else { - original_transient_for_id = None; - new_transient_for_id = verifyTransientFor(None, false); + m_originalTransientForId = XCB_WINDOW_NONE; + new_transient_for_id = verifyTransientFor(XCB_WINDOW_NONE, false); } setTransient(new_transient_for_id); } -void Client::setTransient(Window new_transient_for_id) +void Client::setTransient(xcb_window_t new_transient_for_id) { TRANSIENCY_CHECK(this); - if (new_transient_for_id != transient_for_id) { + if (new_transient_for_id != m_transientForId) { removeFromMainClients(); transient_for = NULL; - transient_for_id = new_transient_for_id; - if (transient_for_id != None && !groupTransient()) { - transient_for = workspace()->findClient(WindowMatchPredicate(transient_for_id)); + m_transientForId = new_transient_for_id; + if (m_transientForId != XCB_WINDOW_NONE && !groupTransient()) { + transient_for = workspace()->findClient(WindowMatchPredicate(m_transientForId)); assert(transient_for != NULL); // verifyTransient() had to check this transient_for->addTransient(this); } // checkGroup() will check 'check_active_modal' @@ -755,18 +756,18 @@ void Client::checkGroupTransients() /*! Check that the window is not transient for itself, and similar nonsense. */ -Window Client::verifyTransientFor(Window new_transient_for, bool defined) +xcb_window_t Client::verifyTransientFor(xcb_window_t new_transient_for, bool set) { - Window new_property_value = new_transient_for; + xcb_window_t new_property_value = new_transient_for; // make sure splashscreens are shown above all their app's windows, even though // they're in Normal layer - if (isSplash() && new_transient_for == None) + if (isSplash() && new_transient_for == XCB_WINDOW_NONE) new_transient_for = rootWindow(); - if (new_transient_for == None) { - if (defined) // sometimes WM_TRANSIENT_FOR is set to None, instead of root window + if (new_transient_for == XCB_WINDOW_NONE) { + if (set) // sometimes WM_TRANSIENT_FOR is set to None, instead of root window new_property_value = new_transient_for = rootWindow(); else - return None; + return XCB_WINDOW_NONE; } if (new_transient_for == window()) { // pointing to self // also fix the property itself @@ -776,19 +777,15 @@ Window Client::verifyTransientFor(Window new_transient_for, bool defined) // The transient_for window may be embedded in another application, // so kwin cannot see it. Try to find the managed client for the // window and fix the transient_for property if possible. - WId before_search = new_transient_for; - while (new_transient_for != None + xcb_window_t before_search = new_transient_for; + while (new_transient_for != XCB_WINDOW_NONE && new_transient_for != rootWindow() && !workspace()->findClient(WindowMatchPredicate(new_transient_for))) { - Window root_return, parent_return; - Window* wins = NULL; - unsigned int nwins; - int r = XQueryTree(display(), new_transient_for, &root_return, &parent_return, &wins, &nwins); - if (wins) - XFree((void *) wins); - if (r == 0) + Xcb::Tree tree(new_transient_for); + if (tree.isNull()) { break; - new_transient_for = parent_return; + } + new_transient_for = tree->parent; } if (Client* new_transient_for_client = workspace()->findClient(WindowMatchPredicate(new_transient_for))) { if (new_transient_for != before_search) { @@ -802,12 +799,12 @@ Window Client::verifyTransientFor(Window new_transient_for, bool defined) // group transients cannot cause loops, because they're considered transient only for non-transient // windows in the group int count = 20; - Window loop_pos = new_transient_for; - while (loop_pos != None && loop_pos != rootWindow()) { + xcb_window_t loop_pos = new_transient_for; + while (loop_pos != XCB_WINDOW_NONE && loop_pos != rootWindow()) { Client* pos = workspace()->findClient(WindowMatchPredicate(loop_pos)); if (pos == NULL) break; - loop_pos = pos->transient_for_id; + loop_pos = pos->m_transientForId; if (--count == 0 || pos == this) { kWarning(1216) << "Client " << this << " caused WM_TRANSIENT_FOR loop." ; new_transient_for = rootWindow(); @@ -818,8 +815,8 @@ Window Client::verifyTransientFor(Window new_transient_for, bool defined) // it's transient for a specific window, but that window is not mapped new_transient_for = rootWindow(); } - if (new_property_value != original_transient_for_id) - XSetTransientForHint(display(), window(), new_property_value); + if (new_property_value != m_originalTransientForId) + xcb_icccm_set_wm_transient_for(connection(), window(), new_property_value); return new_transient_for; } @@ -849,18 +846,18 @@ void Client::removeTransient(Client* cl) // cl is transient for this, but this is going away // make cl group transient if (cl->transientFor() == this) { - cl->transient_for_id = None; + cl->m_transientForId = XCB_WINDOW_NONE; cl->transient_for = NULL; // SELI // SELI cl->setTransient( rootWindow()); - cl->setTransient(None); + cl->setTransient(XCB_WINDOW_NONE); } } // A new window has been mapped. Check if it's not a mainwindow for this already existing window. -void Client::checkTransient(Window w) +void Client::checkTransient(xcb_window_t w) { TRANSIENCY_CHECK(this); - if (original_transient_for_id != w) + if (m_originalTransientForId != w) return; w = verifyTransientFor(w, true); setTransient(w); diff --git a/xcbutils.h b/xcbutils.h index b09a126b24..09f8e8dc8d 100644 --- a/xcbutils.h +++ b/xcbutils.h @@ -29,6 +29,7 @@ along with this program. If not, see . #include #include +#include namespace KWin { @@ -206,6 +207,27 @@ public: } }; +class TransientFor : public Wrapper +{ +public: + explicit TransientFor(WindowId window) : Wrapper(window) {} + + /** + * @brief Fill given window pointer with the WM_TRANSIENT_FOR property of a window. + * @param prop WM_TRANSIENT_FOR property value. + * @returns @c true on success, @c false otherwise + **/ + inline bool getTransientFor(WindowId *prop) { + if (isNull()) { + return false; + } + if (xcb_icccm_get_wm_transient_for_from_reply(prop, const_cast(data()))) { + return true; + } + return false; + } +}; + class ExtensionData { public: