| 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 1cd057e8dcfc1e33813236383bba75570df59295..581fbb974aba5d1ee1eafc7ef61d282b74084786 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,31 @@ 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* OtherHotTrackedButton(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 = OtherHotTrackedButton(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 +156,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 {
|
| @@ -939,7 +956,13 @@ void MenuController::SetSelection(MenuItemView* menu_item,
|
| if (pending_item_changed && pending_state_.item) {
|
| CustomButton* button = GetFirstHotTrackedView(pending_state_.item);
|
| if (button)
|
| - button->SetHotTracked(false);
|
| + SetHotTrackedButton(button, false);
|
| + }
|
| + CustomButton* new_hot_button = OtherHotTrackedButton(menu_item, hot_button_);
|
| + if (new_hot_button) {
|
| + if (hot_button_)
|
| + SetHotTrackedButton(hot_button_, false);
|
| + SetHotTrackedButton(new_hot_button, true);
|
| }
|
|
|
| // Notify the old path it isn't selected.
|
| @@ -1191,6 +1214,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()),
|
| @@ -1226,8 +1250,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, true);
|
| return true;
|
| }
|
|
|
| @@ -1989,8 +2012,7 @@ 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;
|
| }
|
| }
|
| @@ -1998,20 +2020,20 @@ void MenuController::IncrementSelection(
|
| if (item->has_children()) {
|
| CustomButton* button = GetFirstHotTrackedView(item);
|
| if (button) {
|
| - button->SetHotTracked(false);
|
| - View* to_make_hot = GetNextFocusableView(
|
| + SetHotTrackedButton(button, false);
|
| + View* hot_view = GetNextFocusableView(
|
| item, button, direction == INCREMENT_SELECTION_DOWN);
|
| - CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
|
| - if (button_hot) {
|
| - button_hot->SetHotTracked(true);
|
| + CustomButton* hot_button = CustomButton::AsCustomButton(hot_view);
|
| + if (hot_button) {
|
| + SetHotTrackedButton(hot_button, true);
|
| return;
|
| }
|
| } else {
|
| - View* to_make_hot =
|
| + View* hot_view =
|
| GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
|
| - CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
|
| - if (button_hot) {
|
| - button_hot->SetHotTracked(true);
|
| + CustomButton* hot_button = CustomButton::AsCustomButton(hot_view);
|
| + if (hot_button) {
|
| + SetHotTrackedButton(hot_button, true);
|
| return;
|
| }
|
| }
|
| @@ -2025,14 +2047,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;
|
| }
|
| }
|
| @@ -2597,4 +2612,25 @@ void MenuController::HandleMouseLocation(SubmenuView* source,
|
| }
|
| }
|
|
|
| +void MenuController::SetHotTrackedButton(CustomButton* hot_button,
|
| + bool is_hot_tracked) {
|
| + DCHECK(hot_button);
|
| + hot_button->SetHotTracked(is_hot_tracked);
|
| + DCHECK(is_hot_tracked || (hot_button_ == hot_button));
|
| + hot_button_ = is_hot_tracked ? hot_button : nullptr;
|
| +}
|
| +
|
| +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);
|
| + if (hot_button)
|
| + SetHotTrackedButton(hot_button, true);
|
| +}
|
| +
|
| } // namespace views
|
|
|