| 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 |
| 436 if (owner_) | 442 if (owner_) |
| 437 owner_->RemoveObserver(this); | 443 owner_->RemoveObserver(this); |
| 438 owner_ = parent; | 444 owner_ = parent; |
| 439 if (owner_) | 445 if (owner_) |
| 440 owner_->AddObserver(this); | 446 owner_->AddObserver(this); |
| 441 | 447 |
| 442 #if defined(USE_AURA) | 448 #if defined(USE_AURA) |
| 443 // Only create a MenuPreTargetHandler for non-nested menus. Nested menus | 449 // Only create a MenuPreTargetHandler for non-nested menus. Nested menus |
| 444 // will use the existing one. | 450 // will use the existing one. |
| 445 menu_pre_target_handler_.reset(new MenuPreTargetHandler(this, owner_)); | 451 menu_pre_target_handler_.reset(new MenuPreTargetHandler(this, owner_)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 463 return NULL; | 469 return NULL; |
| 464 } | 470 } |
| 465 | 471 |
| 466 if (button) | 472 if (button) |
| 467 pressed_lock_.reset(new MenuButton::PressedLock(button)); | 473 pressed_lock_.reset(new MenuButton::PressedLock(button)); |
| 468 | 474 |
| 469 // Make sure Chrome doesn't attempt to shut down while the menu is showing. | 475 // Make sure Chrome doesn't attempt to shut down while the menu is showing. |
| 470 if (ViewsDelegate::GetInstance()) | 476 if (ViewsDelegate::GetInstance()) |
| 471 ViewsDelegate::GetInstance()->AddRef(); | 477 ViewsDelegate::GetInstance()->AddRef(); |
| 472 | 478 |
| 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 |
| 473 if (async_run_) | 483 if (async_run_) |
| 474 return nullptr; | 484 return nullptr; |
| 475 | 485 |
| 476 // We need to turn on nestable tasks as in some situations (pressing alt-f for | 486 // We need to turn on nestable tasks as in some situations (pressing alt-f for |
| 477 // one) the menus are run from a task. If we don't do this and are invoked | 487 // one) the menus are run from a task. If we don't do this and are invoked |
| 478 // from a task none of the tasks we schedule are processed and the menu | 488 // from a task none of the tasks we schedule are processed and the menu |
| 479 // appears totally broken. | 489 // appears totally broken. |
| 480 message_loop_depth_++; | 490 message_loop_depth_++; |
| 481 DCHECK_LE(message_loop_depth_, 2); | 491 DCHECK_LE(message_loop_depth_, 2); |
| 482 RunMessageLoop(); | 492 RunMessageLoop(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 511 | 521 |
| 512 MenuItemView* selected = state_.item; | 522 MenuItemView* selected = state_.item; |
| 513 SetExitType(type); | 523 SetExitType(type); |
| 514 | 524 |
| 515 SendMouseCaptureLostToActiveView(); | 525 SendMouseCaptureLostToActiveView(); |
| 516 | 526 |
| 517 // Hide windows immediately. | 527 // Hide windows immediately. |
| 518 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); | 528 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); |
| 519 | 529 |
| 520 if (!blocking_run_) { | 530 if (!blocking_run_) { |
| 531 // TODO(jonross): remove after tracking down the cause of |
| 532 // (crbug.com/683087). |
| 533 bool nested = delegate_stack_.size() > 1; |
| 534 CHECK(!nested); |
| 535 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); |
| 521 // If we didn't block the caller we need to notify the menu, which | 536 // If we didn't block the caller we need to notify the menu, which |
| 522 // triggers deleting us. | 537 // triggers deleting us. |
| 523 DCHECK(selected); | 538 DCHECK(selected); |
| 524 showing_ = false; | 539 showing_ = false; |
| 525 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 540 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 526 selected->GetRootMenuItem(), accept_event_flags_); | 541 selected->GetRootMenuItem(), accept_event_flags_); |
| 527 // WARNING: the call to MenuClosed deletes us. | 542 // WARNING: the call to MenuClosed deletes us. |
| 543 CHECK(!this_ref); |
| 528 return; | 544 return; |
| 529 } | 545 } |
| 530 | 546 |
| 531 // On Windows and Linux the destruction of this menu's Widget leads to the | 547 // On Windows and Linux the destruction of this menu's Widget leads to the |
| 532 // teardown of the platform specific drag-and-drop Widget. Do not shutdown | 548 // teardown of the platform specific drag-and-drop Widget. Do not shutdown |
| 533 // while dragging, leave the Widget hidden until drag-and-drop has completed, | 549 // while dragging, leave the Widget hidden until drag-and-drop has completed, |
| 534 // at which point all menus will be destroyed. | 550 // at which point all menus will be destroyed. |
| 535 // | 551 // |
| 536 // If |type| is EXIT_ALL we update the state of the menu to not showing. So | 552 // If |type| is EXIT_ALL we update the state of the menu to not showing. So |
| 537 // that during the completion of a drag we are not incorrectly reporting the | 553 // that during the completion of a drag we are not incorrectly reporting the |
| 538 // visual state. | 554 // visual state. |
| 539 if (!drag_in_progress_) | 555 if (!drag_in_progress_) |
| 540 ExitAsyncRun(); | 556 ExitAsyncRun(); |
| 541 else if (type == EXIT_ALL) | 557 else if (type == EXIT_ALL) |
| 542 showing_ = false; | 558 showing_ = false; |
| 543 } | 559 } |
| 544 | 560 |
| 545 void MenuController::AddNestedDelegate( | 561 void MenuController::AddNestedDelegate( |
| 546 internal::MenuControllerDelegate* delegate) { | 562 internal::MenuControllerDelegate* delegate) { |
| 563 // TODO(jonross): remove after tracking down the cause of (crbug.com/683087). |
| 564 for (auto delegates : delegate_stack_) { |
| 565 // Having the same delegate in the stack could cause deletion order issues. |
| 566 CHECK_NE(delegates.first, delegate); |
| 567 } |
| 568 |
| 547 delegate_stack_.push_back(std::make_pair(delegate, async_run_)); | 569 delegate_stack_.push_back(std::make_pair(delegate, async_run_)); |
| 548 delegate_ = delegate; | 570 delegate_ = delegate; |
| 549 } | 571 } |
| 550 | 572 |
| 551 void MenuController::SetAsyncRun(bool is_async) { | 573 void MenuController::SetAsyncRun(bool is_async) { |
| 552 delegate_stack_.back().second = is_async; | 574 delegate_stack_.back().second = is_async; |
| 553 async_run_ = is_async; | 575 async_run_ = is_async; |
| 554 } | 576 } |
| 555 | 577 |
| 556 bool MenuController::OnMousePressed(SubmenuView* source, | 578 bool MenuController::OnMousePressed(SubmenuView* source, |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 | 994 |
| 973 // Set state such that we exit. | 995 // Set state such that we exit. |
| 974 showing_ = false; | 996 showing_ = false; |
| 975 SetExitType(EXIT_ALL); | 997 SetExitType(EXIT_ALL); |
| 976 | 998 |
| 977 // If over an empty menu item, drop occurs on the parent. | 999 // If over an empty menu item, drop occurs on the parent. |
| 978 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) | 1000 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) |
| 979 drop_target = drop_target->GetParentMenuItem(); | 1001 drop_target = drop_target->GetParentMenuItem(); |
| 980 | 1002 |
| 981 if (!IsBlockingRun()) { | 1003 if (!IsBlockingRun()) { |
| 1004 // TODO(jonross): remove after tracking down the cause of |
| 1005 // (crbug.com/683087). |
| 1006 base::WeakPtr<MenuController> this_ref = AsWeakPtr(); |
| 982 delegate_->OnMenuClosed( | 1007 delegate_->OnMenuClosed( |
| 983 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, | 1008 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, |
| 984 item->GetRootMenuItem(), accept_event_flags_); | 1009 item->GetRootMenuItem(), accept_event_flags_); |
| 1010 CHECK(!this_ref); |
| 985 } | 1011 } |
| 986 | 1012 |
| 987 // WARNING: the call to MenuClosed deletes us. | 1013 // WARNING: the call to MenuClosed deletes us. |
| 988 | 1014 |
| 989 return drop_target->GetDelegate()->OnPerformDrop( | 1015 return drop_target->GetDelegate()->OnPerformDrop( |
| 990 drop_target, drop_position, event); | 1016 drop_target, drop_position, event); |
| 991 } | 1017 } |
| 992 | 1018 |
| 993 void MenuController::OnDragEnteredScrollButton(SubmenuView* source, | 1019 void MenuController::OnDragEnteredScrollButton(SubmenuView* source, |
| 994 bool is_up) { | 1020 bool is_up) { |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 | 1399 |
| 1374 default: | 1400 default: |
| 1375 break; | 1401 break; |
| 1376 } | 1402 } |
| 1377 } | 1403 } |
| 1378 | 1404 |
| 1379 MenuController::MenuController(bool blocking, | 1405 MenuController::MenuController(bool blocking, |
| 1380 internal::MenuControllerDelegate* delegate) | 1406 internal::MenuControllerDelegate* delegate) |
| 1381 : blocking_run_(blocking), | 1407 : blocking_run_(blocking), |
| 1382 showing_(false), | 1408 showing_(false), |
| 1409 running_(false), |
| 1383 exit_type_(EXIT_NONE), | 1410 exit_type_(EXIT_NONE), |
| 1384 did_capture_(false), | 1411 did_capture_(false), |
| 1385 result_(NULL), | 1412 result_(NULL), |
| 1386 accept_event_flags_(0), | 1413 accept_event_flags_(0), |
| 1387 drop_target_(NULL), | 1414 drop_target_(NULL), |
| 1388 drop_position_(MenuDelegate::DROP_UNKNOWN), | 1415 drop_position_(MenuDelegate::DROP_UNKNOWN), |
| 1389 owner_(NULL), | 1416 owner_(NULL), |
| 1390 possible_drag_(false), | 1417 possible_drag_(false), |
| 1391 drag_in_progress_(false), | 1418 drag_in_progress_(false), |
| 1392 did_initiate_drag_(false), | 1419 did_initiate_drag_(false), |
| (...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2651 delegate_ = delegate_stack_.back().first; | 2678 delegate_ = delegate_stack_.back().first; |
| 2652 async_run_ = delegate_stack_.back().second; | 2679 async_run_ = delegate_stack_.back().second; |
| 2653 } | 2680 } |
| 2654 } else { | 2681 } else { |
| 2655 #if defined(USE_AURA) | 2682 #if defined(USE_AURA) |
| 2656 menu_pre_target_handler_.reset(); | 2683 menu_pre_target_handler_.reset(); |
| 2657 #endif | 2684 #endif |
| 2658 | 2685 |
| 2659 showing_ = false; | 2686 showing_ = false; |
| 2660 did_capture_ = false; | 2687 did_capture_ = false; |
| 2688 // TODO(jonross): remove after tracking down the cause of |
| 2689 // (crbug.com/683087). |
| 2690 running_ = false; |
| 2661 } | 2691 } |
| 2662 | 2692 |
| 2663 MenuItemView* result = result_; | 2693 MenuItemView* result = result_; |
| 2664 // In case we're nested, reset |result_|. | 2694 // In case we're nested, reset |result_|. |
| 2665 result_ = nullptr; | 2695 result_ = nullptr; |
| 2666 | 2696 |
| 2667 if (exit_type_ == EXIT_OUTERMOST) { | 2697 if (exit_type_ == EXIT_OUTERMOST) { |
| 2668 SetExitType(EXIT_NONE); | 2698 SetExitType(EXIT_NONE); |
| 2669 } else { | 2699 } else { |
| 2670 if (nested_menu && result) { | 2700 if (nested_menu && result) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2746 if (hot_button_) | 2776 if (hot_button_) |
| 2747 hot_button_->SetHotTracked(false); | 2777 hot_button_->SetHotTracked(false); |
| 2748 hot_button_ = hot_button; | 2778 hot_button_ = hot_button; |
| 2749 if (hot_button) { | 2779 if (hot_button) { |
| 2750 hot_button->SetHotTracked(true); | 2780 hot_button->SetHotTracked(true); |
| 2751 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); | 2781 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); |
| 2752 } | 2782 } |
| 2753 } | 2783 } |
| 2754 | 2784 |
| 2755 } // namespace views | 2785 } // namespace views |
| OLD | NEW |