mirror of
https://github.com/google/blockly.git
synced 2026-01-04 23:50:12 +01:00
* chore: remove deprecated functionality in events files * chore: remove deprecated items in renderers * chore: remove deprecated items in core * chore: remove mixin deprecation * chore: fix tests after removing deprecations
157 lines
4.7 KiB
TypeScript
157 lines
4.7 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import * as goog from '../closure/goog/goog.js';
|
|
goog.declareModuleId('Blockly.Touch');
|
|
|
|
import type {Gesture} from './gesture.js';
|
|
|
|
/** Length in ms for a touch to become a long press. */
|
|
const LONGPRESS = 750;
|
|
|
|
/**
|
|
* Whether touch is enabled in the browser.
|
|
* Copied from Closure's goog.events.BrowserFeature.TOUCH_ENABLED
|
|
*/
|
|
export const TOUCH_ENABLED =
|
|
'ontouchstart' in globalThis ||
|
|
!!(
|
|
globalThis['document'] &&
|
|
document.documentElement &&
|
|
'ontouchstart' in document.documentElement
|
|
) || // IE10 uses non-standard touch events,
|
|
// so it has a different check.
|
|
!!(
|
|
globalThis['navigator'] &&
|
|
(globalThis['navigator']['maxTouchPoints'] ||
|
|
(globalThis['navigator'] as any)['msMaxTouchPoints'])
|
|
);
|
|
|
|
/** Which touch events are we currently paying attention to? */
|
|
let touchIdentifier_: string | null = null;
|
|
|
|
/**
|
|
* The TOUCH_MAP lookup dictionary specifies additional touch events to fire,
|
|
* in conjunction with mouse events.
|
|
*/
|
|
export const TOUCH_MAP: {[key: string]: string[]} = {
|
|
'mousedown': ['pointerdown'],
|
|
'mouseenter': ['pointerenter'],
|
|
'mouseleave': ['pointerleave'],
|
|
'mousemove': ['pointermove'],
|
|
'mouseout': ['pointerout'],
|
|
'mouseover': ['pointerover'],
|
|
'mouseup': ['pointerup', 'pointercancel'],
|
|
'touchend': ['pointerup'],
|
|
'touchcancel': ['pointercancel'],
|
|
};
|
|
|
|
/** PID of queued long-press task. */
|
|
let longPid_: AnyDuringMigration = 0;
|
|
|
|
/**
|
|
* Context menus on touch devices are activated using a long-press.
|
|
* Unfortunately the contextmenu touch event is currently (2015) only supported
|
|
* by Chrome. This function is fired on any touchstart event, queues a task,
|
|
* which after about a second opens the context menu. The tasks is killed
|
|
* if the touch event terminates early.
|
|
*
|
|
* @param e Touch start event.
|
|
* @param gesture The gesture that triggered this longStart.
|
|
* @internal
|
|
*/
|
|
export function longStart(e: PointerEvent, gesture: Gesture) {
|
|
longStop();
|
|
longPid_ = setTimeout(function () {
|
|
// Let the gesture route the right-click correctly.
|
|
if (gesture) {
|
|
gesture.handleRightClick(e);
|
|
}
|
|
}, LONGPRESS);
|
|
}
|
|
|
|
/**
|
|
* Nope, that's not a long-press. Either touchend or touchcancel was fired,
|
|
* or a drag hath begun. Kill the queued long-press task.
|
|
*
|
|
* @internal
|
|
*/
|
|
export function longStop() {
|
|
if (longPid_) {
|
|
clearTimeout(longPid_);
|
|
longPid_ = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear the touch identifier that tracks which touch stream to pay attention
|
|
* to. This ends the current drag/gesture and allows other pointers to be
|
|
* captured.
|
|
*/
|
|
export function clearTouchIdentifier() {
|
|
touchIdentifier_ = null;
|
|
}
|
|
|
|
/**
|
|
* Decide whether Blockly should handle or ignore this event.
|
|
* Mouse and touch events require special checks because we only want to deal
|
|
* with one touch stream at a time. All other events should always be handled.
|
|
*
|
|
* @param e The event to check.
|
|
* @returns True if this event should be passed through to the registered
|
|
* handler; false if it should be blocked.
|
|
*/
|
|
export function shouldHandleEvent(e: Event): boolean {
|
|
// Do not replace the startsWith with a check for `instanceof PointerEvent`.
|
|
// `click` and `contextmenu` are PointerEvents in some browsers,
|
|
// despite not starting with `pointer`, but we want to always handle them
|
|
// without worrying about touch identifiers.
|
|
return (
|
|
!e.type.startsWith('pointer') ||
|
|
(e instanceof PointerEvent && checkTouchIdentifier(e))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the pointer identifier from the given event.
|
|
*
|
|
* @param e Pointer event.
|
|
* @returns The pointerId of the event.
|
|
*/
|
|
export function getTouchIdentifierFromEvent(e: PointerEvent): string {
|
|
return `${e.pointerId}`;
|
|
}
|
|
|
|
/**
|
|
* Check whether the pointer identifier on the event matches the current saved
|
|
* identifier. If the current identifier was unset, save the identifier from
|
|
* the event. This starts a drag/gesture, during which pointer events with
|
|
* other identifiers will be silently ignored.
|
|
*
|
|
* @param e Pointer event.
|
|
* @returns Whether the identifier on the event matches the current saved
|
|
* identifier.
|
|
*/
|
|
export function checkTouchIdentifier(e: PointerEvent): boolean {
|
|
const identifier = getTouchIdentifierFromEvent(e);
|
|
|
|
if (touchIdentifier_) {
|
|
// We're already tracking some touch/mouse event. Is this from the same
|
|
// source?
|
|
return touchIdentifier_ === identifier;
|
|
}
|
|
if (e.type === 'pointerdown') {
|
|
// No identifier set yet, and this is the start of a drag. Set it and
|
|
// return.
|
|
touchIdentifier_ = identifier;
|
|
return true;
|
|
}
|
|
// There was no identifier yet, but this wasn't a start event so we're going
|
|
// to ignore it. This probably means that another drag finished while this
|
|
// pointer was down.
|
|
return false;
|
|
}
|