1 // Copyright (c) 2013 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.
5 #include "ui/wm/core/transient_window_stacking_client.h"
9 #include "ui/wm/core/transient_window_manager.h"
10 #include "ui/wm/core/window_util.h"
18 // Populates |ancestors| with all transient ancestors of |window| that are
19 // siblings of |window|. Returns true if any ancestors were found, false if not.
20 bool GetAllTransientAncestors(Window
* window
, Window::Windows
* ancestors
) {
21 Window
* parent
= window
->parent();
22 for (; window
; window
= GetTransientParent(window
)) {
23 if (window
->parent() == parent
)
24 ancestors
->push_back(window
);
26 return (!ancestors
->empty());
29 // Replaces |window1| and |window2| with their possible transient ancestors that
30 // are still siblings (have a common transient parent). |window1| and |window2|
31 // are not modified if such ancestors cannot be found.
32 void FindCommonTransientAncestor(Window
** window1
, Window
** window2
) {
37 // Assemble chains of ancestors of both windows.
38 Window::Windows ancestors1
;
39 Window::Windows ancestors2
;
40 if (!GetAllTransientAncestors(*window1
, &ancestors1
) ||
41 !GetAllTransientAncestors(*window2
, &ancestors2
)) {
44 // Walk the two chains backwards and look for the first difference.
45 Window::Windows::reverse_iterator it1
= ancestors1
.rbegin();
46 Window::Windows::reverse_iterator it2
= ancestors2
.rbegin();
47 for (; it1
!= ancestors1
.rend() && it2
!= ancestors2
.rend(); ++it1
, ++it2
) {
59 TransientWindowStackingClient
* TransientWindowStackingClient::instance_
= NULL
;
61 TransientWindowStackingClient::TransientWindowStackingClient() {
65 TransientWindowStackingClient::~TransientWindowStackingClient() {
66 if (instance_
== this)
70 bool TransientWindowStackingClient::AdjustStacking(
73 Window::StackDirection
* direction
) {
74 const TransientWindowManager
* transient_manager
=
75 TransientWindowManager::Get(static_cast<const Window
*>(*child
));
76 if (transient_manager
&& transient_manager
->IsStackingTransient(*target
))
79 // For windows that have transient children stack the transient ancestors that
80 // are siblings. This prevents one transient group from being inserted in the
82 FindCommonTransientAncestor(child
, target
);
84 // When stacking above skip to the topmost transient descendant of the target.
85 if (*direction
== Window::STACK_ABOVE
&&
86 !HasTransientAncestor(*child
, *target
)) {
87 const Window::Windows
& siblings((*child
)->parent()->children());
89 std::find(siblings
.begin(), siblings
.end(), *target
) - siblings
.begin();
90 while (target_i
+ 1 < siblings
.size() &&
91 HasTransientAncestor(siblings
[target_i
+ 1], *target
)) {
94 *target
= siblings
[target_i
];
97 // If we couldn't find a valid target position, don't move anything.
98 if (*direction
== Window::STACK_ABOVE
&&
99 ((*target
)->layer() && (*target
)->layer()->delegate() == NULL
)) {
103 return *child
!= *target
;