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
parent
c175e75939
commit
f0c6f06241
|
@ -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 New Issue