| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef COMPONENTS_MUS_COMMON_TRANSIENT_WINDOW_UTILS_H_ | |
| 6 #define COMPONENTS_MUS_COMMON_TRANSIENT_WINDOW_UTILS_H_ | |
| 7 | |
| 8 #include <stddef.h> | |
| 9 | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "components/mus/public/interfaces/mus_constants.mojom.h" | |
| 13 | |
| 14 namespace mus { | |
| 15 | |
| 16 // Returns true if |window| has |ancestor| as a transient ancestor. A transient | |
| 17 // ancestor is found by following the transient parent chain of the window. | |
| 18 template <class T> | |
| 19 bool HasTransientAncestor(const T* window, const T* ancestor) { | |
| 20 const T* transient_parent = window->transient_parent(); | |
| 21 if (transient_parent == ancestor) | |
| 22 return true; | |
| 23 return transient_parent ? HasTransientAncestor(transient_parent, ancestor) | |
| 24 : false; | |
| 25 } | |
| 26 | |
| 27 // Populates |ancestors| with all transient ancestors of |window| that are | |
| 28 // siblings of |window|. Returns true if any ancestors were found, false if not. | |
| 29 template <class T> | |
| 30 bool GetAllTransientAncestors(T* window, std::vector<T*>* ancestors) { | |
| 31 T* parent = window->parent(); | |
| 32 for (; window; window = window->transient_parent()) { | |
| 33 if (window->parent() == parent) | |
| 34 ancestors->push_back(window); | |
| 35 } | |
| 36 return !ancestors->empty(); | |
| 37 } | |
| 38 | |
| 39 // Replaces |window1| and |window2| with their possible transient ancestors that | |
| 40 // are still siblings (have a common transient parent). |window1| and |window2| | |
| 41 // are not modified if such ancestors cannot be found. | |
| 42 template <class T> | |
| 43 void FindCommonTransientAncestor(T** window1, T** window2) { | |
| 44 DCHECK(window1); | |
| 45 DCHECK(window2); | |
| 46 DCHECK(*window1); | |
| 47 DCHECK(*window2); | |
| 48 // Assemble chains of ancestors of both windows. | |
| 49 std::vector<T*> ancestors1; | |
| 50 std::vector<T*> ancestors2; | |
| 51 if (!GetAllTransientAncestors(*window1, &ancestors1) || | |
| 52 !GetAllTransientAncestors(*window2, &ancestors2)) { | |
| 53 return; | |
| 54 } | |
| 55 // Walk the two chains backwards and look for the first difference. | |
| 56 auto it1 = ancestors1.rbegin(); | |
| 57 auto it2 = ancestors2.rbegin(); | |
| 58 for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) { | |
| 59 if (*it1 != *it2) { | |
| 60 *window1 = *it1; | |
| 61 *window2 = *it2; | |
| 62 break; | |
| 63 } | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 template <class T> | |
| 68 bool AdjustStackingForTransientWindows(T** child, | |
| 69 T** target, | |
| 70 mojom::OrderDirection* direction, | |
| 71 T* stacking_target) { | |
| 72 if (stacking_target == *target) | |
| 73 return true; | |
| 74 | |
| 75 // For windows that have transient children stack the transient ancestors that | |
| 76 // are siblings. This prevents one transient group from being inserted in the | |
| 77 // middle of another. | |
| 78 FindCommonTransientAncestor(child, target); | |
| 79 | |
| 80 // When stacking above skip to the topmost transient descendant of the target. | |
| 81 if (*direction == mojom::OrderDirection::ABOVE && | |
| 82 !HasTransientAncestor(*child, *target)) { | |
| 83 const std::vector<T*>& siblings((*child)->parent()->children()); | |
| 84 size_t target_i = | |
| 85 std::find(siblings.begin(), siblings.end(), *target) - siblings.begin(); | |
| 86 while (target_i + 1 < siblings.size() && | |
| 87 HasTransientAncestor(siblings[target_i + 1], *target)) { | |
| 88 ++target_i; | |
| 89 } | |
| 90 *target = siblings[target_i]; | |
| 91 } | |
| 92 | |
| 93 return *child != *target; | |
| 94 } | |
| 95 | |
| 96 // Stacks transient descendants of |window| that are its siblings just above it. | |
| 97 // |GetStackingTarget| is a function that returns a marker associated with a | |
| 98 // Window that indicates the current Window being stacked. | |
| 99 // |Reorder| is a function that takes in two windows and orders the first | |
| 100 // relative to the second based on the provided OrderDirection. | |
| 101 template <class T> | |
| 102 void RestackTransientDescendants(T* window, | |
| 103 T** (*GetStackingTarget)(T*), | |
| 104 void (*Reorder)(T*, | |
| 105 T*, | |
| 106 mojom::OrderDirection)) { | |
| 107 T* parent = window->parent(); | |
| 108 if (!parent) | |
| 109 return; | |
| 110 | |
| 111 // stack any transient children that share the same parent to be in front of | |
| 112 // |window_|. the existing stacking order is preserved by iterating backwards | |
| 113 // and always stacking on top. | |
| 114 std::vector<T*> children(parent->children()); | |
| 115 for (auto it = children.rbegin(); it != children.rend(); ++it) { | |
| 116 if ((*it) != window && HasTransientAncestor(*it, window)) { | |
| 117 T* old_stacking_target = *GetStackingTarget(*it); | |
| 118 *GetStackingTarget(*it) = window; | |
| 119 Reorder(*it, window, mojom::OrderDirection::ABOVE); | |
| 120 *GetStackingTarget(*it) = old_stacking_target; | |
| 121 } | |
| 122 } | |
| 123 } | |
| 124 } // namespace mus | |
| 125 | |
| 126 #endif // COMPONENTS_MUS_COMMON_TRANSIENT_WINDOW_UTILS_H_ | |
| OLD | NEW |