implement restack configure events, fix stackUnder when stacking up under a foreign client
BUG: 288721 REVIEW: 103387
This commit is contained in:
parent
8979af0a5f
commit
31f9533029
1 changed files with 91 additions and 43 deletions
126
layers.cpp
126
layers.cpp
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue