OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/views/controls/menu/menu_controller.h" | 5 #include "ui/views/controls/menu/menu_controller.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
14 #include "ui/aura/scoped_window_targeter.h" | 14 #include "ui/aura/scoped_window_targeter.h" |
15 #include "ui/aura/window.h" | 15 #include "ui/aura/window.h" |
16 #include "ui/events/event.h" | 16 #include "ui/events/event.h" |
17 #include "ui/events/event_constants.h" | 17 #include "ui/events/event_constants.h" |
18 #include "ui/events/event_handler.h" | 18 #include "ui/events/event_handler.h" |
19 #include "ui/events/event_utils.h" | 19 #include "ui/events/event_utils.h" |
20 #include "ui/events/null_event_targeter.h" | 20 #include "ui/events/null_event_targeter.h" |
21 #include "ui/events/test/event_generator.h" | 21 #include "ui/events/test/event_generator.h" |
22 #include "ui/gfx/geometry/point.h" | 22 #include "ui/gfx/geometry/point.h" |
23 #include "ui/gfx/geometry/rect.h" | 23 #include "ui/gfx/geometry/rect.h" |
24 #include "ui/views/controls/menu/menu_controller_delegate.h" | 24 #include "ui/views/controls/menu/menu_controller_delegate.h" |
25 #include "ui/views/controls/menu/menu_delegate.h" | 25 #include "ui/views/controls/menu/menu_delegate.h" |
26 #include "ui/views/controls/menu/menu_host.h" | 26 #include "ui/views/controls/menu/menu_host.h" |
27 #include "ui/views/controls/menu/menu_host_root_view.h" | 27 #include "ui/views/controls/menu/menu_host_root_view.h" |
28 #include "ui/views/controls/menu/menu_item_view.h" | 28 #include "ui/views/controls/menu/menu_item_view.h" |
29 #include "ui/views/controls/menu/menu_message_loop.h" | |
30 #include "ui/views/controls/menu/menu_scroll_view_container.h" | 29 #include "ui/views/controls/menu/menu_scroll_view_container.h" |
31 #include "ui/views/controls/menu/submenu_view.h" | 30 #include "ui/views/controls/menu/submenu_view.h" |
32 #include "ui/views/test/menu_test_utils.h" | 31 #include "ui/views/test/menu_test_utils.h" |
33 #include "ui/views/test/test_views_delegate.h" | 32 #include "ui/views/test/test_views_delegate.h" |
34 #include "ui/views/test/views_test_base.h" | 33 #include "ui/views/test/views_test_base.h" |
35 #include "ui/views/widget/root_view.h" | 34 #include "ui/views/widget/root_view.h" |
36 | 35 |
37 #if defined(USE_AURA) | 36 #if defined(USE_AURA) |
38 #include "ui/aura/client/drag_drop_client.h" | 37 #include "ui/aura/client/drag_drop_client.h" |
39 #include "ui/aura/scoped_window_targeter.h" | 38 #include "ui/aura/scoped_window_targeter.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 } | 145 } |
147 } | 146 } |
148 | 147 |
149 int outstanding_touches() const { return outstanding_touches_; } | 148 int outstanding_touches() const { return outstanding_touches_; } |
150 | 149 |
151 private: | 150 private: |
152 int outstanding_touches_; | 151 int outstanding_touches_; |
153 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); | 152 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); |
154 }; | 153 }; |
155 | 154 |
156 // A wrapper around MenuMessageLoop that can be used to track whether a message | |
157 // loop is running or not. | |
158 class TestMenuMessageLoop : public MenuMessageLoop { | |
159 public: | |
160 explicit TestMenuMessageLoop(std::unique_ptr<MenuMessageLoop> original); | |
161 ~TestMenuMessageLoop() override; | |
162 | |
163 bool is_running() const { return is_running_; } | |
164 | |
165 // MenuMessageLoop: | |
166 void QuitNow() override; | |
167 | |
168 private: | |
169 // MenuMessageLoop: | |
170 void Run() override; | |
171 | |
172 std::unique_ptr<MenuMessageLoop> original_; | |
173 bool is_running_; | |
174 | |
175 DISALLOW_COPY_AND_ASSIGN(TestMenuMessageLoop); | |
176 }; | |
177 | |
178 TestMenuMessageLoop::TestMenuMessageLoop( | |
179 std::unique_ptr<MenuMessageLoop> original) | |
180 : original_(std::move(original)) { | |
181 DCHECK(original_); | |
182 } | |
183 | |
184 TestMenuMessageLoop::~TestMenuMessageLoop() {} | |
185 | |
186 void TestMenuMessageLoop::Run() { | |
187 is_running_ = true; | |
188 original_->Run(); | |
189 } | |
190 | |
191 void TestMenuMessageLoop::QuitNow() { | |
192 is_running_ = false; | |
193 original_->QuitNow(); | |
194 } | |
195 | |
196 #if defined(USE_AURA) | 155 #if defined(USE_AURA) |
197 // A DragDropClient which does not trigger a nested message loop. Instead a | 156 // A DragDropClient which does not trigger a nested message loop. Instead a |
198 // callback is triggered during StartDragAndDrop in order to allow testing. | 157 // callback is triggered during StartDragAndDrop in order to allow testing. |
199 class TestDragDropClient : public aura::client::DragDropClient { | 158 class TestDragDropClient : public aura::client::DragDropClient { |
200 public: | 159 public: |
201 explicit TestDragDropClient(const base::Closure& callback) | 160 explicit TestDragDropClient(const base::Closure& callback) |
202 : start_drag_and_drop_callback_(callback), drag_in_progress_(false) {} | 161 : start_drag_and_drop_callback_(callback), drag_in_progress_(false) {} |
203 ~TestDragDropClient() override {} | 162 ~TestDragDropClient() override {} |
204 | 163 |
205 // aura::client::DragDropClient: | 164 // aura::client::DragDropClient: |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 } | 269 } |
311 | 270 |
312 void ReleaseTouchId(int id) { | 271 void ReleaseTouchId(int id) { |
313 event_generator_->ReleaseTouchId(id); | 272 event_generator_->ReleaseTouchId(id); |
314 } | 273 } |
315 | 274 |
316 void PressKey(ui::KeyboardCode key_code) { | 275 void PressKey(ui::KeyboardCode key_code) { |
317 event_generator_->PressKey(key_code, 0); | 276 event_generator_->PressKey(key_code, 0); |
318 } | 277 } |
319 | 278 |
320 #if defined(OS_LINUX) && defined(USE_X11) | |
321 void TestEventTargeter() { | |
322 { | |
323 // With the |ui::NullEventTargeter| instantiated and assigned we expect | |
324 // the menu to not handle the key event. | |
325 aura::ScopedWindowTargeter scoped_targeter( | |
326 owner()->GetNativeWindow()->GetRootWindow(), | |
327 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter)); | |
328 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); | |
329 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type()); | |
330 } | |
331 // Now that the targeter has been destroyed, expect to exit the menu | |
332 // normally when hitting escape. | |
333 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); | |
334 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); | |
335 } | |
336 #endif // defined(OS_LINUX) && defined(USE_X11 | |
337 | |
338 #if defined(USE_AURA) | 279 #if defined(USE_AURA) |
339 // Verifies that a non-nested menu fully closes when receiving an escape key. | 280 // Verifies that a non-nested menu fully closes when receiving an escape key. |
340 void TestAsyncEscapeKey() { | 281 void TestAsyncEscapeKey() { |
341 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); | 282 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); |
342 menu_controller_->OnWillDispatchKeyEvent(&event); | 283 menu_controller_->OnWillDispatchKeyEvent(&event); |
343 } | 284 } |
344 | 285 |
345 // Verifies that an open menu receives a cancel event, and closes. | 286 // Verifies that an open menu receives a cancel event, and closes. |
346 void TestCancelEvent() { | 287 void TestCancelEvent() { |
347 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type()); | 288 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type()); |
(...skipping 11 matching lines...) Expand all Loading... |
359 } | 300 } |
360 | 301 |
361 // Setups |menu_controller_delegate_| to be destroyed when OnMenuClosed is | 302 // Setups |menu_controller_delegate_| to be destroyed when OnMenuClosed is |
362 // called. | 303 // called. |
363 void TestDragCompleteThenDestroyOnMenuClosed() { | 304 void TestDragCompleteThenDestroyOnMenuClosed() { |
364 menu_controller_delegate_->set_on_menu_closed_callback( | 305 menu_controller_delegate_->set_on_menu_closed_callback( |
365 base::Bind(&MenuControllerTest::VerifyDragCompleteThenDestroy, | 306 base::Bind(&MenuControllerTest::VerifyDragCompleteThenDestroy, |
366 base::Unretained(this))); | 307 base::Unretained(this))); |
367 } | 308 } |
368 | 309 |
369 void TestAsynchronousNestedExitAll() { | |
370 ASSERT_TRUE(test_message_loop_->is_running()); | |
371 | |
372 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | |
373 new TestMenuControllerDelegate()); | |
374 | |
375 menu_controller()->AddNestedDelegate(nested_delegate.get()); | |
376 menu_controller()->SetAsyncRun(true); | |
377 | |
378 int mouse_event_flags = 0; | |
379 MenuItemView* run_result = menu_controller()->Run( | |
380 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false, | |
381 false, &mouse_event_flags); | |
382 EXPECT_EQ(run_result, nullptr); | |
383 | |
384 // Exit all menus and check that the parent menu's message loop is | |
385 // terminated. | |
386 menu_controller()->Cancel(MenuController::EXIT_ALL); | |
387 EXPECT_EQ(MenuController::EXIT_ALL, menu_controller()->exit_type()); | |
388 EXPECT_FALSE(test_message_loop_->is_running()); | |
389 } | |
390 | |
391 void TestAsynchronousNestedExitOutermost() { | |
392 ASSERT_TRUE(test_message_loop_->is_running()); | |
393 | |
394 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | |
395 new TestMenuControllerDelegate()); | |
396 | |
397 menu_controller()->AddNestedDelegate(nested_delegate.get()); | |
398 menu_controller()->SetAsyncRun(true); | |
399 | |
400 int mouse_event_flags = 0; | |
401 MenuItemView* run_result = menu_controller()->Run( | |
402 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false, | |
403 false, &mouse_event_flags); | |
404 EXPECT_EQ(run_result, nullptr); | |
405 | |
406 // Exit the nested menu and check that the parent menu's message loop is | |
407 // still running. | |
408 menu_controller()->Cancel(MenuController::EXIT_OUTERMOST); | |
409 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller()->exit_type()); | |
410 EXPECT_TRUE(test_message_loop_->is_running()); | |
411 | |
412 // Now, exit the parent menu and check that its message loop is terminated. | |
413 menu_controller()->Cancel(MenuController::EXIT_OUTERMOST); | |
414 EXPECT_EQ(MenuController::EXIT_OUTERMOST, menu_controller()->exit_type()); | |
415 EXPECT_FALSE(test_message_loop_->is_running()); | |
416 } | |
417 | |
418 // This nested an asynchronous delegate onto a menu with a nested message | |
419 // loop, then kills the loop. Simulates the loop being killed not by | |
420 // MenuController. | |
421 void TestNestedMessageLoopKillsItself( | |
422 TestMenuControllerDelegate* nested_delegate) { | |
423 menu_controller_->AddNestedDelegate(nested_delegate); | |
424 menu_controller_->SetAsyncRun(true); | |
425 | |
426 test_message_loop_->QuitNow(); | |
427 } | |
428 | |
429 // Tests destroying the active |menu_controller_| and replacing it with a new | 310 // Tests destroying the active |menu_controller_| and replacing it with a new |
430 // active instance. | 311 // active instance. |
431 void TestMenuControllerReplacementDuringDrag() { | 312 void TestMenuControllerReplacementDuringDrag() { |
432 DestroyMenuController(); | 313 DestroyMenuController(); |
433 menu_item()->GetSubmenu()->Close(); | 314 menu_item()->GetSubmenu()->Close(); |
434 menu_controller_ = | 315 menu_controller_ = |
435 new MenuController(true, menu_controller_delegate_.get()); | 316 new MenuController(true, menu_controller_delegate_.get()); |
436 menu_controller_->owner_ = owner_.get(); | 317 menu_controller_->owner_ = owner_.get(); |
437 menu_controller_->showing_ = true; | 318 menu_controller_->showing_ = true; |
438 } | 319 } |
439 | 320 |
440 // Tests that the menu does not destroy itself when canceled during a drag. | 321 // Tests that the menu does not destroy itself when canceled during a drag. |
441 void TestCancelAllDuringDrag() { | 322 void TestCancelAllDuringDrag() { |
442 menu_controller_->CancelAll(); | 323 menu_controller_->CancelAll(); |
443 EXPECT_EQ(0, menu_controller_delegate_->on_menu_closed_called()); | 324 EXPECT_EQ(0, menu_controller_delegate_->on_menu_closed_called()); |
444 } | 325 } |
445 | 326 |
446 // Tests that destroying the menu during ViewsDelegate::ReleaseRef does not | 327 // Tests that destroying the menu during ViewsDelegate::ReleaseRef does not |
447 // cause a crash. | 328 // cause a crash. |
448 void TestDestroyedDuringViewsRelease() { | 329 void TestDestroyedDuringViewsRelease() { |
449 // |test_views_delegate_| is owned by views::ViewsTestBase and not deleted | 330 // |test_views_delegate_| is owned by views::ViewsTestBase and not deleted |
450 // until TearDown. MenuControllerTest outlives it. | 331 // until TearDown. MenuControllerTest outlives it. |
451 test_views_delegate_->set_release_ref_callback(base::Bind( | 332 test_views_delegate_->set_release_ref_callback(base::Bind( |
452 &MenuControllerTest::DestroyMenuController, base::Unretained(this))); | 333 &MenuControllerTest::DestroyMenuController, base::Unretained(this))); |
453 menu_controller_->ExitAsyncRun(); | 334 menu_controller_->ExitMenu(); |
454 } | 335 } |
455 | 336 |
456 protected: | 337 protected: |
457 void SetPendingStateItem(MenuItemView* item) { | 338 void SetPendingStateItem(MenuItemView* item) { |
458 menu_controller_->pending_state_.item = item; | 339 menu_controller_->pending_state_.item = item; |
459 menu_controller_->pending_state_.submenu_open = true; | 340 menu_controller_->pending_state_.submenu_open = true; |
460 } | 341 } |
461 | 342 |
462 void SetState(MenuItemView* item) { | 343 void SetState(MenuItemView* item) { |
463 menu_controller_->state_.item = item; | 344 menu_controller_->state_.item = item; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent, | 389 MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent, |
509 int index) { | 390 int index) { |
510 return menu_controller_->FindNextSelectableMenuItem( | 391 return menu_controller_->FindNextSelectableMenuItem( |
511 parent, index, MenuController::INCREMENT_SELECTION_UP); | 392 parent, index, MenuController::INCREMENT_SELECTION_UP); |
512 } | 393 } |
513 | 394 |
514 internal::MenuControllerDelegate* GetCurrentDelegate() { | 395 internal::MenuControllerDelegate* GetCurrentDelegate() { |
515 return menu_controller_->delegate_; | 396 return menu_controller_->delegate_; |
516 } | 397 } |
517 | 398 |
518 bool IsAsyncRun() { return menu_controller_->async_run_; } | |
519 | |
520 bool IsShowing() { return menu_controller_->showing_; } | 399 bool IsShowing() { return menu_controller_->showing_; } |
521 | 400 |
522 MenuHost* GetMenuHost(SubmenuView* submenu) { return submenu->host_; } | 401 MenuHost* GetMenuHost(SubmenuView* submenu) { return submenu->host_; } |
523 | 402 |
524 MenuHostRootView* CreateMenuHostRootView(MenuHost* host) { | 403 MenuHostRootView* CreateMenuHostRootView(MenuHost* host) { |
525 return static_cast<MenuHostRootView*>(host->CreateRootView()); | 404 return static_cast<MenuHostRootView*>(host->CreateRootView()); |
526 } | 405 } |
527 | 406 |
528 void MenuHostOnDragWillStart(MenuHost* host) { host->OnDragWillStart(); } | 407 void MenuHostOnDragWillStart(MenuHost* host) { host->OnDragWillStart(); } |
529 | 408 |
(...skipping 28 matching lines...) Expand all Loading... |
558 } | 437 } |
559 | 438 |
560 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) { | 439 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) { |
561 menu_controller_->OnMouseMoved(source, event); | 440 menu_controller_->OnMouseMoved(source, event); |
562 } | 441 } |
563 | 442 |
564 void ProcessMouseReleased(SubmenuView* source, const ui::MouseEvent& event) { | 443 void ProcessMouseReleased(SubmenuView* source, const ui::MouseEvent& event) { |
565 menu_controller_->OnMouseReleased(source, event); | 444 menu_controller_->OnMouseReleased(source, event); |
566 } | 445 } |
567 | 446 |
568 void RunMenu() { | |
569 #if defined(USE_AURA) | |
570 std::unique_ptr<MenuPreTargetHandler> menu_pre_target_handler( | |
571 new MenuPreTargetHandler(menu_controller_, owner_.get())); | |
572 #endif | |
573 | |
574 menu_controller_->message_loop_depth_++; | |
575 menu_controller_->RunMessageLoop(); | |
576 menu_controller_->message_loop_depth_--; | |
577 } | |
578 | |
579 void Accept(MenuItemView* item, int event_flags) { | 447 void Accept(MenuItemView* item, int event_flags) { |
580 menu_controller_->Accept(item, event_flags); | 448 menu_controller_->Accept(item, event_flags); |
581 } | 449 } |
582 | 450 |
583 void InstallTestMenuMessageLoop() { | |
584 test_message_loop_ = | |
585 new TestMenuMessageLoop(std::move(menu_controller_->message_loop_)); | |
586 menu_controller_->message_loop_.reset(test_message_loop_); | |
587 } | |
588 | |
589 // Causes the |menu_controller_| to begin dragging. Use TestDragDropClient to | 451 // Causes the |menu_controller_| to begin dragging. Use TestDragDropClient to |
590 // avoid nesting message loops. | 452 // avoid nesting message loops. |
591 void StartDrag() { | 453 void StartDrag() { |
592 const gfx::Point location; | 454 const gfx::Point location; |
593 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0); | 455 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0); |
594 menu_controller_->StartDrag( | 456 menu_controller_->StartDrag( |
595 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location); | 457 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location); |
596 } | 458 } |
597 | 459 |
598 Widget* owner() { return owner_.get(); } | 460 Widget* owner() { return owner_.get(); } |
(...skipping 30 matching lines...) Expand all Loading... |
629 CustomButton* GetHotButton() { | 491 CustomButton* GetHotButton() { |
630 return menu_controller_->hot_button_; | 492 return menu_controller_->hot_button_; |
631 } | 493 } |
632 | 494 |
633 void SetHotTrackedButton(CustomButton* hot_button) { | 495 void SetHotTrackedButton(CustomButton* hot_button) { |
634 menu_controller_->SetHotTrackedButton(hot_button); | 496 menu_controller_->SetHotTrackedButton(hot_button); |
635 } | 497 } |
636 | 498 |
637 void ExitMenuRun() { | 499 void ExitMenuRun() { |
638 menu_controller_->SetExitType(MenuController::ExitType::EXIT_OUTERMOST); | 500 menu_controller_->SetExitType(MenuController::ExitType::EXIT_OUTERMOST); |
639 menu_controller_->ExitMenuRun(); | 501 menu_controller_->ExitTopMostMenu(); |
640 } | 502 } |
641 | 503 |
642 void DestroyMenuController() { | 504 void DestroyMenuController() { |
643 if (!menu_controller_) | 505 if (!menu_controller_) |
644 return; | 506 return; |
645 | 507 |
646 if (!owner_->IsClosed()) | 508 if (!owner_->IsClosed()) |
647 owner_->RemoveObserver(menu_controller_); | 509 owner_->RemoveObserver(menu_controller_); |
648 | 510 |
649 menu_controller_->showing_ = false; | 511 menu_controller_->showing_ = false; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 | 550 |
689 // Not owned. | 551 // Not owned. |
690 DestructingTestViewsDelegate* test_views_delegate_; | 552 DestructingTestViewsDelegate* test_views_delegate_; |
691 | 553 |
692 std::unique_ptr<Widget> owner_; | 554 std::unique_ptr<Widget> owner_; |
693 std::unique_ptr<ui::test::EventGenerator> event_generator_; | 555 std::unique_ptr<ui::test::EventGenerator> event_generator_; |
694 std::unique_ptr<TestMenuItemViewShown> menu_item_; | 556 std::unique_ptr<TestMenuItemViewShown> menu_item_; |
695 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_; | 557 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_; |
696 std::unique_ptr<TestMenuDelegate> menu_delegate_; | 558 std::unique_ptr<TestMenuDelegate> menu_delegate_; |
697 MenuController* menu_controller_; | 559 MenuController* menu_controller_; |
698 TestMenuMessageLoop* test_message_loop_; | |
699 | 560 |
700 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); | 561 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); |
701 }; | 562 }; |
702 | 563 |
703 #if defined(OS_LINUX) && defined(USE_X11) | 564 #if defined(OS_LINUX) && defined(USE_X11) |
704 // Tests that an event targeter which blocks events will be honored by the menu | 565 // Tests that an event targeter which blocks events will be honored by the menu |
705 // event dispatcher. | 566 // event dispatcher. |
706 TEST_F(MenuControllerTest, EventTargeter) { | 567 TEST_F(MenuControllerTest, EventTargeter) { |
707 base::ThreadTaskRunnerHandle::Get()->PostTask( | 568 { |
708 FROM_HERE, base::Bind(&MenuControllerTest::TestEventTargeter, | 569 // With the |ui::NullEventTargeter| instantiated and assigned we expect |
709 base::Unretained(this))); | 570 // the menu to not handle the key event. |
710 RunMenu(); | 571 aura::ScopedWindowTargeter scoped_targeter( |
711 } | 572 owner()->GetNativeWindow()->GetRootWindow(), |
712 | 573 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter)); |
713 // Tests that an non-nested menu receiving an escape key will fully shut. This | 574 PressKey(ui::VKEY_ESCAPE); |
714 // should not crash by attempting to retarget the key to an inner menu. | 575 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type()); |
715 TEST_F(MenuControllerTest, AsyncEscapeKey) { | 576 } |
716 menu_controller()->SetAsyncRun(true); | 577 // Now that the targeter has been destroyed, expect to exit the menu |
| 578 // normally when hitting escape. |
717 TestAsyncEscapeKey(); | 579 TestAsyncEscapeKey(); |
718 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); | 580 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); |
719 } | 581 } |
720 | 582 |
721 #endif // defined(OS_LINUX) && defined(USE_X11) | 583 #endif // defined(OS_LINUX) && defined(USE_X11) |
722 | 584 |
723 #if defined(USE_X11) | 585 #if defined(USE_X11) |
724 // Tests that touch event ids are released correctly. See crbug.com/439051 for | 586 // Tests that touch event ids are released correctly. See crbug.com/439051 for |
725 // details. When the ids aren't managed correctly, we get stuck down touches. | 587 // details. When the ids aren't managed correctly, we get stuck down touches. |
726 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { | 588 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { |
727 TestEventHandler test_event_handler; | 589 TestEventHandler test_event_handler; |
728 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( | 590 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( |
729 &test_event_handler); | 591 &test_event_handler); |
730 | 592 |
731 std::vector<int> devices; | 593 std::vector<int> devices; |
732 devices.push_back(1); | 594 devices.push_back(1); |
733 ui::SetUpTouchDevicesForTest(devices); | 595 ui::SetUpTouchDevicesForTest(devices); |
734 | 596 |
735 event_generator()->PressTouchId(0); | 597 event_generator()->PressTouchId(0); |
736 event_generator()->PressTouchId(1); | 598 event_generator()->PressTouchId(1); |
737 event_generator()->ReleaseTouchId(0); | 599 event_generator()->ReleaseTouchId(0); |
738 | 600 |
739 base::ThreadTaskRunnerHandle::Get()->PostTask( | 601 int mouse_event_flags = 0; |
740 FROM_HERE, base::Bind(&MenuControllerTest::ReleaseTouchId, | 602 MenuItemView* run_result = menu_controller()->Run( |
741 base::Unretained(this), 1)); | 603 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false, |
| 604 false, &mouse_event_flags); |
| 605 EXPECT_EQ(run_result, nullptr); |
742 | 606 |
743 base::ThreadTaskRunnerHandle::Get()->PostTask( | 607 MenuControllerTest::ReleaseTouchId(1); |
744 FROM_HERE, base::Bind(&MenuControllerTest::PressKey, | 608 TestAsyncEscapeKey(); |
745 base::Unretained(this), ui::VKEY_ESCAPE)); | |
746 | |
747 RunMenu(); | |
748 | 609 |
749 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); | 610 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); |
750 EXPECT_EQ(0, test_event_handler.outstanding_touches()); | 611 EXPECT_EQ(0, test_event_handler.outstanding_touches()); |
751 | 612 |
752 owner()->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( | 613 owner()->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( |
753 &test_event_handler); | 614 &test_event_handler); |
754 } | 615 } |
755 #endif // defined(USE_X11) | 616 #endif // defined(USE_X11) |
756 | 617 |
757 // Tests that initial selected menu items are correct when items are enabled or | 618 // Tests that initial selected menu items are correct when items are enabled or |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1045 // Increment twice to move selection to |button2|. | 906 // Increment twice to move selection to |button2|. |
1046 IncrementSelection(); | 907 IncrementSelection(); |
1047 IncrementSelection(); | 908 IncrementSelection(); |
1048 EXPECT_EQ(5, pending_state_item()->GetCommand()); | 909 EXPECT_EQ(5, pending_state_item()->GetCommand()); |
1049 EXPECT_FALSE(button1->IsHotTracked()); | 910 EXPECT_FALSE(button1->IsHotTracked()); |
1050 EXPECT_TRUE(button2->IsHotTracked()); | 911 EXPECT_TRUE(button2->IsHotTracked()); |
1051 EXPECT_FALSE(button3->IsHotTracked()); | 912 EXPECT_FALSE(button3->IsHotTracked()); |
1052 EXPECT_EQ(button2, GetHotButton()); | 913 EXPECT_EQ(button2, GetHotButton()); |
1053 | 914 |
1054 MenuController* controller = menu_controller(); | 915 MenuController* controller = menu_controller(); |
1055 controller->SetAsyncRun(true); | |
1056 int mouse_event_flags = 0; | 916 int mouse_event_flags = 0; |
1057 MenuItemView* run_result = | 917 MenuItemView* run_result = |
1058 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 918 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1059 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 919 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1060 EXPECT_EQ(run_result, nullptr); | 920 EXPECT_EQ(run_result, nullptr); |
1061 | 921 |
1062 // |button2| should stay in hot-tracked state but menu controller should not | 922 // |button2| should stay in hot-tracked state but menu controller should not |
1063 // track it anymore (preventing resetting hot-tracked state when changing | 923 // track it anymore (preventing resetting hot-tracked state when changing |
1064 // selection while a nested run is active). | 924 // selection while a nested run is active). |
1065 EXPECT_TRUE(button2->IsHotTracked()); | 925 EXPECT_TRUE(button2->IsHotTracked()); |
1066 EXPECT_EQ(nullptr, GetHotButton()); | 926 EXPECT_EQ(nullptr, GetHotButton()); |
1067 | 927 |
1068 // Setting hot-tracked button while nested should get reverted when nested | 928 // Setting hot-tracked button while nested should get reverted when nested |
1069 // menu run ends. | 929 // menu run ends. |
1070 SetHotTrackedButton(button1); | 930 SetHotTrackedButton(button1); |
1071 EXPECT_TRUE(button1->IsHotTracked()); | 931 EXPECT_TRUE(button1->IsHotTracked()); |
1072 EXPECT_EQ(button1, GetHotButton()); | 932 EXPECT_EQ(button1, GetHotButton()); |
1073 | 933 |
1074 ExitMenuRun(); | 934 ExitMenuRun(); |
1075 EXPECT_FALSE(button1->IsHotTracked()); | 935 EXPECT_FALSE(button1->IsHotTracked()); |
1076 EXPECT_TRUE(button2->IsHotTracked()); | 936 EXPECT_TRUE(button2->IsHotTracked()); |
1077 EXPECT_EQ(button2, GetHotButton()); | 937 EXPECT_EQ(button2, GetHotButton()); |
1078 } | 938 } |
1079 | 939 |
1080 // Tests that a menu opened asynchronously, will notify its | 940 // Tests that a menu opened asynchronously, will notify its |
1081 // MenuControllerDelegate when Accept is called. | 941 // MenuControllerDelegate when Accept is called. |
1082 TEST_F(MenuControllerTest, AsynchronousAccept) { | 942 TEST_F(MenuControllerTest, AsynchronousAccept) { |
1083 MenuController* controller = menu_controller(); | 943 MenuController* controller = menu_controller(); |
1084 controller->SetAsyncRun(true); | |
1085 | 944 |
1086 int mouse_event_flags = 0; | 945 int mouse_event_flags = 0; |
1087 MenuItemView* run_result = | 946 MenuItemView* run_result = |
1088 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 947 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1089 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 948 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1090 EXPECT_EQ(run_result, nullptr); | 949 EXPECT_EQ(run_result, nullptr); |
1091 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 950 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1092 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 951 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
1093 | 952 |
1094 MenuItemView* accepted = menu_item()->GetSubmenu()->GetMenuItemAt(0); | 953 MenuItemView* accepted = menu_item()->GetSubmenu()->GetMenuItemAt(0); |
1095 const int kEventFlags = 42; | 954 const int kEventFlags = 42; |
1096 Accept(accepted, kEventFlags); | 955 Accept(accepted, kEventFlags); |
1097 | 956 |
1098 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 957 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1099 EXPECT_EQ(accepted, delegate->on_menu_closed_menu()); | 958 EXPECT_EQ(accepted, delegate->on_menu_closed_menu()); |
1100 EXPECT_EQ(kEventFlags, delegate->on_menu_closed_mouse_event_flags()); | 959 EXPECT_EQ(kEventFlags, delegate->on_menu_closed_mouse_event_flags()); |
1101 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 960 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1102 delegate->on_menu_closed_notify_type()); | 961 delegate->on_menu_closed_notify_type()); |
1103 } | 962 } |
1104 | 963 |
1105 // Tests that a menu opened asynchronously, will notify its | 964 // Tests that a menu opened asynchronously, will notify its |
1106 // MenuControllerDelegate when CancelAll is called. | 965 // MenuControllerDelegate when CancelAll is called. |
1107 TEST_F(MenuControllerTest, AsynchronousCancelAll) { | 966 TEST_F(MenuControllerTest, AsynchronousCancelAll) { |
1108 MenuController* controller = menu_controller(); | 967 MenuController* controller = menu_controller(); |
1109 controller->SetAsyncRun(true); | |
1110 | 968 |
1111 int mouse_event_flags = 0; | 969 int mouse_event_flags = 0; |
1112 MenuItemView* run_result = | 970 MenuItemView* run_result = |
1113 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 971 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1114 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 972 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1115 EXPECT_EQ(run_result, nullptr); | 973 EXPECT_EQ(run_result, nullptr); |
1116 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 974 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1117 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 975 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
1118 | 976 |
1119 controller->CancelAll(); | 977 controller->CancelAll(); |
1120 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 978 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1121 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); | 979 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); |
1122 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); | 980 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); |
1123 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 981 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1124 delegate->on_menu_closed_notify_type()); | 982 delegate->on_menu_closed_notify_type()); |
1125 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); | 983 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
1126 } | 984 } |
1127 | 985 |
1128 // Tests that an asynchrnous menu nested within a synchronous menu restores the | 986 // Tests that canceling a nested menu restores the previous |
1129 // previous MenuControllerDelegate and synchronous settings. | 987 // MenuControllerDelegate, and notifies each delegate. |
1130 TEST_F(MenuControllerTest, AsynchronousNestedDelegate) { | 988 TEST_F(MenuControllerTest, AsynchronousNestedDelegate) { |
1131 MenuController* controller = menu_controller(); | 989 MenuController* controller = menu_controller(); |
1132 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 990 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1133 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | 991 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( |
1134 new TestMenuControllerDelegate()); | 992 new TestMenuControllerDelegate()); |
1135 | 993 |
1136 ASSERT_FALSE(IsAsyncRun()); | |
1137 controller->AddNestedDelegate(nested_delegate.get()); | 994 controller->AddNestedDelegate(nested_delegate.get()); |
1138 controller->SetAsyncRun(true); | |
1139 | |
1140 EXPECT_TRUE(IsAsyncRun()); | |
1141 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); | 995 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); |
1142 | 996 |
1143 int mouse_event_flags = 0; | 997 int mouse_event_flags = 0; |
1144 MenuItemView* run_result = | 998 MenuItemView* run_result = |
1145 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 999 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1146 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1000 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1147 EXPECT_EQ(run_result, nullptr); | 1001 EXPECT_EQ(run_result, nullptr); |
1148 | 1002 |
1149 controller->CancelAll(); | 1003 controller->CancelAll(); |
1150 EXPECT_FALSE(IsAsyncRun()); | |
1151 EXPECT_EQ(delegate, GetCurrentDelegate()); | 1004 EXPECT_EQ(delegate, GetCurrentDelegate()); |
1152 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 1005 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1153 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 1006 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
1154 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); | 1007 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); |
1155 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); | 1008 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); |
1156 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 1009 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1157 nested_delegate->on_menu_closed_notify_type()); | 1010 nested_delegate->on_menu_closed_notify_type()); |
1158 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); | 1011 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
1159 } | 1012 } |
1160 | 1013 |
1161 // Tests that dropping within an asynchronous menu stops the menu from showing | 1014 // Tests that dropping within an asynchronous menu stops the menu from showing |
1162 // and does not notify the controller. | 1015 // and does not notify the controller. |
1163 TEST_F(MenuControllerTest, AsynchronousPerformDrop) { | 1016 TEST_F(MenuControllerTest, AsynchronousPerformDrop) { |
1164 MenuController* controller = menu_controller(); | 1017 MenuController* controller = menu_controller(); |
1165 controller->SetAsyncRun(true); | |
1166 SubmenuView* source = menu_item()->GetSubmenu(); | 1018 SubmenuView* source = menu_item()->GetSubmenu(); |
1167 MenuItemView* target = source->GetMenuItemAt(0); | 1019 MenuItemView* target = source->GetMenuItemAt(0); |
1168 | 1020 |
1169 SetDropMenuItem(target, MenuDelegate::DropPosition::DROP_AFTER); | 1021 SetDropMenuItem(target, MenuDelegate::DropPosition::DROP_AFTER); |
1170 | 1022 |
1171 ui::OSExchangeData drop_data; | 1023 ui::OSExchangeData drop_data; |
1172 gfx::Rect bounds(target->bounds()); | 1024 gfx::Rect bounds(target->bounds()); |
1173 gfx::Point location(bounds.x(), bounds.y()); | 1025 gfx::Point location(bounds.x(), bounds.y()); |
1174 ui::DropTargetEvent target_event(drop_data, location, location, | 1026 ui::DropTargetEvent target_event(drop_data, location, location, |
1175 ui::DragDropTypes::DRAG_MOVE); | 1027 ui::DragDropTypes::DRAG_MOVE); |
1176 controller->OnPerformDrop(source, target_event); | 1028 controller->OnPerformDrop(source, target_event); |
1177 | 1029 |
1178 TestMenuDelegate* menu_delegate = | 1030 TestMenuDelegate* menu_delegate = |
1179 static_cast<TestMenuDelegate*>(target->GetDelegate()); | 1031 static_cast<TestMenuDelegate*>(target->GetDelegate()); |
1180 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); | 1032 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); |
1181 EXPECT_TRUE(menu_delegate->on_perform_drop_called()); | 1033 EXPECT_TRUE(menu_delegate->on_perform_drop_called()); |
1182 EXPECT_FALSE(IsShowing()); | 1034 EXPECT_FALSE(IsShowing()); |
1183 EXPECT_EQ(0, controller_delegate->on_menu_closed_called()); | 1035 EXPECT_EQ(0, controller_delegate->on_menu_closed_called()); |
1184 } | 1036 } |
1185 | 1037 |
1186 // Tests that dragging within an asynchronous menu notifies the | 1038 // Tests that dragging within an asynchronous menu notifies the |
1187 // MenuControllerDelegate for shutdown. | 1039 // MenuControllerDelegate for shutdown. |
1188 TEST_F(MenuControllerTest, AsynchronousDragComplete) { | 1040 TEST_F(MenuControllerTest, AsynchronousDragComplete) { |
1189 MenuController* controller = menu_controller(); | 1041 MenuController* controller = menu_controller(); |
1190 controller->SetAsyncRun(true); | |
1191 TestDragCompleteThenDestroyOnMenuClosed(); | 1042 TestDragCompleteThenDestroyOnMenuClosed(); |
1192 | 1043 |
1193 controller->OnDragWillStart(); | 1044 controller->OnDragWillStart(); |
1194 controller->OnDragComplete(true); | 1045 controller->OnDragComplete(true); |
1195 | 1046 |
1196 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); | 1047 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); |
1197 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); | 1048 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); |
1198 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); | 1049 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); |
1199 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 1050 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1200 controller_delegate->on_menu_closed_notify_type()); | 1051 controller_delegate->on_menu_closed_notify_type()); |
1201 } | 1052 } |
1202 | 1053 |
1203 // Tests that if Cancel is called during a drag, that OnMenuClosed is still | 1054 // Tests that if Cancel is called during a drag, that OnMenuClosed is still |
1204 // notified when the drag completes. | 1055 // notified when the drag completes. |
1205 TEST_F(MenuControllerTest, AsynchronousCancelDuringDrag) { | 1056 TEST_F(MenuControllerTest, AsynchronousCancelDuringDrag) { |
1206 MenuController* controller = menu_controller(); | 1057 MenuController* controller = menu_controller(); |
1207 controller->SetAsyncRun(true); | |
1208 TestDragCompleteThenDestroyOnMenuClosed(); | 1058 TestDragCompleteThenDestroyOnMenuClosed(); |
1209 | 1059 |
1210 controller->OnDragWillStart(); | 1060 controller->OnDragWillStart(); |
1211 controller->CancelAll(); | 1061 controller->CancelAll(); |
1212 controller->OnDragComplete(true); | 1062 controller->OnDragComplete(true); |
1213 | 1063 |
1214 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); | 1064 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); |
1215 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); | 1065 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); |
1216 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); | 1066 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); |
1217 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 1067 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1218 controller_delegate->on_menu_closed_notify_type()); | 1068 controller_delegate->on_menu_closed_notify_type()); |
1219 } | 1069 } |
1220 | 1070 |
1221 // Tests that if a menu is destroyed while drag operations are occuring, that | 1071 // Tests that if a menu is destroyed while drag operations are occuring, that |
1222 // the MenuHost does not crash as the drag completes. | 1072 // the MenuHost does not crash as the drag completes. |
1223 TEST_F(MenuControllerTest, AsynchronousDragHostDeleted) { | 1073 TEST_F(MenuControllerTest, AsynchronousDragHostDeleted) { |
1224 MenuController* controller = menu_controller(); | |
1225 controller->SetAsyncRun(true); | |
1226 | |
1227 SubmenuView* submenu = menu_item()->GetSubmenu(); | 1074 SubmenuView* submenu = menu_item()->GetSubmenu(); |
1228 submenu->ShowAt(owner(), menu_item()->bounds(), false); | 1075 submenu->ShowAt(owner(), menu_item()->bounds(), false); |
1229 MenuHost* host = GetMenuHost(submenu); | 1076 MenuHost* host = GetMenuHost(submenu); |
1230 MenuHostOnDragWillStart(host); | 1077 MenuHostOnDragWillStart(host); |
1231 submenu->Close(); | 1078 submenu->Close(); |
1232 DestroyMenuItem(); | 1079 DestroyMenuItem(); |
1233 MenuHostOnDragComplete(host); | 1080 MenuHostOnDragComplete(host); |
1234 } | 1081 } |
1235 | 1082 |
1236 // Widget destruction and cleanup occurs on the MessageLoop after the | 1083 // Widget destruction and cleanup occurs on the MessageLoop after the |
1237 // MenuController has been destroyed. A MenuHostRootView should not attempt to | 1084 // MenuController has been destroyed. A MenuHostRootView should not attempt to |
1238 // access a destroyed MenuController. This test should not cause a crash. | 1085 // access a destroyed MenuController. This test should not cause a crash. |
1239 TEST_F(MenuControllerTest, HostReceivesInputBeforeDestruction) { | 1086 TEST_F(MenuControllerTest, HostReceivesInputBeforeDestruction) { |
1240 MenuController* controller = menu_controller(); | |
1241 controller->SetAsyncRun(true); | |
1242 | |
1243 SubmenuView* submenu = menu_item()->GetSubmenu(); | 1087 SubmenuView* submenu = menu_item()->GetSubmenu(); |
1244 submenu->ShowAt(owner(), menu_item()->bounds(), false); | 1088 submenu->ShowAt(owner(), menu_item()->bounds(), false); |
1245 gfx::Point location(submenu->bounds().bottom_right()); | 1089 gfx::Point location(submenu->bounds().bottom_right()); |
1246 location.Offset(1, 1); | 1090 location.Offset(1, 1); |
1247 | 1091 |
1248 MenuHost* host = GetMenuHost(submenu); | 1092 MenuHost* host = GetMenuHost(submenu); |
1249 // Normally created as the full Widget is brought up. Explicitly created here | 1093 // Normally created as the full Widget is brought up. Explicitly created here |
1250 // for testing. | 1094 // for testing. |
1251 std::unique_ptr<MenuHostRootView> root_view(CreateMenuHostRootView(host)); | 1095 std::unique_ptr<MenuHostRootView> root_view(CreateMenuHostRootView(host)); |
1252 DestroyMenuController(); | 1096 DestroyMenuController(); |
1253 | 1097 |
1254 ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, | 1098 ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, |
1255 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); | 1099 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); |
1256 | 1100 |
1257 // This should not attempt to access the destroyed MenuController and should | 1101 // This should not attempt to access the destroyed MenuController and should |
1258 // not crash. | 1102 // not crash. |
1259 root_view->OnMouseMoved(event); | 1103 root_view->OnMouseMoved(event); |
1260 } | 1104 } |
1261 | 1105 |
1262 // Tets that an asynchronous menu nested within an asynchronous menu closes both | 1106 // Tets that an asynchronous menu nested within an asynchronous menu closes both |
1263 // menus, and notifies both delegates. | 1107 // menus, and notifies both delegates. |
1264 TEST_F(MenuControllerTest, DoubleAsynchronousNested) { | 1108 TEST_F(MenuControllerTest, DoubleAsynchronousNested) { |
1265 MenuController* controller = menu_controller(); | 1109 MenuController* controller = menu_controller(); |
1266 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 1110 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1267 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | 1111 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( |
1268 new TestMenuControllerDelegate()); | 1112 new TestMenuControllerDelegate()); |
1269 | 1113 |
1270 ASSERT_FALSE(IsAsyncRun()); | |
1271 // Sets the run created in SetUp | |
1272 controller->SetAsyncRun(true); | |
1273 | |
1274 // Nested run | 1114 // Nested run |
1275 controller->AddNestedDelegate(nested_delegate.get()); | 1115 controller->AddNestedDelegate(nested_delegate.get()); |
1276 controller->SetAsyncRun(true); | |
1277 int mouse_event_flags = 0; | 1116 int mouse_event_flags = 0; |
1278 MenuItemView* run_result = | 1117 MenuItemView* run_result = |
1279 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 1118 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1280 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1119 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1281 EXPECT_EQ(run_result, nullptr); | 1120 EXPECT_EQ(run_result, nullptr); |
1282 | 1121 |
1283 controller->CancelAll(); | 1122 controller->CancelAll(); |
1284 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 1123 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1285 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 1124 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
1286 } | 1125 } |
1287 | 1126 |
1288 // Tests that an asynchronous menu nested within a synchronous menu does not | 1127 // Tests that a nested menu does not crash when trying to repost events that |
1289 // crash when trying to repost events that occur outside of the bounds of the | 1128 // occur outside of the bounds of the menu. Instead a proper shutdown should |
1290 // menu. Instead a proper shutdown should occur. | 1129 // occur. |
1291 TEST_F(MenuControllerTest, AsynchronousRepostEvent) { | 1130 TEST_F(MenuControllerTest, AsynchronousRepostEvent) { |
1292 MenuController* controller = menu_controller(); | 1131 MenuController* controller = menu_controller(); |
1293 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 1132 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1294 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | 1133 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( |
1295 new TestMenuControllerDelegate()); | 1134 new TestMenuControllerDelegate()); |
1296 | 1135 |
1297 ASSERT_FALSE(IsAsyncRun()); | |
1298 | |
1299 controller->AddNestedDelegate(nested_delegate.get()); | 1136 controller->AddNestedDelegate(nested_delegate.get()); |
1300 controller->SetAsyncRun(true); | |
1301 | |
1302 EXPECT_TRUE(IsAsyncRun()); | |
1303 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); | 1137 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); |
1304 | 1138 |
1305 MenuItemView* item = menu_item(); | 1139 MenuItemView* item = menu_item(); |
1306 int mouse_event_flags = 0; | 1140 int mouse_event_flags = 0; |
1307 MenuItemView* run_result = | 1141 MenuItemView* run_result = |
1308 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, | 1142 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, |
1309 false, false, &mouse_event_flags); | 1143 false, false, &mouse_event_flags); |
1310 EXPECT_EQ(run_result, nullptr); | 1144 EXPECT_EQ(run_result, nullptr); |
1311 | 1145 |
1312 // Show a sub menu to target with a pointer selection. However have the event | 1146 // Show a sub menu to target with a pointer selection. However have the event |
1313 // occur outside of the bounds of the entire menu. | 1147 // occur outside of the bounds of the entire menu. |
1314 SubmenuView* sub_menu = item->GetSubmenu(); | 1148 SubmenuView* sub_menu = item->GetSubmenu(); |
1315 sub_menu->ShowAt(owner(), item->bounds(), false); | 1149 sub_menu->ShowAt(owner(), item->bounds(), false); |
1316 gfx::Point location(sub_menu->bounds().bottom_right()); | 1150 gfx::Point location(sub_menu->bounds().bottom_right()); |
1317 location.Offset(1, 1); | 1151 location.Offset(1, 1); |
1318 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location, | 1152 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location, |
1319 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); | 1153 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); |
1320 | 1154 |
1321 // When attempting to select outside of all menus this should lead to a | 1155 // When attempting to select outside of all menus this should lead to a |
1322 // shutdown. This should not crash while attempting to repost the event. | 1156 // shutdown. This should not crash while attempting to repost the event. |
1323 SetSelectionOnPointerDown(sub_menu, &event); | 1157 SetSelectionOnPointerDown(sub_menu, &event); |
1324 | 1158 |
1325 EXPECT_FALSE(IsAsyncRun()); | |
1326 EXPECT_EQ(delegate, GetCurrentDelegate()); | 1159 EXPECT_EQ(delegate, GetCurrentDelegate()); |
1327 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 1160 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1328 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 1161 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
1329 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); | 1162 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); |
1330 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); | 1163 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); |
1331 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 1164 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1332 nested_delegate->on_menu_closed_notify_type()); | 1165 nested_delegate->on_menu_closed_notify_type()); |
1333 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); | 1166 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
1334 } | 1167 } |
1335 | 1168 |
1336 // Tests that an asynchronous menu reposts touch events that occur outside of | 1169 // Tests that an asynchronous menu reposts touch events that occur outside of |
1337 // the bounds of the menu, and that the menu closes. | 1170 // the bounds of the menu, and that the menu closes. |
1338 TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) { | 1171 TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) { |
1339 MenuController* controller = menu_controller(); | 1172 MenuController* controller = menu_controller(); |
1340 TestMenuControllerDelegate* delegate = menu_controller_delegate(); | 1173 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
1341 controller->SetAsyncRun(true); | |
1342 | 1174 |
1343 // Show a sub menu to target with a touch event. However have the event occur | 1175 // Show a sub menu to target with a touch event. However have the event occur |
1344 // outside of the bounds of the entire menu. | 1176 // outside of the bounds of the entire menu. |
1345 MenuItemView* item = menu_item(); | 1177 MenuItemView* item = menu_item(); |
1346 SubmenuView* sub_menu = item->GetSubmenu(); | 1178 SubmenuView* sub_menu = item->GetSubmenu(); |
1347 sub_menu->ShowAt(owner(), item->bounds(), false); | 1179 sub_menu->ShowAt(owner(), item->bounds(), false); |
1348 gfx::Point location(sub_menu->bounds().bottom_right()); | 1180 gfx::Point location(sub_menu->bounds().bottom_right()); |
1349 location.Offset(1, 1); | 1181 location.Offset(1, 1); |
1350 ui::TouchEvent event( | 1182 ui::TouchEvent event( |
1351 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), | 1183 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), |
1352 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); | 1184 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
1353 controller->OnTouchEvent(sub_menu, &event); | 1185 controller->OnTouchEvent(sub_menu, &event); |
1354 | 1186 |
1355 EXPECT_FALSE(IsShowing()); | 1187 EXPECT_FALSE(IsShowing()); |
1356 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 1188 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
1357 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); | 1189 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); |
1358 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); | 1190 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); |
1359 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 1191 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
1360 delegate->on_menu_closed_notify_type()); | 1192 delegate->on_menu_closed_notify_type()); |
1361 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); | 1193 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
1362 } | 1194 } |
1363 | 1195 |
1364 // Tests that if you exit all menus when an asynchrnous menu is nested within a | |
1365 // synchronous menu, the message loop for the parent menu finishes running. | |
1366 TEST_F(MenuControllerTest, AsynchronousNestedExitAll) { | |
1367 InstallTestMenuMessageLoop(); | |
1368 | |
1369 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
1370 FROM_HERE, base::Bind(&MenuControllerTest::TestAsynchronousNestedExitAll, | |
1371 base::Unretained(this))); | |
1372 | |
1373 RunMenu(); | |
1374 } | |
1375 | |
1376 // Tests that if you exit the nested menu when an asynchrnous menu is nested | |
1377 // within a synchronous menu, the message loop for the parent menu remains | |
1378 // running. | |
1379 TEST_F(MenuControllerTest, AsynchronousNestedExitOutermost) { | |
1380 InstallTestMenuMessageLoop(); | |
1381 | |
1382 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
1383 FROM_HERE, | |
1384 base::Bind(&MenuControllerTest::TestAsynchronousNestedExitOutermost, | |
1385 base::Unretained(this))); | |
1386 | |
1387 RunMenu(); | |
1388 } | |
1389 | |
1390 // Tests that having the MenuController deleted during RepostEvent does not | 1196 // Tests that having the MenuController deleted during RepostEvent does not |
1391 // cause a crash. ASAN bots should not detect use-after-free in MenuController. | 1197 // cause a crash. ASAN bots should not detect use-after-free in MenuController. |
1392 TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) { | 1198 TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) { |
1393 MenuController* controller = menu_controller(); | 1199 MenuController* controller = menu_controller(); |
1394 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | 1200 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( |
1395 new TestMenuControllerDelegate()); | 1201 new TestMenuControllerDelegate()); |
1396 | 1202 |
1397 ASSERT_FALSE(IsAsyncRun()); | |
1398 | |
1399 controller->AddNestedDelegate(nested_delegate.get()); | 1203 controller->AddNestedDelegate(nested_delegate.get()); |
1400 controller->SetAsyncRun(true); | |
1401 | |
1402 EXPECT_TRUE(IsAsyncRun()); | |
1403 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); | 1204 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); |
1404 | 1205 |
1405 MenuItemView* item = menu_item(); | 1206 MenuItemView* item = menu_item(); |
1406 int mouse_event_flags = 0; | 1207 int mouse_event_flags = 0; |
1407 MenuItemView* run_result = | 1208 MenuItemView* run_result = |
1408 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, | 1209 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, |
1409 false, false, &mouse_event_flags); | 1210 false, false, &mouse_event_flags); |
1410 EXPECT_EQ(run_result, nullptr); | 1211 EXPECT_EQ(run_result, nullptr); |
1411 | 1212 |
1412 // Show a sub menu to target with a pointer selection. However have the event | 1213 // Show a sub menu to target with a pointer selection. However have the event |
(...skipping 16 matching lines...) Expand all Loading... |
1429 sub_menu->Close(); | 1230 sub_menu->Close(); |
1430 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 1231 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
1431 } | 1232 } |
1432 | 1233 |
1433 // Tests that having the MenuController deleted during OnGestureEvent does not | 1234 // Tests that having the MenuController deleted during OnGestureEvent does not |
1434 // cause a crash. ASAN bots should not detect use-after-free in MenuController. | 1235 // cause a crash. ASAN bots should not detect use-after-free in MenuController. |
1435 TEST_F(MenuControllerTest, AsynchronousGestureDeletesController) { | 1236 TEST_F(MenuControllerTest, AsynchronousGestureDeletesController) { |
1436 MenuController* controller = menu_controller(); | 1237 MenuController* controller = menu_controller(); |
1437 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | 1238 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( |
1438 new TestMenuControllerDelegate()); | 1239 new TestMenuControllerDelegate()); |
1439 ASSERT_FALSE(IsAsyncRun()); | |
1440 | 1240 |
1441 controller->AddNestedDelegate(nested_delegate.get()); | 1241 controller->AddNestedDelegate(nested_delegate.get()); |
1442 controller->SetAsyncRun(true); | |
1443 | |
1444 EXPECT_TRUE(IsAsyncRun()); | |
1445 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); | 1242 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); |
1446 | 1243 |
1447 MenuItemView* item = menu_item(); | 1244 MenuItemView* item = menu_item(); |
1448 int mouse_event_flags = 0; | 1245 int mouse_event_flags = 0; |
1449 MenuItemView* run_result = | 1246 MenuItemView* run_result = |
1450 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, | 1247 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, |
1451 false, false, &mouse_event_flags); | 1248 false, false, &mouse_event_flags); |
1452 EXPECT_EQ(run_result, nullptr); | 1249 EXPECT_EQ(run_result, nullptr); |
1453 | 1250 |
1454 // Show a sub menu to target with a tap event. | 1251 // Show a sub menu to target with a tap event. |
1455 SubmenuView* sub_menu = item->GetSubmenu(); | 1252 SubmenuView* sub_menu = item->GetSubmenu(); |
1456 sub_menu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), true); | 1253 sub_menu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), true); |
1457 | 1254 |
1458 gfx::Point location(sub_menu->bounds().CenterPoint()); | 1255 gfx::Point location(sub_menu->bounds().CenterPoint()); |
1459 ui::GestureEvent event(location.x(), location.y(), 0, ui::EventTimeForNow(), | 1256 ui::GestureEvent event(location.x(), location.y(), 0, ui::EventTimeForNow(), |
1460 ui::GestureEventDetails(ui::ET_GESTURE_TAP)); | 1257 ui::GestureEventDetails(ui::ET_GESTURE_TAP)); |
1461 | 1258 |
1462 // This will lead to MenuController being deleted during the processing of the | 1259 // This will lead to MenuController being deleted during the processing of the |
1463 // gesture event. The remainder of this test, and TearDown should not crash. | 1260 // gesture event. The remainder of this test, and TearDown should not crash. |
1464 DestroyMenuControllerOnMenuClosed(nested_delegate.get()); | 1261 DestroyMenuControllerOnMenuClosed(nested_delegate.get()); |
1465 controller->OnGestureEvent(sub_menu, &event); | 1262 controller->OnGestureEvent(sub_menu, &event); |
1466 | 1263 |
1467 // Close to remove observers before test TearDown | 1264 // Close to remove observers before test TearDown |
1468 sub_menu->Close(); | 1265 sub_menu->Close(); |
1469 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 1266 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
1470 } | 1267 } |
1471 | 1268 |
1472 // Tests that when an asynchronous menu is nested, and the nested message loop | |
1473 // is kill not by the MenuController, that the nested menu is notified of | |
1474 // destruction. | |
1475 TEST_F(MenuControllerTest, NestedMessageLoopDiesWithNestedMenu) { | |
1476 menu_controller()->CancelAll(); | |
1477 InstallTestMenuMessageLoop(); | |
1478 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( | |
1479 new TestMenuControllerDelegate()); | |
1480 // This will nest an asynchronous menu, and then kill the nested message loop. | |
1481 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
1482 FROM_HERE, | |
1483 base::Bind(&MenuControllerTest::TestNestedMessageLoopKillsItself, | |
1484 base::Unretained(this), nested_delegate.get())); | |
1485 | |
1486 int result_event_flags = 0; | |
1487 // This creates a nested message loop. | |
1488 EXPECT_EQ(nullptr, menu_controller()->Run(owner(), nullptr, menu_item(), | |
1489 gfx::Rect(), MENU_ANCHOR_TOPLEFT, | |
1490 false, false, &result_event_flags)); | |
1491 EXPECT_FALSE(menu_controller_delegate()->on_menu_closed_called()); | |
1492 EXPECT_TRUE(nested_delegate->on_menu_closed_called()); | |
1493 } | |
1494 | |
1495 #if defined(USE_AURA) | 1269 #if defined(USE_AURA) |
1496 // Tests that when a synchronous menu receives a cancel event, that it closes. | |
1497 TEST_F(MenuControllerTest, SynchronousCancelEvent) { | |
1498 ExitMenuRun(); | |
1499 // Post actual test to run once the menu has created a nested message loop. | |
1500 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
1501 FROM_HERE, | |
1502 base::Bind(&MenuControllerTest::TestCancelEvent, base::Unretained(this))); | |
1503 int mouse_event_flags = 0; | |
1504 MenuItemView* run_result = menu_controller()->Run( | |
1505 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false, | |
1506 false, &mouse_event_flags); | |
1507 EXPECT_EQ(run_result, nullptr); | |
1508 } | |
1509 | |
1510 // Tests that when an asynchronous menu receives a cancel event, that it closes. | 1270 // Tests that when an asynchronous menu receives a cancel event, that it closes. |
1511 TEST_F(MenuControllerTest, AsynchronousCancelEvent) { | 1271 TEST_F(MenuControllerTest, AsynchronousCancelEvent) { |
1512 ExitMenuRun(); | 1272 ExitMenuRun(); |
1513 MenuController* controller = menu_controller(); | 1273 MenuController* controller = menu_controller(); |
1514 controller->SetAsyncRun(true); | |
1515 | 1274 |
1516 int mouse_event_flags = 0; | 1275 int mouse_event_flags = 0; |
1517 MenuItemView* run_result = | 1276 MenuItemView* run_result = |
1518 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 1277 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1519 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1278 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1520 EXPECT_EQ(run_result, nullptr); | 1279 EXPECT_EQ(run_result, nullptr); |
1521 TestCancelEvent(); | 1280 EXPECT_EQ(MenuController::EXIT_NONE, controller->exit_type()); |
| 1281 ui::CancelModeEvent cancel_event; |
| 1282 event_generator()->Dispatch(&cancel_event); |
| 1283 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
1522 } | 1284 } |
1523 | 1285 |
1524 // Tests that if a menu is ran without a widget, that MenuPreTargetHandler does | 1286 // Tests that if a menu is ran without a widget, that MenuPreTargetHandler does |
1525 // not cause a crash. | 1287 // not cause a crash. |
1526 TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) { | 1288 TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) { |
1527 ExitMenuRun(); | 1289 ExitMenuRun(); |
1528 MenuController* controller = menu_controller(); | 1290 MenuController* controller = menu_controller(); |
1529 controller->SetAsyncRun(true); | |
1530 int mouse_event_flags = 0; | 1291 int mouse_event_flags = 0; |
1531 MenuItemView* run_result = | 1292 MenuItemView* run_result = |
1532 controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(), | 1293 controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(), |
1533 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1294 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1534 EXPECT_EQ(run_result, nullptr); | 1295 EXPECT_EQ(run_result, nullptr); |
1535 } | 1296 } |
1536 | 1297 |
1537 // Tests that if a MenuController is destroying during drag/drop, and another | 1298 // Tests that if a MenuController is destroying during drag/drop, and another |
1538 // MenuController becomes active, that the exiting of drag does not cause a | 1299 // MenuController becomes active, that the exiting of drag does not cause a |
1539 // crash. | 1300 // crash. |
(...skipping 10 matching lines...) Expand all Loading... |
1550 ->GetNativeWindow() | 1311 ->GetNativeWindow() |
1551 ->GetRootWindow(), | 1312 ->GetRootWindow(), |
1552 &drag_drop_client); | 1313 &drag_drop_client); |
1553 StartDrag(); | 1314 StartDrag(); |
1554 } | 1315 } |
1555 | 1316 |
1556 // Tests that if a CancelAll is called during drag-and-drop that it does not | 1317 // Tests that if a CancelAll is called during drag-and-drop that it does not |
1557 // destroy the MenuController. On Windows and Linux this destruction also | 1318 // destroy the MenuController. On Windows and Linux this destruction also |
1558 // destroys the Widget used for drag-and-drop, thereby ending the drag. | 1319 // destroys the Widget used for drag-and-drop, thereby ending the drag. |
1559 TEST_F(MenuControllerTest, CancelAllDuringDrag) { | 1320 TEST_F(MenuControllerTest, CancelAllDuringDrag) { |
1560 MenuController* controller = menu_controller(); | |
1561 controller->SetAsyncRun(true); | |
1562 | |
1563 // Build the menu so that the appropriate root window is available to set the | 1321 // Build the menu so that the appropriate root window is available to set the |
1564 // drag drop client on. | 1322 // drag drop client on. |
1565 AddButtonMenuItems(); | 1323 AddButtonMenuItems(); |
1566 TestDragDropClient drag_drop_client(base::Bind( | 1324 TestDragDropClient drag_drop_client(base::Bind( |
1567 &MenuControllerTest::TestCancelAllDuringDrag, base::Unretained(this))); | 1325 &MenuControllerTest::TestCancelAllDuringDrag, base::Unretained(this))); |
1568 aura::client::SetDragDropClient(menu_item() | 1326 aura::client::SetDragDropClient(menu_item() |
1569 ->GetSubmenu() | 1327 ->GetSubmenu() |
1570 ->GetWidget() | 1328 ->GetWidget() |
1571 ->GetNativeWindow() | 1329 ->GetNativeWindow() |
1572 ->GetRootWindow(), | 1330 ->GetRootWindow(), |
1573 &drag_drop_client); | 1331 &drag_drop_client); |
1574 StartDrag(); | 1332 StartDrag(); |
1575 } | 1333 } |
1576 | 1334 |
1577 // Tests that when releasing the ref on ViewsDelegate and MenuController is | 1335 // Tests that when releasing the ref on ViewsDelegate and MenuController is |
1578 // deleted, that shutdown occurs without crashing. | 1336 // deleted, that shutdown occurs without crashing. |
1579 TEST_F(MenuControllerTest, DestroyedDuringViewsRelease) { | 1337 TEST_F(MenuControllerTest, DestroyedDuringViewsRelease) { |
1580 ExitMenuRun(); | 1338 ExitMenuRun(); |
1581 MenuController* controller = menu_controller(); | 1339 MenuController* controller = menu_controller(); |
1582 controller->SetAsyncRun(true); | |
1583 | 1340 |
1584 int mouse_event_flags = 0; | 1341 int mouse_event_flags = 0; |
1585 MenuItemView* run_result = | 1342 MenuItemView* run_result = |
1586 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 1343 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
1587 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1344 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
1588 EXPECT_EQ(run_result, nullptr); | 1345 EXPECT_EQ(run_result, nullptr); |
1589 TestDestroyedDuringViewsRelease(); | 1346 TestDestroyedDuringViewsRelease(); |
1590 } | 1347 } |
1591 | 1348 |
1592 // Tests that when a context menu is opened above an empty menu item, and a | 1349 // Tests that when a context menu is opened above an empty menu item, and a |
1593 // right-click occurs over the empty item, that the bottom menu is not hidden, | 1350 // right-click occurs over the empty item, that the bottom menu is not hidden, |
1594 // that a request to relaunch the context menu is received, and that | 1351 // that a request to relaunch the context menu is received, and that |
1595 // subsequently pressing ESC does not crash the browser. | 1352 // subsequently pressing ESC does not crash the browser. |
1596 TEST_F(MenuControllerTest, RepostEventToEmptyMenuItem) { | 1353 TEST_F(MenuControllerTest, RepostEventToEmptyMenuItem) { |
1597 // Setup a submenu. Additionally hook up appropriate Widget and View | 1354 // Setup a submenu. Additionally hook up appropriate Widget and View |
1598 // containers, with bounds, so that hit testing works. | 1355 // containers, with bounds, so that hit testing works. |
1599 MenuController* controller = menu_controller(); | 1356 MenuController* controller = menu_controller(); |
1600 controller->SetAsyncRun(true); | |
1601 MenuItemView* base_menu = menu_item(); | 1357 MenuItemView* base_menu = menu_item(); |
1602 base_menu->SetBounds(0, 0, 200, 200); | 1358 base_menu->SetBounds(0, 0, 200, 200); |
1603 SubmenuView* base_submenu = base_menu->GetSubmenu(); | 1359 SubmenuView* base_submenu = base_menu->GetSubmenu(); |
1604 base_submenu->SetBounds(0, 0, 200, 200); | 1360 base_submenu->SetBounds(0, 0, 200, 200); |
1605 base_submenu->ShowAt(owner(), gfx::Rect(0, 0, 200, 200), false); | 1361 base_submenu->ShowAt(owner(), gfx::Rect(0, 0, 200, 200), false); |
1606 GetMenuHost(base_submenu) | 1362 GetMenuHost(base_submenu) |
1607 ->SetContentsView(base_submenu->GetScrollViewContainer()); | 1363 ->SetContentsView(base_submenu->GetScrollViewContainer()); |
1608 | 1364 |
1609 // Build the submenu to have an empty menu item. Additionally hook up | 1365 // Build the submenu to have an empty menu item. Additionally hook up |
1610 // appropriate Widget and View containersm with counds, so that hit testing | 1366 // appropriate Widget and View containersm with counds, so that hit testing |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 // crash. | 1455 // crash. |
1700 TestAsyncEscapeKey(); | 1456 TestAsyncEscapeKey(); |
1701 EXPECT_EQ(nested_controller_delegate_2->on_menu_closed_called(), 1); | 1457 EXPECT_EQ(nested_controller_delegate_2->on_menu_closed_called(), 1); |
1702 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate()); | 1458 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate()); |
1703 } | 1459 } |
1704 | 1460 |
1705 #endif // defined(USE_AURA) | 1461 #endif // defined(USE_AURA) |
1706 | 1462 |
1707 } // namespace test | 1463 } // namespace test |
1708 } // namespace views | 1464 } // namespace views |
OLD | NEW |