OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/mus/ws/focus_controller.h" | 5 #include "components/mus/ws/focus_controller.h" |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "components/mus/public/interfaces/window_manager.mojom.h" | 8 #include "components/mus/public/interfaces/window_manager.mojom.h" |
9 #include "components/mus/ws/focus_controller_delegate.h" | 9 #include "components/mus/ws/focus_controller_delegate.h" |
10 #include "components/mus/ws/focus_controller_observer.h" | 10 #include "components/mus/ws/focus_controller_observer.h" |
11 #include "components/mus/ws/server_window.h" | 11 #include "components/mus/ws/server_window.h" |
12 #include "components/mus/ws/server_window_drawn_tracker.h" | 12 #include "components/mus/ws/server_window_drawn_tracker.h" |
13 | 13 |
14 namespace mus { | 14 namespace mus { |
15 namespace ws { | 15 namespace ws { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) { | 19 ServerWindow* GetDeepestFirstDescendant(ServerWindow* window) { |
sky
2016/01/05 16:42:38
Update function name to reflect new meaning.
| |
20 while (!window->children().empty()) | 20 while (!window->children().empty()) |
21 window = window->children()[0]; | 21 window = window->children().back(); |
22 return window; | 22 return window; |
23 } | 23 } |
24 | 24 |
25 // This can be used to iterate over each node in a rooted tree for the purpose | 25 // This can be used to iterate over each node in a rooted tree for the purpose |
26 // of shifting focus/activation. | 26 // of shifting focus/activation. |
27 class WindowTreeIterator { | 27 class WindowTreeIterator { |
28 public: | 28 public: |
29 explicit WindowTreeIterator(ServerWindow* root) : root_(root) {} | 29 explicit WindowTreeIterator(ServerWindow* root) : root_(root) {} |
30 ~WindowTreeIterator() {} | 30 ~WindowTreeIterator() {} |
31 | 31 |
32 ServerWindow* GetNext(ServerWindow* window) const { | 32 ServerWindow* GetNext(ServerWindow* window) const { |
33 if (window == root_ || window == nullptr) | 33 if (window == root_ || window == nullptr) |
34 return GetDeepestFirstDescendant(root_); | 34 return GetDeepestFirstDescendant(root_); |
35 | 35 |
36 // Return the next sibling. | 36 // Return the next sibling. |
37 ServerWindow* parent = window->parent(); | 37 ServerWindow* parent = window->parent(); |
38 if (parent) { | 38 if (parent) { |
39 const ServerWindow::Windows& siblings = parent->children(); | 39 const ServerWindow::Windows& siblings = parent->children(); |
40 ServerWindow::Windows::const_iterator iter = | 40 ServerWindow::Windows::const_reverse_iterator iter = |
41 std::find(siblings.begin(), siblings.end(), window); | 41 std::find(siblings.rbegin(), siblings.rend(), window); |
42 DCHECK(iter != siblings.end()); | 42 DCHECK(iter != siblings.rend()); |
43 ++iter; | 43 ++iter; |
44 if (iter != siblings.end()) | 44 if (iter != siblings.rend()) |
45 return GetDeepestFirstDescendant(*iter); | 45 return GetDeepestFirstDescendant(*iter); |
46 } | 46 } |
47 | 47 |
48 // All children and siblings have been explored. Next is the parent. | 48 // All children and siblings have been explored. Next is the parent. |
49 return parent; | 49 return parent; |
50 } | 50 } |
51 | 51 |
52 private: | 52 private: |
53 ServerWindow* root_; | 53 ServerWindow* root_; |
54 | 54 |
55 DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator); | 55 DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator); |
56 }; | 56 }; |
57 | 57 |
58 } // namespace | 58 } // namespace |
59 | 59 |
60 FocusController::FocusController(FocusControllerDelegate* delegate, | 60 FocusController::FocusController(FocusControllerDelegate* delegate, |
61 ServerWindow* root) | 61 ServerWindow* root) |
62 : delegate_(delegate), | 62 : delegate_(delegate), |
63 root_(root), | 63 root_(root), |
64 focused_window_(nullptr), | 64 focused_window_(nullptr), |
65 active_window_(nullptr) { | 65 active_window_(nullptr), |
66 activation_reason_(ActivationChangeReason::UNKNONW) { | |
66 DCHECK(delegate_); | 67 DCHECK(delegate_); |
67 DCHECK(root_); | 68 DCHECK(root_); |
68 } | 69 } |
69 | 70 |
70 FocusController::~FocusController() {} | 71 FocusController::~FocusController() {} |
71 | 72 |
72 void FocusController::SetFocusedWindow(ServerWindow* window) { | 73 void FocusController::SetFocusedWindow(ServerWindow* window) { |
73 if (GetFocusedWindow() == window) | 74 if (GetFocusedWindow() == window) |
74 return; | 75 return; |
75 | 76 |
76 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); | 77 SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); |
77 } | 78 } |
78 | 79 |
79 ServerWindow* FocusController::GetFocusedWindow() { | 80 ServerWindow* FocusController::GetFocusedWindow() { |
80 return focused_window_; | 81 return focused_window_; |
81 } | 82 } |
82 | 83 |
83 void FocusController::ActivateNextWindow() { | 84 void FocusController::ActivateNextWindow() { |
84 WindowTreeIterator iter(root_); | 85 WindowTreeIterator iter(root_); |
85 ServerWindow* activate = active_window_; | 86 ServerWindow* activate = active_window_; |
86 do { | 87 while (true) { |
87 activate = iter.GetNext(activate); | 88 activate = iter.GetNext(activate); |
88 } while (activate != active_window_ && !CanBeActivated(activate)); | 89 if (activation_reason_ == ActivationChangeReason::CYCLE) { |
89 SetActiveWindow(activate); | 90 if (activate == active_window_) { |
91 // We have cycled over all the activatable windows. Remove the oldest | |
92 // window that was cycled. | |
93 if (!cycle_windows_.empty()) { | |
94 cycle_windows_.erase(cycle_windows_.begin()); | |
95 continue; | |
96 } | |
97 } else if (std::find(cycle_windows_.begin(), cycle_windows_.end(), | |
98 activate->id()) != cycle_windows_.end()) { | |
99 // We are cycling between activated windows, and this window has already | |
100 // been through the cycle. So skip over it. | |
101 continue; | |
102 } | |
103 } | |
104 if (activate == active_window_ || CanBeActivated(activate)) | |
105 break; | |
106 } | |
107 SetActiveWindow(activate, ActivationChangeReason::CYCLE); | |
90 | 108 |
91 if (active_window_) { | 109 if (active_window_) { |
92 // Do not shift focus if the focused window already lives in the active | 110 // Do not shift focus if the focused window already lives in the active |
93 // window. | 111 // window. |
94 if (focused_window_ && active_window_->Contains(focused_window_)) | 112 if (focused_window_ && active_window_->Contains(focused_window_)) |
95 return; | 113 return; |
96 // Focus the first focusable window in the tree. | 114 // Focus the first focusable window in the tree. |
97 WindowTreeIterator iter(active_window_); | 115 WindowTreeIterator iter(active_window_); |
98 ServerWindow* focus = nullptr; | 116 ServerWindow* focus = nullptr; |
99 do { | 117 do { |
100 focus = iter.GetNext(focus); | 118 focus = iter.GetNext(focus); |
101 } while (focus != active_window_ && !CanBeFocused(focus)); | 119 } while (focus != active_window_ && !CanBeFocused(focus)); |
102 SetFocusedWindow(focus); | 120 SetFocusedWindow(focus); |
103 } else { | 121 } else { |
104 SetFocusedWindow(nullptr); | 122 SetFocusedWindow(nullptr); |
105 } | 123 } |
106 } | 124 } |
107 | 125 |
108 void FocusController::AddObserver(FocusControllerObserver* observer) { | 126 void FocusController::AddObserver(FocusControllerObserver* observer) { |
109 observers_.AddObserver(observer); | 127 observers_.AddObserver(observer); |
110 } | 128 } |
111 | 129 |
112 void FocusController::RemoveObserver(FocusControllerObserver* observer) { | 130 void FocusController::RemoveObserver(FocusControllerObserver* observer) { |
113 observers_.RemoveObserver(observer); | 131 observers_.RemoveObserver(observer); |
114 } | 132 } |
115 | 133 |
116 void FocusController::SetActiveWindow(ServerWindow* window) { | 134 void FocusController::SetActiveWindow(ServerWindow* window, |
135 ActivationChangeReason reason) { | |
117 DCHECK(!window || CanBeActivated(window)); | 136 DCHECK(!window || CanBeActivated(window)); |
118 if (active_window_ == window) | 137 if (active_window_ == window) |
119 return; | 138 return; |
139 if (reason != ActivationChangeReason::CYCLE) { | |
140 cycle_windows_.clear(); | |
141 } else if (activation_reason_ != ActivationChangeReason::CYCLE) { | |
142 DCHECK(cycle_windows_.empty()); | |
143 if (active_window_) | |
144 cycle_windows_.push_back(active_window_->id()); | |
145 } | |
146 | |
120 ServerWindow* old_active = active_window_; | 147 ServerWindow* old_active = active_window_; |
121 active_window_ = window; | 148 active_window_ = window; |
122 if (old_active != active_window_) { | 149 activation_reason_ = reason; |
123 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, | 150 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, |
124 OnActivationChanged(old_active, active_window_)); | 151 OnActivationChanged(old_active, active_window_)); |
125 } | 152 if (active_window_ && activation_reason_ == ActivationChangeReason::CYCLE) |
153 cycle_windows_.push_back(active_window_->id()); | |
126 } | 154 } |
127 | 155 |
128 bool FocusController::CanBeFocused(ServerWindow* window) const { | 156 bool FocusController::CanBeFocused(ServerWindow* window) const { |
129 // All ancestors of |window| must be drawn, and be focusable. | 157 // All ancestors of |window| must be drawn, and be focusable. |
130 for (ServerWindow* w = window; w; w = w->parent()) { | 158 for (ServerWindow* w = window; w; w = w->parent()) { |
131 if (!w->IsDrawn()) | 159 if (!w->IsDrawn()) |
132 return false; | 160 return false; |
133 if (!w->can_focus()) | 161 if (!w->can_focus()) |
134 return false; | 162 return false; |
135 } | 163 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
180 ServerWindow* window) { | 208 ServerWindow* window) { |
181 if (window && !CanBeFocused(window)) | 209 if (window && !CanBeFocused(window)) |
182 return; | 210 return; |
183 ServerWindow* old_focused = GetFocusedWindow(); | 211 ServerWindow* old_focused = GetFocusedWindow(); |
184 | 212 |
185 DCHECK(!window || window->IsDrawn()); | 213 DCHECK(!window || window->IsDrawn()); |
186 | 214 |
187 // Activate the closest activatable ancestor window. | 215 // Activate the closest activatable ancestor window. |
188 // TODO(sad): The window to activate doesn't necessarily have to be a direct | 216 // TODO(sad): The window to activate doesn't necessarily have to be a direct |
189 // ancestor (e.g. could be a transient parent). | 217 // ancestor (e.g. could be a transient parent). |
190 SetActiveWindow(GetActivatableAncestorOf(window)); | 218 SetActiveWindow(GetActivatableAncestorOf(window), |
219 ActivationChangeReason::FOCUS); | |
191 | 220 |
192 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, | 221 FOR_EACH_OBSERVER(FocusControllerObserver, observers_, |
193 OnFocusChanged(change_source, old_focused, window)); | 222 OnFocusChanged(change_source, old_focused, window)); |
194 | 223 |
195 focused_window_ = window; | 224 focused_window_ = window; |
196 // We can currently use only a single ServerWindowDrawnTracker since focused | 225 // We can currently use only a single ServerWindowDrawnTracker since focused |
197 // window is expected to be a direct descendant of the active window. | 226 // window is expected to be a direct descendant of the active window. |
198 if (focused_window_ && active_window_) { | 227 if (focused_window_ && active_window_) { |
199 DCHECK(active_window_->Contains(focused_window_)); | 228 DCHECK(active_window_->Contains(focused_window_)); |
200 } | 229 } |
(...skipping 21 matching lines...) Expand all Loading... | |
222 // that does not belong to the subtree which is getting hidden. | 251 // that does not belong to the subtree which is getting hidden. |
223 if (window == active_window_) { | 252 if (window == active_window_) { |
224 WindowTreeIterator iter(root_); | 253 WindowTreeIterator iter(root_); |
225 ServerWindow* activate = active_window_; | 254 ServerWindow* activate = active_window_; |
226 do { | 255 do { |
227 activate = iter.GetNext(activate); | 256 activate = iter.GetNext(activate); |
228 } while (activate != active_window_ && | 257 } while (activate != active_window_ && |
229 (will_be_hidden(activate) || !CanBeActivated(activate))); | 258 (will_be_hidden(activate) || !CanBeActivated(activate))); |
230 if (activate == window) | 259 if (activate == window) |
231 activate = nullptr; | 260 activate = nullptr; |
232 SetActiveWindow(activate); | 261 SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED); |
233 | 262 |
234 // Now make sure focus is in the active window. | 263 // Now make sure focus is in the active window. |
235 ServerWindow* focus = nullptr; | 264 ServerWindow* focus = nullptr; |
236 if (active_window_) { | 265 if (active_window_) { |
237 WindowTreeIterator iter(active_window_); | 266 WindowTreeIterator iter(active_window_); |
238 focus = nullptr; | 267 focus = nullptr; |
239 do { | 268 do { |
240 focus = iter.GetNext(focus); | 269 focus = iter.GetNext(focus); |
241 } while (focus != active_window_ && | 270 } while (focus != active_window_ && |
242 (will_be_hidden(focus) || !CanBeFocused(focus))); | 271 (will_be_hidden(focus) || !CanBeFocused(focus))); |
(...skipping 18 matching lines...) Expand all Loading... | |
261 } | 290 } |
262 | 291 |
263 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, | 292 void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, |
264 ServerWindow* window, | 293 ServerWindow* window, |
265 bool is_drawn) { | 294 bool is_drawn) { |
266 DCHECK(false); | 295 DCHECK(false); |
267 } | 296 } |
268 | 297 |
269 } // namespace ws | 298 } // namespace ws |
270 } // namespace mus | 299 } // namespace mus |
OLD | NEW |