chromium/android_webview/java/src/org/chromium/android_webview/AwKeyboardShortcuts.java

// Copyright 2023 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.android_webview;

import android.view.KeyEvent;

import org.chromium.android_webview.common.AwFeatures;
import org.chromium.content_public.browser.KeyboardShortcutRecorder;
import org.chromium.content_public.browser.KeyboardShortcutRecorder.KeyboardShortcut;

/**
 * Handles WebView keyboard shortcut events that weren't handled in {@link
 * AwWebContentsDelegateAdapter#handleKeyboardEvent(KeyEvent)}.
 */
/**
 * TODO(wbjacksonjr) Possibly merge this class with {@link
 * org.chromium.chrome.browser.KeyboardShortcuts}
 */
public class AwKeyboardShortcuts {
    private static final int CTRL = 1 << 31;
    private static final int ALT = 1 << 30;
    private static final int SHIFT = 1 << 29;

    private AwKeyboardShortcuts() {}

    private static int getMetaState(KeyEvent event) {
        return (event.isCtrlPressed() ? CTRL : 0)
                | (event.isAltPressed() ? ALT : 0)
                | (event.isShiftPressed() ? SHIFT : 0);
    }

    public static boolean onKeyDown(KeyEvent event, AwContents awContents) {
        int keyCode = event.getKeyCode();
        if (event.getRepeatCount() != 0
                || event.getAction() != KeyEvent.ACTION_DOWN
                || KeyEvent.isModifierKey(keyCode)) {
            return false;
        }

        int metaState = getMetaState(event);
        int keyCodeAndMeta = keyCode | metaState;

        if (AwFeatureMap.isEnabled(AwFeatures.WEBVIEW_ZOOM_KEYBOARD_SHORTCUTS)) {
            return handleZoomShortcut(awContents, keyCodeAndMeta);
        }
        return false;
    }

    private static boolean handleZoomShortcut(AwContents awContents, int keyCodeAndMeta) {
        // We want to return true even if zoom is not supported as technically the keyboard shortcut
        // was handled
        boolean supportsZoom = awContents.getSettings().supportZoom();
        switch (keyCodeAndMeta) {
            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:
                if (supportsZoom) {
                    awContents.zoomIn();
                    KeyboardShortcutRecorder.recordKeyboardShortcut(KeyboardShortcut.ZOOM_IN);
                }
                return true;
            case CTRL | KeyEvent.KEYCODE_MINUS:
            case KeyEvent.KEYCODE_ZOOM_OUT:
                if (supportsZoom) {
                    awContents.zoomOut();
                    KeyboardShortcutRecorder.recordKeyboardShortcut(KeyboardShortcut.ZOOM_OUT);
                }
                return true;
            case CTRL | KeyEvent.KEYCODE_0:
                if (supportsZoom) {
                    awContents.zoomReset();
                    KeyboardShortcutRecorder.recordKeyboardShortcut(KeyboardShortcut.ZOOM_RESET);
                }
                return true;
        }
        return false;
    }
}