Bug 1795116 - Support specifying tiltX/tiltY/twist on synthesized touch event; r=webdriver-reviewers,smaug,whimboo

Differential Revision: https://phabricator.services.mozilla.com/D160970
This commit is contained in:
Edgar Chen 2022-11-08 19:47:29 +00:00
Родитель e98fad02f0
Коммит 04cf2a513c
29 изменённых файлов: 268 добавлений и 102 удалений

Просмотреть файл

@ -840,10 +840,13 @@ nsDOMWindowUtils::SendTouchEvent(
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
int32_t aModifiers, bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
aRotationAngles, aForces, aModifiers,
aIgnoreRootScrollFrame, false, aPreventDefault);
aRotationAngles, aForces, aTiltXs, aTiltYs,
aTwists, aModifiers, aIgnoreRootScrollFrame,
false, aPreventDefault);
}
NS_IMETHODIMP
@ -852,10 +855,13 @@ nsDOMWindowUtils::SendTouchEventToWindow(
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
int32_t aModifiers, bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
aRotationAngles, aForces, aModifiers,
aIgnoreRootScrollFrame, true, aPreventDefault);
aRotationAngles, aForces, aTiltXs, aTiltYs,
aTwists, aModifiers, aIgnoreRootScrollFrame, true,
aPreventDefault);
}
nsresult nsDOMWindowUtils::SendTouchEventCommon(
@ -863,8 +869,9 @@ nsresult nsDOMWindowUtils::SendTouchEventCommon(
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
int32_t aModifiers, bool aIgnoreRootScrollFrame, bool aToWindow,
bool* aPreventDefault) {
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool aToWindow, bool* aPreventDefault) {
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
@ -905,8 +912,8 @@ nsresult nsDOMWindowUtils::SendTouchEventCommon(
CSSPoint::ToAppUnits(CSSPoint(aRxs[i], aRys[i])),
presContext->AppUnitsPerDevPixel());
RefPtr<Touch> t =
new Touch(aIdentifiers[i], pt, radius, aRotationAngles[i], aForces[i]);
RefPtr<Touch> t = new Touch(aIdentifiers[i], pt, radius, aRotationAngles[i],
aForces[i], aTiltXs[i], aTiltYs[i], aTwists[i]);
event.mTouches.AppendElement(t);
}

Просмотреть файл

@ -101,8 +101,9 @@ class nsDOMWindowUtils final : public nsIDOMWindowUtils,
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
int32_t aModifiers, bool aIgnoreRootScrollFrame, bool aToWindow,
bool* aPreventDefault);
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool aToWindow, bool* aPreventDefault);
void ReportErrorMessageForWindow(const nsAString& aErrorMessage,
const char* aClassification,

Просмотреть файл

@ -67,6 +67,15 @@ Touch::Touch(int32_t aIdentifier, LayoutDeviceIntPoint aPoint,
nsJSContext::LikelyShortLivingObjectCreated();
}
Touch::Touch(int32_t aIdentifier, LayoutDeviceIntPoint aPoint,
LayoutDeviceIntPoint aRadius, float aRotationAngle, float aForce,
int32_t aTiltX, int32_t aTiltY, int32_t aTwist)
: Touch(aIdentifier, aPoint, aRadius, aRotationAngle, aForce) {
tiltX = aTiltX;
tiltY = aTiltY;
twist = aTwist;
}
Touch::Touch(const Touch& aOther)
: mOriginalTarget(aOther.mOriginalTarget),
mTarget(aOther.mTarget),

Просмотреть файл

@ -36,6 +36,9 @@ class Touch final : public nsISupports,
float aRotationAngle, float aForce);
Touch(int32_t aIdentifier, LayoutDeviceIntPoint aPoint,
LayoutDeviceIntPoint aRadius, float aRotationAngle, float aForce);
Touch(int32_t aIdentifier, LayoutDeviceIntPoint aPoint,
LayoutDeviceIntPoint aRadius, float aRotationAngle, float aForce,
int32_t aTiltX, int32_t aTiltY, int32_t aTwist);
Touch(const Touch& aOther);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS

