Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5e3e62d authored by Simon Chan's avatar Simon Chan
Browse files

feat(demo): improve key event handling

parent 667a44b0
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ import { makeStyles } from "@griffel/react";
import {
    CSSProperties,
    ComponentType,
    HTMLAttributes,
    ReactNode,
    useImperativeHandle,
    useMemo,
@@ -12,7 +13,7 @@ import {
import { forwardRef } from "../utils/with-display-name";
import { ResizeObserver, Size } from "./resize-observer";

export interface DeviceViewProps {
export interface DeviceViewProps extends HTMLAttributes<HTMLDivElement> {
    width: number;

    height: number;
@@ -46,7 +47,10 @@ const useClasses = makeStyles({
});

export const DeviceView = forwardRef<DeviceViewRef>("DeviceView")(
    ({ width, height, BottomElement, children }: DeviceViewProps, ref) => {
    (
        { width, height, BottomElement, children, ...props }: DeviceViewProps,
        ref
    ) => {
        const classes = useClasses();

        const [containerSize, setContainerSize] = useState<Size>({
@@ -122,7 +126,7 @@ export const DeviceView = forwardRef<DeviceViewRef>("DeviceView")(

        return (
            <StackItem grow styles={{ root: { position: "relative" } }}>
                <div ref={containerRef} className={classes.outer}>
                <div ref={containerRef} className={classes.outer} {...props}>
                    <ResizeObserver onResize={setContainerSize} />

                    <div
+7 −0
Original line number Diff line number Diff line
@@ -33,6 +33,13 @@ function handlePointerDown(e: PointerEvent<HTMLDivElement>) {
    }

    e.currentTarget.setPointerCapture(e.pointerId);
    e.preventDefault();
    e.stopPropagation();

    // Don't focus virtual navigation buttons
    // make sure all keyboard events are sent to the renderer
    STATE.rendererContainer!.focus();

    return true;
}

+4 −1
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ import { ADB_SYNC_MAX_PACKET_SIZE } from "@yume-chan/adb";
import {
    AdbScrcpyClient,
    AdbScrcpyOptions1_22,
    AndroidKeyCode,
    AndroidScreenPowerMode,
    CodecOptions,
    DEFAULT_SERVER_PATH,
@@ -56,6 +57,7 @@ export class ScrcpyPageState {

    client: AdbScrcpyClient | undefined = undefined;
    hoverHelper: ScrcpyHoverHelper | undefined = undefined;
    pressedKeys: Set<AndroidKeyCode> = new Set();

    async pushServer() {
        const serverBuffer = await fetchServer();
@@ -333,7 +335,6 @@ export class ScrcpyPageState {
                );
            }


            runInAction(() => {
                this.client = client;
                this.hoverHelper = new ScrcpyHoverHelper();
@@ -364,6 +365,8 @@ export class ScrcpyPageState {
            RECORD_STATE.recording = false;
        }

        this.pressedKeys.clear();

        this.fps = "0";
        clearTimeout(this.fpsCounterIntervalId);

+50 −5
Original line number Diff line number Diff line
@@ -78,9 +78,14 @@ function injectTouch(
}

function handlePointerDown(e: PointerEvent<HTMLDivElement>) {
    if (!STATE.client) {
        return;
    }

    STATE.rendererContainer!.focus();
    e.preventDefault();
    e.stopPropagation();

    e.currentTarget.setPointerCapture(e.pointerId);
    injectTouch(AndroidMotionEventAction.Down, e);
}
@@ -101,15 +106,24 @@ function handlePointerMove(e: PointerEvent<HTMLDivElement>) {
}

function handlePointerUp(e: PointerEvent<HTMLDivElement>) {
    if (!STATE.client) {
        return;
    }

    e.preventDefault();
    e.stopPropagation();
    injectTouch(AndroidMotionEventAction.Up, e);
}

function handlePointerLeave(e: PointerEvent<HTMLDivElement>) {
    if (!STATE.client) {
        return;
    }

    e.preventDefault();
    e.stopPropagation();
    // Prevent hover state on device from "stuck" at the last position
    // Because pointer capture on pointer down, this event only happens for hovering mouse and pen.
    // Release the injected pointer, otherwise it will stuck at the last position.
    injectTouch(AndroidMotionEventAction.HoverExit, e);
    injectTouch(AndroidMotionEventAction.Up, e);
}
@@ -123,14 +137,23 @@ async function handleKeyEvent(e: KeyboardEvent<HTMLDivElement>) {
        return;
    }

    const { type, key, code } = e;
    e.preventDefault();
    e.stopPropagation();

    const { repeat, type, code } = e;
    if (repeat) {
        return;
    }

    const keyCode = AndroidKeyCode[code as keyof typeof AndroidKeyCode];
    if (keyCode) {
        // Intercept keys like "Tab"
        e.preventDefault();
        e.stopPropagation();
        if (type === "keydown") {
            STATE.pressedKeys.add(keyCode);
        } else {
            STATE.pressedKeys.delete(keyCode);
        }

        // TODO: workaround the missing keyup event on macOS https://crbug.com/1393524
        STATE.client!.controlMessageSerializer!.injectKeyCode({
            action:
                type === "keydown"
@@ -147,6 +170,25 @@ async function handleKeyEvent(e: KeyboardEvent<HTMLDivElement>) {
    }
}

function handleBlur() {
    if (!STATE.client) {
        return;
    }

    // Release all pressed keys on window blur,
    // Because there will not be any keyup events when window is not focused.
    for (const key of STATE.pressedKeys) {
        STATE.client.controlMessageSerializer!.injectKeyCode({
            action: AndroidKeyEventAction.Up,
            keyCode: key,
            metaState: 0,
            repeat: 0,
        });
    }

    STATE.pressedKeys.clear();
}

export function VideoContainer() {
    const classes = useClasses();

@@ -163,8 +205,11 @@ export function VideoContainer() {
            passive: false,
        });

        window.addEventListener("blur", handleBlur);

        return () => {
            container.removeEventListener("wheel", handleWheel);
            window.removeEventListener("blur", handleBlur);
        };
    }, [container]);