diff --git a/ui/src/components/WebRTCVideo.tsx b/ui/src/components/WebRTCVideo.tsx index c3c22f4..fff858f 100644 --- a/ui/src/components/WebRTCVideo.tsx +++ b/ui/src/components/WebRTCVideo.tsx @@ -67,6 +67,8 @@ export default function WebRTCVideo() { const hdmiError = ["no_lock", "no_signal", "out_of_range"].includes(hdmiState); const isVideoLoading = !isPlaying; + const [blockWheelEvent, setBlockWheelEvent] = useState(false); + // Misc states and hooks const disableVideoFocusTrap = useUiStore(state => state.disableVideoFocusTrap); const [send] = useJsonRpc(); @@ -281,6 +283,11 @@ export default function WebRTCVideo() { const mouseWheelHandler = useCallback( (e: WheelEvent) => { + + if (settings.scrollThrottling && blockWheelEvent) { + return; + } + // Determine if the wheel event is an accel scroll value const isAccel = Math.abs(e.deltaY) >= 100; @@ -300,8 +307,14 @@ export default function WebRTCVideo() { const invertedScrollValue = -clampedScrollValue; send("wheelReport", { wheelY: invertedScrollValue }); + + // Apply blocking delay based of throttling settings + if (settings.scrollThrottling && !blockWheelEvent) { + setBlockWheelEvent(true); + setTimeout(() => setBlockWheelEvent(false), settings.scrollThrottling); + } }, - [send], + [send, blockWheelEvent, settings], ); const resetMousePosition = useCallback(() => { diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index 43b9273..9475316 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -314,6 +314,9 @@ interface SettingsState { keyboardLedSync: KeyboardLedSync; setKeyboardLedSync: (sync: KeyboardLedSync) => void; + scrollThrottling: number; + setScrollThrottling: (value: number) => void; + showPressedKeys: boolean; setShowPressedKeys: (show: boolean) => void; } @@ -354,6 +357,9 @@ export const useSettingsStore = create( keyboardLedSync: "auto", setKeyboardLedSync: sync => set({ keyboardLedSync: sync }), + scrollThrottling: 0, + setScrollThrottling: value => set({ scrollThrottling: value }), + showPressedKeys: true, setShowPressedKeys: show => set({ showPressedKeys: show }), }), diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx index 0c710ce..0fecef0 100644 --- a/ui/src/routes/devices.$id.settings.mouse.tsx +++ b/ui/src/routes/devices.$id.settings.mouse.tsx @@ -14,6 +14,7 @@ import { useFeatureFlag } from "../hooks/useFeatureFlag"; import { cx } from "../cva.config"; import { SettingsItem } from "./devices.$id.settings"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; export default function SettingsMouseRoute() { const hideCursor = useSettingsStore(state => state.isCursorHidden); @@ -26,6 +27,19 @@ export default function SettingsMouseRoute() { const [jiggler, setJiggler] = useState(false); + const scrollThrottling = useSettingsStore(state => state.scrollThrottling); + const setScrollThrottling = useSettingsStore( + state => state.setScrollThrottling, + ); + + const scrollThrottlingOptions = [ + { value: "0", label: "Off" }, + { value: "10", label: "Low" }, + { value: "25", label: "Medium" }, + { value: "50", label: "High" }, + { value: "100", label: "Very High" }, + ]; + const [send] = useJsonRpc(); useEffect(() => { @@ -65,6 +79,21 @@ export default function SettingsMouseRoute() { /> + + setScrollThrottling(parseInt(e.target.value))} + options={scrollThrottlingOptions} + /> + +