Skip to content

Add system key events (media, volume, brightness) to hs.eventtap - #281

Open
cmsj wants to merge 2 commits into
mainfrom
eventtap-system-keys
Open

cmsj wants to merge 2 commits into
mainfrom
eventtap-system-keys

Conversation

@cmsj

@cmsj cmsj commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Fixes #268.

v2 had no equivalent of v1's hs.eventtap.event.newSystemKeyEvent(), so there was no way to post media keys. Only real media key events go through macOS's Now Playing routing, so hs.audiodevice or AppleScript workarounds don't cover play/next/previous (e.g. audio in a browser tab).

What's new

  • hs.eventtap.makeSystemKeyEvent(key, isDown) returns an ordinary HSEventTapEvent, so .post()/.duplicate() work unchanged
  • hs.eventtap.systemKeyStroke(key) presses and releases a key (5 ms between, like keyStroke)
  • hs.eventtap.systemKeys lists the 22 v1 key names (PLAY, NEXT, SOUND_UP, BRIGHTNESS_UP, …) and their NX_KEYTYPE_* codes. Names are matched case-insensitively.
  • hs.eventtap.eventTypes.systemDefined and event.systemKey ({key, keyCode, isDown, isRepeat}, or undefined for other events) let watchers recognise these keys

v1's down/repeat fields became isDown/isRepeat to match v2 style; the migration guide covers this. The docs warn about POWER/EJECT, and that synthetic brightness keys don't work on some Macs or external displays.

Testing

  • 130 HSEventTapTests pass in a VM. The new tests check every key name, pressed and released, by building an event and decoding it again; they never post one.
  • End to end in a VM: two systemKeyStroke("SOUND_UP") calls raised the output volume from 50 to 63, and a systemDefined watcher decoded all four down/up events.
  • npm run docs:generate and docs:test pass.

🤖 Generated with Claude Code

v2 had no equivalent of v1's hs.eventtap.event.newSystemKeyEvent(), so
media keys couldn't be posted, and only real media key events go through
macOS's Now Playing routing.

Add makeSystemKeyEvent() and systemKeyStroke() using v1's key names, a
systemKeys table, eventTypes.systemDefined, and an event.systemKey
property so watchers can recognise these keys too.

Fixes #268

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with the previous testing concern addressed.

Summary

Adds system-key support to hs.eventtap.

  • Scripts can build and send named system-key events.
  • Watchers can read which system key was pressed or released.

Since the last review, only tests changed. The new fixtures address the previous request for repeat, unknown-code, and other-subtype coverage. No new actionable issues were found.

Reviews (2) · Last reviewed commit: "Test the system key decoder against hand..." · Reviewed by Greptile

The existing tests only decoded events made by makeSystemKeyEvent(), so
repeats, unknown key codes and other systemDefined subtypes went
untested, and a mistake shared by the builder and decoder would pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cmsj

cmsj commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@greptile

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hs.eventtap: no way to post system/media key events (play, next, volume, brightness)

1 participant