author | Stone Shih <sshih@mozilla.com> |
Wed, 20 Sep 2017 13:00:57 +0800 | |
changeset 450995 | 0152c7d3651e74f78d10e98b00675075ae3ab2a3 |
parent 450994 | 80c087207c12814bbbce83abb7a4be552b406a49 |
child 450996 | 767cb7462ef858b377678af010d2111fa35deacb |
push id | 1648 |
push user | mtabara@mozilla.com |
push date | Thu, 01 Mar 2018 12:45:47 +0000 |
treeherder | mozilla-release@cbb9688c2eeb [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1303957 |
milestone | 59.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/events/PointerEvent.cpp +++ b/dom/events/PointerEvent.cpp @@ -2,16 +2,17 @@ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Portions Copyright 2013 Microsoft Open Technologies, Inc. */ #include "mozilla/dom/PointerEvent.h" +#include "mozilla/dom/PointerEventBinding.h" #include "mozilla/MouseEvents.h" #include "prtime.h" namespace mozilla { namespace dom { PointerEvent::PointerEvent(EventTarget* aOwner, nsPresContext* aPresContext, @@ -32,16 +33,23 @@ PointerEvent::PointerEvent(EventTarget* mEvent->mRefPoint = LayoutDeviceIntPoint(0, 0); mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; } // 5.2 Pointer Event types, for all pointer events, |detail| attribute SHOULD // be 0. mDetail = 0; } +JSObject* +PointerEvent::WrapObjectInternal(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) +{ + return PointerEventBinding::Wrap(aCx, this, aGivenProto); +} + static uint16_t ConvertStringToPointerType(const nsAString& aPointerTypeArg) { if (aPointerTypeArg.EqualsLiteral("mouse")) { return nsIDOMMouseEvent::MOZ_SOURCE_MOUSE; } if (aPointerTypeArg.EqualsLiteral("pen")) { return nsIDOMMouseEvent::MOZ_SOURCE_PEN; @@ -96,32 +104,51 @@ PointerEvent::Constructor(EventTarget* a widgetEvent->tangentialPressure = aParam.mTangentialPressure; widgetEvent->tiltX = aParam.mTiltX; widgetEvent->tiltY = aParam.mTiltY; widgetEvent->twist = aParam.mTwist; widgetEvent->inputSource = ConvertStringToPointerType(aParam.mPointerType); widgetEvent->mIsPrimary = aParam.mIsPrimary; widgetEvent->buttons = aParam.mButtons; + if (!aParam.mCoalescedEvents.IsEmpty()) { + e->mCoalescedEvents.AppendElements(aParam.mCoalescedEvents); + } e->SetTrusted(trusted); e->SetComposed(aParam.mComposed); return e.forget(); } // static already_AddRefed<PointerEvent> PointerEvent::Constructor(const GlobalObject& aGlobal, const nsAString& aType, const PointerEventInit& aParam, ErrorResult& aRv) { nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports()); return Constructor(owner, aType, aParam); } +NS_IMPL_CYCLE_COLLECTION_CLASS(PointerEvent) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PointerEvent, MouseEvent) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mCoalescedEvents) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PointerEvent, MouseEvent) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCoalescedEvents) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PointerEvent) +NS_INTERFACE_MAP_END_INHERITING(MouseEvent) + +NS_IMPL_ADDREF_INHERITED(PointerEvent, MouseEvent) +NS_IMPL_RELEASE_INHERITED(PointerEvent, MouseEvent) + void PointerEvent::GetPointerType(nsAString& aPointerType) { ConvertPointerTypeToString(mEvent->AsPointerEvent()->inputSource, aPointerType); } int32_t PointerEvent::PointerId() @@ -172,16 +199,50 @@ PointerEvent::Twist() } bool PointerEvent::IsPrimary() { return mEvent->AsPointerEvent()->mIsPrimary; } +void +PointerEvent::GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents) +{ + WidgetPointerEvent* widgetEvent = mEvent->AsPointerEvent(); + if (mCoalescedEvents.IsEmpty() && widgetEvent && + widgetEvent->mCoalescedWidgetEvents && + !widgetEvent->mCoalescedWidgetEvents->mEvents.IsEmpty()) { + for (WidgetPointerEvent& event : + widgetEvent->mCoalescedWidgetEvents->mEvents) { + RefPtr<PointerEvent> domEvent = + NS_NewDOMPointerEvent(nullptr, nullptr, &event); + + // The coalesced widget mouse events shouldn't have been dispatched. + MOZ_ASSERT(!domEvent->mEvent->mTarget); + // The event target should be the same as the dispatched event's target. + domEvent->mEvent->mTarget = mEvent->mTarget; + + // JS could hold reference to dom events. We have to ask dom event to + // duplicate its private data to avoid the widget event is destroyed. + domEvent->DuplicatePrivateData(); + mCoalescedEvents.AppendElement(domEvent); + } + } + if (mEvent->mTarget) { + for (RefPtr<PointerEvent>& pointerEvent : mCoalescedEvents) { + // Only set event target when it's null. + if (!pointerEvent->mEvent->mTarget) { + pointerEvent->mEvent->mTarget = mEvent->mTarget; + } + } + } + aPointerEvents.AppendElements(mCoalescedEvents); +} + } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; already_AddRefed<PointerEvent> NS_NewDOMPointerEvent(EventTarget* aOwner,
--- a/dom/events/PointerEvent.h +++ b/dom/events/PointerEvent.h @@ -12,27 +12,31 @@ #include "mozilla/dom/MouseEvent.h" #include "mozilla/dom/PointerEventBinding.h" class nsPresContext; namespace mozilla { namespace dom { +struct PointerEventInit; + class PointerEvent : public MouseEvent { public: PointerEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetPointerEvent* aEvent); - virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override - { - return PointerEventBinding::Wrap(aCx, this, aGivenProto); - } + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PointerEvent, MouseEvent) + + virtual JSObject* WrapObjectInternal( + JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<PointerEvent> Constructor(const GlobalObject& aGlobal, const nsAString& aType, const PointerEventInit& aParam, ErrorResult& aRv); static already_AddRefed<PointerEvent> @@ -45,16 +49,23 @@ public: int32_t Height(); float Pressure(); float TangentialPressure(); int32_t TiltX(); int32_t TiltY(); int32_t Twist(); bool IsPrimary(); void GetPointerType(nsAString& aPointerType); + void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents); + +protected: + ~PointerEvent() {} + +private: + nsTArray<RefPtr<PointerEvent>> mCoalescedEvents; }; void ConvertPointerTypeToString(uint16_t aPointerTypeSrc, nsAString& aPointerTypeDest); } // namespace dom } // namespace mozilla already_AddRefed<mozilla::dom::PointerEvent>
--- a/dom/ipc/CoalescedMouseData.cpp +++ b/dom/ipc/CoalescedMouseData.cpp @@ -15,36 +15,54 @@ void CoalescedMouseData::Coalesce(const WidgetMouseEvent& aEvent, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId) { if (IsEmpty()) { mCoalescedInputEvent = MakeUnique<WidgetMouseEvent>(aEvent); mGuid = aGuid; mInputBlockId = aInputBlockId; + MOZ_ASSERT(!mCoalescedInputEvent->mCoalescedWidgetEvents); } else { MOZ_ASSERT(mGuid == aGuid); MOZ_ASSERT(mInputBlockId == aInputBlockId); MOZ_ASSERT(mCoalescedInputEvent->mModifiers == aEvent.mModifiers); MOZ_ASSERT(mCoalescedInputEvent->mReason == aEvent.mReason); MOZ_ASSERT(mCoalescedInputEvent->inputSource == aEvent.inputSource); MOZ_ASSERT(mCoalescedInputEvent->button == aEvent.button); MOZ_ASSERT(mCoalescedInputEvent->buttons == aEvent.buttons); mCoalescedInputEvent->mTimeStamp = aEvent.mTimeStamp; mCoalescedInputEvent->mRefPoint = aEvent.mRefPoint; mCoalescedInputEvent->pressure = aEvent.pressure; mCoalescedInputEvent->AssignPointerHelperData(aEvent); } + + if (aEvent.mMessage == eMouseMove && + PointerEventHandler::IsPointerEventEnabled()) { + // PointerEvent::getCoalescedEvents is only applied to pointermove events. + if (!mCoalescedInputEvent->mCoalescedWidgetEvents) { + mCoalescedInputEvent->mCoalescedWidgetEvents = + new WidgetPointerEventHolder(); + } + // Append current event in mCoalescedWidgetEvents. We use them to generate + // DOM events when content calls PointerEvent::getCoalescedEvents. + WidgetPointerEvent* event = mCoalescedInputEvent->mCoalescedWidgetEvents + ->mEvents.AppendElement(aEvent); + + event->mFlags.mBubbles = false; + event->mFlags.mCancelable = false; + } } bool CoalescedMouseData::CanCoalesce(const WidgetMouseEvent& aEvent, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId) { + MOZ_ASSERT(aEvent.mMessage == eMouseMove); return !mCoalescedInputEvent || (mCoalescedInputEvent->mModifiers == aEvent.mModifiers && mCoalescedInputEvent->inputSource == aEvent.inputSource && mCoalescedInputEvent->pointerId == aEvent.pointerId && mCoalescedInputEvent->button == aEvent.button && mCoalescedInputEvent->buttons == aEvent.buttons && mGuid == aGuid && mInputBlockId == aInputBlockId);
--- a/dom/webidl/PointerEvent.webidl +++ b/dom/webidl/PointerEvent.webidl @@ -18,24 +18,25 @@ interface PointerEvent : MouseEvent readonly attribute long height; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; + sequence<PointerEvent> getCoalescedEvents(); }; dictionary PointerEventInit : MouseEventInit { long pointerId = 0; long width = 1; long height = 1; float pressure = 0; float tangentialPressure = 0; long tiltX = 0; long tiltY = 0; long twist = 0; DOMString pointerType = ""; boolean isPrimary = false; + sequence<PointerEvent> coalescedEvents = []; }; -
--- a/testing/web-platform/meta/pointerevents/extension/idlharness.html.ini +++ b/testing/web-platform/meta/pointerevents/extension/idlharness.html.ini @@ -1,6 +1,3 @@ [idlharness.html] type: testharness prefs: [dom.w3c_pointer_events.enabled:true] - [PointerEvent interface: operation getCoalescedEvents()] - expected: FAIL -
--- a/testing/web-platform/meta/pointerevents/extension/pointerevent_constructor.html.ini +++ b/testing/web-platform/meta/pointerevents/extension/pointerevent_constructor.html.ini @@ -1,5 +1,4 @@ [pointerevent_constructor.html] type: testharness - [PointerEvent: Constructor test] - expected: FAIL + prefs: [dom.w3c_pointer_events.enabled:true]
--- a/widget/MouseEvents.h +++ b/widget/MouseEvents.h @@ -31,29 +31,41 @@ enum nsDragDropEventStatus namespace mozilla { namespace dom { class PBrowserParent; class PBrowserChild; } // namespace dom +class WidgetPointerEvent; +class WidgetPointerEventHolder final +{ +public: + nsTArray<WidgetPointerEvent> mEvents; + NS_INLINE_DECL_REFCOUNTING(WidgetPointerEventHolder) + +private: + virtual ~WidgetPointerEventHolder() {} +}; + /****************************************************************************** * mozilla::WidgetPointerHelper ******************************************************************************/ class WidgetPointerHelper { public: uint32_t pointerId; uint32_t tiltX; uint32_t tiltY; uint32_t twist; float tangentialPressure; bool convertToPointer; + RefPtr<WidgetPointerEventHolder> mCoalescedWidgetEvents; WidgetPointerHelper() : pointerId(0) , tiltX(0) , tiltY(0) , twist(0) , tangentialPressure(0) , convertToPointer(true) @@ -66,24 +78,39 @@ public: , tiltX(aTiltX) , tiltY(aTiltY) , twist(aTwist) , tangentialPressure(aTangentialPressure) , convertToPointer(true) { } - void AssignPointerHelperData(const WidgetPointerHelper& aEvent) + explicit WidgetPointerHelper(const WidgetPointerHelper& aHelper) + : pointerId(aHelper.pointerId) + , tiltX(aHelper.tiltX) + , tiltY(aHelper.tiltY) + , twist(aHelper.twist) + , tangentialPressure(aHelper.tangentialPressure) + , convertToPointer(aHelper.convertToPointer) + , mCoalescedWidgetEvents(aHelper.mCoalescedWidgetEvents) + { + } + + void AssignPointerHelperData(const WidgetPointerHelper& aEvent, + bool aCopyCoalescedEvents = false) { pointerId = aEvent.pointerId; tiltX = aEvent.tiltX; tiltY = aEvent.tiltY; twist = aEvent.twist; tangentialPressure = aEvent.tangentialPressure; convertToPointer = aEvent.convertToPointer; + if (aCopyCoalescedEvents) { + mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents; + } } }; /****************************************************************************** * mozilla::WidgetMouseEventBase ******************************************************************************/ class WidgetMouseEventBase : public WidgetInputEvent @@ -313,17 +340,17 @@ public: // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp, // eMouseClick or eMouseDoubleClick. The number is count of mouse clicks. // Otherwise, this must be 0. uint32_t mClickCount; void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets) { AssignMouseEventBaseData(aEvent, aCopyTargets); - AssignPointerHelperData(aEvent); + AssignPointerHelperData(aEvent, /* aCopyCoalescedEvents */ true); mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame; mClickCount = aEvent.mClickCount; } /** * Returns true if the event is a context menu event caused by key. */