diff --git a/browser_tests/keybindings.spec.ts b/browser_tests/keybindings.spec.ts index 7c7d556e2..e5286c445 100644 --- a/browser_tests/keybindings.spec.ts +++ b/browser_tests/keybindings.spec.ts @@ -35,4 +35,20 @@ test.describe('Keybindings', () => { true ) }) + + test('Should not trigger keybinding reserved by text input when typing in input fields', async ({ + comfyPage + }) => { + await comfyPage.registerKeybinding({ key: 'Ctrl+v' }, () => { + window['TestCommand'] = true + }) + + const textBox = comfyPage.widgetTextBox + await textBox.click() + await textBox.press('Control+v') + await expect(textBox).toBeFocused() + expect(await comfyPage.page.evaluate(() => window['TestCommand'])).toBe( + undefined + ) + }) }) diff --git a/src/constants/reservedKeyCombos.ts b/src/constants/reservedKeyCombos.ts new file mode 100644 index 000000000..1dc04708f --- /dev/null +++ b/src/constants/reservedKeyCombos.ts @@ -0,0 +1,35 @@ +export const RESERVED_BY_TEXT_INPUT = new Set([ + 'Ctrl + a', + 'Ctrl + c', + 'Ctrl + v', + 'Ctrl + x', + 'Ctrl + z', + 'Ctrl + y', + 'Ctrl + p', + 'Enter', + 'Shift + Enter', + 'Ctrl + Backspace', + 'Ctrl + Delete', + 'Home', + 'Ctrl + Home', + 'Ctrl + Shift + Home', + 'End', + 'Ctrl + End', + 'Ctrl + Shift + End', + 'PageUp', + 'PageDown', + 'Shift + PageUp', + 'Shift + PageDown', + 'ArrowLeft', + 'Ctrl + ArrowLeft', + 'Shift + ArrowLeft', + 'Ctrl + Shift + ArrowLeft', + 'ArrowRight', + 'Ctrl + ArrowRight', + 'Shift + ArrowRight', + 'Ctrl + Shift + ArrowRight', + 'ArrowUp', + 'Shift + ArrowUp', + 'ArrowDown', + 'Shift + ArrowDown' +]) diff --git a/src/services/keybindingService.ts b/src/services/keybindingService.ts index 20e293798..b1c23a1ce 100644 --- a/src/services/keybindingService.ts +++ b/src/services/keybindingService.ts @@ -18,10 +18,10 @@ export const useKeybindingService = () => { return } - // Ignore non-modifier keybindings if typing in input fields + // Ignore reserved or non-modifier keybindings if typing in input fields const target = event.composedPath()[0] as HTMLElement if ( - !keyCombo.hasModifier && + keyCombo.isReservedByTextInput && (target.tagName === 'TEXTAREA' || target.tagName === 'INPUT' || (target.tagName === 'SPAN' && diff --git a/src/stores/keybindingStore.ts b/src/stores/keybindingStore.ts index 90cf22944..8c9401018 100644 --- a/src/stores/keybindingStore.ts +++ b/src/stores/keybindingStore.ts @@ -2,6 +2,7 @@ import _ from 'lodash' import { defineStore } from 'pinia' import { Ref, computed, ref, toRaw } from 'vue' +import { RESERVED_BY_TEXT_INPUT } from '@/constants/reservedKeyCombos' import { KeyCombo, Keybinding } from '@/types/keyBindingTypes' export class KeybindingImpl implements Keybinding { @@ -76,6 +77,23 @@ export class KeyComboImpl implements KeyCombo { return ['Control', 'Meta', 'Alt', 'Shift'].includes(this.key) } + get modifierCount(): number { + const modifiers = [this.ctrl, this.alt, this.shift] + return modifiers.reduce((acc, cur) => acc + Number(cur), 0) + } + + get isShiftOnly(): boolean { + return this.shift && this.modifierCount === 1 + } + + get isReservedByTextInput(): boolean { + return ( + !this.hasModifier || + this.isShiftOnly || + RESERVED_BY_TEXT_INPUT.has(this.toString()) + ) + } + getKeySequences(): string[] { const sequences: string[] = [] if (this.ctrl) {