summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2022-06-03 17:11:32 -0400
committerGitHub <noreply@github.com>2022-06-03 17:11:32 -0400
commitc966d9b1ebb12386ac876d93f377fe3a470c6976 (patch)
treefaa270fae2c011da8b05056271453f24d77c9d3c /ext
parente61edc387c1edeca1745c96d163a397b5bf1abdf (diff)
Touch and pen input updates (#2172)
* Remove unnecessary return * Move touch start input filtering * Refactor * Add scanOnTouchPress * Add preventPenScrolling * Rename scanOnPenPress to scanOnPenMove * Rename scanOnPenRelease to scanOnPenReleaseHover * Simplify * Refactor _searchAtFromPen early exit * Merge _penPointerPressed and _penPointerReleased into a single variable * Add more options * Simplify pen pointer coordinates * Implement scanOnPenPress and scanOnPenRelease * Implement scanOnTouchRelease * Fix tests * Don't search on touch cancel * Cancel touch if the touch action is used for scrolling or other gestures * Fix incorrect scroll prevention options being used * Organize options * Fix typos
Diffstat (limited to 'ext')
-rw-r--r--ext/css/settings.css13
-rw-r--r--ext/data/schemas/options-schema.json42
-rw-r--r--ext/js/data/options-util.js16
-rw-r--r--ext/js/display/display.js7
-rw-r--r--ext/js/language/text-scanner.js145
-rw-r--r--ext/js/pages/settings/scan-inputs-controller.js7
-rw-r--r--ext/settings.html36
7 files changed, 198 insertions, 68 deletions
diff --git a/ext/css/settings.css b/ext/css/settings.css
index dc8132be..6f1afa00 100644
--- a/ext/css/settings.css
+++ b/ext/css/settings.css
@@ -1714,9 +1714,12 @@ code.anki-field-marker {
.scan-input-prefix-cell[data-property=search-options] {
grid-area: 4/2/5/3;
}
-.scan-input-prefix-cell[data-property=touch-pen-options] {
+.scan-input-prefix-cell[data-property=touch-options] {
grid-area: 5/2/6/3;
}
+.scan-input-prefix-cell[data-property=pen-options] {
+ grid-area: 6/2/7/3;
+}
.scan-input-content-cell[data-property=include] {
grid-area: 1/3/2/4;
}
@@ -1735,12 +1738,18 @@ code.anki-field-marker {
flex-flow: row wrap;
align-items: center;
}
-.scan-input-content-cell[data-property=touch-pen-options] {
+.scan-input-content-cell[data-property=touch-options] {
grid-area: 5/3/6/4;
display: flex;
flex-flow: column nowrap;
align-items: flex-start;
}
+.scan-input-content-cell[data-property=pen-options] {
+ grid-area: 6/3/7/4;
+ display: flex;
+ flex-flow: column nowrap;
+ align-items: flex-start;
+}
.scan-input-options-cell {
padding: 0.25em 0;
align-self: start;
diff --git a/ext/data/schemas/options-schema.json b/ext/data/schemas/options-schema.json
index 279be153..d7e3b5f4 100644
--- a/ext/data/schemas/options-schema.json
+++ b/ext/data/schemas/options-schema.json
@@ -457,10 +457,15 @@
"searchTerms": true,
"searchKanji": true,
"scanOnTouchMove": true,
+ "scanOnTouchPress": true,
+ "scanOnTouchRelease": false,
+ "scanOnPenMove": true,
"scanOnPenHover": true,
+ "scanOnPenReleaseHover": false,
"scanOnPenPress": true,
"scanOnPenRelease": false,
- "preventTouchScrolling": false
+ "preventTouchScrolling": false,
+ "preventPenScrolling": false
}
},
{
@@ -476,10 +481,15 @@
"searchTerms": true,
"searchKanji": true,
"scanOnTouchMove": true,
+ "scanOnTouchPress": true,
+ "scanOnTouchRelease": false,
+ "scanOnPenMove": true,
"scanOnPenHover": true,
+ "scanOnPenReleaseHover": false,
"scanOnPenPress": true,
"scanOnPenRelease": false,
- "preventTouchScrolling": true
+ "preventTouchScrolling": true,
+ "preventPenScrolling": true
}
}
],
@@ -528,10 +538,12 @@
"searchTerms",
"searchKanji",
"scanOnTouchMove",
+ "scanOnTouchPress",
+ "scanOnPenMove",
"scanOnPenHover",
- "scanOnPenPress",
- "scanOnPenRelease",
- "preventTouchScrolling"
+ "scanOnPenReleaseHover",
+ "preventTouchScrolling",
+ "preventPenScrolling"
],
"properties": {
"showAdvanced": {
@@ -550,10 +562,26 @@
"type": "boolean",
"default": true
},
+ "scanOnTouchPress": {
+ "type": "boolean",
+ "default": true
+ },
+ "scanOnTouchRelease": {
+ "type": "boolean",
+ "default": false
+ },
+ "scanOnPenMove": {
+ "type": "boolean",
+ "default": true
+ },
"scanOnPenHover": {
"type": "boolean",
"default": true
},
+ "scanOnPenReleaseHover": {
+ "type": "boolean",
+ "default": false
+ },
"scanOnPenPress": {
"type": "boolean",
"default": true
@@ -565,6 +593,10 @@
"preventTouchScrolling": {
"type": "boolean",
"default": true
+ },
+ "preventPenScrolling": {
+ "type": "boolean",
+ "default": true
}
}
}
diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js
index f19094df..a163580f 100644
--- a/ext/js/data/options-util.js
+++ b/ext/js/data/options-util.js
@@ -953,9 +953,25 @@ class OptionsUtil {
// Version 19 changes:
// Added anki.noteGuiMode.
// Added anki.apiKey.
+ // Renamed scanning.inputs[].options.scanOnPenPress to scanOnPenMove.
+ // Renamed scanning.inputs[].options.scanOnPenRelease to scanOnPenReleaseHover.
+ // Added scanning.inputs[].options.scanOnTouchPress.
+ // Added scanning.inputs[].options.scanOnTouchRelease.
+ // Added scanning.inputs[].options.scanOnPenPress.
+ // Added scanning.inputs[].options.scanOnPenRelease.
+ // Added scanning.inputs[].options.preventPenScrolling.
for (const profile of options.profiles) {
profile.options.anki.noteGuiMode = 'browse';
profile.options.anki.apiKey = '';
+ for (const input of profile.options.scanning.inputs) {
+ input.options.scanOnPenMove = input.options.scanOnPenPress;
+ input.options.scanOnPenReleaseHover = input.options.scanOnPenRelease;
+ input.options.scanOnTouchPress = true;
+ input.options.scanOnTouchRelease = false;
+ input.options.scanOnPenPress = input.options.scanOnPenMove;
+ input.options.scanOnPenRelease = false;
+ input.options.preventPenScrolling = input.options.preventTouchScrolling;
+ }
}
return options;
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index f9153420..923c9dd2 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -1516,10 +1516,15 @@ class Display extends EventDispatcher {
searchTerms: true,
searchKanji: true,
scanOnTouchMove: false,
+ scanOnTouchPress: false,
+ scanOnTouchRelease: false,
+ scanOnPenMove: false,
scanOnPenHover: false,
+ scanOnPenReleaseHover: false,
scanOnPenPress: false,
scanOnPenRelease: false,
- preventTouchScrolling: false
+ preventTouchScrolling: false,
+ preventPenScrolling: false
}
}],
deepContentScan: scanningOptions.deepDomScan,
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index 36091805..978f3d36 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -83,8 +83,7 @@ class TextScanner extends EventDispatcher {
this._preventNextMouseDown = false;
this._preventNextClick = false;
this._preventScroll = false;
- this._penPointerPressed = false;
- this._penPointerReleased = false;
+ this._penPointerState = 0; // 0 = not active; 1 = hovering; 2 = touching; 3 = hovering after touching
this._pointerIdTypeMap = new Map();
this._canClearSelection = true;
@@ -135,8 +134,7 @@ class TextScanner extends EventDispatcher {
this._preventNextMouseDown = false;
this._preventNextClick = false;
this._preventScroll = false;
- this._penPointerPressed = false;
- this._penPointerReleased = false;
+ this._penPointerState = 0;
this._pointerIdTypeMap.clear();
this._enabledValue = value;
@@ -168,10 +166,15 @@ class TextScanner extends EventDispatcher {
searchTerms,
searchKanji,
scanOnTouchMove,
+ scanOnTouchPress,
+ scanOnTouchRelease,
+ scanOnPenMove,
scanOnPenHover,
+ scanOnPenReleaseHover,
scanOnPenPress,
scanOnPenRelease,
- preventTouchScrolling
+ preventTouchScrolling,
+ preventPenScrolling
}
}) => ({
include: this._getInputArray(include),
@@ -181,10 +184,15 @@ class TextScanner extends EventDispatcher {
searchTerms,
searchKanji,
scanOnTouchMove,
+ scanOnTouchPress,
+ scanOnTouchRelease,
+ scanOnPenMove,
scanOnPenHover,
+ scanOnPenReleaseHover,
scanOnPenPress,
scanOnPenRelease,
- preventTouchScrolling
+ preventTouchScrolling,
+ preventPenScrolling
}
}));
}
@@ -515,41 +523,60 @@ class TextScanner extends EventDispatcher {
this._primaryTouchIdentifier = identifier;
- this._searchAtFromTouchStart(e, x, y);
+ if (this._pendingLookup) { return; }
+
+ const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchStart', e);
+ if (inputInfo === null || !inputInfo.input.options.scanOnTouchPress) { return; }
+
+ this._searchAtFromTouchStart(x, y, inputInfo);
}
_onTouchEnd(e) {
- if (
- this._primaryTouchIdentifier === null ||
- this._getTouch(e.changedTouches, this._primaryTouchIdentifier) === null
- ) {
- return;
- }
+ if (this._primaryTouchIdentifier === null) { return; }
+
+ const primaryTouch = this._getTouch(e.changedTouches, this._primaryTouchIdentifier);
+ if (primaryTouch === null) { return; }
- this._onPrimaryTouchEnd();
+ const {clientX, clientY} = primaryTouch;
+ this._onPrimaryTouchEnd(e, clientX, clientY, true);
}
- _onPrimaryTouchEnd() {
+ _onPrimaryTouchEnd(e, x, y, allowSearch) {
this._primaryTouchIdentifier = null;
this._preventScroll = false;
this._preventNextClick = false;
// Don't revert context menu and mouse down prevention, since these events can occur after the touch has ended.
// I.e. this._preventNextContextMenu and this._preventNextMouseDown should not be assigned to false.
+
+ if (!allowSearch) { return; }
+
+ const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchEnd', e);
+ if (inputInfo === null || !inputInfo.input.options.scanOnTouchRelease) { return; }
+
+ this._searchAtFromTouchEnd(x, y, inputInfo);
}
_onTouchCancel(e) {
- this._onTouchEnd(e);
+ if (this._primaryTouchIdentifier === null) { return; }
+
+ const primaryTouch = this._getTouch(e.changedTouches, this._primaryTouchIdentifier);
+ if (primaryTouch === null) { return; }
+
+ this._onPrimaryTouchEnd(e, 0, 0, false);
}
_onTouchMove(e) {
- if (!this._preventScroll || !e.cancelable || this._primaryTouchIdentifier === null) {
+ if (this._primaryTouchIdentifier === null) { return; }
+
+ if (!e.cancelable) {
+ this._onPrimaryTouchEnd(e, 0, 0, false);
return;
}
+ if (!this._preventScroll) { return; }
+
const primaryTouch = this._getTouch(e.changedTouches, this._primaryTouchIdentifier);
- if (primaryTouch === null) {
- return;
- }
+ if (primaryTouch === null) { return; }
const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchMove', e);
if (inputInfo === null) { return; }
@@ -652,7 +679,7 @@ class TextScanner extends EventDispatcher {
_onTouchPointerDown(e) {
const {clientX, clientY, pointerId} = e;
- return this._onPrimaryTouchStart(e, clientX, clientY, pointerId);
+ this._onPrimaryTouchStart(e, clientX, clientY, pointerId);
}
_onTouchPointerMove(e) {
@@ -666,12 +693,13 @@ class TextScanner extends EventDispatcher {
this._searchAt(e.clientX, e.clientY, inputInfo);
}
- _onTouchPointerUp() {
- return this._onPrimaryTouchEnd();
+ _onTouchPointerUp(e) {
+ const {clientX, clientY} = e;
+ return this._onPrimaryTouchEnd(e, clientX, clientY, true);
}
- _onTouchPointerCancel() {
- return this._onPrimaryTouchEnd();
+ _onTouchPointerCancel(e) {
+ return this._onPrimaryTouchEnd(e, 0, 0, false);
}
_onTouchPointerOut() {
@@ -689,25 +717,24 @@ class TextScanner extends EventDispatcher {
}
_onPenPointerOver(e) {
- this._penPointerPressed = false;
- this._penPointerReleased = false;
- this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerOver', false);
+ this._penPointerState = 1;
+ this._searchAtFromPen(e, 'pointerOver', false);
}
_onPenPointerDown(e) {
- this._penPointerPressed = true;
- this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerDown', true);
+ this._penPointerState = 2;
+ this._searchAtFromPen(e, 'pointerDown', true);
}
_onPenPointerMove(e) {
- if (this._penPointerPressed && (!this._preventScroll || !e.cancelable)) { return; }
- this._searchAtFromPen(e, e.clientX, e.clientY, 'pointerMove', true);
+ if (this._penPointerState === 2 && (!this._preventScroll || !e.cancelable)) { return; }
+ this._searchAtFromPen(e, 'pointerMove', true);
}
- _onPenPointerUp() {
- this._penPointerPressed = false;
- this._penPointerReleased = true;
+ _onPenPointerUp(e) {
+ this._penPointerState = 3;
this._preventScroll = false;
+ this._searchAtFromPen(e, 'pointerUp', false);
}
_onPenPointerCancel(e) {
@@ -715,8 +742,7 @@ class TextScanner extends EventDispatcher {
}
_onPenPointerOut() {
- this._penPointerPressed = false;
- this._penPointerReleased = false;
+ this._penPointerState = 0;
this._preventScroll = false;
this._preventNextContextMenu = false;
this._preventNextMouseDown = false;
@@ -953,12 +979,7 @@ class TextScanner extends EventDispatcher {
await this._searchAt(x, y, inputInfo);
}
- async _searchAtFromTouchStart(e, x, y) {
- if (this._pendingLookup) { return; }
-
- const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchStart', e);
- if (inputInfo === null) { return; }
-
+ async _searchAtFromTouchStart(x, y, inputInfo) {
const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null;
const preventScroll = inputInfo.input.options.preventTouchScrolling;
@@ -974,23 +995,22 @@ class TextScanner extends EventDispatcher {
}
}
- async _searchAtFromPen(e, x, y, eventType, prevent) {
+ async _searchAtFromTouchEnd(x, y, inputInfo) {
+ await this._searchAt(x, y, inputInfo);
+ }
+
+ async _searchAtFromPen(e, eventType, prevent) {
if (this._pendingLookup) { return; }
const inputInfo = this._getMatchingInputGroupFromEvent('pen', eventType, e);
if (inputInfo === null) { return; }
- const {input: {options}} = inputInfo;
- if (
- (!options.scanOnPenRelease && this._penPointerReleased) ||
- !(this._penPointerPressed ? options.scanOnPenPress : options.scanOnPenHover)
- ) {
- return;
- }
+ const {options} = inputInfo.input;
+ if (!this._isPenEventSupported(eventType, options)) { return; }
- const preventScroll = inputInfo.input.options.preventTouchScrolling;
+ const preventScroll = options.preventPenScrolling;
- await this._searchAt(x, y, inputInfo);
+ await this._searchAt(e.clientX, e.clientY, inputInfo);
if (
prevent &&
@@ -1003,6 +1023,25 @@ class TextScanner extends EventDispatcher {
}
}
+ _isPenEventSupported(eventType, options) {
+ switch (eventType) {
+ case 'pointerDown':
+ return options.scanOnPenPress;
+ case 'pointerUp':
+ return options.scanOnPenRelease;
+ }
+ switch (this._penPointerState) {
+ case 1: // hovering
+ return options.scanOnPenHover;
+ case 2: // touching
+ return options.scanOnPenMove;
+ case 3: // hovering after touching
+ return options.scanOnPenReleaseHover;
+ default: // not active
+ return false;
+ }
+ }
+
_getMatchingInputGroupFromEvent(pointerType, eventType, event) {
const modifiers = DocumentUtil.getActiveModifiersAndButtons(event);
const modifierKeys = DocumentUtil.getActiveModifiers(event);
diff --git a/ext/js/pages/settings/scan-inputs-controller.js b/ext/js/pages/settings/scan-inputs-controller.js
index 7b363b9a..855ccf9a 100644
--- a/ext/js/pages/settings/scan-inputs-controller.js
+++ b/ext/js/pages/settings/scan-inputs-controller.js
@@ -150,10 +150,15 @@ class ScanInputsController {
searchTerms: true,
searchKanji: true,
scanOnTouchMove: true,
+ scanOnTouchPress: true,
+ scanOnTouchRelease: false,
+ scanOnPenMove: true,
scanOnPenHover: true,
+ scanOnPenReleaseHover: false,
scanOnPenPress: true,
scanOnPenRelease: false,
- preventTouchScrolling: true
+ preventTouchScrolling: true,
+ preventPenScrolling: true
}
};
}
diff --git a/ext/settings.html b/ext/settings.html
index 64246fd6..ec9dd34b 100644
--- a/ext/settings.html
+++ b/ext/settings.html
@@ -2934,16 +2934,28 @@
</label>
</div>
- <div class="scan-input-prefix-cell scan-input-options-cell scan-input-advanced-only" data-property="touch-pen-options"><span>Touch &amp; pen:</span></div>
- <div class="scan-input-content-cell scan-input-options-cell scan-input-advanced-only" data-property="touch-pen-options">
+ <div class="scan-input-prefix-cell scan-input-options-cell scan-input-advanced-only" data-property="touch-options"><span>Touch options:</span></div>
+ <div class="scan-input-content-cell scan-input-options-cell scan-input-advanced-only" data-property="touch-options">
+ <label class="scan-input-checkbox-item">
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnTouchPress"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Scan on touch press</span>
+ </label>
+ <label class="scan-input-checkbox-item">
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnTouchRelease"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Scan on touch release</span>
+ </label>
<label class="scan-input-checkbox-item">
<label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnTouchMove"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
<span>Scan on touch move</span>
</label>
<label class="scan-input-checkbox-item">
- <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnPenHover"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
- <span>Scan on pen hover</span>
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.preventTouchScrolling"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Prevent touch scrolling</span>
</label>
+ </div>
+
+ <div class="scan-input-prefix-cell scan-input-options-cell scan-input-advanced-only" data-property="pen-options"><span>Pen options:</span></div>
+ <div class="scan-input-content-cell scan-input-options-cell scan-input-advanced-only" data-property="pen-options">
<label class="scan-input-checkbox-item">
<label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnPenPress"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
<span>Scan on pen press</span>
@@ -2953,8 +2965,20 @@
<span>Scan on pen release</span>
</label>
<label class="scan-input-checkbox-item">
- <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.preventTouchScrolling"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
- <span>Prevent touch/pen scrolling</span>
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnPenMove"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Scan on pen move (while touched)</span>
+ </label>
+ <label class="scan-input-checkbox-item">
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnPenHover"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Scan on pen hover (before touched)</span>
+ </label>
+ <label class="scan-input-checkbox-item">
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.scanOnPenReleaseHover"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Scan on pen hover (after touched)</span>
+ </label>
+ <label class="scan-input-checkbox-item">
+ <label class="checkbox"><input type="checkbox" class="scan-input-settings-checkbox" data-property="options.preventPenScrolling"><span class="checkbox-body"><span class="checkbox-fill"></span><span class="checkbox-border"></span><span class="checkbox-check"></span></span></label>
+ <span>Prevent pen scrolling</span>
</label>
</div>
</div>