3

What is the JXA equivalent of

--AppleScript
    tell application ("System Events")
        click at(x,y)
    end tell
1
Application("System Events")
  .applicationProcesses.whose({frontmost: true}).at(0)
  .click({ at: [x, y] })

click is performed on a UIElement, so we get one, then call click with that.

1

In JXA, it appears that the click() function must be sent to a specific UI element (which can be an application process), while this isn't the case in AppleScript.

(()=>{
    return clickAt('Safari', [60, 44]);
})();


// {x, y} relative to screen's top-left
function clickAt(appName, [x, y]) {
    const sys = Application('System Events');
    const proc = sys.processes[appName];
    if (!proc.exists()) return -1;

    return proc.click({ at: [x, y] });
}

As you are probably aware, this System Events command is a simulated click, that merely detects a UI element at the specified coordinates belonging to the specified process (regardless of window obscuration, i.e. applications at the rear, out-of-sight, will respond to the command), and if that element recognises a click action (typically if its actions contain one named AXPress), then the action is triggered. Thus, it is not an actual mouse click event processed by the system.

But, given that you're working in JXA, you can optionally benefit from its extended Objective-C bridging:

(()=>{
    mouseclick();       // Clicks at mouse location
    mouseclick(35, 60); // Clicks at coordinates {35, 60}
                        // relative to top-left of screen
})();


function mouseclick(x = null, y = null) {
    ObjC.import('Cocoa');
    const nil = $();

    const mouseLoc = $.NSEvent.mouseLocation;
    const screenH = $.NSScreen.mainScreen.frame.size.height;
    mouseLoc.y = screenH - mouseLoc.y;
    var coords = mouseLoc;

    if (x && y) coords = {x: x, y: y};

    var mousedownevent = $.CGEventCreateMouseEvent(nil, 
                                $.kCGEventLeftMouseDown,
                                coords,
                                nil);

    var mouseupevent = $.CGEventCreateMouseEvent(nil, 
                            $.kCGEventLeftMouseUp,
                            coords,
                            nil);

    $.CGEventPost($.kCGHIDEventTap, mousedownevent);
    $.CGEventPost($.kCGHIDEventTap, mouseupevent);
    $.CFRelease(mousedownevent);
    $.CFRelease(mouseupevent);
}

This mouseclick() function sends an actual event to be processed as if it had been generated by physically clicking the mouse. Thus, as you'd expect, a mouse click won't penetrate through to obscured rear application windows; it acts upon what you see upon a 2D pixel landscape.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .