| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "ui/views/focus/focus_manager.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/command_line.h" | |
| 11 #include "base/strings/utf_string_conversions.h" | |
| 12 #include "ui/aura/client/focus_client.h" | |
| 13 #include "ui/aura/window.h" | |
| 14 #include "ui/base/accelerators/accelerator.h" | |
| 15 #include "ui/base/ime/dummy_text_input_client.h" | |
| 16 #include "ui/base/ime/text_input_focus_manager.h" | |
| 17 #include "ui/base/ui_base_switches.h" | |
| 18 #include "ui/events/keycodes/keyboard_codes.h" | |
| 19 #include "ui/views/accessible_pane_view.h" | |
| 20 #include "ui/views/controls/button/label_button.h" | |
| 21 #include "ui/views/focus/focus_manager_factory.h" | |
| 22 #include "ui/views/focus/widget_focus_manager.h" | |
| 23 #include "ui/views/test/focus_manager_test.h" | |
| 24 #include "ui/views/widget/widget.h" | |
| 25 | |
| 26 namespace views { | |
| 27 | |
| 28 enum FocusTestEventType { | |
| 29 ON_FOCUS = 0, | |
| 30 ON_BLUR | |
| 31 }; | |
| 32 | |
| 33 struct FocusTestEvent { | |
| 34 FocusTestEvent(FocusTestEventType type, int view_id) | |
| 35 : type(type), | |
| 36 view_id(view_id) { | |
| 37 } | |
| 38 | |
| 39 FocusTestEventType type; | |
| 40 int view_id; | |
| 41 }; | |
| 42 | |
| 43 class SimpleTestView : public View { | |
| 44 public: | |
| 45 SimpleTestView(std::vector<FocusTestEvent>* event_list, int view_id) | |
| 46 : event_list_(event_list) { | |
| 47 SetFocusable(true); | |
| 48 set_id(view_id); | |
| 49 } | |
| 50 | |
| 51 virtual void OnFocus() override { | |
| 52 event_list_->push_back(FocusTestEvent(ON_FOCUS, id())); | |
| 53 } | |
| 54 | |
| 55 virtual void OnBlur() override { | |
| 56 event_list_->push_back(FocusTestEvent(ON_BLUR, id())); | |
| 57 } | |
| 58 | |
| 59 private: | |
| 60 std::vector<FocusTestEvent>* event_list_; | |
| 61 | |
| 62 DISALLOW_COPY_AND_ASSIGN(SimpleTestView); | |
| 63 }; | |
| 64 | |
| 65 // Tests that the appropriate Focus related methods are called when a View | |
| 66 // gets/loses focus. | |
| 67 TEST_F(FocusManagerTest, ViewFocusCallbacks) { | |
| 68 std::vector<FocusTestEvent> event_list; | |
| 69 const int kView1ID = 1; | |
| 70 const int kView2ID = 2; | |
| 71 | |
| 72 SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID); | |
| 73 SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID); | |
| 74 GetContentsView()->AddChildView(view1); | |
| 75 GetContentsView()->AddChildView(view2); | |
| 76 | |
| 77 view1->RequestFocus(); | |
| 78 ASSERT_EQ(1, static_cast<int>(event_list.size())); | |
| 79 EXPECT_EQ(ON_FOCUS, event_list[0].type); | |
| 80 EXPECT_EQ(kView1ID, event_list[0].view_id); | |
| 81 | |
| 82 event_list.clear(); | |
| 83 view2->RequestFocus(); | |
| 84 ASSERT_EQ(2, static_cast<int>(event_list.size())); | |
| 85 EXPECT_EQ(ON_BLUR, event_list[0].type); | |
| 86 EXPECT_EQ(kView1ID, event_list[0].view_id); | |
| 87 EXPECT_EQ(ON_FOCUS, event_list[1].type); | |
| 88 EXPECT_EQ(kView2ID, event_list[1].view_id); | |
| 89 | |
| 90 event_list.clear(); | |
| 91 GetFocusManager()->ClearFocus(); | |
| 92 ASSERT_EQ(1, static_cast<int>(event_list.size())); | |
| 93 EXPECT_EQ(ON_BLUR, event_list[0].type); | |
| 94 EXPECT_EQ(kView2ID, event_list[0].view_id); | |
| 95 } | |
| 96 | |
| 97 TEST_F(FocusManagerTest, FocusChangeListener) { | |
| 98 View* view1 = new View(); | |
| 99 view1->SetFocusable(true); | |
| 100 View* view2 = new View(); | |
| 101 view2->SetFocusable(true); | |
| 102 GetContentsView()->AddChildView(view1); | |
| 103 GetContentsView()->AddChildView(view2); | |
| 104 | |
| 105 TestFocusChangeListener listener; | |
| 106 AddFocusChangeListener(&listener); | |
| 107 | |
| 108 // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/det
ails/520043/error-converting-from-null-to-a-pointer-type-in-std-pair | |
| 109 views::View* null_view = NULL; | |
| 110 | |
| 111 view1->RequestFocus(); | |
| 112 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); | |
| 113 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view1)); | |
| 114 listener.ClearFocusChanges(); | |
| 115 | |
| 116 view2->RequestFocus(); | |
| 117 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); | |
| 118 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2)); | |
| 119 listener.ClearFocusChanges(); | |
| 120 | |
| 121 GetFocusManager()->ClearFocus(); | |
| 122 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); | |
| 123 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view)); | |
| 124 } | |
| 125 | |
| 126 TEST_F(FocusManagerTest, WidgetFocusChangeListener) { | |
| 127 TestWidgetFocusChangeListener widget_listener; | |
| 128 AddWidgetFocusChangeListener(&widget_listener); | |
| 129 | |
| 130 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 131 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 132 params.bounds = gfx::Rect(10, 10, 100, 100); | |
| 133 params.parent = GetWidget()->GetNativeView(); | |
| 134 | |
| 135 scoped_ptr<Widget> widget1(new Widget); | |
| 136 widget1->Init(params); | |
| 137 widget1->Show(); | |
| 138 | |
| 139 scoped_ptr<Widget> widget2(new Widget); | |
| 140 widget2->Init(params); | |
| 141 widget2->Show(); | |
| 142 | |
| 143 widget_listener.ClearFocusChanges(); | |
| 144 gfx::NativeView native_view1 = widget1->GetNativeView(); | |
| 145 aura::client::GetFocusClient(native_view1)->FocusWindow(native_view1); | |
| 146 ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size())); | |
| 147 EXPECT_EQ(native_view1, widget_listener.focus_changes()[0].second); | |
| 148 EXPECT_EQ(native_view1, widget_listener.focus_changes()[1].second); | |
| 149 | |
| 150 widget_listener.ClearFocusChanges(); | |
| 151 gfx::NativeView native_view2 = widget2->GetNativeView(); | |
| 152 aura::client::GetFocusClient(native_view2)->FocusWindow(native_view2); | |
| 153 ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size())); | |
| 154 EXPECT_EQ(NativeViewPair(native_view1, native_view2), | |
| 155 widget_listener.focus_changes()[0]); | |
| 156 EXPECT_EQ(NativeViewPair(native_view1, native_view2), | |
| 157 widget_listener.focus_changes()[1]); | |
| 158 } | |
| 159 | |
| 160 // Counts accelerator calls. | |
| 161 class TestAcceleratorTarget : public ui::AcceleratorTarget { | |
| 162 public: | |
| 163 explicit TestAcceleratorTarget(bool process_accelerator) | |
| 164 : accelerator_count_(0), | |
| 165 process_accelerator_(process_accelerator), | |
| 166 can_handle_accelerators_(true) {} | |
| 167 | |
| 168 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) override { | |
| 169 ++accelerator_count_; | |
| 170 return process_accelerator_; | |
| 171 } | |
| 172 | |
| 173 virtual bool CanHandleAccelerators() const override { | |
| 174 return can_handle_accelerators_; | |
| 175 } | |
| 176 | |
| 177 int accelerator_count() const { return accelerator_count_; } | |
| 178 | |
| 179 void set_can_handle_accelerators(bool can_handle_accelerators) { | |
| 180 can_handle_accelerators_ = can_handle_accelerators; | |
| 181 } | |
| 182 | |
| 183 private: | |
| 184 int accelerator_count_; // number of times that the accelerator is activated | |
| 185 bool process_accelerator_; // return value of AcceleratorPressed | |
| 186 bool can_handle_accelerators_; // return value of CanHandleAccelerators | |
| 187 | |
| 188 DISALLOW_COPY_AND_ASSIGN(TestAcceleratorTarget); | |
| 189 }; | |
| 190 | |
| 191 TEST_F(FocusManagerTest, CallsNormalAcceleratorTarget) { | |
| 192 FocusManager* focus_manager = GetFocusManager(); | |
| 193 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); | |
| 194 ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE); | |
| 195 | |
| 196 TestAcceleratorTarget return_target(true); | |
| 197 TestAcceleratorTarget escape_target(true); | |
| 198 EXPECT_EQ(return_target.accelerator_count(), 0); | |
| 199 EXPECT_EQ(escape_target.accelerator_count(), 0); | |
| 200 EXPECT_EQ(NULL, | |
| 201 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 202 EXPECT_EQ(NULL, | |
| 203 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 204 | |
| 205 // Register targets. | |
| 206 focus_manager->RegisterAccelerator(return_accelerator, | |
| 207 ui::AcceleratorManager::kNormalPriority, | |
| 208 &return_target); | |
| 209 focus_manager->RegisterAccelerator(escape_accelerator, | |
| 210 ui::AcceleratorManager::kNormalPriority, | |
| 211 &escape_target); | |
| 212 | |
| 213 // Checks if the correct target is registered. | |
| 214 EXPECT_EQ(&return_target, | |
| 215 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 216 EXPECT_EQ(&escape_target, | |
| 217 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 218 | |
| 219 // Hitting the return key. | |
| 220 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 221 EXPECT_EQ(return_target.accelerator_count(), 1); | |
| 222 EXPECT_EQ(escape_target.accelerator_count(), 0); | |
| 223 | |
| 224 // Hitting the escape key. | |
| 225 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 226 EXPECT_EQ(return_target.accelerator_count(), 1); | |
| 227 EXPECT_EQ(escape_target.accelerator_count(), 1); | |
| 228 | |
| 229 // Register another target for the return key. | |
| 230 TestAcceleratorTarget return_target2(true); | |
| 231 EXPECT_EQ(return_target2.accelerator_count(), 0); | |
| 232 focus_manager->RegisterAccelerator(return_accelerator, | |
| 233 ui::AcceleratorManager::kNormalPriority, | |
| 234 &return_target2); | |
| 235 EXPECT_EQ(&return_target2, | |
| 236 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 237 | |
| 238 // Hitting the return key; return_target2 has the priority. | |
| 239 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 240 EXPECT_EQ(return_target.accelerator_count(), 1); | |
| 241 EXPECT_EQ(return_target2.accelerator_count(), 1); | |
| 242 | |
| 243 // Register a target that does not process the accelerator event. | |
| 244 TestAcceleratorTarget return_target3(false); | |
| 245 EXPECT_EQ(return_target3.accelerator_count(), 0); | |
| 246 focus_manager->RegisterAccelerator(return_accelerator, | |
| 247 ui::AcceleratorManager::kNormalPriority, | |
| 248 &return_target3); | |
| 249 EXPECT_EQ(&return_target3, | |
| 250 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 251 | |
| 252 // Hitting the return key. | |
| 253 // Since the event handler of return_target3 returns false, return_target2 | |
| 254 // should be called too. | |
| 255 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 256 EXPECT_EQ(return_target.accelerator_count(), 1); | |
| 257 EXPECT_EQ(return_target2.accelerator_count(), 2); | |
| 258 EXPECT_EQ(return_target3.accelerator_count(), 1); | |
| 259 | |
| 260 // Unregister return_target2. | |
| 261 focus_manager->UnregisterAccelerator(return_accelerator, &return_target2); | |
| 262 EXPECT_EQ(&return_target3, | |
| 263 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 264 | |
| 265 // Hitting the return key. return_target3 and return_target should be called. | |
| 266 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 267 EXPECT_EQ(return_target.accelerator_count(), 2); | |
| 268 EXPECT_EQ(return_target2.accelerator_count(), 2); | |
| 269 EXPECT_EQ(return_target3.accelerator_count(), 2); | |
| 270 | |
| 271 // Unregister targets. | |
| 272 focus_manager->UnregisterAccelerator(return_accelerator, &return_target); | |
| 273 focus_manager->UnregisterAccelerator(return_accelerator, &return_target3); | |
| 274 focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target); | |
| 275 | |
| 276 // Now there is no target registered. | |
| 277 EXPECT_EQ(NULL, | |
| 278 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 279 EXPECT_EQ(NULL, | |
| 280 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 281 | |
| 282 // Hitting the return key and the escape key. Nothing should happen. | |
| 283 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 284 EXPECT_EQ(return_target.accelerator_count(), 2); | |
| 285 EXPECT_EQ(return_target2.accelerator_count(), 2); | |
| 286 EXPECT_EQ(return_target3.accelerator_count(), 2); | |
| 287 EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 288 EXPECT_EQ(escape_target.accelerator_count(), 1); | |
| 289 } | |
| 290 | |
| 291 TEST_F(FocusManagerTest, HighPriorityHandlers) { | |
| 292 FocusManager* focus_manager = GetFocusManager(); | |
| 293 ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE); | |
| 294 | |
| 295 TestAcceleratorTarget escape_target_high(true); | |
| 296 TestAcceleratorTarget escape_target_normal(true); | |
| 297 EXPECT_EQ(escape_target_high.accelerator_count(), 0); | |
| 298 EXPECT_EQ(escape_target_normal.accelerator_count(), 0); | |
| 299 EXPECT_EQ(NULL, | |
| 300 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 301 EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 302 | |
| 303 // Register high priority target. | |
| 304 focus_manager->RegisterAccelerator(escape_accelerator, | |
| 305 ui::AcceleratorManager::kHighPriority, | |
| 306 &escape_target_high); | |
| 307 EXPECT_EQ(&escape_target_high, | |
| 308 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 309 EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 310 | |
| 311 // Hit the escape key. | |
| 312 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 313 EXPECT_EQ(escape_target_high.accelerator_count(), 1); | |
| 314 EXPECT_EQ(escape_target_normal.accelerator_count(), 0); | |
| 315 | |
| 316 // Add a normal priority target and make sure it doesn't see the key. | |
| 317 focus_manager->RegisterAccelerator(escape_accelerator, | |
| 318 ui::AcceleratorManager::kNormalPriority, | |
| 319 &escape_target_normal); | |
| 320 | |
| 321 // Checks if the correct target is registered (same as before, the high | |
| 322 // priority one). | |
| 323 EXPECT_EQ(&escape_target_high, | |
| 324 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 325 EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 326 | |
| 327 // Hit the escape key. | |
| 328 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 329 EXPECT_EQ(escape_target_high.accelerator_count(), 2); | |
| 330 EXPECT_EQ(escape_target_normal.accelerator_count(), 0); | |
| 331 | |
| 332 // Unregister the high priority accelerator. | |
| 333 focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target_high); | |
| 334 EXPECT_EQ(&escape_target_normal, | |
| 335 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 336 EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 337 | |
| 338 // Hit the escape key. | |
| 339 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 340 EXPECT_EQ(escape_target_high.accelerator_count(), 2); | |
| 341 EXPECT_EQ(escape_target_normal.accelerator_count(), 1); | |
| 342 | |
| 343 // Add the high priority target back and make sure it starts seeing the key. | |
| 344 focus_manager->RegisterAccelerator(escape_accelerator, | |
| 345 ui::AcceleratorManager::kHighPriority, | |
| 346 &escape_target_high); | |
| 347 EXPECT_EQ(&escape_target_high, | |
| 348 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 349 EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 350 | |
| 351 // Hit the escape key. | |
| 352 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 353 EXPECT_EQ(escape_target_high.accelerator_count(), 3); | |
| 354 EXPECT_EQ(escape_target_normal.accelerator_count(), 1); | |
| 355 | |
| 356 // Unregister the normal priority accelerator. | |
| 357 focus_manager->UnregisterAccelerator( | |
| 358 escape_accelerator, &escape_target_normal); | |
| 359 EXPECT_EQ(&escape_target_high, | |
| 360 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 361 EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 362 | |
| 363 // Hit the escape key. | |
| 364 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 365 EXPECT_EQ(escape_target_high.accelerator_count(), 4); | |
| 366 EXPECT_EQ(escape_target_normal.accelerator_count(), 1); | |
| 367 | |
| 368 // Unregister the high priority accelerator. | |
| 369 focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target_high); | |
| 370 EXPECT_EQ(NULL, | |
| 371 focus_manager->GetCurrentTargetForAccelerator(escape_accelerator)); | |
| 372 EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator)); | |
| 373 | |
| 374 // Hit the escape key (no change, no targets registered). | |
| 375 EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator)); | |
| 376 EXPECT_EQ(escape_target_high.accelerator_count(), 4); | |
| 377 EXPECT_EQ(escape_target_normal.accelerator_count(), 1); | |
| 378 } | |
| 379 | |
| 380 TEST_F(FocusManagerTest, CallsEnabledAcceleratorTargetsOnly) { | |
| 381 FocusManager* focus_manager = GetFocusManager(); | |
| 382 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); | |
| 383 | |
| 384 TestAcceleratorTarget return_target1(true); | |
| 385 TestAcceleratorTarget return_target2(true); | |
| 386 | |
| 387 focus_manager->RegisterAccelerator(return_accelerator, | |
| 388 ui::AcceleratorManager::kNormalPriority, | |
| 389 &return_target1); | |
| 390 focus_manager->RegisterAccelerator(return_accelerator, | |
| 391 ui::AcceleratorManager::kNormalPriority, | |
| 392 &return_target2); | |
| 393 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 394 EXPECT_EQ(0, return_target1.accelerator_count()); | |
| 395 EXPECT_EQ(1, return_target2.accelerator_count()); | |
| 396 | |
| 397 // If CanHandleAccelerators() return false, FocusManager shouldn't call | |
| 398 // AcceleratorPressed(). | |
| 399 return_target2.set_can_handle_accelerators(false); | |
| 400 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 401 EXPECT_EQ(1, return_target1.accelerator_count()); | |
| 402 EXPECT_EQ(1, return_target2.accelerator_count()); | |
| 403 | |
| 404 // If no accelerator targets are enabled, ProcessAccelerator() should fail. | |
| 405 return_target1.set_can_handle_accelerators(false); | |
| 406 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 407 EXPECT_EQ(1, return_target1.accelerator_count()); | |
| 408 EXPECT_EQ(1, return_target2.accelerator_count()); | |
| 409 | |
| 410 // Enabling the target again causes the accelerators to be processed again. | |
| 411 return_target1.set_can_handle_accelerators(true); | |
| 412 return_target2.set_can_handle_accelerators(true); | |
| 413 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 414 EXPECT_EQ(1, return_target1.accelerator_count()); | |
| 415 EXPECT_EQ(2, return_target2.accelerator_count()); | |
| 416 } | |
| 417 | |
| 418 // Unregisters itself when its accelerator is invoked. | |
| 419 class SelfUnregisteringAcceleratorTarget : public ui::AcceleratorTarget { | |
| 420 public: | |
| 421 SelfUnregisteringAcceleratorTarget(ui::Accelerator accelerator, | |
| 422 FocusManager* focus_manager) | |
| 423 : accelerator_(accelerator), | |
| 424 focus_manager_(focus_manager), | |
| 425 accelerator_count_(0) { | |
| 426 } | |
| 427 | |
| 428 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) override { | |
| 429 ++accelerator_count_; | |
| 430 focus_manager_->UnregisterAccelerator(accelerator, this); | |
| 431 return true; | |
| 432 } | |
| 433 | |
| 434 virtual bool CanHandleAccelerators() const override { | |
| 435 return true; | |
| 436 } | |
| 437 | |
| 438 int accelerator_count() const { return accelerator_count_; } | |
| 439 | |
| 440 private: | |
| 441 ui::Accelerator accelerator_; | |
| 442 FocusManager* focus_manager_; | |
| 443 int accelerator_count_; | |
| 444 | |
| 445 DISALLOW_COPY_AND_ASSIGN(SelfUnregisteringAcceleratorTarget); | |
| 446 }; | |
| 447 | |
| 448 TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) { | |
| 449 FocusManager* focus_manager = GetFocusManager(); | |
| 450 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); | |
| 451 SelfUnregisteringAcceleratorTarget target(return_accelerator, focus_manager); | |
| 452 EXPECT_EQ(target.accelerator_count(), 0); | |
| 453 EXPECT_EQ(NULL, | |
| 454 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 455 | |
| 456 // Register the target. | |
| 457 focus_manager->RegisterAccelerator(return_accelerator, | |
| 458 ui::AcceleratorManager::kNormalPriority, | |
| 459 &target); | |
| 460 EXPECT_EQ(&target, | |
| 461 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 462 | |
| 463 // Hitting the return key. The target will be unregistered. | |
| 464 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 465 EXPECT_EQ(target.accelerator_count(), 1); | |
| 466 EXPECT_EQ(NULL, | |
| 467 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); | |
| 468 | |
| 469 // Hitting the return key again; nothing should happen. | |
| 470 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); | |
| 471 EXPECT_EQ(target.accelerator_count(), 1); | |
| 472 } | |
| 473 | |
| 474 class FocusManagerDtorTest : public FocusManagerTest { | |
| 475 protected: | |
| 476 typedef std::vector<std::string> DtorTrackVector; | |
| 477 | |
| 478 class FocusManagerDtorTracked : public FocusManager { | |
| 479 public: | |
| 480 FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker) | |
| 481 : FocusManager(widget, NULL /* delegate */), | |
| 482 dtor_tracker_(dtor_tracker) { | |
| 483 } | |
| 484 | |
| 485 virtual ~FocusManagerDtorTracked() { | |
| 486 dtor_tracker_->push_back("FocusManagerDtorTracked"); | |
| 487 } | |
| 488 | |
| 489 DtorTrackVector* dtor_tracker_; | |
| 490 | |
| 491 private: | |
| 492 DISALLOW_COPY_AND_ASSIGN(FocusManagerDtorTracked); | |
| 493 }; | |
| 494 | |
| 495 class TestFocusManagerFactory : public FocusManagerFactory { | |
| 496 public: | |
| 497 explicit TestFocusManagerFactory(DtorTrackVector* dtor_tracker) | |
| 498 : dtor_tracker_(dtor_tracker) { | |
| 499 } | |
| 500 | |
| 501 virtual FocusManager* CreateFocusManager(Widget* widget, | |
| 502 bool desktop_widget) override { | |
| 503 return new FocusManagerDtorTracked(widget, dtor_tracker_); | |
| 504 } | |
| 505 | |
| 506 private: | |
| 507 DtorTrackVector* dtor_tracker_; | |
| 508 DISALLOW_COPY_AND_ASSIGN(TestFocusManagerFactory); | |
| 509 }; | |
| 510 | |
| 511 class LabelButtonDtorTracked : public LabelButton { | |
| 512 public: | |
| 513 LabelButtonDtorTracked(const base::string16& text, | |
| 514 DtorTrackVector* dtor_tracker) | |
| 515 : LabelButton(NULL, text), | |
| 516 dtor_tracker_(dtor_tracker) { | |
| 517 SetStyle(STYLE_BUTTON); | |
| 518 }; | |
| 519 virtual ~LabelButtonDtorTracked() { | |
| 520 dtor_tracker_->push_back("LabelButtonDtorTracked"); | |
| 521 } | |
| 522 | |
| 523 DtorTrackVector* dtor_tracker_; | |
| 524 }; | |
| 525 | |
| 526 class WindowDtorTracked : public Widget { | |
| 527 public: | |
| 528 explicit WindowDtorTracked(DtorTrackVector* dtor_tracker) | |
| 529 : dtor_tracker_(dtor_tracker) { | |
| 530 } | |
| 531 | |
| 532 virtual ~WindowDtorTracked() { | |
| 533 dtor_tracker_->push_back("WindowDtorTracked"); | |
| 534 } | |
| 535 | |
| 536 DtorTrackVector* dtor_tracker_; | |
| 537 }; | |
| 538 | |
| 539 virtual void SetUp() { | |
| 540 ViewsTestBase::SetUp(); | |
| 541 FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_)); | |
| 542 // Create WindowDtorTracked that uses FocusManagerDtorTracked. | |
| 543 Widget* widget = new WindowDtorTracked(&dtor_tracker_); | |
| 544 Widget::InitParams params; | |
| 545 params.delegate = this; | |
| 546 params.bounds = gfx::Rect(0, 0, 100, 100); | |
| 547 widget->Init(params); | |
| 548 | |
| 549 tracked_focus_manager_ = | |
| 550 static_cast<FocusManagerDtorTracked*>(GetFocusManager()); | |
| 551 widget->Show(); | |
| 552 } | |
| 553 | |
| 554 virtual void TearDown() { | |
| 555 FocusManagerFactory::Install(NULL); | |
| 556 ViewsTestBase::TearDown(); | |
| 557 } | |
| 558 | |
| 559 FocusManager* tracked_focus_manager_; | |
| 560 DtorTrackVector dtor_tracker_; | |
| 561 }; | |
| 562 | |
| 563 namespace { | |
| 564 | |
| 565 class FocusInAboutToRequestFocusFromTabTraversalView : public View { | |
| 566 public: | |
| 567 FocusInAboutToRequestFocusFromTabTraversalView() : view_to_focus_(NULL) {} | |
| 568 | |
| 569 void set_view_to_focus(View* view) { view_to_focus_ = view; } | |
| 570 | |
| 571 virtual void AboutToRequestFocusFromTabTraversal(bool reverse) override { | |
| 572 view_to_focus_->RequestFocus(); | |
| 573 } | |
| 574 | |
| 575 private: | |
| 576 views::View* view_to_focus_; | |
| 577 | |
| 578 DISALLOW_COPY_AND_ASSIGN(FocusInAboutToRequestFocusFromTabTraversalView); | |
| 579 }; | |
| 580 } // namespace | |
| 581 | |
| 582 // Verifies a focus change done during a call to | |
| 583 // AboutToRequestFocusFromTabTraversal() is honored. | |
| 584 TEST_F(FocusManagerTest, FocusInAboutToRequestFocusFromTabTraversal) { | |
| 585 // Create 3 views focuses the 3 and advances to the second. The 2nd views | |
| 586 // implementation of AboutToRequestFocusFromTabTraversal() focuses the first. | |
| 587 views::View* v1 = new View; | |
| 588 v1->SetFocusable(true); | |
| 589 GetContentsView()->AddChildView(v1); | |
| 590 | |
| 591 FocusInAboutToRequestFocusFromTabTraversalView* v2 = | |
| 592 new FocusInAboutToRequestFocusFromTabTraversalView; | |
| 593 v2->SetFocusable(true); | |
| 594 v2->set_view_to_focus(v1); | |
| 595 GetContentsView()->AddChildView(v2); | |
| 596 | |
| 597 views::View* v3 = new View; | |
| 598 v3->SetFocusable(true); | |
| 599 GetContentsView()->AddChildView(v3); | |
| 600 | |
| 601 v3->RequestFocus(); | |
| 602 GetWidget()->GetFocusManager()->AdvanceFocus(true); | |
| 603 EXPECT_TRUE(v1->HasFocus()); | |
| 604 } | |
| 605 | |
| 606 TEST_F(FocusManagerTest, RotatePaneFocus) { | |
| 607 views::AccessiblePaneView* pane1 = new AccessiblePaneView(); | |
| 608 GetContentsView()->AddChildView(pane1); | |
| 609 | |
| 610 views::View* v1 = new View; | |
| 611 v1->SetFocusable(true); | |
| 612 pane1->AddChildView(v1); | |
| 613 | |
| 614 views::View* v2 = new View; | |
| 615 v2->SetFocusable(true); | |
| 616 pane1->AddChildView(v2); | |
| 617 | |
| 618 views::AccessiblePaneView* pane2 = new AccessiblePaneView(); | |
| 619 GetContentsView()->AddChildView(pane2); | |
| 620 | |
| 621 views::View* v3 = new View; | |
| 622 v3->SetFocusable(true); | |
| 623 pane2->AddChildView(v3); | |
| 624 | |
| 625 views::View* v4 = new View; | |
| 626 v4->SetFocusable(true); | |
| 627 pane2->AddChildView(v4); | |
| 628 | |
| 629 std::vector<views::View*> panes; | |
| 630 panes.push_back(pane1); | |
| 631 panes.push_back(pane2); | |
| 632 SetAccessiblePanes(panes); | |
| 633 | |
| 634 FocusManager* focus_manager = GetWidget()->GetFocusManager(); | |
| 635 | |
| 636 // Advance forwards. Focus should stay trapped within each pane. | |
| 637 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 638 FocusManager::kForward, FocusManager::kWrap)); | |
| 639 EXPECT_EQ(v1, focus_manager->GetFocusedView()); | |
| 640 focus_manager->AdvanceFocus(false); | |
| 641 EXPECT_EQ(v2, focus_manager->GetFocusedView()); | |
| 642 focus_manager->AdvanceFocus(false); | |
| 643 EXPECT_EQ(v1, focus_manager->GetFocusedView()); | |
| 644 | |
| 645 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 646 FocusManager::kForward, FocusManager::kWrap)); | |
| 647 EXPECT_EQ(v3, focus_manager->GetFocusedView()); | |
| 648 focus_manager->AdvanceFocus(false); | |
| 649 EXPECT_EQ(v4, focus_manager->GetFocusedView()); | |
| 650 focus_manager->AdvanceFocus(false); | |
| 651 EXPECT_EQ(v3, focus_manager->GetFocusedView()); | |
| 652 | |
| 653 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 654 FocusManager::kForward, FocusManager::kWrap)); | |
| 655 EXPECT_EQ(v1, focus_manager->GetFocusedView()); | |
| 656 | |
| 657 // Advance backwards. | |
| 658 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 659 FocusManager::kBackward, FocusManager::kWrap)); | |
| 660 EXPECT_EQ(v3, focus_manager->GetFocusedView()); | |
| 661 | |
| 662 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 663 FocusManager::kBackward, FocusManager::kWrap)); | |
| 664 EXPECT_EQ(v1, focus_manager->GetFocusedView()); | |
| 665 | |
| 666 // Advance without wrap. When it gets to the end of the list of | |
| 667 // panes, RotatePaneFocus should return false but the current | |
| 668 // focused view shouldn't change. | |
| 669 EXPECT_TRUE(focus_manager->RotatePaneFocus( | |
| 670 FocusManager::kForward, FocusManager::kNoWrap)); | |
| 671 EXPECT_EQ(v3, focus_manager->GetFocusedView()); | |
| 672 | |
| 673 EXPECT_FALSE(focus_manager->RotatePaneFocus( | |
| 674 FocusManager::kForward, FocusManager::kNoWrap)); | |
| 675 EXPECT_EQ(v3, focus_manager->GetFocusedView()); | |
| 676 } | |
| 677 | |
| 678 // Verifies the stored focus view tracks the focused view. | |
| 679 TEST_F(FocusManagerTest, ImplicitlyStoresFocus) { | |
| 680 views::View* v1 = new View; | |
| 681 v1->SetFocusable(true); | |
| 682 GetContentsView()->AddChildView(v1); | |
| 683 | |
| 684 views::View* v2 = new View; | |
| 685 v2->SetFocusable(true); | |
| 686 GetContentsView()->AddChildView(v2); | |
| 687 | |
| 688 // Verify a focus request on |v1| implicitly updates the stored focus view. | |
| 689 v1->RequestFocus(); | |
| 690 EXPECT_TRUE(v1->HasFocus()); | |
| 691 EXPECT_EQ(v1, GetWidget()->GetFocusManager()->GetStoredFocusView()); | |
| 692 | |
| 693 // Verify a focus request on |v2| implicitly updates the stored focus view. | |
| 694 v2->RequestFocus(); | |
| 695 EXPECT_TRUE(v2->HasFocus()); | |
| 696 EXPECT_EQ(v2, GetWidget()->GetFocusManager()->GetStoredFocusView()); | |
| 697 } | |
| 698 | |
| 699 namespace { | |
| 700 | |
| 701 class FocusManagerArrowKeyTraversalTest : public FocusManagerTest { | |
| 702 public: | |
| 703 FocusManagerArrowKeyTraversalTest() | |
| 704 : previous_arrow_key_traversal_enabled_(false) { | |
| 705 } | |
| 706 virtual ~FocusManagerArrowKeyTraversalTest() {} | |
| 707 | |
| 708 // FocusManagerTest overrides: | |
| 709 virtual void SetUp() override { | |
| 710 FocusManagerTest::SetUp(); | |
| 711 | |
| 712 previous_arrow_key_traversal_enabled_ = | |
| 713 FocusManager::arrow_key_traversal_enabled(); | |
| 714 } | |
| 715 virtual void TearDown() override { | |
| 716 FocusManager::set_arrow_key_traversal_enabled( | |
| 717 previous_arrow_key_traversal_enabled_); | |
| 718 FocusManagerTest::TearDown(); | |
| 719 } | |
| 720 | |
| 721 private: | |
| 722 bool previous_arrow_key_traversal_enabled_; | |
| 723 | |
| 724 DISALLOW_COPY_AND_ASSIGN(FocusManagerArrowKeyTraversalTest); | |
| 725 }; | |
| 726 | |
| 727 } // namespace | |
| 728 | |
| 729 TEST_F(FocusManagerArrowKeyTraversalTest, ArrowKeyTraversal) { | |
| 730 FocusManager* focus_manager = GetFocusManager(); | |
| 731 const ui::KeyEvent left_key(ui::ET_KEY_PRESSED, ui::VKEY_LEFT, ui::EF_NONE); | |
| 732 const ui::KeyEvent right_key(ui::ET_KEY_PRESSED, ui::VKEY_RIGHT, ui::EF_NONE); | |
| 733 const ui::KeyEvent up_key(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE); | |
| 734 const ui::KeyEvent down_key(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE); | |
| 735 | |
| 736 std::vector<views::View*> v; | |
| 737 for (size_t i = 0; i < 2; ++i) { | |
| 738 views::View* view = new View; | |
| 739 view->SetFocusable(true); | |
| 740 GetContentsView()->AddChildView(view); | |
| 741 v.push_back(view); | |
| 742 } | |
| 743 | |
| 744 // Arrow key traversal is off and arrow key does not change focus. | |
| 745 FocusManager::set_arrow_key_traversal_enabled(false); | |
| 746 v[0]->RequestFocus(); | |
| 747 focus_manager->OnKeyEvent(right_key); | |
| 748 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 749 focus_manager->OnKeyEvent(left_key); | |
| 750 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 751 focus_manager->OnKeyEvent(down_key); | |
| 752 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 753 focus_manager->OnKeyEvent(up_key); | |
| 754 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 755 | |
| 756 // Turn on arrow key traversal. | |
| 757 FocusManager::set_arrow_key_traversal_enabled(true); | |
| 758 v[0]->RequestFocus(); | |
| 759 focus_manager->OnKeyEvent(right_key); | |
| 760 EXPECT_EQ(v[1], focus_manager->GetFocusedView()); | |
| 761 focus_manager->OnKeyEvent(left_key); | |
| 762 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 763 focus_manager->OnKeyEvent(down_key); | |
| 764 EXPECT_EQ(v[1], focus_manager->GetFocusedView()); | |
| 765 focus_manager->OnKeyEvent(up_key); | |
| 766 EXPECT_EQ(v[0], focus_manager->GetFocusedView()); | |
| 767 } | |
| 768 | |
| 769 TEST_F(FocusManagerTest, StoreFocusedView) { | |
| 770 View view; | |
| 771 GetFocusManager()->SetFocusedView(&view); | |
| 772 GetFocusManager()->StoreFocusedView(false); | |
| 773 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); | |
| 774 EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); | |
| 775 EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView()); | |
| 776 | |
| 777 // Repeat with |true|. | |
| 778 GetFocusManager()->SetFocusedView(&view); | |
| 779 GetFocusManager()->StoreFocusedView(true); | |
| 780 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); | |
| 781 EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); | |
| 782 EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView()); | |
| 783 } | |
| 784 | |
| 785 class TextInputTestView : public View { | |
| 786 public: | |
| 787 TextInputTestView() {} | |
| 788 | |
| 789 virtual ui::TextInputClient* GetTextInputClient() override { | |
| 790 return &text_input_client_; | |
| 791 } | |
| 792 | |
| 793 private: | |
| 794 ui::DummyTextInputClient text_input_client_; | |
| 795 | |
| 796 DISALLOW_COPY_AND_ASSIGN(TextInputTestView); | |
| 797 }; | |
| 798 | |
| 799 TEST_F(FocusManagerTest, TextInputClient) { | |
| 800 base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | |
| 801 cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager); | |
| 802 | |
| 803 View* view = new TextInputTestView; | |
| 804 ui::TextInputClient* text_input_client = view->GetTextInputClient(); | |
| 805 view->SetFocusable(true); | |
| 806 GetContentsView()->AddChildView(view); | |
| 807 ui::TextInputFocusManager* text_input_focus_manager = | |
| 808 ui::TextInputFocusManager::GetInstance(); | |
| 809 | |
| 810 GetFocusManager()->SetFocusedView(view); | |
| 811 EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); | |
| 812 EXPECT_EQ(text_input_client, | |
| 813 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 814 GetFocusManager()->StoreFocusedView(false); | |
| 815 EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); | |
| 816 EXPECT_EQ(text_input_client, | |
| 817 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 818 | |
| 819 // Repeat with |true|. | |
| 820 GetFocusManager()->SetFocusedView(view); | |
| 821 EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); | |
| 822 EXPECT_EQ(text_input_client, | |
| 823 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 824 GetFocusManager()->StoreFocusedView(true); | |
| 825 EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); | |
| 826 EXPECT_EQ(text_input_client, | |
| 827 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 828 | |
| 829 // Focus the view twice in a row. | |
| 830 GetFocusManager()->SetFocusedView(view); | |
| 831 EXPECT_EQ(text_input_client, | |
| 832 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 833 ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL); | |
| 834 GetFocusManager()->SetFocusedView(view); | |
| 835 EXPECT_EQ(text_input_client, | |
| 836 text_input_focus_manager->GetFocusedTextInputClient()); | |
| 837 } | |
| 838 | |
| 839 namespace { | |
| 840 | |
| 841 // Trivial WidgetDelegate implementation that allows setting return value of | |
| 842 // ShouldAdvanceFocusToTopLevelWidget(). | |
| 843 class AdvanceFocusWidgetDelegate : public WidgetDelegate { | |
| 844 public: | |
| 845 explicit AdvanceFocusWidgetDelegate(Widget* widget) | |
| 846 : widget_(widget), | |
| 847 should_advance_focus_to_parent_(false) {} | |
| 848 virtual ~AdvanceFocusWidgetDelegate() {} | |
| 849 | |
| 850 void set_should_advance_focus_to_parent(bool value) { | |
| 851 should_advance_focus_to_parent_ = value; | |
| 852 } | |
| 853 | |
| 854 // WidgetDelegate overrides: | |
| 855 virtual bool ShouldAdvanceFocusToTopLevelWidget() const override { | |
| 856 return should_advance_focus_to_parent_; | |
| 857 } | |
| 858 virtual Widget* GetWidget() override { return widget_; } | |
| 859 virtual const Widget* GetWidget() const override { return widget_; } | |
| 860 | |
| 861 private: | |
| 862 Widget* widget_; | |
| 863 bool should_advance_focus_to_parent_; | |
| 864 | |
| 865 DISALLOW_COPY_AND_ASSIGN(AdvanceFocusWidgetDelegate); | |
| 866 }; | |
| 867 | |
| 868 } // namespace | |
| 869 | |
| 870 // Verifies focus wrapping happens in the same widget. | |
| 871 TEST_F(FocusManagerTest, AdvanceFocusStaysInWidget) { | |
| 872 // Add |widget_view| as a child of the Widget. | |
| 873 View* widget_view = new View; | |
| 874 widget_view->SetFocusable(true); | |
| 875 widget_view->SetBounds(20, 0, 20, 20); | |
| 876 GetContentsView()->AddChildView(widget_view); | |
| 877 | |
| 878 // Create a widget with two views, focus the second. | |
| 879 scoped_ptr<AdvanceFocusWidgetDelegate> delegate; | |
| 880 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 881 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 882 params.child = true; | |
| 883 params.bounds = gfx::Rect(10, 10, 100, 100); | |
| 884 params.parent = GetWidget()->GetNativeView(); | |
| 885 Widget child_widget; | |
| 886 delegate.reset(new AdvanceFocusWidgetDelegate(&child_widget)); | |
| 887 params.delegate = delegate.get(); | |
| 888 child_widget.Init(params); | |
| 889 View* view1 = new View; | |
| 890 view1->SetFocusable(true); | |
| 891 view1->SetBounds(0, 0, 20, 20); | |
| 892 View* view2 = new View; | |
| 893 view2->SetFocusable(true); | |
| 894 view2->SetBounds(20, 0, 20, 20); | |
| 895 child_widget.client_view()->AddChildView(view1); | |
| 896 child_widget.client_view()->AddChildView(view2); | |
| 897 child_widget.Show(); | |
| 898 view2->RequestFocus(); | |
| 899 EXPECT_EQ(view2, GetFocusManager()->GetFocusedView()); | |
| 900 | |
| 901 // Advance focus backwards, which should focus the first. | |
| 902 GetFocusManager()->AdvanceFocus(false); | |
| 903 EXPECT_EQ(view1, GetFocusManager()->GetFocusedView()); | |
| 904 | |
| 905 // Focus forward to |view2|. | |
| 906 GetFocusManager()->AdvanceFocus(true); | |
| 907 EXPECT_EQ(view2, GetFocusManager()->GetFocusedView()); | |
| 908 | |
| 909 // And forward again, wrapping back to |view1|. | |
| 910 GetFocusManager()->AdvanceFocus(true); | |
| 911 EXPECT_EQ(view1, GetFocusManager()->GetFocusedView()); | |
| 912 | |
| 913 // Allow focus to go to the parent, and focus backwards which should now move | |
| 914 // up |widget_view| (in the parent). | |
| 915 delegate->set_should_advance_focus_to_parent(true); | |
| 916 GetFocusManager()->AdvanceFocus(true); | |
| 917 EXPECT_EQ(widget_view, GetFocusManager()->GetFocusedView()); | |
| 918 } | |
| 919 | |
| 920 } // namespace views | |
| OLD | NEW |