mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-11-13 17:42:57 +00:00
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:
parent
4d6b010c19
commit
ecf5751ec9
3 changed files with 21 additions and 2 deletions
|
|
@ -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;
|
||||
|
|
|
|||
16
scripts/fixtures/accept-owned-browser-dialog.py
Normal file
16
scripts/fixtures/accept-owned-browser-dialog.py
Normal 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)
|
||||
|
|
@ -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)])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue