fix: keep Cua foreground actions on the target window

This commit is contained in:
chenmingxuan committed 2026-10-18 21:02:49 +08:00
1 parent 889a951c9b
commit 6de0b1b276
13 files changed
+327 -31

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
package main
import (
"errors"
"reflect"
"testing"
)
func TestForegroundActivatesBeforeInputAndDoesNotRestore(t *testing.T) {
var calls []string
foreground := int64(10) // The user's foreground app, e.g. Codex.
call := func(name string, args obj) (obj, error) {
calls = append(calls, name)
if name == "bring_to_front" {
if len(args) != 2 || num(args["window_id"]) != 20 {
t.Fatal("activation changed the target or forwarded input arguments")
}
foreground = 20
return obj{"structuredContent": obj{"landed_on_target": true}}, nil
}
// Simulate upstream's activate/act/restore: it now saves the target,
// not the user's previous app, as its restore destination.
previous := foreground
foreground = 20
foreground = previous
return obj{"structuredContent": obj{"effect": "unverifiable"}}, nil
}
r, err := callWithForeground(call, "press_key", obj{"pid": 2, "window_id": 20, "key": "t", "delivery_mode": "foreground"}, func() int64 { return foreground })
if err != nil || r["isError"] == true || foreground != 20 || !reflect.DeepEqual(calls, []string{"bring_to_front", "press_key"}) {
t.Fatalf("foreground handoff failed: %v %v %v %v", calls, foreground, r, err)
}
}
func TestUnconfirmedActivationNeverSendsInput(t *testing.T) {
for _, mode := range []string{"refused", "raised_only", "lost_focus", "transport"} {
t.Run(mode, func(t *testing.T) {
calls := 0
r, err := callWithForeground(func(name string, _ obj) (obj, error) {
calls++
if name != "bring_to_front" {
t.Fatal("input sent without focus")
}
if mode == "transport" {
return nil, errors.New("disconnected")
}
return obj{"isError": mode == "refused", "structuredContent": obj{"raised": true, "landed_on_target": mode != "raised_only"}}, nil
}, "click", obj{"pid": 2, "window_id": 20, "delivery_mode": "foreground"}, func() int64 {
if mode == "lost_focus" {
return 10
}
return 20
})
rec := object(object(r["structuredContent"])["artemis"])
if err != nil || calls != 1 || r["isError"] != true || rec["execution"] != "not_started" || rec["retryable"] != false {
t.Fatalf("unsafe activation handling: %v %v", r, err)
}
})
}
}
func TestBackgroundAndObservationsNeverActivate(t *testing.T) {
for _, name := range []string{"get_window_state", "verify_state", "save_screenshot", "click"} {
var calls []string
_, err := callWithForeground(func(tool string, _ obj) (obj, error) {
calls = append(calls, tool)
return obj{}, nil
}, name, obj{"pid": 2, "window_id": 20}, func() int64 { t.Fatal("unexpected focus probe"); return 0 })
if err != nil || !reflect.DeepEqual(calls, []string{name}) {
t.Fatal(calls, err)
}
}
}
func TestUncertainInputIsNotReplayed(t *testing.T) {
calls := 0
_, err := callWithForeground(func(name string, _ obj) (obj, error) {
calls++
if name == "bring_to_front" {
return obj{"structuredContent": obj{"landed_on_target": true}}, nil
}
return nil, errors.New("input reply lost")
}, "type_text", obj{"pid": 2, "window_id": 20, "delivery_mode": "foreground"}, func() int64 { return 20 })
if calls != 2 || err == nil {
t.Fatal(calls, err)
}
}
func TestCaptureRecordsFocusWithoutHidingBackgroundEvidence(t *testing.T) {
r := obj{"content": []any{obj{"type": "image", "data": "original"}}}
annotateCaptureFocus(r, 20, 20, 10)
s := object(object(r["structuredContent"])["capture_focus"])
if s["changed_during_capture"] != true || s["target_foreground_after"] != false || len(items(r["content"])) != 2 || object(items(r["content"])[0])["data"] != "original" {
t.Fatal(r)
}
}