Diff
Modified: trunk/LayoutTests/ChangeLog (238343 => 238344)
--- trunk/LayoutTests/ChangeLog 2018-11-17 06:46:55 UTC (rev 238343)
+++ trunk/LayoutTests/ChangeLog 2018-11-17 09:29:52 UTC (rev 238344)
@@ -1,3 +1,40 @@
+2018-11-16 Antoine Quint <grao...@apple.com>
+
+ [Pointer Events] event.isPrimary doesn't always represent the oldest active touch
+ https://bugs.webkit.org/show_bug.cgi?id=191752
+ <rdar://problem/46129270>
+
+ Reviewed by Dean Jackson.
+
+ Add a new test that checks that adding a touch after another existing touch does not make it be
+ the primary touch, but that removing the first touch makes the second touch become the primary touch.
+
+ To do this we add a new ui.sequence() method that allows a series of touch actions to be performed
+ in a linear sequence. The test author can create a finger and call various actions on it, currently
+ begin(), move() and end().
+
+ When these actions are processed, we compute all "stationary" actions for each part of the sequence
+ so that we can provide this to the uiController.sendEventStream() function.
+
+ Finally, we add a way to track events received by the target and assert that the events that were
+ received match those that were expected.
+
+ * pointerevents/ios/pointer-events-is-primary-expected.txt: Added.
+ * pointerevents/ios/pointer-events-is-primary.html: Added.
+ * pointerevents/utils.js:
+ (prototype.handleEvent):
+ (prototype.assertMatchesEvents):
+ (const.ui.new.UIController):
+ (const.ui.new.UIController.prototype.finger):
+ (const.ui.new.UIController.prototype.pinchOut):
+ (const.ui.new.UIController.prototype.sequence):
+ (const.ui.new.UIController.prototype._runEvents):
+ (prototype.begin):
+ (prototype.move):
+ (prototype.end):
+ (prototype.stationary):
+ (prototype._action):
+
2018-11-16 Devin Rousso <drou...@apple.com>
Web Inspector: Audit: minor style improvements
Added: trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary-expected.txt (0 => 238344)
--- trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary-expected.txt (rev 0)
+++ trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary-expected.txt 2018-11-17 09:29:52 UTC (rev 238344)
@@ -0,0 +1,3 @@
+
+PASS Oldest active touch has isPrimary = true.
+
Added: trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary.html (0 => 238344)
--- trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary.html (rev 0)
+++ trunk/LayoutTests/pointerevents/ios/pointer-events-is-primary.html 2018-11-17 09:29:52 UTC (rev 238344)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script>
+
+'use strict';
+
+target_test((target, test) => {
+ const eventTracker = new EventTracker(target, ["pointerdown", "pointermove"]);
+
+ const _one_ = ui.finger();
+ const two = ui.finger();
+ ui.sequence([
+ one.begin({ x: 10, y: 10 }),
+ two.begin({ x: 50, y: 50 }),
+ two.move({ x: 70, y: 70 }),
+ one.move({ x: 30, y: 30 }),
+ one.end(),
+ two.move({ x: 50, y: 50 })
+ ]).then(() => {
+ eventTracker.assertMatchesEvents([
+ { id: 1, type: "pointerdown", x: 10, y: 10, isPrimary: true },
+ { id: 2, type: "pointerdown", x: 50, y: 50, isPrimary: false },
+ { id: 2, type: "pointermove", x: 70, y: 70, isPrimary: false },
+ { id: 1, type: "pointermove", x: 30, y: 30, isPrimary: true },
+ { id: 2, type: "pointermove", x: 50, y: 50, isPrimary: true }
+ ]);
+ test.done();
+ });
+}, "Oldest active touch has isPrimary = true.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/LayoutTests/pointerevents/utils.js (238343 => 238344)
--- trunk/LayoutTests/pointerevents/utils.js 2018-11-17 06:46:55 UTC (rev 238343)
+++ trunk/LayoutTests/pointerevents/utils.js 2018-11-17 09:29:52 UTC (rev 238344)
@@ -32,8 +32,61 @@
}, description);
}
+class EventTracker
+{
+
+ constructor(target, eventNames)
+ {
+ this.target = target;
+ this.events = [];
+ this.pointerIdToTouchIdMap = {};
+
+ for (let eventName of eventNames)
+ target.addEventListener(eventName, this);
+ }
+
+ handleEvent(event)
+ {
+ if (!this.pointerIdToTouchIdMap[event.pointerId])
+ this.pointerIdToTouchIdMap[event.pointerId] = Object.keys(this.pointerIdToTouchIdMap).length + 1;
+
+ const id = this.pointerIdToTouchIdMap[event.pointerId];
+ this.events.push({
+ id,
+ type: event.type,
+ x: event.clientX,
+ y: event.clientY,
+ isPrimary: event.isPrimary
+ });
+ }
+
+ assertMatchesEvents(expectedEvents)
+ {
+ assert_true(!!this.events.length, "Event tracker saw some events.");
+ assert_equals(expectedEvents.length, this.events.length, "Expected events and actual events have the same length.");
+ for (let i = 0; i < expectedEvents.length; ++i) {
+ const expectedEvent = expectedEvents[i];
+ const actualEvent = this.events[i];
+ for (let property of Object.getOwnPropertyNames(expectedEvent))
+ assert_equals(expectedEvent[property], actualEvent[property], `Property ${property} matches for event at index ${i}.`);
+ }
+ }
+
+}
+
const ui = new (class UIController {
+ constructor()
+ {
+ this.fingers = {};
+ }
+
+ finger()
+ {
+ const id = Object.keys(this.fingers).length + 1;
+ return this.fingers[id] = new Finger(id);
+ }
+
beginTouches(options)
{
return this._run(`uiController.touchDownAtPoint(${options.x}, ${options.y}, ${options.numberOfTouches || 1})`);
@@ -92,18 +145,52 @@
]
};
- return this._runEvents({
+ return this._runEvents([{
interpolate : "linear",
timestep: 0.1,
coordinateSpace : "content",
startEvent: startEvent,
endEvent: endEvent
- });
+ }]);
}
+ sequence(touches)
+ {
+ const activeFingers = {};
+
+ return this._runEvents(touches.map((touches, index) => {
+ if (!Array.isArray(touches))
+ touches = [touches];
+
+ const processedIDs = {};
+
+ // Update the list of active touches.
+ touches.forEach(touch => {
+ processedIDs[touch.id] = true;
+ if (touch.phase === "ended")
+ delete activeFingers[touch.id];
+ else
+ activeFingers[touch.id] = { x: touch.x, y: touch.y };
+ });
+
+ // Now go through the active touches and check that they're all listed in the new touches.
+ for (let id in activeFingers) {
+ if (!processedIDs[id])
+ touches.push(this.fingers[id].stationary(activeFingers[id]));
+ }
+
+ return {
+ inputType : "hand",
+ timeOffset : index * 0.05,
+ coordinateSpace : "content",
+ touches : touches
+ }
+ }));
+ }
+
_runEvents(events)
{
- return this._run(`uiController.sendEventStream('${JSON.stringify({ events: [events] })}')`);
+ return this._run(`uiController.sendEventStream('${JSON.stringify({ events })}')`);
}
_run(command)
@@ -115,3 +202,40 @@
}
})();
+
+class Finger
+{
+
+ constructor(id)
+ {
+ this.id = id;
+ }
+
+ begin(options)
+ {
+ return this._action("began", options.x || 0, options.y || 0);
+ }
+
+ move(options)
+ {
+ return this._action("moved", options.x || 0, options.y || 0);
+ }
+
+ end(options)
+ {
+ return this._action("ended", this._lastX, this._lastY);
+ }
+
+ stationary(options)
+ {
+ return this._action("stationary", options.x || 0, options.y || 0);
+ }
+
+ _action(phase, x, y)
+ {
+ this._lastX = x;
+ this._lastY = y;
+ return { inputType: "finger", id: this.id, phase, x, y };
+ }
+
+}
Modified: trunk/Source/WebCore/ChangeLog (238343 => 238344)
--- trunk/Source/WebCore/ChangeLog 2018-11-17 06:46:55 UTC (rev 238343)
+++ trunk/Source/WebCore/ChangeLog 2018-11-17 09:29:52 UTC (rev 238344)
@@ -1,3 +1,21 @@
+2018-11-16 Antoine Quint <grao...@apple.com>
+
+ [Pointer Events] event.isPrimary doesn't always represent the oldest active touch
+ https://bugs.webkit.org/show_bug.cgi?id=191752
+ <rdar://problem/46129270>
+
+ Reviewed by Dean Jackson.
+
+ Provide isPrimary to the constructor so its value can be determined at the call site.
+
+ Test: pointerevents/ios/pointer-events-is-primary.html
+
+ * dom/PointerEvent.h:
+ * dom/ios/PointerEventIOS.cpp:
+ (WebCore::PointerEvent::create):
+ (WebCore::PointerEvent::PointerEvent):
+ (WebCore::m_isPrimary):
+
2018-11-16 Alex Christensen <achristen...@webkit.org>
Tweak _showSafeBrowsingWarningWithTitle SPI
Modified: trunk/Source/WebCore/dom/PointerEvent.h (238343 => 238344)
--- trunk/Source/WebCore/dom/PointerEvent.h 2018-11-17 06:46:55 UTC (rev 238343)
+++ trunk/Source/WebCore/dom/PointerEvent.h 2018-11-17 09:29:52 UTC (rev 238344)
@@ -60,7 +60,7 @@
}
#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
- static Ref<PointerEvent> create(const PlatformTouchEvent&, unsigned touchIndex, Ref<WindowProxy>&&);
+ static Ref<PointerEvent> create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
#endif
virtual ~PointerEvent();
@@ -84,7 +84,7 @@
PointerEvent();
PointerEvent(const AtomicString&, Init&&);
#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS_FAMILY)
- PointerEvent(const AtomicString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, Ref<WindowProxy>&&);
+ PointerEvent(const AtomicString& type, const PlatformTouchEvent&, IsCancelable isCancelable, unsigned touchIndex, bool isPrimary, Ref<WindowProxy>&&);
#endif
long m_pointerId { 0 };
Modified: trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp (238343 => 238344)
--- trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp 2018-11-17 06:46:55 UTC (rev 238343)
+++ trunk/Source/WebCore/dom/ios/PointerEventIOS.cpp 2018-11-17 09:29:52 UTC (rev 238344)
@@ -57,19 +57,19 @@
return PointerEvent::IsCancelable::Yes;
}
-Ref<PointerEvent> PointerEvent::create(const PlatformTouchEvent& event, unsigned index, Ref<WindowProxy>&& view)
+Ref<PointerEvent> PointerEvent::create(const PlatformTouchEvent& event, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
{
auto phase = event.touchPhaseAtIndex(index);
- return adoptRef(*new PointerEvent(eventType(phase), event, phaseIsCancelable(phase), index, WTFMove(view)));
+ return adoptRef(*new PointerEvent(eventType(phase), event, phaseIsCancelable(phase), index, isPrimary, WTFMove(view)));
}
-PointerEvent::PointerEvent(const AtomicString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, Ref<WindowProxy>&& view)
+PointerEvent::PointerEvent(const AtomicString& type, const PlatformTouchEvent& event, IsCancelable isCancelable, unsigned index, bool isPrimary, Ref<WindowProxy>&& view)
: MouseEvent(type, CanBubble::Yes, isCancelable, IsComposed::Yes, event.timestamp().approximateMonotonicTime(), WTFMove(view), 0, event.touchLocationAtIndex(index), event.touchLocationAtIndex(index), { }, event.modifiers(), 0, 0, nullptr, 0, 0, nullptr, IsSimulated::No, IsTrusted::Yes)
, m_pointerId(event.touchIdentifierAtIndex(index))
, m_width(2 * event.radiusXAtIndex(index))
, m_height(2 * event.radiusYAtIndex(index))
, m_pointerType(event.touchTypeAtIndex(index) == PlatformTouchPoint::TouchType::Stylus ? "pen"_s : "touch"_s)
- , m_isPrimary(!index)
+ , m_isPrimary(isPrimary)
{
}