Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: ui/views/controls/menu/menu_controller.cc

Issue 1775533002: Fixes incorrect clearing of hot-tracked state when context menu is opened from a menu item (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moves hot_button tracking from MenuController to MenuItemView Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 551
552 current_mouse_pressed_state_ |= event.changed_button_flags(); 552 current_mouse_pressed_state_ |= event.changed_button_flags();
553 553
554 if (forward_to_root) { 554 if (forward_to_root) {
555 ui::MouseEvent event_for_root(event); 555 ui::MouseEvent event_for_root(event);
556 // Reset hot-tracking if a different view is getting a mouse press. 556 // Reset hot-tracking if a different view is getting a mouse press.
557 ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root); 557 ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root);
558 View* view = 558 View* view =
559 forward_to_root->GetEventHandlerForPoint(event_for_root.location()); 559 forward_to_root->GetEventHandlerForPoint(event_for_root.location());
560 CustomButton* button = CustomButton::AsCustomButton(view); 560 CustomButton* button = CustomButton::AsCustomButton(view);
561 if (hot_button_ && hot_button_ != button) 561 MenuItemView* item = static_cast<MenuItemView*>(
562 SetHotTrackedButton(nullptr); 562 button->GetAncestorWithClassName(MenuItemView::kViewClassName));
sky 2016/03/08 16:45:37 What if button is null?
varkha 2016/03/23 21:16:01 Acknowledged (this is no longer necessary if I don
563 if (item && item->hot_button() != button)
564 item->SetHotTrackedButton(nullptr);
563 565
564 // Empty menu items are always handled by the menu controller. 566 // Empty menu items are always handled by the menu controller.
565 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) { 567 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) {
566 bool processed = forward_to_root->ProcessMousePressed(event_for_root); 568 bool processed = forward_to_root->ProcessMousePressed(event_for_root);
567 // If the event was processed, the root view becomes our current mouse 569 // If the event was processed, the root view becomes our current mouse
568 // handler... 570 // handler...
569 if (processed && !current_mouse_event_target_) { 571 if (processed && !current_mouse_event_target_) {
570 current_mouse_event_target_ = forward_to_root; 572 current_mouse_event_target_ = forward_to_root;
571 } 573 }
572 574
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 const ui::MouseEvent& event) { 713 const ui::MouseEvent& event) {
712 if (current_mouse_event_target_) { 714 if (current_mouse_event_target_) {
713 ui::MouseEvent event_for_root(event); 715 ui::MouseEvent event_for_root(event);
714 ConvertLocatedEventForRootView(source, current_mouse_event_target_, 716 ConvertLocatedEventForRootView(source, current_mouse_event_target_,
715 &event_for_root); 717 &event_for_root);
716 current_mouse_event_target_->ProcessMouseMoved(event_for_root); 718 current_mouse_event_target_->ProcessMouseMoved(event_for_root);
717 return; 719 return;
718 } 720 }
719 721
720 MenuHostRootView* root_view = GetRootView(source, event.location()); 722 MenuHostRootView* root_view = GetRootView(source, event.location());
721 if (root_view) { 723 if (root_view)
722 root_view->ProcessMouseMoved(event); 724 root_view->ProcessMouseMoved(event);
723 725
726 HandleMouseLocation(source, event.location());
727 if (pending_state_.item && root_view) {
724 // Update hot-tracked button when a button state is changed with a mouse 728 // Update hot-tracked button when a button state is changed with a mouse
725 // event. It is necessary to track it for accurate hot-tracking when both 729 // event. It is necessary to track it for accurate hot-tracking when both
726 // mouse and keyboard are used to navigate the menu. 730 // mouse and keyboard are used to navigate the menu.
727 ui::MouseEvent event_for_root(event); 731 ui::MouseEvent event_for_root(event);
728 ConvertLocatedEventForRootView(source, root_view, &event_for_root); 732 ConvertLocatedEventForRootView(source, root_view, &event_for_root);
729 View* view = 733 View* view =
730 root_view->GetEventHandlerForPoint(event_for_root.location()); 734 root_view->GetEventHandlerForPoint(event_for_root.location());
731 CustomButton* button = CustomButton::AsCustomButton(view); 735 CustomButton* button = CustomButton::AsCustomButton(view);
732 if (button && button->IsHotTracked()) 736 if (button && button->IsHotTracked() &&
733 SetHotTrackedButton(button); 737 button->GetAncestorWithClassName(MenuItemView::kViewClassName) ==
738 pending_state_.item) {
739 pending_state_.item->SetHotTrackedButton(button);
740 }
734 } 741 }
735
736 HandleMouseLocation(source, event.location());
737 } 742 }
738 743
739 void MenuController::OnMouseEntered(SubmenuView* source, 744 void MenuController::OnMouseEntered(SubmenuView* source,
740 const ui::MouseEvent& event) { 745 const ui::MouseEvent& event) {
741 // MouseEntered is always followed by a mouse moved, so don't need to 746 // MouseEntered is always followed by a mouse moved, so don't need to
742 // do anything here. 747 // do anything here.
743 } 748 }
744 749
745 bool MenuController::OnMouseWheel(SubmenuView* source, 750 bool MenuController::OnMouseWheel(SubmenuView* source,
746 const ui::MouseWheelEvent& event) { 751 const ui::MouseWheelEvent& event) {
747 MenuPart part = GetMenuPart(source, event.location()); 752 MenuPart part = GetMenuPart(source, event.location());
748 return part.submenu && part.submenu->OnMouseWheel(event); 753 return part.submenu && part.submenu->OnMouseWheel(event);
749 } 754 }
750 755
751 void MenuController::OnGestureEvent(SubmenuView* source, 756 void MenuController::OnGestureEvent(SubmenuView* source,
752 ui::GestureEvent* event) { 757 ui::GestureEvent* event) {
753 MenuHostRootView* root_view = GetRootView(source, event->location()); 758 MenuHostRootView* root_view = GetRootView(source, event->location());
754 if (root_view) { 759 if (root_view) {
755 // Reset hot-tracking if a different view is getting a touch event. 760 // Reset hot-tracking if a different view is getting a touch event.
756 ui::GestureEvent event_for_root(*event); 761 ui::GestureEvent event_for_root(*event);
757 ConvertLocatedEventForRootView(source, root_view, &event_for_root); 762 ConvertLocatedEventForRootView(source, root_view, &event_for_root);
758 View* view = 763 View* view =
759 root_view->GetEventHandlerForPoint(event_for_root.location()); 764 root_view->GetEventHandlerForPoint(event_for_root.location());
760 CustomButton* button = CustomButton::AsCustomButton(view); 765 CustomButton* button = CustomButton::AsCustomButton(view);
761 if (hot_button_ && hot_button_ != button) 766 MenuItemView* item = static_cast<MenuItemView*>(
762 SetHotTrackedButton(nullptr); 767 button->GetAncestorWithClassName(MenuItemView::kViewClassName));
768 if (item && item->hot_button() != button)
769 item->SetHotTrackedButton(nullptr);
763 } 770 }
764 771
765 MenuPart part = GetMenuPart(source, event->location()); 772 MenuPart part = GetMenuPart(source, event->location());
766 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { 773 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
767 SetSelectionOnPointerDown(source, event); 774 SetSelectionOnPointerDown(source, event);
768 event->StopPropagation(); 775 event->StopPropagation();
769 } else if (event->type() == ui::ET_GESTURE_LONG_PRESS) { 776 } else if (event->type() == ui::ET_GESTURE_LONG_PRESS) {
770 if (part.type == MenuPart::MENU_ITEM && part.menu) { 777 if (part.type == MenuPart::MENU_ITEM && part.menu) {
771 gfx::Point screen_location(event->location()); 778 gfx::Point screen_location(event->location());
772 View::ConvertPointToScreen(source->GetScrollViewContainer(), 779 View::ConvertPointToScreen(source->GetScrollViewContainer(),
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 834
828 void MenuController::ViewHierarchyChanged( 835 void MenuController::ViewHierarchyChanged(
829 SubmenuView* source, 836 SubmenuView* source,
830 const View::ViewHierarchyChangedDetails& details) { 837 const View::ViewHierarchyChangedDetails& details) {
831 if (!details.is_add) { 838 if (!details.is_add) {
832 // If the current mouse handler is removed, remove it as the handler. 839 // If the current mouse handler is removed, remove it as the handler.
833 if (details.child == current_mouse_event_target_) { 840 if (details.child == current_mouse_event_target_) {
834 current_mouse_event_target_ = nullptr; 841 current_mouse_event_target_ = nullptr;
835 current_mouse_pressed_state_ = 0; 842 current_mouse_pressed_state_ = 0;
836 } 843 }
837 // Update |hot_button_| if it gets removed while a menu is up.
838 if (details.child == hot_button_)
839 hot_button_ = nullptr;
840 } 844 }
841 } 845 }
842 846
843 bool MenuController::GetDropFormats( 847 bool MenuController::GetDropFormats(
844 SubmenuView* source, 848 SubmenuView* source,
845 int* formats, 849 int* formats,
846 std::set<ui::Clipboard::FormatType>* format_types) { 850 std::set<ui::Clipboard::FormatType>* format_types) {
847 return source->GetMenuItem()->GetDelegate()->GetDropFormats( 851 return source->GetMenuItem()->GetDelegate()->GetDropFormats(
848 source->GetMenuItem(), formats, format_types); 852 source->GetMenuItem(), formats, format_types);
849 } 853 }
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 size_t paths_differ_at = 0; 1061 size_t paths_differ_at = 0;
1058 std::vector<MenuItemView*> current_path; 1062 std::vector<MenuItemView*> current_path;
1059 std::vector<MenuItemView*> new_path; 1063 std::vector<MenuItemView*> new_path;
1060 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, &current_path, 1064 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, &current_path,
1061 &new_path, &paths_differ_at); 1065 &new_path, &paths_differ_at);
1062 1066
1063 size_t current_size = current_path.size(); 1067 size_t current_size = current_path.size();
1064 size_t new_size = new_path.size(); 1068 size_t new_size = new_path.size();
1065 1069
1066 bool pending_item_changed = pending_state_.item != menu_item; 1070 bool pending_item_changed = pending_state_.item != menu_item;
1067 if (pending_item_changed && pending_state_.item)
1068 SetHotTrackedButton(nullptr);
1069 1071
1070 // Notify the old path it isn't selected. 1072 // Notify the old path it isn't selected.
1071 MenuDelegate* current_delegate = 1073 MenuDelegate* current_delegate =
1072 current_path.empty() ? NULL : current_path.front()->GetDelegate(); 1074 current_path.empty() ? NULL : current_path.front()->GetDelegate();
1073 for (size_t i = paths_differ_at; i < current_size; ++i) { 1075 for (size_t i = paths_differ_at; i < current_size; ++i) {
1074 if (current_delegate && 1076 if (current_delegate &&
1075 current_path[i]->GetType() == MenuItemView::SUBMENU) { 1077 current_path[i]->GetType() == MenuItemView::SUBMENU) {
1076 current_delegate->WillHideMenu(current_path[i]); 1078 current_delegate->WillHideMenu(current_path[i]);
1077 } 1079 }
1078 current_path[i]->SetSelected(false); 1080 current_path[i]->SetSelected(false);
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 drop_target_(NULL), 1311 drop_target_(NULL),
1310 drop_position_(MenuDelegate::DROP_UNKNOWN), 1312 drop_position_(MenuDelegate::DROP_UNKNOWN),
1311 owner_(NULL), 1313 owner_(NULL),
1312 possible_drag_(false), 1314 possible_drag_(false),
1313 drag_in_progress_(false), 1315 drag_in_progress_(false),
1314 did_initiate_drag_(false), 1316 did_initiate_drag_(false),
1315 valid_drop_coordinates_(false), 1317 valid_drop_coordinates_(false),
1316 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), 1318 last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
1317 showing_submenu_(false), 1319 showing_submenu_(false),
1318 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), 1320 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
1319 hot_button_(nullptr),
1320 delegate_(delegate), 1321 delegate_(delegate),
1321 message_loop_depth_(0), 1322 message_loop_depth_(0),
1322 closing_event_time_(base::TimeDelta()), 1323 closing_event_time_(base::TimeDelta()),
1323 menu_start_time_(base::TimeTicks()), 1324 menu_start_time_(base::TimeTicks()),
1324 async_run_(false), 1325 async_run_(false),
1325 is_combobox_(false), 1326 is_combobox_(false),
1326 item_selected_by_touch_(false), 1327 item_selected_by_touch_(false),
1327 current_mouse_event_target_(nullptr), 1328 current_mouse_event_target_(nullptr),
1328 current_mouse_pressed_state_(0), 1329 current_mouse_pressed_state_(0),
1329 message_loop_(MenuMessageLoop::Create()) { 1330 message_loop_(MenuMessageLoop::Create()) {
1330 delegate_stack_.push_back(std::make_pair(delegate_, async_run_)); 1331 delegate_stack_.push_back(std::make_pair(delegate_, async_run_));
1331 active_instance_ = this; 1332 active_instance_ = this;
1332 } 1333 }
1333 1334
1334 MenuController::~MenuController() { 1335 MenuController::~MenuController() {
1335 DCHECK(!showing_); 1336 DCHECK(!showing_);
1336 if (owner_) 1337 if (owner_)
1337 owner_->RemoveObserver(this); 1338 owner_->RemoveObserver(this);
1338 if (active_instance_ == this) 1339 if (active_instance_ == this)
1339 active_instance_ = NULL; 1340 active_instance_ = NULL;
1340 StopShowTimer(); 1341 StopShowTimer();
1341 StopCancelAllTimer(); 1342 StopCancelAllTimer();
1342 } 1343 }
1343 1344
1344 void MenuController::RunMessageLoop(bool nested_menu) { 1345 void MenuController::RunMessageLoop(bool nested_menu) {
1345 message_loop_->Run(this, owner_, nested_menu); 1346 message_loop_->Run(this, owner_, nested_menu);
1346 } 1347 }
1347 1348
1348 bool MenuController::SendAcceleratorToHotTrackedView() { 1349 bool MenuController::SendAcceleratorToHotTrackedView() {
1349 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); 1350 MenuItemView* item = pending_state_.item;
1351 CustomButton* hot_view = GetFirstHotTrackedView(item);
1350 if (!hot_view) 1352 if (!hot_view)
1351 return false; 1353 return false;
1352
1353 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); 1354 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE);
1354 hot_view->AcceleratorPressed(accelerator); 1355 hot_view->AcceleratorPressed(accelerator);
1355 CustomButton* button = static_cast<CustomButton*>(hot_view); 1356 CustomButton* button = static_cast<CustomButton*>(hot_view);
1356 SetHotTrackedButton(button); 1357 item->SetHotTrackedButton(button);
1357 return true; 1358 return true;
1358 } 1359 }
1359 1360
1360 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds, 1361 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
1361 MenuAnchorPosition position, 1362 MenuAnchorPosition position,
1362 bool context_menu) { 1363 bool context_menu) {
1363 pending_state_.context_menu = context_menu; 1364 pending_state_.context_menu = context_menu;
1364 pending_state_.initial_bounds = bounds; 1365 pending_state_.initial_bounds = bounds;
1365 if (bounds.height() > 1) { 1366 if (bounds.height() > 1) {
1366 // Inset the bounds slightly, otherwise drag coordinates don't line up 1367 // Inset the bounds slightly, otherwise drag coordinates don't line up
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 if (item->GetSubmenu()->GetMenuItemCount()) { 2117 if (item->GetSubmenu()->GetMenuItemCount()) {
2117 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); 2118 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction);
2118 SetInitialHotTrackedView(to_select, direction); 2119 SetInitialHotTrackedView(to_select, direction);
2119 return; 2120 return;
2120 } 2121 }
2121 } 2122 }
2122 2123
2123 if (item->has_children()) { 2124 if (item->has_children()) {
2124 CustomButton* button = GetFirstHotTrackedView(item); 2125 CustomButton* button = GetFirstHotTrackedView(item);
2125 if (button) { 2126 if (button) {
2126 DCHECK_EQ(hot_button_, button); 2127 DCHECK_EQ(item->hot_button(), button);
2127 SetHotTrackedButton(nullptr); 2128 item->SetHotTrackedButton(nullptr);
2128 } 2129 }
2129 bool direction_is_down = direction == INCREMENT_SELECTION_DOWN; 2130 bool direction_is_down = direction == INCREMENT_SELECTION_DOWN;
2130 View* to_make_hot = button 2131 View* to_make_hot = button
2131 ? GetNextFocusableView(item, button, direction_is_down) 2132 ? GetNextFocusableView(item, button, direction_is_down)
2132 : GetInitialFocusableView(item, direction_is_down); 2133 : GetInitialFocusableView(item, direction_is_down);
2133 CustomButton* hot_button = CustomButton::AsCustomButton(to_make_hot); 2134 CustomButton* hot_button = CustomButton::AsCustomButton(to_make_hot);
2134 if (hot_button) { 2135 if (hot_button) {
2135 SetHotTrackedButton(hot_button); 2136 item->SetHotTrackedButton(hot_button);
2136 return; 2137 return;
2137 } 2138 }
2138 } 2139 }
2139 2140
2140 MenuItemView* parent = item->GetParentMenuItem(); 2141 MenuItemView* parent = item->GetParentMenuItem();
2141 if (parent) { 2142 if (parent) {
2142 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); 2143 int parent_count = parent->GetSubmenu()->GetMenuItemCount();
2143 if (parent_count > 1) { 2144 if (parent_count > 1) {
2144 for (int i = 0; i < parent_count; ++i) { 2145 for (int i = 0; i < parent_count; ++i) {
2145 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) { 2146 if (parent->GetSubmenu()->GetMenuItemAt(i) == item) {
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2627 } 2628 }
2628 2629
2629 void MenuController::SetInitialHotTrackedView( 2630 void MenuController::SetInitialHotTrackedView(
2630 MenuItemView* item, 2631 MenuItemView* item,
2631 SelectionIncrementDirectionType direction) { 2632 SelectionIncrementDirectionType direction) {
2632 if (!item) 2633 if (!item)
2633 return; 2634 return;
2634 SetSelection(item, SELECTION_DEFAULT); 2635 SetSelection(item, SELECTION_DEFAULT);
2635 View* hot_view = 2636 View* hot_view =
2636 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); 2637 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
2637 SetHotTrackedButton(CustomButton::AsCustomButton(hot_view)); 2638 item->SetHotTrackedButton(CustomButton::AsCustomButton(hot_view));
2638 }
2639
2640 void MenuController::SetHotTrackedButton(CustomButton* hot_button) {
2641 if (hot_button == hot_button_) {
2642 // Hot-tracked state may change outside of the MenuController. Correct it.
2643 if (hot_button && !hot_button->IsHotTracked())
2644 hot_button->SetHotTracked(true);
2645 return;
2646 }
2647 if (hot_button_)
2648 hot_button_->SetHotTracked(false);
2649 hot_button_ = hot_button;
2650 if (hot_button)
2651 hot_button->SetHotTracked(true);
2652 } 2639 }
2653 2640
2654 } // namespace views 2641 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698