fix(browser): preserve Cocoa wheel coordinates in app windows

Convert the constructed CG wheel event's Y coordinate so eventWithCGEvent yields the window-local Cocoa location expected by direct WKWebView dispatch. The real application qualification catches the mismatch by scrolling a nested region, rather than only the page.

Keep private-daemon bridge discovery aligned with the desktop's registry when HOME is isolated, and accept only the owned macOS native dialog through process-targeted Return events. Complete real agent browser actions and preview capability smoke now pass on the macOS application.
This commit is contained in:
Pascal André 2026-11-08 03:40:14 +01:00
parent 4d6b010c19
commit ecf5751ec9
No known key found for this signature in database
3 changed files with 21 additions and 2 deletions

View file

@ -234,7 +234,9 @@ int cn_wheel(void *opaque, double x, double y, double dx, double dy, unsigned fl
CGEventRef cg = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, (int32_t)(-dy*view.pageZoom), (int32_t)(-dx*view.pageZoom));
if (!cg) return 0;
CGEventSetFlags(cg, (CGEventFlags)modifiers(flags));
CGEventSetLocation(cg, point);
// Direct view dispatch consumes window-local Cocoa coordinates. The CGEvent
// constructor flips Y when producing locationInWindow, even with no window.
CGEventSetLocation(cg, CGPointMake(point.x, NSMaxY(NSScreen.screens.firstObject.frame) - point.y));
[view scrollWheel:[NSEvent eventWithCGEvent:cg]];
CFRelease(cg);
return 1;

View file

@ -0,0 +1,16 @@
"""Send Return to the qualification app's native dialog, never another process."""
import ctypes as c
import sys
cg = c.CDLL('/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics')
cf = c.CDLL('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation')
cg.CGEventCreateKeyboardEvent.restype = c.c_void_p
cg.CGEventCreateKeyboardEvent.argtypes = [c.c_void_p, c.c_ushort, c.c_bool]
cg.CGEventPostToPid.argtypes = [c.c_int, c.c_void_p]
cf.CFRelease.argtypes = [c.c_void_p]
for down in [True, False]:
event = cg.CGEventCreateKeyboardEvent(None, 36, down)
if not event:
raise RuntimeError('Cannot create native Return event')
cg.CGEventPostToPid(int(sys.argv[1]), event)
cf.CFRelease(event)

View file

@ -46,6 +46,7 @@ await Promise.all([fixture, provider].map(server => new Promise(done => server.l
const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => !/^(OPENCODE_|CODENOMAD_)/.test(key)))
for (const key of ["XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_STATE_HOME", "XDG_CACHE_HOME"]) env[key] = path.join(root, key)
Object.assign(env, { HOME: root, USERPROFILE: root, OPENCODE_TEST_HOME: root,
XDG_RUNTIME_DIR: process.env.XDG_RUNTIME_DIR || path.join(os.homedir(), ".config"),
OPENCODE_CONFIG_DIR: path.join(root, "config"), OPENCODE_DB: path.join(root, "fixture.db"), OPENCODE_SERVER_PASSWORD: password,
OPENCODE_CONFIG_PROJECT_DISABLE: "1", OPENCODE_DISABLE_MODELS_FETCH: "1", OPENCODE_DISABLE_FFF: "1" })
await mkdir(env.OPENCODE_CONFIG_DIR, { recursive: true })
@ -131,7 +132,7 @@ try {
assert.equal(await readFile(path.join(downloads, download), "utf8"), `native-download-${run}`)
await call({ action: "click", ref: ref("Native dialog") })
await delay(1500)
if (process.platform === "darwin") execFileSync("osascript", ["-e", `tell application "System Events" to tell (first process whose unix id is ${app.pid}) to set frontmost to true`, "-e", 'tell application "System Events" to key code 36'])
if (process.platform === "darwin") execFileSync("python3", [new URL("fixtures/accept-owned-browser-dialog.py", import.meta.url).pathname, String(app.pid)])
else if (process.platform === "linux") {
const windows = execFileSync("xdotool", ["search", "--onlyvisible", "--pid", String(app.pid)], { encoding: "utf8" }).trim().split("\n")
execFileSync("xdotool", ["windowactivate", "--sync", windows.at(-1)])