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