Просмотреть файл

@ -27,24 +27,24 @@
var endYForFirstTouch = Math.floor(rect.y + ((rect.height / 4) * 2));
var endYForSecondTouch = Math.floor(rect.y + ((rect.height / 4) * 4));
utils.sendTouchEvent("touchstart", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
while (y != endYForFirstTouch) {
utils.sendTouchEvent("touchmove", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
++y;
}
// Add a new touch and move this touch
utils.sendTouchEvent("touchstart", [0, 1], [x, x], [endYForFirstTouch, endYForFirstTouch], [1, 1], [1, 1], [0, 0], [1, 1],
0, false);
[0, 0], [0, 0], [0, 0], 0, false);
while (y != endYForSecondTouch) {
utils.sendTouchEvent("touchmove", [0, 1], [x, x], [endYForFirstTouch, y], [1, 1], [1, 1], [0, 0], [1, 1],
0, false);
[0, 0], [0, 0], [0, 0], 0, false);
++y;
}
utils.sendTouchEvent("touchend", [0, 1], [x, x], [endYForFirstTouch, endYForSecondTouch], [1, 1], [1, 1], [0, 0], [1, 1],
0, false);
[0, 0], [0, 0], [0, 0], 0, false);
});
let touchStartCount = 0;

Просмотреть файл

@ -34,14 +34,14 @@
var y = Math.floor(rect.y + (rect.height / 4));
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
while (y != endY) {
utils.sendTouchEvent("touchmove", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
++y;
}
utils.sendTouchEvent("touchend", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
});
@ -68,13 +68,13 @@
var startY = Math.floor(rect.y + (rect.height / 4));
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0], [x], [startY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchmove", [0], [x], [startY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchmove", [0], [x], [startY + 1], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchend", [0], [x], [endY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
});
touchmoveEvents = [];
@ -101,15 +101,16 @@
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0, 1], [x, x + 1],
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
[1, 1], 0, false);
[1, 1], [0, 0], [0, 0], [0, 0], 0, false);
while (startY != endY) {
utils.sendTouchEvent("touchmove", [0, 1], [x, x + 1],
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
[1, 1], 0, false);
[1, 1], [0, 0], [0, 0], [0, 0], 0, false);
++startY;
}
utils.sendTouchEvent("touchend", [0, 1], [x, x + 1], [endY, endY + 1],
[1, 1], [1, 1], [0, 0], [1, 1], 0, false);
[1, 1], [1, 1], [0, 0], [1, 1], [0, 0], [0, 0],
[0, 0], 0, false);
});

Просмотреть файл

@ -34,14 +34,14 @@
var y = Math.floor(rect.y + (rect.height / 4));
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
while (y != endY) {
utils.sendTouchEvent("touchmove", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
++y;
}
utils.sendTouchEvent("touchend", [0], [x], [y], [1], [1], [0], [1],
0, false);
[0], [0], [0], 0, false);
});
@ -68,13 +68,13 @@
var startY = Math.floor(rect.y + (rect.height / 4));
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0], [x], [startY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchmove", [0], [x], [startY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchmove", [0], [x], [startY + 1], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
utils.sendTouchEvent("touchend", [0], [x], [endY], [1], [1], [0],
[1], 0, false);
[1], [0], [0], [0], 0, false);
});
touchmoveEvents = [];
@ -101,15 +101,16 @@
var endY = Math.floor(rect.y + ((rect.height / 4) * 2));
utils.sendTouchEvent("touchstart", [0, 1], [x, x + 1],
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
[1, 1], 0, false);
[1, 1], [0, 0], [0, 0], [0, 0], 0, false);
while (startY != endY) {
utils.sendTouchEvent("touchmove", [0, 1], [x, x + 1],
[startY, startY + 1], [1, 1], [1, 1], [0, 0],
[1, 1], 0, false);
[1, 1], [0, 0], [0, 0], [0, 0], 0, false);
++startY;
}
utils.sendTouchEvent("touchend", [0, 1], [x, x + 1], [endY, endY + 1],
[1, 1], [1, 1], [0, 0], [1, 1], 0, false);
[1, 1], [1, 1], [0, 0], [1, 1], [0, 0], [0, 0],
[0, 0], 0, false);
});

