зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1670295 - [marionette] Move legacy touch helpers from listener.js to legacyaction.js r=marionette-reviewers,whimboo,maja_zf
Depends on D93324 Move singleTap and dependencies to legacyaction.js in order to reuse them in the JSWindowActor. Differential Revision: https://phabricator.services.mozilla.com/D93365
This commit is contained in:
Родитель
b932959de4
Коммит
891c58ed1a
|
@ -15,6 +15,7 @@ const { XPCOMUtils } = ChromeUtils.import(
|
|||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
Preferences: "resource://gre/modules/Preferences.jsm",
|
||||
|
||||
accessibility: "chrome://marionette/content/accessibility.js",
|
||||
element: "chrome://marionette/content/element.js",
|
||||
error: "chrome://marionette/content/error.js",
|
||||
evaluate: "chrome://marionette/content/evaluate.js",
|
||||
|
@ -52,19 +53,49 @@ action.Chain = function() {
|
|||
this.inputSource = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a touch based event.
|
||||
*
|
||||
* @param {Element} elem
|
||||
* The Element on which the touch event should be created.
|
||||
* @param {Number} x
|
||||
* x coordinate relative to the viewport.
|
||||
* @param {Number} y
|
||||
* y coordinate relative to the viewport.
|
||||
* @param {Number} touchId
|
||||
* Touch event id used by legacyactions.
|
||||
*/
|
||||
action.Chain.prototype.createATouch = function(elem, x, y, touchId) {
|
||||
const doc = elem.ownerDocument;
|
||||
const win = doc.defaultView;
|
||||
const [
|
||||
clientX,
|
||||
clientY,
|
||||
pageX,
|
||||
pageY,
|
||||
screenX,
|
||||
screenY,
|
||||
] = this.getCoordinateInfo(elem, x, y);
|
||||
const atouch = doc.createTouch(
|
||||
win,
|
||||
elem,
|
||||
touchId,
|
||||
pageX,
|
||||
pageY,
|
||||
screenX,
|
||||
screenY,
|
||||
clientX,
|
||||
clientY
|
||||
);
|
||||
return atouch;
|
||||
};
|
||||
|
||||
action.Chain.prototype.dispatchActions = function(
|
||||
args,
|
||||
touchId,
|
||||
container,
|
||||
seenEls,
|
||||
touchProvider
|
||||
seenEls
|
||||
) {
|
||||
// Some touch events code in the listener needs to do ipc, so we can't
|
||||
// share this code across chrome/content.
|
||||
if (touchProvider) {
|
||||
this.touchProvider = touchProvider;
|
||||
}
|
||||
|
||||
this.seenEls = seenEls;
|
||||
this.container = container;
|
||||
let commandArray = evaluate.fromJSON(args, seenEls, container.frame);
|
||||
|
@ -145,16 +176,82 @@ action.Chain.prototype.emitMouseEvent = function(
|
|||
);
|
||||
};
|
||||
|
||||
action.Chain.prototype.emitTouchEvent = function(doc, type, touch) {
|
||||
logger.info(
|
||||
`Emitting Touch event of type ${type} ` +
|
||||
`to element with id: ${touch.target.id} ` +
|
||||
`and tag name: ${touch.target.tagName} ` +
|
||||
`at coordinates (${touch.clientX}), ` +
|
||||
`${touch.clientY}) relative to the viewport`
|
||||
);
|
||||
|
||||
const win = doc.defaultView;
|
||||
if (win.docShell.asyncPanZoomEnabled && this.scrolling) {
|
||||
logger.debug(
|
||||
`Cannot emit touch event with asyncPanZoomEnabled and legacyactions.scrolling`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// we get here if we're not in asyncPacZoomEnabled land, or if we're
|
||||
// the main process
|
||||
win.windowUtils.sendTouchEvent(
|
||||
type,
|
||||
[touch.identifier],
|
||||
[touch.clientX],
|
||||
[touch.clientY],
|
||||
[touch.radiusX],
|
||||
[touch.radiusY],
|
||||
[touch.rotationAngle],
|
||||
[touch.force],
|
||||
0
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset any persisted values after a command completes.
|
||||
*/
|
||||
action.Chain.prototype.resetValues = function() {
|
||||
this.container = null;
|
||||
this.seenEls = null;
|
||||
this.touchProvider = null;
|
||||
this.mouseEventsOnly = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that performs a single tap.
|
||||
*/
|
||||
action.Chain.prototype.singleTap = async function(
|
||||
el,
|
||||
corx,
|
||||
cory,
|
||||
capabilities
|
||||
) {
|
||||
const doc = el.ownerDocument;
|
||||
// after this block, the element will be scrolled into view
|
||||
let visible = element.isVisible(el, corx, cory);
|
||||
if (!visible) {
|
||||
throw new error.ElementNotInteractableError(
|
||||
"Element is not currently visible and may not be manipulated"
|
||||
);
|
||||
}
|
||||
|
||||
let a11y = accessibility.get(capabilities["moz:accessibilityChecks"]);
|
||||
let acc = await a11y.getAccessible(el, true);
|
||||
a11y.assertVisible(acc, el, visible);
|
||||
a11y.assertActionable(acc, el);
|
||||
if (!doc.createTouch) {
|
||||
this.mouseEventsOnly = true;
|
||||
}
|
||||
let c = element.coordinates(el, corx, cory);
|
||||
if (!this.mouseEventsOnly) {
|
||||
let touchId = this.nextTouchId++;
|
||||
let touch = this.createATouch(el, c.x, c.y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
}
|
||||
this.mouseTap(doc, c.x, c.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Emit events for each action in the provided chain.
|
||||
*
|
||||
|
@ -386,7 +483,7 @@ action.Chain.prototype.generateEvents = function(
|
|||
switch (type) {
|
||||
case "tap":
|
||||
if (this.mouseEventsOnly) {
|
||||
let touch = this.touchProvider.createATouch(target, x, y, touchId);
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.mouseTap(
|
||||
touch.target.ownerDocument,
|
||||
touch.clientX,
|
||||
|
@ -397,9 +494,9 @@ action.Chain.prototype.generateEvents = function(
|
|||
);
|
||||
} else {
|
||||
touchId = this.nextTouchId++;
|
||||
let touch = this.touchProvider.createATouch(target, x, y, touchId);
|
||||
this.touchProvider.emitTouchEvent("touchstart", touch);
|
||||
this.touchProvider.emitTouchEvent("touchend", touch);
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
this.mouseTap(
|
||||
touch.target.ownerDocument,
|
||||
touch.clientX,
|
||||
|
@ -419,8 +516,8 @@ action.Chain.prototype.generateEvents = function(
|
|||
this.emitMouseEvent(doc, "mousedown", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
touchId = this.nextTouchId++;
|
||||
let touch = this.touchProvider.createATouch(target, x, y, touchId);
|
||||
this.touchProvider.emitTouchEvent("touchstart", touch);
|
||||
let touch = this.createATouch(target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchstart", touch);
|
||||
this.touchIds[touchId] = touch;
|
||||
return touchId;
|
||||
}
|
||||
|
@ -434,8 +531,8 @@ action.Chain.prototype.generateEvents = function(
|
|||
let touch = this.touchIds[touchId];
|
||||
let [x, y] = this.lastCoordinates;
|
||||
|
||||
touch = this.touchProvider.createATouch(touch.target, x, y, touchId);
|
||||
this.touchProvider.emitTouchEvent("touchend", touch);
|
||||
touch = this.createATouch(touch.target, x, y, touchId);
|
||||
this.emitTouchEvent(doc, "touchend", touch);
|
||||
|
||||
if (this.isTap) {
|
||||
this.mouseTap(
|
||||
|
@ -460,10 +557,7 @@ action.Chain.prototype.generateEvents = function(
|
|||
let [x, y] = this.lastCoordinates;
|
||||
this.emitMouseEvent(doc, "mouseup", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
this.touchProvider.emitTouchEvent(
|
||||
"touchcancel",
|
||||
this.touchIds[touchId]
|
||||
);
|
||||
this.emitTouchEvent(doc, "touchcancel", this.touchIds[touchId]);
|
||||
delete this.touchIds[touchId];
|
||||
}
|
||||
this.lastCoordinates = null;
|
||||
|
@ -474,14 +568,14 @@ action.Chain.prototype.generateEvents = function(
|
|||
if (this.mouseEventsOnly) {
|
||||
this.emitMouseEvent(doc, "mousemove", x, y, null, null, keyModifiers);
|
||||
} else {
|
||||
let touch = this.touchProvider.createATouch(
|
||||
let touch = this.createATouch(
|
||||
this.touchIds[touchId].target,
|
||||
x,
|
||||
y,
|
||||
touchId
|
||||
);
|
||||
this.touchIds[touchId] = touch;
|
||||
this.touchProvider.emitTouchEvent("touchmove", touch);
|
||||
this.emitTouchEvent(doc, "touchmove", touch);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -317,94 +317,11 @@ async function executeScript(script, args, opts = {}) {
|
|||
return evaluate.sandbox(sb, script, args, opts);
|
||||
}
|
||||
|
||||
function emitTouchEvent(type, touch) {
|
||||
logger.info(
|
||||
`Emitting Touch event of type ${type} ` +
|
||||
`to element with id: ${touch.target.id} ` +
|
||||
`and tag name: ${touch.target.tagName} ` +
|
||||
`at coordinates (${touch.clientX}), ` +
|
||||
`${touch.clientY}) relative to the viewport`
|
||||
);
|
||||
|
||||
const win = curContainer.frame;
|
||||
if (win.docShell.asyncPanZoomEnabled && legacyactions.scrolling) {
|
||||
logger.debug(
|
||||
`Cannot emit touch event with asyncPanZoomEnabled and legacyactions.scrolling`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// we get here if we're not in asyncPacZoomEnabled land, or if we're
|
||||
// the main process
|
||||
win.windowUtils.sendTouchEvent(
|
||||
type,
|
||||
[touch.identifier],
|
||||
[touch.clientX],
|
||||
[touch.clientY],
|
||||
[touch.radiusX],
|
||||
[touch.radiusY],
|
||||
[touch.rotationAngle],
|
||||
[touch.force],
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that perform a single tap
|
||||
* Function that performs a single tap.
|
||||
*/
|
||||
async function singleTap(el, corx, cory, capabilities) {
|
||||
// after this block, the element will be scrolled into view
|
||||
let visible = element.isVisible(el, corx, cory);
|
||||
if (!visible) {
|
||||
throw new error.ElementNotInteractableError(
|
||||
"Element is not currently visible and may not be manipulated"
|
||||
);
|
||||
}
|
||||
|
||||
let a11y = accessibility.get(capabilities["moz:accessibilityChecks"]);
|
||||
let acc = await a11y.getAccessible(el, true);
|
||||
a11y.assertVisible(acc, el, visible);
|
||||
a11y.assertActionable(acc, el);
|
||||
if (!curContainer.frame.document.createTouch) {
|
||||
legacyactions.mouseEventsOnly = true;
|
||||
}
|
||||
let c = element.coordinates(el, corx, cory);
|
||||
if (!legacyactions.mouseEventsOnly) {
|
||||
let touchId = legacyactions.nextTouchId++;
|
||||
let touch = createATouch(el, c.x, c.y, touchId);
|
||||
emitTouchEvent("touchstart", touch);
|
||||
emitTouchEvent("touchend", touch);
|
||||
}
|
||||
legacyactions.mouseTap(el.ownerDocument, c.x, c.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create a touch based on the element
|
||||
* corx and cory are relative to the viewport, id is the touchId
|
||||
*/
|
||||
function createATouch(el, corx, cory, touchId) {
|
||||
let doc = el.ownerDocument;
|
||||
let win = doc.defaultView;
|
||||
let [
|
||||
clientX,
|
||||
clientY,
|
||||
pageX,
|
||||
pageY,
|
||||
screenX,
|
||||
screenY,
|
||||
] = legacyactions.getCoordinateInfo(el, corx, cory);
|
||||
let atouch = doc.createTouch(
|
||||
win,
|
||||
el,
|
||||
touchId,
|
||||
pageX,
|
||||
pageY,
|
||||
screenX,
|
||||
screenY,
|
||||
clientX,
|
||||
clientY
|
||||
);
|
||||
return atouch;
|
||||
return legacyactions.singleTap(el, corx, cory, capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -447,17 +364,7 @@ async function releaseActions() {
|
|||
* Start action chain on one finger.
|
||||
*/
|
||||
function actionChain(chain, touchId) {
|
||||
let touchProvider = {};
|
||||
touchProvider.createATouch = createATouch;
|
||||
touchProvider.emitTouchEvent = emitTouchEvent;
|
||||
|
||||
return legacyactions.dispatchActions(
|
||||
chain,
|
||||
touchId,
|
||||
curContainer,
|
||||
seenEls,
|
||||
touchProvider
|
||||
);
|
||||
return legacyactions.dispatchActions(chain, touchId, curContainer, seenEls);
|
||||
}
|
||||
|
||||
function emitMultiEvents(type, touch, touches) {
|
||||
|
@ -534,7 +441,7 @@ function setDispatch(batches, touches, batchIndex = 0) {
|
|||
case "press":
|
||||
el = seenEls.get(pack[2], curContainer.frame);
|
||||
c = element.coordinates(el, pack[3], pack[4]);
|
||||
touch = createATouch(el, c.x, c.y, touchId);
|
||||
touch = legacyactions.createATouch(el, c.x, c.y, touchId);
|
||||
multiLast[touchId] = touch;
|
||||
touches.push(touch);
|
||||
emitMultiEvents("touchstart", touch, touches);
|
||||
|
@ -552,7 +459,12 @@ function setDispatch(batches, touches, batchIndex = 0) {
|
|||
case "move":
|
||||
el = seenEls.get(pack[2], curContainer.frame);
|
||||
c = element.coordinates(el);
|
||||
touch = createATouch(multiLast[touchId].target, c.x, c.y, touchId);
|
||||
touch = legacyactions.createATouch(
|
||||
multiLast[touchId].target,
|
||||
c.x,
|
||||
c.y,
|
||||
touchId
|
||||
);
|
||||
touchIndex = touches.indexOf(lastTouch);
|
||||
touches[touchIndex] = touch;
|
||||
multiLast[touchId] = touch;
|
||||
|
|
Загрузка…
Ссылка в новой задаче