Follow-up to the game keyboard-capture fix (spikersoft-angular PR #61, issues #182/#157/#181/#193). The Minecraft (wasm-voxel) engine leaks all of its global window/document listeners when you leave the game, and most are registered with preventDefault() enabled. The leaked documentmousedown/mouseup/mousemove + contextmenu listeners then preventDefault() those events everywhere, which blocks click-to-focus on inputs (so form fields look completely inert) and disables the right-click menu across the whole app.
Root cause
GameWindow.registerListener(parent, event, listener, preventDefaults = true) wraps the handler in an anonymous function and calls parent.addEventListener(...) but stores no reference, so nothing can ever be removed. Minecraft.stop() (called from wasm-voxel.component.ngOnDestroy) resets renderers but never removes these listeners. Keyboard.create() similarly adds static windowkeydown/keyup listeners (the keyup one calls preventDefault()) that are never removed. block-editor.component adds an anonymous documentkeydown (Escape handler) that is also never removed.
Because registerListener defaults preventDefaults to true, the leaked documentmousedown handler calls event.preventDefault() on every mouse press anywhere — and preventDefault on mousedown suppresses the default focus, so clicking into a text field no longer focuses it. This matches the "fields render but are completely unresponsive / can't even click in" reports (#181 calendar, #193 fundraiser modal) when the user had visited Minecraft earlier in the session.
Proposed fix
GameWindow: track every registered { parent, event, handler } and add removeListeners() that removes them all.
Keyboard: store the keydown/keyup handlers in static fields and add destroy() to remove them (and guard create() against double-registration).
Minecraft.stop(): call this.window.removeListeners() and Keyboard.destroy().
block-editor.component: store the keydown handler and remove it in ngOnDestroy.
Acceptance criteria
After opening Minecraft and navigating away, document no longer has lingering mousedown/mousemove/mouseup/contextmenu/keydown/keyup listeners from the game.
Clicking into and typing in the Calendar event form / Fundraiser modal / sandbox works after a Minecraft session.
Right-click context menu works again after leaving Minecraft.
In-game input still works while Minecraft is open.
## Summary
Follow-up to the game keyboard-capture fix (spikersoft-angular PR #61, issues #182/#157/#181/#193). The Minecraft (`wasm-voxel`) engine leaks **all** of its global `window`/`document` listeners when you leave the game, and most are registered with `preventDefault()` enabled. The leaked `document` `mousedown`/`mouseup`/`mousemove` + `contextmenu` listeners then `preventDefault()` those events everywhere, which blocks click-to-focus on inputs (so form fields look completely inert) and disables the right-click menu across the whole app.
## Root cause
`GameWindow.registerListener(parent, event, listener, preventDefaults = true)` wraps the handler in an anonymous function and calls `parent.addEventListener(...)` but **stores no reference**, so nothing can ever be removed. `Minecraft.stop()` (called from `wasm-voxel.component.ngOnDestroy`) resets renderers but never removes these listeners. `Keyboard.create()` similarly adds static `window` `keydown`/`keyup` listeners (the `keyup` one calls `preventDefault()`) that are never removed. `block-editor.component` adds an anonymous `document` `keydown` (Escape handler) that is also never removed.
Because `registerListener` defaults `preventDefaults` to `true`, the leaked `document` `mousedown` handler calls `event.preventDefault()` on every mouse press anywhere — and `preventDefault` on `mousedown` suppresses the default focus, so clicking into a text field no longer focuses it. This matches the "fields render but are completely unresponsive / can't even click in" reports (#181 calendar, #193 fundraiser modal) when the user had visited Minecraft earlier in the session.
## Proposed fix
1. `GameWindow`: track every registered `{ parent, event, handler }` and add `removeListeners()` that removes them all.
2. `Keyboard`: store the keydown/keyup handlers in static fields and add `destroy()` to remove them (and guard `create()` against double-registration).
3. `Minecraft.stop()`: call `this.window.removeListeners()` and `Keyboard.destroy()`.
4. `block-editor.component`: store the keydown handler and remove it in `ngOnDestroy`.
## Acceptance criteria
- [ ] After opening Minecraft and navigating away, `document` no longer has lingering `mousedown`/`mousemove`/`mouseup`/`contextmenu`/`keydown`/`keyup` listeners from the game.
- [ ] Clicking into and typing in the Calendar event form / Fundraiser modal / sandbox works after a Minecraft session.
- [ ] Right-click context menu works again after leaving Minecraft.
- [ ] In-game input still works while Minecraft is open.
Resolved in spikersoft-angular PR #62 (merged to master). GameWindow now tracks and removes every global window/document listener it registers (removeListeners()), Keyboard.destroy() removes its keydown/keyup handlers (and create() guards against double-registration), Minecraft.stop() calls both, and block-editor removes its keydown listener in ngOnDestroy. This eliminates the leaked global mousedown/mouseup/mousemove/contextmenu/keyup handlers that previously preventDefault()-ed input across the whole app after leaving Minecraft. Closing.
Resolved in spikersoft-angular PR #62 (merged to `master`). `GameWindow` now tracks and removes every global window/document listener it registers (`removeListeners()`), `Keyboard.destroy()` removes its keydown/keyup handlers (and `create()` guards against double-registration), `Minecraft.stop()` calls both, and `block-editor` removes its keydown listener in `ngOnDestroy`. This eliminates the leaked global `mousedown`/`mouseup`/`mousemove`/`contextmenu`/`keyup` handlers that previously `preventDefault()`-ed input across the whole app after leaving Minecraft. Closing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Follow-up to the game keyboard-capture fix (spikersoft-angular PR #61, issues #182/#157/#181/#193). The Minecraft (
wasm-voxel) engine leaks all of its globalwindow/documentlisteners when you leave the game, and most are registered withpreventDefault()enabled. The leakeddocumentmousedown/mouseup/mousemove+contextmenulisteners thenpreventDefault()those events everywhere, which blocks click-to-focus on inputs (so form fields look completely inert) and disables the right-click menu across the whole app.Root cause
GameWindow.registerListener(parent, event, listener, preventDefaults = true)wraps the handler in an anonymous function and callsparent.addEventListener(...)but stores no reference, so nothing can ever be removed.Minecraft.stop()(called fromwasm-voxel.component.ngOnDestroy) resets renderers but never removes these listeners.Keyboard.create()similarly adds staticwindowkeydown/keyuplisteners (thekeyupone callspreventDefault()) that are never removed.block-editor.componentadds an anonymousdocumentkeydown(Escape handler) that is also never removed.Because
registerListenerdefaultspreventDefaultstotrue, the leakeddocumentmousedownhandler callsevent.preventDefault()on every mouse press anywhere — andpreventDefaultonmousedownsuppresses the default focus, so clicking into a text field no longer focuses it. This matches the "fields render but are completely unresponsive / can't even click in" reports (#181 calendar, #193 fundraiser modal) when the user had visited Minecraft earlier in the session.Proposed fix
GameWindow: track every registered{ parent, event, handler }and addremoveListeners()that removes them all.Keyboard: store the keydown/keyup handlers in static fields and adddestroy()to remove them (and guardcreate()against double-registration).Minecraft.stop(): callthis.window.removeListeners()andKeyboard.destroy().block-editor.component: store the keydown handler and remove it inngOnDestroy.Acceptance criteria
documentno longer has lingeringmousedown/mousemove/mouseup/contextmenu/keydown/keyuplisteners from the game.Resolved in spikersoft-angular PR #62 (merged to
master).GameWindownow tracks and removes every global window/document listener it registers (removeListeners()),Keyboard.destroy()removes its keydown/keyup handlers (andcreate()guards against double-registration),Minecraft.stop()calls both, andblock-editorremoves its keydown listener inngOnDestroy. This eliminates the leaked globalmousedown/mouseup/mousemove/contextmenu/keyuphandlers that previouslypreventDefault()-ed input across the whole app after leaving Minecraft. Closing.