Просмотреть файл

@ -194,15 +194,18 @@ function runTests() {
// event listener.
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// No implicitly / explicitly pointer capture. pointermove should be
// dispatched to 1d2, 2d2
@ -217,11 +220,13 @@ function runTests() {
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
// should be dispatched to 1d1, 2d1
@ -237,7 +242,8 @@ function runTests() {
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Explicitly capture pointer to 1d1, 2d1 when pointerdown
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
@ -249,17 +255,20 @@ function runTests() {
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// This should send pointer event to test1d1, test2d1.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1 + 5, left2d1 + 5], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// This should send pointer event to test1d2, test2d2.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1 + 5, left2d1 + 5], [top1d1 + 5, top2d1 + 5], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
is(test1d1pointermovecount, 2, "1d1 should have got pointermove");
is(test1d1pointergotcapture, 2, "1d1 should have got pointergotcapture");
@ -273,7 +282,8 @@ function runTests() {
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
finishTest();
}

Просмотреть файл

@ -194,15 +194,18 @@ function runTests() {
// event listener.
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Implicitly pointer capture. pointermove should be dispatched to 1d1, 2d1
is(test1d1pointermovecount, 1, "1d1 should have got pointermove");
@ -216,11 +219,13 @@ function runTests() {
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d2, left2d2], [top1d2, top2d2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Explicitly capture pointer to 1d1, 2d1. pointermove, gotpointercapture
// should be dispatched to 1d1, 2d1
@ -236,7 +241,8 @@ function runTests() {
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Explicitly capture pointer to 1d1, 2d1 when pointerdown
test1d1.addEventListener("pointerdown", test1d1CapturePointer, {capture: true, once: true});
@ -248,17 +254,20 @@ function runTests() {
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// This should send pointer event to test1d1, test2d1.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1 + 5, left2d1 + 5], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// This should send pointer event to test1d2, test2d2.
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1d1 + 5, left2d1 + 5], [top1d1 + 5, top2d1 + 5], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
is(test1d1pointermovecount, 3, "1d1 shouldn't have got pointermove");
is(test1d1pointergotcapture, 3, "1d1 should have got pointergotcapture");
@ -272,7 +281,8 @@ function runTests() {
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1d1, left2d1], [top1d1, top2d1], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
finishTest();
}

Просмотреть файл

@ -132,3 +132,4 @@ support-files =
[test_pointercapture_remove_iframe.html]
[test_pointermove_drag_scrollbar.html]
skip-if = os == 'android' # scrollbar not showed on mobile
[test_synthesized_touch.html]

Просмотреть файл

@ -83,13 +83,16 @@ function withoutImplicitlyPointerCaptureForTouch() {
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1 + 1, left2 + 1], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1 + 1, left2 + 1], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
}
SimpleTest.waitForFocus(() => {

Просмотреть файл

@ -96,17 +96,20 @@ function withoutImplicitlyPointerCaptureForTouch() {
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Move the touch pointers so that we dispatch all of them to content.
left1++;
left2++;
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
}
SimpleTest.waitForFocus(() => {

Просмотреть файл

@ -89,17 +89,20 @@ function withoutImplicitlyPointerCaptureForTouch() {
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendTouchEvent('touchstart', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
// Move the touch pointers so that we dispatch all of them to content.
left1++;
left2++;
utils.sendTouchEvent('touchmove', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
utils.sendTouchEvent('touchend', [test1PointerId, test2PointerId],
[left1, left2], [top1, top2], [rx, rx], [ry, ry],
[angle, angle], [force, force], modifiers);
[angle, angle], [force, force], [0, 0], [0, 0],
[0, 0], modifiers);
}
SimpleTest.waitForFocus(() => {

Просмотреть файл

@ -24,17 +24,22 @@ var touches = {
rys: [],
angles: [],
forces: [],
tiltXs: [],
tiltYs: [],
twists: [],
};
function synthesizeTouchEvent(aType, aIds, aLefts, aTops, aRxs, aRys, aAngles, aForces) {
function synthesizeTouchEvent(aType, aTouches) {
var utils = _getDOMWindowUtils(window);
if (!utils) {
ok(false, "unable to get nsIDOMWindowUtils");
return;
}
utils.sendTouchEvent(aType, aIds, aLefts, aTops, aRxs, aRys,
aAngles, aForces, 0 /* modifiers */);
utils.sendTouchEvent(aType, aTouches.ids, aTouches.lefts, aTouches.tops,
aTouches.rxs, aTouches.rys, aTouches.angles,
aTouches.forces, aTouches.tiltXs, aTouches.tiltYs,
aTouches.twists, 0 /* modifiers */);
}
function synthesizeTouchStart(aTarget, aId, aOffsetX, aOffsetY) {
@ -51,9 +56,11 @@ function synthesizeTouchStart(aTarget, aId, aOffsetX, aOffsetY) {
touches.rys.push(1);
touches.angles.push(0);
touches.forces.push(1);
touches.tiltXs.push(0);
touches.tiltYs.push(0);
touches.twists.push(0);
synthesizeTouchEvent("touchstart", touches.ids, touches.lefts, touches.tops,
touches.rxs, touches.rys, touches.angles, touches.forces);
synthesizeTouchEvent("touchstart", touches);
}
function synthesizeTouchEnd(aTarget, aId, aOffsetX, aOffsetY) {
@ -63,17 +70,20 @@ function synthesizeTouchEnd(aTarget, aId, aOffsetX, aOffsetY) {
return;
}
let rect = aTarget.getBoundingClientRect();
touches.ids.splice(index, 1);
touches.lefts.splice(index, 1);
touches.tops.splice(index, 1);
touches.rxs.splice(index, 1);
touches.rys.splice(index, 1);
touches.angles.splice(index, 1);
touches.forces.splice(index, 1);
var removedTouches = {
ids: touches.ids.splice(index, 1),
lefts: touches.lefts.splice(index, 1),
tops: touches.tops.splice(index, 1),
rxs: touches.rxs.splice(index, 1),
rys: touches.rys.splice(index, 1),
angles: touches.angles.splice(index, 1),
forces: touches.forces.splice(index, 1),
tiltXs: touches.tiltXs.splice(index, 1),
tiltYs: touches.tiltYs.splice(index, 1),
twists: touches.twists.splice(index, 1),
};
synthesizeTouchEvent("touchend", [aId], [rect.left + aOffsetX], [rect.top + aOffsetY],
[1], [1], [0], [1]);
synthesizeTouchEvent("touchend", removedTouches);
}
function synthesizeTouchMove(aTarget, aId, aOffsetX, aOffsetY) {
@ -87,8 +97,7 @@ function synthesizeTouchMove(aTarget, aId, aOffsetX, aOffsetY) {
touches.lefts[index] = rect.left + aOffsetX;
touches.tops[index] = rect.top + aOffsetY;
synthesizeTouchEvent("touchmove", touches.ids, touches.lefts, touches.tops,
touches.rxs, touches.rys, touches.angles, touches.forces);
synthesizeTouchEvent("touchmove", touches);
}
var target0 = document.getElementById("target0");

Просмотреть файл

@ -0,0 +1,47 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Test synthesized touch input</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
<style>
#container {
width: 100px;
height: 100px;
background-color: green;
}
</style>
<div id="container"></div>
<script>
function waitForEvent(aTarget, aEvent, aCheckFn) {
return new Promise(aResolve => {
aTarget.addEventListener(aEvent, function(e) {
info(`${aEvent} received`);
aCheckFn(e);
aResolve();
}, { once: true });
});
}
add_task(async function test() {
const tiltX = 10;
const tiltY = -10;
const twist = 5;
const check = function(aEvent) {
is(aEvent.tiltX, tiltX, "check tiltX");
is(aEvent.tiltY, tiltY, "check tiltY");
is(aEvent.twist, twist, "check twist");
};
const container = document.getElementById("container");
const pointerDownPromise = waitForEvent(container, "pointerdown", check);
const pointerUpPromise = waitForEvent(container, "pointerup", check);
synthesizeTouchAtCenter(container, {tiltX, tiltY, twist});
await Promise.all([pointerDownPromise, pointerUpPromise]);
});
</script>

Просмотреть файл

@ -75,7 +75,7 @@ function checkTouch(aFakeTouch, aTouch) {
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
var ids = [], xs=[], ys=[], rxs = [], rys = [],
rotations = [], forces = [];
rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = [];
for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
for (var i = 0; i < aEvent[touchType].length; i++) {
@ -87,12 +87,15 @@ function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
rys.push(aEvent[touchType][i].radius.y);
rotations.push(aEvent[touchType][i].rotationAngle);
forces.push(aEvent[touchType][i].force);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
}
}
return windowUtils.sendTouchEvent(aType,
ids, xs, ys, rxs, rys,
rotations, forces,
rotations, forces, tiltXs, tiltYs, twists,
aModifiers, 0);
}

Просмотреть файл

@ -73,7 +73,7 @@ function checkTouch(aFakeTouch, aTouch) {
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
var ids = [], xs=[], ys=[], rxs = [], rys = [],
rotations = [], forces = [];
rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = [];
for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
for (var i = 0; i < aEvent[touchType].length; i++) {
@ -85,12 +85,15 @@ function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
rys.push(aEvent[touchType][i].radius.y);
rotations.push(aEvent[touchType][i].rotationAngle);
forces.push(aEvent[touchType][i].force);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
}
}
return windowUtils.sendTouchEvent(aType,
ids, xs, ys, rxs, rys,
rotations, forces,
rotations, forces, tiltXs, tiltYs, twists,
aModifiers, 0);
}

Просмотреть файл

@ -39,6 +39,9 @@
var rys = [];
var angles = [];
var forces = [];
var tiltXs = [];
var tiltYs = [];
var twists = [];
for (var i = 0; i < targets.length; ++i) {
touches.push(++touchCounter);
var rect = targets[i].getBoundingClientRect();
@ -52,11 +55,14 @@
rys.push(1);
angles.push(0);
forces.push(1);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
winUtils.sendTouchEvent("touchstart",
touches, xs, ys, rxs, rys, angles, forces, 0);
touches, xs, ys, rxs, rys, angles, forces, tiltXs, tiltYs, twists, 0);
winUtils.sendTouchEvent("touchend",
touches, xs, ys, rxs, rys, angles, forces, 0);
touches, xs, ys, rxs, rys, angles, forces, tiltXs, tiltYs, twists, 0);
}
function next() {

Просмотреть файл

@ -393,6 +393,9 @@ interface nsIDOMWindowUtils : nsISupports {
* @param rys array of radii in CSS pixels for each touch to be sent
* @param rotationAngles array of angles in degrees for each touch to be sent
* @param forces array of forces (floats from 0 to 1) for each touch to be sent
* @param tiltXs array of tiltX for each touch to be sent
* @param tiltYs array of tiltY for each touch to be sent
* @param twists array of twist for each touch to be sent
* @param count number of touches in this set
* @param aModifiers modifiers pressed, using constants defined as MODIFIER_*
* @param aIgnoreRootScrollFrame whether the event should ignore viewport bounds
@ -409,6 +412,9 @@ interface nsIDOMWindowUtils : nsISupports {
in Array<uint32_t> aRys,
in Array<float> aRotationAngles,
in Array<float> aForces,
in Array<long> aTiltXs,
in Array<long> aTiltYs,
in Array<long> aTwists,
in long aModifiers,
[optional] in boolean aIgnoreRootScrollFrame);
@ -442,6 +448,9 @@ interface nsIDOMWindowUtils : nsISupports {
in Array<uint32_t> aRys,
in Array<float> aRotationAngles,
in Array<float> aForces,
in Array<long> aTiltXs,
in Array<long> aTiltYs,
in Array<long> aTwists,
in long aModifiers,
[optional] in boolean aIgnoreRootScrollFrame);

Просмотреть файл

@ -54,7 +54,7 @@ function touchEvent(aOptions) {
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
var ids = [], xs=[], ys=[], rxs = [], rys = [],
rotations = [], forces = [];
rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = [];
for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
for (var i = 0; i < aEvent[touchType].length; i++) {
@ -66,12 +66,15 @@ function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
rys.push(aEvent[touchType][i].radius.y);
rotations.push(aEvent[touchType][i].rotationAngle);
forces.push(aEvent[touchType][i].force);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
}
}
return windowUtils.sendTouchEvent(aType,
ids, xs, ys, rxs, rys,
rotations, forces,
rotations, forces, tiltXs, tiltYs, twists,
aModifiers, 0);
}

Просмотреть файл

@ -54,7 +54,7 @@ function touchEvent(aOptions) {
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
var ids = [], xs=[], ys=[], rxs = [], rys = [],
rotations = [], forces = [];
rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = [];
for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
for (var i = 0; i < aEvent[touchType].length; i++) {
@ -66,12 +66,15 @@ function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
rys.push(aEvent[touchType][i].radius.y);
rotations.push(aEvent[touchType][i].rotationAngle);
forces.push(aEvent[touchType][i].force);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
}
}
return windowUtils.sendTouchEvent(aType,
ids, xs, ys, rxs, rys,
rotations, forces,
rotations, forces, tiltXs, tiltYs, twists,
aModifiers, 0);
}

Просмотреть файл

@ -149,12 +149,12 @@ class AccessibleCaretSelectionModeTestCase(MarionetteTestCase):
let utils = window.windowUtils;
utils.sendTouchEventToWindow('touchstart', [0],
[arguments[0]], [arguments[1]],
[1], [1], [0], [1], 0);
[1], [1], [0], [1], [0], [0], [0], 0);
utils.sendMouseEventToWindow('mouselongtap', arguments[0], arguments[1],
0, 1, 0);
utils.sendTouchEventToWindow('touchend', [0],
[arguments[0]], [arguments[1]],
[1], [1], [0], [1], 0);
[1], [1], [0], [1], [0], [0], [0], 0);
""",
script_args=[target_x, target_y],
sandbox="system",

Просмотреть файл

@ -41,7 +41,7 @@ function touchEvent(aOptions) {
function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
var ids = [], xs=[], ys=[], rxs = [], rys = [],
rotations = [], forces = [];
rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = [];
for (var touchType of ["touches", "changedTouches", "targetTouches"]) {
for (var i = 0; i < aEvent[touchType].length; i++) {
@ -53,12 +53,15 @@ function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) {
rys.push(aEvent[touchType][i].radius.y);
rotations.push(aEvent[touchType][i].rotationAngle);
forces.push(aEvent[touchType][i].force);
tiltXs.push(0);
tiltYs.push(0);
twists.push(0);
}
}
}
return windowUtils.sendTouchEvent(aType,
ids, xs, ys, rxs, rys,
rotations, forces,
rotations, forces, tiltXs, tiltYs, twists,
aModifiers, 0);
}

Просмотреть файл

@ -16,7 +16,7 @@ var div1 = document.getElementById("div1");
function sendTouch(aType, aX, aY) {
var cwu = SpecialPowers.getDOMWindowUtils(window);
cwu.sendTouchEvent(aType, [0], [aX], [aY], [1], [1], [0], [1], 0, true);
cwu.sendTouchEvent(aType, [0], [aX], [aY], [1], [1], [0], [1], [0], [0], [0], 0, true);
}
function test()

Просмотреть файл

@ -2042,6 +2042,9 @@ class MultiTouchEventData extends PointerEventData {
this.ry = [];
this.angle = [];
this.force = [];
this.tiltx = [];
this.tilty = [];
this.twist = [];
this.#setGlobalState = false;
}
@ -2059,6 +2062,9 @@ class MultiTouchEventData extends PointerEventData {
this.ry.push(action.height || 1);
this.angle.push(0);
this.force.push(action.pressure || (this.type === "touchend" ? 0 : 1));
this.tiltx.push(action.tiltX || 0);
this.tilty.push(action.tiltY || 0);
this.twist.push(action.twist || 0);
}
update(state, inputSource) {

Просмотреть файл

@ -178,6 +178,9 @@ event.synthesizeMultiTouch = function(opts, win) {
opts.ry,
opts.angle,
opts.force,
opts.tiltx,
opts.tilty,
opts.twist,
modifiers
);
};

Просмотреть файл

@ -207,6 +207,9 @@ action.Chain.prototype.emitTouchEvent = function(doc, type, touch) {
[touch.radiusY],
[touch.rotationAngle],
[touch.force],
[0],
[0],
[0],
0
);
};

Просмотреть файл

@ -22,6 +22,8 @@
* synthesizeDrop
* synthesizePlainDragAndDrop
* synthesizePlainDragAndCancel
* synthesizeTouch
* synthesizeTouchAtCenter
*
* When adding methods to this file, please add a performance test for it.
*/
@ -691,6 +693,9 @@ function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window) {
var ry = aEvent.ry || 1;
var angle = aEvent.angle || 0;
var force = aEvent.force || (aEvent.type === "touchend" ? 0 : 1);
var tiltX = aEvent.tiltX || 0;
var tiltY = aEvent.tiltY || 0;
var twist = aEvent.twist || 0;
var modifiers = _parseModifiers(aEvent, aWindow);
if ("type" in aEvent && aEvent.type) {
@ -703,6 +708,9 @@ function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window) {
[ry],
[angle],
[force],
[tiltX],
[tiltY],
[twist],
modifiers
);
} else {
@ -715,6 +723,9 @@ function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window) {
[ry],
[angle],
[force],
[tiltX],
[tiltY],
[twist],
modifiers
);
utils.sendTouchEvent(
@ -726,6 +737,9 @@ function synthesizeTouchAtPoint(left, top, aEvent, aWindow = window) {
[ry],
[angle],
[force],
[tiltX],
[tiltY],
[twist],
modifiers
);
}
@ -746,7 +760,12 @@ function synthesizeMouseAtCenter(aTarget, aEvent, aWindow) {
}
function synthesizeTouchAtCenter(aTarget, aEvent, aWindow) {
var rect = aTarget.getBoundingClientRect();
synthesizeTouch(aTarget, rect.width / 2, rect.height / 2, aEvent, aWindow);
synthesizeTouchAtPoint(
rect.left + rect.width / 2,
rect.top + rect.height / 2,
aEvent,
aWindow
);
}
/**

Просмотреть файл

@ -1,3 +0,0 @@
[pointer_touch.py]
[test_touch_pointer_properties_tilt_twist]
expected: FAIL