95    if (m_blockStackingUpdates > 0) {
 
   96        if (propagate_new_windows) {
 
   97            m_blockedPropagatingNewWindows = 
true;
 
  101    QList<Window *> new_stacking_order = constrainedStackingOrder();
 
  102    bool changed = (force_restacking || new_stacking_order != stacking_order);
 
  103    force_restacking = 
false;
 
  104    stacking_order = new_stacking_order;
 
  105    if (changed || propagate_new_windows) {
 
  106        propagateWindows(propagate_new_windows);
 
  108        for (
int i = 0; i < stacking_order.size(); ++i) {
 
  109            stacking_order[i]->setStackingOrder(i);
 
  114        if (m_activeWindow) {
 
 
  139void Workspace::propagateWindows(
bool propagate_new_windows)
 
  146    QList<xcb_window_t> newWindowStack;
 
  153    newWindowStack << 
rootInfo()->supportWindow();
 
  157    newWindowStack << manual_overlays;
 
  159    newWindowStack.reserve(newWindowStack.size() + 2 * stacking_order.size()); 
 
  161    for (
int i = stacking_order.size() - 1; i >= 0; --i) {
 
  162        X11Window *window = qobject_cast<X11Window *>(stacking_order.at(i));
 
  163        if (!window || window->isUnmanaged() || window->hiddenPreview()) {
 
  167        if (window->inputId()) {
 
  169            newWindowStack << window->inputId();
 
  172        newWindowStack << window->frameId();
 
  178    for (
int i = stacking_order.size() - 1; i >= 0; --i) {
 
  179        X11Window *window = qobject_cast<X11Window *>(stacking_order.at(i));
 
  180        if (!window || window->isUnmanaged() || !window->hiddenPreview()) {
 
  183        newWindowStack << window->frameId();
 
  187    Q_ASSERT(newWindowStack.at(0) == 
rootInfo()->supportWindow());
 
  188    Xcb::restackWindows(newWindowStack);
 
  190    QList<xcb_window_t> cl;
 
  191    if (propagate_new_windows) {
 
  192        cl.reserve(manual_overlays.size() + m_windows.size());
 
  193        for (
const auto win : std::as_const(manual_overlays)) {
 
  196        for (
Window *window : std::as_const(m_windows)) {
 
  197            X11Window *x11Window = qobject_cast<X11Window *>(window);
 
  198            if (x11Window && !x11Window->isUnmanaged()) {
 
  199                cl.push_back(x11Window->window());
 
  202        rootInfo()->setClientList(cl.constData(), cl.size());
 
  206    for (
auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {
 
  207        X11Window *window = qobject_cast<X11Window *>(*it);
 
  208        if (window && !window->isUnmanaged()) {
 
  209            cl.push_back(window->window());
 
  212    for (
const auto win : std::as_const(manual_overlays)) {
 
  215    rootInfo()->setClientListStacking(cl.constData(), cl.size());
 
  227    QList<Window *> list;
 
  228    if (!unconstrained) {
 
  229        list = stacking_order;
 
  231        list = unconstrained_stacking_order;
 
  233    for (
int i = list.size() - 1; i >= 0; --i) {
 
  234        auto window = list.at(i);
 
  235        if (!window->isClient() || window->isDeleted()) {
 
  238        if (window->isOnDesktop(desktop) && window->isShown() && window->isOnCurrentActivity() && !window->isShade()) {
 
  239            if (output && window->output() != output) {
 
  245            if (window->wantsTabFocus() && !window->isSpecialWindow()) {
 
 
  257        for (
int i = stacking_order.size() - 1; i >= 0; i--) {
 
  258            auto window = stacking_order.at(i);
 
  259            if (window->isDeleted()) {
 
  262            if (window->isClient() && window->isOnDesktop(desktop) && window->isDesktop() && window->isShown()) {
 
  267        for (
Window *window : std::as_const(stacking_order)) {
 
  268            if (window->isDeleted()) {
 
  271            if (window->isClient() && window->isOnDesktop(desktop) && window->isDesktop() && window->isShown()) {
 
 
  289    if (window == topmost) {
 
 
  299        qCWarning(KWIN_CORE) << 
"Workspace::lowerWindow: closed window" << window << 
"cannot be restacked";
 
  307    unconstrained_stacking_order.removeAll(window);
 
  308    unconstrained_stacking_order.prepend(window);
 
  311        QList<X11Window *> wins;
 
  312        if (
auto group = window->
group()) {
 
  315        for (
int i = wins.size() - 1; i >= 0; --i) {
 
  316            if (wins[i] != window) {
 
 
  323void Workspace::lowerWindowWithinApplication(
Window *window)
 
  326        qCWarning(KWIN_CORE) << 
"Workspace::lowerWindowWithinApplication: closed window" << window << 
"cannot be restacked";
 
  334    unconstrained_stacking_order.removeAll(window);
 
  335    bool lowered = 
false;
 
  337    for (
auto it = unconstrained_stacking_order.begin(); it != unconstrained_stacking_order.end(); ++it) {
 
  339        if (!other->isClient() || other->isDeleted()) {
 
  343            unconstrained_stacking_order.insert(it, window);
 
  349        unconstrained_stacking_order.prepend(window);
 
  357        qCWarning(KWIN_CORE) << 
"Workspace::raiseWindow: closed window" << window << 
"cannot be restacked";
 
  366        QList<Window *> transients;
 
  367        Window *transient_parent = window;
 
  368        while ((transient_parent = transient_parent->
transientFor())) {
 
  369            transients.prepend(transient_parent);
 
  371        for (
const auto &transient_parent : std::as_const(transients)) {
 
  376    unconstrained_stacking_order.removeAll(window);
 
  377    unconstrained_stacking_order.append(window);
 
 
  380void Workspace::raiseWindowWithinApplication(
Window *window)
 
  383        qCWarning(KWIN_CORE) << 
"Workspace::raiseWindowWithinApplication: closed window" << window << 
"cannot be restacked";
 
  393    for (
int i = unconstrained_stacking_order.size() - 1; i > -1; --i) {
 
  394        auto other = unconstrained_stacking_order.at(i);
 
  395        if (!other->isClient() || other->isDeleted()) {
 
  398        if (other == window) { 
 
  402            unconstrained_stacking_order.removeAll(window);
 
  403            unconstrained_stacking_order.insert(unconstrained_stacking_order.indexOf(other) + 1, window); 
 
  411    if (src == NET::FromTool || allowFullClientRaising(window, timestamp)) {
 
  414        raiseWindowWithinApplication(window);
 
 
  428        lowerWindowWithinApplication(window);
 
 
  434    lowerWindowWithinApplication(window);
 
 
  440        qCWarning(KWIN_CORE) << 
"Workspace::restack: closed window" << window << 
"cannot be restacked";
 
  443    Q_ASSERT(unconstrained_stacking_order.contains(under));
 
  446        for (
int i = 0; i < unconstrained_stacking_order.size(); ++i) {
 
  447            auto other = unconstrained_stacking_order.at(i);
 
  449                under = (window == other) ? 
nullptr : other;
 
  455        unconstrained_stacking_order.removeAll(window);
 
  456        unconstrained_stacking_order.insert(unconstrained_stacking_order.indexOf(under), window);
 
  459    Q_ASSERT(unconstrained_stacking_order.contains(window));
 
  460    m_focusChain->moveAfterWindow(window, under);
 
 
  466    if (!m_activeWindow || m_activeWindow == window || m_activeWindow->
layer() != window->
layer()) {
 
  470    restack(window, m_activeWindow);
 
 
  479    unconstrained_stacking_order.removeAll(window);
 
  480    for (
auto it = unconstrained_stacking_order.begin(); it != unconstrained_stacking_order.end(); ++it) {
 
  481        X11Window *current = qobject_cast<X11Window *>(*it);
 
  486            unconstrained_stacking_order.insert(it, window);
 
  490    unconstrained_stacking_order.append(window);
 
 
  502    if (
const Group *group = window->
group()) {
 
  503        const auto members = group->members();
 
  504        for (
const X11Window *member : members) {
 
  505            if (member == window) {
 
  507            } 
else if (member->output() != window->
output()) {
 
  521    if (
auto x11Window = qobject_cast<const X11Window *>(window)) {
 
  522        return layerForWindow(x11Window);
 
  524        return window->layer();
 
  531QList<Window *> Workspace::constrainedStackingOrder()
 
  536    for (
Window *window : std::as_const(unconstrained_stacking_order)) {
 
  537        const Layer layer = computeLayer(window);
 
  541    QList<Window *> stacking;
 
  542    stacking.reserve(unconstrained_stacking_order.count());
 
  549    QList<Constraint *> constraints;
 
  550    constraints.reserve(m_constraints.count());
 
  551    for (
Constraint *constraint : std::as_const(m_constraints)) {
 
  552        if (constraint->parents.isEmpty()) {
 
  553            constraint->enqueued = 
true;
 
  554            constraints.append(constraint);
 
  556            constraint->enqueued = 
false;
 
  562        return stacking.indexOf(a->above) > stacking.indexOf(b->above);
 
  564    std::sort(constraints.begin(), constraints.end(), constraintComparator);
 
  569    while (!constraints.isEmpty()) {
 
  570        Constraint *constraint = constraints.takeFirst();
 
  572        const int belowIndex = stacking.indexOf(constraint->below);
 
  573        const int aboveIndex = stacking.indexOf(constraint->above);
 
  574        if (belowIndex == -1 || aboveIndex == -1) {
 
  576        } 
else if (aboveIndex < belowIndex) {
 
  577            stacking.removeAt(aboveIndex);
 
  578            stacking.insert(belowIndex, constraint->above);
 
  582        QList<Constraint *> children = constraint->children;
 
  583        std::sort(children.begin(), children.end(), constraintComparator);
 
  585        for (
Constraint *child : std::as_const(children)) {
 
  586            if (!child->enqueued) {
 
  587                child->enqueued = 
true;
 
  588                constraints.append(child);
 
  596void Workspace::blockStackingUpdates(
bool block)
 
  599        if (m_blockStackingUpdates == 0) {
 
  600            m_blockedPropagatingNewWindows = 
false;
 
  602        ++m_blockStackingUpdates;
 
  604        if (--m_blockStackingUpdates == 0) {
 
  615QList<T *> ensureStackingOrderInList(
const QList<Window *> &stackingOrder, 
const QList<T *> &list)
 
  617    static_assert(std::is_base_of<Window, T>::value,
 
  618                  "U must be derived from T");
 
  620    if (list.count() < 2) {
 
  624    QList<T *> result = list;
 
  625    for (
auto it = stackingOrder.begin(); it != stackingOrder.end(); ++it) {
 
  626        T *window = qobject_cast<T *>(*it);
 
  630        if (result.removeAll(window) != 0) {
 
  631            result.append(window);
 
  641    return ensureStackingOrderInList(stacking_order, list);
 
 
  646    return ensureStackingOrderInList(stacking_order, list);
 
 
  651    return unconstrained_stacking_order;
 
 
  654void Workspace::updateXStackingOrder()
 
  657    Xcb::Tree tree(kwinApp()->x11RootWindow());
 
  658    xcb_window_t *
windows = tree.children();
 
  660    const auto count = tree.data()->children_len;
 
  661    bool changed = 
false;
 
  662    for (
unsigned int i = 0; i < count; ++i) {
 
  665            unconstrained_stacking_order.removeAll(window);
 
  666            unconstrained_stacking_order.append(window);
 
  683    if (detail == XCB_STACK_MODE_OPPOSITE) {
 
  693                detail = XCB_STACK_MODE_ABOVE;
 
  695            } 
else if (*it == other) {
 
  696                detail = XCB_STACK_MODE_BELOW;
 
  701    } 
else if (detail == XCB_STACK_MODE_TOP_IF) {
 
  707    } 
else if (detail == XCB_STACK_MODE_BOTTOM_IF) {
 
  719    if (other && detail == XCB_STACK_MODE_ABOVE) {
 
  722        while (--it != begin) {
 
  731            if (!
window || !((*it)->isNormalWindow() && 
window->isShown() && (*it)->isOnCurrentDesktop() && (*it)->isOnCurrentActivity() && (*it)->isOnOutput(
output()))) {
 
  735            if (*(it - 1) == other) {
 
  740        if (it != begin && (*(it - 1) == other)) {
 
  741            other = qobject_cast<X11Window *>(*it);
 
  749    } 
else if (detail == XCB_STACK_MODE_BELOW) {
 
  751    } 
else if (detail == XCB_STACK_MODE_ABOVE) {
 
  756        sendSyntheticConfigureNotify();
 
 
  764        if (
window->isDesktop()) {
 
 
void checkInputWindowStacking()
const QList< X11Window * > & members() const
bool isSeparateScreenFocus() const
QList< xcb_window_t > windows() const
virtual void updateMouseGrab()
virtual bool isTransient() const
static bool belongToSameApplication(const Window *c1, const Window *c2, SameApplicationChecks checks=SameApplicationChecks())
void demandAttention(bool set=true)
bool isOnCurrentDesktop() const
KWin::Window * transientFor
virtual const Group * group() const
X11Window * findUnmanaged(std::function< bool(const X11Window *)> func) const
ScreenEdges * screenEdges() const
void lowerWindowRequest(X11Window *window, NET::RequestSource src, xcb_timestamp_t timestamp)
X11Window * findClient(std::function< bool(const X11Window *)> func) const
Finds the first Client matching the condition expressed by passed in func.
const QList< Window * > & stackingOrder() const
void raiseWindowRequest(Window *window, NET::RequestSource src=NET::FromApplication, xcb_timestamp_t timestamp=0)
void stackScreenEdgesUnderOverrideRedirect()
void stackingOrderChanged()
Window * findDesktop(bool topmost, VirtualDesktop *desktop) const
friend Workspace * workspace()
void restack(Window *window, Window *under, bool force=false)
void updateStackingOrder(bool propagate_new_windows=false)
void raiseWindow(Window *window, bool nogroup=false)
Window * topWindowOnDesktop(VirtualDesktop *desktop, Output *output=nullptr, bool unconstrained=false, bool only_normal=true) const
QList< Window * > unconstrainedStackingOrder() const
void lowerWindow(Window *window, bool nogroup=false)
const QList< Window * > windows() const
friend class StackingUpdatesBlocker
void restoreSessionStackingOrder(X11Window *window)
void restackWindowUnderActive(Window *window)
void raiseOrLowerWindow(Window *window)
QList< X11Window * > ensureStackingOrder(const QList< X11Window * > &windows) const
bool hasUserTimeSupport() const
int sessionStackingOrder() const
void restackWindow(xcb_window_t above, int detail, NET::RequestSource source, xcb_timestamp_t timestamp, bool send_event=false)
bool belongsToDesktop() const override
bool isUnmanaged() const override
xcb_window_t window() const
const Group * group() const override