Home: git.evandro.dev.br/evandro/vencord-wayland-keybinds, on my self-hosted Gitea. GitHub only carries this copy for reach.
**WaylandKeybinds** is a [Vencord](https://vencord.dev) plugin for the Discord desktop app on Linux. Discord already hands your keybinds to GNOME through the `GlobalShortcuts` portal, but GNOME loses the key release whenever a modifier is let go first, and Discord's mute and deafen only act on the release. The plugin fixes this inside Discord's own **Keybinds** screen: whatever key you choose there becomes global, like Discord on Windows.
Measured on GNOME 50 with Discord 1.0.168: every press toggled the mute exactly once, 11 to 14 ms after GNOME's signal, including a 6-second hold that GNOME repeated 57 times.
## Why Discord's keybinds break on GNOME
- GNOME's compositor looks up a shortcut's release using the modifiers still held at that moment. Let Ctrl or Shift go before the main key and the release never matches, so the portal never sends `Deactivated` ([`process_event`](https://gitlab.gnome.org/GNOME/mutter/-/blob/main/src/core/keybindings.c)).
- Mute, deafen and most other toggles fire on the key **release** only.
- Discord's native module ignores further presses until it sees a release, so after one lost release the next gesture disappears too.
- GNOME describes the trigger as `Press F10` while Discord expects `CTRL+SHIFT+F10`, so every working shortcut is flagged as different from the system one.
## What the plugin does
- Toggle actions (mute, deafen, streamer mode and the rest) fire on the **press**.
- One second after a press it re-registers the shortcut, which clears Discord's stuck state, then listens for 300 ms. While the keys are held, GNOME's key repeat answers within a few milliseconds; silence means they were released. That is how push-to-talk stops even when the release is lost. A real release still stops it at once.
- It reads GNOME's trigger format, so the Keybinds screen stops warning about a mismatch.
- It changes nothing unless Discord registers the keybind through the Wayland portal. It runs in the renderer only: no native code, no new dependency, no DOM clicks.
## Install
You need a [Vencord source checkout](https://docs.vencord.dev/installing/), because user plugins are compiled into your build.
```sh
cd /path/to/Vencord
git clone https://git.evandro.dev.br/evandro/vencord-wayland-keybinds.git src/userplugins/waylandKeybinds.discordDesktop
pnpm build
pnpm inject
```
Restart Discord. The plugin is on by default; you can find it as **WaylandKeybinds** in Vencord's plugin list. Its info panel shows whether the fix is active, how many keybinds GNOME has registered, and a button that opens Discord's Keybinds page.
> [!IMPORTANT]
> Keep the folder name `waylandKeybinds.discordDesktop`. The suffix limits the plugin to the Discord desktop app, the only place where Discord's native keybind module exists.
## Use
1. Open Discord **User Settings → System → Keybinds** and click **Add a Keybind**.
2. Pick an action (Toggle Mute, Toggle Deafen, Push to Talk…) and press your combination.
3. GNOME asks once to allow the shortcut. Click **Add**.
Change the keys whenever you want on the same screen; GNOME asks again for the new combination.
> [!TIP]
> For push-to-talk, a single key without modifiers (Pause, F13 to F24) keeps both press and release reliable.
On Wayland, Discord records only combinations the portal can represent: one main key plus optional modifiers. Mouse buttons cannot be global shortcuts there.
## Compatibility
| Component | Tested with |
| --- | --- |
| Discord | 1.0.168 (Electron 44) |
| Vencord | 1.15.15 |
| GNOME | 50.5 (mutter 18, xdg-desktop-portal-gnome 50) |
| KDE Plasma, Hyprland | Not tested. The portal path is the same, the release behavior may differ. |
## Limits
- Release detection relies on GNOME's key repeat (500 ms, then every 30 ms by default). With key repeat turned off, push-to-talk ends about 1.3 s after the press even while you hold it.
- When the release is lost, push-to-talk stops up to about 1.3 s after you let go.
- The live checks covered toggle mute; push-to-talk is covered by the state-machine tests.
- Soundboard hold stays off the portal on Linux. That is Discord's own choice.
- The patches target Discord's minified code and can break with Discord updates. Run `check-patches.mjs` before you rebuild.
## Development
From the root of your Vencord checkout:
```sh
# one test case per independent path of every function in logic.ts
pnpm exec esbuild src/userplugins/waylandKeybinds.discordDesktop/logic.test.ts \
--bundle --platform=node --format=esm --outfile=/tmp/wk-test.mjs
node --test /tmp/wk-test.mjs
# apply the patches to the Discord build that discord.com serves right now
node src/userplugins/waylandKeybinds.discordDesktop/check-patches.mjs
```
The design notes, measurements and acceptance criteria (in Portuguese) are in [`specs/2026-11-01-wayland-keybinds.md`](specs/2026-11-01-wayland-keybinds.md).
---
Made by Evandro · git.evandro.dev.br/evandro · evandro.dev.br