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

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

Issue 1741093002: Fixes alternating keyboard and mouse hot-tracking in menus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes alternating keyboard and mouse hot-tracking in menus (rebased) Created 4 years, 10 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 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) { 562 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) {
563 bool processed = forward_to_root->ProcessMousePressed(event_for_root); 563 bool processed = forward_to_root->ProcessMousePressed(event_for_root);
564 // If the event was processed, the root view becomes our current mouse 564 // If the event was processed, the root view becomes our current mouse
565 // handler... 565 // handler...
566 if (processed && !current_mouse_event_target_) { 566 if (processed && !current_mouse_event_target_) {
567 current_mouse_event_target_ = forward_to_root; 567 current_mouse_event_target_ = forward_to_root;
568 } 568 }
569 569
570 // ...and we always return the result of the current handler. 570 // ...and we always return the result of the current handler.
571 if (current_mouse_event_target_) 571 if (current_mouse_event_target_)
572 return processed; 572 return processed;
sky 2016/02/29 16:33:32 Do you need to update this branch to change the se
varkha 2016/02/29 19:09:44 Done. I could not see how another button could hav
573 } 573 }
574 } 574 }
575 575
576 // Otherwise, the menu handles this click directly. 576 // Otherwise, the menu handles this click directly.
577 SetSelectionOnPointerDown(source, &event); 577 SetSelectionOnPointerDown(source, &event);
578 return true; 578 return true;
579 } 579 }
580 580
581 bool MenuController::OnMouseDragged(SubmenuView* source, 581 bool MenuController::OnMouseDragged(SubmenuView* source,
582 const ui::MouseEvent& event) { 582 const ui::MouseEvent& event) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 const ui::MouseEvent& event) { 708 const ui::MouseEvent& event) {
709 if (current_mouse_event_target_) { 709 if (current_mouse_event_target_) {
710 ui::MouseEvent event_for_root(event); 710 ui::MouseEvent event_for_root(event);
711 ConvertLocatedEventForRootView(source, current_mouse_event_target_, 711 ConvertLocatedEventForRootView(source, current_mouse_event_target_,
712 &event_for_root); 712 &event_for_root);
713 current_mouse_event_target_->ProcessMouseMoved(event_for_root); 713 current_mouse_event_target_->ProcessMouseMoved(event_for_root);
714 return; 714 return;
715 } 715 }
716 716
717 MenuHostRootView* root_view = GetRootView(source, event.location()); 717 MenuHostRootView* root_view = GetRootView(source, event.location());
718 if (root_view) 718 if (root_view) {
719 root_view->ProcessMouseMoved(event); 719 root_view->ProcessMouseMoved(event);
720 // TODO(varkha): It is possible that another child CustomButton has become 720
721 // hot-tracked as a result of this event. We need to track it for accurate 721 // Update hot-tracked button when a button state is changed with a mouse
722 // hot-tracking when both mouse and keyboard are used to navigate the menu. 722 // event. It is necessary to track it for accurate hot-tracking when both
723 // mouse and keyboard are used to navigate the menu.
724 ui::MouseEvent event_for_root(event);
725 ConvertLocatedEventForRootView(source, root_view, &event_for_root);
726 View* view =
727 root_view->GetEventHandlerForPoint(event_for_root.location());
728 CustomButton* button = CustomButton::AsCustomButton(view);
729 if (button && button->IsHotTracked())
730 SetHotTrackedButton(button);
731 }
732
723 HandleMouseLocation(source, event.location()); 733 HandleMouseLocation(source, event.location());
724 } 734 }
725 735
726 void MenuController::OnMouseEntered(SubmenuView* source, 736 void MenuController::OnMouseEntered(SubmenuView* source,
727 const ui::MouseEvent& event) { 737 const ui::MouseEvent& event) {
728 // MouseEntered is always followed by a mouse moved, so don't need to 738 // MouseEntered is always followed by a mouse moved, so don't need to
729 // do anything here. 739 // do anything here.
730 } 740 }
731 741
732 bool MenuController::OnMouseWheel(SubmenuView* source, 742 bool MenuController::OnMouseWheel(SubmenuView* source,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source, 806 View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source,
797 const gfx::Point& point) { 807 const gfx::Point& point) {
798 MenuHostRootView* root_view = GetRootView(source, point); 808 MenuHostRootView* root_view = GetRootView(source, point);
799 return root_view ? root_view->ProcessGetTooltipHandlerForPoint(point) 809 return root_view ? root_view->ProcessGetTooltipHandlerForPoint(point)
800 : nullptr; 810 : nullptr;
801 } 811 }
802 812
803 void MenuController::ViewHierarchyChanged( 813 void MenuController::ViewHierarchyChanged(
804 SubmenuView* source, 814 SubmenuView* source,
805 const View::ViewHierarchyChangedDetails& details) { 815 const View::ViewHierarchyChangedDetails& details) {
806 // If the current mouse handler is removed, remove it as the handler. 816 if (!details.is_add) {
807 if (!details.is_add && details.child == current_mouse_event_target_) { 817 // If the current mouse handler is removed, remove it as the handler.
808 current_mouse_event_target_ = nullptr; 818 if (details.child == current_mouse_event_target_) {
809 current_mouse_pressed_state_ = 0; 819 current_mouse_event_target_ = nullptr;
820 current_mouse_pressed_state_ = 0;
821 }
822 // Update |hot_button_| if it gets deleted while a menu is up.
sky 2016/02/29 16:33:32 deleted->removed
varkha 2016/02/29 19:09:44 Done.
823 if (details.child == hot_button_)
824 hot_button_ = nullptr;
810 } 825 }
811 } 826 }
812 827
813 bool MenuController::GetDropFormats( 828 bool MenuController::GetDropFormats(
814 SubmenuView* source, 829 SubmenuView* source,
815 int* formats, 830 int* formats,
816 std::set<ui::Clipboard::FormatType>* format_types) { 831 std::set<ui::Clipboard::FormatType>* format_types) {
817 return source->GetMenuItem()->GetDelegate()->GetDropFormats( 832 return source->GetMenuItem()->GetDelegate()->GetDropFormats(
818 source->GetMenuItem(), formats, format_types); 833 source->GetMenuItem(), formats, format_types);
819 } 834 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 std::vector<MenuItemView*> current_path; 1043 std::vector<MenuItemView*> current_path;
1029 std::vector<MenuItemView*> new_path; 1044 std::vector<MenuItemView*> new_path;
1030 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, &current_path, 1045 BuildPathsAndCalculateDiff(pending_state_.item, menu_item, &current_path,
1031 &new_path, &paths_differ_at); 1046 &new_path, &paths_differ_at);
1032 1047
1033 size_t current_size = current_path.size(); 1048 size_t current_size = current_path.size();
1034 size_t new_size = new_path.size(); 1049 size_t new_size = new_path.size();
1035 1050
1036 bool pending_item_changed = pending_state_.item != menu_item; 1051 bool pending_item_changed = pending_state_.item != menu_item;
1037 if (pending_item_changed && pending_state_.item) { 1052 if (pending_item_changed && pending_state_.item) {
1038 CustomButton* button = GetFirstHotTrackedView(pending_state_.item); 1053 CustomButton* button = GetFirstHotTrackedView(pending_state_.item);
sky 2016/02/29 16:33:32 It doesn't seem necessary to call this anymore. Ca
varkha 2016/02/29 19:09:44 Here, yes. Done.
1039 if (button) 1054 if (button) {
1040 button->SetHotTracked(false); 1055 DCHECK_EQ(hot_button_, button);
1056 SetHotTrackedButton(nullptr);
1057 }
1041 } 1058 }
1042 1059
1043 // Notify the old path it isn't selected. 1060 // Notify the old path it isn't selected.
1044 MenuDelegate* current_delegate = 1061 MenuDelegate* current_delegate =
1045 current_path.empty() ? NULL : current_path.front()->GetDelegate(); 1062 current_path.empty() ? NULL : current_path.front()->GetDelegate();
1046 for (size_t i = paths_differ_at; i < current_size; ++i) { 1063 for (size_t i = paths_differ_at; i < current_size; ++i) {
1047 if (current_delegate && 1064 if (current_delegate &&
1048 current_path[i]->GetType() == MenuItemView::SUBMENU) { 1065 current_path[i]->GetType() == MenuItemView::SUBMENU) {
1049 current_delegate->WillHideMenu(current_path[i]); 1066 current_delegate->WillHideMenu(current_path[i]);
1050 } 1067 }
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 drop_target_(NULL), 1299 drop_target_(NULL),
1283 drop_position_(MenuDelegate::DROP_UNKNOWN), 1300 drop_position_(MenuDelegate::DROP_UNKNOWN),
1284 owner_(NULL), 1301 owner_(NULL),
1285 possible_drag_(false), 1302 possible_drag_(false),
1286 drag_in_progress_(false), 1303 drag_in_progress_(false),
1287 did_initiate_drag_(false), 1304 did_initiate_drag_(false),
1288 valid_drop_coordinates_(false), 1305 valid_drop_coordinates_(false),
1289 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), 1306 last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
1290 showing_submenu_(false), 1307 showing_submenu_(false),
1291 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), 1308 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
1309 hot_button_(nullptr),
1292 delegate_(delegate), 1310 delegate_(delegate),
1293 message_loop_depth_(0), 1311 message_loop_depth_(0),
1294 closing_event_time_(base::TimeDelta()), 1312 closing_event_time_(base::TimeDelta()),
1295 menu_start_time_(base::TimeTicks()), 1313 menu_start_time_(base::TimeTicks()),
1296 async_run_(false), 1314 async_run_(false),
1297 is_combobox_(false), 1315 is_combobox_(false),
1298 item_selected_by_touch_(false), 1316 item_selected_by_touch_(false),
1299 current_mouse_event_target_(nullptr), 1317 current_mouse_event_target_(nullptr),
1300 current_mouse_pressed_state_(0), 1318 current_mouse_pressed_state_(0),
1301 message_loop_(MenuMessageLoop::Create()) { 1319 message_loop_(MenuMessageLoop::Create()) {
(...skipping 16 matching lines...) Expand all
1318 } 1336 }
1319 1337
1320 bool MenuController::SendAcceleratorToHotTrackedView() { 1338 bool MenuController::SendAcceleratorToHotTrackedView() {
1321 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); 1339 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item);
1322 if (!hot_view) 1340 if (!hot_view)
1323 return false; 1341 return false;
1324 1342
1325 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); 1343 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE);
1326 hot_view->AcceleratorPressed(accelerator); 1344 hot_view->AcceleratorPressed(accelerator);
1327 CustomButton* button = static_cast<CustomButton*>(hot_view); 1345 CustomButton* button = static_cast<CustomButton*>(hot_view);
1328 button->SetHotTracked(true); 1346 SetHotTrackedButton(button);
1329 return true; 1347 return true;
1330 } 1348 }
1331 1349
1332 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds, 1350 void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
1333 MenuAnchorPosition position, 1351 MenuAnchorPosition position,
1334 bool context_menu) { 1352 bool context_menu) {
1335 pending_state_.context_menu = context_menu; 1353 pending_state_.context_menu = context_menu;
1336 pending_state_.initial_bounds = bounds; 1354 pending_state_.initial_bounds = bounds;
1337 if (bounds.height() > 1) { 1355 if (bounds.height() > 1) {
1338 // Inset the bounds slightly, otherwise drag coordinates don't line up 1356 // Inset the bounds slightly, otherwise drag coordinates don't line up
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
2088 if (item->GetSubmenu()->GetMenuItemCount()) { 2106 if (item->GetSubmenu()->GetMenuItemCount()) {
2089 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction); 2107 MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction);
2090 SetInitialHotTrackedView(to_select, direction); 2108 SetInitialHotTrackedView(to_select, direction);
2091 return; 2109 return;
2092 } 2110 }
2093 } 2111 }
2094 2112
2095 if (item->has_children()) { 2113 if (item->has_children()) {
2096 CustomButton* button = GetFirstHotTrackedView(item); 2114 CustomButton* button = GetFirstHotTrackedView(item);
2097 if (button) { 2115 if (button) {
2098 button->SetHotTracked(false); 2116 DCHECK_EQ(hot_button_, button);
2117 SetHotTrackedButton(nullptr);
2099 View* to_make_hot = GetNextFocusableView( 2118 View* to_make_hot = GetNextFocusableView(
2100 item, button, direction == INCREMENT_SELECTION_DOWN); 2119 item, button, direction == INCREMENT_SELECTION_DOWN);
2101 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); 2120 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
2102 if (button_hot) { 2121 if (button_hot) {
2103 button_hot->SetHotTracked(true); 2122 SetHotTrackedButton(button_hot);
2104 return; 2123 return;
2105 } 2124 }
2106 } else { 2125 } else {
2107 View* to_make_hot = 2126 View* to_make_hot =
2108 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); 2127 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
2109 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot); 2128 CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
2110 if (button_hot) { 2129 if (button_hot) {
2111 button_hot->SetHotTracked(true); 2130 SetHotTrackedButton(button_hot);
2112 return; 2131 return;
2113 } 2132 }
2114 } 2133 }
2115 } 2134 }
2116 2135
2117 MenuItemView* parent = item->GetParentMenuItem(); 2136 MenuItemView* parent = item->GetParentMenuItem();
2118 if (parent) { 2137 if (parent) {
2119 int parent_count = parent->GetSubmenu()->GetMenuItemCount(); 2138 int parent_count = parent->GetSubmenu()->GetMenuItemCount();
2120 if (parent_count > 1) { 2139 if (parent_count > 1) {
2121 for (int i = 0; i < parent_count; ++i) { 2140 for (int i = 0; i < parent_count; ++i) {
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 } 2624 }
2606 2625
2607 void MenuController::SetInitialHotTrackedView( 2626 void MenuController::SetInitialHotTrackedView(
2608 MenuItemView* item, 2627 MenuItemView* item,
2609 SelectionIncrementDirectionType direction) { 2628 SelectionIncrementDirectionType direction) {
2610 if (!item) 2629 if (!item)
2611 return; 2630 return;
2612 SetSelection(item, SELECTION_DEFAULT); 2631 SetSelection(item, SELECTION_DEFAULT);
2613 View* hot_view = 2632 View* hot_view =
2614 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN); 2633 GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
2615 CustomButton* hot_button = CustomButton::AsCustomButton(hot_view); 2634 SetHotTrackedButton(CustomButton::AsCustomButton(hot_view));
2635 }
2636
2637 void MenuController::SetHotTrackedButton(CustomButton* hot_button) {
2638 if (hot_button == hot_button_)
2639 return;
2640 if (hot_button_)
2641 hot_button_->SetHotTracked(false);
2642 hot_button_ = hot_button;
2616 if (hot_button) 2643 if (hot_button)
2617 hot_button->SetHotTracked(true); 2644 hot_button->SetHotTracked(true);
2618 } 2645 }
2619 2646
2620 } // namespace views 2647 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698