macotron.event
Send clicks, key presses, typed text, and scrolls as if they came from the hardware, and watch keyboard, mouse, and trackpad input from every app. A tap can also swallow an event so that no app sees it.
// Option-Tab opens a window switcher instead of reaching the app.
const TAB = 48;
macotron.event.tap(["keyDown", "keyUp"], (e) => {
if (e.keyCode === TAB && e.flags.includes("opt")) {
if (e.type === "keyDown") showSwitcher();
return false;
}
});
Posting events
post(event): boolean
Posts one event to the system, which sends it to the app under the pointer or the app with keyboard focus. Returns false for an unknown type, a key name that does not parse, or an empty string. Events you post are marked, so your own tap() listeners never see them.
| type | Fields | What it does |
|---|---|---|
"click" | button?: "left" (default), "right", or "middle". x?, y? | A press and a release at that point. |
"key" | key: a key name from the combo list. flags?: any of "cmd", "shift", "ctrl", "opt", "fn", "caps" | A key down and a key up, with those modifiers held. key can also be a whole combo such as "cmd+v"; flags, when given, replaces its modifiers. |
"unicode" | string | Types the string as one key press, whatever the keyboard layout. Use it for emoji and accented letters. |
"scroll" | dy?, dx?, pixel? | One scroll. dy is vertical and dx is horizontal, in lines, or in pixels when pixel is true. Values are rounded to whole numbers. |
Click coordinates are global screen points with the origin at the top-left of the main display and y going down. That is the same space as macotron.window frames, and not the space of macotron.mouse.
Without x and y, the click lands where the pointer is.
// Paste after the launcher closes and focus returns to the app.
setTimeout(() => macotron.event.post({ type: "unicode", string: "🎉" }), 150);
macotron.event.post({ type: "key", key: "v", flags: ["cmd"] });
Posting events needs Accessibility permission. Declare permissions: ["accessibility"] in macotron.plugin().
Watching input
tap(types: string | string[], callback: (e) => boolean | void): void
Calls callback for each matching event from any app. Return false to swallow the event. Any other return value lets it through. Unknown type names are ignored, and if no name is valid the call does nothing. Taps last until plugins reload; there is no way to remove one sooner.
| Type names | Can swallow |
|---|---|
keyDown, keyUp, flagsChanged (a modifier key goes down or up) | Yes |
leftMouseDown, leftMouseUp, rightMouseDown, rightMouseUp, mouseMoved, leftMouseDragged | Yes |
scroll (or scrollWheel) | Yes |
swipe, magnify, rotate (trackpad gestures) | No. The return value is ignored |
The callback receives one object:
| Field | Present for | Meaning |
|---|---|---|
type | All | The type name. Scroll events report "scroll". |
flags | All | Modifiers held: any of "cmd", "shift", "ctrl", "opt", "fn", "caps". |
x, y | Keyboard, mouse, scroll | Pointer position, with the origin at the top-left of the main display. |
keyCode | keyDown, keyUp | The macOS virtual key code, for example 48 for Tab. |
dx, dy | scroll | Scroll amount in lines. |
button, down | Left and right mouse down and up | "left" or "right", and whether this is the press. |
fingers | Gestures | The number of fingers. |
direction | swipe | "left", "right", "up", or "down". |
delta | magnify, rotate | The zoom amount, or the rotation in degrees. |
macotron.event.tap("swipe", (e) => {
if (e.fingers !== 3) return;
const win = macotron.window.focused();
if (!win) return;
const x = e.direction === "left" ? 0 : 0.5;
macotron.window.moveToFraction(win.id, { x, y: 0, w: 0.5, h: 1 });
});
Every key press and click on the Mac waits for your callback, so keep it short. A tap callback has 250 ms before Macotron interrupts it, and an interrupted callback lets the event through. Do slow work in a setTimeout.
Taps need Accessibility and Input Monitoring permission. Declare permissions: ["accessibility", "inputMonitoring"] in macotron.plugin().
See also
- macotron.keyboard for hotkeys and the Hyper key.
- macotron.mouse to read and move the pointer.
- The
window-switcher.jsandgestures.jsexample plugins.