11cb0ef41Sopenharmony_ci(function() { 21cb0ef41Sopenharmony_ci let sourceNameIdx = 0; 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ci /** 51cb0ef41Sopenharmony_ci * @class 61cb0ef41Sopenharmony_ci * Builder for creating a sequence of actions 71cb0ef41Sopenharmony_ci * 81cb0ef41Sopenharmony_ci * 91cb0ef41Sopenharmony_ci * The actions are dispatched once 101cb0ef41Sopenharmony_ci * :js:func:`test_driver.Actions.send` is called. This returns a 111cb0ef41Sopenharmony_ci * promise which resolves once the actions are complete. 121cb0ef41Sopenharmony_ci * 131cb0ef41Sopenharmony_ci * The other methods on :js:class:`test_driver.Actions` object are 141cb0ef41Sopenharmony_ci * used to build the sequence of actions that will be sent. These 151cb0ef41Sopenharmony_ci * return the `Actions` object itself, so the actions sequence can 161cb0ef41Sopenharmony_ci * be constructed by chaining method calls. 171cb0ef41Sopenharmony_ci * 181cb0ef41Sopenharmony_ci * Internally :js:func:`test_driver.Actions.send` invokes 191cb0ef41Sopenharmony_ci * :js:func:`test_driver.action_sequence`. 201cb0ef41Sopenharmony_ci * 211cb0ef41Sopenharmony_ci * @example 221cb0ef41Sopenharmony_ci * let text_box = document.getElementById("text"); 231cb0ef41Sopenharmony_ci * 241cb0ef41Sopenharmony_ci * let actions = new test_driver.Actions() 251cb0ef41Sopenharmony_ci * .pointerMove(0, 0, {origin: text_box}) 261cb0ef41Sopenharmony_ci * .pointerDown() 271cb0ef41Sopenharmony_ci * .pointerUp() 281cb0ef41Sopenharmony_ci * .addTick() 291cb0ef41Sopenharmony_ci * .keyDown("p") 301cb0ef41Sopenharmony_ci * .keyUp("p"); 311cb0ef41Sopenharmony_ci * 321cb0ef41Sopenharmony_ci * await actions.send(); 331cb0ef41Sopenharmony_ci * 341cb0ef41Sopenharmony_ci * @param {number} [defaultTickDuration] - The default duration of a 351cb0ef41Sopenharmony_ci * tick. Be default this is set ot 16ms, which is one frame time 361cb0ef41Sopenharmony_ci * based on 60Hz display. 371cb0ef41Sopenharmony_ci */ 381cb0ef41Sopenharmony_ci function Actions(defaultTickDuration=16) { 391cb0ef41Sopenharmony_ci this.sourceTypes = new Map([["key", KeySource], 401cb0ef41Sopenharmony_ci ["pointer", PointerSource], 411cb0ef41Sopenharmony_ci ["wheel", WheelSource], 421cb0ef41Sopenharmony_ci ["none", GeneralSource]]); 431cb0ef41Sopenharmony_ci this.sources = new Map(); 441cb0ef41Sopenharmony_ci this.sourceOrder = []; 451cb0ef41Sopenharmony_ci for (let sourceType of this.sourceTypes.keys()) { 461cb0ef41Sopenharmony_ci this.sources.set(sourceType, new Map()); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci this.currentSources = new Map(); 491cb0ef41Sopenharmony_ci for (let sourceType of this.sourceTypes.keys()) { 501cb0ef41Sopenharmony_ci this.currentSources.set(sourceType, null); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci this.createSource("none"); 531cb0ef41Sopenharmony_ci this.tickIdx = 0; 541cb0ef41Sopenharmony_ci this.defaultTickDuration = defaultTickDuration; 551cb0ef41Sopenharmony_ci this.context = null; 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci Actions.prototype = { 591cb0ef41Sopenharmony_ci ButtonType: { 601cb0ef41Sopenharmony_ci LEFT: 0, 611cb0ef41Sopenharmony_ci MIDDLE: 1, 621cb0ef41Sopenharmony_ci RIGHT: 2, 631cb0ef41Sopenharmony_ci BACK: 3, 641cb0ef41Sopenharmony_ci FORWARD: 4, 651cb0ef41Sopenharmony_ci }, 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci /** 681cb0ef41Sopenharmony_ci * Generate the action sequence suitable for passing to 691cb0ef41Sopenharmony_ci * test_driver.action_sequence 701cb0ef41Sopenharmony_ci * 711cb0ef41Sopenharmony_ci * @returns {Array} Array of WebDriver-compatible actions sequences 721cb0ef41Sopenharmony_ci */ 731cb0ef41Sopenharmony_ci serialize: function() { 741cb0ef41Sopenharmony_ci let actions = []; 751cb0ef41Sopenharmony_ci for (let [sourceType, sourceName] of this.sourceOrder) { 761cb0ef41Sopenharmony_ci let source = this.sources.get(sourceType).get(sourceName); 771cb0ef41Sopenharmony_ci let serialized = source.serialize(this.tickIdx + 1, this.defaultTickDuration); 781cb0ef41Sopenharmony_ci if (serialized) { 791cb0ef41Sopenharmony_ci serialized.id = sourceName; 801cb0ef41Sopenharmony_ci actions.push(serialized); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci return actions; 841cb0ef41Sopenharmony_ci }, 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci /** 871cb0ef41Sopenharmony_ci * Generate and send the action sequence 881cb0ef41Sopenharmony_ci * 891cb0ef41Sopenharmony_ci * @returns {Promise} fulfilled after the sequence is executed, 901cb0ef41Sopenharmony_ci * rejected if any actions fail. 911cb0ef41Sopenharmony_ci */ 921cb0ef41Sopenharmony_ci send: function() { 931cb0ef41Sopenharmony_ci let actions; 941cb0ef41Sopenharmony_ci try { 951cb0ef41Sopenharmony_ci actions = this.serialize(); 961cb0ef41Sopenharmony_ci } catch(e) { 971cb0ef41Sopenharmony_ci return Promise.reject(e); 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci return test_driver.action_sequence(actions, this.context); 1001cb0ef41Sopenharmony_ci }, 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci /** 1031cb0ef41Sopenharmony_ci * Set the context for the actions 1041cb0ef41Sopenharmony_ci * 1051cb0ef41Sopenharmony_ci * @param {WindowProxy} context - Context in which to run the action sequence 1061cb0ef41Sopenharmony_ci */ 1071cb0ef41Sopenharmony_ci setContext: function(context) { 1081cb0ef41Sopenharmony_ci this.context = context; 1091cb0ef41Sopenharmony_ci return this; 1101cb0ef41Sopenharmony_ci }, 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci /** 1131cb0ef41Sopenharmony_ci * Get the action source with a particular source type and name. 1141cb0ef41Sopenharmony_ci * If no name is passed, a new source with the given type is 1151cb0ef41Sopenharmony_ci * created. 1161cb0ef41Sopenharmony_ci * 1171cb0ef41Sopenharmony_ci * @param {String} type - Source type ('none', 'key', 'pointer', or 'wheel') 1181cb0ef41Sopenharmony_ci * @param {String?} name - Name of the source 1191cb0ef41Sopenharmony_ci * @returns {Source} Source object for that source. 1201cb0ef41Sopenharmony_ci */ 1211cb0ef41Sopenharmony_ci getSource: function(type, name) { 1221cb0ef41Sopenharmony_ci if (!this.sources.has(type)) { 1231cb0ef41Sopenharmony_ci throw new Error(`${type} is not a valid action type`); 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci if (name === null || name === undefined) { 1261cb0ef41Sopenharmony_ci name = this.currentSources.get(type); 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci if (name === null || name === undefined) { 1291cb0ef41Sopenharmony_ci return this.createSource(type, null); 1301cb0ef41Sopenharmony_ci } 1311cb0ef41Sopenharmony_ci return this.sources.get(type).get(name); 1321cb0ef41Sopenharmony_ci }, 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci setSource: function(type, name) { 1351cb0ef41Sopenharmony_ci if (!this.sources.has(type)) { 1361cb0ef41Sopenharmony_ci throw new Error(`${type} is not a valid action type`); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci if (!this.sources.get(type).has(name)) { 1391cb0ef41Sopenharmony_ci throw new Error(`${name} is not a valid source for ${type}`); 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci this.currentSources.set(type, name); 1421cb0ef41Sopenharmony_ci return this; 1431cb0ef41Sopenharmony_ci }, 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci /** 1461cb0ef41Sopenharmony_ci * Add a new key input source with the given name 1471cb0ef41Sopenharmony_ci * 1481cb0ef41Sopenharmony_ci * @param {String} name - Name of the key source 1491cb0ef41Sopenharmony_ci * @param {Bool} set - Set source as the default key source 1501cb0ef41Sopenharmony_ci * @returns {Actions} 1511cb0ef41Sopenharmony_ci */ 1521cb0ef41Sopenharmony_ci addKeyboard: function(name, set=true) { 1531cb0ef41Sopenharmony_ci this.createSource("key", name); 1541cb0ef41Sopenharmony_ci if (set) { 1551cb0ef41Sopenharmony_ci this.setKeyboard(name); 1561cb0ef41Sopenharmony_ci } 1571cb0ef41Sopenharmony_ci return this; 1581cb0ef41Sopenharmony_ci }, 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci /** 1611cb0ef41Sopenharmony_ci * Set the current default key source 1621cb0ef41Sopenharmony_ci * 1631cb0ef41Sopenharmony_ci * @param {String} name - Name of the key source 1641cb0ef41Sopenharmony_ci * @returns {Actions} 1651cb0ef41Sopenharmony_ci */ 1661cb0ef41Sopenharmony_ci setKeyboard: function(name) { 1671cb0ef41Sopenharmony_ci this.setSource("key", name); 1681cb0ef41Sopenharmony_ci return this; 1691cb0ef41Sopenharmony_ci }, 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci /** 1721cb0ef41Sopenharmony_ci * Add a new pointer input source with the given name 1731cb0ef41Sopenharmony_ci * 1741cb0ef41Sopenharmony_ci * @param {String} type - Name of the pointer source 1751cb0ef41Sopenharmony_ci * @param {String} pointerType - Type of pointing device 1761cb0ef41Sopenharmony_ci * @param {Bool} set - Set source as the default pointer source 1771cb0ef41Sopenharmony_ci * @returns {Actions} 1781cb0ef41Sopenharmony_ci */ 1791cb0ef41Sopenharmony_ci addPointer: function(name, pointerType="mouse", set=true) { 1801cb0ef41Sopenharmony_ci this.createSource("pointer", name, {pointerType: pointerType}); 1811cb0ef41Sopenharmony_ci if (set) { 1821cb0ef41Sopenharmony_ci this.setPointer(name); 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci return this; 1851cb0ef41Sopenharmony_ci }, 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci /** 1881cb0ef41Sopenharmony_ci * Set the current default pointer source 1891cb0ef41Sopenharmony_ci * 1901cb0ef41Sopenharmony_ci * @param {String} name - Name of the pointer source 1911cb0ef41Sopenharmony_ci * @returns {Actions} 1921cb0ef41Sopenharmony_ci */ 1931cb0ef41Sopenharmony_ci setPointer: function(name) { 1941cb0ef41Sopenharmony_ci this.setSource("pointer", name); 1951cb0ef41Sopenharmony_ci return this; 1961cb0ef41Sopenharmony_ci }, 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci /** 1991cb0ef41Sopenharmony_ci * Add a new wheel input source with the given name 2001cb0ef41Sopenharmony_ci * 2011cb0ef41Sopenharmony_ci * @param {String} type - Name of the wheel source 2021cb0ef41Sopenharmony_ci * @param {Bool} set - Set source as the default wheel source 2031cb0ef41Sopenharmony_ci * @returns {Actions} 2041cb0ef41Sopenharmony_ci */ 2051cb0ef41Sopenharmony_ci addWheel: function(name, set=true) { 2061cb0ef41Sopenharmony_ci this.createSource("wheel", name); 2071cb0ef41Sopenharmony_ci if (set) { 2081cb0ef41Sopenharmony_ci this.setWheel(name); 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci return this; 2111cb0ef41Sopenharmony_ci }, 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci /** 2141cb0ef41Sopenharmony_ci * Set the current default wheel source 2151cb0ef41Sopenharmony_ci * 2161cb0ef41Sopenharmony_ci * @param {String} name - Name of the wheel source 2171cb0ef41Sopenharmony_ci * @returns {Actions} 2181cb0ef41Sopenharmony_ci */ 2191cb0ef41Sopenharmony_ci setWheel: function(name) { 2201cb0ef41Sopenharmony_ci this.setSource("wheel", name); 2211cb0ef41Sopenharmony_ci return this; 2221cb0ef41Sopenharmony_ci }, 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci createSource: function(type, name, parameters={}) { 2251cb0ef41Sopenharmony_ci if (!this.sources.has(type)) { 2261cb0ef41Sopenharmony_ci throw new Error(`${type} is not a valid action type`); 2271cb0ef41Sopenharmony_ci } 2281cb0ef41Sopenharmony_ci let sourceNames = new Set(); 2291cb0ef41Sopenharmony_ci for (let [_, name] of this.sourceOrder) { 2301cb0ef41Sopenharmony_ci sourceNames.add(name); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci if (!name) { 2331cb0ef41Sopenharmony_ci do { 2341cb0ef41Sopenharmony_ci name = "" + sourceNameIdx++; 2351cb0ef41Sopenharmony_ci } while (sourceNames.has(name)) 2361cb0ef41Sopenharmony_ci } else { 2371cb0ef41Sopenharmony_ci if (sourceNames.has(name)) { 2381cb0ef41Sopenharmony_ci throw new Error(`Alreay have a source of type ${type} named ${name}.`); 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci this.sources.get(type).set(name, new (this.sourceTypes.get(type))(parameters)); 2421cb0ef41Sopenharmony_ci this.currentSources.set(type, name); 2431cb0ef41Sopenharmony_ci this.sourceOrder.push([type, name]); 2441cb0ef41Sopenharmony_ci return this.sources.get(type).get(name); 2451cb0ef41Sopenharmony_ci }, 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci /** 2481cb0ef41Sopenharmony_ci * Insert a new actions tick 2491cb0ef41Sopenharmony_ci * 2501cb0ef41Sopenharmony_ci * @param {Number?} duration - Minimum length of the tick in ms. 2511cb0ef41Sopenharmony_ci * @returns {Actions} 2521cb0ef41Sopenharmony_ci */ 2531cb0ef41Sopenharmony_ci addTick: function(duration) { 2541cb0ef41Sopenharmony_ci this.tickIdx += 1; 2551cb0ef41Sopenharmony_ci if (duration) { 2561cb0ef41Sopenharmony_ci this.pause(duration); 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci return this; 2591cb0ef41Sopenharmony_ci }, 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci /** 2621cb0ef41Sopenharmony_ci * Add a pause to the current tick 2631cb0ef41Sopenharmony_ci * 2641cb0ef41Sopenharmony_ci * @param {Number?} duration - Minimum length of the tick in ms. 2651cb0ef41Sopenharmony_ci * @param {String} sourceType - source type 2661cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named key, pointer or wheel source to use 2671cb0ef41Sopenharmony_ci * or null for the default key, pointer or 2681cb0ef41Sopenharmony_ci * wheel source 2691cb0ef41Sopenharmony_ci * @returns {Actions} 2701cb0ef41Sopenharmony_ci */ 2711cb0ef41Sopenharmony_ci pause: function(duration=0, sourceType="none", {sourceName=null}={}) { 2721cb0ef41Sopenharmony_ci if (sourceType=="none") 2731cb0ef41Sopenharmony_ci this.getSource("none").addPause(this, duration); 2741cb0ef41Sopenharmony_ci else 2751cb0ef41Sopenharmony_ci this.getSource(sourceType, sourceName).addPause(this, duration); 2761cb0ef41Sopenharmony_ci return this; 2771cb0ef41Sopenharmony_ci }, 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci /** 2801cb0ef41Sopenharmony_ci * Create a keyDown event for the current default key source 2811cb0ef41Sopenharmony_ci * 2821cb0ef41Sopenharmony_ci * @param {String} key - Key to press 2831cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named key source to use or null for the default key source 2841cb0ef41Sopenharmony_ci * @returns {Actions} 2851cb0ef41Sopenharmony_ci */ 2861cb0ef41Sopenharmony_ci keyDown: function(key, {sourceName=null}={}) { 2871cb0ef41Sopenharmony_ci let source = this.getSource("key", sourceName); 2881cb0ef41Sopenharmony_ci source.keyDown(this, key); 2891cb0ef41Sopenharmony_ci return this; 2901cb0ef41Sopenharmony_ci }, 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci /** 2931cb0ef41Sopenharmony_ci * Create a keyDown event for the current default key source 2941cb0ef41Sopenharmony_ci * 2951cb0ef41Sopenharmony_ci * @param {String} key - Key to release 2961cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named key source to use or null for the default key source 2971cb0ef41Sopenharmony_ci * @returns {Actions} 2981cb0ef41Sopenharmony_ci */ 2991cb0ef41Sopenharmony_ci keyUp: function(key, {sourceName=null}={}) { 3001cb0ef41Sopenharmony_ci let source = this.getSource("key", sourceName); 3011cb0ef41Sopenharmony_ci source.keyUp(this, key); 3021cb0ef41Sopenharmony_ci return this; 3031cb0ef41Sopenharmony_ci }, 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci /** 3061cb0ef41Sopenharmony_ci * Create a pointerDown event for the current default pointer source 3071cb0ef41Sopenharmony_ci * 3081cb0ef41Sopenharmony_ci * @param {String} button - Button to press 3091cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named pointer source to use or null for the default 3101cb0ef41Sopenharmony_ci * pointer source 3111cb0ef41Sopenharmony_ci * @returns {Actions} 3121cb0ef41Sopenharmony_ci */ 3131cb0ef41Sopenharmony_ci pointerDown: function({button=this.ButtonType.LEFT, sourceName=null, 3141cb0ef41Sopenharmony_ci width, height, pressure, tangentialPressure, 3151cb0ef41Sopenharmony_ci tiltX, tiltY, twist, altitudeAngle, azimuthAngle}={}) { 3161cb0ef41Sopenharmony_ci let source = this.getSource("pointer", sourceName); 3171cb0ef41Sopenharmony_ci source.pointerDown(this, button, width, height, pressure, tangentialPressure, 3181cb0ef41Sopenharmony_ci tiltX, tiltY, twist, altitudeAngle, azimuthAngle); 3191cb0ef41Sopenharmony_ci return this; 3201cb0ef41Sopenharmony_ci }, 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci /** 3231cb0ef41Sopenharmony_ci * Create a pointerUp event for the current default pointer source 3241cb0ef41Sopenharmony_ci * 3251cb0ef41Sopenharmony_ci * @param {String} button - Button to release 3261cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named pointer source to use or null for the default pointer 3271cb0ef41Sopenharmony_ci * source 3281cb0ef41Sopenharmony_ci * @returns {Actions} 3291cb0ef41Sopenharmony_ci */ 3301cb0ef41Sopenharmony_ci pointerUp: function({button=this.ButtonType.LEFT, sourceName=null}={}) { 3311cb0ef41Sopenharmony_ci let source = this.getSource("pointer", sourceName); 3321cb0ef41Sopenharmony_ci source.pointerUp(this, button); 3331cb0ef41Sopenharmony_ci return this; 3341cb0ef41Sopenharmony_ci }, 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci /** 3371cb0ef41Sopenharmony_ci * Create a move event for the current default pointer source 3381cb0ef41Sopenharmony_ci * 3391cb0ef41Sopenharmony_ci * @param {Number} x - Destination x coordinate 3401cb0ef41Sopenharmony_ci * @param {Number} y - Destination y coordinate 3411cb0ef41Sopenharmony_ci * @param {String|Element} origin - Origin of the coordinate system. 3421cb0ef41Sopenharmony_ci * Either "pointer", "viewport" or an Element 3431cb0ef41Sopenharmony_ci * @param {Number?} duration - Time in ms for the move 3441cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named pointer source to use or null for the default pointer 3451cb0ef41Sopenharmony_ci * source 3461cb0ef41Sopenharmony_ci * @returns {Actions} 3471cb0ef41Sopenharmony_ci */ 3481cb0ef41Sopenharmony_ci pointerMove: function(x, y, 3491cb0ef41Sopenharmony_ci {origin="viewport", duration, sourceName=null, 3501cb0ef41Sopenharmony_ci width, height, pressure, tangentialPressure, 3511cb0ef41Sopenharmony_ci tiltX, tiltY, twist, altitudeAngle, azimuthAngle}={}) { 3521cb0ef41Sopenharmony_ci let source = this.getSource("pointer", sourceName); 3531cb0ef41Sopenharmony_ci source.pointerMove(this, x, y, duration, origin, width, height, pressure, 3541cb0ef41Sopenharmony_ci tangentialPressure, tiltX, tiltY, twist, altitudeAngle, 3551cb0ef41Sopenharmony_ci azimuthAngle); 3561cb0ef41Sopenharmony_ci return this; 3571cb0ef41Sopenharmony_ci }, 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci /** 3601cb0ef41Sopenharmony_ci * Create a scroll event for the current default wheel source 3611cb0ef41Sopenharmony_ci * 3621cb0ef41Sopenharmony_ci * @param {Number} x - mouse cursor x coordinate 3631cb0ef41Sopenharmony_ci * @param {Number} y - mouse cursor y coordinate 3641cb0ef41Sopenharmony_ci * @param {Number} deltaX - scroll delta value along the x-axis in pixels 3651cb0ef41Sopenharmony_ci * @param {Number} deltaY - scroll delta value along the y-axis in pixels 3661cb0ef41Sopenharmony_ci * @param {String|Element} origin - Origin of the coordinate system. 3671cb0ef41Sopenharmony_ci * Either "viewport" or an Element 3681cb0ef41Sopenharmony_ci * @param {Number?} duration - Time in ms for the scroll 3691cb0ef41Sopenharmony_ci * @param {String?} sourceName - Named wheel source to use or null for the 3701cb0ef41Sopenharmony_ci * default wheel source 3711cb0ef41Sopenharmony_ci * @returns {Actions} 3721cb0ef41Sopenharmony_ci */ 3731cb0ef41Sopenharmony_ci scroll: function(x, y, deltaX, deltaY, 3741cb0ef41Sopenharmony_ci {origin="viewport", duration, sourceName=null}={}) { 3751cb0ef41Sopenharmony_ci let source = this.getSource("wheel", sourceName); 3761cb0ef41Sopenharmony_ci source.scroll(this, x, y, deltaX, deltaY, duration, origin); 3771cb0ef41Sopenharmony_ci return this; 3781cb0ef41Sopenharmony_ci }, 3791cb0ef41Sopenharmony_ci }; 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci function GeneralSource() { 3821cb0ef41Sopenharmony_ci this.actions = new Map(); 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci GeneralSource.prototype = { 3861cb0ef41Sopenharmony_ci serialize: function(tickCount, defaultTickDuration) { 3871cb0ef41Sopenharmony_ci let actions = []; 3881cb0ef41Sopenharmony_ci let data = {"type": "none", "actions": actions}; 3891cb0ef41Sopenharmony_ci for (let i=0; i<tickCount; i++) { 3901cb0ef41Sopenharmony_ci if (this.actions.has(i)) { 3911cb0ef41Sopenharmony_ci actions.push(this.actions.get(i)); 3921cb0ef41Sopenharmony_ci } else { 3931cb0ef41Sopenharmony_ci actions.push({"type": "pause", duration: defaultTickDuration}); 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci return data; 3971cb0ef41Sopenharmony_ci }, 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci addPause: function(actions, duration) { 4001cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 4011cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 4021cb0ef41Sopenharmony_ci throw new Error(`Already have a pause action for the current tick`); 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "pause", duration: duration}); 4051cb0ef41Sopenharmony_ci }, 4061cb0ef41Sopenharmony_ci }; 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ci function KeySource() { 4091cb0ef41Sopenharmony_ci this.actions = new Map(); 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci KeySource.prototype = { 4131cb0ef41Sopenharmony_ci serialize: function(tickCount) { 4141cb0ef41Sopenharmony_ci if (!this.actions.size) { 4151cb0ef41Sopenharmony_ci return undefined; 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci let actions = []; 4181cb0ef41Sopenharmony_ci let data = {"type": "key", "actions": actions}; 4191cb0ef41Sopenharmony_ci for (let i=0; i<tickCount; i++) { 4201cb0ef41Sopenharmony_ci if (this.actions.has(i)) { 4211cb0ef41Sopenharmony_ci actions.push(this.actions.get(i)); 4221cb0ef41Sopenharmony_ci } else { 4231cb0ef41Sopenharmony_ci actions.push({"type": "pause"}); 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci return data; 4271cb0ef41Sopenharmony_ci }, 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci keyDown: function(actions, key) { 4301cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 4311cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 4321cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 4331cb0ef41Sopenharmony_ci } 4341cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "keyDown", value: key}); 4351cb0ef41Sopenharmony_ci }, 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci keyUp: function(actions, key) { 4381cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 4391cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 4401cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 4411cb0ef41Sopenharmony_ci } 4421cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "keyUp", value: key}); 4431cb0ef41Sopenharmony_ci }, 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci addPause: function(actions, duration) { 4461cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 4471cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 4481cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "pause", duration: duration}); 4511cb0ef41Sopenharmony_ci }, 4521cb0ef41Sopenharmony_ci }; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci function PointerSource(parameters={pointerType: "mouse"}) { 4551cb0ef41Sopenharmony_ci let pointerType = parameters.pointerType || "mouse"; 4561cb0ef41Sopenharmony_ci if (!["mouse", "pen", "touch"].includes(pointerType)) { 4571cb0ef41Sopenharmony_ci throw new Error(`Invalid pointerType ${pointerType}`); 4581cb0ef41Sopenharmony_ci } 4591cb0ef41Sopenharmony_ci this.type = pointerType; 4601cb0ef41Sopenharmony_ci this.actions = new Map(); 4611cb0ef41Sopenharmony_ci } 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci function setPointerProperties(action, width, height, pressure, tangentialPressure, 4641cb0ef41Sopenharmony_ci tiltX, tiltY, twist, altitudeAngle, azimuthAngle) { 4651cb0ef41Sopenharmony_ci if (width) { 4661cb0ef41Sopenharmony_ci action.width = width; 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci if (height) { 4691cb0ef41Sopenharmony_ci action.height = height; 4701cb0ef41Sopenharmony_ci } 4711cb0ef41Sopenharmony_ci if (pressure) { 4721cb0ef41Sopenharmony_ci action.pressure = pressure; 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci if (tangentialPressure) { 4751cb0ef41Sopenharmony_ci action.tangentialPressure = tangentialPressure; 4761cb0ef41Sopenharmony_ci } 4771cb0ef41Sopenharmony_ci if (tiltX) { 4781cb0ef41Sopenharmony_ci action.tiltX = tiltX; 4791cb0ef41Sopenharmony_ci } 4801cb0ef41Sopenharmony_ci if (tiltY) { 4811cb0ef41Sopenharmony_ci action.tiltY = tiltY; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci if (twist) { 4841cb0ef41Sopenharmony_ci action.twist = twist; 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci if (altitudeAngle) { 4871cb0ef41Sopenharmony_ci action.altitudeAngle = altitudeAngle; 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci if (azimuthAngle) { 4901cb0ef41Sopenharmony_ci action.azimuthAngle = azimuthAngle; 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci return action; 4931cb0ef41Sopenharmony_ci } 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_ci PointerSource.prototype = { 4961cb0ef41Sopenharmony_ci serialize: function(tickCount) { 4971cb0ef41Sopenharmony_ci if (!this.actions.size) { 4981cb0ef41Sopenharmony_ci return undefined; 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci let actions = []; 5011cb0ef41Sopenharmony_ci let data = {"type": "pointer", "actions": actions, "parameters": {"pointerType": this.type}}; 5021cb0ef41Sopenharmony_ci for (let i=0; i<tickCount; i++) { 5031cb0ef41Sopenharmony_ci if (this.actions.has(i)) { 5041cb0ef41Sopenharmony_ci actions.push(this.actions.get(i)); 5051cb0ef41Sopenharmony_ci } else { 5061cb0ef41Sopenharmony_ci actions.push({"type": "pause"}); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci return data; 5101cb0ef41Sopenharmony_ci }, 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci pointerDown: function(actions, button, width, height, pressure, tangentialPressure, 5131cb0ef41Sopenharmony_ci tiltX, tiltY, twist, altitudeAngle, azimuthAngle) { 5141cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5151cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5161cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci let actionProperties = setPointerProperties({type: "pointerDown", button}, width, height, 5191cb0ef41Sopenharmony_ci pressure, tangentialPressure, tiltX, tiltY, 5201cb0ef41Sopenharmony_ci twist, altitudeAngle, azimuthAngle); 5211cb0ef41Sopenharmony_ci this.actions.set(tick, actionProperties); 5221cb0ef41Sopenharmony_ci }, 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci pointerUp: function(actions, button) { 5251cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5261cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5271cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "pointerUp", button}); 5301cb0ef41Sopenharmony_ci }, 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci pointerMove: function(actions, x, y, duration, origin, width, height, pressure, 5331cb0ef41Sopenharmony_ci tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle) { 5341cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5351cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5361cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci let moveAction = {type: "pointerMove", x, y, origin}; 5391cb0ef41Sopenharmony_ci if (duration) { 5401cb0ef41Sopenharmony_ci moveAction.duration = duration; 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci let actionProperties = setPointerProperties(moveAction, width, height, pressure, 5431cb0ef41Sopenharmony_ci tangentialPressure, tiltX, tiltY, twist, 5441cb0ef41Sopenharmony_ci altitudeAngle, azimuthAngle); 5451cb0ef41Sopenharmony_ci this.actions.set(tick, actionProperties); 5461cb0ef41Sopenharmony_ci }, 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci addPause: function(actions, duration) { 5491cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5501cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5511cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5521cb0ef41Sopenharmony_ci } 5531cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "pause", duration: duration}); 5541cb0ef41Sopenharmony_ci }, 5551cb0ef41Sopenharmony_ci }; 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci function WheelSource() { 5581cb0ef41Sopenharmony_ci this.actions = new Map(); 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci WheelSource.prototype = { 5621cb0ef41Sopenharmony_ci serialize: function(tickCount) { 5631cb0ef41Sopenharmony_ci if (!this.actions.size) { 5641cb0ef41Sopenharmony_ci return undefined; 5651cb0ef41Sopenharmony_ci } 5661cb0ef41Sopenharmony_ci let actions = []; 5671cb0ef41Sopenharmony_ci let data = {"type": "wheel", "actions": actions}; 5681cb0ef41Sopenharmony_ci for (let i=0; i<tickCount; i++) { 5691cb0ef41Sopenharmony_ci if (this.actions.has(i)) { 5701cb0ef41Sopenharmony_ci actions.push(this.actions.get(i)); 5711cb0ef41Sopenharmony_ci } else { 5721cb0ef41Sopenharmony_ci actions.push({"type": "pause"}); 5731cb0ef41Sopenharmony_ci } 5741cb0ef41Sopenharmony_ci } 5751cb0ef41Sopenharmony_ci return data; 5761cb0ef41Sopenharmony_ci }, 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci scroll: function(actions, x, y, deltaX, deltaY, duration, origin) { 5791cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5801cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5811cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5821cb0ef41Sopenharmony_ci } 5831cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "scroll", x, y, deltaX, deltaY, origin}); 5841cb0ef41Sopenharmony_ci if (duration) { 5851cb0ef41Sopenharmony_ci this.actions.get(tick).duration = duration; 5861cb0ef41Sopenharmony_ci } 5871cb0ef41Sopenharmony_ci }, 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci addPause: function(actions, duration) { 5901cb0ef41Sopenharmony_ci let tick = actions.tickIdx; 5911cb0ef41Sopenharmony_ci if (this.actions.has(tick)) { 5921cb0ef41Sopenharmony_ci tick = actions.addTick().tickIdx; 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci this.actions.set(tick, {type: "pause", duration: duration}); 5951cb0ef41Sopenharmony_ci }, 5961cb0ef41Sopenharmony_ci }; 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci test_driver.Actions = Actions; 5991cb0ef41Sopenharmony_ci})(); 600