| 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" |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 public: | 271 public: |
| 272 TestMenuItemViewShown(MenuDelegate* delegate) : MenuItemView(delegate) { | 272 TestMenuItemViewShown(MenuDelegate* delegate) : MenuItemView(delegate) { |
| 273 submenu_ = new SubmenuViewShown(this); | 273 submenu_ = new SubmenuViewShown(this); |
| 274 } | 274 } |
| 275 ~TestMenuItemViewShown() override {} | 275 ~TestMenuItemViewShown() override {} |
| 276 | 276 |
| 277 void SetController(MenuController* controller) { | 277 void SetController(MenuController* controller) { |
| 278 set_controller(controller); | 278 set_controller(controller); |
| 279 } | 279 } |
| 280 | 280 |
| 281 void AddEmptyMenusForTest() { AddEmptyMenus(); } |
| 282 |
| 281 private: | 283 private: |
| 282 DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewShown); | 284 DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewShown); |
| 283 }; | 285 }; |
| 284 | 286 |
| 285 class MenuControllerTest : public ViewsTestBase { | 287 class MenuControllerTest : public ViewsTestBase { |
| 286 public: | 288 public: |
| 287 MenuControllerTest() : menu_controller_(nullptr) { | 289 MenuControllerTest() : menu_controller_(nullptr) { |
| 288 } | 290 } |
| 289 | 291 |
| 290 ~MenuControllerTest() override {} | 292 ~MenuControllerTest() override {} |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 owner()->GetNativeWindow()->GetRootWindow(), | 326 owner()->GetNativeWindow()->GetRootWindow(), |
| 325 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter)); | 327 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter)); |
| 326 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); | 328 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); |
| 327 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type()); | 329 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type()); |
| 328 } | 330 } |
| 329 // Now that the targeter has been destroyed, expect to exit the menu | 331 // Now that the targeter has been destroyed, expect to exit the menu |
| 330 // normally when hitting escape. | 332 // normally when hitting escape. |
| 331 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); | 333 event_generator_->PressKey(ui::VKEY_ESCAPE, 0); |
| 332 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); | 334 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); |
| 333 } | 335 } |
| 336 #endif // defined(OS_LINUX) && defined(USE_X11 |
| 334 | 337 |
| 338 #if defined(USE_AURA) |
| 335 // Verifies that a non-nested menu fully closes when receiving an escape key. | 339 // Verifies that a non-nested menu fully closes when receiving an escape key. |
| 336 void TestAsyncEscapeKey() { | 340 void TestAsyncEscapeKey() { |
| 337 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); | 341 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); |
| 338 menu_controller_->OnWillDispatchKeyEvent(&event); | 342 menu_controller_->OnWillDispatchKeyEvent(&event); |
| 339 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); | |
| 340 } | 343 } |
| 341 | 344 |
| 342 #endif // defined(OS_LINUX) && defined(USE_X11) | |
| 343 | |
| 344 #if defined(USE_AURA) | |
| 345 // Verifies that an open menu receives a cancel event, and closes. | 345 // Verifies that an open menu receives a cancel event, and closes. |
| 346 void TestCancelEvent() { | 346 void TestCancelEvent() { |
| 347 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type()); | 347 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type()); |
| 348 ui::CancelModeEvent cancel_event; | 348 ui::CancelModeEvent cancel_event; |
| 349 event_generator_->Dispatch(&cancel_event); | 349 event_generator_->Dispatch(&cancel_event); |
| 350 EXPECT_EQ(MenuController::EXIT_ALL, menu_controller_->exit_type()); | 350 EXPECT_EQ(MenuController::EXIT_ALL, menu_controller_->exit_type()); |
| 351 } | 351 } |
| 352 #endif // defined(USE_AURA) | 352 #endif // defined(USE_AURA) |
| 353 | 353 |
| 354 // Verifies the state of the |menu_controller_| before destroying it. | 354 // Verifies the state of the |menu_controller_| before destroying it. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 &MenuControllerTest::DestroyMenuController, base::Unretained(this))); | 452 &MenuControllerTest::DestroyMenuController, base::Unretained(this))); |
| 453 menu_controller_->ExitAsyncRun(); | 453 menu_controller_->ExitAsyncRun(); |
| 454 } | 454 } |
| 455 | 455 |
| 456 protected: | 456 protected: |
| 457 void SetPendingStateItem(MenuItemView* item) { | 457 void SetPendingStateItem(MenuItemView* item) { |
| 458 menu_controller_->pending_state_.item = item; | 458 menu_controller_->pending_state_.item = item; |
| 459 menu_controller_->pending_state_.submenu_open = true; | 459 menu_controller_->pending_state_.submenu_open = true; |
| 460 } | 460 } |
| 461 | 461 |
| 462 void SetState(MenuItemView* item) { |
| 463 menu_controller_->state_.item = item; |
| 464 menu_controller_->state_.submenu_open = true; |
| 465 } |
| 466 |
| 462 void ResetSelection() { | 467 void ResetSelection() { |
| 463 menu_controller_->SetSelection( | 468 menu_controller_->SetSelection( |
| 464 nullptr, | 469 nullptr, |
| 465 MenuController::SELECTION_EXIT | | 470 MenuController::SELECTION_EXIT | |
| 466 MenuController::SELECTION_UPDATE_IMMEDIATELY); | 471 MenuController::SELECTION_UPDATE_IMMEDIATELY); |
| 467 } | 472 } |
| 468 | 473 |
| 469 void IncrementSelection() { | 474 void IncrementSelection() { |
| 470 menu_controller_->IncrementSelection( | 475 menu_controller_->IncrementSelection( |
| 471 MenuController::INCREMENT_SELECTION_DOWN); | 476 MenuController::INCREMENT_SELECTION_DOWN); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 menu_controller_->set_is_combobox(is_combobox); | 542 menu_controller_->set_is_combobox(is_combobox); |
| 538 } | 543 } |
| 539 | 544 |
| 540 void SetSelectionOnPointerDown(SubmenuView* source, | 545 void SetSelectionOnPointerDown(SubmenuView* source, |
| 541 const ui::LocatedEvent* event) { | 546 const ui::LocatedEvent* event) { |
| 542 menu_controller_->SetSelectionOnPointerDown(source, event); | 547 menu_controller_->SetSelectionOnPointerDown(source, event); |
| 543 } | 548 } |
| 544 | 549 |
| 545 // Note that coordinates of events passed to MenuController must be in that of | 550 // Note that coordinates of events passed to MenuController must be in that of |
| 546 // the MenuScrollViewContainer. | 551 // the MenuScrollViewContainer. |
| 552 void ProcessMousePressed(SubmenuView* source, const ui::MouseEvent& event) { |
| 553 menu_controller_->OnMousePressed(source, event); |
| 554 } |
| 555 |
| 556 void ProcessMouseDragged(SubmenuView* source, const ui::MouseEvent& event) { |
| 557 menu_controller_->OnMouseDragged(source, event); |
| 558 } |
| 559 |
| 547 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) { | 560 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) { |
| 548 menu_controller_->OnMouseMoved(source, event); | 561 menu_controller_->OnMouseMoved(source, event); |
| 549 } | 562 } |
| 550 | 563 |
| 564 void ProcessMouseReleased(SubmenuView* source, const ui::MouseEvent& event) { |
| 565 menu_controller_->OnMouseReleased(source, event); |
| 566 } |
| 567 |
| 551 void RunMenu() { | 568 void RunMenu() { |
| 552 #if defined(USE_AURA) | 569 #if defined(USE_AURA) |
| 553 std::unique_ptr<MenuPreTargetHandler> menu_pre_target_handler( | 570 std::unique_ptr<MenuPreTargetHandler> menu_pre_target_handler( |
| 554 new MenuPreTargetHandler(menu_controller_, owner_.get())); | 571 new MenuPreTargetHandler(menu_controller_, owner_.get())); |
| 555 #endif | 572 #endif |
| 556 | 573 |
| 557 menu_controller_->message_loop_depth_++; | 574 menu_controller_->message_loop_depth_++; |
| 558 menu_controller_->RunMessageLoop(); | 575 menu_controller_->RunMessageLoop(); |
| 559 menu_controller_->message_loop_depth_--; | 576 menu_controller_->message_loop_depth_--; |
| 560 } | 577 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 574 void StartDrag() { | 591 void StartDrag() { |
| 575 const gfx::Point location; | 592 const gfx::Point location; |
| 576 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0); | 593 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0); |
| 577 menu_controller_->StartDrag( | 594 menu_controller_->StartDrag( |
| 578 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location); | 595 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location); |
| 579 } | 596 } |
| 580 | 597 |
| 581 Widget* owner() { return owner_.get(); } | 598 Widget* owner() { return owner_.get(); } |
| 582 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } | 599 ui::test::EventGenerator* event_generator() { return event_generator_.get(); } |
| 583 TestMenuItemViewShown* menu_item() { return menu_item_.get(); } | 600 TestMenuItemViewShown* menu_item() { return menu_item_.get(); } |
| 601 TestMenuDelegate* menu_delegate() { return menu_delegate_.get(); } |
| 584 TestMenuControllerDelegate* menu_controller_delegate() { | 602 TestMenuControllerDelegate* menu_controller_delegate() { |
| 585 return menu_controller_delegate_.get(); | 603 return menu_controller_delegate_.get(); |
| 586 } | 604 } |
| 587 MenuController* menu_controller() { return menu_controller_; } | 605 MenuController* menu_controller() { return menu_controller_; } |
| 588 const MenuItemView* pending_state_item() const { | 606 const MenuItemView* pending_state_item() const { |
| 589 return menu_controller_->pending_state_.item; | 607 return menu_controller_->pending_state_.item; |
| 590 } | 608 } |
| 591 MenuController::ExitType menu_exit_type() const { | 609 MenuController::ExitType menu_exit_type() const { |
| 592 return menu_controller_->exit_type_; | 610 return menu_controller_->exit_type_; |
| 593 } | 611 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 menu_item_->SetController(menu_controller_); | 686 menu_item_->SetController(menu_controller_); |
| 669 } | 687 } |
| 670 | 688 |
| 671 // Not owned. | 689 // Not owned. |
| 672 DestructingTestViewsDelegate* test_views_delegate_; | 690 DestructingTestViewsDelegate* test_views_delegate_; |
| 673 | 691 |
| 674 std::unique_ptr<Widget> owner_; | 692 std::unique_ptr<Widget> owner_; |
| 675 std::unique_ptr<ui::test::EventGenerator> event_generator_; | 693 std::unique_ptr<ui::test::EventGenerator> event_generator_; |
| 676 std::unique_ptr<TestMenuItemViewShown> menu_item_; | 694 std::unique_ptr<TestMenuItemViewShown> menu_item_; |
| 677 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_; | 695 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_; |
| 678 std::unique_ptr<MenuDelegate> menu_delegate_; | 696 std::unique_ptr<TestMenuDelegate> menu_delegate_; |
| 679 MenuController* menu_controller_; | 697 MenuController* menu_controller_; |
| 680 TestMenuMessageLoop* test_message_loop_; | 698 TestMenuMessageLoop* test_message_loop_; |
| 681 | 699 |
| 682 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); | 700 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); |
| 683 }; | 701 }; |
| 684 | 702 |
| 685 #if defined(OS_LINUX) && defined(USE_X11) | 703 #if defined(OS_LINUX) && defined(USE_X11) |
| 686 // Tests that an event targeter which blocks events will be honored by the menu | 704 // Tests that an event targeter which blocks events will be honored by the menu |
| 687 // event dispatcher. | 705 // event dispatcher. |
| 688 TEST_F(MenuControllerTest, EventTargeter) { | 706 TEST_F(MenuControllerTest, EventTargeter) { |
| 689 base::ThreadTaskRunnerHandle::Get()->PostTask( | 707 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 690 FROM_HERE, base::Bind(&MenuControllerTest::TestEventTargeter, | 708 FROM_HERE, base::Bind(&MenuControllerTest::TestEventTargeter, |
| 691 base::Unretained(this))); | 709 base::Unretained(this))); |
| 692 RunMenu(); | 710 RunMenu(); |
| 693 } | 711 } |
| 694 | 712 |
| 695 // Tests that an non-nested menu receiving an escape key will fully shut. This | 713 // Tests that an non-nested menu receiving an escape key will fully shut. This |
| 696 // should not crash by attempting to retarget the key to an inner menu. | 714 // should not crash by attempting to retarget the key to an inner menu. |
| 697 TEST_F(MenuControllerTest, AsyncEscapeKey) { | 715 TEST_F(MenuControllerTest, AsyncEscapeKey) { |
| 698 menu_controller()->SetAsyncRun(true); | 716 menu_controller()->SetAsyncRun(true); |
| 699 TestAsyncEscapeKey(); | 717 TestAsyncEscapeKey(); |
| 718 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); |
| 700 } | 719 } |
| 701 | 720 |
| 702 #endif // defined(OS_LINUX) && defined(USE_X11) | 721 #endif // defined(OS_LINUX) && defined(USE_X11) |
| 703 | 722 |
| 704 #if defined(USE_X11) | 723 #if defined(USE_X11) |
| 705 // Tests that touch event ids are released correctly. See crbug.com/439051 for | 724 // Tests that touch event ids are released correctly. See crbug.com/439051 for |
| 706 // details. When the ids aren't managed correctly, we get stuck down touches. | 725 // details. When the ids aren't managed correctly, we get stuck down touches. |
| 707 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { | 726 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { |
| 708 TestEventHandler test_event_handler; | 727 TestEventHandler test_event_handler; |
| 709 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( | 728 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( |
| (...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 controller->SetAsyncRun(true); | 1582 controller->SetAsyncRun(true); |
| 1564 | 1583 |
| 1565 int mouse_event_flags = 0; | 1584 int mouse_event_flags = 0; |
| 1566 MenuItemView* run_result = | 1585 MenuItemView* run_result = |
| 1567 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 1586 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
| 1568 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 1587 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
| 1569 EXPECT_EQ(run_result, nullptr); | 1588 EXPECT_EQ(run_result, nullptr); |
| 1570 TestDestroyedDuringViewsRelease(); | 1589 TestDestroyedDuringViewsRelease(); |
| 1571 } | 1590 } |
| 1572 | 1591 |
| 1592 // 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, |
| 1594 // that a request to relaunch the context menu is received, and that |
| 1595 // subsequently pressing ESC does not crash the browser. |
| 1596 TEST_F(MenuControllerTest, RepostEventToEmptyMenuItem) { |
| 1597 // Setup a submenu. Additionally hook up appropriate Widget and View |
| 1598 // containers, with bounds, so that hit testing works. |
| 1599 MenuController* controller = menu_controller(); |
| 1600 controller->SetAsyncRun(true); |
| 1601 MenuItemView* base_menu = menu_item(); |
| 1602 base_menu->SetBounds(0, 0, 200, 200); |
| 1603 SubmenuView* base_submenu = base_menu->GetSubmenu(); |
| 1604 base_submenu->SetBounds(0, 0, 200, 200); |
| 1605 base_submenu->ShowAt(owner(), gfx::Rect(0, 0, 200, 200), false); |
| 1606 GetMenuHost(base_submenu) |
| 1607 ->SetContentsView(base_submenu->GetScrollViewContainer()); |
| 1608 |
| 1609 // Build the submenu to have an empty menu item. Additionally hook up |
| 1610 // appropriate Widget and View containersm with counds, so that hit testing |
| 1611 // works. |
| 1612 std::unique_ptr<TestMenuDelegate> sub_menu_item_delegate = |
| 1613 base::MakeUnique<TestMenuDelegate>(); |
| 1614 std::unique_ptr<TestMenuItemViewShown> sub_menu_item = |
| 1615 base::MakeUnique<TestMenuItemViewShown>(sub_menu_item_delegate.get()); |
| 1616 sub_menu_item->AddEmptyMenusForTest(); |
| 1617 sub_menu_item->SetController(controller); |
| 1618 sub_menu_item->SetBounds(0, 50, 50, 50); |
| 1619 base_submenu->AddChildView(sub_menu_item.get()); |
| 1620 SubmenuView* sub_menu_view = sub_menu_item->GetSubmenu(); |
| 1621 sub_menu_view->SetBounds(0, 50, 50, 50); |
| 1622 sub_menu_view->ShowAt(owner(), gfx::Rect(0, 50, 50, 50), false); |
| 1623 GetMenuHost(sub_menu_view) |
| 1624 ->SetContentsView(sub_menu_view->GetScrollViewContainer()); |
| 1625 |
| 1626 // Set that the last selection target was the item which launches the submenu, |
| 1627 // as the empty item can never become a target. |
| 1628 SetPendingStateItem(sub_menu_item.get()); |
| 1629 |
| 1630 // Nest a context menu. |
| 1631 std::unique_ptr<TestMenuDelegate> nested_menu_delegate_1 = |
| 1632 base::MakeUnique<TestMenuDelegate>(); |
| 1633 std::unique_ptr<TestMenuItemViewShown> nested_menu_item_1 = |
| 1634 base::MakeUnique<TestMenuItemViewShown>(nested_menu_delegate_1.get()); |
| 1635 nested_menu_item_1->SetBounds(0, 0, 100, 100); |
| 1636 nested_menu_item_1->SetController(controller); |
| 1637 std::unique_ptr<TestMenuControllerDelegate> nested_controller_delegate_1 = |
| 1638 base::MakeUnique<TestMenuControllerDelegate>(); |
| 1639 controller->AddNestedDelegate(nested_controller_delegate_1.get()); |
| 1640 int mouse_event_flags = 0; |
| 1641 MenuItemView* run_result = controller->Run( |
| 1642 owner(), nullptr, nested_menu_item_1.get(), gfx::Rect(150, 50, 100, 100), |
| 1643 MENU_ANCHOR_TOPLEFT, true, false, &mouse_event_flags); |
| 1644 EXPECT_EQ(run_result, nullptr); |
| 1645 |
| 1646 SubmenuView* nested_menu_submenu = nested_menu_item_1->GetSubmenu(); |
| 1647 nested_menu_submenu->SetBounds(0, 0, 100, 100); |
| 1648 nested_menu_submenu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), false); |
| 1649 GetMenuHost(nested_menu_submenu) |
| 1650 ->SetContentsView(nested_menu_submenu->GetScrollViewContainer()); |
| 1651 |
| 1652 // Press down outside of the context menu, and within the empty menu item. |
| 1653 // This should close the first context menu. |
| 1654 gfx::Point press_location(sub_menu_view->bounds().CenterPoint()); |
| 1655 ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, press_location, |
| 1656 press_location, ui::EventTimeForNow(), |
| 1657 ui::EF_RIGHT_MOUSE_BUTTON, 0); |
| 1658 ProcessMousePressed(nested_menu_submenu, press_event); |
| 1659 EXPECT_EQ(nested_controller_delegate_1->on_menu_closed_called(), 1); |
| 1660 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate()); |
| 1661 |
| 1662 // While the current state is the menu item which launched the sub menu, cause |
| 1663 // a drag in the empty menu item. This should not hide the menu. |
| 1664 SetState(sub_menu_item.get()); |
| 1665 press_location.Offset(-5, 0); |
| 1666 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, press_location, |
| 1667 press_location, ui::EventTimeForNow(), |
| 1668 ui::EF_RIGHT_MOUSE_BUTTON, 0); |
| 1669 ProcessMouseDragged(sub_menu_view, drag_event); |
| 1670 EXPECT_EQ(menu_delegate()->will_hide_menu_count(), 0); |
| 1671 |
| 1672 // Release the mouse in the empty menu item, triggering a context menu |
| 1673 // request. |
| 1674 ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, press_location, |
| 1675 press_location, ui::EventTimeForNow(), |
| 1676 ui::EF_RIGHT_MOUSE_BUTTON, 0); |
| 1677 ProcessMouseReleased(sub_menu_view, release_event); |
| 1678 EXPECT_EQ(sub_menu_item_delegate->show_context_menu_count(), 1); |
| 1679 EXPECT_EQ(sub_menu_item_delegate->show_context_menu_source(), |
| 1680 sub_menu_item.get()); |
| 1681 |
| 1682 // Nest a context menu. |
| 1683 std::unique_ptr<TestMenuDelegate> nested_menu_delegate_2 = |
| 1684 base::MakeUnique<TestMenuDelegate>(); |
| 1685 std::unique_ptr<TestMenuItemViewShown> nested_menu_item_2 = |
| 1686 base::MakeUnique<TestMenuItemViewShown>(nested_menu_delegate_2.get()); |
| 1687 nested_menu_item_2->SetBounds(0, 0, 100, 100); |
| 1688 nested_menu_item_2->SetController(controller); |
| 1689 |
| 1690 std::unique_ptr<TestMenuControllerDelegate> nested_controller_delegate_2 = |
| 1691 base::MakeUnique<TestMenuControllerDelegate>(); |
| 1692 controller->AddNestedDelegate(nested_controller_delegate_2.get()); |
| 1693 run_result = controller->Run( |
| 1694 owner(), nullptr, nested_menu_item_2.get(), gfx::Rect(150, 50, 100, 100), |
| 1695 MENU_ANCHOR_TOPLEFT, true, false, &mouse_event_flags); |
| 1696 EXPECT_EQ(run_result, nullptr); |
| 1697 |
| 1698 // The escapce key should only close the nested menu. SelectByChar should not |
| 1699 // crash. |
| 1700 TestAsyncEscapeKey(); |
| 1701 EXPECT_EQ(nested_controller_delegate_2->on_menu_closed_called(), 1); |
| 1702 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate()); |
| 1703 } |
| 1704 |
| 1573 #endif // defined(USE_AURA) | 1705 #endif // defined(USE_AURA) |
| 1574 | 1706 |
| 1575 } // namespace test | 1707 } // namespace test |
| 1576 } // namespace views | 1708 } // namespace views |
| OLD | NEW |