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.
icc-effect-5.14.5
Martin Gräßlin 2012-04-08 10:07:35 +02:00
parent c175e75939
commit f0c6f06241
12 changed files with 235 additions and 144 deletions

View File

@ -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

View File

@ -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()) {

View File

@ -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

View File

@ -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()))

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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*)));

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;