| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/i18n/case_conversion.h" | 7 #include "base/i18n/case_conversion.h" |
| 8 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 state_.hot_button = hot_button_; | 426 state_.hot_button = hot_button_; |
| 427 hot_button_ = nullptr; | 427 hot_button_ = nullptr; |
| 428 // We're already showing, push the current state. | 428 // We're already showing, push the current state. |
| 429 menu_stack_.push_back(std::make_pair(state_, std::move(pressed_lock_))); | 429 menu_stack_.push_back(std::make_pair(state_, std::move(pressed_lock_))); |
| 430 | 430 |
| 431 // The context menu should be owned by the same parent. | 431 // The context menu should be owned by the same parent. |
| 432 DCHECK_EQ(owner_, parent); | 432 DCHECK_EQ(owner_, parent); |
| 433 } else { | 433 } else { |
| 434 showing_ = true; | 434 showing_ = true; |
| 435 | 435 |
| 436 // TODO(jonross): remove after tracking down the cause of | |
| 437 // (crbug.com/683087). | |
| 438 // If we are not showing we should be shutting down, this could lead to | |
| 439 // incorrect delegate states. | |
| 440 CHECK(!running_); | |
| 441 | |
| 442 if (owner_) | 436 if (owner_) |
| 443 owner_->RemoveObserver(this); | 437 owner_->RemoveObserver(this); |
| 444 owner_ = parent; | 438 owner_ = parent; |
| 445 if (owner_) | 439 if (owner_) |
| 446 owner_->AddObserver(this); | 440 owner_->AddObserver(this); |
| 447 | 441 |
| 448 #if defined(USE_AURA) | 442 #if defined(USE_AURA) |
| 449 // Only create a MenuPreTargetHandler for non-nested menus. Nested menus | 443 // Only create a MenuPreTargetHandler for non-nested menus. Nested menus |
| 450 // will use the existing one. | 444 // will use the existing one. |
| 451 menu_pre_target_handler_.reset(new MenuPreTargetHandler(this, owner_)); | 445 menu_pre_target_handler_.reset(new MenuPreTargetHandler(this, owner_)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 469 return NULL; | 463 return NULL; |
| 470 } | 464 } |
| 471 | 465 |
| 472 if (button) | 466 if (button) |
| 473 pressed_lock_.reset(new MenuButton::PressedLock(button)); | 467 pressed_lock_.reset(new MenuButton::PressedLock(button)); |
| 474 | 468 |
| 475 // Make sure Chrome doesn't attempt to shut down while the menu is showing. | 469 // Make sure Chrome doesn't attempt to shut down while the menu is showing. |
| 476 if (ViewsDelegate::GetInstance()) | 470 if (ViewsDelegate::GetInstance()) |
| 477 ViewsDelegate::GetInstance()->AddRef(); | 471 ViewsDelegate::GetInstance()->AddRef(); |
| 478 | 472 |
| 479 // TODO(jonross): remove after tracking down the cause of (crbug.com/683087). | |
| 480 // About to either exit and run async, or nest message loop. | |
| 481 running_ = true; | |
| 482 | |
| 483 if (async_run_) | 473 if (async_run_) |
| 484 return nullptr; | 474 return nullptr; |
| 485 | 475 |
| 486 // We need to turn on nestable tasks as in some situations (pressing alt-f for | 476 // We need to turn on nestable tasks as in some situations (pressing alt-f for |
| 487 // one) the menus are run from a task. If we don't do this and are invoked | 477 // one) the menus are run from a task. If we don't do this and are invoked |
| 488 // from a task none of the tasks we schedule are processed and the menu | 478 // from a task none of the tasks we schedule are processed and the menu |
| 489 // appears totally broken. | 479 // appears totally broken. |
| 490 message_loop_depth_++; | 480 message_loop_depth_++; |
| 491 DCHECK_LE(message_loop_depth_, 2); | 481 DCHECK_LE(message_loop_depth_, 2); |
| 492 RunMessageLoop(); | 482 RunMessageLoop(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 522 | 512 |
| 523 MenuItemView* selected = state_.item; | 513 MenuItemView* selected = state_.item; |
| 524 SetExitType(type); | 514 SetExitType(type); |
| 525 | 515 |
| 526 SendMouseCaptureLostToActiveView(); | 516 SendMouseCaptureLostToActiveView(); |
| 527 | 517 |
| 528 // Hide windows immediately. | 518 // Hide windows immediately. |
| 529 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); | 519 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); |
| 530 | 520 |
| 531 if (!blocking_run_) { | 521 if (!blocking_run_) { |
| 532 // TODO(jonross): remove after tracking down the cause of | |
| 533 // (crbug.com/683087). | |
| 534 bool nested = delegate_stack_.size() > 1; | |
| 535 CHECK(!nested); | |
| 536 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); | |
| 537 // If we didn't block the caller we need to notify the menu, which | 522 // If we didn't block the caller we need to notify the menu, which |
| 538 // triggers deleting us. | 523 // triggers deleting us. |
| 539 DCHECK(selected); | 524 DCHECK(selected); |
| 540 showing_ = false; | 525 showing_ = false; |
| 541 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 526 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 542 selected->GetRootMenuItem(), accept_event_flags_); | 527 selected->GetRootMenuItem(), accept_event_flags_); |
| 543 // WARNING: the call to MenuClosed deletes us. | 528 // WARNING: the call to MenuClosed deletes us. |
| 544 CHECK(!this_ref); | |
| 545 return; | 529 return; |
| 546 } | 530 } |
| 547 | 531 |
| 548 // If |type| is EXIT_ALL we update the state of the menu to not showing. For | 532 // If |type| is EXIT_ALL we update the state of the menu to not showing. For |
| 549 // dragging this ensures that the correct visual state is reported until the | 533 // dragging this ensures that the correct visual state is reported until the |
| 550 // drag operation completes. For non-dragging cases it is possible that the | 534 // drag operation completes. For non-dragging cases it is possible that the |
| 551 // release of ViewsDelegate leads immediately to shutdown, which can trigger | 535 // release of ViewsDelegate leads immediately to shutdown, which can trigger |
| 552 // nested calls to Cancel. We want to reject these to prevent attempting a | 536 // nested calls to Cancel. We want to reject these to prevent attempting a |
| 553 // nested tear down of this and |delegate_|. | 537 // nested tear down of this and |delegate_|. |
| 554 if (type == EXIT_ALL) | 538 if (type == EXIT_ALL) |
| 555 showing_ = false; | 539 showing_ = false; |
| 556 | 540 |
| 557 // On Windows and Linux the destruction of this menu's Widget leads to the | 541 // On Windows and Linux the destruction of this menu's Widget leads to the |
| 558 // teardown of the platform specific drag-and-drop Widget. Do not shutdown | 542 // teardown of the platform specific drag-and-drop Widget. Do not shutdown |
| 559 // while dragging, leave the Widget hidden until drag-and-drop has completed, | 543 // while dragging, leave the Widget hidden until drag-and-drop has completed, |
| 560 // at which point all menus will be destroyed. | 544 // at which point all menus will be destroyed. |
| 561 if (!drag_in_progress_) | 545 if (!drag_in_progress_) |
| 562 ExitAsyncRun(); | 546 ExitAsyncRun(); |
| 563 } | 547 } |
| 564 | 548 |
| 565 void MenuController::AddNestedDelegate( | 549 void MenuController::AddNestedDelegate( |
| 566 internal::MenuControllerDelegate* delegate) { | 550 internal::MenuControllerDelegate* delegate) { |
| 567 // TODO(jonross): remove after tracking down the cause of (crbug.com/683087). | |
| 568 for (auto delegates : delegate_stack_) { | |
| 569 // Having the same delegate in the stack could cause deletion order issues. | |
| 570 CHECK_NE(delegates.first, delegate); | |
| 571 } | |
| 572 | |
| 573 delegate_stack_.push_back(std::make_pair(delegate, async_run_)); | 551 delegate_stack_.push_back(std::make_pair(delegate, async_run_)); |
| 574 delegate_ = delegate; | 552 delegate_ = delegate; |
| 575 } | 553 } |
| 576 | 554 |
| 577 void MenuController::SetAsyncRun(bool is_async) { | 555 void MenuController::SetAsyncRun(bool is_async) { |
| 578 delegate_stack_.back().second = is_async; | 556 delegate_stack_.back().second = is_async; |
| 579 async_run_ = is_async; | 557 async_run_ = is_async; |
| 580 } | 558 } |
| 581 | 559 |
| 582 bool MenuController::OnMousePressed(SubmenuView* source, | 560 bool MenuController::OnMousePressed(SubmenuView* source, |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 | 976 |
| 999 // Set state such that we exit. | 977 // Set state such that we exit. |
| 1000 showing_ = false; | 978 showing_ = false; |
| 1001 SetExitType(EXIT_ALL); | 979 SetExitType(EXIT_ALL); |
| 1002 | 980 |
| 1003 // If over an empty menu item, drop occurs on the parent. | 981 // If over an empty menu item, drop occurs on the parent. |
| 1004 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) | 982 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) |
| 1005 drop_target = drop_target->GetParentMenuItem(); | 983 drop_target = drop_target->GetParentMenuItem(); |
| 1006 | 984 |
| 1007 if (!IsBlockingRun()) { | 985 if (!IsBlockingRun()) { |
| 1008 // TODO(jonross): remove after tracking down the cause of | |
| 1009 // (crbug.com/683087). | |
| 1010 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); | |
| 1011 delegate_->OnMenuClosed( | 986 delegate_->OnMenuClosed( |
| 1012 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, | 987 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, |
| 1013 item->GetRootMenuItem(), accept_event_flags_); | 988 item->GetRootMenuItem(), accept_event_flags_); |
| 1014 CHECK(!this_ref); | |
| 1015 } | 989 } |
| 1016 | 990 |
| 1017 // WARNING: the call to MenuClosed deletes us. | 991 // WARNING: the call to MenuClosed deletes us. |
| 1018 | 992 |
| 1019 return drop_target->GetDelegate()->OnPerformDrop( | 993 return drop_target->GetDelegate()->OnPerformDrop( |
| 1020 drop_target, drop_position, event); | 994 drop_target, drop_position, event); |
| 1021 } | 995 } |
| 1022 | 996 |
| 1023 void MenuController::OnDragEnteredScrollButton(SubmenuView* source, | 997 void MenuController::OnDragEnteredScrollButton(SubmenuView* source, |
| 1024 bool is_up) { | 998 bool is_up) { |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 | 1377 |
| 1404 default: | 1378 default: |
| 1405 break; | 1379 break; |
| 1406 } | 1380 } |
| 1407 } | 1381 } |
| 1408 | 1382 |
| 1409 MenuController::MenuController(bool blocking, | 1383 MenuController::MenuController(bool blocking, |
| 1410 internal::MenuControllerDelegate* delegate) | 1384 internal::MenuControllerDelegate* delegate) |
| 1411 : blocking_run_(blocking), | 1385 : blocking_run_(blocking), |
| 1412 showing_(false), | 1386 showing_(false), |
| 1413 running_(false), | |
| 1414 exit_type_(EXIT_NONE), | 1387 exit_type_(EXIT_NONE), |
| 1415 did_capture_(false), | 1388 did_capture_(false), |
| 1416 result_(NULL), | 1389 result_(NULL), |
| 1417 accept_event_flags_(0), | 1390 accept_event_flags_(0), |
| 1418 drop_target_(NULL), | 1391 drop_target_(NULL), |
| 1419 drop_position_(MenuDelegate::DROP_UNKNOWN), | 1392 drop_position_(MenuDelegate::DROP_UNKNOWN), |
| 1420 owner_(NULL), | 1393 owner_(NULL), |
| 1421 possible_drag_(false), | 1394 possible_drag_(false), |
| 1422 drag_in_progress_(false), | 1395 drag_in_progress_(false), |
| 1423 did_initiate_drag_(false), | 1396 did_initiate_drag_(false), |
| (...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2682 delegate_ = delegate_stack_.back().first; | 2655 delegate_ = delegate_stack_.back().first; |
| 2683 async_run_ = delegate_stack_.back().second; | 2656 async_run_ = delegate_stack_.back().second; |
| 2684 } | 2657 } |
| 2685 } else { | 2658 } else { |
| 2686 #if defined(USE_AURA) | 2659 #if defined(USE_AURA) |
| 2687 menu_pre_target_handler_.reset(); | 2660 menu_pre_target_handler_.reset(); |
| 2688 #endif | 2661 #endif |
| 2689 | 2662 |
| 2690 showing_ = false; | 2663 showing_ = false; |
| 2691 did_capture_ = false; | 2664 did_capture_ = false; |
| 2692 // TODO(jonross): remove after tracking down the cause of | |
| 2693 // (crbug.com/683087). | |
| 2694 running_ = false; | |
| 2695 } | 2665 } |
| 2696 | 2666 |
| 2697 MenuItemView* result = result_; | 2667 MenuItemView* result = result_; |
| 2698 // In case we're nested, reset |result_|. | 2668 // In case we're nested, reset |result_|. |
| 2699 result_ = nullptr; | 2669 result_ = nullptr; |
| 2700 | 2670 |
| 2701 if (exit_type_ == EXIT_OUTERMOST) { | 2671 if (exit_type_ == EXIT_OUTERMOST) { |
| 2702 SetExitType(EXIT_NONE); | 2672 SetExitType(EXIT_NONE); |
| 2703 } else { | 2673 } else { |
| 2704 if (nested_menu && result) { | 2674 if (nested_menu && result) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2780 if (hot_button_) | 2750 if (hot_button_) |
| 2781 hot_button_->SetHotTracked(false); | 2751 hot_button_->SetHotTracked(false); |
| 2782 hot_button_ = hot_button; | 2752 hot_button_ = hot_button; |
| 2783 if (hot_button) { | 2753 if (hot_button) { |
| 2784 hot_button->SetHotTracked(true); | 2754 hot_button->SetHotTracked(true); |
| 2785 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); | 2755 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); |
| 2786 } | 2756 } |
| 2787 } | 2757 } |
| 2788 | 2758 |
| 2789 } // namespace views | 2759 } // namespace views |
| OLD | NEW |