Commit aed90203 authored by Nektarios Paisios's avatar Nektarios Paisios Committed by Commit Bot

Enables the use of Home and End keys to navigate to the top and bottom of menus

Also, enables Option-Up and Option-Down on the Mac.
R=sky@chromium.org, aleventhal@chromium.org, dmazzoni@chromium.org, pboss@chromium.org

Change-Id: I78b32b170e4600c14faf81fdfb1850bb0a720cd6
Bug: 908522
Reviewed-on: https://chromium-review.googlesource.com/c/1337819
Commit-Queue: Nektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611312}
parent 35c76d4b
...@@ -1118,7 +1118,23 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent( ...@@ -1118,7 +1118,23 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
if (event->type() == ui::ET_KEY_PRESSED) { if (event->type() == ui::ET_KEY_PRESSED) {
base::WeakPtr<MenuController> this_ref = AsWeakPtr(); base::WeakPtr<MenuController> this_ref = AsWeakPtr();
#if defined(OS_MACOSX)
// Special handling for Option-Up and Option-Down, which should behave like
// Home and End respectively in menus.
if ((event->flags() & ui::EF_ALT_DOWN)) {
if (event->key_code() == ui::VKEY_UP) {
OnKeyDown(ui::VKEY_HOME);
} else if (event->key_code() == ui::VKEY_DOWN) {
OnKeyDown(ui::VKEY_END);
} else {
OnKeyDown(event->key_code());
}
} else {
OnKeyDown(event->key_code());
}
#else
OnKeyDown(event->key_code()); OnKeyDown(event->key_code());
#endif
// Key events can lead to this being deleted. // Key events can lead to this being deleted.
if (!this_ref) if (!this_ref)
return ui::POST_DISPATCH_NONE; return ui::POST_DISPATCH_NONE;
...@@ -1348,6 +1364,14 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) { ...@@ -1348,6 +1364,14 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
return; return;
switch (key_code) { switch (key_code) {
case ui::VKEY_HOME:
MoveSelectionToFirstOrLastItem(INCREMENT_SELECTION_DOWN);
break;
case ui::VKEY_END:
MoveSelectionToFirstOrLastItem(INCREMENT_SELECTION_UP);
break;
case ui::VKEY_UP: case ui::VKEY_UP:
IncrementSelection(INCREMENT_SELECTION_UP); IncrementSelection(INCREMENT_SELECTION_UP);
break; break;
...@@ -2417,6 +2441,27 @@ void MenuController::IncrementSelection( ...@@ -2417,6 +2441,27 @@ void MenuController::IncrementSelection(
} }
} }
void MenuController::MoveSelectionToFirstOrLastItem(
SelectionIncrementDirectionType direction) {
MenuItemView* item = pending_state_.item;
DCHECK(item);
MenuItemView* submenu = nullptr;
if (pending_state_.submenu_open && item->SubmenuIsShowing()) {
if (!item->GetSubmenu()->GetMenuItemCount())
return;
// A menu is selected and open, but none of its children are selected,
// select the first or last menu item that is visible and enabled.
submenu = item;
} else {
submenu = item->GetParentMenuItem();
}
MenuItemView* to_select = FindInitialSelectableMenuItem(submenu, direction);
SetInitialHotTrackedView(to_select, direction);
}
MenuItemView* MenuController::FindInitialSelectableMenuItem( MenuItemView* MenuController::FindInitialSelectableMenuItem(
MenuItemView* parent, MenuItemView* parent,
SelectionIncrementDirectionType direction) { SelectionIncrementDirectionType direction) {
......
...@@ -487,6 +487,10 @@ class VIEWS_EXPORT MenuController ...@@ -487,6 +487,10 @@ class VIEWS_EXPORT MenuController
// Selects the next or previous (depending on |direction|) menu item. // Selects the next or previous (depending on |direction|) menu item.
void IncrementSelection(SelectionIncrementDirectionType direction); void IncrementSelection(SelectionIncrementDirectionType direction);
// Selects the first or last (depending on |direction|) menu item.
void MoveSelectionToFirstOrLastItem(
SelectionIncrementDirectionType direction);
// Returns the first (|direction| == NAVIGATE_SELECTION_DOWN) or the last // Returns the first (|direction| == NAVIGATE_SELECTION_DOWN) or the last
// (|direction| == INCREMENT_SELECTION_UP) selectable child menu item of // (|direction| == INCREMENT_SELECTION_UP) selectable child menu item of
// |parent|. If there are no selectable items returns NULL. // |parent|. If there are no selectable items returns NULL.
......
...@@ -779,6 +779,66 @@ TEST_F(MenuControllerTest, InitialSelectedItem) { ...@@ -779,6 +779,66 @@ TEST_F(MenuControllerTest, InitialSelectedItem) {
ResetSelection(); ResetSelection();
} }
// Tests that opening the menu and pressing 'Home' selects the first menu item.
TEST_F(MenuControllerTest, FirstSelectedItem) {
SetPendingStateItem(menu_item()->GetSubmenu()->GetMenuItemAt(0));
EXPECT_EQ(1, pending_state_item()->GetCommand());
// Select the first menu item.
DispatchKey(ui::VKEY_HOME);
EXPECT_EQ(1, pending_state_item()->GetCommand());
// Fake initial root item selection and submenu showing.
SetPendingStateItem(menu_item());
EXPECT_EQ(0, pending_state_item()->GetCommand());
// Select the first menu item.
DispatchKey(ui::VKEY_HOME);
EXPECT_EQ(1, pending_state_item()->GetCommand());
// Select the last item.
SetPendingStateItem(menu_item()->GetSubmenu()->GetMenuItemAt(3));
EXPECT_EQ(4, pending_state_item()->GetCommand());
// Select the first menu item.
DispatchKey(ui::VKEY_HOME);
EXPECT_EQ(1, pending_state_item()->GetCommand());
// Clear references in menu controller to the menu item that is going away.
ResetSelection();
}
// Tests that opening the menu and pressing 'End' selects the last enabled menu
// item.
TEST_F(MenuControllerTest, LastSelectedItem) {
// Fake initial root item selection and submenu showing.
SetPendingStateItem(menu_item());
EXPECT_EQ(0, pending_state_item()->GetCommand());
// Select the last menu item.
DispatchKey(ui::VKEY_END);
EXPECT_EQ(4, pending_state_item()->GetCommand());
// Select the last item.
SetPendingStateItem(menu_item()->GetSubmenu()->GetMenuItemAt(3));
EXPECT_EQ(4, pending_state_item()->GetCommand());
// Select the last menu item.
DispatchKey(ui::VKEY_END);
EXPECT_EQ(4, pending_state_item()->GetCommand());
// Select the first item.
SetPendingStateItem(menu_item()->GetSubmenu()->GetMenuItemAt(0));
EXPECT_EQ(1, pending_state_item()->GetCommand());
// Select the last menu item.
DispatchKey(ui::VKEY_END);
EXPECT_EQ(4, pending_state_item()->GetCommand());
// Clear references in menu controller to the menu item that is going away.
ResetSelection();
}
// Tests that opening menu and pressing 'Down' and 'Up' iterates over enabled // Tests that opening menu and pressing 'Down' and 'Up' iterates over enabled
// items. // items.
TEST_F(MenuControllerTest, NextSelectedItem) { TEST_F(MenuControllerTest, NextSelectedItem) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment