Input type filters (#806)

* Add options for scanning input types

* Move buttons in layout, refactor CSS

* Add options for input types

* Use input type filters

* Add _getMatchingInputGroupFromEvent

* Use input filters for touch events
This commit is contained in:
toasted-nutbread 2020-09-11 14:13:52 -04:00 committed by GitHub
parent 18634dca1a
commit a1729eb9ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 142 additions and 33 deletions

View File

@ -133,10 +133,7 @@ html:root:not([data-options-general-result-output-mode=merge]) #dict-main-group
} }
.scan-input-table { .scan-input-table {
width: 100%; width: 100%;
} margin-bottom: 8px;
.scan-input-list:not(:empty)+#scan-input-add {
border-top-left-radius: 0;
border-top-right-radius: 0;
} }
.scan-input-index-cell { .scan-input-index-cell {
position: relative; position: relative;
@ -153,6 +150,7 @@ html:root:not([data-options-general-result-output-mode=merge]) #dict-main-group
background-color: #eee; background-color: #eee;
border: 1px solid #ccc; border: 1px solid #ccc;
border-top-left-radius: 4px; border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -174,22 +172,46 @@ html:root:not([data-options-general-result-output-mode=merge]) #dict-main-group
.scan-input-input-cell { .scan-input-input-cell {
width: 100%; width: 100%;
} }
.scan-input-input-cell>input { .scan-input-input-cell-inner {
display: flex;
}
.scan-input-input-cell-inner .form-control,
.scan-input-input-cell-inner button {
border-radius: 0; border-radius: 0;
} }
.scan-input-mouse-button-cell>button { .scan-input-input-cell-inner button {
border-radius: 0; padding-left: 10px;
padding-right: 10px;
}
.scan-input-input-cell-inner button>span {
width: 20px;
} }
.scan-input-remove-button-cell>button { .scan-input-remove-button-cell>button {
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
} }
.scan-input:nth-child(n+2) .scan-input-index { .scan-input tr:last-of-type .scan-input-input-cell-inner button:last-of-type,
border-top-left-radius: 0; .scan-input tr:last-of-type .scan-input-input-cell-inner .form-control:last-of-type {
}
.scan-input:last-child tr:last-of-type .scan-input-mouse-button-cell>button {
border-bottom-right-radius: 4px; border-bottom-right-radius: 4px;
} }
.scan-input-type-list {
display: flex;
}
.scan-input-type {
font-weight: normal;
margin: 0;
}
.scan-input-type+.scan-input-type {
margin-left: 1em;
}
.scan-input-type>input[type=checkbox] {
margin: 0 0.375em 0 0;
padding: 0;
vertical-align: middle;
}
.scan-input-type>span {
vertical-align: middle;
}
.generic-input-list { .generic-input-list {
counter-reset: generic-input-id; counter-reset: generic-input-id;

View File

@ -341,13 +341,28 @@
"default": [ "default": [
{ {
"include": "shift", "include": "shift",
"exclude": "" "exclude": "",
"types": {
"mouse": true,
"touch": false,
"pen": false
}
},
{
"include": "",
"exclude": "",
"types": {
"mouse": false,
"touch": true,
"pen": true
}
} }
], ],
"items": { "items": {
"required": [ "required": [
"include", "include",
"exclude" "exclude",
"types"
], ],
"properties": { "properties": {
"include": { "include": {
@ -357,6 +372,28 @@
"exclude": { "exclude": {
"type": "string", "type": "string",
"default": "" "default": ""
},
"types": {
"type": "object",
"required": [
"mouse",
"touch",
"pen"
],
"properties": {
"mouse": {
"type": "boolean",
"default": true
},
"touch": {
"type": "boolean",
"default": true
},
"pen": {
"type": "boolean",
"default": true
}
}
} }
} }
} }

View File

@ -491,7 +491,7 @@ class OptionsUtil {
profileOptions.general.usePopupWindow = false; profileOptions.general.usePopupWindow = false;
profileOptions.scanning.hideDelay = 0; profileOptions.scanning.hideDelay = 0;
const {modifier, middleMouse} = profileOptions.scanning; const {modifier, middleMouse, touchInputEnabled} = profileOptions.scanning;
const scanningInputs = []; const scanningInputs = [];
let modifierInput = ''; let modifierInput = '';
switch (modifier) { switch (modifier) {
@ -507,12 +507,21 @@ class OptionsUtil {
} }
scanningInputs.push({ scanningInputs.push({
include: modifierInput, include: modifierInput,
exclude: '' exclude: '',
types: {mouse: true, touch: false, pen: false}
}); });
if (middleMouse) { if (middleMouse) {
scanningInputs.push({ scanningInputs.push({
include: 'mouse2', include: 'mouse2',
exclude: '' exclude: '',
types: {mouse: true, touch: false, pen: false}
});
}
if (touchInputEnabled) {
scanningInputs.push({
include: '',
exclude: '',
types: {mouse: false, touch: true, pen: true}
}); });
} }
profileOptions.scanning.inputs = scanningInputs; profileOptions.scanning.inputs = scanningInputs;

View File

@ -142,6 +142,11 @@ class ScanInputField {
this._eventListeners.on(this._includeInputField, 'change', this._onIncludeValueChange.bind(this)); this._eventListeners.on(this._includeInputField, 'change', this._onIncludeValueChange.bind(this));
this._eventListeners.on(this._excludeInputField, 'change', this._onExcludeValueChange.bind(this)); this._eventListeners.on(this._excludeInputField, 'change', this._onExcludeValueChange.bind(this));
this._eventListeners.addEventListener(removeButton, 'click', this._onRemoveClick.bind(this)); this._eventListeners.addEventListener(removeButton, 'click', this._onRemoveClick.bind(this));
for (const typeCheckbox of node.querySelectorAll('.scan-input-type-checkbox')) {
const {type} = typeCheckbox.dataset;
typeCheckbox.dataset.setting = `scanning.inputs[${this._index}].types.${type}`;
}
} }
cleanup() { cleanup() {

View File

@ -436,16 +436,31 @@
<template id="scan-input-template"><div class="scan-input"> <template id="scan-input-template"><div class="scan-input">
<table class="scan-input-table"><tbody> <table class="scan-input-table"><tbody>
<tr class="scan-input-include"> <tr class="scan-input-include">
<td class="scan-input-index-cell" rowspan="2"><div class="scan-input-index"></div></td> <td class="scan-input-index-cell" rowspan="3"><div class="scan-input-index"></div></td>
<td class="scan-input-prefix-cell"><div class="scan-input-prefix">Include</div></td> <td class="scan-input-prefix-cell"><div class="scan-input-prefix">Include</div></td>
<td class="scan-input-input-cell"><input type="text" class="form-control scan-input-field" placeholder="No inputs"></td> <td class="scan-input-input-cell"><div class="scan-input-input-cell-inner">
<td class="scan-input-mouse-button-cell"><button class="btn btn-default mouse-button" title="Mouse button"><span class="mouse-button-icon"></span></button></td> <input type="text" class="form-control scan-input-field" placeholder="No inputs">
<button class="btn btn-default mouse-button" title="Mouse button"><span class="mouse-button-icon"></span></button>
</div></td>
<td class="scan-input-remove-button-cell"><button class="btn btn-danger scan-input-remove" title="Remove"><span class="glyphicon glyphicon-remove"></span></button></td> <td class="scan-input-remove-button-cell"><button class="btn btn-danger scan-input-remove" title="Remove"><span class="glyphicon glyphicon-remove"></span></button></td>
</tr> </tr>
<tr class="scan-input-exclude"> <tr class="scan-input-exclude">
<td class="scan-input-prefix-cell"><div class="scan-input-prefix">Exclude</div></td> <td class="scan-input-prefix-cell"><div class="scan-input-prefix">Exclude</div></td>
<td class="scan-input-input-cell"><input type="text" class="form-control scan-input-field" placeholder="No inputs"></td> <td class="scan-input-input-cell"><div class="scan-input-input-cell-inner">
<td class="scan-input-mouse-button-cell"><button class="btn btn-default mouse-button" title="Mouse button"><span class="mouse-button-icon"></span></button></td> <input type="text" class="form-control scan-input-field" placeholder="No inputs">
<button class="btn btn-default mouse-button" title="Mouse button"><span class="mouse-button-icon"></span></button>
</div></td>
<td class="scan-input-empty-cell"></td>
</tr>
<tr class="scan-input-types">
<td class="scan-input-prefix-cell"><div class="scan-input-prefix">Types</div></td>
<td class="scan-input-input-cell"><div class="scan-input-input-cell-inner">
<div class="form-control scan-input-type-list">
<label class="scan-input-type"><input type="checkbox" class="scan-input-type-checkbox" data-type="mouse"><span>Mouse</span></label>
<label class="scan-input-type"><input type="checkbox" class="scan-input-type-checkbox" data-type="touch"><span>Touch</span></label>
<label class="scan-input-type"><input type="checkbox" class="scan-input-type-checkbox" data-type="pen"><span>Pen</span></label>
</div>
</div></td>
<td class="scan-input-empty-cell"></td> <td class="scan-input-empty-cell"></td>
</tr> </tr>
</tbody></table> </tbody></table>

View File

@ -95,9 +95,10 @@ class TextScanner extends EventDispatcher {
setOptions({inputs, deepContentScan, selectText, delay, touchInputEnabled, scanLength, sentenceExtent, layoutAwareScan}) { setOptions({inputs, deepContentScan, selectText, delay, touchInputEnabled, scanLength, sentenceExtent, layoutAwareScan}) {
if (Array.isArray(inputs)) { if (Array.isArray(inputs)) {
this._inputs = inputs.map(({include, exclude}) => ({ this._inputs = inputs.map(({include, exclude, types}) => ({
include: this._getInputArray(include), include: this._getInputArray(include),
exclude: this._getInputArray(exclude) exclude: this._getInputArray(exclude),
types: this._getInputTypeSet(types)
})); }));
} }
if (typeof deepContentScan === 'boolean') { if (typeof deepContentScan === 'boolean') {
@ -241,10 +242,7 @@ class TextScanner extends EventDispatcher {
return; return;
} }
const modifiers = DocumentUtil.getActiveModifiersAndButtons(e); const inputInfo = this._getMatchingInputGroupFromEvent(e, 'mouse');
this.trigger('activeModifiersChanged', {modifiers});
const inputInfo = this._getMatchingInputGroup(modifiers);
if (inputInfo === null) { return; } if (inputInfo === null) { return; }
const {index, empty} = inputInfo; const {index, empty} = inputInfo;
@ -313,7 +311,7 @@ class TextScanner extends EventDispatcher {
this._primaryTouchIdentifier = primaryTouch.identifier; this._primaryTouchIdentifier = primaryTouch.identifier;
this._searchAtFromTouchStart(primaryTouch.clientX, primaryTouch.clientY); this._searchAtFromTouchStart(e, primaryTouch.clientX, primaryTouch.clientY);
} }
_onTouchEnd(e) { _onTouchEnd(e) {
@ -345,7 +343,11 @@ class TextScanner extends EventDispatcher {
return; return;
} }
this._searchAt(primaryTouch.clientX, primaryTouch.clientY, {cause: 'touchMove', index: -1, empty: false}); const inputInfo = this._getMatchingInputGroupFromEvent(e, 'touch');
if (inputInfo === null) { return; }
const {index, empty} = inputInfo;
this._searchAt(primaryTouch.clientX, primaryTouch.clientY, {cause: 'touchMove', index, empty});
e.preventDefault(); // Disable scroll e.preventDefault(); // Disable scroll
} }
@ -496,12 +498,16 @@ class TextScanner extends EventDispatcher {
await this._searchAt(x, y, {cause: 'mouse', index: inputIndex, empty: inputEmpty}); await this._searchAt(x, y, {cause: 'mouse', index: inputIndex, empty: inputEmpty});
} }
async _searchAtFromTouchStart(x, y) { async _searchAtFromTouchStart(e, x, y) {
if (this._pendingLookup) { return; } if (this._pendingLookup) { return; }
const inputInfo = this._getMatchingInputGroupFromEvent(e, 'touch');
if (inputInfo === null) { return; }
const {index, empty} = inputInfo;
const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null; const textSourceCurrentPrevious = this._textSourceCurrent !== null ? this._textSourceCurrent.clone() : null;
await this._searchAt(x, y, {cause: 'touchStart', index: -1, empty: false}); await this._searchAt(x, y, {cause: 'touchStart', index, empty});
if ( if (
this._textSourceCurrent !== null && this._textSourceCurrent !== null &&
@ -513,11 +519,18 @@ class TextScanner extends EventDispatcher {
} }
} }
_getMatchingInputGroup(modifiers) { _getMatchingInputGroupFromEvent(event, type) {
const modifiers = DocumentUtil.getActiveModifiersAndButtons(event);
this.trigger('activeModifiersChanged', {modifiers});
return this._getMatchingInputGroup(modifiers, type);
}
_getMatchingInputGroup(modifiers, type) {
let fallback = null; let fallback = null;
for (let i = 0, ii = this._inputs.length; i < ii; ++i) { for (let i = 0, ii = this._inputs.length; i < ii; ++i) {
const input = this._inputs[i]; const input = this._inputs[i];
const {include, exclude} = input; const {include, exclude, types} = input;
if (!types.has(type)) { continue; }
if (this._setHasAll(modifiers, include) && (exclude.length === 0 || !this._setHasAll(modifiers, exclude))) { if (this._setHasAll(modifiers, include) && (exclude.length === 0 || !this._setHasAll(modifiers, exclude))) {
if (include.length > 0) { if (include.length > 0) {
return {index: i, empty: false, input}; return {index: i, empty: false, input};
@ -545,4 +558,12 @@ class TextScanner extends EventDispatcher {
[] []
); );
} }
_getInputTypeSet({mouse, touch, pen}) {
const set = new Set();
if (mouse) { set.add('mouse'); }
if (touch) { set.add('touch'); }
if (pen) { set.add('pen'); }
return set;
}
} }