Stacking Order becomes a list of Toplevel Windows
The common usage of stacking order is to loop through the list and find a specific Client. All these usages still need to find a Client. For that the loops are adjusted to first cast the Toplevel into a Client and continue if the current item is no Client. At the moment all entries in the stacking order should still be Clients as the Deleted are not yet added.
This commit is contained in:
parent
c175e75939
commit
f0c6f06241
12 changed files with 235 additions and 144 deletions
|
@ -406,9 +406,12 @@ static inline bool isUsableFocusCandidate(Client *c, Client *prev, bool respectS
|
|||
|
||||
Client *Workspace::clientUnderMouse(int screen) const
|
||||
{
|
||||
QList<Client*>::const_iterator it = stackingOrder().constEnd();
|
||||
ToplevelList::const_iterator it = stackingOrder().constEnd();
|
||||
while (it != stackingOrder().constBegin()) {
|
||||
Client *client = *(--it);
|
||||
Client *client = qobject_cast<Client*>(*(--it));
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// rule out clients which are not really visible.
|
||||
// the screen test is rather superflous for xrandr & twinview since the geometry would differ -> TODO: might be dropped
|
||||
|
|
18
bridge.cpp
18
bridge.cpp
|
@ -172,25 +172,29 @@ Qt::WFlags Bridge::initialWFlags() const
|
|||
QRegion Bridge::unobscuredRegion(const QRegion& r) const
|
||||
{
|
||||
QRegion reg(r);
|
||||
const ClientList stacking_order = c->workspace()->stackingOrder();
|
||||
const ToplevelList stacking_order = c->workspace()->stackingOrder();
|
||||
int pos = stacking_order.indexOf(c);
|
||||
++pos;
|
||||
for (; pos < stacking_order.count(); ++pos) {
|
||||
if (!stacking_order[pos]->isShown(true))
|
||||
Client *client = qobject_cast<Client*>(stacking_order[pos]);
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
if (!client->isShown(true))
|
||||
continue; // these don't obscure the window
|
||||
if (c->isOnAllDesktops()) {
|
||||
if (!stacking_order[ pos ]->isOnCurrentDesktop())
|
||||
if (!client->isOnCurrentDesktop())
|
||||
continue;
|
||||
} else {
|
||||
if (!stacking_order[ pos ]->isOnDesktop(c->desktop()))
|
||||
if (!client->isOnDesktop(c->desktop()))
|
||||
continue;
|
||||
}
|
||||
/* the clients all have their mask-regions in local coords
|
||||
so we have to translate them to a shared coord system
|
||||
we choose ours */
|
||||
int dx = stacking_order[ pos ]->x() - c->x();
|
||||
int dy = stacking_order[ pos ]->y() - c->y();
|
||||
QRegion creg = stacking_order[ pos ]->mask();
|
||||
int dx = client->x() - c->x();
|
||||
int dy = client->y() - c->y();
|
||||
QRegion creg = client->mask();
|
||||
creg.translate(dx, dy);
|
||||
reg -= creg;
|
||||
if (reg.isEmpty()) {
|
||||
|
|
11
client.cpp
11
client.cpp
|
@ -1115,9 +1115,14 @@ void Client::setShade(ShadeMode mode)
|
|||
if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(input))
|
||||
setActive(true);
|
||||
if (shade_mode == ShadeHover) {
|
||||
ClientList order = workspace()->stackingOrder();
|
||||
int idx = order.indexOf(this) + 1; // this is likely related to the index parameter?!
|
||||
shade_below = (idx < order.count()) ? order.at(idx) : NULL;
|
||||
ToplevelList order = workspace()->stackingOrder();
|
||||
// this is likely related to the index parameter?!
|
||||
for (int idx = order.indexOf(this) + 1; idx < order.count(); ++idx) {
|
||||
shade_below = qobject_cast<Client*>(order.at(idx));
|
||||
if (shade_below) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shade_below && shade_below->isNormalWindow())
|
||||
workspace()->raiseClient(this);
|
||||
else
|
||||
|
|
|
@ -772,8 +772,10 @@ void Workspace::cascadeDesktop()
|
|||
Q_ASSERT(block_stacking_updates == 0);
|
||||
initPositioning->reinitCascading(currentDesktop());
|
||||
QRect area = clientArea(PlacementArea, QPoint(0, 0), currentDesktop());
|
||||
foreach (Client * client, stackingOrder()) {
|
||||
if ((!client->isOnDesktop(currentDesktop())) ||
|
||||
foreach (Toplevel *toplevel, stackingOrder()) {
|
||||
Client *client = qobject_cast<Client*>(toplevel);
|
||||
if (!client ||
|
||||
(!client->isOnDesktop(currentDesktop())) ||
|
||||
(client->isMinimized()) ||
|
||||
(client->isOnAllDesktops()) ||
|
||||
(!client->isMovable()))
|
||||
|
|
105
layers.cpp
105
layers.cpp
|
@ -115,13 +115,7 @@ void Workspace::updateStackingOrder(bool propagate_new_clients)
|
|||
blocked_propagating_new_clients = true;
|
||||
return;
|
||||
}
|
||||
ToplevelList constrainedOrder = constrainedStackingOrder();
|
||||
ClientList new_stacking_order;
|
||||
foreach (Toplevel *t, constrainedOrder) {
|
||||
if (Client *c = qobject_cast<Client*>(t)) {
|
||||
new_stacking_order << c;
|
||||
}
|
||||
}
|
||||
ToplevelList new_stacking_order = constrainedStackingOrder();
|
||||
bool changed = (new_stacking_order != stacking_order || force_restacking);
|
||||
force_restacking = false;
|
||||
stacking_order = new_stacking_order;
|
||||
|
@ -169,8 +163,8 @@ void Workspace::propagateClients(bool propagate_new_clients)
|
|||
}
|
||||
#endif
|
||||
for (int i = stacking_order.size() - 1; i >= 0; i--) {
|
||||
Client *client = stacking_order.at(i);
|
||||
if (client->hiddenPreview()) {
|
||||
Client *client = qobject_cast<Client*>(stacking_order.at(i));
|
||||
if (!client || client->hiddenPreview()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -185,9 +179,10 @@ void Workspace::propagateClients(bool propagate_new_clients)
|
|||
// (as far as pure X stacking order is concerned), in order to avoid having
|
||||
// these windows that should be unmapped to interfere with other windows
|
||||
for (int i = stacking_order.size() - 1; i >= 0; i--) {
|
||||
if (!stacking_order.at(i)->hiddenPreview())
|
||||
Client *client = qobject_cast<Client*>(stacking_order.at(i));
|
||||
if (!client || !client->hiddenPreview())
|
||||
continue;
|
||||
newWindowStack << (Window*)stacking_order.at(i)->frameId();
|
||||
newWindowStack << (Window*)client->frameId();
|
||||
}
|
||||
// TODO isn't it too inefficient to restack always all clients?
|
||||
// TODO don't restack not visible windows?
|
||||
|
@ -208,7 +203,7 @@ void Workspace::propagateClients(bool propagate_new_clients)
|
|||
|
||||
cl = new Window[ stacking_order.count()];
|
||||
pos = 0;
|
||||
for (ClientList::ConstIterator it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it)
|
||||
for (ToplevelList::ConstIterator it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it)
|
||||
cl[pos++] = (*it)->window();
|
||||
rootInfo->setClientListStacking(cl, pos);
|
||||
delete [] cl;
|
||||
|
@ -227,7 +222,7 @@ void Workspace::propagateClients(bool propagate_new_clients)
|
|||
Client* Workspace::topClientOnDesktop(int desktop, int screen, bool unconstrained, bool only_normal) const
|
||||
{
|
||||
// TODO Q_ASSERT( block_stacking_updates == 0 );
|
||||
ClientList list;
|
||||
ToplevelList list;
|
||||
if (!unconstrained)
|
||||
list = stacking_order;
|
||||
else
|
||||
|
@ -235,13 +230,17 @@ Client* Workspace::topClientOnDesktop(int desktop, int screen, bool unconstraine
|
|||
for (int i = list.size() - 1;
|
||||
i >= 0;
|
||||
--i) {
|
||||
if (list.at(i)->isOnDesktop(desktop) && list.at(i)->isShown(false) && list.at(i)->isOnCurrentActivity()) {
|
||||
if (screen != -1 && list.at(i)->screen() != screen)
|
||||
Client *c = qobject_cast<Client*>(list.at(i));
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->isOnDesktop(desktop) && c->isShown(false) && c->isOnCurrentActivity()) {
|
||||
if (screen != -1 && c->screen() != screen)
|
||||
continue;
|
||||
if (!only_normal)
|
||||
return list.at(i);
|
||||
if (list.at(i)->wantsTabFocus() && !list.at(i)->isSpecialWindow())
|
||||
return list.at(i);
|
||||
return c;
|
||||
if (c->wantsTabFocus() && !c->isSpecialWindow())
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -252,16 +251,18 @@ Client* Workspace::findDesktop(bool topmost, int desktop) const
|
|||
// TODO Q_ASSERT( block_stacking_updates == 0 );
|
||||
if (topmost) {
|
||||
for (int i = stacking_order.size() - 1; i >= 0; i--) {
|
||||
if (stacking_order.at(i)->isOnDesktop(desktop) && stacking_order.at(i)->isDesktop()
|
||||
&& stacking_order.at(i)->isShown(true))
|
||||
return stacking_order.at(i);
|
||||
}
|
||||
} else { // bottom-most
|
||||
foreach (Client * c, stacking_order) {
|
||||
if (c->isOnDesktop(desktop) && c->isDesktop()
|
||||
Client *c = qobject_cast<Client*>(stacking_order.at(i));
|
||||
if (c && c->isOnDesktop(desktop) && c->isDesktop()
|
||||
&& c->isShown(true))
|
||||
return c;
|
||||
}
|
||||
} else { // bottom-most
|
||||
foreach (Toplevel * c, stacking_order) {
|
||||
Client *client = qobject_cast<Client*>(c);
|
||||
if (client && c->isOnDesktop(desktop) && c->isDesktop()
|
||||
&& client->isShown(true))
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -323,10 +324,10 @@ void Workspace::lowerClientWithinApplication(Client* c)
|
|||
unconstrained_stacking_order.removeAll(c);
|
||||
bool lowered = false;
|
||||
// first try to put it below the bottom-most window of the application
|
||||
for (ClientList::Iterator it = unconstrained_stacking_order.begin();
|
||||
for (ToplevelList::Iterator it = unconstrained_stacking_order.begin();
|
||||
it != unconstrained_stacking_order.end();
|
||||
++it)
|
||||
if (Client::belongToSameApplication(*it, c)) {
|
||||
if (Client::belongToSameApplication(qobject_cast<Client*>(*it), c)) {
|
||||
unconstrained_stacking_order.insert(it, c);
|
||||
lowered = true;
|
||||
break;
|
||||
|
@ -375,7 +376,10 @@ void Workspace::raiseClientWithinApplication(Client* c)
|
|||
|
||||
// first try to put it above the top-most window of the application
|
||||
for (int i = unconstrained_stacking_order.size() - 1; i > -1 ; --i) {
|
||||
Client *other = unconstrained_stacking_order.at(i);
|
||||
Client *other = qobject_cast<Client*>(unconstrained_stacking_order.at(i));
|
||||
if (!other) {
|
||||
continue;
|
||||
}
|
||||
if (other == c) // don't lower it just because it asked to be raised
|
||||
return;
|
||||
if (Client::belongToSameApplication(other, c)) {
|
||||
|
@ -416,7 +420,7 @@ void Workspace::restack(Client* c, Client* under)
|
|||
// put in the stacking order below _all_ windows belonging to the active application
|
||||
Client *other = 0;
|
||||
for (int i = 0; i < unconstrained_stacking_order.size(); ++i) { // TODO ignore topmenus?
|
||||
if (Client::belongToSameApplication(under, (other = unconstrained_stacking_order.at(i)))) {
|
||||
if (Client::belongToSameApplication(under, (other = qobject_cast<Client*>(unconstrained_stacking_order.at(i))))) {
|
||||
under = (c == other) ? 0 : other;
|
||||
break;
|
||||
}
|
||||
|
@ -480,11 +484,14 @@ void Workspace::restoreSessionStackingOrder(Client* c)
|
|||
return;
|
||||
StackingUpdatesBlocker blocker(this);
|
||||
unconstrained_stacking_order.removeAll(c);
|
||||
ClientList::Iterator best_pos = unconstrained_stacking_order.end();
|
||||
for (ClientList::Iterator it = unconstrained_stacking_order.begin(); // from bottom
|
||||
for (ToplevelList::Iterator it = unconstrained_stacking_order.begin(); // from bottom
|
||||
it != unconstrained_stacking_order.end();
|
||||
++it) {
|
||||
if ((*it)->sessionStackingOrder() > c->sessionStackingOrder()) {
|
||||
Client *current = qobject_cast<Client*>(*it);
|
||||
if (!current) {
|
||||
continue;
|
||||
}
|
||||
if (current->sessionStackingOrder() > c->sessionStackingOrder()) {
|
||||
unconstrained_stacking_order.insert(it, c);
|
||||
return;
|
||||
}
|
||||
|
@ -522,12 +529,13 @@ ToplevelList Workspace::constrainedStackingOrder()
|
|||
#endif
|
||||
// build the order from layers
|
||||
QVector< QMap<Group*, Layer> > minimum_layer(numScreens());
|
||||
for (ClientList::ConstIterator it = unconstrained_stacking_order.constBegin(),
|
||||
for (ToplevelList::ConstIterator it = unconstrained_stacking_order.constBegin(),
|
||||
end = unconstrained_stacking_order.constEnd(); it != end; ++it) {
|
||||
Layer l = (*it)->layer();
|
||||
|
||||
const int screen = (*it)->screen();
|
||||
QMap< Group*, Layer >::iterator mLayer = minimum_layer[screen].find((*it)->group());
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
QMap< Group*, Layer >::iterator mLayer = minimum_layer[screen].find(c ? c->group() : NULL);
|
||||
if (mLayer != minimum_layer[screen].end()) {
|
||||
// If a window is raised above some other window in the same window group
|
||||
// which is in the ActiveLayer (i.e. it's fulscreened), make sure it stays
|
||||
|
@ -535,8 +543,8 @@ ToplevelList Workspace::constrainedStackingOrder()
|
|||
if (*mLayer == ActiveLayer && (l == NormalLayer || l == AboveLayer))
|
||||
l = ActiveLayer;
|
||||
*mLayer = l;
|
||||
} else {
|
||||
minimum_layer[screen].insertMulti((*it)->group(), l);
|
||||
} else if (c) {
|
||||
minimum_layer[screen].insertMulti(c->group(), l);
|
||||
}
|
||||
layer[ l ].append(*it);
|
||||
}
|
||||
|
@ -644,11 +652,16 @@ ClientList Workspace::ensureStackingOrder(const ClientList& list) const
|
|||
return list;
|
||||
// TODO is this worth optimizing?
|
||||
ClientList result = list;
|
||||
for (ClientList::ConstIterator it = stacking_order.constBegin();
|
||||
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
|
||||
it != stacking_order.constEnd();
|
||||
++it)
|
||||
if (result.removeAll(*it) != 0)
|
||||
result.append(*it);
|
||||
++it) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (result.removeAll(c) != 0)
|
||||
result.append(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -684,7 +697,7 @@ ToplevelList Workspace::xStackingOrder() const
|
|||
unsigned int count = 0;
|
||||
XQueryTree(display(), rootWindow(), &dummy, &dummy, &windows, &count);
|
||||
// use our own stacking order, not the X one, as they may differ
|
||||
foreach (Client * c, stacking_order)
|
||||
foreach (Toplevel * c, stacking_order)
|
||||
x_stacking.append(c);
|
||||
for (unsigned int i = 0;
|
||||
i < count;
|
||||
|
@ -692,6 +705,7 @@ ToplevelList Workspace::xStackingOrder() const
|
|||
if (Unmanaged* c = findUnmanaged(WindowMatchPredicate(windows[ i ])))
|
||||
x_stacking.append(c);
|
||||
}
|
||||
// TODO: remove after stacking_order contains Deleted
|
||||
foreach (Deleted * c, deleted)
|
||||
x_stacking.append(c);
|
||||
if (windows != NULL)
|
||||
|
@ -713,7 +727,7 @@ void Client::restackWindow(Window above, int detail, NET::RequestSource src, Tim
|
|||
workspace()->raiseOrLowerClient(this);
|
||||
return;
|
||||
}
|
||||
ClientList::const_iterator it = workspace()->stackingOrder().constBegin(),
|
||||
ToplevelList::const_iterator it = workspace()->stackingOrder().constBegin(),
|
||||
end = workspace()->stackingOrder().constEnd();
|
||||
while (it != end) {
|
||||
if (*it == this) {
|
||||
|
@ -743,7 +757,7 @@ void Client::restackWindow(Window above, int detail, NET::RequestSource src, Tim
|
|||
other = workspace()->findClient(WindowMatchPredicate(above));
|
||||
|
||||
if (other && detail == Above) {
|
||||
ClientList::const_iterator it = workspace()->stackingOrder().constEnd(),
|
||||
ToplevelList::const_iterator it = workspace()->stackingOrder().constEnd(),
|
||||
begin = workspace()->stackingOrder().constBegin();
|
||||
while (--it != begin) {
|
||||
if (*it == this)
|
||||
|
@ -754,8 +768,9 @@ void Client::restackWindow(Window above, int detail, NET::RequestSource src, Tim
|
|||
src = NET::FromTool; // force
|
||||
break;
|
||||
}
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
|
||||
if (!( (*it)->isNormalWindow() && (*it)->isShown(true) &&
|
||||
if (!( (*it)->isNormalWindow() && c->isShown(true) &&
|
||||
(*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnScreen(screen()) ))
|
||||
continue; // irrelevant clients
|
||||
|
||||
|
@ -764,7 +779,7 @@ void Client::restackWindow(Window above, int detail, NET::RequestSource src, Tim
|
|||
}
|
||||
|
||||
if (it != begin && (*(it - 1) == other))
|
||||
other = const_cast<Client*>(*it);
|
||||
other = qobject_cast<Client*>(*it);
|
||||
else
|
||||
other = 0;
|
||||
}
|
||||
|
|
|
@ -181,22 +181,26 @@ void Placement::placeSmart(Client* c, const QRect& area, Policy /*next*/)
|
|||
|
||||
cxl = x; cxr = x + cw;
|
||||
cyt = y; cyb = y + ch;
|
||||
ClientList::ConstIterator l;
|
||||
ToplevelList::ConstIterator l;
|
||||
for (l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l) {
|
||||
if ((*l)->isOnDesktop(desktop) &&
|
||||
(*l)->isShown(false) && (*l) != c) {
|
||||
Client *client = qobject_cast<Client*>(*l);
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
if (client->isOnDesktop(desktop) &&
|
||||
client->isShown(false) && client != c) {
|
||||
|
||||
xl = (*l)->x(); yt = (*l)->y();
|
||||
xr = xl + (*l)->width(); yb = yt + (*l)->height();
|
||||
xl = client->x(); yt = client->y();
|
||||
xr = xl + client->width(); yb = yt + client->height();
|
||||
|
||||
//if windows overlap, calc the overall overlapping
|
||||
if ((cxl < xr) && (cxr > xl) &&
|
||||
(cyt < yb) && (cyb > yt)) {
|
||||
xl = qMax(cxl, xl); xr = qMin(cxr, xr);
|
||||
yt = qMax(cyt, yt); yb = qMin(cyb, yb);
|
||||
if ((*l)->keepAbove())
|
||||
if (client->keepAbove())
|
||||
overlap += 16 * (xr - xl) * (yb - yt);
|
||||
else if ((*l)->keepBelow() && !(*l)->isDock()) // ignore KeepBelow windows
|
||||
else if (client->keepBelow() && !client->isDock()) // ignore KeepBelow windows
|
||||
overlap += 0; // for placement (see Client::belongsToLayer() for Dock)
|
||||
else
|
||||
overlap += (xr - xl) * (yb - yt);
|
||||
|
@ -230,14 +234,18 @@ void Placement::placeSmart(Client* c, const QRect& area, Policy /*next*/)
|
|||
if (possible - cw > x) possible -= cw;
|
||||
|
||||
// compare to the position of each client on the same desk
|
||||
ClientList::ConstIterator l;
|
||||
ToplevelList::ConstIterator l;
|
||||
for (l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l) {
|
||||
Client *client = qobject_cast<Client*>(*l);
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*l)->isOnDesktop(desktop) &&
|
||||
(*l)->isShown(false) && (*l) != c) {
|
||||
if (client->isOnDesktop(desktop) &&
|
||||
client->isShown(false) && client != c) {
|
||||
|
||||
xl = (*l)->x(); yt = (*l)->y();
|
||||
xr = xl + (*l)->width(); yb = yt + (*l)->height();
|
||||
xl = client->x(); yt = client->y();
|
||||
xr = xl + client->width(); yb = yt + client->height();
|
||||
|
||||
// if not enough room above or under the current tested client
|
||||
// determine the first non-overlapped x position
|
||||
|
@ -261,13 +269,17 @@ void Placement::placeSmart(Client* c, const QRect& area, Policy /*next*/)
|
|||
if (possible - ch > y) possible -= ch;
|
||||
|
||||
//test the position of each window on the desk
|
||||
ClientList::ConstIterator l;
|
||||
ToplevelList::ConstIterator l;
|
||||
for (l = m_WorkspacePtr->stackingOrder().constBegin(); l != m_WorkspacePtr->stackingOrder().constEnd() ; ++l) {
|
||||
if ((*l)->isOnDesktop(desktop) &&
|
||||
(*l) != c && c->isShown(false)) {
|
||||
Client *client = qobject_cast<Client*>(*l);
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
if (client->isOnDesktop(desktop) &&
|
||||
client != c && c->isShown(false)) {
|
||||
|
||||
xl = (*l)->x(); yt = (*l)->y();
|
||||
xr = xl + (*l)->width(); yb = yt + (*l)->height();
|
||||
xl = client->x(); yt = client->y();
|
||||
xr = xl + client->width(); yb = yt + client->height();
|
||||
|
||||
// if not enough room to the left or right of the current tested client
|
||||
// determine the first non-overlapped y position
|
||||
|
|
|
@ -235,10 +235,12 @@ TabBoxClient* TabBoxHandlerImpl::clientToAddToList(TabBoxClient* client, int des
|
|||
|
||||
TabBoxClientList TabBoxHandlerImpl::stackingOrder() const
|
||||
{
|
||||
ClientList stacking = Workspace::self()->stackingOrder();
|
||||
ToplevelList stacking = Workspace::self()->stackingOrder();
|
||||
TabBoxClientList ret;
|
||||
foreach (const Client * client, stacking) {
|
||||
ret.append(client->tabBoxClient());
|
||||
foreach (Toplevel *toplevel, stacking) {
|
||||
if (Client *client = qobject_cast<Client*>(toplevel)) {
|
||||
ret.append(client->tabBoxClient());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -266,8 +268,9 @@ void TabBoxHandlerImpl::elevateClient(TabBoxClient *c, bool b) const
|
|||
|
||||
TabBoxClient* TabBoxHandlerImpl::desktopClient() const
|
||||
{
|
||||
foreach (const Client * client, Workspace::self()->stackingOrder()) {
|
||||
if (client->isDesktop() && client->isOnCurrentDesktop() && client->screen() == Workspace::self()->activeScreen()) {
|
||||
foreach (Toplevel *toplevel, Workspace::self()->stackingOrder()) {
|
||||
Client *client = qobject_cast<Client*>(toplevel);
|
||||
if (client && client->isDesktop() && client->isOnCurrentDesktop() && client->screen() == Workspace::self()->activeScreen()) {
|
||||
return client->tabBoxClient();
|
||||
}
|
||||
}
|
||||
|
@ -1110,8 +1113,8 @@ void TabBox::CDEWalkThroughWindows(bool forward)
|
|||
for (int i = Workspace::self()->stackingOrder().size() - 1;
|
||||
i >= 0 ;
|
||||
--i) {
|
||||
Client* it = Workspace::self()->stackingOrder().at(i);
|
||||
if (it->isOnCurrentActivity() && it->isOnCurrentDesktop() && !it->isSpecialWindow()
|
||||
Client* it = qobject_cast<Client*>(Workspace::self()->stackingOrder().at(i));
|
||||
if (it && it->isOnCurrentActivity() && it->isOnCurrentDesktop() && !it->isSpecialWindow()
|
||||
&& it->isShown(false) && it->wantsTabFocus()
|
||||
&& !it->keepAbove() && !it->keepBelow()) {
|
||||
c = it;
|
||||
|
|
|
@ -96,8 +96,10 @@ void Tiling::setEnabled(bool tiling)
|
|||
connect(m_workspace, SIGNAL(clientRemoved(KWin::Client*)), this, SLOT(removeTile(KWin::Client*)));
|
||||
connect(m_workspace, SIGNAL(clientActivated(KWin::Client*)), this, SLOT(notifyTilingWindowActivated(KWin::Client*)));
|
||||
m_tilingLayouts.resize(Workspace::self()->numberOfDesktops() + 1);
|
||||
foreach (Client * c, Workspace::self()->stackingOrder()) {
|
||||
createTile(c);
|
||||
foreach (Toplevel *t, Workspace::self()->stackingOrder()) {
|
||||
if (Client *c = qobject_cast<Client*>(t)) {
|
||||
createTile(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disconnect(m_workspace, SIGNAL(clientAdded(KWin::Client*)));
|
||||
|
|
|
@ -195,9 +195,11 @@ void TilingLayout::reconfigureTiling()
|
|||
if (tiles().length() > 0)
|
||||
arrange(layoutArea(tiles().first()));
|
||||
|
||||
foreach (Client * c, workspace()->stackingOrder()) {
|
||||
if (c->rules()->checkTilingOption(0) == 1)
|
||||
workspace()->tiling()->createTile(c);
|
||||
foreach (Toplevel * t, workspace()->stackingOrder()) {
|
||||
if (Client *c = qobject_cast<Client*>(t)) {
|
||||
if (c->rules()->checkTilingOption(0) == 1)
|
||||
workspace()->tiling()->createTile(c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -847,12 +847,13 @@ bool Client::performMouseCommand(Options::MouseCommand command, const QPoint &gl
|
|||
replay = isActive(); // for clickraise mode
|
||||
bool mustReplay = !rules()->checkAcceptFocus(input);
|
||||
if (mustReplay) {
|
||||
ClientList::const_iterator it = workspace()->stackingOrder().constEnd(),
|
||||
ToplevelList::const_iterator it = workspace()->stackingOrder().constEnd(),
|
||||
begin = workspace()->stackingOrder().constBegin();
|
||||
while (mustReplay && --it != begin && *it != this) {
|
||||
if (((*it)->keepAbove() && !keepAbove()) || (keepBelow() && !(*it)->keepBelow()))
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c || (c->keepAbove() && !keepAbove()) || (keepBelow() && !c->keepBelow()))
|
||||
continue; // can never raise above "it"
|
||||
mustReplay = !((*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->geometry().intersects(geometry()));
|
||||
mustReplay = !(c->isOnCurrentDesktop() && c->isOnCurrentActivity() && c->geometry().intersects(geometry()));
|
||||
}
|
||||
}
|
||||
workspace()->takeActivity(this, ActivityFocus | ActivityRaise, handled && replay);
|
||||
|
@ -1467,13 +1468,17 @@ void Workspace::switchWindow(Direction direction)
|
|||
QPoint curPos(c->pos().x() + c->geometry().width() / 2,
|
||||
c->pos().y() + c->geometry().height() / 2);
|
||||
|
||||
QList<Client *> clist = stackingOrder();
|
||||
for (QList<Client *>::Iterator i = clist.begin(); i != clist.end(); ++i) {
|
||||
if ((*i)->wantsTabFocus() && *i != c &&
|
||||
(*i)->desktop() == d && !(*i)->isMinimized() && (*i)->isOnCurrentActivity()) {
|
||||
ToplevelList clist = stackingOrder();
|
||||
for (ToplevelList::Iterator i = clist.begin(); i != clist.end(); ++i) {
|
||||
Client *client = qobject_cast<Client*>(c);
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
if (client->wantsTabFocus() && *i != c &&
|
||||
client->desktop() == d && !client->isMinimized() && (*i)->isOnCurrentActivity()) {
|
||||
// Centre of the other window
|
||||
QPoint other((*i)->pos().x() + (*i)->geometry().width() / 2,
|
||||
(*i)->pos().y() + (*i)->geometry().height() / 2);
|
||||
QPoint other(client->pos().x() + client->geometry().width() / 2,
|
||||
client->pos().y() + client->geometry().height() / 2);
|
||||
|
||||
int distance;
|
||||
int offset;
|
||||
|
@ -1503,7 +1508,7 @@ void Workspace::switchWindow(Direction direction)
|
|||
// Inverse score
|
||||
int score = distance + offset + ((offset * offset) / distance);
|
||||
if (score < bestScore || !switchTo) {
|
||||
switchTo = *i;
|
||||
switchTo = client;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
|
|
122
workspace.cpp
122
workspace.cpp
|
@ -490,14 +490,18 @@ Workspace::~Workspace()
|
|||
// TODO: grabXServer();
|
||||
|
||||
// Use stacking_order, so that kwin --replace keeps stacking order
|
||||
for (ClientList::iterator it = stacking_order.begin(), end = stacking_order.end(); it != end; ++it) {
|
||||
for (ToplevelList::iterator it = stacking_order.begin(), end = stacking_order.end(); it != end; ++it) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
// Only release the window
|
||||
(*it)->releaseWindow(true);
|
||||
c->releaseWindow(true);
|
||||
// No removeClient() is called, it does more than just removing.
|
||||
// However, remove from some lists to e.g. prevent performTransiencyCheck()
|
||||
// from crashing.
|
||||
clients.removeAll(*it);
|
||||
desktops.removeAll(*it);
|
||||
clients.removeAll(c);
|
||||
desktops.removeAll(c);
|
||||
}
|
||||
for (UnmanagedList::iterator it = unmanaged.begin(), end = unmanaged.end(); it != end; ++it)
|
||||
(*it)->release();
|
||||
|
@ -792,28 +796,32 @@ void Workspace::updateToolWindows(bool also_hide)
|
|||
|
||||
// SELI TODO: But maybe it should - what if a new client has been added that's not in stacking order yet?
|
||||
ClientList to_show, to_hide;
|
||||
for (ClientList::ConstIterator it = stacking_order.constBegin();
|
||||
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
|
||||
it != stacking_order.constEnd();
|
||||
++it) {
|
||||
if ((*it)->isUtility() || (*it)->isMenu() || (*it)->isToolbar()) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->isUtility() || c->isMenu() || c->isToolbar()) {
|
||||
bool show = true;
|
||||
if (!(*it)->isTransient()) {
|
||||
if ((*it)->group()->members().count() == 1) // Has its own group, keep always visible
|
||||
if (!c->isTransient()) {
|
||||
if (c->group()->members().count() == 1) // Has its own group, keep always visible
|
||||
show = true;
|
||||
else if (client != NULL && (*it)->group() == client->group())
|
||||
else if (client != NULL && c->group() == client->group())
|
||||
show = true;
|
||||
else
|
||||
show = false;
|
||||
} else {
|
||||
if (group != NULL && (*it)->group() == group)
|
||||
if (group != NULL && c->group() == group)
|
||||
show = true;
|
||||
else if (client != NULL && client->hasTransient((*it), true))
|
||||
else if (client != NULL && client->hasTransient(c, true))
|
||||
show = true;
|
||||
else
|
||||
show = false;
|
||||
}
|
||||
if (!show && also_hide) {
|
||||
const ClientList mainclients = (*it)->mainClients();
|
||||
const ClientList mainclients = c->mainClients();
|
||||
// Don't hide utility windows which are standalone(?) or
|
||||
// have e.g. kicker as mainwindow
|
||||
if (mainclients.isEmpty())
|
||||
|
@ -821,14 +829,14 @@ void Workspace::updateToolWindows(bool also_hide)
|
|||
for (ClientList::ConstIterator it2 = mainclients.constBegin();
|
||||
it2 != mainclients.constEnd();
|
||||
++it2) {
|
||||
if ((*it2)->isSpecialWindow())
|
||||
if (c->isSpecialWindow())
|
||||
show = true;
|
||||
}
|
||||
if (!show)
|
||||
to_hide.append(*it);
|
||||
to_hide.append(c);
|
||||
}
|
||||
if (show)
|
||||
to_show.append(*it);
|
||||
to_show.append(c);
|
||||
}
|
||||
} // First show new ones, then hide
|
||||
for (int i = to_show.size() - 1;
|
||||
|
@ -1254,14 +1262,19 @@ bool Workspace::setCurrentDesktop(int new_desktop)
|
|||
|
||||
currentDesktop_ = new_desktop; // Change the desktop (so that Client::updateVisibility() works)
|
||||
|
||||
for (ClientList::ConstIterator it = stacking_order.constBegin();
|
||||
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
|
||||
it != stacking_order.constEnd();
|
||||
++it)
|
||||
if (!(*it)->isOnDesktop(new_desktop) && (*it) != movingClient && (*it)->isOnCurrentActivity()) {
|
||||
if ((*it)->isShown(true) && (*it)->isOnDesktop(old_desktop))
|
||||
obs_wins.create(*it);
|
||||
(*it)->updateVisibility();
|
||||
++it) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (!c->isOnDesktop(new_desktop) && c != movingClient && c->isOnCurrentActivity()) {
|
||||
if (c->isShown(true) && c->isOnDesktop(old_desktop))
|
||||
obs_wins.create(c);
|
||||
(c)->updateVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
// Now propagate the change, after hiding, before showing
|
||||
rootInfo->setCurrentDesktop(currentDesktop());
|
||||
|
@ -1281,9 +1294,14 @@ bool Workspace::setCurrentDesktop(int new_desktop)
|
|||
#endif
|
||||
}
|
||||
|
||||
for (int i = stacking_order.size() - 1; i >= 0 ; --i)
|
||||
if (stacking_order.at(i)->isOnDesktop(new_desktop) && stacking_order.at(i)->isOnCurrentActivity())
|
||||
stacking_order.at(i)->updateVisibility();
|
||||
for (int i = stacking_order.size() - 1; i >= 0 ; --i) {
|
||||
Client *c = qobject_cast<Client*>(stacking_order.at(i));
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->isOnDesktop(new_desktop) && c->isOnCurrentActivity())
|
||||
c->updateVisibility();
|
||||
}
|
||||
|
||||
--block_showing_desktop;
|
||||
if (showingDesktop()) // Do this only after desktop change to avoid flicker
|
||||
|
@ -1302,9 +1320,12 @@ bool Workspace::setCurrentDesktop(int new_desktop)
|
|||
c = active_client; // The requestFocus below will fail, as the client is already active
|
||||
// from actiavtion.cpp
|
||||
if (!c && options->isNextFocusPrefersMouse()) {
|
||||
QList<Client*>::const_iterator it = stackingOrder().constEnd();
|
||||
ToplevelList::const_iterator it = stackingOrder().constEnd();
|
||||
while (it != stackingOrder().constBegin()) {
|
||||
Client *client = *(--it);
|
||||
Client *client = qobject_cast<Client*>(*(--it));
|
||||
if (!client) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(client->isShown(false) && client->isOnDesktop(new_desktop) &&
|
||||
client->isOnCurrentActivity() && client->isOnScreen(activeScreen())))
|
||||
|
@ -1393,14 +1414,19 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
|
|||
QString old_activity = activity_;
|
||||
activity_ = new_activity;
|
||||
|
||||
for (ClientList::ConstIterator it = stacking_order.constBegin();
|
||||
for (ToplevelList::ConstIterator it = stacking_order.constBegin();
|
||||
it != stacking_order.constEnd();
|
||||
++it)
|
||||
if (!(*it)->isOnActivity(new_activity) && (*it) != movingClient && (*it)->isOnCurrentDesktop()) {
|
||||
if ((*it)->isShown(true) && (*it)->isOnActivity(old_activity))
|
||||
obs_wins.create(*it);
|
||||
(*it)->updateVisibility();
|
||||
++it) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (!c->isOnActivity(new_activity) && c != movingClient && c->isOnCurrentDesktop()) {
|
||||
if (c->isShown(true) && c->isOnActivity(old_activity))
|
||||
obs_wins.create(c);
|
||||
c->updateVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
// Now propagate the change, after hiding, before showing
|
||||
//rootInfo->setCurrentDesktop( currentDesktop() );
|
||||
|
@ -1417,9 +1443,14 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
|
|||
}
|
||||
*/
|
||||
|
||||
for (int i = stacking_order.size() - 1; i >= 0 ; --i)
|
||||
if (stacking_order.at(i)->isOnActivity(new_activity))
|
||||
stacking_order.at(i)->updateVisibility();
|
||||
for (int i = stacking_order.size() - 1; i >= 0 ; --i) {
|
||||
Client *c = qobject_cast<Client*>(stacking_order.at(i));
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->isOnActivity(new_activity))
|
||||
c->updateVisibility();
|
||||
}
|
||||
|
||||
--block_showing_desktop;
|
||||
//FIXME not sure if I should do this either
|
||||
|
@ -1497,8 +1528,10 @@ void Workspace::updateCurrentActivity(const QString &new_activity)
|
|||
void Workspace::activityRemoved(const QString &activity)
|
||||
{
|
||||
allActivities_.removeOne(activity);
|
||||
foreach (Client * client, stacking_order) {
|
||||
client->setOnActivity(activity, false);
|
||||
foreach (Toplevel * toplevel, stacking_order) {
|
||||
if (Client *client = qobject_cast<Client*>(toplevel)) {
|
||||
client->setOnActivity(activity, false);
|
||||
}
|
||||
}
|
||||
//toss out any session data for it
|
||||
KConfigGroup cg(KGlobal::config(), QString("SubSession: ") + activity);
|
||||
|
@ -1892,14 +1925,19 @@ void Workspace::setShowingDesktop(bool showing)
|
|||
if (showing_desktop) {
|
||||
showing_desktop_clients.clear();
|
||||
++block_focus;
|
||||
ClientList cls = stackingOrder();
|
||||
ToplevelList cls = stackingOrder();
|
||||
// Find them first, then minimize, otherwise transients may get minimized with the window
|
||||
// they're transient for
|
||||
for (ClientList::ConstIterator it = cls.constBegin();
|
||||
for (ToplevelList::ConstIterator it = cls.constBegin();
|
||||
it != cls.constEnd();
|
||||
++it)
|
||||
if ((*it)->isOnCurrentActivity() && (*it)->isOnCurrentDesktop() && (*it)->isShown(true) && !(*it)->isSpecialWindow())
|
||||
showing_desktop_clients.prepend(*it); // Topmost first to reduce flicker
|
||||
++it) {
|
||||
Client *c = qobject_cast<Client*>(*it);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
if (c->isOnCurrentActivity() && c->isOnCurrentDesktop() && c->isShown(true) && !c->isSpecialWindow())
|
||||
showing_desktop_clients.prepend(c); // Topmost first to reduce flicker
|
||||
}
|
||||
for (ClientList::ConstIterator it = showing_desktop_clients.constBegin();
|
||||
it != showing_desktop_clients.constEnd();
|
||||
++it)
|
||||
|
|
|
@ -378,7 +378,7 @@ public:
|
|||
* Returns the list of clients sorted in stacking order, with topmost client
|
||||
* at the last position
|
||||
*/
|
||||
const ClientList& stackingOrder() const;
|
||||
const ToplevelList& stackingOrder() const;
|
||||
ToplevelList xStackingOrder() const;
|
||||
ClientList ensureStackingOrder(const ClientList& clients) const;
|
||||
|
||||
|
@ -790,8 +790,8 @@ private:
|
|||
UnmanagedList unmanaged;
|
||||
DeletedList deleted;
|
||||
|
||||
ClientList unconstrained_stacking_order; // Topmost last
|
||||
ClientList stacking_order; // Topmost last
|
||||
ToplevelList unconstrained_stacking_order; // Topmost last
|
||||
ToplevelList stacking_order; // Topmost last
|
||||
bool force_restacking;
|
||||
mutable ToplevelList x_stacking; // From XQueryTree()
|
||||
mutable bool x_stacking_dirty;
|
||||
|
@ -1025,7 +1025,7 @@ inline void Workspace::removeGroup(Group* group, allowed_t)
|
|||
groups.removeAll(group);
|
||||
}
|
||||
|
||||
inline const ClientList& Workspace::stackingOrder() const
|
||||
inline const ToplevelList& Workspace::stackingOrder() const
|
||||
{
|
||||
// TODO: Q_ASSERT( block_stacking_updates == 0 );
|
||||
return stacking_order;
|
||||
|
|
Loading…
Reference in a new issue