META-INF.dirigible.dev-tools.input.InputModel.js Maven / Gradle / Ivy
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import * as SDK from '../sdk/sdk.js';
export class InputModel extends SDK.SDKModel.SDKModel {
/**
* @param {!SDK.SDKModel.Target} target
*/
constructor(target) {
super(target);
this._inputAgent = target.inputAgent();
/** @type {?number} */
this._eventDispatchTimer = null;
/** @type {!Array}*/
this._dispatchEventDataList = [];
/** @type {?function()} */
this._finishCallback = null;
this._reset();
}
_reset() {
/** @type {?number} */
this._lastEventTime = null;
/** @type {boolean} */
this._replayPaused = false;
/** @type {number} */
this._dispatchingIndex = 0;
clearTimeout(this._eventDispatchTimer);
}
/**
* @param {!SDK.TracingModel.TracingModel} tracingModel
*/
setEvents(tracingModel) {
this._dispatchEventDataList = [];
for (const process of tracingModel.sortedProcesses()) {
for (const thread of process.sortedThreads()) {
this._processThreadEvents(tracingModel, thread);
}
}
function compareTimestamp(a, b) {
return a.timestamp - b.timestamp;
}
this._dispatchEventDataList.sort(compareTimestamp);
}
/**
* @param {?function()} finishCallback
*/
startReplay(finishCallback) {
this._reset();
this._finishCallback = finishCallback;
if (this._dispatchEventDataList.length) {
this._dispatchNextEvent();
} else {
this._replayStopped();
}
}
pause() {
clearTimeout(this._eventDispatchTimer);
if (this._dispatchingIndex >= this._dispatchEventDataList.length) {
this._replayStopped();
} else {
this._replayPaused = true;
}
}
resume() {
this._replayPaused = false;
if (this._dispatchingIndex < this._dispatchEventDataList.length) {
this._dispatchNextEvent();
}
}
/**
* @param {!SDK.TracingModel.TracingModel} tracingModel
* @param {!SDK.TracingModel.Thread} thread
*/
_processThreadEvents(tracingModel, thread) {
for (const event of thread.events()) {
if (event.name === 'EventDispatch' && this._isValidInputEvent(event.args.data)) {
this._dispatchEventDataList.push(event.args.data);
}
}
}
/**
* @param {!EventData} eventData
* @return {boolean}
*/
_isValidInputEvent(eventData) {
return this._isMouseEvent(/** @type {!MouseEventData} */ (eventData)) ||
this._isKeyboardEvent(/** @type {!KeyboardEventData} */ (eventData));
}
/**
* @param {!MouseEventData} eventData
* @return {boolean}
*/
_isMouseEvent(eventData) {
if (!InputModel.MouseEventTypes.has(eventData.type)) {
return false;
}
if (!('x' in eventData && 'y' in eventData)) {
return false;
}
return true;
}
/**
* @param {!KeyboardEventData} eventData
* @return {boolean}
*/
_isKeyboardEvent(eventData) {
if (!InputModel.KeyboardEventTypes.has(eventData.type)) {
return false;
}
if (!('code' in eventData && 'key' in eventData)) {
return false;
}
return true;
}
_dispatchNextEvent() {
const eventData = this._dispatchEventDataList[this._dispatchingIndex];
this._lastEventTime = eventData.timestamp;
if (InputModel.MouseEventTypes.has(eventData.type)) {
this._dispatchMouseEvent(/** @type {!MouseEventData} */ (eventData));
} else if (InputModel.KeyboardEventTypes.has(eventData.type)) {
this._dispatchKeyEvent(/** @type {!KeyboardEventData} */ (eventData));
}
++this._dispatchingIndex;
if (this._dispatchingIndex < this._dispatchEventDataList.length) {
const waitTime = (this._dispatchEventDataList[this._dispatchingIndex].timestamp - this._lastEventTime) / 1000;
this._eventDispatchTimer = setTimeout(this._dispatchNextEvent.bind(this), waitTime);
} else {
this._replayStopped();
}
}
/**
* @param {!MouseEventData} eventData
*/
async _dispatchMouseEvent(eventData) {
console.assert(InputModel.MouseEventTypes.has(eventData.type));
const buttons = {0: 'left', 1: 'middle', 2: 'right', 3: 'back', 4: 'forward'};
const params = {
type: InputModel.MouseEventTypes.get(eventData.type),
x: eventData.x,
y: eventData.y,
modifiers: eventData.modifiers,
button: (eventData.type === 'mousedown' || eventData.type === 'mouseup') ? buttons[eventData.button] : 'none',
buttons: eventData.buttons,
clickCount: eventData.clickCount,
deltaX: eventData.deltaX,
deltaY: eventData.deltaY
};
await this._inputAgent.invoke_dispatchMouseEvent(params);
}
/**
* @param {!KeyboardEventData} eventData
*/
async _dispatchKeyEvent(eventData) {
console.assert(InputModel.KeyboardEventTypes.has(eventData.type));
const text = eventData.type === 'keypress' ? eventData.key[0] : undefined;
const params = {
type: InputModel.KeyboardEventTypes.get(eventData.type),
modifiers: eventData.modifiers,
text: text,
unmodifiedText: text ? text.toLowerCase() : undefined,
code: eventData.code,
key: eventData.key
};
await this._inputAgent.invoke_dispatchKeyEvent(params);
}
_replayStopped() {
clearTimeout(this._eventDispatchTimer);
this._reset();
this._finishCallback();
}
}
InputModel.MouseEventTypes = new Map([
['mousedown', 'mousePressed'], ['mouseup', 'mouseReleased'], ['mousemove', 'mouseMoved'], ['wheel', 'mouseWheel']
]);
InputModel.KeyboardEventTypes = new Map([['keydown', 'keyDown'], ['keyup', 'keyUp'], ['keypress', 'char']]);
SDK.SDKModel.SDKModel.register(InputModel, SDK.SDKModel.Capability.Input, false);
/** @typedef {{type: string, modifiers: number, timestamp: number}} */
export let EventData;
/** @typedef {{x: number, y: number, button: number, buttons: number, clickCount: number, deltaX: number, deltaY: number}} */
export let MouseEventData;
/** @typedef {{code: string, key: string, modifiers: number}} */
export let KeyboardEventData;
© 2015 - 2025 Weber Informatics LLC | Privacy Policy