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