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