Changeset View
Changeset View
Standalone View
Standalone View
layers.cpp
Show First 20 Lines • Show All 519 Lines • ▼ Show 20 Line(s) | 497 | { | |||
---|---|---|---|---|---|
520 | } | 520 | } | ||
521 | ToplevelList stacking; | 521 | ToplevelList stacking; | ||
522 | for (Layer lay = FirstLayer; | 522 | for (Layer lay = FirstLayer; | ||
523 | lay < NumLayers; | 523 | lay < NumLayers; | ||
524 | ++lay) | 524 | ++lay) | ||
525 | stacking += layer[ lay ]; | 525 | stacking += layer[ lay ]; | ||
526 | // now keep transients above their mainwindows | 526 | // now keep transients above their mainwindows | ||
527 | // TODO this could(?) use some optimization | 527 | // TODO this could(?) use some optimization | ||
528 | for (int i = stacking.size() - 1; | 528 | for (int i = stacking.size() - 1; i >= 0;) { | ||
529 | i >= 0; | 529 | // Index of the main window for the current transient window. | ||
530 | ) { | 530 | int i2 = -1; | ||
531 | AbstractClient *current = qobject_cast<AbstractClient*>(stacking[i]); | 531 | | ||
532 | if (!current || !current->isTransient()) { | 532 | // If the current transient has "child" transients, we'd like to restart | ||
533 | // construction of the constrained stacking order from the position where | ||||
534 | // the current transient will be moved. | ||||
535 | bool hasTransients = false; | ||||
536 | | ||||
537 | // Find topmost client this one is transient for. | ||||
538 | if (auto *client = qobject_cast<AbstractClient *>(stacking[i])) { | ||||
539 | if (!client->isTransient()) { | ||||
533 | --i; | 540 | --i; | ||
534 | continue; | 541 | continue; | ||
535 | } | 542 | } | ||
536 | int i2 = -1; | | |||
537 | // find topmost client this one is transient for | | |||
538 | for (i2 = stacking.size() - 1; i2 >= 0; --i2) { | 543 | for (i2 = stacking.size() - 1; i2 >= 0; --i2) { | ||
539 | AbstractClient *c2 = qobject_cast<AbstractClient *>(stacking[i2]); | 544 | auto *c2 = qobject_cast<AbstractClient *>(stacking[i2]); | ||
540 | if (!c2) { | 545 | if (!c2) { | ||
541 | continue; | 546 | continue; | ||
542 | } | 547 | } | ||
543 | if (c2 == current) { | 548 | if (c2 == client) { | ||
544 | i2 = -1; // Don't reorder, already on top of its main window. | 549 | i2 = -1; // Don't reorder, already on top of its main window. | ||
545 | break; | 550 | break; | ||
546 | } | 551 | } | ||
547 | if (c2->hasTransient(current, true) | 552 | if (c2->hasTransient(client, true) | ||
548 | && keepTransientAbove(c2, current)) { | 553 | && keepTransientAbove(c2, client)) { | ||
554 | break; | ||||
555 | } | ||||
556 | } | ||||
557 | | ||||
558 | hasTransients = !client->transients().isEmpty(); | ||||
559 | | ||||
560 | // If the current transient doesn't have any "alive" transients, check | ||||
561 | // whether it has deleted transients that have to be raised. | ||||
562 | const bool searchForDeletedTransients = !hasTransients | ||||
563 | && !deletedList().isEmpty(); | ||||
564 | if (searchForDeletedTransients) { | ||||
565 | for (int j = i + 1; j < stacking.count(); ++j) { | ||||
566 | auto *deleted = qobject_cast<Deleted *>(stacking[j]); | ||||
567 | if (!deleted) { | ||||
568 | continue; | ||||
569 | } | ||||
570 | if (deleted->wasTransientFor(client)) { | ||||
571 | hasTransients = true; | ||||
549 | break; | 572 | break; | ||
550 | } | 573 | } | ||
551 | } | 574 | } | ||
575 | } | ||||
576 | } else if (auto *deleted = qobject_cast<Deleted *>(stacking[i])) { | ||||
577 | if (!deleted->wasTransient()) { | ||||
578 | --i; | ||||
579 | continue; | ||||
580 | } | ||||
581 | for (i2 = stacking.size() - 1; i2 >= 0; --i2) { | ||||
582 | Toplevel *c2 = stacking[i2]; | ||||
583 | if (c2 == deleted) { | ||||
584 | i2 = -1; // Don't reorder, already on top of its main window. | ||||
585 | break; | ||||
586 | } | ||||
587 | if (deleted->wasTransientFor(c2) | ||||
588 | && keepDeletedTransientAbove(c2, deleted)) { | ||||
589 | break; | ||||
590 | } | ||||
591 | } | ||||
592 | hasTransients = !deleted->transients().isEmpty(); | ||||
593 | } | ||||
594 | | ||||
552 | if (i2 == -1) { | 595 | if (i2 == -1) { | ||
553 | --i; | 596 | --i; | ||
554 | continue; | 597 | continue; | ||
555 | } | 598 | } | ||
599 | | ||||
600 | Toplevel *current = stacking[i]; | ||||
601 | | ||||
556 | stacking.removeAt(i); | 602 | stacking.removeAt(i); | ||
557 | --i; // move onto the next item (for next for () iteration) | 603 | --i; // move onto the next item (for next for () iteration) | ||
558 | --i2; // adjust index of the mainwindow after the remove above | 604 | --i2; // adjust index of the mainwindow after the remove above | ||
559 | if (!current->transients().isEmpty()) // this one now can be possibly above its transients, | 605 | if (hasTransients) { // this one now can be possibly above its transients, | ||
560 | i = i2; // so go again higher in the stack order and possibly move those transients again | 606 | i = i2; // so go again higher in the stack order and possibly move those transients again | ||
607 | } | ||||
561 | ++i2; // insert after (on top of) the mainwindow, it's ok if it2 is now stacking.end() | 608 | ++i2; // insert after (on top of) the mainwindow, it's ok if it2 is now stacking.end() | ||
562 | stacking.insert(i2, current); | 609 | stacking.insert(i2, current); | ||
563 | } | 610 | } | ||
564 | return stacking; | 611 | return stacking; | ||
565 | } | 612 | } | ||
566 | 613 | | |||
567 | void Workspace::blockStackingUpdates(bool block) | 614 | void Workspace::blockStackingUpdates(bool block) | ||
568 | { | 615 | { | ||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | 667 | { | |||
632 | // #63223 - don't keep transients above docks, because the dock is kept high, | 679 | // #63223 - don't keep transients above docks, because the dock is kept high, | ||
633 | // and e.g. dialogs for them would be too high too | 680 | // and e.g. dialogs for them would be too high too | ||
634 | // ignore this if the transient has a placement hint which indicates it should go above it's parent | 681 | // ignore this if the transient has a placement hint which indicates it should go above it's parent | ||
635 | if (mainwindow->isDock() && !transient->hasTransientPlacementHint()) | 682 | if (mainwindow->isDock() && !transient->hasTransientPlacementHint()) | ||
636 | return false; | 683 | return false; | ||
637 | return true; | 684 | return true; | ||
638 | } | 685 | } | ||
639 | 686 | | |||
687 | bool Workspace::keepDeletedTransientAbove(const Toplevel *mainWindow, const Deleted *transient) const | ||||
688 | { | ||||
689 | // #93832 - Don't keep splashscreens above dialogs. | ||||
690 | if (transient->isSplash() && mainWindow->isDialog()) { | ||||
691 | return false; | ||||
692 | } | ||||
693 | | ||||
694 | if (transient->wasX11Client()) { | ||||
695 | // If a group transient was active, we should keep it above no matter | ||||
696 | // what, because at the time when the transient was closed, it was above | ||||
697 | // the main window. | ||||
698 | if (transient->wasGroupTransient() && transient->wasActive()) { | ||||
699 | return true; | ||||
700 | } | ||||
701 | | ||||
702 | // This is rather a hack for #76026. Don't keep non-modal dialogs above | ||||
703 | // the mainwindow, but only if they're group transient (since only such | ||||
704 | // dialogs have taskbar entry in Kicker). A proper way of doing this | ||||
705 | // (both kwin and kicker) needs to be found. | ||||
706 | if (transient->wasGroupTransient() && transient->isDialog() | ||||
707 | && !transient->isModal()) { | ||||
708 | return false; | ||||
709 | } | ||||
710 | | ||||
711 | // #63223 - Don't keep transients above docks, because the dock is kept | ||||
712 | // high, and e.g. dialogs for them would be too high too. | ||||
713 | if (mainWindow->isDock()) { | ||||
714 | return false; | ||||
715 | } | ||||
716 | } | ||||
717 | | ||||
718 | return true; | ||||
719 | } | ||||
720 | | ||||
640 | // Returns all windows in their stacking order on the root window. | 721 | // Returns all windows in their stacking order on the root window. | ||
641 | ToplevelList Workspace::xStackingOrder() const | 722 | ToplevelList Workspace::xStackingOrder() const | ||
642 | { | 723 | { | ||
643 | if (m_xStackingDirty) { | 724 | if (m_xStackingDirty) { | ||
644 | const_cast<Workspace*>(this)->updateXStackingOrder(); | 725 | const_cast<Workspace*>(this)->updateXStackingOrder(); | ||
645 | } | 726 | } | ||
646 | return x_stacking; | 727 | return x_stacking; | ||
647 | } | 728 | } | ||
▲ Show 20 Lines • Show All 143 Lines • Show Last 20 Lines |