Changeset View
Changeset View
Standalone View
Standalone View
layers.cpp
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Line(s) | |||||
75 | Workspace::stackingOrder() up to date and propagated to the world. | 75 | Workspace::stackingOrder() up to date and propagated to the world. | ||
76 | Using Workspace::blockStackingUpdates() (or the StackingUpdatesBlocker | 76 | Using Workspace::blockStackingUpdates() (or the StackingUpdatesBlocker | ||
77 | helper class) it's possible to temporarily disable updates | 77 | helper class) it's possible to temporarily disable updates | ||
78 | and the stacking order will be updated once after it's allowed again. | 78 | and the stacking order will be updated once after it's allowed again. | ||
79 | 79 | | |||
80 | */ | 80 | */ | ||
81 | 81 | | |||
82 | #include "utils.h" | 82 | #include "utils.h" | ||
83 | #include "client.h" | 83 | #include "x11client.h" | ||
84 | #include "focuschain.h" | 84 | #include "focuschain.h" | ||
85 | #include "netinfo.h" | 85 | #include "netinfo.h" | ||
86 | #include "workspace.h" | 86 | #include "workspace.h" | ||
87 | #include "tabbox.h" | 87 | #include "tabbox.h" | ||
88 | #include "group.h" | 88 | #include "group.h" | ||
89 | #include "rules.h" | 89 | #include "rules.h" | ||
90 | #include "screens.h" | 90 | #include "screens.h" | ||
91 | #include "unmanaged.h" | 91 | #include "unmanaged.h" | ||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | 158 | { | |||
172 | 172 | | |||
173 | newWindowStack << ScreenEdges::self()->windows(); | 173 | newWindowStack << ScreenEdges::self()->windows(); | ||
174 | 174 | | |||
175 | newWindowStack << manual_overlays; | 175 | newWindowStack << manual_overlays; | ||
176 | 176 | | |||
177 | newWindowStack.reserve(newWindowStack.size() + 2*stacking_order.size()); // *2 for inputWindow | 177 | newWindowStack.reserve(newWindowStack.size() + 2*stacking_order.size()); // *2 for inputWindow | ||
178 | 178 | | |||
179 | for (int i = stacking_order.size() - 1; i >= 0; --i) { | 179 | for (int i = stacking_order.size() - 1; i >= 0; --i) { | ||
180 | Client *client = qobject_cast<Client*>(stacking_order.at(i)); | 180 | X11Client *client = qobject_cast<X11Client *>(stacking_order.at(i)); | ||
181 | if (!client || client->hiddenPreview()) { | 181 | if (!client || client->hiddenPreview()) { | ||
182 | continue; | 182 | continue; | ||
183 | } | 183 | } | ||
184 | 184 | | |||
185 | if (client->inputId()) | 185 | if (client->inputId()) | ||
186 | // Stack the input window above the frame | 186 | // Stack the input window above the frame | ||
187 | newWindowStack << client->inputId(); | 187 | newWindowStack << client->inputId(); | ||
188 | 188 | | |||
189 | newWindowStack << client->frameId(); | 189 | newWindowStack << client->frameId(); | ||
190 | } | 190 | } | ||
191 | 191 | | |||
192 | // when having hidden previews, stack hidden windows below everything else | 192 | // when having hidden previews, stack hidden windows below everything else | ||
193 | // (as far as pure X stacking order is concerned), in order to avoid having | 193 | // (as far as pure X stacking order is concerned), in order to avoid having | ||
194 | // these windows that should be unmapped to interfere with other windows | 194 | // these windows that should be unmapped to interfere with other windows | ||
195 | for (int i = stacking_order.size() - 1; i >= 0; --i) { | 195 | for (int i = stacking_order.size() - 1; i >= 0; --i) { | ||
196 | Client *client = qobject_cast<Client*>(stacking_order.at(i)); | 196 | X11Client *client = qobject_cast<X11Client *>(stacking_order.at(i)); | ||
197 | if (!client || !client->hiddenPreview()) | 197 | if (!client || !client->hiddenPreview()) | ||
198 | continue; | 198 | continue; | ||
199 | newWindowStack << client->frameId(); | 199 | newWindowStack << client->frameId(); | ||
200 | } | 200 | } | ||
201 | // TODO isn't it too inefficient to restack always all clients? | 201 | // TODO isn't it too inefficient to restack always all clients? | ||
202 | // TODO don't restack not visible windows? | 202 | // TODO don't restack not visible windows? | ||
203 | Q_ASSERT(newWindowStack.at(0) == rootInfo()->supportWindow()); | 203 | Q_ASSERT(newWindowStack.at(0) == rootInfo()->supportWindow()); | ||
204 | Xcb::restackWindows(newWindowStack); | 204 | Xcb::restackWindows(newWindowStack); | ||
▲ Show 20 Lines • Show All 220 Lines • ▼ Show 20 Line(s) | 424 | { | |||
425 | if (src == NET::FromTool || allowFullClientRaising(c, timestamp)) | 425 | if (src == NET::FromTool || allowFullClientRaising(c, timestamp)) | ||
426 | raiseClient(c); | 426 | raiseClient(c); | ||
427 | else { | 427 | else { | ||
428 | raiseClientWithinApplication(c); | 428 | raiseClientWithinApplication(c); | ||
429 | c->demandAttention(); | 429 | c->demandAttention(); | ||
430 | } | 430 | } | ||
431 | } | 431 | } | ||
432 | 432 | | |||
433 | void Workspace::lowerClientRequest(KWin::Client *c, NET::RequestSource src, xcb_timestamp_t /*timestamp*/) | 433 | void Workspace::lowerClientRequest(KWin::X11Client *c, NET::RequestSource src, xcb_timestamp_t /*timestamp*/) | ||
434 | { | 434 | { | ||
435 | // If the client has support for all this focus stealing prevention stuff, | 435 | // If the client has support for all this focus stealing prevention stuff, | ||
436 | // do only lowering within the application, as that's the more logical | 436 | // do only lowering within the application, as that's the more logical | ||
437 | // variant of lowering when application requests it. | 437 | // variant of lowering when application requests it. | ||
438 | // No demanding of attention here of course. | 438 | // No demanding of attention here of course. | ||
439 | if (src == NET::FromTool || !c->hasUserTimeSupport()) | 439 | if (src == NET::FromTool || !c->hasUserTimeSupport()) | ||
440 | lowerClient(c); | 440 | lowerClient(c); | ||
441 | else | 441 | else | ||
Show All 32 Lines | |||||
474 | { | 474 | { | ||
475 | if (!active_client || active_client == c || active_client->layer() != c->layer()) { | 475 | if (!active_client || active_client == c || active_client->layer() != c->layer()) { | ||
476 | raiseClient(c); | 476 | raiseClient(c); | ||
477 | return; | 477 | return; | ||
478 | } | 478 | } | ||
479 | restack(c, active_client); | 479 | restack(c, active_client); | ||
480 | } | 480 | } | ||
481 | 481 | | |||
482 | void Workspace::restoreSessionStackingOrder(Client* c) | 482 | void Workspace::restoreSessionStackingOrder(X11Client *c) | ||
483 | { | 483 | { | ||
484 | if (c->sessionStackingOrder() < 0) | 484 | if (c->sessionStackingOrder() < 0) | ||
485 | return; | 485 | return; | ||
486 | StackingUpdatesBlocker blocker(this); | 486 | StackingUpdatesBlocker blocker(this); | ||
487 | unconstrained_stacking_order.removeAll(c); | 487 | unconstrained_stacking_order.removeAll(c); | ||
488 | for (ToplevelList::Iterator it = unconstrained_stacking_order.begin(); // from bottom | 488 | for (ToplevelList::Iterator it = unconstrained_stacking_order.begin(); // from bottom | ||
489 | it != unconstrained_stacking_order.end(); | 489 | it != unconstrained_stacking_order.end(); | ||
490 | ++it) { | 490 | ++it) { | ||
491 | Client *current = qobject_cast<Client*>(*it); | 491 | X11Client *current = qobject_cast<X11Client *>(*it); | ||
492 | if (!current) { | 492 | if (!current) { | ||
493 | continue; | 493 | continue; | ||
494 | } | 494 | } | ||
495 | if (current->sessionStackingOrder() > c->sessionStackingOrder()) { | 495 | if (current->sessionStackingOrder() > c->sessionStackingOrder()) { | ||
496 | unconstrained_stacking_order.insert(it, c); | 496 | unconstrained_stacking_order.insert(it, c); | ||
497 | return; | 497 | return; | ||
498 | } | 498 | } | ||
499 | } | 499 | } | ||
Show All 9 Lines | 507 | { | |||
509 | 509 | | |||
510 | // build the order from layers | 510 | // build the order from layers | ||
511 | QVector< QMap<Group*, Layer> > minimum_layer(screens()->count()); | 511 | QVector< QMap<Group*, Layer> > minimum_layer(screens()->count()); | ||
512 | for (ToplevelList::ConstIterator it = unconstrained_stacking_order.constBegin(), | 512 | for (ToplevelList::ConstIterator it = unconstrained_stacking_order.constBegin(), | ||
513 | end = unconstrained_stacking_order.constEnd(); it != end; ++it) { | 513 | end = unconstrained_stacking_order.constEnd(); it != end; ++it) { | ||
514 | Layer l = (*it)->layer(); | 514 | Layer l = (*it)->layer(); | ||
515 | 515 | | |||
516 | const int screen = (*it)->screen(); | 516 | const int screen = (*it)->screen(); | ||
517 | Client *c = qobject_cast<Client*>(*it); | 517 | X11Client *c = qobject_cast<X11Client *>(*it); | ||
518 | QMap< Group*, Layer >::iterator mLayer = minimum_layer[screen].find(c ? c->group() : nullptr); | 518 | QMap< Group*, Layer >::iterator mLayer = minimum_layer[screen].find(c ? c->group() : nullptr); | ||
519 | if (mLayer != minimum_layer[screen].end()) { | 519 | if (mLayer != minimum_layer[screen].end()) { | ||
520 | // If a window is raised above some other window in the same window group | 520 | // If a window is raised above some other window in the same window group | ||
521 | // which is in the ActiveLayer (i.e. it's fulscreened), make sure it stays | 521 | // which is in the ActiveLayer (i.e. it's fulscreened), make sure it stays | ||
522 | // above that window (see #95731). | 522 | // above that window (see #95731). | ||
523 | if (*mLayer == ActiveLayer && (l > BelowLayer)) | 523 | if (*mLayer == ActiveLayer && (l > BelowLayer)) | ||
524 | l = ActiveLayer; | 524 | l = ActiveLayer; | ||
525 | *mLayer = l; | 525 | *mLayer = l; | ||
▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Line(s) | 738 | { | |||
771 | 771 | | |||
772 | m_xStackingDirty = false; | 772 | m_xStackingDirty = false; | ||
773 | } | 773 | } | ||
774 | 774 | | |||
775 | //******************************* | 775 | //******************************* | ||
776 | // Client | 776 | // Client | ||
777 | //******************************* | 777 | //******************************* | ||
778 | 778 | | |||
779 | void Client::restackWindow(xcb_window_t above, int detail, NET::RequestSource src, xcb_timestamp_t timestamp, bool send_event) | 779 | void X11Client::restackWindow(xcb_window_t above, int detail, NET::RequestSource src, xcb_timestamp_t timestamp, bool send_event) | ||
780 | { | 780 | { | ||
781 | Client *other = nullptr; | 781 | X11Client *other = nullptr; | ||
782 | if (detail == XCB_STACK_MODE_OPPOSITE) { | 782 | if (detail == XCB_STACK_MODE_OPPOSITE) { | ||
783 | other = workspace()->findClient(Predicate::WindowMatch, above); | 783 | other = workspace()->findClient(Predicate::WindowMatch, above); | ||
784 | if (!other) { | 784 | if (!other) { | ||
785 | workspace()->raiseOrLowerClient(this); | 785 | workspace()->raiseOrLowerClient(this); | ||
786 | return; | 786 | return; | ||
787 | } | 787 | } | ||
788 | ToplevelList::const_iterator it = workspace()->stackingOrder().constBegin(), | 788 | ToplevelList::const_iterator it = workspace()->stackingOrder().constBegin(), | ||
789 | end = workspace()->stackingOrder().constEnd(); | 789 | end = workspace()->stackingOrder().constEnd(); | ||
Show All 29 Lines | 818 | ToplevelList::const_iterator it = workspace()->stackingOrder().constEnd(), | |||
819 | begin = workspace()->stackingOrder().constBegin(); | 819 | begin = workspace()->stackingOrder().constBegin(); | ||
820 | while (--it != begin) { | 820 | while (--it != begin) { | ||
821 | 821 | | |||
822 | if (*it == other) { // the other one is top on stack | 822 | if (*it == other) { // the other one is top on stack | ||
823 | it = begin; // invalidate | 823 | it = begin; // invalidate | ||
824 | src = NET::FromTool; // force | 824 | src = NET::FromTool; // force | ||
825 | break; | 825 | break; | ||
826 | } | 826 | } | ||
827 | Client *c = qobject_cast<Client*>(*it); | 827 | X11Client *c = qobject_cast<X11Client *>(*it); | ||
828 | 828 | | |||
829 | if (!c || !( (*it)->isNormalWindow() && c->isShown(true) && | 829 | if (!c || !( (*it)->isNormalWindow() && c->isShown(true) && | ||
830 | (*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnScreen(screen()) )) | 830 | (*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnScreen(screen()) )) | ||
831 | continue; // irrelevant clients | 831 | continue; // irrelevant clients | ||
832 | 832 | | |||
833 | if (*(it - 1) == other) | 833 | if (*(it - 1) == other) | ||
834 | break; // "it" is the one above the target one, stack below "it" | 834 | break; // "it" is the one above the target one, stack below "it" | ||
835 | } | 835 | } | ||
836 | 836 | | |||
837 | if (it != begin && (*(it - 1) == other)) | 837 | if (it != begin && (*(it - 1) == other)) | ||
838 | other = qobject_cast<Client*>(*it); | 838 | other = qobject_cast<X11Client *>(*it); | ||
839 | else | 839 | else | ||
840 | other = nullptr; | 840 | other = nullptr; | ||
841 | } | 841 | } | ||
842 | 842 | | |||
843 | if (other) | 843 | if (other) | ||
844 | workspace()->restack(this, other); | 844 | workspace()->restack(this, other); | ||
845 | else if (detail == XCB_STACK_MODE_BELOW) | 845 | else if (detail == XCB_STACK_MODE_BELOW) | ||
846 | workspace()->lowerClientRequest(this, src, timestamp); | 846 | workspace()->lowerClientRequest(this, src, timestamp); | ||
847 | else if (detail == XCB_STACK_MODE_ABOVE) | 847 | else if (detail == XCB_STACK_MODE_ABOVE) | ||
848 | workspace()->raiseClientRequest(this, src, timestamp); | 848 | workspace()->raiseClientRequest(this, src, timestamp); | ||
849 | 849 | | |||
850 | if (send_event) | 850 | if (send_event) | ||
851 | sendSyntheticConfigureNotify(); | 851 | sendSyntheticConfigureNotify(); | ||
852 | } | 852 | } | ||
853 | 853 | | |||
854 | void Client::doSetKeepAbove() | 854 | void X11Client::doSetKeepAbove() | ||
855 | { | 855 | { | ||
856 | } | 856 | } | ||
857 | 857 | | |||
858 | void Client::doSetKeepBelow() | 858 | void X11Client::doSetKeepBelow() | ||
859 | { | 859 | { | ||
860 | } | 860 | } | ||
861 | 861 | | |||
862 | bool Client::belongsToDesktop() const | 862 | bool X11Client::belongsToDesktop() const | ||
863 | { | 863 | { | ||
864 | foreach (const Client *c, group()->members()) { | 864 | foreach (const X11Client *c, group()->members()) { | ||
865 | if (c->isDesktop()) | 865 | if (c->isDesktop()) | ||
866 | return true; | 866 | return true; | ||
867 | } | 867 | } | ||
868 | return false; | 868 | return false; | ||
869 | } | 869 | } | ||
870 | 870 | | |||
871 | } // namespace | 871 | } // namespace |