Skip to content

fix: moonwalking on a mac (and every other key the modifiers broke) - #42

Merged
benjackwhite merged 1 commit into
PostHog:mainfrom
Colin-Moran:fix/mac-modifier-controls
Sep 10, 2026
Merged

benjackwhite merged 1 commit into
PostHog:mainfrom
Colin-Moran:fix/mac-modifier-controls

Conversation

@Colin-Moran

Copy link
Copy Markdown
Contributor

the hedgehog has been telling mac users to hold alt for the better part of a
year. mac users do not have an alt. worse, the key that is there rewrites
every other key you press, which the controls were not ready for at all.

what was broken

controls.ts mapped keys off event.key, which is what a keypress produces
rather than which key you pressed. hold a modifier and the browser rewrites it:
macOS turns ⌥+a into "å", and every platform turns shift+a into "A". neither
of those is in the map, so:

what you do what happened
⌥ + A to moonwalk on a mac nothing. the flagship feature, dead on arrival
shift + D to run with WASD nothing (arrows worked, so nobody noticed)
walk, then grab ⌥ or shift, then let go the keyup arrives as "å"/"A", never matches the keydown, and the key is never released. the hog walks off and never comes back
ctrl+d to open the debug renderer we claimed it too, so he sprints right while you debug
⌘+D, then anything macOS swallows the keyup while ⌘ is held. see above. he's gone

what changed

resolve from event.code instead. that's the physical key, so KeyA stays
KeyA no matter what's held down with it, with an event.key fallback for the
mobile keyboards that don't report a code. then:

  • release everything on blur, because browsers don't send keyup for keys
    that were down when the window lost focus. alt-tab mid-stride no longer
    sentences him to walk forever.
  • leave ⌘/ctrl chords to the browser, which is where they belong.
  • call it ⌥ option on apple devices, alt everywhere else.
  • write the controls down: a table in the README, and a line in the in-game
    cheat sheet (cheatcodes), where they had never been documented at all.

while i was in there: HedgehogActorControls built a teardown function and then
threw it away, so every hedgehog leaked two window listeners for the life of the
page. it now has a destroy() and beforeUnload calls it. konami code spawns
10,000 hedgehogs, which was 20,000 listeners, which is a lot of retention.

how it was tested

unit tests on the resolver (keyboard.test.ts, platform.test.ts) covering the
⌥/shift rewrites, the no-code fallback, and the label.

then, because "trust me, it walks now" is exactly the kind of pr description
this hedgehog makes fun of, i measured it. built main and this branch, and
read the player hog's real walkSpeed out of the running game for each case:

scenario before after
release a while ⌥ held -2, still walking 0
release a while shift held -2, still walking 0
⌥ + a (moonwalk) 0, nothing -1.6, facing right
shift + a (run) 0, nothing -4
ctrl+d +2, off he goes 0
blur mid-walk -2, still walking 0
arrow keys -2 / 0 -2 / 0, unchanged

pnpm test, pnpm lint and pnpm build (engine, playground, extension
typecheck) all pass. also loaded the unpacked extension and confirmed the fix
ships in content.js. the extension is where this bit hardest, since ⌘+L and
⌘+Tab are keys you actually press on a real website.

not fixed here

the hogwars title screen still tells you to hold ALT to moonwalk. that branch
is a museum piece and i'm not touching it, but it does suggest the assumption
runs deeper than one file.

nothing else changed. arrows, space, drop-through, fire and web-climbing all
behave exactly as before. he's just no longer at the mercy of whichever modifier
you happened to be resting a finger on.

@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

@Colin-Moran is attempting to deploy a commit to the PostHog Team on Vercel.

A member of the Team first needs to authorize it.

@benjackwhite benjackwhite left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a solid fix and great PR - thanks!

@vercel

vercel Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hedgehog-mode Ready Ready Preview Sep 10, 2026 8:34am UTC

Request Review

The controls were keyed off `event.key`, which is what a keypress
produces rather than which key was pressed, and every modifier rewrites
it. macOS turns option+a into "å" and every platform turns shift+a into
"A", so:

- moonwalking (option) never worked with WASD on a mac at all
- running (shift) never worked with WASD anywhere
- pressing a movement key and then grabbing a modifier stranded the key,
  because the keyup arrived under a different name than the keydown and
  never released it. The hog just kept walking.
- cmd/ctrl combos were claimed too, so ctrl+d (the debug renderer) also
  sent him running right, and macOS swallows the keyup while cmd is
  held, so he never stopped.

Resolve from `event.code` instead, which is the physical key and immune
to modifier rewriting, keeping an `event.key` fallback for the mobile
keyboards that report no code. Also release every held key on blur
(browsers don't deliver keyup for keys held when focus is lost) and
leave cmd/ctrl chords to the browser.

While in here, HedgehogActorControls now actually detaches its
listeners. It built a teardown function and threw it away, so every
hedgehog leaked two window listeners for the lifetime of the page.

Labels the moonwalk key "option" on Apple devices, since "alt" is a key
mac users don't have, and documents the controls in the README and the
in-game cheat sheet, where they weren't written down anywhere.
@benjackwhite
benjackwhite force-pushed the fix/mac-modifier-controls branch from 913cad7 to eab85f9 Compare September 10, 2026 08:31
@benjackwhite
benjackwhite merged commit 0212e2f into PostHog:main Sep 10, 2026
9 of 10 checks passed

This branch was successfully deployed

1 active deployment
Preview – hedgehog-mode — eab85f9a Deployed Sep 10, 2026 by vercel[bot]
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.

2 participants