Loading apps/demo/src/components/device-view.tsx +7 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { makeStyles } from "@griffel/react"; import { CSSProperties, ComponentType, HTMLAttributes, ReactNode, useImperativeHandle, useMemo, Loading @@ -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; Loading Loading @@ -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>({ Loading Loading @@ -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 Loading apps/demo/src/components/scrcpy/navigation-bar.tsx +7 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading apps/demo/src/components/scrcpy/state.tsx +4 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import { ADB_SYNC_MAX_PACKET_SIZE } from "@yume-chan/adb"; import { AdbScrcpyClient, AdbScrcpyOptions1_22, AndroidKeyCode, AndroidScreenPowerMode, CodecOptions, DEFAULT_SERVER_PATH, Loading Loading @@ -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(); Loading Loading @@ -333,7 +335,6 @@ export class ScrcpyPageState { ); } runInAction(() => { this.client = client; this.hoverHelper = new ScrcpyHoverHelper(); Loading Loading @@ -364,6 +365,8 @@ export class ScrcpyPageState { RECORD_STATE.recording = false; } this.pressedKeys.clear(); this.fps = "0"; clearTimeout(this.fpsCounterIntervalId); Loading apps/demo/src/components/scrcpy/video-container.tsx +50 −5 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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); } Loading @@ -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" Loading @@ -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(); Loading @@ -163,8 +205,11 @@ export function VideoContainer() { passive: false, }); window.addEventListener("blur", handleBlur); return () => { container.removeEventListener("wheel", handleWheel); window.removeEventListener("blur", handleBlur); }; }, [container]); Loading Loading
apps/demo/src/components/device-view.tsx +7 −3 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ import { makeStyles } from "@griffel/react"; import { CSSProperties, ComponentType, HTMLAttributes, ReactNode, useImperativeHandle, useMemo, Loading @@ -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; Loading Loading @@ -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>({ Loading Loading @@ -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 Loading
apps/demo/src/components/scrcpy/navigation-bar.tsx +7 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading
apps/demo/src/components/scrcpy/state.tsx +4 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import { ADB_SYNC_MAX_PACKET_SIZE } from "@yume-chan/adb"; import { AdbScrcpyClient, AdbScrcpyOptions1_22, AndroidKeyCode, AndroidScreenPowerMode, CodecOptions, DEFAULT_SERVER_PATH, Loading Loading @@ -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(); Loading Loading @@ -333,7 +335,6 @@ export class ScrcpyPageState { ); } runInAction(() => { this.client = client; this.hoverHelper = new ScrcpyHoverHelper(); Loading Loading @@ -364,6 +365,8 @@ export class ScrcpyPageState { RECORD_STATE.recording = false; } this.pressedKeys.clear(); this.fps = "0"; clearTimeout(this.fpsCounterIntervalId); Loading
apps/demo/src/components/scrcpy/video-container.tsx +50 −5 Original line number Diff line number Diff line Loading @@ -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); } Loading @@ -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); } Loading @@ -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" Loading @@ -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(); Loading @@ -163,8 +205,11 @@ export function VideoContainer() { passive: false, }); window.addEventListener("blur", handleBlur); return () => { container.removeEventListener("wheel", handleWheel); window.removeEventListener("blur", handleBlur); }; }, [container]); Loading