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/TextEvents.h"
12 #include "nsContentUtils.h"
14 #include "nsThreadUtils.h"
15 #include "mozilla/MouseEvents.h"
16 #include "mozilla/TouchEvents.h"
17 #include "UnitTransforms.h"
23 InputData::~InputData() = default;
25 InputData::InputData(InputType aInputType
)
26 : mInputType(aInputType
),
28 mFocusSequenceNumber(0),
32 InputData::InputData(InputType aInputType
, uint32_t aTime
, TimeStamp aTimeStamp
,
34 : mInputType(aInputType
),
36 mTimeStamp(aTimeStamp
),
37 mFocusSequenceNumber(0),
39 modifiers(aModifiers
) {}
41 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
42 ScreenIntPoint aScreenPoint
,
43 ScreenSize aRadius
, float aRotationAngle
,
45 : mIdentifier(aIdentifier
),
46 mScreenPoint(aScreenPoint
),
48 mRotationAngle(aRotationAngle
),
51 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
52 ParentLayerPoint aLocalScreenPoint
,
53 ScreenSize aRadius
, float aRotationAngle
,
55 : mIdentifier(aIdentifier
),
56 mLocalScreenPoint(aLocalScreenPoint
),
58 mRotationAngle(aRotationAngle
),
61 SingleTouchData::SingleTouchData()
62 : mIdentifier(0), mRotationAngle(0.0), mForce(0.0) {}
64 already_AddRefed
<Touch
> SingleTouchData::ToNewDOMTouch() const {
65 MOZ_ASSERT(NS_IsMainThread(),
66 "Can only create dom::Touch instances on main thread");
68 new Touch(mIdentifier
,
69 LayoutDeviceIntPoint::Truncate(mScreenPoint
.x
, mScreenPoint
.y
),
70 LayoutDeviceIntPoint::Truncate(mRadius
.width
, mRadius
.height
),
71 mRotationAngle
, mForce
);
72 touch
->tiltX
= mTiltX
;
73 touch
->tiltY
= mTiltY
;
74 touch
->twist
= mTwist
;
75 return touch
.forget();
78 MultiTouchInput::MultiTouchInput(MultiTouchType aType
, uint32_t aTime
,
79 TimeStamp aTimeStamp
, Modifiers aModifiers
)
80 : InputData(MULTITOUCH_INPUT
, aTime
, aTimeStamp
, aModifiers
),
82 mHandledByAPZ(false) {}
84 MultiTouchInput::MultiTouchInput()
85 : InputData(MULTITOUCH_INPUT
),
86 mType(MULTITOUCH_START
),
87 mHandledByAPZ(false) {}
89 MultiTouchInput::MultiTouchInput(const MultiTouchInput
& aOther
)
90 : InputData(MULTITOUCH_INPUT
, aOther
.mTime
, aOther
.mTimeStamp
,
93 mScreenOffset(aOther
.mScreenOffset
),
94 mHandledByAPZ(aOther
.mHandledByAPZ
),
95 mButton(aOther
.mButton
),
96 mButtons(aOther
.mButtons
) {
97 mTouches
.AppendElements(aOther
.mTouches
);
100 MultiTouchInput::MultiTouchInput(const WidgetTouchEvent
& aTouchEvent
)
101 : InputData(MULTITOUCH_INPUT
, aTouchEvent
.mTime
, aTouchEvent
.mTimeStamp
,
102 aTouchEvent
.mModifiers
),
103 mHandledByAPZ(aTouchEvent
.mFlags
.mHandledByAPZ
),
104 mButton(aTouchEvent
.mButton
),
105 mButtons(aTouchEvent
.mButtons
) {
106 MOZ_ASSERT(NS_IsMainThread(),
107 "Can only copy from WidgetTouchEvent on main thread");
109 switch (aTouchEvent
.mMessage
) {
111 mType
= MULTITOUCH_START
;
114 mType
= MULTITOUCH_MOVE
;
117 mType
= MULTITOUCH_END
;
120 mType
= MULTITOUCH_CANCEL
;
123 MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
127 mScreenOffset
= ViewAs
<ExternalPixel
>(
128 aTouchEvent
.mWidget
->WidgetToScreenOffset(),
129 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
131 for (size_t i
= 0; i
< aTouchEvent
.mTouches
.Length(); i
++) {
132 const Touch
* domTouch
= aTouchEvent
.mTouches
[i
];
134 // Extract data from weird interfaces.
135 int32_t identifier
= domTouch
->Identifier();
136 int32_t radiusX
= domTouch
->RadiusX(CallerType::System
);
137 int32_t radiusY
= domTouch
->RadiusY(CallerType::System
);
138 float rotationAngle
= domTouch
->RotationAngle(CallerType::System
);
139 float force
= domTouch
->Force(CallerType::System
);
141 SingleTouchData
data(
145 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
),
146 ScreenSize((float)radiusX
, (float)radiusY
), rotationAngle
, force
);
148 mTouches
.AppendElement(data
);
152 void MultiTouchInput::Translate(const ScreenPoint
& aTranslation
) {
153 const int32_t xTranslation
= (int32_t)(aTranslation
.x
+ 0.5f
);
154 const int32_t yTranslation
= (int32_t)(aTranslation
.y
+ 0.5f
);
156 for (auto& touchData
: mTouches
) {
157 for (auto& historicalData
: touchData
.mHistoricalData
) {
158 historicalData
.mScreenPoint
.MoveBy(xTranslation
, yTranslation
);
160 touchData
.mScreenPoint
.MoveBy(xTranslation
, yTranslation
);
164 WidgetTouchEvent
MultiTouchInput::ToWidgetEvent(nsIWidget
* aWidget
,
165 uint16_t aInputSource
) const {
166 MOZ_ASSERT(NS_IsMainThread(),
167 "Can only convert To WidgetTouchEvent on main thread");
168 MOZ_ASSERT(aInputSource
==
169 mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
||
170 aInputSource
== mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_PEN
);
172 EventMessage touchEventMessage
= eVoidEvent
;
174 case MULTITOUCH_START
:
175 touchEventMessage
= eTouchStart
;
177 case MULTITOUCH_MOVE
:
178 touchEventMessage
= eTouchMove
;
181 touchEventMessage
= eTouchEnd
;
183 case MULTITOUCH_CANCEL
:
184 touchEventMessage
= eTouchCancel
;
187 MOZ_ASSERT_UNREACHABLE(
188 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
192 WidgetTouchEvent
event(true, touchEventMessage
, aWidget
);
193 if (touchEventMessage
== eVoidEvent
) {
197 event
.mModifiers
= this->modifiers
;
198 event
.mTime
= this->mTime
;
199 event
.mTimeStamp
= this->mTimeStamp
;
200 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
201 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
202 event
.mLayersId
= mLayersId
;
203 event
.mInputSource
= aInputSource
;
204 event
.mButton
= mButton
;
205 event
.mButtons
= mButtons
;
207 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
208 *event
.mTouches
.AppendElement() = mTouches
[i
].ToNewDOMTouch();
214 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier
) {
215 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
216 if (mTouches
[i
].mIdentifier
== aTouchIdentifier
) {
223 bool MultiTouchInput::TransformToLocal(
224 const ScreenToParentLayerMatrix4x4
& aTransform
) {
225 for (auto& touchData
: mTouches
) {
226 for (auto& historicalData
: touchData
.mHistoricalData
) {
227 Maybe
<ParentLayerIntPoint
> historicalPoint
=
228 UntransformBy(aTransform
, historicalData
.mScreenPoint
);
229 if (!historicalPoint
) {
232 historicalData
.mLocalScreenPoint
= *historicalPoint
;
234 Maybe
<ParentLayerIntPoint
> point
=
235 UntransformBy(aTransform
, touchData
.mScreenPoint
);
239 touchData
.mLocalScreenPoint
= *point
;
244 MouseInput::MouseInput()
245 : InputData(MOUSE_INPUT
),
250 mHandledByAPZ(false),
251 mPreventClickEvent(false) {}
253 MouseInput::MouseInput(MouseType aType
, ButtonType aButtonType
,
254 uint16_t aInputSource
, int16_t aButtons
,
255 const ScreenPoint
& aPoint
, uint32_t aTime
,
256 TimeStamp aTimeStamp
, Modifiers aModifiers
)
257 : InputData(MOUSE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
259 mButtonType(aButtonType
),
260 mInputSource(aInputSource
),
263 mHandledByAPZ(false),
264 mPreventClickEvent(false) {}
266 MouseInput::MouseInput(const WidgetMouseEventBase
& aMouseEvent
)
267 : InputData(MOUSE_INPUT
, aMouseEvent
.mTime
, aMouseEvent
.mTimeStamp
,
268 aMouseEvent
.mModifiers
),
271 mInputSource(aMouseEvent
.mInputSource
),
272 mButtons(aMouseEvent
.mButtons
),
273 mHandledByAPZ(aMouseEvent
.mFlags
.mHandledByAPZ
),
274 mPreventClickEvent(aMouseEvent
.mClass
== eMouseEventClass
&&
275 aMouseEvent
.AsMouseEvent()->mClickEventPrevented
) {
276 MOZ_ASSERT(NS_IsMainThread(),
277 "Can only copy from WidgetTouchEvent on main thread");
281 switch (aMouseEvent
.mButton
) {
282 case MouseButton::ePrimary
:
283 mButtonType
= MouseInput::PRIMARY_BUTTON
;
285 case MouseButton::eMiddle
:
286 mButtonType
= MouseInput::MIDDLE_BUTTON
;
288 case MouseButton::eSecondary
:
289 mButtonType
= MouseInput::SECONDARY_BUTTON
;
293 switch (aMouseEvent
.mMessage
) {
304 mType
= MOUSE_DRAG_START
;
307 mType
= MOUSE_DRAG_END
;
309 case eMouseEnterIntoWidget
:
310 mType
= MOUSE_WIDGET_ENTER
;
312 case eMouseExitFromWidget
:
313 mType
= MOUSE_WIDGET_EXIT
;
316 mType
= MOUSE_HITTEST
;
319 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
323 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
324 aMouseEvent
.mRefPoint
,
325 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
328 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
330 bool MouseInput::TransformToLocal(
331 const ScreenToParentLayerMatrix4x4
& aTransform
) {
332 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
336 mLocalOrigin
= *point
;
341 WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
342 MOZ_ASSERT(NS_IsMainThread(),
343 "Can only convert To WidgetTouchEvent on main thread");
345 EventMessage msg
= eVoidEvent
;
346 uint32_t clickCount
= 0;
347 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
360 case MOUSE_DRAG_START
:
366 case MOUSE_WIDGET_ENTER
:
367 msg
= eMouseEnterIntoWidget
;
369 case MOUSE_WIDGET_EXIT
:
370 msg
= eMouseExitFromWidget
;
371 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
377 MOZ_ASSERT_UNREACHABLE(
378 "Did not assign a type to WidgetMouseEvent in MouseInput");
382 WidgetMouseEvent
event(true, msg
, aWidget
, WidgetMouseEvent::eReal
,
383 WidgetMouseEvent::eNormal
);
385 if (msg
== eVoidEvent
) {
389 switch (mButtonType
) {
390 case MouseInput::PRIMARY_BUTTON
:
391 event
.mButton
= MouseButton::ePrimary
;
393 case MouseInput::MIDDLE_BUTTON
:
394 event
.mButton
= MouseButton::eMiddle
;
396 case MouseInput::SECONDARY_BUTTON
:
397 event
.mButton
= MouseButton::eSecondary
;
399 case MouseInput::NONE
:
404 event
.mButtons
= mButtons
;
405 event
.mModifiers
= modifiers
;
407 event
.mTimeStamp
= mTimeStamp
;
408 event
.mLayersId
= mLayersId
;
409 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
410 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
412 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
413 event
.mClickCount
= clickCount
;
414 event
.mInputSource
= mInputSource
;
415 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
416 event
.mExitFrom
= exitFrom
;
417 event
.mClickEventPrevented
= mPreventClickEvent
;
422 PanGestureInput::PanGestureInput()
423 : InputData(PANGESTURE_INPUT
),
424 mType(PANGESTURE_MAYSTART
),
425 mLineOrPageDeltaX(0),
426 mLineOrPageDeltaY(0),
427 mUserDeltaMultiplierX(1.0),
428 mUserDeltaMultiplierY(1.0),
429 mHandledByAPZ(false),
430 mFollowedByMomentum(false),
431 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
432 mOverscrollBehaviorAllowsSwipe(false),
433 mSimulateMomentum(false),
434 mIsNoLineOrPageDelta(true) {}
436 PanGestureInput::PanGestureInput(PanGestureType aType
, uint32_t aTime
,
437 TimeStamp aTimeStamp
,
438 const ScreenPoint
& aPanStartPoint
,
439 const ScreenPoint
& aPanDisplacement
,
440 Modifiers aModifiers
)
441 : InputData(PANGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
443 mPanStartPoint(aPanStartPoint
),
444 mPanDisplacement(aPanDisplacement
),
445 mLineOrPageDeltaX(0),
446 mLineOrPageDeltaY(0),
447 mUserDeltaMultiplierX(1.0),
448 mUserDeltaMultiplierY(1.0),
449 mHandledByAPZ(false),
450 mFollowedByMomentum(false),
451 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
452 mOverscrollBehaviorAllowsSwipe(false),
453 mSimulateMomentum(false),
454 mIsNoLineOrPageDelta(true) {}
456 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
457 int32_t aLineOrPageDeltaY
) {
458 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
459 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
460 mIsNoLineOrPageDelta
= false;
463 bool PanGestureInput::IsMomentum() const {
465 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
466 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
467 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
474 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
475 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
476 wheelEvent
.mModifiers
= this->modifiers
;
477 wheelEvent
.mTime
= mTime
;
478 wheelEvent
.mTimeStamp
= mTimeStamp
;
479 wheelEvent
.mLayersId
= mLayersId
;
480 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
482 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
483 wheelEvent
.mButtons
= 0;
484 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
485 wheelEvent
.mIsMomentum
= IsMomentum();
486 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
487 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
488 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
489 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
490 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
491 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
492 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
493 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
494 // widget/gtk is currently the only consumer that uses delta type
496 // Emulate legacy widget/gtk behavior
497 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
498 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY
;
499 wheelEvent
.mDeltaX
*= 3;
500 wheelEvent
.mDeltaY
*= 3;
502 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
507 bool PanGestureInput::TransformToLocal(
508 const ScreenToParentLayerMatrix4x4
& aTransform
) {
509 Maybe
<ParentLayerPoint
> panStartPoint
=
510 UntransformBy(aTransform
, mPanStartPoint
);
511 if (!panStartPoint
) {
514 mLocalPanStartPoint
= *panStartPoint
;
516 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
517 // Skip transforming the pan displacement because we want
518 // raw page proportion counts.
519 mLocalPanDisplacement
.x
= mPanDisplacement
.x
;
520 mLocalPanDisplacement
.y
= mPanDisplacement
.y
;
524 Maybe
<ParentLayerPoint
> panDisplacement
=
525 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
526 if (!panDisplacement
) {
529 mLocalPanDisplacement
= *panDisplacement
;
533 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
534 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
535 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
538 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
539 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
540 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
543 static int32_t TakeLargestInt(gfx::Float
* aFloat
) {
544 int32_t result(*aFloat
); // truncate towards zero
549 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
550 bool aIsStart
, float x
, float y
) {
551 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
553 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
557 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
558 TakeLargestInt(&sAccumulator
.y
));
561 PinchGestureInput::PinchGestureInput()
562 : InputData(PINCHGESTURE_INPUT
),
563 mType(PINCHGESTURE_START
),
565 mHandledByAPZ(false) {}
567 PinchGestureInput::PinchGestureInput(
568 PinchGestureType aType
, PinchGestureSource aSource
, uint32_t aTime
,
569 TimeStamp aTimeStamp
, const ExternalPoint
& aScreenOffset
,
570 const ScreenPoint
& aFocusPoint
, ScreenCoord aCurrentSpan
,
571 ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
572 : InputData(PINCHGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
575 mFocusPoint(aFocusPoint
),
576 mScreenOffset(aScreenOffset
),
577 mCurrentSpan(aCurrentSpan
),
578 mPreviousSpan(aPreviousSpan
),
579 mLineOrPageDeltaY(0),
580 mHandledByAPZ(false) {}
582 bool PinchGestureInput::TransformToLocal(
583 const ScreenToParentLayerMatrix4x4
& aTransform
) {
584 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
588 mLocalFocusPoint
= *point
;
592 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
593 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
594 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
595 wheelEvent
.mTime
= mTime
;
596 wheelEvent
.mTimeStamp
= mTimeStamp
;
597 wheelEvent
.mLayersId
= mLayersId
;
598 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
600 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
601 wheelEvent
.mButtons
= 0;
602 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
603 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
605 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
607 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
609 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
614 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
615 #if defined(OS_MACOSX)
616 // This converts the pinch gesture value to a fake wheel event that has the
617 // control key pressed so that pages can implement custom pinch gesture
618 // handling. It may seem strange that this doesn't use a wheel event with
619 // the deltaZ property set, but this matches Chrome's behavior as described
620 // at https://code.google.com/p/chromium/issues/detail?id=289887
622 // The intent of the formula below is to produce numbers similar to Chrome's
623 // implementation of this feature. Chrome implements deltaY using the formula
624 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
625 // All deltas for a single pinch gesture should sum to 0 if the start and end
626 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
627 // because they followed Apple's misleading documentation, which implies that
628 // "1 + [event magnification]" is the scale factor. The scale factor is
629 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
630 // already in log space.
632 // The multiplication by the backing scale factor below counteracts the
633 // division by the backing scale factor in WheelEvent.
635 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
636 // is [event magnification] but [event magnification] is only available in the
637 // macOS widget code so we have to reverse engineer from mCurrentSpan and
638 // mPreviousSpan (which are derived from [event magnification]) to get it.
639 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
640 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
641 // for M in terms of mPreviousSpan and plugging that into to the formula for
643 return (mPreviousSpan
- 100.0) *
644 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
646 // This calculation is based on what the Windows and Linux widget code does.
647 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
648 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
649 // is the scale from the current OS event and lastScale is the scale when the
650 // previous OS event happened. On macOS [event magnification] is a relative
651 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
652 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
653 // calculate the relative scale change on Windows we would calculate |M =
654 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
655 // same formula as the macOS code
656 // (|-100.0 * M * GetDefaultScaleInternal()|).
658 return (mPreviousSpan
- mCurrentSpan
) *
659 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
663 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
664 double deltaY
= ComputeDeltaY(aWidget
);
665 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
668 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
669 (mType
== PINCHGESTURE_START
), 0, deltaY
);
670 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
671 if (mLineOrPageDeltaY
== 0) {
672 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
673 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
674 if (mType
== PINCHGESTURE_SCALE
) {
677 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
678 // defer the START event until we accumulate enough delta).
679 // The Linux widget code doesn't support this, so instead set the event's
680 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
682 if (mType
== PINCHGESTURE_START
) {
686 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
689 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
695 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
696 bool aIsStart
, float x
, float y
) {
697 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
699 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
703 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
704 TakeLargestInt(&sAccumulator
.y
));
707 TapGestureInput::TapGestureInput()
708 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
710 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
711 TimeStamp aTimeStamp
,
712 const ScreenIntPoint
& aPoint
,
713 Modifiers aModifiers
)
714 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
718 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
719 TimeStamp aTimeStamp
,
720 const ParentLayerPoint
& aLocalPoint
,
721 Modifiers aModifiers
)
722 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
724 mLocalPoint(aLocalPoint
) {}
726 bool TapGestureInput::TransformToLocal(
727 const ScreenToParentLayerMatrix4x4
& aTransform
) {
728 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
732 mLocalPoint
= *point
;
736 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
737 nsIWidget
* aWidget
) const {
738 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
741 event
.mTimeStamp
= mTimeStamp
;
742 event
.mLayersId
= mLayersId
;
743 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
745 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
747 event
.mClickCount
= 1;
748 event
.mModifiers
= modifiers
;
753 ScrollWheelInput::ScrollWheelInput()
754 : InputData(SCROLLWHEEL_INPUT
),
755 mDeltaType(SCROLLDELTA_LINE
),
756 mScrollMode(SCROLLMODE_INSTANT
),
757 mHandledByAPZ(false),
760 mLineOrPageDeltaX(0),
761 mLineOrPageDeltaY(0),
762 mScrollSeriesNumber(0),
763 mUserDeltaMultiplierX(1.0),
764 mUserDeltaMultiplierY(1.0),
765 mMayHaveMomentum(false),
767 mAPZAction(APZWheelAction::Scroll
) {}
769 ScrollWheelInput::ScrollWheelInput(
770 uint32_t aTime
, TimeStamp aTimeStamp
, Modifiers aModifiers
,
771 ScrollMode aScrollMode
, ScrollDeltaType aDeltaType
,
772 const ScreenPoint
& aOrigin
, double aDeltaX
, double aDeltaY
,
773 bool aAllowToOverrideSystemScrollSpeed
,
774 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
775 : InputData(SCROLLWHEEL_INPUT
, aTime
, aTimeStamp
, aModifiers
),
776 mDeltaType(aDeltaType
),
777 mScrollMode(aScrollMode
),
779 mHandledByAPZ(false),
782 mLineOrPageDeltaX(0),
783 mLineOrPageDeltaY(0),
784 mScrollSeriesNumber(0),
785 mUserDeltaMultiplierX(1.0),
786 mUserDeltaMultiplierY(1.0),
787 mMayHaveMomentum(false),
789 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
790 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
791 mAPZAction(APZWheelAction::Scroll
) {}
793 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
794 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTime
, aWheelEvent
.mTimeStamp
,
795 aWheelEvent
.mModifiers
),
796 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
797 mScrollMode(SCROLLMODE_INSTANT
),
798 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
799 mDeltaX(aWheelEvent
.mDeltaX
),
800 mDeltaY(aWheelEvent
.mDeltaY
),
801 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
802 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
803 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
804 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
805 mScrollSeriesNumber(0),
806 mUserDeltaMultiplierX(1.0),
807 mUserDeltaMultiplierY(1.0),
808 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
809 mIsMomentum(aWheelEvent
.mIsMomentum
),
810 mAllowToOverrideSystemScrollSpeed(
811 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
812 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
813 mAPZAction(APZWheelAction::Scroll
) {
814 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
815 aWheelEvent
.mRefPoint
,
816 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
819 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
820 uint32_t aDeltaMode
) {
821 switch (aDeltaMode
) {
822 case WheelEvent_Binding::DOM_DELTA_LINE
:
823 return SCROLLDELTA_LINE
;
824 case WheelEvent_Binding::DOM_DELTA_PAGE
:
825 return SCROLLDELTA_PAGE
;
826 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
827 return SCROLLDELTA_PIXEL
;
831 return SCROLLDELTA_LINE
;
834 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
835 switch (aDeltaType
) {
836 case ScrollWheelInput::SCROLLDELTA_LINE
:
837 return WheelEvent_Binding::DOM_DELTA_LINE
;
838 case ScrollWheelInput::SCROLLDELTA_PAGE
:
839 return WheelEvent_Binding::DOM_DELTA_PAGE
;
840 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
842 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
846 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
847 ScrollDeltaType aDeltaType
) {
848 switch (aDeltaType
) {
849 case SCROLLDELTA_LINE
:
850 return ScrollUnit::LINES
;
851 case SCROLLDELTA_PAGE
:
852 return ScrollUnit::PAGES
;
853 case SCROLLDELTA_PIXEL
:
854 return ScrollUnit::DEVICE_PIXELS
;
858 return ScrollUnit::LINES
;
861 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
862 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
863 wheelEvent
.mModifiers
= this->modifiers
;
864 wheelEvent
.mTime
= mTime
;
865 wheelEvent
.mTimeStamp
= mTimeStamp
;
866 wheelEvent
.mLayersId
= mLayersId
;
867 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
869 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
870 wheelEvent
.mButtons
= 0;
871 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
872 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
873 wheelEvent
.mIsMomentum
= mIsMomentum
;
874 wheelEvent
.mDeltaX
= mDeltaX
;
875 wheelEvent
.mDeltaY
= mDeltaY
;
876 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
877 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
878 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
879 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
880 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
881 mAllowToOverrideSystemScrollSpeed
;
882 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
883 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
887 bool ScrollWheelInput::TransformToLocal(
888 const ScreenToParentLayerMatrix4x4
& aTransform
) {
889 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
893 mLocalOrigin
= *point
;
897 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
898 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
901 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
902 : InputData(KEYBOARD_INPUT
, aEvent
.mTime
, aEvent
.mTimeStamp
,
904 mKeyCode(aEvent
.mKeyCode
),
905 mCharCode(aEvent
.mCharCode
),
906 mHandledByAPZ(false) {
907 switch (aEvent
.mMessage
) {
909 mType
= KeyboardInput::KEY_PRESS
;
913 mType
= KeyboardInput::KEY_UP
;
917 mType
= KeyboardInput::KEY_DOWN
;
921 mType
= KeyboardInput::KEY_OTHER
;
925 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
928 KeyboardInput::KeyboardInput()
929 : InputData(KEYBOARD_INPUT
),
933 mHandledByAPZ(false) {}
935 } // namespace mozilla