Skip to content

Commit

Permalink
Add getCoalescedEvents API to PointerEvent
Browse files Browse the repository at this point in the history
Adding getCoalescedEvents API to the idl file
of PointerEventInit and getter method to
PointerEvent idl.
Also add the plumbing and creation in EventHandler
layer and PointerEventManager.

BUG=665937

Review-Url: https://codereview.chromium.org/2510133002
Cr-Commit-Position: refs/heads/master@{#434849}
  • Loading branch information
NavidZ authored and Commit bot committed Nov 29, 2016
1 parent e19337b commit 92109db
Show file tree
Hide file tree
Showing 25 changed files with 506 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,14 @@ PASS new PointerEvent('eventType').metaKey is false
PASS new PointerEvent('eventType').button is 0
PASS new PointerEvent('eventType').buttons is 0
PASS new PointerEvent('eventType').relatedTarget is null
--- tests for coalesced events ---
PASS pe.getCoalescedEvents().length is 2
PASS pe.pressure is within 0.00001 of 0.1
PASS pe.getCoalescedEvents()[0].pressure is within 0.00001 of 1
PASS pe.getCoalescedEvents()[1].pressure is within 0.00001 of 0.5
PASS pe.pointerId is 1
PASS pe.getCoalescedEvents()[0].pointerId is 2
PASS pe.getCoalescedEvents()[1].pointerId is 2
PASS successfullyParsed is true

TEST COMPLETE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,21 @@
shouldBeZero("new PointerEvent('eventType').buttons");
shouldBeNull("new PointerEvent('eventType').relatedTarget");

debug("--- tests for coalesced events ---");
var coalescedEvents = [
new PointerEvent('eventType', { 'pressure' : 1, pointerId : 2 }),
new PointerEvent('eventType', { 'pressure' : 0.5, pointerId : 2 }),
];
var pe = new PointerEvent('eventType', {'coalescedEvents': coalescedEvents, 'pressure' : 0.1, pointerId : 1 });
shouldBeEqualToNumber("pe.getCoalescedEvents().length", coalescedEvents.length);

shouldBeCloseTo("pe.pressure", 0.1, 0.00001);
shouldBeCloseTo("pe.getCoalescedEvents()[0].pressure", 1, 0.00001);
shouldBeCloseTo("pe.getCoalescedEvents()[1].pressure", 0.5, 0.00001);

shouldBeEqualToNumber("pe.pointerId", 1);
shouldBeEqualToNumber("pe.getCoalescedEvents()[0].pointerId", 2);
shouldBeEqualToNumber("pe.getCoalescedEvents()[1].pointerId", 2);


</script>
Original file line number Diff line number Diff line change
Expand Up @@ -4730,6 +4730,7 @@ interface PointerEvent : MouseEvent
getter tiltY
getter width
method constructor
method getCoalescedEvents
interface PopStateEvent : Event
attribute @@toStringTag
getter state
Expand Down
9 changes: 9 additions & 0 deletions third_party/WebKit/Source/core/events/PointerEvent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ PointerEvent::PointerEvent(const AtomicString& type,
m_pointerType = initializer.pointerType();
if (initializer.hasIsPrimary())
m_isPrimary = initializer.isPrimary();
if (initializer.hasCoalescedEvents()) {
for (auto coalescedEvent : initializer.coalescedEvents())
m_coalescedEvents.append(coalescedEvent);
}
}

bool PointerEvent::isMouseEvent() const {
Expand All @@ -49,7 +53,12 @@ EventDispatchMediator* PointerEvent::createMediator() {
return PointerEventDispatchMediator::create(this);
}

HeapVector<Member<PointerEvent>> PointerEvent::getCoalescedEvents() const {
return m_coalescedEvents;
}

DEFINE_TRACE(PointerEvent) {
visitor->trace(m_coalescedEvents);
MouseEvent::trace(visitor);
}

Expand Down
6 changes: 5 additions & 1 deletion third_party/WebKit/Source/core/events/PointerEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace blink {

class PointerEvent final : public MouseEvent {
class CORE_EXPORT PointerEvent final : public MouseEvent {
DEFINE_WRAPPERTYPEINFO();

public:
Expand All @@ -35,6 +35,8 @@ class PointerEvent final : public MouseEvent {

EventDispatchMediator* createMediator() override;

HeapVector<Member<PointerEvent>> getCoalescedEvents() const;

DECLARE_VIRTUAL_TRACE();

private:
Expand All @@ -48,6 +50,8 @@ class PointerEvent final : public MouseEvent {
long m_tiltY;
String m_pointerType;
bool m_isPrimary;

HeapVector<Member<PointerEvent>> m_coalescedEvents;
};

class PointerEventDispatchMediator final : public EventDispatchMediator {
Expand Down
2 changes: 2 additions & 0 deletions third_party/WebKit/Source/core/events/PointerEvent.idl
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@
[MeasureAs=PointerEventAttributeCount] readonly attribute long tiltY;
[MeasureAs=PointerEventAttributeCount] readonly attribute DOMString pointerType;
[MeasureAs=PointerEventAttributeCount] readonly attribute boolean isPrimary;

[RuntimeEnabled=CoalescedEvents] sequence<PointerEvent> getCoalescedEvents();
};
186 changes: 138 additions & 48 deletions third_party/WebKit/Source/core/events/PointerEventFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,99 @@ unsigned short buttonToButtonsBitfield(WebPointerProperties::Button button) {
return 0;
}

} // namespace

const int PointerEventFactory::s_invalidId = 0;

// Mouse id is 1 to behave the same as MS Edge for compatibility reasons.
const int PointerEventFactory::s_mouseId = 1;
const AtomicString& pointerEventNameForTouchPointState(
PlatformTouchPoint::TouchState state) {
switch (state) {
case PlatformTouchPoint::TouchReleased:
return EventTypeNames::pointerup;
case PlatformTouchPoint::TouchCancelled:
return EventTypeNames::pointercancel;
case PlatformTouchPoint::TouchPressed:
return EventTypeNames::pointerdown;
case PlatformTouchPoint::TouchMoved:
return EventTypeNames::pointermove;
case PlatformTouchPoint::TouchStationary:
// Fall through to default
default:
NOTREACHED();
return emptyAtom;
}
}

float getPointerEventPressure(float force, int buttons) {
if (std::isnan(force))
return buttons ? 0.5 : 0;
return force;
}

void updateTouchPointerEventInit(const PlatformTouchPoint& touchPoint,
LocalFrame* targetFrame,
PointerEventInit* pointerEventInit) {
// This function should not update attributes like pointerId, isPrimary,
// and pointerType which is the same among the coalesced events and the
// dispatched event.

if (targetFrame) {
FloatPoint pagePoint =
targetFrame->view()->rootFrameToContents(touchPoint.pos());
float scaleFactor = 1.0f / targetFrame->pageZoomFactor();
FloatPoint scrollPosition(targetFrame->view()->scrollOffset());
FloatPoint clientPoint = pagePoint.scaledBy(scaleFactor);
clientPoint.moveBy(scrollPosition.scaledBy(-scaleFactor));

pointerEventInit->setClientX(clientPoint.x());
pointerEventInit->setClientY(clientPoint.y());

FloatSize pointRadius = touchPoint.radius().scaledBy(scaleFactor);
pointerEventInit->setWidth(pointRadius.width());
pointerEventInit->setHeight(pointRadius.height());
}

pointerEventInit->setScreenX(touchPoint.screenPos().x());
pointerEventInit->setScreenY(touchPoint.screenPos().y());
pointerEventInit->setPressure(
getPointerEventPressure(touchPoint.force(), pointerEventInit->buttons()));
pointerEventInit->setTiltX(touchPoint.pointerProperties().tiltX);
pointerEventInit->setTiltY(touchPoint.pointerProperties().tiltY);
}

void updateMousePointerEventInit(const PlatformMouseEvent& mouseEvent,
LocalDOMWindow* view,
PointerEventInit* pointerEventInit) {
// This function should not update attributes like pointerId, isPrimary,
// and pointerType which is the same among the coalesced events and the
// dispatched event.

pointerEventInit->setScreenX(mouseEvent.globalPosition().x());
pointerEventInit->setScreenY(mouseEvent.globalPosition().y());

IntPoint locationInFrameZoomed;
if (view && view->frame() && view->frame()->view()) {
LocalFrame* frame = view->frame();
FrameView* frameView = frame->view();
IntPoint locationInContents =
frameView->rootFrameToContents(mouseEvent.position());
locationInFrameZoomed = frameView->contentsToFrame(locationInContents);
float scaleFactor = 1 / frame->pageZoomFactor();
locationInFrameZoomed.scale(scaleFactor, scaleFactor);
}

pointerEventInit->setClientX(locationInFrameZoomed.x());
pointerEventInit->setClientY(locationInFrameZoomed.y());

pointerEventInit->setPressure(getPointerEventPressure(
mouseEvent.pointerProperties().force, pointerEventInit->buttons()));
pointerEventInit->setTiltX(mouseEvent.pointerProperties().tiltX);
pointerEventInit->setTiltY(mouseEvent.pointerProperties().tiltY);
}

} // namespace

const int PointerEventFactory::s_invalidId = 0;

// Mouse id is 1 to behave the same as MS Edge for compatibility reasons.
const int PointerEventFactory::s_mouseId = 1;

void PointerEventFactory::setIdTypeButtons(
PointerEventInit& pointerEventInit,
const WebPointerProperties& pointerProperties,
Expand Down Expand Up @@ -128,40 +208,27 @@ void PointerEventFactory::setEventSpecificFields(
pointerEventInit.setDetail(0);
}

PointerEvent* PointerEventFactory::create(const AtomicString& mouseEventName,
const PlatformMouseEvent& mouseEvent,
LocalDOMWindow* view) {
PointerEvent* PointerEventFactory::create(
const AtomicString& mouseEventName,
const PlatformMouseEvent& mouseEvent,
const Vector<PlatformMouseEvent>& coalescedMouseEvents,
LocalDOMWindow* view) {
DCHECK(mouseEventName == EventTypeNames::mousemove ||
mouseEventName == EventTypeNames::mousedown ||
mouseEventName == EventTypeNames::mouseup);

AtomicString pointerEventName =
pointerEventNameForMouseEventName(mouseEventName);
DCHECK(pointerEventName == EventTypeNames::pointermove ||
coalescedMouseEvents.isEmpty());

unsigned buttons =
MouseEvent::platformModifiersToButtons(mouseEvent.getModifiers());
PointerEventInit pointerEventInit;

setIdTypeButtons(pointerEventInit, mouseEvent.pointerProperties(), buttons);
setEventSpecificFields(pointerEventInit, pointerEventName);

pointerEventInit.setScreenX(mouseEvent.globalPosition().x());
pointerEventInit.setScreenY(mouseEvent.globalPosition().y());

IntPoint locationInFrameZoomed;
if (view && view->frame() && view->frame()->view()) {
LocalFrame* frame = view->frame();
FrameView* frameView = frame->view();
IntPoint locationInContents =
frameView->rootFrameToContents(mouseEvent.position());
locationInFrameZoomed = frameView->contentsToFrame(locationInContents);
float scaleFactor = 1 / frame->pageZoomFactor();
locationInFrameZoomed.scale(scaleFactor, scaleFactor);
}

// Set up initial values for coordinates.
pointerEventInit.setClientX(locationInFrameZoomed.x());
pointerEventInit.setClientY(locationInFrameZoomed.y());

if (pointerEventName == EventTypeNames::pointerdown ||
pointerEventName == EventTypeNames::pointerup) {
WebPointerProperties::Button button = mouseEvent.pointerProperties().button;
Expand All @@ -176,10 +243,6 @@ PointerEvent* PointerEventFactory::create(const AtomicString& mouseEventName,
pointerEventInit.setButton(
static_cast<int>(WebPointerProperties::Button::NoButton));
}
pointerEventInit.setPressure(getPointerEventPressure(
mouseEvent.pointerProperties().force, pointerEventInit.buttons()));
pointerEventInit.setTiltX(mouseEvent.pointerProperties().tiltX);
pointerEventInit.setTiltY(mouseEvent.pointerProperties().tiltY);

UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit,
mouseEvent.getModifiers());
Expand All @@ -194,16 +257,36 @@ PointerEvent* PointerEventFactory::create(const AtomicString& mouseEventName,

pointerEventInit.setView(view);

updateMousePointerEventInit(mouseEvent, view, &pointerEventInit);

// Created coalesced events init structure
HeapVector<Member<PointerEvent>> coalescedPointerEvents;
for (const auto& coalescedMouseEvent : coalescedMouseEvents) {
DCHECK_EQ(mouseEvent.pointerProperties().id,
coalescedMouseEvent.pointerProperties().id);
DCHECK_EQ(mouseEvent.pointerProperties().pointerType,
coalescedMouseEvent.pointerProperties().pointerType);
PointerEventInit coalescedEventInit = pointerEventInit;
updateMousePointerEventInit(coalescedMouseEvent, view, &coalescedEventInit);
coalescedPointerEvents.append(
PointerEvent::create(pointerEventName, coalescedEventInit));
}
pointerEventInit.setCoalescedEvents(coalescedPointerEvents);

return PointerEvent::create(pointerEventName, pointerEventInit);
}

PointerEvent* PointerEventFactory::create(const AtomicString& type,
const PlatformTouchPoint& touchPoint,
PlatformEvent::Modifiers modifiers,
const FloatSize& pointRadius,
const FloatPoint& clientPoint,
DOMWindow* view) {
PointerEvent* PointerEventFactory::create(
const PlatformTouchPoint& touchPoint,
const Vector<PlatformTouchPoint>& coalescedPoints,
PlatformEvent::Modifiers modifiers,
LocalFrame* targetFrame,
DOMWindow* view) {
const PlatformTouchPoint::TouchState pointState = touchPoint.state();
const AtomicString& type =
pointerEventNameForTouchPointState(touchPoint.state());

DCHECK(type == EventTypeNames::pointermove || coalescedPoints.isEmpty());

bool pointerReleasedOrCancelled =
pointState == PlatformTouchPoint::TouchReleased ||
Expand All @@ -216,26 +299,33 @@ PointerEvent* PointerEventFactory::create(const AtomicString& type,

setIdTypeButtons(pointerEventInit, touchPoint.pointerProperties(),
pointerReleasedOrCancelled ? 0 : 1);

pointerEventInit.setWidth(pointRadius.width());
pointerEventInit.setHeight(pointRadius.height());
pointerEventInit.setScreenX(touchPoint.screenPos().x());
pointerEventInit.setScreenY(touchPoint.screenPos().y());
pointerEventInit.setClientX(clientPoint.x());
pointerEventInit.setClientY(clientPoint.y());
pointerEventInit.setButton(static_cast<int>(
pointerPressedOrReleased ? WebPointerProperties::Button::Left
: WebPointerProperties::Button::NoButton));
pointerEventInit.setPressure(
getPointerEventPressure(touchPoint.force(), pointerEventInit.buttons()));
pointerEventInit.setTiltX(touchPoint.pointerProperties().tiltX);
pointerEventInit.setTiltY(touchPoint.pointerProperties().tiltY);

pointerEventInit.setView(view);
updateTouchPointerEventInit(touchPoint, targetFrame, &pointerEventInit);

UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, modifiers);

setEventSpecificFields(pointerEventInit, type);

// Created coalesced events init structure
HeapVector<Member<PointerEvent>> coalescedPointerEvents;
for (const auto& coalescedTouchPoint : coalescedPoints) {
DCHECK_EQ(touchPoint.state(), coalescedTouchPoint.state());
DCHECK_EQ(touchPoint.pointerProperties().id,
coalescedTouchPoint.pointerProperties().id);
DCHECK_EQ(touchPoint.pointerProperties().pointerType,
coalescedTouchPoint.pointerProperties().pointerType);
PointerEventInit coalescedEventInit = pointerEventInit;
updateTouchPointerEventInit(coalescedTouchPoint, targetFrame,
&coalescedEventInit);
coalescedPointerEvents.append(
PointerEvent::create(type, coalescedEventInit));
}
pointerEventInit.setCoalescedEvents(coalescedPointerEvents);

return PointerEvent::create(type, pointerEventInit);
}

Expand Down
8 changes: 4 additions & 4 deletions third_party/WebKit/Source/core/events/PointerEventFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ class CORE_EXPORT PointerEventFactory {

PointerEvent* create(const AtomicString& mouseEventName,
const PlatformMouseEvent&,
const Vector<PlatformMouseEvent>&,
LocalDOMWindow*);

PointerEvent* create(const AtomicString& type,
const PlatformTouchPoint&,
PointerEvent* create(const PlatformTouchPoint&,
const Vector<PlatformTouchPoint>&,
PlatformEvent::Modifiers,
const FloatSize& pointRadius,
const FloatPoint& clientPoint,
LocalFrame*,
DOMWindow*);

PointerEvent* createPointerCancelEvent(
Expand Down
Loading

0 comments on commit 92109db

Please sign in to comment.