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.
remotes/origin/Plasma/5.0
Martin Gräßlin 13 years ago
parent 9d1fb072d4
commit 5afe5f810e
  1. 4
      client.cpp
  2. 16
      client.h
  3. 67
      group.cpp
  4. 22
      xcbutils.h

@ -99,8 +99,8 @@ Client::Client()
, move_resize_has_keyboard_grab(false) , move_resize_has_keyboard_grab(false)
, m_managed(false) , m_managed(false)
, transient_for (NULL) , transient_for (NULL)
, transient_for_id(None) , m_transientForId(XCB_WINDOW_NONE)
, original_transient_for_id(None) , m_originalTransientForId(XCB_WINDOW_NONE)
, shade_below(NULL) , shade_below(NULL)
, skip_switcher(false) , skip_switcher(false)
, blocks_compositing(false) , blocks_compositing(false)

@ -283,7 +283,7 @@ public:
ClientList allMainClients() const; // Call once before loop , is indirect ClientList allMainClients() const; // Call once before loop , is indirect
bool hasTransient(const Client* c, bool indirect) const; bool hasTransient(const Client* c, bool indirect) const;
const ClientList& transients() const; // Is not indirect const ClientList& transients() const; // Is not indirect
void checkTransient(Window w); void checkTransient(xcb_window_t w);
Client* findModal(bool allow_itself = false); Client* findModal(bool allow_itself = false);
const Group* group() const; const Group* group() const;
Group* group(); Group* group();
@ -869,16 +869,16 @@ private:
int quick_tile_mode; int quick_tile_mode;
void readTransient(); 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 addTransient(Client* cl);
void removeTransient(Client* cl); void removeTransient(Client* cl);
void removeFromMainClients(); void removeFromMainClients();
void cleanGrouping(); void cleanGrouping();
void checkGroupTransients(); void checkGroupTransients();
void setTransient(Window new_transient_for_id); void setTransient(xcb_window_t new_transient_for_id);
Client* transient_for; Client* transient_for;
Window transient_for_id; xcb_window_t m_transientForId;
Window original_transient_for_id; xcb_window_t m_originalTransientForId;
ClientList transients_list; // SELI TODO: Make this ordered in stacking order? ClientList transients_list; // SELI TODO: Make this ordered in stacking order?
ShadeMode shade_mode; ShadeMode shade_mode;
Client *shade_below; Client *shade_below;
@ -1033,19 +1033,19 @@ inline Client* Client::transientFor()
inline bool Client::groupTransient() const 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, // Needed because verifyTransientFor() may set transient_for_id to root window,
// if the original value has a problem (window doesn't exist, etc.) // if the original value has a problem (window doesn't exist, etc.)
inline bool Client::wasOriginallyGroupTransient() const inline bool Client::wasOriginallyGroupTransient() const
{ {
return original_transient_for_id == rootWindow(); return m_originalTransientForId == rootWindow();
} }
inline bool Client::isTransient() const inline bool Client::isTransient() const
{ {
return transient_for_id != None; return m_transientForId != XCB_WINDOW_NONE;
} }
inline const ClientList& Client::transients() const inline const ClientList& Client::transients() const

@ -588,26 +588,27 @@ bool Client::sameAppWindowRoleMatch(const Client* c1, const Client* c2, bool act
void Client::readTransient() void Client::readTransient()
{ {
TRANSIENCY_CHECK(this); TRANSIENCY_CHECK(this);
Window new_transient_for_id; Xcb::TransientFor transientFor(window());
if (XGetTransientForHint(display(), window(), &new_transient_for_id)) { xcb_window_t new_transient_for_id = XCB_WINDOW_NONE;
original_transient_for_id = new_transient_for_id; if (transientFor.getTransientFor(&new_transient_for_id)) {
m_originalTransientForId = new_transient_for_id;
new_transient_for_id = verifyTransientFor(new_transient_for_id, true); new_transient_for_id = verifyTransientFor(new_transient_for_id, true);
} else { } else {
original_transient_for_id = None; m_originalTransientForId = XCB_WINDOW_NONE;
new_transient_for_id = verifyTransientFor(None, false); new_transient_for_id = verifyTransientFor(XCB_WINDOW_NONE, false);
} }
setTransient(new_transient_for_id); 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); TRANSIENCY_CHECK(this);
if (new_transient_for_id != transient_for_id) { if (new_transient_for_id != m_transientForId) {
removeFromMainClients(); removeFromMainClients();
transient_for = NULL; transient_for = NULL;
transient_for_id = new_transient_for_id; m_transientForId = new_transient_for_id;
if (transient_for_id != None && !groupTransient()) { if (m_transientForId != XCB_WINDOW_NONE && !groupTransient()) {
transient_for = workspace()->findClient(WindowMatchPredicate(transient_for_id)); transient_for = workspace()->findClient(WindowMatchPredicate(m_transientForId));
assert(transient_for != NULL); // verifyTransient() had to check this assert(transient_for != NULL); // verifyTransient() had to check this
transient_for->addTransient(this); transient_for->addTransient(this);
} // checkGroup() will check 'check_active_modal' } // 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. 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 // make sure splashscreens are shown above all their app's windows, even though
// they're in Normal layer // they're in Normal layer
if (isSplash() && new_transient_for == None) if (isSplash() && new_transient_for == XCB_WINDOW_NONE)
new_transient_for = rootWindow(); new_transient_for = rootWindow();
if (new_transient_for == None) { if (new_transient_for == XCB_WINDOW_NONE) {
if (defined) // sometimes WM_TRANSIENT_FOR is set to None, instead of root window if (set) // sometimes WM_TRANSIENT_FOR is set to None, instead of root window
new_property_value = new_transient_for = rootWindow(); new_property_value = new_transient_for = rootWindow();
else else
return None; return XCB_WINDOW_NONE;
} }
if (new_transient_for == window()) { // pointing to self if (new_transient_for == window()) { // pointing to self
// also fix the property itself // 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, // The transient_for window may be embedded in another application,
// so kwin cannot see it. Try to find the managed client for the // so kwin cannot see it. Try to find the managed client for the
// window and fix the transient_for property if possible. // window and fix the transient_for property if possible.
WId before_search = new_transient_for; xcb_window_t before_search = new_transient_for;
while (new_transient_for != None while (new_transient_for != XCB_WINDOW_NONE
&& new_transient_for != rootWindow() && new_transient_for != rootWindow()
&& !workspace()->findClient(WindowMatchPredicate(new_transient_for))) { && !workspace()->findClient(WindowMatchPredicate(new_transient_for))) {
Window root_return, parent_return; Xcb::Tree tree(new_transient_for);
Window* wins = NULL; if (tree.isNull()) {
unsigned int nwins;
int r = XQueryTree(display(), new_transient_for, &root_return, &parent_return, &wins, &nwins);
if (wins)
XFree((void *) wins);
if (r == 0)
break; break;
new_transient_for = parent_return; }
new_transient_for = tree->parent;
} }
if (Client* new_transient_for_client = workspace()->findClient(WindowMatchPredicate(new_transient_for))) { if (Client* new_transient_for_client = workspace()->findClient(WindowMatchPredicate(new_transient_for))) {
if (new_transient_for != before_search) { 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 // group transients cannot cause loops, because they're considered transient only for non-transient
// windows in the group // windows in the group
int count = 20; int count = 20;
Window loop_pos = new_transient_for; xcb_window_t loop_pos = new_transient_for;
while (loop_pos != None && loop_pos != rootWindow()) { while (loop_pos != XCB_WINDOW_NONE && loop_pos != rootWindow()) {
Client* pos = workspace()->findClient(WindowMatchPredicate(loop_pos)); Client* pos = workspace()->findClient(WindowMatchPredicate(loop_pos));
if (pos == NULL) if (pos == NULL)
break; break;
loop_pos = pos->transient_for_id; loop_pos = pos->m_transientForId;
if (--count == 0 || pos == this) { if (--count == 0 || pos == this) {
kWarning(1216) << "Client " << this << " caused WM_TRANSIENT_FOR loop." ; kWarning(1216) << "Client " << this << " caused WM_TRANSIENT_FOR loop." ;
new_transient_for = rootWindow(); 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 // it's transient for a specific window, but that window is not mapped
new_transient_for = rootWindow(); new_transient_for = rootWindow();
} }
if (new_property_value != original_transient_for_id) if (new_property_value != m_originalTransientForId)
XSetTransientForHint(display(), window(), new_property_value); xcb_icccm_set_wm_transient_for(connection(), window(), new_property_value);
return new_transient_for; return new_transient_for;
} }
@ -849,18 +846,18 @@ void Client::removeTransient(Client* cl)
// cl is transient for this, but this is going away // cl is transient for this, but this is going away
// make cl group transient // make cl group transient
if (cl->transientFor() == this) { if (cl->transientFor() == this) {
cl->transient_for_id = None; cl->m_transientForId = XCB_WINDOW_NONE;
cl->transient_for = NULL; // SELI cl->transient_for = NULL; // SELI
// SELI cl->setTransient( rootWindow()); // 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. // 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); TRANSIENCY_CHECK(this);
if (original_transient_for_id != w) if (m_originalTransientForId != w)
return; return;
w = verifyTransientFor(w, true); w = verifyTransientFor(w, true);
setTransient(w); setTransient(w);

@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/composite.h> #include <xcb/composite.h>
#include <xcb/xcb_icccm.h>
namespace KWin { namespace KWin {
@ -206,6 +207,27 @@ public:
} }
}; };
class TransientFor : public Wrapper<xcb_get_property_reply_t, xcb_get_property_cookie_t, &xcb_get_property_reply, &xcb_icccm_get_wm_transient_for_unchecked>
{
public:
explicit TransientFor(WindowId window) : Wrapper<xcb_get_property_reply_t, xcb_get_property_cookie_t, &xcb_get_property_reply, &xcb_icccm_get_wm_transient_for_unchecked>(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<xcb_get_property_reply_t*>(data()))) {
return true;
}
return false;
}
};
class ExtensionData class ExtensionData
{ {
public: public:

Loading…
Cancel
Save