aboutsummaryrefslogtreecommitdiff
path: root/ext/js/pages/settings/keyboard-mouse-input-field.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/js/pages/settings/keyboard-mouse-input-field.js')
-rw-r--r--ext/js/pages/settings/keyboard-mouse-input-field.js92
1 files changed, 91 insertions, 1 deletions
diff --git a/ext/js/pages/settings/keyboard-mouse-input-field.js b/ext/js/pages/settings/keyboard-mouse-input-field.js
index aee01a36..f0a53f1a 100644
--- a/ext/js/pages/settings/keyboard-mouse-input-field.js
+++ b/ext/js/pages/settings/keyboard-mouse-input-field.js
@@ -20,31 +20,58 @@ import {EventDispatcher, EventListenerCollection} from '../../core.js';
import {DocumentUtil} from '../../dom/document-util.js';
import {HotkeyUtil} from '../../input/hotkey-util.js';
+/**
+ * @augments EventDispatcher<import('keyboard-mouse-input-field').EventType>
+ */
export class KeyboardMouseInputField extends EventDispatcher {
+ /**
+ * @param {HTMLInputElement} inputNode
+ * @param {?HTMLButtonElement} mouseButton
+ * @param {?import('environment').OperatingSystem} os
+ * @param {?(pointerType: string) => boolean} [isPointerTypeSupported]
+ */
constructor(inputNode, mouseButton, os, isPointerTypeSupported=null) {
super();
+ /** @type {HTMLInputElement} */
this._inputNode = inputNode;
+ /** @type {?HTMLButtonElement} */
this._mouseButton = mouseButton;
+ /** @type {?(pointerType: string) => boolean} */
this._isPointerTypeSupported = isPointerTypeSupported;
+ /** @type {HotkeyUtil} */
this._hotkeyUtil = new HotkeyUtil(os);
+ /** @type {EventListenerCollection} */
this._eventListeners = new EventListenerCollection();
+ /** @type {?string} */
this._key = null;
+ /** @type {import('input').Modifier[]} */
this._modifiers = [];
+ /** @type {Set<number>} */
this._penPointerIds = new Set();
+ /** @type {boolean} */
this._mouseModifiersSupported = false;
+ /** @type {boolean} */
this._keySupported = false;
}
+ /** @type {import('input').Modifier[]} */
get modifiers() {
return this._modifiers;
}
+ /**
+ * @param {?string} key
+ * @param {import('input').Modifier[]} modifiers
+ * @param {boolean} [mouseModifiersSupported]
+ * @param {boolean} [keySupported]
+ */
prepare(key, modifiers, mouseModifiersSupported=false, keySupported=false) {
this.cleanup();
this._mouseModifiersSupported = mouseModifiersSupported;
this._keySupported = keySupported;
this.setInput(key, modifiers);
+ /** @type {import('event-listener-collection').AddEventListenerArgs[]} */
const events = [
[this._inputNode, 'keydown', this._onModifierKeyDown.bind(this), false],
[this._inputNode, 'keyup', this._onModifierKeyUp.bind(this), false]
@@ -65,12 +92,17 @@ export class KeyboardMouseInputField extends EventDispatcher {
}
}
+ /**
+ * @param {?string} key
+ * @param {import('input').Modifier[]} modifiers
+ */
setInput(key, modifiers) {
this._key = key;
this._modifiers = this._sortModifiers(modifiers);
this._updateDisplayString();
}
+ /** */
cleanup() {
this._eventListeners.removeAllEventListeners();
this._modifiers = [];
@@ -80,21 +112,31 @@ export class KeyboardMouseInputField extends EventDispatcher {
this._penPointerIds.clear();
}
+ /** */
clearInputs() {
this._updateModifiers([], null);
}
// Private
+ /**
+ * @param {import('input').Modifier[]} modifiers
+ * @returns {import('input').Modifier[]}
+ */
_sortModifiers(modifiers) {
return this._hotkeyUtil.sortModifiers(modifiers);
}
+ /** */
_updateDisplayString() {
const displayValue = this._hotkeyUtil.getInputDisplayValue(this._key, this._modifiers);
this._inputNode.value = displayValue;
}
+ /**
+ * @param {KeyboardEvent} e
+ * @returns {Set<import('input').ModifierKey>}
+ */
_getModifierKeys(e) {
const modifiers = new Set(DocumentUtil.getActiveModifiers(e));
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/metaKey
@@ -115,6 +157,10 @@ export class KeyboardMouseInputField extends EventDispatcher {
return modifiers;
}
+ /**
+ * @param {string|undefined} keyName
+ * @returns {boolean}
+ */
_isModifierKey(keyName) {
switch (keyName) {
case 'AltLeft':
@@ -133,9 +179,13 @@ export class KeyboardMouseInputField extends EventDispatcher {
}
}
+ /**
+ * @param {KeyboardEvent} e
+ */
_onModifierKeyDown(e) {
e.preventDefault();
+ /** @type {string|undefined} */
let key = e.code;
if (key === 'Unidentified' || key === '') { key = void 0; }
if (this._keySupported) {
@@ -153,15 +203,24 @@ export class KeyboardMouseInputField extends EventDispatcher {
}
}
+ /**
+ * @param {KeyboardEvent} e
+ */
_onModifierKeyUp(e) {
e.preventDefault();
}
+ /**
+ * @param {MouseEvent} e
+ */
_onMouseButtonMouseDown(e) {
e.preventDefault();
this._addModifiers(DocumentUtil.getActiveButtons(e));
}
+ /**
+ * @param {PointerEvent} e
+ */
_onMouseButtonPointerDown(e) {
if (!e.isPrimary) { return; }
@@ -179,6 +238,9 @@ export class KeyboardMouseInputField extends EventDispatcher {
this._addModifiers(DocumentUtil.getActiveButtons(e));
}
+ /**
+ * @param {PointerEvent} e
+ */
_onMouseButtonPointerOver(e) {
const {pointerType, pointerId} = e;
if (pointerType === 'pen') {
@@ -186,23 +248,39 @@ export class KeyboardMouseInputField extends EventDispatcher {
}
}
+ /**
+ * @param {PointerEvent} e
+ */
_onMouseButtonPointerOut(e) {
const {pointerId} = e;
this._penPointerIds.delete(pointerId);
}
+ /**
+ * @param {PointerEvent} e
+ */
_onMouseButtonPointerCancel(e) {
this._onMouseButtonPointerOut(e);
}
+ /**
+ * @param {MouseEvent} e
+ */
_onMouseButtonMouseUp(e) {
e.preventDefault();
}
+ /**
+ * @param {MouseEvent} e
+ */
_onMouseButtonContextMenu(e) {
e.preventDefault();
}
+ /**
+ * @param {Iterable<import('input').Modifier>} newModifiers
+ * @param {?string} [newKey]
+ */
_addModifiers(newModifiers, newKey) {
const modifiers = new Set(this._modifiers);
for (const modifier of newModifiers) {
@@ -211,6 +289,10 @@ export class KeyboardMouseInputField extends EventDispatcher {
this._updateModifiers([...modifiers], newKey);
}
+ /**
+ * @param {import('input').Modifier[]} modifiers
+ * @param {?string} [newKey]
+ */
_updateModifiers(modifiers, newKey) {
modifiers = this._sortModifiers(modifiers);
@@ -226,10 +308,18 @@ export class KeyboardMouseInputField extends EventDispatcher {
this._updateDisplayString();
if (changed) {
- this.trigger('change', {modifiers: this._modifiers, key: this._key});
+ /** @type {import('keyboard-mouse-input-field').ChangeEvent} */
+ const event = {modifiers: this._modifiers, key: this._key};
+ this.trigger('change', event);
}
}
+ /**
+ * @template T
+ * @param {T[]} array1
+ * @param {T[]} array2
+ * @returns {boolean}
+ */
_areArraysEqual(array1, array2) {
const length = array1.length;
if (length !== array2.length) { return false; }