| 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 |