pub unsafe fn send_mouse(
window: *mut c_void,
kind: u64,
x: f64,
y: f64,
clicks: i64,
)Expand description
Hand a synthetic mouse event straight to window, bypassing the
application’s event queue.
post_mouse enqueues on NSApp and needs the run loop to dequeue it;
sendEvent: is the method NSApp would itself call once it had, so the
event arrives without waiting on the queue.
This is not a way around needing focus, and neither is anything else. With
the process inactive and its window on screen but not key — measured, the
window was isVisible: true and occlusion-visible on a real screen — a
click was delivered by none of: this, NSApp sendEvent:, NSApp postEvent:, mouseDown: at the hit-tested view, or any of those with
acceptsFirstMouse: installed on the hosting view’s class at run time.
Nor by changing what the window is: an NSPanel, and a
nonactivatingPanel — which becomes key without activating its
application, and is the obvious thing to reach for here — both stayed
non-key and delivered nothing, with and without a makeKeyWindow or an
activate.
What decides it is CGSSessionScreenIsLocked. A locked login session has no
active application and cannot be given one, so every route above is closed
at the same place; unlock it and all of them work. That is the point of the
lock rather than a gap, so code here should ask whether the session is
locked and say so, not try to route around it.
Below AppKit is worse, not better: Quartz Event Services
(CGEventPostToPid, CGEventPost) is gated on the Accessibility
permission, and an unbundled binary reports AXIsProcessTrusted() == false,
so both of those deliver nothing even when the application is frontmost.
See examples/activation_probe.rs, which measures each route side by side.
§Safety
window must be a live NSWindow.