// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser;
import android.content.Context;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
import android.view.KeyboardShortcutInfo;
import androidx.annotation.IntDef;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.fullscreen.FullscreenManager;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelUtils;
import org.chromium.chrome.browser.toolbar.ToolbarManager;
import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.device.gamepad.GamepadList;
import org.chromium.ui.accessibility.AccessibilityState;
import java.util.ArrayList;
import java.util.List;
/** Implements app-level keyboard shortcuts for ChromeTabbedActivity and DocumentActivity. */
public class KeyboardShortcuts {
private static final int CTRL = 1 << 31;
private static final int ALT = 1 << 30;
private static final int SHIFT = 1 << 29;
private KeyboardShortcuts() {}
// KeyboardShortcutsSemanticMeaning defined in tools/metrics/histograms/enums.xml.
// Add new values before MAX_VALUE. These values are persisted to logs. Entries should not be
// renumbered and numeric values should never be reused.
// LINT.IfChange(KeyboardShortcutsSemanticMeaning)
@IntDef({
KeyboardShortcutsSemanticMeaning.UNKNOWN,
KeyboardShortcutsSemanticMeaning.OPEN_RECENTLY_CLOSED_TAB,
KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB,
KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB_INCOGNITO,
KeyboardShortcutsSemanticMeaning.OPEN_NEW_WINDOW,
KeyboardShortcutsSemanticMeaning.RELOAD_TAB,
KeyboardShortcutsSemanticMeaning.CLOSE_TAB,
KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_LEFT,
KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_RIGHT,
KeyboardShortcutsSemanticMeaning.MOVE_TO_SPECIFIC_TAB,
KeyboardShortcutsSemanticMeaning.MOVE_TO_LAST_TAB,
KeyboardShortcutsSemanticMeaning.JUMP_TO_OMNIBOX,
KeyboardShortcutsSemanticMeaning.GO_BACK,
KeyboardShortcutsSemanticMeaning.GO_FORWARD,
KeyboardShortcutsSemanticMeaning.OPEN_MENU,
KeyboardShortcutsSemanticMeaning.OPEN_HELP,
KeyboardShortcutsSemanticMeaning.FIND_IN_PAGE,
KeyboardShortcutsSemanticMeaning.OPEN_BOOKMARKS,
KeyboardShortcutsSemanticMeaning.BOOKMARK_PAGE,
KeyboardShortcutsSemanticMeaning.OPEN_HISTORY,
KeyboardShortcutsSemanticMeaning.SAVE_PAGE,
KeyboardShortcutsSemanticMeaning.PRINT,
KeyboardShortcutsSemanticMeaning.ZOOM_IN,
KeyboardShortcutsSemanticMeaning.ZOOM_OUT,
KeyboardShortcutsSemanticMeaning.ZOOM_RESET,
KeyboardShortcutsSemanticMeaning.MAX_VALUE
})
public @interface KeyboardShortcutsSemanticMeaning {
// Unrecognized key combination.
int UNKNOWN = 0;
// Tab/window creation.
int OPEN_RECENTLY_CLOSED_TAB = 1;
int OPEN_NEW_TAB = 2;
int OPEN_NEW_TAB_INCOGNITO = 3;
int OPEN_NEW_WINDOW = 4;
// Tab control.
int RELOAD_TAB = 5;
int CLOSE_TAB = 6;
int MOVE_TO_TAB_LEFT = 7;
int MOVE_TO_TAB_RIGHT = 8;
int MOVE_TO_SPECIFIC_TAB = 9;
int MOVE_TO_LAST_TAB = 10;
// Navigation controls.
int JUMP_TO_OMNIBOX = 11;
int GO_BACK = 12;
int GO_FORWARD = 13;
// 3-dot menu controls.
int OPEN_MENU = 14;
int OPEN_HELP = 15;
int FIND_IN_PAGE = 16;
int OPEN_BOOKMARKS = 17;
int BOOKMARK_PAGE = 18;
int OPEN_HISTORY = 19;
int SAVE_PAGE = 20;
int PRINT = 21;
// Zoom controls.
int ZOOM_IN = 22;
int ZOOM_OUT = 23;
int ZOOM_RESET = 24;
// Be sure to also update enums.xml when updating these values.
int MAX_VALUE = 25;
}
// LINT.ThenChange(/tools/metrics/histograms/metadata/accessibility/enums.xml:KeyboardShortcutsSemanticMeaning)
private static @KeyboardShortcutsSemanticMeaning int getKeyboardSemanticMeaning(
int keyCodeAndMeta) {
switch (keyCodeAndMeta) {
// Tab/window creation.
case CTRL | SHIFT | KeyEvent.KEYCODE_T:
return KeyboardShortcutsSemanticMeaning.OPEN_RECENTLY_CLOSED_TAB;
case CTRL | KeyEvent.KEYCODE_T:
return KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB;
case CTRL | SHIFT | KeyEvent.KEYCODE_N:
return KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB_INCOGNITO;
case CTRL | KeyEvent.KEYCODE_N:
return KeyboardShortcutsSemanticMeaning.OPEN_NEW_WINDOW;
// Tab control.
case CTRL | SHIFT | KeyEvent.KEYCODE_R:
case CTRL | KeyEvent.KEYCODE_R:
case SHIFT | KeyEvent.KEYCODE_F5:
case KeyEvent.KEYCODE_F5:
case KeyEvent.KEYCODE_REFRESH:
return KeyboardShortcutsSemanticMeaning.RELOAD_TAB;
case CTRL | KeyEvent.KEYCODE_W:
case CTRL | KeyEvent.KEYCODE_F4:
case KeyEvent.KEYCODE_BUTTON_B:
return KeyboardShortcutsSemanticMeaning.CLOSE_TAB;
case CTRL | SHIFT | KeyEvent.KEYCODE_TAB:
case CTRL | KeyEvent.KEYCODE_PAGE_UP:
case KeyEvent.KEYCODE_BUTTON_L1:
return KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_LEFT;
case CTRL | KeyEvent.KEYCODE_TAB:
case CTRL | KeyEvent.KEYCODE_PAGE_DOWN:
case KeyEvent.KEYCODE_BUTTON_R1:
return KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_RIGHT;
case CTRL | KeyEvent.KEYCODE_1:
case CTRL | KeyEvent.KEYCODE_2:
case CTRL | KeyEvent.KEYCODE_3:
case CTRL | KeyEvent.KEYCODE_4:
case CTRL | KeyEvent.KEYCODE_5:
case CTRL | KeyEvent.KEYCODE_6:
case CTRL | KeyEvent.KEYCODE_7:
case CTRL | KeyEvent.KEYCODE_8:
case ALT | KeyEvent.KEYCODE_1:
case ALT | KeyEvent.KEYCODE_2:
case ALT | KeyEvent.KEYCODE_3:
case ALT | KeyEvent.KEYCODE_4:
case ALT | KeyEvent.KEYCODE_5:
case ALT | KeyEvent.KEYCODE_6:
case ALT | KeyEvent.KEYCODE_7:
case ALT | KeyEvent.KEYCODE_8:
return KeyboardShortcutsSemanticMeaning.MOVE_TO_SPECIFIC_TAB;
case CTRL | KeyEvent.KEYCODE_9:
case ALT | KeyEvent.KEYCODE_9:
return KeyboardShortcutsSemanticMeaning.MOVE_TO_LAST_TAB;
// Navigation controls.
case CTRL | KeyEvent.KEYCODE_L:
case ALT | KeyEvent.KEYCODE_D:
case KeyEvent.KEYCODE_BUTTON_X:
return KeyboardShortcutsSemanticMeaning.JUMP_TO_OMNIBOX;
case ALT | KeyEvent.KEYCODE_DPAD_LEFT:
return KeyboardShortcutsSemanticMeaning.GO_BACK;
case ALT | KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_FORWARD:
case KeyEvent.KEYCODE_BUTTON_START:
return KeyboardShortcutsSemanticMeaning.GO_FORWARD;
// 3-dot menu controls.
case ALT | KeyEvent.KEYCODE_E:
case ALT | KeyEvent.KEYCODE_F:
case KeyEvent.KEYCODE_F10:
case KeyEvent.KEYCODE_BUTTON_Y:
return KeyboardShortcutsSemanticMeaning.OPEN_MENU;
case CTRL | SHIFT | KeyEvent.KEYCODE_SLASH: // i.e. Ctrl+?
return KeyboardShortcutsSemanticMeaning.OPEN_HELP;
case CTRL | KeyEvent.KEYCODE_F:
case CTRL | KeyEvent.KEYCODE_G:
case CTRL | SHIFT | KeyEvent.KEYCODE_G:
case KeyEvent.KEYCODE_F3:
case SHIFT | KeyEvent.KEYCODE_F3:
return KeyboardShortcutsSemanticMeaning.FIND_IN_PAGE;
case CTRL | SHIFT | KeyEvent.KEYCODE_B:
return KeyboardShortcutsSemanticMeaning.OPEN_BOOKMARKS;
case KeyEvent.KEYCODE_BOOKMARK:
case CTRL | KeyEvent.KEYCODE_D:
return KeyboardShortcutsSemanticMeaning.BOOKMARK_PAGE;
case CTRL | KeyEvent.KEYCODE_H:
return KeyboardShortcutsSemanticMeaning.OPEN_HISTORY;
case CTRL | KeyEvent.KEYCODE_S:
return KeyboardShortcutsSemanticMeaning.SAVE_PAGE;
case CTRL | KeyEvent.KEYCODE_P:
return KeyboardShortcutsSemanticMeaning.PRINT;
// Zoom controls.
case CTRL | KeyEvent.KEYCODE_PLUS:
case CTRL | KeyEvent.KEYCODE_EQUALS:
case CTRL | SHIFT | KeyEvent.KEYCODE_PLUS:
case CTRL | SHIFT | KeyEvent.KEYCODE_EQUALS:
case KeyEvent.KEYCODE_ZOOM_IN:
return KeyboardShortcutsSemanticMeaning.ZOOM_IN;
case CTRL | KeyEvent.KEYCODE_MINUS:
case KeyEvent.KEYCODE_ZOOM_OUT:
return KeyboardShortcutsSemanticMeaning.ZOOM_OUT;
case CTRL | KeyEvent.KEYCODE_0:
return KeyboardShortcutsSemanticMeaning.ZOOM_RESET;
}
return KeyboardShortcutsSemanticMeaning.UNKNOWN;
}
private static int getMetaState(KeyEvent event) {
return (event.isCtrlPressed() ? CTRL : 0)
| (event.isAltPressed() ? ALT : 0)
| (event.isShiftPressed() ? SHIFT : 0);
}
/**
* This should be called from the Activity's dispatchKeyEvent() to handle keyboard shortcuts.
*
* Note: dispatchKeyEvent() is called before the active view or web page gets a chance to handle
* the key event. So the keys handled here cannot be overridden by any view or web page.
*
* @param event The KeyEvent to handle.
* @param uiInitialized Whether the UI has been initialized. If this is false, most keys will
* not be handled.
* @param fullscreenManager Manages fullscreen state.
* @param menuOrKeyboardActionController Controls keyboard actions.
* @return True if the event was handled. False if the event was ignored. Null if the event
* should be handled by the activity's parent class.
*/
public static Boolean dispatchKeyEvent(
KeyEvent event,
boolean uiInitialized,
FullscreenManager fullscreenManager,
MenuOrKeyboardActionController menuOrKeyboardActionController) {
int keyCode = event.getKeyCode();
if (!uiInitialized) {
if (keyCode == KeyEvent.KEYCODE_SEARCH || keyCode == KeyEvent.KEYCODE_MENU) return true;
return null;
}
switch (keyCode) {
case KeyEvent.KEYCODE_SEARCH:
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.focus_url_bar, false);
}
// Always consume the SEARCH key events to prevent android from showing
// the default app search UI, which locks up Chrome.
return true;
case KeyEvent.KEYCODE_MENU:
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.show_menu, false);
}
return true;
case KeyEvent.KEYCODE_ESCAPE:
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
if (fullscreenManager.getPersistentFullscreenMode()) {
fullscreenManager.exitPersistentFullscreenMode();
return true;
}
}
break;
case KeyEvent.KEYCODE_TV:
case KeyEvent.KEYCODE_GUIDE:
case KeyEvent.KEYCODE_DVR:
case KeyEvent.KEYCODE_AVR_INPUT:
case KeyEvent.KEYCODE_AVR_POWER:
case KeyEvent.KEYCODE_STB_INPUT:
case KeyEvent.KEYCODE_STB_POWER:
case KeyEvent.KEYCODE_TV_INPUT:
case KeyEvent.KEYCODE_TV_POWER:
case KeyEvent.KEYCODE_WINDOW:
// Do not consume the AV device-related keys so that the system will take
// an appropriate action, such as switching to TV mode.
return false;
}
return null;
}
/**
* This method should be called when overriding from
* {@link android.app.Activity#onProvideKeyboardShortcuts(List, android.view.Menu, int)}
* in an activity. It will return a list of the possible shortcuts. If
* someone adds a shortcut they also need to add an explanation in the
* appropriate group in this method so the user can see it when this method
* is called.
*
* Preventing inlining since this uses APIs only available on Android N, and this causes dex
* validation failures on earlier versions if inlined.
*
* @param context We need an activity so we can call the strings from our
* resource.
* @return a list of shortcuts organized into groups.
*/
public static List<KeyboardShortcutGroup> createShortcutGroup(Context context) {
final int ctrlShift = KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON;
List<KeyboardShortcutGroup> shortcutGroups = new ArrayList<>();
KeyboardShortcutGroup tabShortcutGroup =
new KeyboardShortcutGroup(
context.getString(R.string.keyboard_shortcut_tab_group_header));
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_open_new_tab,
KeyEvent.KEYCODE_T,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_open_new_window,
KeyEvent.KEYCODE_N,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_reopen_new_tab,
KeyEvent.KEYCODE_T,
ctrlShift);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_new_incognito_tab,
KeyEvent.KEYCODE_N,
ctrlShift);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_next_tab,
KeyEvent.KEYCODE_TAB,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_prev_tab,
KeyEvent.KEYCODE_TAB,
ctrlShift);
addShortcut(
context,
tabShortcutGroup,
R.string.keyboard_shortcut_close_tab,
KeyEvent.KEYCODE_W,
KeyEvent.META_CTRL_ON);
shortcutGroups.add(tabShortcutGroup);
KeyboardShortcutGroup chromeFeatureShortcutGroup =
new KeyboardShortcutGroup(
context.getString(R.string.keyboard_shortcut_chrome_feature_group_header));
addShortcut(
context,
chromeFeatureShortcutGroup,
R.string.keyboard_shortcut_open_menu,
KeyEvent.KEYCODE_E,
KeyEvent.META_ALT_ON);
addShortcut(
context,
chromeFeatureShortcutGroup,
R.string.keyboard_shortcut_bookmark_manager,
KeyEvent.KEYCODE_B,
ctrlShift);
addShortcut(
context,
chromeFeatureShortcutGroup,
R.string.keyboard_shortcut_history_manager,
KeyEvent.KEYCODE_H,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
chromeFeatureShortcutGroup,
R.string.keyboard_shortcut_find_bar,
KeyEvent.KEYCODE_F,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
chromeFeatureShortcutGroup,
R.string.keyboard_shortcut_address_bar,
KeyEvent.KEYCODE_L,
KeyEvent.META_CTRL_ON);
shortcutGroups.add(chromeFeatureShortcutGroup);
KeyboardShortcutGroup webpageShortcutGroup =
new KeyboardShortcutGroup(
context.getString(R.string.keyboard_shortcut_webpage_group_header));
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_print_page,
KeyEvent.KEYCODE_P,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_reload_page,
KeyEvent.KEYCODE_R,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_reload_no_cache,
KeyEvent.KEYCODE_R,
ctrlShift);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_bookmark_page,
KeyEvent.KEYCODE_D,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_zoom_in,
KeyEvent.KEYCODE_EQUALS,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_zoom_out,
KeyEvent.KEYCODE_MINUS,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_reset_zoom,
KeyEvent.KEYCODE_0,
KeyEvent.META_CTRL_ON);
addShortcut(
context,
webpageShortcutGroup,
R.string.keyboard_shortcut_help_center,
KeyEvent.KEYCODE_SLASH,
ctrlShift);
shortcutGroups.add(webpageShortcutGroup);
return shortcutGroups;
}
private static void addShortcut(
Context context,
KeyboardShortcutGroup shortcutGroup,
int resId,
int keyCode,
int keyModifier) {
shortcutGroup.addItem(
new KeyboardShortcutInfo(context.getString(resId), keyCode, keyModifier));
}
/**
* This should be called from the Activity's onKeyDown() to handle keyboard shortcuts.
*
* Note: onKeyDown() is called after the active view or web page has had a chance to handle
* the key event. So the keys handled here *can* be overridden by any view or web page.
*
* @param event The KeyEvent to handle.
* @param isCurrentTabVisible Whether page-related actions are valid, e.g. reload, zoom in. This
* should be false when in the tab switcher.
* @param tabSwitchingEnabled Whether shortcuts that switch between tabs are enabled (e.g.
* Ctrl+Tab, Ctrl+3).
* @param tabModelSelector The current tab modelSelector.
* @param menuOrKeyboardActionController Controls keyboard actions.
* @param toolbarManager Manages the toolbar.
* @return Whether the key event was handled.
*/
public static boolean onKeyDown(
KeyEvent event,
boolean isCurrentTabVisible,
boolean tabSwitchingEnabled,
TabModelSelector tabModelSelector,
MenuOrKeyboardActionController menuOrKeyboardActionController,
ToolbarManager toolbarManager) {
int keyCode = event.getKeyCode();
if (event.getRepeatCount() != 0 || KeyEvent.isModifierKey(keyCode)) return false;
if (KeyEvent.isGamepadButton(keyCode)) {
if (GamepadList.isGamepadAPIActive()) return false;
} else if (!event.isCtrlPressed()
&& !event.isAltPressed()
&& keyCode != KeyEvent.KEYCODE_F3
&& keyCode != KeyEvent.KEYCODE_F5
&& keyCode != KeyEvent.KEYCODE_F10
&& keyCode != KeyEvent.KEYCODE_FORWARD
&& keyCode != KeyEvent.KEYCODE_REFRESH) {
return false;
}
TabModel currentTabModel = tabModelSelector.getCurrentModel();
Tab currentTab = tabModelSelector.getCurrentTab();
WebContents currentWebContents = currentTab == null ? null : currentTab.getWebContents();
int tabCount = currentTabModel.getCount();
int metaState = getMetaState(event);
int keyCodeAndMeta = keyCode | metaState;
@KeyboardShortcutsSemanticMeaning
int semanticMeaning = getKeyboardSemanticMeaning(keyCodeAndMeta);
RecordHistogram.recordEnumeratedHistogram(
AccessibilityState.isScreenReaderEnabled()
? "Accessibility.Android.KeyboardShortcut.ScreenReaderRunning"
: "Accessibility.Android.KeyboardShortcut.NoScreenReader",
semanticMeaning,
KeyboardShortcuts.KeyboardShortcutsSemanticMeaning.MAX_VALUE);
switch (semanticMeaning) {
case KeyboardShortcutsSemanticMeaning.OPEN_RECENTLY_CLOSED_TAB:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.open_recently_closed_tab, false);
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
currentTabModel.isIncognito()
? R.id.new_incognito_tab_menu_id
: R.id.new_tab_menu_id,
false);
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_NEW_WINDOW:
if (MultiWindowUtils.isMultiInstanceApi31Enabled()) {
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.new_window_menu_id, false);
return true;
} else {
break;
}
case KeyboardShortcutsSemanticMeaning.SAVE_PAGE:
menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.offline_page_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_NEW_TAB_INCOGNITO:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.new_incognito_tab_menu_id, false);
return true;
// Alt+E represents a special character ยด (latin code: ´) in Android.
// If an EditText or ContentView has focus, Alt+E will be swallowed by
// the default dispatchKeyEvent and cannot open the menu.
case KeyboardShortcutsSemanticMeaning.OPEN_MENU:
menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.show_menu, false);
return true;
}
if (isCurrentTabVisible) {
switch (semanticMeaning) {
case KeyboardShortcutsSemanticMeaning.MOVE_TO_SPECIFIC_TAB:
if (tabSwitchingEnabled) {
int numCode = keyCode - KeyEvent.KEYCODE_0;
if (numCode > 0 && numCode <= Math.min(tabCount, 8)) {
TabModelUtils.setIndex(currentTabModel, numCode - 1);
}
}
return true;
case KeyboardShortcutsSemanticMeaning.MOVE_TO_LAST_TAB:
if (tabSwitchingEnabled && tabCount != 0) {
TabModelUtils.setIndex(currentTabModel, tabCount - 1);
}
return true;
case KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_RIGHT:
if (tabSwitchingEnabled && tabCount > 1) {
TabModelUtils.setIndex(
currentTabModel, (currentTabModel.index() + 1) % tabCount);
}
return true;
case KeyboardShortcutsSemanticMeaning.MOVE_TO_TAB_LEFT:
if (tabSwitchingEnabled && tabCount > 1) {
TabModelUtils.setIndex(
currentTabModel,
(currentTabModel.index() + tabCount - 1) % tabCount);
}
return true;
case KeyboardShortcutsSemanticMeaning.CLOSE_TAB:
TabModelUtils.closeCurrentTab(currentTabModel);
return true;
case KeyboardShortcutsSemanticMeaning.FIND_IN_PAGE:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.find_in_page_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.JUMP_TO_OMNIBOX:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.focus_url_bar, false);
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_BOOKMARKS:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.all_bookmarks_menu_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.BOOKMARK_PAGE:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.bookmark_this_page_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_HISTORY:
menuOrKeyboardActionController.onMenuOrKeyboardAction(
R.id.open_history_menu_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.PRINT:
menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.print_id, false);
return true;
case KeyboardShortcutsSemanticMeaning.ZOOM_IN:
ZoomController.zoomIn(currentWebContents);
return true;
case KeyboardShortcutsSemanticMeaning.ZOOM_OUT:
ZoomController.zoomOut(currentWebContents);
return true;
case KeyboardShortcutsSemanticMeaning.ZOOM_RESET:
ZoomController.zoomReset(currentWebContents);
return true;
case KeyboardShortcutsSemanticMeaning.RELOAD_TAB:
if (currentTab != null) {
if ((keyCodeAndMeta & SHIFT) == SHIFT) {
currentTab.reloadIgnoringCache();
} else {
currentTab.reload();
}
if (toolbarManager != null
&& currentWebContents != null
&& currentWebContents.focusLocationBarByDefault()) {
toolbarManager.revertLocationBarChanges();
} else if (currentTab.getView() != null) {
currentTab.getView().requestFocus();
}
}
return true;
case KeyboardShortcutsSemanticMeaning.GO_BACK:
if (currentTab != null && currentTab.canGoBack()) currentTab.goBack();
return true;
case KeyboardShortcutsSemanticMeaning.GO_FORWARD:
if (currentTab != null && currentTab.canGoForward()) currentTab.goForward();
return true;
case KeyboardShortcutsSemanticMeaning.OPEN_HELP:
menuOrKeyboardActionController.onMenuOrKeyboardAction(R.id.help_id, false);
return true;
}
}
return false;
}
}