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.icc-effect-5.14.5
parent
9d1fb072d4
commit
5afe5f810e
|
@ -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)
|
||||
|
|
16
client.h
16
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
|
||||
|
|
67
group.cpp
67
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);
|
||||
|
|
22
xcbutils.h
22
xcbutils.h
|
@ -29,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/composite.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue