mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-27 16:49:51 -07:00
feat(keybindings): add mouse button support for mpv keybindings (#103)
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
buildMpvKeybindingConfigValue,
|
||||
createMpvKeybindingRows,
|
||||
keyboardEventToConfigKey,
|
||||
mouseEventToConfigKey,
|
||||
} from './key-input';
|
||||
|
||||
test('keyboardEventToConfigKey formats Electron accelerators from learned input', () => {
|
||||
@@ -75,6 +76,23 @@ test('keyboardEventToConfigKey formats mpv key bindings from learned input', ()
|
||||
);
|
||||
});
|
||||
|
||||
test('mouseEventToConfigKey formats mpv mouse buttons from learned input', () => {
|
||||
assert.equal(
|
||||
mouseEventToConfigKey(
|
||||
{ button: 3, ctrlKey: false, altKey: false, shiftKey: false, metaKey: false },
|
||||
'dom-code',
|
||||
),
|
||||
'MBTN_BACK',
|
||||
);
|
||||
assert.equal(
|
||||
mouseEventToConfigKey(
|
||||
{ button: 4, ctrlKey: false, altKey: true, shiftKey: true, metaKey: false },
|
||||
'dom-code',
|
||||
),
|
||||
'Alt+Shift+MBTN_FORWARD',
|
||||
);
|
||||
});
|
||||
|
||||
test('MPV keybinding rows save default key moves as a disable plus replacement', () => {
|
||||
const defaults: Keybinding[] = [{ key: 'Space', command: ['cycle', 'pause'] }];
|
||||
const rows = createMpvKeybindingRows(defaults, []);
|
||||
|
||||
@@ -11,6 +11,14 @@ export interface KeyboardInputLike {
|
||||
metaKey: boolean;
|
||||
}
|
||||
|
||||
export interface MouseInputLike {
|
||||
button: number;
|
||||
ctrlKey: boolean;
|
||||
altKey: boolean;
|
||||
shiftKey: boolean;
|
||||
metaKey: boolean;
|
||||
}
|
||||
|
||||
export interface MpvKeybindingRow {
|
||||
defaultKey: string;
|
||||
key: string;
|
||||
@@ -79,6 +87,14 @@ const MPV_KEY_BY_CODE: Record<string, string> = {
|
||||
Tab: 'TAB',
|
||||
};
|
||||
|
||||
const MPV_MOUSE_BUTTON_BY_BUTTON: Record<number, string> = {
|
||||
0: 'MBTN_LEFT',
|
||||
1: 'MBTN_MID',
|
||||
2: 'MBTN_RIGHT',
|
||||
3: 'MBTN_BACK',
|
||||
4: 'MBTN_FORWARD',
|
||||
};
|
||||
|
||||
function commandEquals(a: Keybinding['command'], b: Keybinding['command']): boolean {
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
}
|
||||
@@ -152,6 +168,24 @@ export function keyboardEventToConfigKey(
|
||||
return [...parts, input.code].join('+');
|
||||
}
|
||||
|
||||
export function mouseEventToConfigKey(input: MouseInputLike, mode: KeyInputMode): string | null {
|
||||
if (mode !== 'dom-code') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const key = MPV_MOUSE_BUTTON_BY_BUTTON[input.button];
|
||||
if (!key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
if (input.ctrlKey) parts.push('Ctrl');
|
||||
if (input.altKey) parts.push('Alt');
|
||||
if (input.shiftKey) parts.push('Shift');
|
||||
if (input.metaKey) parts.push('Meta');
|
||||
return [...parts, key].join('+');
|
||||
}
|
||||
|
||||
export function createMpvKeybindingRows(
|
||||
defaultBindings: Keybinding[],
|
||||
userBindings: unknown,
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { shouldUseLearnedMouseBinding } from './settings-keybinding-controls';
|
||||
|
||||
test('mouse key learning ignores primary left clicks in DOM-code mode', () => {
|
||||
const learnButton = {};
|
||||
const outsideTarget = {};
|
||||
|
||||
assert.equal(
|
||||
shouldUseLearnedMouseBinding(
|
||||
'MBTN_LEFT',
|
||||
'dom-code',
|
||||
{ button: 0, target: outsideTarget } as MouseEvent,
|
||||
learnButton as HTMLButtonElement,
|
||||
),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldUseLearnedMouseBinding(
|
||||
'MBTN_BACK',
|
||||
'dom-code',
|
||||
{ button: 3, target: outsideTarget } as MouseEvent,
|
||||
learnButton as HTMLButtonElement,
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('mouse key learning still ignores primary learn-button activation', () => {
|
||||
const learnButton = {};
|
||||
|
||||
assert.equal(
|
||||
shouldUseLearnedMouseBinding(
|
||||
'MBTN_LEFT',
|
||||
'dom-code',
|
||||
{ button: 0, target: learnButton } as MouseEvent,
|
||||
learnButton as HTMLButtonElement,
|
||||
),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldUseLearnedMouseBinding(
|
||||
'MBTN_BACK',
|
||||
'dom-code',
|
||||
{ button: 3, target: learnButton } as MouseEvent,
|
||||
learnButton as HTMLButtonElement,
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
buildMpvKeybindingConfigValue,
|
||||
createMpvKeybindingRows,
|
||||
keyboardEventToConfigKey,
|
||||
mouseEventToConfigKey,
|
||||
parseMpvCommandText,
|
||||
type KeyInputMode,
|
||||
type MpvKeybindingRow,
|
||||
@@ -18,6 +19,18 @@ export function configureKeybindingControls(options: { requestRender: () => void
|
||||
requestRender = options.requestRender;
|
||||
}
|
||||
|
||||
export function shouldUseLearnedMouseBinding(
|
||||
next: string,
|
||||
mode: KeyInputMode,
|
||||
event: MouseEvent,
|
||||
button: HTMLButtonElement,
|
||||
): boolean {
|
||||
return Boolean(
|
||||
!(event.target === button && event.button === 0) &&
|
||||
!(mode === 'dom-code' && event.button === 0),
|
||||
);
|
||||
}
|
||||
|
||||
function startKeyLearning(
|
||||
button: HTMLButtonElement,
|
||||
mode: KeyInputMode,
|
||||
@@ -58,6 +71,15 @@ function startKeyLearning(
|
||||
};
|
||||
onBlur = (): void => stop();
|
||||
onMouseDown = (event: MouseEvent): void => {
|
||||
const next = mouseEventToConfigKey(event, mode);
|
||||
if (next && shouldUseLearnedMouseBinding(next, mode, event, button)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
stop();
|
||||
onValue(next);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target !== button) {
|
||||
stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user