From 0114f8efa42474e9dae12affa245eed73bfd30f9 Mon Sep 17 00:00:00 2001 From: Tuxinal <24763016+tuxinal@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:47:48 +0330 Subject: [PATCH] Add all available actions to globalshortcuts on startup --- src/main/venbind.ts | 18 ++++++++-- src/preload/VesktopNative.ts | 4 ++- src/renderer/patches/keybinds.ts | 62 +++++++++++++++++++++++++++++++- src/shared/IpcEvents.ts | 5 ++- 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/main/venbind.ts b/src/main/venbind.ts index 64ba87d..0af7263 100644 --- a/src/main/venbind.ts +++ b/src/main/venbind.ts @@ -10,7 +10,7 @@ import { STATIC_DIR } from "shared/paths"; import type { Venbind as VenbindType } from "venbind"; import { mainWin } from "./mainWindow"; -import { handle } from "./utils/ipcWrappers"; +import { handle, handleSync } from "./utils/ipcWrappers"; let venbind: VenbindType | null = null; export function obtainVenbind() { @@ -50,7 +50,7 @@ export function obtainVenbind() { export function startVenbind() { const venbind = obtainVenbind(); - venbind?.startKeybinds(null, x => { + venbind?.startKeybinds(x => { mainWin.webContents.executeJavaScript(`Vesktop.keybindCallbacks[${x}](false)`); }); } @@ -61,3 +61,17 @@ handle(IpcEvents.KEYBIND_REGISTER, (_, id: number, shortcut: string, options: an handle(IpcEvents.KEYBIND_UNREGISTER, (_, id: number) => { obtainVenbind()?.unregisterKeybind(id); }); +handleSync(IpcEvents.KEYBIND_SHOULD_PREREGISTER, _ => { + if ( + process.platform === "linux" && + (process.env.XDG_SESSION_TYPE === "wayland" || + !!process.env.WAYLAND_DISPLAY || + !!process.env.VENBIND_USE_XDG_PORTAL) + ) { + return true; + } + return false; +}); +handle(IpcEvents.KEYBIND_PREREGISTER, (_, actions: { id: number; name: string }[]) => { + obtainVenbind()?.preregisterKeybinds(actions); +}); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 5f93cfe..1e49b9a 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -82,6 +82,8 @@ export const VesktopNative = { keybind: { register: (id: number, shortcut: string, options: any) => invoke(IpcEvents.KEYBIND_REGISTER, id, shortcut), - unregister: (id: number) => invoke(IpcEvents.KEYBIND_UNREGISTER, id) + unregister: (id: number) => invoke(IpcEvents.KEYBIND_UNREGISTER, id), + shouldPreRegister: () => sendSync(IpcEvents.KEYBIND_SHOULD_PREREGISTER), + preRegister: (actions: { id: number; name: string }[]) => invoke(IpcEvents.KEYBIND_PREREGISTER, actions) } }; diff --git a/src/renderer/patches/keybinds.ts b/src/renderer/patches/keybinds.ts index b8550c5..ec0b1cf 100644 --- a/src/renderer/patches/keybinds.ts +++ b/src/renderer/patches/keybinds.ts @@ -9,7 +9,18 @@ import { keybindCallbacks } from "renderer"; import { addPatch } from "./shared"; const toShortcutString = findByCodeLazy('return"gamepad".'); - +const actionReadableNames: { [key: string]: string } = { + PUSH_TO_TALK: "Push To Talk", + PUSH_TO_TALK_PRIORITY: "Push To Talk (Priority)", + PUSH_TO_MUTE: "Push To Mute", + TOGGLE_MUTE: "Toggle Mute", + TOGGLE_DEAFEN: "Toggle Deafen", + TOGGLE_VOICE_MODE: "Toggle Voice Activity Mode", + TOGGLE_STREAMER_MODE: "Toggle Streamer Mode", + NAVIGATE_BACK: "Navigate Back", + NAVIGATE_FORWARD: "Navigate Forward", + DISCONNECT_FROM_VOICE_CHANNEL: "Disconnect From Voice Channel" +}; addPatch({ patches: [ { @@ -45,17 +56,66 @@ addPatch({ // eslint-disable-next-line no-useless-escape match: /inputEventUnregister\((parseInt\(\i,10\))\);else/, replace: "$&{$self.unregisterKeybind($1);return;}" + }, + { + match: /let{keybinds:(\i)}=\i;/, + replace: "$&$self.preRegisterKeybinds($1);" } ] } ], registerKeybind: function (id, shortcut, callback, options) { + if (VesktopNative.keybind.shouldPreRegister()) { + return; + } keybindCallbacks[id] = callback; VesktopNative.keybind.register(id, toShortcutString(shortcut), options); }, unregisterKeybind: function (id) { + if (VesktopNative.keybind.shouldPreRegister()) { + return; + } delete keybindCallbacks[id]; VesktopNative.keybind.unregister(id); + }, + // only used for wayland/xdg-desktop-portal globalshortcuts + preRegisterKeybinds: function (allActions: { + [action: string]: { + onTrigger: Function; + }; + }) { + let actions: { id: number; name: string }[] = []; + if (!VesktopNative.keybind.shouldPreRegister()) { + return; + } + let id = 1; + Object.entries(allActions).forEach(([key, val]) => { + if ( + [ + "UNASSIGNED", + "SWITCH_TO_VOICE_CHANNEL", + "TOGGLE_OVERLAY", + "TOGGLE_OVERLAY_INPUT_LOCK", + "TOGGLE_PRIORITY_SPEAKER", + "OVERLAY_ACTIVATE_REGION_TEXT_WIDGET", + "TOGGLE_GO_LIVE_STREAMING", // ??? + "SOUNDBOARD", + "SOUNDBOARD_HOLD", + "SAVE_CLIP" + // most of these aren't available to change through discord as far as i can tell + ].includes(key) + ) { + return; + } + // the second argument in onTrigger seems to hold some context in some specific actions + // as far as i can tell these are the only actions that use it: push to talk (except it doesn't seem to do anything there??) + // and switch to voice channel which requires a channel parameter which is provided through discord's ui + // except we can't really provide that with xdp so i'll just skip it for now + keybindCallbacks[id] = (keyState: boolean) => val.onTrigger(keyState, undefined); + actions.push({ id, name: actionReadableNames[key] }); + id++; + }); + VesktopNative.keybind.preRegister(actions); } }); diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 62ea94c..5d80260 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -51,6 +51,9 @@ export const enum IpcEvents { ARRPC_ACTIVITY = "VCD_ARRPC_ACTIVITY", CLIPBOARD_COPY_IMAGE = "VCD_CLIPBOARD_COPY_IMAGE", + KEYBIND_REGISTER = "VCD_KEYBIND_REGISTER", - KEYBIND_UNREGISTER = "VCD_KEYBIND_UNREGISTER" + KEYBIND_UNREGISTER = "VCD_KEYBIND_UNREGISTER", + KEYBIND_SHOULD_PREREGISTER = "VCD_KEYBIND_SHOULD_PREREGISTER", + KEYBIND_PREREGISTER = "VCD_KEYBIND_PREREGISTER" }