implement restack configure events, fix stackUnder when stacking up under a foreign client

BUG: 288721
REVIEW: 103387
This commit is contained in:
Thomas Lübking 2011-12-11 19:00:43 +01:00
parent 8979af0a5f
commit 31f9533029

View file

@ -359,13 +359,14 @@ void Workspace::raiseClientWithinApplication(Client* c)
// ignore mainwindows // ignore mainwindows
// first try to put it above the top-most window of the application // first try to put it above the top-most window of the application
for (int i = unconstrained_stacking_order.size() - 1; i >= 0 ; i--) { for (int i = unconstrained_stacking_order.size() - 1; i > -1 ; --i) {
if (unconstrained_stacking_order.at(i) == c) // don't lower it just because it asked to be raised Client *other = unconstrained_stacking_order.at(i);
if (other == c) // don't lower it just because it asked to be raised
return; return;
if (Client::belongToSameApplication(unconstrained_stacking_order.at(i), c)) { if (Client::belongToSameApplication(other, c)) {
unconstrained_stacking_order.removeAll(c); unconstrained_stacking_order.removeAll(c);
unconstrained_stacking_order.insert(++i, c); // insert after the found one unconstrained_stacking_order.insert(unconstrained_stacking_order.indexOf(other) + 1, c); // insert after the found one
return; break;
} }
} }
} }
@ -396,29 +397,23 @@ void Workspace::lowerClientRequest(Client* c, NET::RequestSource src, Time /*tim
void Workspace::restack(Client* c, Client* under) void Workspace::restack(Client* c, Client* under)
{ {
assert(unconstrained_stacking_order.contains(under)); assert(unconstrained_stacking_order.contains(under));
if (Client::belongToSameApplication(under, c)) { if (!Client::belongToSameApplication(under, c)) {
// put it below the active window if it's the same app
unconstrained_stacking_order.removeAll(c);
unconstrained_stacking_order.insert(unconstrained_stacking_order.indexOf(under), c);
} else {
// put in the stacking order below _all_ windows belonging to the active application // put in the stacking order below _all_ windows belonging to the active application
for (ClientList::Iterator it = unconstrained_stacking_order.begin(); Client *other = 0;
it != unconstrained_stacking_order.end(); for (int i = 0; i < unconstrained_stacking_order.size(); ++i) { // TODO ignore topmenus?
++it) { if (Client::belongToSameApplication(under, (other = unconstrained_stacking_order.at(i)))) {
// TODO ignore topmenus? under = (c == other) ? 0 : other;
if (Client::belongToSameApplication(under, *it)) {
if (*it != c) {
unconstrained_stacking_order.removeAll(c);
unconstrained_stacking_order.insert(it, c);
}
break; break;
} }
} }
} }
if (under) {
unconstrained_stacking_order.removeAll(c);
unconstrained_stacking_order.insert(unconstrained_stacking_order.indexOf(under), c);
}
assert(unconstrained_stacking_order.contains(c)); assert(unconstrained_stacking_order.contains(c));
for (int desktop = 1; for (int desktop = 1; desktop <= numberOfDesktops(); ++desktop) {
desktop <= numberOfDesktops();
++desktop) {
// do for every virtual desktop to handle the case of onalldesktop windows // do for every virtual desktop to handle the case of onalldesktop windows
if (c->wantsTabFocus() && c->isOnDesktop(desktop) && focus_chain[ desktop ].contains(under)) { if (c->wantsTabFocus() && c->isOnDesktop(desktop) && focus_chain[ desktop ].contains(under)) {
if (Client::belongToSameApplication(under, c)) { if (Client::belongToSameApplication(under, c)) {
@ -428,9 +423,7 @@ void Workspace::restack(Client* c, Client* under)
} else { } else {
// put it in focus_chain[currentDesktop()] after all windows belonging to the active applicationa // put it in focus_chain[currentDesktop()] after all windows belonging to the active applicationa
focus_chain[ desktop ].removeAll(c); focus_chain[ desktop ].removeAll(c);
for (int i = focus_chain[ desktop ].size() - 1; for (int i = focus_chain[ desktop ].size() - 1; i >= 0; --i) {
i >= 0;
--i) {
if (Client::belongToSameApplication(under, focus_chain[ desktop ].at(i))) { if (Client::belongToSameApplication(under, focus_chain[ desktop ].at(i))) {
focus_chain[ desktop ].insert(i, c); focus_chain[ desktop ].insert(i, c);
break; break;
@ -446,9 +439,7 @@ void Workspace::restack(Client* c, Client* under)
global_focus_chain.insert(global_focus_chain.indexOf(under), c); global_focus_chain.insert(global_focus_chain.indexOf(under), c);
} else { } else {
global_focus_chain.removeAll(c); global_focus_chain.removeAll(c);
for (int i = global_focus_chain.size() - 1; for (int i = global_focus_chain.size() - 1; i >= 0; --i) {
i >= 0;
--i) {
if (Client::belongToSameApplication(under, global_focus_chain.at(i))) { if (Client::belongToSameApplication(under, global_focus_chain.at(i))) {
global_focus_chain.insert(i, c); global_focus_chain.insert(i, c);
break; break;
@ -687,21 +678,78 @@ ToplevelList Workspace::xStackingOrder() const
// Client // Client
//******************************* //*******************************
void Client::restackWindow(Window /*above TODO */, int detail, NET::RequestSource src, Time timestamp, bool send_event) void Client::restackWindow(Window above, int detail, NET::RequestSource src, Time timestamp, bool send_event)
{ {
switch(detail) { Client *other = 0;
case Above: if (detail == Opposite) {
case TopIf: other = workspace()->findClient(WindowMatchPredicate(above));
workspace()->raiseClientRequest(this, src, timestamp); if (!other) {
workspace()->raiseOrLowerClient(this);
return;
}
ClientList::const_iterator it = workspace()->stackingOrder().constBegin(),
end = workspace()->stackingOrder().constEnd();
while (it != end) {
if (*it == this) {
detail = Above;
break; break;
case Below: } else if (*it == other) {
case BottomIf: detail = Below;
workspace()->lowerClientRequest(this, src, timestamp);
break;
case Opposite:
default:
break; break;
} }
++it;
}
}
else if (detail == TopIf) {
other = workspace()->findClient(WindowMatchPredicate(above));
if (other && other->geometry().intersects(geometry()))
workspace()->raiseClientRequest(this, src, timestamp);
return;
}
else if (detail == BottomIf) {
other = workspace()->findClient(WindowMatchPredicate(above));
if (other && other->geometry().intersects(geometry()))
workspace()->lowerClientRequest(this, src, timestamp);
return;
}
if (!other)
other = workspace()->findClient(WindowMatchPredicate(above));
if (other && detail == Above) {
ClientList::const_iterator it = workspace()->stackingOrder().constEnd(),
begin = workspace()->stackingOrder().constBegin();
while (--it != begin) {
if (*it == this)
return; // we're already above
if (*it == other) { // the other one is top on stack
it = begin; // invalidate
src = NET::FromTool; // force
break;
}
if (!( (*it)->isNormalWindow() && (*it)->isShown(true) &&
(*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnScreen(screen()) ))
continue; // irrelevant clients
if (*(it - 1) == other)
break; // "it" is the one above the target one, stack below "it"
}
if (it != begin && (*(it - 1) == other))
other = const_cast<Client*>(*it);
else
other = 0;
}
if (other)
workspace()->restack(this, other);
else if (detail == Below)
workspace()->lowerClientRequest(this, src, timestamp);
else if (detail == Above)
workspace()->raiseClientRequest(this, src, timestamp);
if (send_event) if (send_event)
sendSyntheticConfigureNotify(); sendSyntheticConfigureNotify();
} }