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/macros.h" | 7 #include "base/macros.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "ui/aura/scoped_window_targeter.h" | 10 #include "ui/aura/scoped_window_targeter.h" |
11 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
| 12 #include "ui/events/event.h" |
| 13 #include "ui/events/event_constants.h" |
12 #include "ui/events/event_handler.h" | 14 #include "ui/events/event_handler.h" |
| 15 #include "ui/events/event_utils.h" |
13 #include "ui/events/null_event_targeter.h" | 16 #include "ui/events/null_event_targeter.h" |
14 #include "ui/events/test/event_generator.h" | 17 #include "ui/events/test/event_generator.h" |
| 18 #include "ui/gfx/geometry/point.h" |
| 19 #include "ui/gfx/geometry/rect.h" |
15 #include "ui/views/controls/menu/menu_controller_delegate.h" | 20 #include "ui/views/controls/menu/menu_controller_delegate.h" |
16 #include "ui/views/controls/menu/menu_delegate.h" | 21 #include "ui/views/controls/menu/menu_delegate.h" |
17 #include "ui/views/controls/menu/menu_item_view.h" | 22 #include "ui/views/controls/menu/menu_item_view.h" |
18 #include "ui/views/controls/menu/menu_message_loop.h" | 23 #include "ui/views/controls/menu/menu_message_loop.h" |
19 #include "ui/views/controls/menu/submenu_view.h" | 24 #include "ui/views/controls/menu/submenu_view.h" |
20 #include "ui/views/test/views_test_base.h" | 25 #include "ui/views/test/views_test_base.h" |
21 | 26 |
22 #if defined(OS_WIN) | 27 #if defined(OS_WIN) |
23 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" | 28 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h" |
24 #endif | 29 #endif |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 384 |
380 void SetDropMenuItem(MenuItemView* target, | 385 void SetDropMenuItem(MenuItemView* target, |
381 MenuDelegate::DropPosition position) { | 386 MenuDelegate::DropPosition position) { |
382 menu_controller_->SetDropMenuItem(target, position); | 387 menu_controller_->SetDropMenuItem(target, position); |
383 } | 388 } |
384 | 389 |
385 void SetIsCombobox(bool is_combobox) { | 390 void SetIsCombobox(bool is_combobox) { |
386 menu_controller_->set_is_combobox(is_combobox); | 391 menu_controller_->set_is_combobox(is_combobox); |
387 } | 392 } |
388 | 393 |
| 394 void SetSelectionOnPointerDown(SubmenuView* source, |
| 395 const ui::LocatedEvent* event) { |
| 396 menu_controller_->SetSelectionOnPointerDown(source, event); |
| 397 } |
| 398 |
389 void RunMenu() { | 399 void RunMenu() { |
390 menu_controller_->message_loop_depth_++; | 400 menu_controller_->message_loop_depth_++; |
391 menu_controller_->RunMessageLoop(false); | 401 menu_controller_->RunMessageLoop(false); |
392 menu_controller_->message_loop_depth_--; | 402 menu_controller_->message_loop_depth_--; |
393 } | 403 } |
394 | 404 |
395 void Accept(MenuItemView* item, int event_flags) { | 405 void Accept(MenuItemView* item, int event_flags) { |
396 menu_controller_->Accept(item, event_flags); | 406 menu_controller_->Accept(item, event_flags); |
397 } | 407 } |
398 | 408 |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 MenuItemView* run_result = | 828 MenuItemView* run_result = |
819 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), | 829 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), |
820 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); | 830 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); |
821 EXPECT_EQ(run_result, nullptr); | 831 EXPECT_EQ(run_result, nullptr); |
822 | 832 |
823 controller->CancelAll(); | 833 controller->CancelAll(); |
824 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 834 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
825 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); | 835 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
826 } | 836 } |
827 | 837 |
| 838 // Tests that an asynchronous menu nested within a synchronous menu does not |
| 839 // crash when trying to repost events that occur outside of the bounds of the |
| 840 // menu. Instead a proper shutdown should occur. |
| 841 TEST_F(MenuControllerTest, AsynchronousRepostEvent) { |
| 842 MenuController* controller = menu_controller(); |
| 843 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
| 844 scoped_ptr<TestMenuControllerDelegate> nested_delegate( |
| 845 new TestMenuControllerDelegate()); |
| 846 |
| 847 ASSERT_FALSE(IsAsyncRun()); |
| 848 |
| 849 controller->AddNestedDelegate(nested_delegate.get()); |
| 850 controller->SetAsyncRun(true); |
| 851 |
| 852 EXPECT_TRUE(IsAsyncRun()); |
| 853 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); |
| 854 |
| 855 MenuItemView* item = menu_item(); |
| 856 int mouse_event_flags = 0; |
| 857 MenuItemView* run_result = |
| 858 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, |
| 859 false, false, &mouse_event_flags); |
| 860 EXPECT_EQ(run_result, nullptr); |
| 861 |
| 862 // Show a sub menu to targert with a pointer selection. However have the event |
| 863 // occur outside of the bounds of the entire menu. |
| 864 SubmenuView* sub_menu = item->GetSubmenu(); |
| 865 sub_menu->ShowAt(owner(), item->bounds(), false); |
| 866 gfx::Point location(sub_menu->bounds().bottom_right()); |
| 867 location.Offset(1, 1); |
| 868 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location, |
| 869 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); |
| 870 |
| 871 // When attempting to select outside of all menus this should lead to a |
| 872 // shutdown. This should not crash while attempting to repost the event. |
| 873 SetSelectionOnPointerDown(sub_menu, &event); |
| 874 |
| 875 EXPECT_FALSE(IsAsyncRun()); |
| 876 EXPECT_EQ(delegate, GetCurrentDelegate()); |
| 877 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
| 878 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); |
| 879 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); |
| 880 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); |
| 881 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 882 nested_delegate->on_menu_closed_notify_type()); |
| 883 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
| 884 } |
| 885 |
| 886 // Tests that an asynchronous menu reposts touch events that occur outside of |
| 887 // the bounds of the menu, and that the menu closes. |
| 888 TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) { |
| 889 MenuController* controller = menu_controller(); |
| 890 TestMenuControllerDelegate* delegate = menu_controller_delegate(); |
| 891 controller->SetAsyncRun(true); |
| 892 |
| 893 // Show a sub menu to targert with a touch event. However have the event occur |
| 894 // outside of the bounds of the entire menu. |
| 895 MenuItemView* item = menu_item(); |
| 896 SubmenuView* sub_menu = item->GetSubmenu(); |
| 897 sub_menu->ShowAt(owner(), item->bounds(), false); |
| 898 gfx::Point location(sub_menu->bounds().bottom_right()); |
| 899 location.Offset(1, 1); |
| 900 ui::TouchEvent event(ui::ET_TOUCH_PRESSED, location, 0, 0, |
| 901 ui::EventTimeForNow(), 0, 0, 0, 0); |
| 902 controller->OnTouchEvent(sub_menu, &event); |
| 903 |
| 904 EXPECT_FALSE(IsShowing()); |
| 905 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
| 906 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); |
| 907 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); |
| 908 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 909 delegate->on_menu_closed_notify_type()); |
| 910 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); |
| 911 } |
| 912 |
828 // Tests that if you exit all menus when an asynchrnous menu is nested within a | 913 // Tests that if you exit all menus when an asynchrnous menu is nested within a |
829 // synchronous menu, the message loop for the parent menu finishes running. | 914 // synchronous menu, the message loop for the parent menu finishes running. |
830 TEST_F(MenuControllerTest, AsynchronousNestedExitAll) { | 915 TEST_F(MenuControllerTest, AsynchronousNestedExitAll) { |
831 InstallTestMenuMessageLoop(); | 916 InstallTestMenuMessageLoop(); |
832 | 917 |
833 base::MessageLoopForUI::current()->PostTask( | 918 base::MessageLoopForUI::current()->PostTask( |
834 FROM_HERE, base::Bind(&MenuControllerTest::TestAsynchronousNestedExitAll, | 919 FROM_HERE, base::Bind(&MenuControllerTest::TestAsynchronousNestedExitAll, |
835 base::Unretained(this))); | 920 base::Unretained(this))); |
836 | 921 |
837 RunMenu(); | 922 RunMenu(); |
838 } | 923 } |
839 | 924 |
840 // Tests that if you exit the nested menu when an asynchrnous menu is nested | 925 // Tests that if you exit the nested menu when an asynchrnous menu is nested |
841 // within a synchronous menu, the message loop for the parent menu remains | 926 // within a synchronous menu, the message loop for the parent menu remains |
842 // running. | 927 // running. |
843 TEST_F(MenuControllerTest, AsynchronousNestedExitOutermost) { | 928 TEST_F(MenuControllerTest, AsynchronousNestedExitOutermost) { |
844 InstallTestMenuMessageLoop(); | 929 InstallTestMenuMessageLoop(); |
845 | 930 |
846 base::MessageLoopForUI::current()->PostTask( | 931 base::MessageLoopForUI::current()->PostTask( |
847 FROM_HERE, | 932 FROM_HERE, |
848 base::Bind(&MenuControllerTest::TestAsynchronousNestedExitOutermost, | 933 base::Bind(&MenuControllerTest::TestAsynchronousNestedExitOutermost, |
849 base::Unretained(this))); | 934 base::Unretained(this))); |
850 | 935 |
851 RunMenu(); | 936 RunMenu(); |
852 } | 937 } |
853 | 938 |
854 } // namespace test | 939 } // namespace test |
855 } // namespace views | 940 } // namespace views |
OLD | NEW |