Skip to content

Commit b989625

Browse files
committed
Compute the correct pageX/Y for touch events.
Previously, pageX/Y were always the same as clientX/Y, which would be incorrect if the page had been scrolled. Submitted on behalf of a Googler.
1 parent 79d76e3 commit b989625

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

javascript/atoms/device.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ bot.Device.prototype.fireTouchEvent = function(type, id, coord, opt_id2,
214214
scale: 0,
215215
rotation: 0
216216
};
217+
var pageOffset = goog.dom.getDomHelper(this.element_).getDocumentScroll();
217218

218219
function addTouch(identifier, coords) {
219220
// Android devices leave identifier to zero.
@@ -224,8 +225,8 @@ bot.Device.prototype.fireTouchEvent = function(type, id, coord, opt_id2,
224225
screenY: coords.y,
225226
clientX: coords.x,
226227
clientY: coords.y,
227-
pageX: coords.x,
228-
pageY: coords.y
228+
pageX: coords.x + pageOffset.x,
229+
pageY: coords.y + pageOffset.y
229230
};
230231

231232
args.changedTouches.push(touch);

javascript/atoms/events.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,12 +534,14 @@ bot.events.TouchEventFactory_.prototype.create = function(target, opt_args) {
534534
event.rotation = args.rotation;
535535
} else {
536536
event = doc.createEvent('TouchEvent');
537-
if (goog.userAgent.product.ANDROID) {
538-
// Android's initTouchEvent method is not compliant with the W3C spec.
537+
// Different browsers have different implementations of initTouchEvent.
538+
if (event.initTouchEvent.length == 0) {
539+
// Chrome/Android.
539540
event.initTouchEvent(touches, targetTouches, changedTouches,
540541
this.type_, view, /*screenX*/ 0, /*screenY*/ 0, args.clientX,
541542
args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey);
542543
} else {
544+
// iOS.
543545
event.initTouchEvent(this.type_, this.bubbles_, this.cancelable_, view,
544546
/*detail*/ 1, /*screenX*/ 0, /*screenY*/ 0, args.clientX,
545547
args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey,

javascript/atoms/test/touchscreen_test.html

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
<html>
33
<head>
44
<title>touchscreen_test</title>
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
56
<script src="test_bootstrap.js"></script>
67
<script type="text/javascript">
78
goog.require('bot.Touchscreen');
89
goog.require('bot.action');
10+
goog.require('bot.dom');
11+
goog.require('goog.Promise');
912
goog.require('goog.events');
1013
goog.require('goog.events.EventType');
1114
goog.require('goog.math.Coordinate');
@@ -18,6 +21,7 @@
1821
var lowerTarget;
1922
var innerCaptureTarget;
2023
var noTouchTarget;
24+
var coordsTarget;
2125

2226
var touchscreen;
2327
var events = [];
@@ -45,6 +49,7 @@
4549
captureTarget = document.getElementById('captureTarget');
4650
innerCaptureTarget = document.getElementById('innerCaptureTarget');
4751
noTouchTarget = document.getElementById('notouch');
52+
coordsTarget = document.getElementById('coordsTarget');
4853
}
4954

5055
function setUp() {
@@ -55,6 +60,7 @@
5560
goog.events.removeAll(captureTarget);
5661
goog.events.removeAll(innerCaptureTarget);
5762
goog.events.removeAll(noTouchTarget);
63+
goog.events.removeAll(coordsTarget);
5864

5965
goog.events.listen(target, TOUCH_EVENTS, function(e) {
6066
events.push(e.type);
@@ -81,6 +87,16 @@
8187
events.push(e.type);
8288
events.push(e.target);
8389
});
90+
goog.events.listen(coordsTarget, goog.events.EventType.TOUCHSTART,
91+
function(e) {
92+
var event = e.getBrowserEvent();
93+
if (event.changedTouches.length == 1) {
94+
events.push(event.changedTouches[0].clientX);
95+
events.push(event.changedTouches[0].clientY);
96+
events.push(event.changedTouches[0].pageX);
97+
events.push(event.changedTouches[0].pageY);
98+
}
99+
});
84100
}
85101

86102
function msPointerDownEvents(elem) {
@@ -458,6 +474,25 @@
458474
assertEvents(events);
459475
}
460476
}
477+
478+
function testTouchEventCoords() {
479+
if (!bot.events.SUPPORTS_TOUCH_EVENTS || bot.userAgent.IE_DOC_10) {
480+
return;
481+
}
482+
window.scrollTo(20, 30);
483+
// Yield to ensure all browsers apply the scrolling change.
484+
// Relying on the implicit tick in a promise resolution is enough.
485+
return goog.Promise.resolve().then(function() {
486+
var coords = bot.dom.getClientRect(coordsTarget);
487+
touchscreen.move(coordsTarget, new goog.math.Coordinate(0, 0));
488+
touchscreen.press();
489+
touchscreen.release();
490+
// The client coords of the touch event should be the top left of the
491+
// target and the page coords should include the scroll offset.
492+
assertEvents([coords.left, coords.top,
493+
coords.left + 20, coords.top + 30]);
494+
});
495+
}
461496
</script>
462497
</head>
463498
<body>
@@ -502,5 +537,12 @@
502537
-ms-touch-action:auto">
503538
no touch
504539
</div>
540+
<div id="coordsTarget"
541+
style="background-color:magenta;
542+
width:8000px;
543+
height:8000px;
544+
-ms-touch-action:none">
545+
coords target
546+
</div>
505547
</body>
506548
</html>

0 commit comments

Comments
 (0)