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 #include "components/mus/ws/focus_controller.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include "base/macros.h" | |
11 #include "components/mus/ws/focus_controller_delegate.h" | |
12 #include "components/mus/ws/focus_controller_observer.h" | |
13 #include "components/mus/ws/server_window.h" | |
14 #include "components/mus/ws/test_server_window_delegate.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace mus { | |
18 | |
19 namespace ws { | |
20 namespace { | |
21 | |
22 const char kDisallowActiveChildren[] = "disallow-active-children"; | |
23 | |
24 class TestFocusControllerObserver : public FocusControllerObserver, | |
25 public FocusControllerDelegate { | |
26 public: | |
27 TestFocusControllerObserver() | |
28 : ignore_explicit_(true), | |
29 focus_change_count_(0u), | |
30 old_focused_window_(nullptr), | |
31 new_focused_window_(nullptr), | |
32 old_active_window_(nullptr), | |
33 new_active_window_(nullptr) {} | |
34 | |
35 void ClearAll() { | |
36 focus_change_count_ = 0u; | |
37 old_focused_window_ = nullptr; | |
38 new_focused_window_ = nullptr; | |
39 old_active_window_ = nullptr; | |
40 new_active_window_ = nullptr; | |
41 } | |
42 size_t focus_change_count() const { return focus_change_count_; } | |
43 ServerWindow* old_focused_window() { return old_focused_window_; } | |
44 ServerWindow* new_focused_window() { return new_focused_window_; } | |
45 | |
46 ServerWindow* old_active_window() { return old_active_window_; } | |
47 ServerWindow* new_active_window() { return new_active_window_; } | |
48 | |
49 void set_ignore_explicit(bool ignore) { ignore_explicit_ = ignore; } | |
50 | |
51 private: | |
52 // FocusControllerDelegate: | |
53 bool CanHaveActiveChildren(ServerWindow* window) const override { | |
54 return !window || window->properties().count(kDisallowActiveChildren) == 0; | |
55 } | |
56 // FocusControllerObserver: | |
57 void OnActivationChanged(ServerWindow* old_active_window, | |
58 ServerWindow* new_active_window) override { | |
59 old_active_window_ = old_active_window; | |
60 new_active_window_ = new_active_window; | |
61 } | |
62 void OnFocusChanged(FocusControllerChangeSource source, | |
63 ServerWindow* old_focused_window, | |
64 ServerWindow* new_focused_window) override { | |
65 if (ignore_explicit_ && source == FocusControllerChangeSource::EXPLICIT) | |
66 return; | |
67 | |
68 focus_change_count_++; | |
69 old_focused_window_ = old_focused_window; | |
70 new_focused_window_ = new_focused_window; | |
71 } | |
72 | |
73 bool ignore_explicit_; | |
74 size_t focus_change_count_; | |
75 ServerWindow* old_focused_window_; | |
76 ServerWindow* new_focused_window_; | |
77 ServerWindow* old_active_window_; | |
78 ServerWindow* new_active_window_; | |
79 | |
80 DISALLOW_COPY_AND_ASSIGN(TestFocusControllerObserver); | |
81 }; | |
82 | |
83 } // namespace | |
84 | |
85 TEST(FocusControllerTest, Basic) { | |
86 TestServerWindowDelegate server_window_delegate; | |
87 ServerWindow root(&server_window_delegate, WindowId()); | |
88 server_window_delegate.set_root_window(&root); | |
89 root.SetVisible(true); | |
90 ServerWindow child(&server_window_delegate, WindowId()); | |
91 child.SetVisible(true); | |
92 root.Add(&child); | |
93 ServerWindow child_child(&server_window_delegate, WindowId()); | |
94 child_child.SetVisible(true); | |
95 child.Add(&child_child); | |
96 | |
97 TestFocusControllerObserver focus_observer; | |
98 FocusController focus_controller(&focus_observer, &root); | |
99 focus_controller.AddObserver(&focus_observer); | |
100 | |
101 focus_controller.SetFocusedWindow(&child_child); | |
102 EXPECT_EQ(0u, focus_observer.focus_change_count()); | |
103 | |
104 // Remove the ancestor of the focused window, focus should go to the |root|. | |
105 root.Remove(&child); | |
106 EXPECT_EQ(1u, focus_observer.focus_change_count()); | |
107 EXPECT_EQ(&root, focus_observer.new_focused_window()); | |
108 EXPECT_EQ(&child_child, focus_observer.old_focused_window()); | |
109 focus_observer.ClearAll(); | |
110 | |
111 // Make the focused window invisible. Focus is lost in this case (as no one | |
112 // to give focus to). | |
113 root.SetVisible(false); | |
114 EXPECT_EQ(1u, focus_observer.focus_change_count()); | |
115 EXPECT_EQ(nullptr, focus_observer.new_focused_window()); | |
116 EXPECT_EQ(&root, focus_observer.old_focused_window()); | |
117 focus_observer.ClearAll(); | |
118 | |
119 // Go back to initial state and focus |child_child|. | |
120 root.SetVisible(true); | |
121 root.Add(&child); | |
122 focus_controller.SetFocusedWindow(&child_child); | |
123 EXPECT_EQ(0u, focus_observer.focus_change_count()); | |
124 | |
125 // Hide the focused window, focus should go to parent. | |
126 child_child.SetVisible(false); | |
127 EXPECT_EQ(1u, focus_observer.focus_change_count()); | |
128 EXPECT_EQ(&child, focus_observer.new_focused_window()); | |
129 EXPECT_EQ(&child_child, focus_observer.old_focused_window()); | |
130 focus_observer.ClearAll(); | |
131 | |
132 child_child.SetVisible(true); | |
133 focus_controller.SetFocusedWindow(&child_child); | |
134 EXPECT_EQ(0u, focus_observer.focus_change_count()); | |
135 | |
136 // Hide the parent of the focused window. | |
137 child.SetVisible(false); | |
138 EXPECT_EQ(1u, focus_observer.focus_change_count()); | |
139 EXPECT_EQ(&root, focus_observer.new_focused_window()); | |
140 EXPECT_EQ(&child_child, focus_observer.old_focused_window()); | |
141 focus_observer.ClearAll(); | |
142 focus_controller.RemoveObserver(&focus_observer); | |
143 } | |
144 | |
145 // Tests that focus shifts correctly if the focused window is destroyed. | |
146 TEST(FocusControllerTest, FocusShiftsOnDestroy) { | |
147 TestServerWindowDelegate server_window_delegate; | |
148 ServerWindow parent(&server_window_delegate, WindowId()); | |
149 server_window_delegate.set_root_window(&parent); | |
150 parent.SetVisible(true); | |
151 ServerWindow child_first(&server_window_delegate, WindowId()); | |
152 child_first.SetVisible(true); | |
153 parent.Add(&child_first); | |
154 std::unique_ptr<ServerWindow> child_second( | |
155 new ServerWindow(&server_window_delegate, WindowId())); | |
156 child_second->SetVisible(true); | |
157 parent.Add(child_second.get()); | |
158 std::vector<uint8_t> dummy; | |
159 // Allow only |parent| to be activated. | |
160 parent.SetProperty(kDisallowActiveChildren, &dummy); | |
161 | |
162 TestFocusControllerObserver focus_observer; | |
163 focus_observer.set_ignore_explicit(false); | |
164 FocusController focus_controller(&focus_observer, &parent); | |
165 focus_controller.AddObserver(&focus_observer); | |
166 | |
167 focus_controller.ActivateNextWindow(); | |
168 EXPECT_EQ(nullptr, focus_observer.old_active_window()); | |
169 EXPECT_EQ(&parent, focus_observer.new_active_window()); | |
170 EXPECT_EQ(nullptr, focus_observer.old_focused_window()); | |
171 EXPECT_EQ(child_second.get(), focus_observer.new_focused_window()); | |
172 focus_observer.ClearAll(); | |
173 | |
174 // Destroying |child_second| should move focus to |child_first|. | |
175 child_second.reset(); | |
176 EXPECT_NE(nullptr, focus_observer.old_focused_window()); | |
177 EXPECT_EQ(&child_first, focus_observer.new_focused_window()); | |
178 | |
179 focus_controller.RemoveObserver(&focus_observer); | |
180 } | |
181 | |
182 TEST(FocusControllerTest, ActivationSkipsOverHiddenWindow) { | |
183 TestServerWindowDelegate server_window_delegate; | |
184 ServerWindow parent(&server_window_delegate, WindowId()); | |
185 server_window_delegate.set_root_window(&parent); | |
186 parent.SetVisible(true); | |
187 | |
188 ServerWindow child_first(&server_window_delegate, WindowId()); | |
189 ServerWindow child_second(&server_window_delegate, WindowId()); | |
190 ServerWindow child_third(&server_window_delegate, WindowId()); | |
191 | |
192 parent.Add(&child_first); | |
193 parent.Add(&child_second); | |
194 parent.Add(&child_third); | |
195 | |
196 child_first.SetVisible(true); | |
197 child_second.SetVisible(false); | |
198 child_third.SetVisible(true); | |
199 | |
200 TestFocusControllerObserver focus_observer; | |
201 focus_observer.set_ignore_explicit(false); | |
202 FocusController focus_controller(&focus_observer, &parent); | |
203 focus_controller.AddObserver(&focus_observer); | |
204 | |
205 // Since |child_second| is invisible, activation should cycle from | |
206 // |child_third|, to |child_first|, to |parent|, back to |child_third|. | |
207 focus_controller.ActivateNextWindow(); | |
208 EXPECT_EQ(nullptr, focus_observer.old_active_window()); | |
209 EXPECT_EQ(&child_third, focus_observer.new_active_window()); | |
210 focus_observer.ClearAll(); | |
211 | |
212 focus_controller.ActivateNextWindow(); | |
213 EXPECT_EQ(&child_third, focus_observer.old_active_window()); | |
214 EXPECT_EQ(&child_first, focus_observer.new_active_window()); | |
215 focus_observer.ClearAll(); | |
216 | |
217 focus_controller.ActivateNextWindow(); | |
218 EXPECT_EQ(&child_first, focus_observer.old_active_window()); | |
219 EXPECT_EQ(&parent, focus_observer.new_active_window()); | |
220 focus_observer.ClearAll(); | |
221 | |
222 focus_controller.ActivateNextWindow(); | |
223 EXPECT_EQ(&parent, focus_observer.old_active_window()); | |
224 EXPECT_EQ(&child_third, focus_observer.new_active_window()); | |
225 focus_observer.ClearAll(); | |
226 | |
227 // Once |child_second| is made visible, activation should go from | |
228 // |child_third| to |child_second|. | |
229 child_second.SetVisible(true); | |
230 focus_controller.ActivateNextWindow(); | |
231 EXPECT_EQ(&child_third, focus_observer.old_active_window()); | |
232 EXPECT_EQ(&child_second, focus_observer.new_active_window()); | |
233 } | |
234 | |
235 TEST(FocusControllerTest, ActivationSkipsOverHiddenContainers) { | |
236 TestServerWindowDelegate server_window_delegate; | |
237 ServerWindow parent(&server_window_delegate, WindowId()); | |
238 server_window_delegate.set_root_window(&parent); | |
239 parent.SetVisible(true); | |
240 | |
241 ServerWindow child1(&server_window_delegate, WindowId()); | |
242 ServerWindow child2(&server_window_delegate, WindowId()); | |
243 | |
244 parent.Add(&child1); | |
245 parent.Add(&child2); | |
246 | |
247 child1.SetVisible(true); | |
248 child2.SetVisible(true); | |
249 | |
250 ServerWindow child11(&server_window_delegate, WindowId()); | |
251 ServerWindow child12(&server_window_delegate, WindowId()); | |
252 ServerWindow child21(&server_window_delegate, WindowId()); | |
253 ServerWindow child22(&server_window_delegate, WindowId()); | |
254 | |
255 child1.Add(&child11); | |
256 child1.Add(&child12); | |
257 child2.Add(&child21); | |
258 child2.Add(&child22); | |
259 | |
260 child11.SetVisible(true); | |
261 child12.SetVisible(true); | |
262 child21.SetVisible(true); | |
263 child22.SetVisible(true); | |
264 | |
265 TestFocusControllerObserver focus_observer; | |
266 FocusController focus_controller(&focus_observer, &parent); | |
267 focus_controller.AddObserver(&focus_observer); | |
268 | |
269 focus_controller.ActivateNextWindow(); | |
270 EXPECT_EQ(nullptr, focus_observer.old_active_window()); | |
271 EXPECT_EQ(&child22, focus_observer.new_active_window()); | |
272 focus_observer.ClearAll(); | |
273 | |
274 child2.SetVisible(false); | |
275 EXPECT_EQ(&child22, focus_observer.old_active_window()); | |
276 EXPECT_EQ(&child12, focus_observer.new_active_window()); | |
277 } | |
278 | |
279 TEST(FocusControllerTest, NonFocusableWindowNotActivated) { | |
280 TestServerWindowDelegate server_window_delegate; | |
281 ServerWindow parent(&server_window_delegate, WindowId()); | |
282 server_window_delegate.set_root_window(&parent); | |
283 parent.SetVisible(true); | |
284 | |
285 ServerWindow child_first(&server_window_delegate, WindowId()); | |
286 ServerWindow child_second(&server_window_delegate, WindowId()); | |
287 parent.Add(&child_first); | |
288 parent.Add(&child_second); | |
289 child_first.SetVisible(true); | |
290 child_second.SetVisible(true); | |
291 | |
292 TestFocusControllerObserver focus_observer; | |
293 focus_observer.set_ignore_explicit(false); | |
294 FocusController focus_controller(&focus_observer, &parent); | |
295 focus_controller.AddObserver(&focus_observer); | |
296 | |
297 child_first.set_can_focus(false); | |
298 | |
299 // |child_second| is activated first, but then activation skips over | |
300 // |child_first| and goes to |parent| instead. | |
301 focus_controller.ActivateNextWindow(); | |
302 EXPECT_EQ(nullptr, focus_observer.old_active_window()); | |
303 EXPECT_EQ(&child_second, focus_observer.new_active_window()); | |
304 focus_observer.ClearAll(); | |
305 | |
306 focus_controller.ActivateNextWindow(); | |
307 EXPECT_EQ(&child_second, focus_observer.old_active_window()); | |
308 EXPECT_EQ(&parent, focus_observer.new_active_window()); | |
309 } | |
310 | |
311 } // namespace ws | |
312 } // namespace mus | |
OLD | NEW |