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

Unified Diff: ui/views/controls/menu/menu_controller.cc

Issue 1661673004: Enables hot-tracking for overflow extension buttons in the app menu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Restores hot-tracking of extension buttons in app menu with MD (comments) 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 side-by-side diff with in-line comments
Download patch
Index: ui/views/controls/menu/menu_controller.cc
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 0a5dca62ad1639ed708126188ae25607a4f01af2..9f6fa9d77fad943b37b2784fc5ad572aadfd405a 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -53,16 +53,6 @@ using base::Time;
using base::TimeDelta;
using ui::OSExchangeData;
-// Period of the scroll timer (in milliseconds).
-static const int kScrollTimerMS = 30;
-
-// Amount of time from when the drop exits the menu and the menu is hidden.
-static const int kCloseOnExitTime = 1200;
-
-// If a context menu is invoked by touch, we shift the menu by this offset so
-// that the finger does not obscure the menu.
-static const int kCenteredContextMenuYOffset = -15;
-
namespace views {
namespace {
@@ -70,7 +60,17 @@ namespace {
// When showing context menu on mouse down, the user might accidentally select
// the menu item on the subsequent mouse up. To prevent this, we add the
// following delay before the user is able to select an item.
-static int menu_selection_hold_time_ms = kMinimumMsPressedToActivate;
+int menu_selection_hold_time_ms = kMinimumMsPressedToActivate;
+
+// Period of the scroll timer (in milliseconds).
+const int kScrollTimerMS = 30;
+
+// Amount of time from when the drop exits the menu and the menu is hidden.
+const int kCloseOnExitTime = 1200;
+
+// If a context menu is invoked by touch, we shift the menu by this offset so
+// that the finger does not obscure the menu.
+const int kCenteredContextMenuYOffset = -15;
// The spacing offset for the bubble tip.
const int kBubbleTipSizeLeftRight = 12;
@@ -97,7 +97,7 @@ bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) {
}
// Returns the first descendant of |view| that is hot tracked.
-static CustomButton* GetFirstHotTrackedView(View* view) {
+CustomButton* GetFirstHotTrackedView(View* view) {
if (!view)
return NULL;
CustomButton* button = CustomButton::AsCustomButton(view);
@@ -114,12 +114,32 @@ static CustomButton* GetFirstHotTrackedView(View* view) {
return NULL;
}
+// Returns a CustomButton descendant of |view| that is (a) hot-tracked and
+// (b) not equal to |hot_button|. Returns null if such descendant is not found.
+// This allows a caller to detect when a button is set to be hot-tracked by a
+// mouse event and its |hot_button_| indicator becomes stale.
+CustomButton* GetFirstHotTrackedViewDifferingFrom(View* view,
+ CustomButton* hot_button) {
+ if (!view)
+ return nullptr;
+ CustomButton* button = CustomButton::AsCustomButton(view);
+ if (button && button != hot_button && button->IsHotTracked())
+ return button;
+
+ for (int i = 0; i < view->child_count(); ++i) {
+ button = GetFirstHotTrackedViewDifferingFrom(view->child_at(i), hot_button);
+ if (button)
+ return button;
+ }
+ return nullptr;
+}
+
// Recurses through the child views of |view| returning the first view starting
// at |start| that is focusable. A value of -1 for |start| indicates to start at
// the first view (if |forward| is false, iterating starts at the last view). If
// |forward| is true the children are considered first to last, otherwise last
// to first.
-static View* GetFirstFocusableView(View* view, int start, bool forward) {
+View* GetFirstFocusableView(View* view, int start, bool forward) {
if (forward) {
for (int i = start == -1 ? 0 : start; i < view->child_count(); ++i) {
View* deepest = GetFirstFocusableView(view->child_at(i), -1, forward);
@@ -137,15 +157,13 @@ static View* GetFirstFocusableView(View* view, int start, bool forward) {
}
// Returns the first child of |start| that is focusable.
-static View* GetInitialFocusableView(View* start, bool forward) {
+View* GetInitialFocusableView(View* start, bool forward) {
return GetFirstFocusableView(start, -1, forward);
}
// Returns the next view after |start_at| that is focusable. Returns NULL if
// there are no focusable children of |ancestor| after |start_at|.
-static View* GetNextFocusableView(View* ancestor,
- View* start_at,
- bool forward) {
+View* GetNextFocusableView(View* ancestor, View* start_at, bool forward) {
DCHECK(ancestor->Contains(start_at));
View* parent = start_at;
do {
@@ -800,10 +818,15 @@ View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source,
void MenuController::ViewHierarchyChanged(
SubmenuView* source,
const View::ViewHierarchyChangedDetails& details) {
- // If the current mouse handler is removed, remove it as the handler.
- if (!details.is_add && details.child == current_mouse_event_target_) {
- current_mouse_event_target_ = nullptr;
- current_mouse_pressed_state_ = 0;
+ if (!details.is_add) {
+ // If the current mouse handler is removed, remove it as the handler.
+ if (details.child == current_mouse_event_target_) {
+ current_mouse_event_target_ = nullptr;
+ current_mouse_pressed_state_ = 0;
+ }
+ // Update |hot_button_| if it gets deleted while a menu is up.
+ if (details.child == hot_button_)
+ hot_button_ = nullptr;
}
}
@@ -1032,10 +1055,21 @@ void MenuController::SetSelection(MenuItemView* menu_item,
bool pending_item_changed = pending_state_.item != menu_item;
if (pending_item_changed && pending_state_.item) {
- CustomButton* button = GetFirstHotTrackedView(pending_state_.item);
- if (button)
- button->SetHotTracked(false);
- }
+ DCHECK_EQ(hot_button_, GetFirstHotTrackedView(pending_state_.item));
+ SetHotTrackedButton(nullptr);
+ }
+ // A button could become hot-tracked when a mouse is moved without changing
+ // which MenuItem is selected. When a menu item selection is updated, presence
+ // of a hot-tracked button that is not |hot_button_| can mean only that a new
+ // hot-tracked button was set. In this case update |hot_button_| to match.
+ // This allows correct hot-tracked button to be used when alternating between
Peter Kasting 2016/02/24 02:04:48 Nit: correct -> the correct
varkha 2016/02/24 05:52:09 Done.
+ // keyboard and mouse navigation in the menu.
+ CustomButton* new_hot_button =
+ GetFirstHotTrackedViewDifferingFrom(menu_item, hot_button_);
+ // Avoid clearing hot-tracked state from the current |hot_button_| if no other
+ // hot-tracked view exists.
+ if (new_hot_button)
+ SetHotTrackedButton(new_hot_button);
// Notify the old path it isn't selected.
MenuDelegate* current_delegate =
@@ -1286,6 +1320,7 @@ MenuController::MenuController(bool blocking,
last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
showing_submenu_(false),
active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
+ hot_button_(nullptr),
delegate_(delegate),
message_loop_depth_(0),
closing_event_time_(base::TimeDelta()),
@@ -1321,8 +1356,7 @@ bool MenuController::SendAcceleratorToHotTrackedView() {
ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE);
hot_view->AcceleratorPressed(accelerator);
- CustomButton* button = static_cast<CustomButton*>(hot_view);
- button->SetHotTracked(true);
+ SetHotTrackedButton(hot_view);
return true;
}
@@ -2084,32 +2118,20 @@ void MenuController::IncrementSelection(
// select the first menu item that is visible and enabled.
if (item->GetSubmenu()->GetMenuItemCount()) {
MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction);
- if (to_select)
- SetSelection(to_select, SELECTION_DEFAULT);
+ SetInitialHotTrackedView(to_select, direction);
return;
}
}
if (item->has_children()) {
CustomButton* button = GetFirstHotTrackedView(item);
- if (button) {
- button->SetHotTracked(false);
- View* to_make_hot = GetNextFocusableView(
- item, button, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot) {
- button_hot->SetHotTracked(true);
- return;
- }
- } else {
- View* to_make_hot =
- GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot) {
- button_hot->SetHotTracked(true);
- return;
- }
- }
+ bool direction_down = direction == INCREMENT_SELECTION_DOWN;
+ View* hot_view = button ? GetNextFocusableView(item, button, direction_down)
+ : GetInitialFocusableView(item, direction_down);
+ CustomButton* hot_button = CustomButton::AsCustomButton(hot_view);
+ SetHotTrackedButton(hot_button);
+ if (hot_button)
+ return;
}
MenuItemView* parent = item->GetParentMenuItem();
@@ -2120,14 +2142,7 @@ void MenuController::IncrementSelection(
if (parent->GetSubmenu()->GetMenuItemAt(i) == item) {
MenuItemView* to_select =
FindNextSelectableMenuItem(parent, i, direction);
- if (!to_select)
- break;
- SetSelection(to_select, SELECTION_DEFAULT);
- View* to_make_hot = GetInitialFocusableView(
- to_select, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot)
- button_hot->SetHotTracked(true);
+ SetInitialHotTrackedView(to_select, direction);
break;
}
}
@@ -2609,4 +2624,26 @@ void MenuController::HandleMouseLocation(SubmenuView* source,
}
}
+void MenuController::SetHotTrackedButton(CustomButton* hot_button) {
+ if (hot_button_ == hot_button)
+ return;
+ if (hot_button_)
+ hot_button_->SetHotTracked(false);
+ if (hot_button)
+ hot_button->SetHotTracked(true);
+ hot_button_ = hot_button;
+}
+
+void MenuController::SetInitialHotTrackedView(
+ MenuItemView* item,
+ SelectionIncrementDirectionType direction) {
+ if (!item)
+ return;
+ SetSelection(item, SELECTION_DEFAULT);
+ View* hot_view =
+ GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
+ CustomButton* hot_button = CustomButton::AsCustomButton(hot_view);
Peter Kasting 2016/02/24 02:04:48 Nit: Inline into next line
varkha 2016/02/24 05:52:09 Done.
+ SetHotTrackedButton(hot_button);
+}
+
} // namespace views

Powered by Google App Engine
This is Rietveld 408576698