1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "mozilla/dom/MouseEventBinding.h"
9 #include "mozilla/dom/Touch.h"
10 #include "mozilla/dom/WheelEventBinding.h"
11 #include "mozilla/MouseEvents.h"
12 #include "mozilla/StaticPrefs_dom.h"
13 #include "mozilla/SwipeTracker.h"
14 #include "mozilla/TextEvents.h"
15 #include "mozilla/TouchEvents.h"
16 #include "nsContentUtils.h"
18 #include "nsThreadUtils.h"
19 #include "UnitTransforms.h"
20 #include <type_traits>
26 template WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const;
27 template WidgetPointerEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const;
28 template WidgetDragEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const;
30 InputData::~InputData() = default;
32 InputData::InputData(InputType aInputType
)
33 : mInputType(aInputType
),
34 mFocusSequenceNumber(0),
38 InputData::InputData(InputType aInputType
, TimeStamp aTimeStamp
,
40 : mInputType(aInputType
),
41 mTimeStamp(aTimeStamp
),
42 mFocusSequenceNumber(0),
44 modifiers(aModifiers
) {}
46 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
47 ScreenIntPoint aScreenPoint
,
48 ScreenSize aRadius
, float aRotationAngle
,
50 : mIdentifier(aIdentifier
),
51 mScreenPoint(aScreenPoint
),
53 mRotationAngle(aRotationAngle
),
56 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
57 ParentLayerPoint aLocalScreenPoint
,
58 ScreenSize aRadius
, float aRotationAngle
,
60 : mIdentifier(aIdentifier
),
61 mLocalScreenPoint(aLocalScreenPoint
),
63 mRotationAngle(aRotationAngle
),
66 SingleTouchData::SingleTouchData()
67 : mIdentifier(0), mRotationAngle(0.0), mForce(0.0) {}
69 already_AddRefed
<Touch
> SingleTouchData::ToNewDOMTouch() const {
70 MOZ_ASSERT(NS_IsMainThread(),
71 "Can only create dom::Touch instances on main thread");
73 new Touch(mIdentifier
,
74 LayoutDeviceIntPoint::Truncate(mScreenPoint
.x
, mScreenPoint
.y
),
75 LayoutDeviceIntPoint::Truncate(mRadius
.width
, mRadius
.height
),
76 mRotationAngle
, mForce
);
77 touch
->tiltX
= mTiltX
;
78 touch
->tiltY
= mTiltY
;
79 touch
->twist
= mTwist
;
80 return touch
.forget();
83 MultiTouchInput::MultiTouchInput(MultiTouchType aType
, uint32_t aTime
,
84 TimeStamp aTimeStamp
, Modifiers aModifiers
)
85 : InputData(MULTITOUCH_INPUT
, aTimeStamp
, aModifiers
),
87 mHandledByAPZ(false) {}
89 MultiTouchInput::MultiTouchInput()
90 : InputData(MULTITOUCH_INPUT
),
91 mType(MULTITOUCH_START
),
92 mHandledByAPZ(false) {}
94 MultiTouchInput::MultiTouchInput(const WidgetTouchEvent
& aTouchEvent
)
95 : InputData(MULTITOUCH_INPUT
, aTouchEvent
.mTimeStamp
,
96 aTouchEvent
.mModifiers
),
97 mHandledByAPZ(aTouchEvent
.mFlags
.mHandledByAPZ
),
98 mButton(aTouchEvent
.mButton
),
99 mButtons(aTouchEvent
.mButtons
) {
100 MOZ_ASSERT(NS_IsMainThread(),
101 "Can only copy from WidgetTouchEvent on main thread");
103 switch (aTouchEvent
.mMessage
) {
105 mType
= MULTITOUCH_START
;
108 mType
= MULTITOUCH_MOVE
;
111 mType
= MULTITOUCH_END
;
114 mType
= MULTITOUCH_CANCEL
;
117 MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
121 mScreenOffset
= ViewAs
<ExternalPixel
>(
122 aTouchEvent
.mWidget
->WidgetToScreenOffset(),
123 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
125 for (size_t i
= 0; i
< aTouchEvent
.mTouches
.Length(); i
++) {
126 const Touch
* domTouch
= aTouchEvent
.mTouches
[i
];
128 // Extract data from weird interfaces.
129 int32_t identifier
= domTouch
->Identifier();
130 int32_t radiusX
= domTouch
->RadiusX(CallerType::System
);
131 int32_t radiusY
= domTouch
->RadiusY(CallerType::System
);
132 float rotationAngle
= domTouch
->RotationAngle(CallerType::System
);
133 float force
= domTouch
->Force(CallerType::System
);
135 SingleTouchData
data(
139 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
),
140 ScreenSize((float)radiusX
, (float)radiusY
), rotationAngle
, force
);
142 mTouches
.AppendElement(data
);
146 void MultiTouchInput::Translate(const ScreenPoint
& aTranslation
) {
147 ScreenIntPoint translation
= RoundedToInt(aTranslation
);
149 for (auto& touchData
: mTouches
) {
150 for (auto& historicalData
: touchData
.mHistoricalData
) {
151 historicalData
.mScreenPoint
.MoveBy(translation
.x
, translation
.y
);
153 touchData
.mScreenPoint
.MoveBy(translation
.x
, translation
.y
);
157 WidgetTouchEvent
MultiTouchInput::ToWidgetEvent(nsIWidget
* aWidget
,
158 uint16_t aInputSource
) const {
159 MOZ_ASSERT(NS_IsMainThread(),
160 "Can only convert To WidgetTouchEvent on main thread");
161 MOZ_ASSERT(aInputSource
==
162 mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
||
163 aInputSource
== mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_PEN
);
165 EventMessage touchEventMessage
= eVoidEvent
;
167 case MULTITOUCH_START
:
168 touchEventMessage
= eTouchStart
;
170 case MULTITOUCH_MOVE
:
171 touchEventMessage
= eTouchMove
;
174 touchEventMessage
= eTouchEnd
;
176 case MULTITOUCH_CANCEL
:
177 touchEventMessage
= eTouchCancel
;
180 MOZ_ASSERT_UNREACHABLE(
181 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
185 WidgetTouchEvent
event(true, touchEventMessage
, aWidget
);
186 if (touchEventMessage
== eVoidEvent
) {
190 event
.mModifiers
= this->modifiers
;
191 event
.mTimeStamp
= this->mTimeStamp
;
192 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
193 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
194 event
.mLayersId
= mLayersId
;
195 event
.mInputSource
= aInputSource
;
196 event
.mButton
= mButton
;
197 event
.mButtons
= mButtons
;
199 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
200 *event
.mTouches
.AppendElement() = mTouches
[i
].ToNewDOMTouch();
206 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier
) {
207 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
208 if (mTouches
[i
].mIdentifier
== aTouchIdentifier
) {
215 bool MultiTouchInput::TransformToLocal(
216 const ScreenToParentLayerMatrix4x4
& aTransform
) {
217 for (auto& touchData
: mTouches
) {
218 for (auto& historicalData
: touchData
.mHistoricalData
) {
219 Maybe
<ParentLayerIntPoint
> historicalPoint
=
220 UntransformBy(aTransform
, historicalData
.mScreenPoint
);
221 if (!historicalPoint
) {
224 historicalData
.mLocalScreenPoint
= *historicalPoint
;
226 Maybe
<ParentLayerIntPoint
> point
=
227 UntransformBy(aTransform
, touchData
.mScreenPoint
);
231 touchData
.mLocalScreenPoint
= *point
;
236 MouseInput::MouseInput()
237 : InputData(MOUSE_INPUT
),
242 mHandledByAPZ(false),
243 mPreventClickEvent(false),
244 mIgnoreCapturingContent(false),
245 mSynthesizeMoveAfterDispatch(false) {}
247 MouseInput::MouseInput(MouseType aType
, ButtonType aButtonType
,
248 uint16_t aInputSource
, int16_t aButtons
,
249 const ScreenPoint
& aPoint
, TimeStamp aTimeStamp
,
250 Modifiers aModifiers
)
251 : InputData(MOUSE_INPUT
, aTimeStamp
, aModifiers
),
253 mButtonType(aButtonType
),
254 mInputSource(aInputSource
),
257 mHandledByAPZ(false),
258 mPreventClickEvent(false),
259 mIgnoreCapturingContent(false),
260 mSynthesizeMoveAfterDispatch(false) {}
262 MouseInput::MouseInput(const WidgetMouseEventBase
& aMouseEvent
)
263 : InputData(MOUSE_INPUT
, aMouseEvent
.mTimeStamp
, aMouseEvent
.mModifiers
),
266 mInputSource(aMouseEvent
.mInputSource
),
267 mButtons(aMouseEvent
.mButtons
),
268 mHandledByAPZ(aMouseEvent
.mFlags
.mHandledByAPZ
),
269 mPreventClickEvent(aMouseEvent
.mClass
== eMouseEventClass
&&
270 static_cast<const WidgetMouseEvent
&>(aMouseEvent
)
271 .mClickEventPrevented
),
272 mIgnoreCapturingContent((aMouseEvent
.mClass
== eMouseEventClass
||
273 aMouseEvent
.mClass
== ePointerEventClass
) &&
274 static_cast<const WidgetMouseEvent
&>(aMouseEvent
)
275 .mIgnoreCapturingContent
),
276 mSynthesizeMoveAfterDispatch(
277 (aMouseEvent
.mClass
== eMouseEventClass
||
278 aMouseEvent
.mClass
== ePointerEventClass
) &&
279 static_cast<const WidgetMouseEvent
&>(aMouseEvent
)
280 .mSynthesizeMoveAfterDispatch
) {
281 MOZ_ASSERT(NS_IsMainThread(),
282 "Can only copy from WidgetTouchEvent on main thread");
286 switch (aMouseEvent
.mButton
) {
287 case MouseButton::ePrimary
:
288 mButtonType
= MouseInput::PRIMARY_BUTTON
;
290 case MouseButton::eMiddle
:
291 mButtonType
= MouseInput::MIDDLE_BUTTON
;
293 case MouseButton::eSecondary
:
294 mButtonType
= MouseInput::SECONDARY_BUTTON
;
298 switch (aMouseEvent
.mMessage
) {
309 mType
= MOUSE_DRAG_START
;
312 mType
= MOUSE_DRAG_END
;
315 mType
= MOUSE_DRAG_ENTER
;
318 mType
= MOUSE_DRAG_OVER
;
321 mType
= MOUSE_DRAG_EXIT
;
326 case eMouseEnterIntoWidget
:
327 mType
= MOUSE_WIDGET_ENTER
;
329 case eMouseExitFromWidget
:
330 mType
= MOUSE_WIDGET_EXIT
;
332 case eMouseExploreByTouch
:
333 mType
= MOUSE_EXPLORE_BY_TOUCH
;
336 mType
= MOUSE_HITTEST
;
339 mType
= MOUSE_CONTEXTMENU
;
342 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
346 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
347 aMouseEvent
.mRefPoint
,
348 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
351 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
353 bool MouseInput::TransformToLocal(
354 const ScreenToParentLayerMatrix4x4
& aTransform
) {
355 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
359 mLocalOrigin
= *point
;
364 bool MouseInput::IsPointerEventType() const {
365 return mType
== MOUSE_CONTEXTMENU
;
368 template <class WidgetMouseOrPointerEvent
>
369 WidgetMouseOrPointerEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
370 MOZ_ASSERT(NS_IsMainThread(),
371 "Can only convert To WidgetTouchEvent on main thread");
373 const DebugOnly
<bool> isPointerEvent
=
374 std::is_same
<WidgetMouseOrPointerEvent
, WidgetPointerEvent
>::value
;
375 const DebugOnly
<bool> isMouseEvent
=
376 std::is_same
<WidgetMouseOrPointerEvent
, WidgetMouseEvent
>::value
;
377 const DebugOnly
<bool> isDragEvent
=
378 std::is_same
<WidgetMouseOrPointerEvent
, WidgetDragEvent
>::value
;
379 MOZ_ASSERT(!IsPointerEventType() || isPointerEvent
,
380 "Please use ToWidgetEvent<WidgetPointerEvent>() for the instance");
381 MOZ_ASSERT(IsPointerEventType() || isMouseEvent
|| isDragEvent
,
382 "Please use ToWidgetEvent<WidgetMouseEvent>() or "
383 "ToWidgetEvent<WidgetDragEvent>() for the instance");
385 EventMessage msg
= eVoidEvent
;
386 uint32_t clickCount
= 0;
387 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
400 case MOUSE_DRAG_START
:
406 case MOUSE_DRAG_ENTER
:
409 case MOUSE_DRAG_OVER
:
412 case MOUSE_DRAG_EXIT
:
418 case MOUSE_WIDGET_ENTER
:
419 msg
= eMouseEnterIntoWidget
;
421 case MOUSE_WIDGET_EXIT
:
422 msg
= eMouseExitFromWidget
;
423 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
425 case MOUSE_EXPLORE_BY_TOUCH
:
426 msg
= eMouseExploreByTouch
;
431 case MOUSE_CONTEXTMENU
:
433 MOZ_ASSERT(mButtonType
== MouseInput::SECONDARY_BUTTON
);
436 MOZ_ASSERT_UNREACHABLE(
437 "Did not assign a type to WidgetMouseEvent in MouseInput");
441 WidgetMouseOrPointerEvent
event(true, msg
, aWidget
);
443 if (msg
== eVoidEvent
) {
447 switch (mButtonType
) {
448 case MouseInput::PRIMARY_BUTTON
:
449 event
.mButton
= MouseButton::ePrimary
;
451 case MouseInput::MIDDLE_BUTTON
:
452 event
.mButton
= MouseButton::eMiddle
;
454 case MouseInput::SECONDARY_BUTTON
:
455 event
.mButton
= MouseButton::eSecondary
;
457 case MouseInput::NONE
:
462 event
.mButtons
= mButtons
;
463 event
.mModifiers
= modifiers
;
464 event
.mTimeStamp
= mTimeStamp
;
465 event
.mLayersId
= mLayersId
;
466 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
467 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
469 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
470 event
.mClickCount
= clickCount
;
471 event
.mInputSource
= mInputSource
;
472 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
473 event
.mExitFrom
= exitFrom
;
474 event
.mClickEventPrevented
= mPreventClickEvent
;
475 event
.mIgnoreCapturingContent
= mIgnoreCapturingContent
;
476 event
.mSynthesizeMoveAfterDispatch
= mSynthesizeMoveAfterDispatch
;
481 PanGestureInput::PanGestureInput()
482 : InputData(PANGESTURE_INPUT
),
483 mType(PANGESTURE_MAYSTART
),
484 mLineOrPageDeltaX(0),
485 mLineOrPageDeltaY(0),
486 mUserDeltaMultiplierX(1.0),
487 mUserDeltaMultiplierY(1.0),
488 mHandledByAPZ(false),
489 mOverscrollBehaviorAllowsSwipe(false),
490 mSimulateMomentum(false),
491 mIsNoLineOrPageDelta(true),
492 mMayTriggerSwipe(false) {}
494 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
495 const ScreenPoint
& aPanStartPoint
,
496 const ScreenPoint
& aPanDisplacement
,
497 Modifiers aModifiers
)
498 : InputData(PANGESTURE_INPUT
, aTimeStamp
, aModifiers
),
500 mPanStartPoint(aPanStartPoint
),
501 mPanDisplacement(aPanDisplacement
),
502 mLineOrPageDeltaX(0),
503 mLineOrPageDeltaY(0),
504 mUserDeltaMultiplierX(1.0),
505 mUserDeltaMultiplierY(1.0),
506 mHandledByAPZ(false),
507 mOverscrollBehaviorAllowsSwipe(false),
508 mSimulateMomentum(false),
509 mIsNoLineOrPageDelta(true) {
510 mMayTriggerSwipe
= SwipeTracker::CanTriggerSwipe(*this);
513 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
514 const ScreenPoint
& aPanStartPoint
,
515 const ScreenPoint
& aPanDisplacement
,
516 Modifiers aModifiers
,
517 IsEligibleForSwipe aIsEligibleForSwipe
)
518 : PanGestureInput(aType
, aTimeStamp
, aPanStartPoint
, aPanDisplacement
,
520 mMayTriggerSwipe
&= bool(aIsEligibleForSwipe
);
523 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
524 int32_t aLineOrPageDeltaY
) {
525 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
526 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
527 mIsNoLineOrPageDelta
= false;
530 bool PanGestureInput::IsMomentum() const {
532 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
533 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
534 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
541 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
542 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
543 wheelEvent
.mModifiers
= this->modifiers
;
544 wheelEvent
.mTimeStamp
= mTimeStamp
;
545 wheelEvent
.mLayersId
= mLayersId
;
546 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
548 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
549 wheelEvent
.mButtons
= 0;
550 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
551 wheelEvent
.mIsMomentum
= IsMomentum();
552 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
553 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
554 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
555 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
556 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
557 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
558 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
559 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
560 // widget/gtk is currently the only consumer that uses delta type
562 // Emulate legacy widget/gtk behavior
563 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
564 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
565 wheelEvent
.mDeltaX
*= 3;
566 wheelEvent
.mDeltaY
*= 3;
568 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
573 bool PanGestureInput::TransformToLocal(
574 const ScreenToParentLayerMatrix4x4
& aTransform
) {
575 Maybe
<ParentLayerPoint
> panStartPoint
=
576 UntransformBy(aTransform
, mPanStartPoint
);
577 if (!panStartPoint
) {
580 mLocalPanStartPoint
= *panStartPoint
;
582 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
583 // Skip transforming the pan displacement because we want
584 // raw page proportion counts.
585 mLocalPanDisplacement
= ViewAs
<ParentLayerPixel
>(
586 mPanDisplacement
, PixelCastJustification::DeltaIsPageProportion
);
590 Maybe
<ParentLayerPoint
> panDisplacement
=
591 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
592 if (!panDisplacement
) {
595 mLocalPanDisplacement
= *panDisplacement
;
599 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
600 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
601 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
604 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
605 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
606 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
609 static int32_t TakeLargestInt(gfx::Coord
* aCoord
) {
610 int32_t result(aCoord
->value
); // truncate towards zero
611 aCoord
->value
-= result
;
615 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
616 bool aIsStart
, float x
, float y
) {
617 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
619 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
623 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
624 TakeLargestInt(&sAccumulator
.y
));
627 PinchGestureInput::PinchGestureInput()
628 : InputData(PINCHGESTURE_INPUT
),
629 mType(PINCHGESTURE_START
),
631 mHandledByAPZ(false) {}
633 PinchGestureInput::PinchGestureInput(
634 PinchGestureType aType
, PinchGestureSource aSource
, TimeStamp aTimeStamp
,
635 const ExternalPoint
& aScreenOffset
, const ScreenPoint
& aFocusPoint
,
636 ScreenCoord aCurrentSpan
, ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
637 : InputData(PINCHGESTURE_INPUT
, aTimeStamp
, aModifiers
),
640 mFocusPoint(aFocusPoint
),
641 mScreenOffset(aScreenOffset
),
642 mCurrentSpan(aCurrentSpan
),
643 mPreviousSpan(aPreviousSpan
),
644 mLineOrPageDeltaY(0),
645 mHandledByAPZ(false) {}
647 bool PinchGestureInput::TransformToLocal(
648 const ScreenToParentLayerMatrix4x4
& aTransform
) {
649 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
653 mLocalFocusPoint
= *point
;
657 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
658 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
659 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
660 wheelEvent
.mTimeStamp
= mTimeStamp
;
661 wheelEvent
.mLayersId
= mLayersId
;
662 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
664 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
665 wheelEvent
.mButtons
= 0;
666 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
667 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
669 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
671 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
673 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
678 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
679 #if defined(XP_DARWIN)
680 // This converts the pinch gesture value to a fake wheel event that has the
681 // control key pressed so that pages can implement custom pinch gesture
682 // handling. It may seem strange that this doesn't use a wheel event with
683 // the deltaZ property set, but this matches Chrome's behavior as described
684 // at https://code.google.com/p/chromium/issues/detail?id=289887
686 // The intent of the formula below is to produce numbers similar to Chrome's
687 // implementation of this feature. Chrome implements deltaY using the formula
688 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
689 // All deltas for a single pinch gesture should sum to 0 if the start and end
690 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
691 // because they followed Apple's misleading documentation, which implies that
692 // "1 + [event magnification]" is the scale factor. The scale factor is
693 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
694 // already in log space.
696 // The multiplication by the backing scale factor below counteracts the
697 // division by the backing scale factor in WheelEvent.
699 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
700 // is [event magnification] but [event magnification] is only available in the
701 // macOS widget code so we have to reverse engineer from mCurrentSpan and
702 // mPreviousSpan (which are derived from [event magnification]) to get it.
703 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
704 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
705 // for M in terms of mPreviousSpan and plugging that into to the formula for
707 return (mPreviousSpan
- 100.0) *
708 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
710 // This calculation is based on what the Windows and Linux widget code does.
711 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
712 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
713 // is the scale from the current OS event and lastScale is the scale when the
714 // previous OS event happened. On macOS [event magnification] is a relative
715 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
716 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
717 // calculate the relative scale change on Windows we would calculate |M =
718 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
719 // same formula as the macOS code
720 // (|-100.0 * M * GetDefaultScaleInternal()|).
722 return (mPreviousSpan
- mCurrentSpan
) *
723 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
727 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
728 double deltaY
= ComputeDeltaY(aWidget
);
729 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
732 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
733 (mType
== PINCHGESTURE_START
), 0, deltaY
);
734 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
735 if (mLineOrPageDeltaY
== 0) {
736 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
737 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
738 if (mType
== PINCHGESTURE_SCALE
) {
741 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
742 // defer the START event until we accumulate enough delta).
743 // The Linux widget code doesn't support this, so instead set the event's
744 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
746 if (mType
== PINCHGESTURE_START
) {
750 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
753 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
759 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
760 bool aIsStart
, float x
, float y
) {
761 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
763 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
767 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
768 TakeLargestInt(&sAccumulator
.y
));
771 TapGestureInput::TapGestureInput()
772 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
774 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
775 const ScreenIntPoint
& aPoint
,
776 Modifiers aModifiers
)
777 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
781 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
782 const ParentLayerPoint
& aLocalPoint
,
783 Modifiers aModifiers
)
784 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
786 mLocalPoint(aLocalPoint
) {}
788 bool TapGestureInput::TransformToLocal(
789 const ScreenToParentLayerMatrix4x4
& aTransform
) {
790 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
794 mLocalPoint
= *point
;
798 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
799 nsIWidget
* aWidget
) const {
800 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
802 event
.mTimeStamp
= mTimeStamp
;
803 event
.mLayersId
= mLayersId
;
804 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
806 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
808 event
.mClickCount
= 1;
809 event
.mModifiers
= modifiers
;
814 ScrollWheelInput::ScrollWheelInput()
815 : InputData(SCROLLWHEEL_INPUT
),
816 mDeltaType(SCROLLDELTA_LINE
),
817 mScrollMode(SCROLLMODE_INSTANT
),
818 mHandledByAPZ(false),
821 mLineOrPageDeltaX(0),
822 mLineOrPageDeltaY(0),
823 mScrollSeriesNumber(0),
824 mUserDeltaMultiplierX(1.0),
825 mUserDeltaMultiplierY(1.0),
826 mMayHaveMomentum(false),
828 mAPZAction(APZWheelAction::Scroll
) {}
830 ScrollWheelInput::ScrollWheelInput(
831 TimeStamp aTimeStamp
, Modifiers aModifiers
, ScrollMode aScrollMode
,
832 ScrollDeltaType aDeltaType
, const ScreenPoint
& aOrigin
, double aDeltaX
,
833 double aDeltaY
, bool aAllowToOverrideSystemScrollSpeed
,
834 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
835 : InputData(SCROLLWHEEL_INPUT
, aTimeStamp
, aModifiers
),
836 mDeltaType(aDeltaType
),
837 mScrollMode(aScrollMode
),
839 mHandledByAPZ(false),
842 mLineOrPageDeltaX(0),
843 mLineOrPageDeltaY(0),
844 mScrollSeriesNumber(0),
845 mUserDeltaMultiplierX(1.0),
846 mUserDeltaMultiplierY(1.0),
847 mMayHaveMomentum(false),
849 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
850 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
851 mAPZAction(APZWheelAction::Scroll
) {}
853 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
854 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTimeStamp
,
855 aWheelEvent
.mModifiers
),
856 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
857 mScrollMode(SCROLLMODE_INSTANT
),
858 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
859 mDeltaX(aWheelEvent
.mDeltaX
),
860 mDeltaY(aWheelEvent
.mDeltaY
),
861 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
862 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
863 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
864 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
865 mScrollSeriesNumber(0),
866 mUserDeltaMultiplierX(1.0),
867 mUserDeltaMultiplierY(1.0),
868 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
869 mIsMomentum(aWheelEvent
.mIsMomentum
),
870 mAllowToOverrideSystemScrollSpeed(
871 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
872 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
873 mAPZAction(APZWheelAction::Scroll
) {
874 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
875 aWheelEvent
.mRefPoint
,
876 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
879 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
880 uint32_t aDeltaMode
) {
881 switch (aDeltaMode
) {
882 case WheelEvent_Binding::DOM_DELTA_LINE
:
883 return SCROLLDELTA_LINE
;
884 case WheelEvent_Binding::DOM_DELTA_PAGE
:
885 return SCROLLDELTA_PAGE
;
886 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
887 return SCROLLDELTA_PIXEL
;
891 return SCROLLDELTA_LINE
;
894 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
895 switch (aDeltaType
) {
896 case ScrollWheelInput::SCROLLDELTA_LINE
:
897 return WheelEvent_Binding::DOM_DELTA_LINE
;
898 case ScrollWheelInput::SCROLLDELTA_PAGE
:
899 return WheelEvent_Binding::DOM_DELTA_PAGE
;
900 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
902 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
906 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
907 ScrollDeltaType aDeltaType
) {
908 switch (aDeltaType
) {
909 case SCROLLDELTA_LINE
:
910 return ScrollUnit::LINES
;
911 case SCROLLDELTA_PAGE
:
912 return ScrollUnit::PAGES
;
913 case SCROLLDELTA_PIXEL
:
914 return ScrollUnit::DEVICE_PIXELS
;
918 return ScrollUnit::LINES
;
921 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
922 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
923 wheelEvent
.mModifiers
= this->modifiers
;
924 wheelEvent
.mTimeStamp
= mTimeStamp
;
925 wheelEvent
.mLayersId
= mLayersId
;
926 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
928 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
929 wheelEvent
.mButtons
= 0;
930 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
931 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
932 wheelEvent
.mIsMomentum
= mIsMomentum
;
933 wheelEvent
.mDeltaX
= mDeltaX
;
934 wheelEvent
.mDeltaY
= mDeltaY
;
935 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
936 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
937 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
938 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
939 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
940 mAllowToOverrideSystemScrollSpeed
;
941 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
942 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
946 bool ScrollWheelInput::TransformToLocal(
947 const ScreenToParentLayerMatrix4x4
& aTransform
) {
948 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
952 mLocalOrigin
= *point
;
956 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
957 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
960 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
961 : InputData(KEYBOARD_INPUT
, aEvent
.mTimeStamp
, aEvent
.mModifiers
),
962 mKeyCode(aEvent
.mKeyCode
),
963 mCharCode(aEvent
.mCharCode
),
964 mHandledByAPZ(false) {
965 switch (aEvent
.mMessage
) {
967 mType
= KeyboardInput::KEY_PRESS
;
971 mType
= KeyboardInput::KEY_UP
;
975 mType
= KeyboardInput::KEY_DOWN
;
979 mType
= KeyboardInput::KEY_OTHER
;
983 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
986 KeyboardInput::KeyboardInput()
987 : InputData(KEYBOARD_INPUT
),
991 mHandledByAPZ(false) {}
993 } // namespace mozilla