/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** * Simulate touch events for platforms where they aren't generally available.
*/ class TouchSimulator { /** * @param {ChromeEventHandler} simulatorTarget: The object we'll use to listen for click * and touch events to handle.
*/
constructor(simulatorTarget) { this.simulatorTarget = simulatorTarget; this._currentPickerMap = new Map();
}
enabled = false;
start() { if (this.enabled) { // Simulator is already started return;
}
EVENTS_TO_HANDLE.forEach(evt => { // Only listen trusted events to prevent messing with // event dispatched manually within content documents this.simulatorTarget.addEventListener(evt, this, true, false);
});
/** * Set the state value for one of DevTools pickers (either eyedropper or * element picker). * If any content picker is currently active, we should not be emulating * touch events. Otherwise it is ok to emulate touch events. * In theory only one picker can ever be active at a time, but tracking the * different pickers independantly avoids race issues in the client code. * * @param {Boolean} state * True if the picker is currently active, false otherwise. * @param {String} pickerType * One of PICKER_TYPES.
*/
setElementPickerState(state, pickerType) { if (!Object.values(PICKER_TYPES).includes(pickerType)) { thrownew Error( "Unsupported type in setElementPickerState: " + pickerType
);
} this._currentPickerMap.set(pickerType, state);
}
// eslint-disable-next-line complexity
handleEvent(evt) { // Bail out if devtools is in pick mode in the same tab. if (this._isPicking()) { return;
}
const content = this.getContent(evt.target); if (!content) { return;
}
// App touchstart & touchend should also be dispatched on the system app // to match on-device behavior. if (evt.type.startsWith("touch")) { const sysFrame = content.realFrameElement; if (!sysFrame) { return;
} const sysDocument = sysFrame.ownerDocument; const sysWindow = sysDocument.defaultView;
// Ignore all but real mouse event coming from physical mouse // (especially ignore mouse event being dispatched from a touch event) if (
evt.button ||
evt.inputSource != evt.MOZ_SOURCE_MOUSE ||
evt.isSynthesized
) { return;
}
const eventTarget = this.target;
let type = ""; switch (evt.type) { case"mouseenter": case"mouseover": case"mouseout": case"mouseleave": // Don't propagate events which are not related to touch events
evt.stopPropagation();
evt.preventDefault();
// We don't want to trigger any visual changes to elements whose content can // be modified via hover states. We can avoid this by removing the element's // content state.
InspectorUtils.removeContentState(evt.target, kStateHover); break;
case"mousedown": this.target = evt.target;
// If the click-hold feature is enabled, start a timeout to convert long clicks // into contextmenu events. // Just don't do it if the event occurred on a scrollbar. if (isClickHoldEnabled && !evt.originalTarget.closest("scrollbar")) { this._contextMenuTimeout = this.sendContextMenu(evt);
}
this.startX = evt.pageX; this.startY = evt.pageY;
type = "touchstart"; break;
case"mousemove": if (!eventTarget) { // Don't propagate mousemove event when touchstart event isn't fired
evt.stopPropagation(); return;
}
type = "touchmove"; break;
case"mouseup": if (!eventTarget) { return;
} this.target = null;
content.clearTimeout(this._contextMenuTimeout);
type = "touchend";
// Only register click listener after mouseup to ensure // catching only real user click. (Especially ignore click // being dispatched on form submit) if (evt.detail == 1) { this.simulatorTarget.addEventListener("click", this, {
capture: true,
once: true,
});
} break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.