Skip to content

fix: correct keyUp handler for plugin actions - #53

Merged
tech-stack-studios merged 4 commits into
developfrom
bug/fix-plugin-keyup-handler
May 27, 2026
Merged

fix: correct keyUp handler for plugin actions#53
tech-stack-studios merged 4 commits into
developfrom
bug/fix-plugin-keyup-handler

Conversation

@tech-stack-studios

Copy link
Copy Markdown
Owner

Problem

The keyUp handler for plugin button dispatches read from config (the full button object) instead of config.action (the action sub-object). Since config.type is always undefined, the guard condition was never true — keyUp was never sent to any plugin process.

For Push-to-Talk and Push-to-Mute actions this meant the key was held down indefinitely after pressing the Stream Deck button.

Root cause

buttonConfigsRef.current[index] returns { title, iconDataUrl, bgColor, action: { type, pluginUUID, hotkey, ... } }.
The code incorrectly accessed config.type, config.pluginUUID, and spread { ...config } instead of the action-level equivalents.

The correct pattern was already present 10 lines above in the keyDown handler.

Fix

Four references corrected:

Before After
config?.type?.includes('.') config?.action?.type?.includes('.')
actionUUID: config.type actionUUID: config.action.type
pluginUUID: config.pluginUUID pluginUUID: config.action.pluginUUID
{ ...config } { ...config.action }

Tests

All 115 existing tests pass (npx vitest run).

config is the full button object { title, iconDataUrl, bgColor, action: {...} }.
The action type/pluginUUID/hotkey live at config.action, not at config root.

- config?.type?.includes('.')   → config?.action?.type?.includes('.')
- config.type in context        → config.action.type
- config.pluginUUID in context  → config.action.pluginUUID
- { ...config } as settings     → { ...config.action }

Impact: Push-to-Talk and Push-to-Mute keys were never released because the
condition was always false (config.type === undefined). The key got stuck
held down. Toggle-based actions (Mute, Deafen, Video, etc.) were unaffected
since they only need keyDown.
The electron-builder 'files' array only packaged dist/, electron/, and
package.json. public/bridge/sdpi-bridge.js was never copied into the
app bundle.

In the packaged app (app.isPackaged === true), main.cjs looks for the
bridge at process.resourcesPath/bridge/sdpi-bridge.js. Since the file
was absent, net.fetch() returned ERR_FILE_NOT_FOUND, sdpi-bridge.js
failed to load, and window.sdpi was undefined in the inspector iframe —
causing 'ReferenceError: sdpi is not defined' when clicking Save.

Fix: add extraResources entry so electron-builder copies the bridge into
resources/bridge/sdpi-bridge.js during packaging.
xdotool key without --window sends events to the currently focused
window. When a physical Stream Deck button is pressed, the Electron
app or another window may be focused, so Discord never receives the
synthetic key event.

Add getDiscordWindowId() which searches by window class 'discord'
(with title fallback) and passes --window <id> to all xdotool calls.
Also add --clearmodifiers to prevent stale modifier state from
interfering with the key combination.

Falls back to sending to the focused window if Discord is not found.
xdotool key --window uses XSendEvent which sets send_event=True in the
X11 event. Discord (and Chromium/Electron in general) rejects these as
synthetic events - they are ignored by both the global hotkey listener
and the Electron renderer's isTrusted check.

Switch to: focus Discord's window first, then send the key via
XTestFakeKeyEvent (no --window). XTest events have send_event=False so
Chromium treats them as real hardware input (isTrusted=true), and they
are dispatched to Discord's focused-window keyboard handler which
triggers the mute/deafen/PTT action.

Focus is saved before and restored after each call so the user's
original window regains focus immediately.
@tech-stack-studios
tech-stack-studios merged commit c173cab into develop May 27, 2026
2 checks passed
@tech-stack-studios
tech-stack-studios deleted the bug/fix-plugin-keyup-handler branch May 31, 2026 01:12
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.

1 participant