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
;
315 case eMouseExploreByTouch
:
316 mType
= MOUSE_EXPLORE_BY_TOUCH
;
319 mType
= MOUSE_HITTEST
;
322 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
326 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
327 aMouseEvent
.mRefPoint
,
328 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
331 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
333 bool MouseInput::TransformToLocal(
334 const ScreenToParentLayerMatrix4x4
& aTransform
) {
335 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
339 mLocalOrigin
= *point
;
344 WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
345 MOZ_ASSERT(NS_IsMainThread(),
346 "Can only convert To WidgetTouchEvent on main thread");
348 EventMessage msg
= eVoidEvent
;
349 uint32_t clickCount
= 0;
350 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
363 case MOUSE_DRAG_START
:
369 case MOUSE_WIDGET_ENTER
:
370 msg
= eMouseEnterIntoWidget
;
372 case MOUSE_WIDGET_EXIT
:
373 msg
= eMouseExitFromWidget
;
374 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
376 case MOUSE_EXPLORE_BY_TOUCH
:
377 msg
= eMouseExploreByTouch
;
383 MOZ_ASSERT_UNREACHABLE(
384 "Did not assign a type to WidgetMouseEvent in MouseInput");
388 WidgetMouseEvent
event(true, msg
, aWidget
, WidgetMouseEvent::eReal
,
389 WidgetMouseEvent::eNormal
);
391 if (msg
== eVoidEvent
) {
395 switch (mButtonType
) {
396 case MouseInput::PRIMARY_BUTTON
:
397 event
.mButton
= MouseButton::ePrimary
;
399 case MouseInput::MIDDLE_BUTTON
:
400 event
.mButton
= MouseButton::eMiddle
;
402 case MouseInput::SECONDARY_BUTTON
:
403 event
.mButton
= MouseButton::eSecondary
;
405 case MouseInput::NONE
:
410 event
.mButtons
= mButtons
;
411 event
.mModifiers
= modifiers
;
413 event
.mTimeStamp
= mTimeStamp
;
414 event
.mLayersId
= mLayersId
;
415 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
416 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
418 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
419 event
.mClickCount
= clickCount
;
420 event
.mInputSource
= mInputSource
;
421 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
422 event
.mExitFrom
= exitFrom
;
423 event
.mClickEventPrevented
= mPreventClickEvent
;
428 PanGestureInput::PanGestureInput()
429 : InputData(PANGESTURE_INPUT
),
430 mType(PANGESTURE_MAYSTART
),
431 mLineOrPageDeltaX(0),
432 mLineOrPageDeltaY(0),
433 mUserDeltaMultiplierX(1.0),
434 mUserDeltaMultiplierY(1.0),
435 mHandledByAPZ(false),
436 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
437 mOverscrollBehaviorAllowsSwipe(false),
438 mSimulateMomentum(false),
439 mIsNoLineOrPageDelta(true) {}
441 PanGestureInput::PanGestureInput(PanGestureType aType
, uint32_t aTime
,
442 TimeStamp aTimeStamp
,
443 const ScreenPoint
& aPanStartPoint
,
444 const ScreenPoint
& aPanDisplacement
,
445 Modifiers aModifiers
)
446 : InputData(PANGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
448 mPanStartPoint(aPanStartPoint
),
449 mPanDisplacement(aPanDisplacement
),
450 mLineOrPageDeltaX(0),
451 mLineOrPageDeltaY(0),
452 mUserDeltaMultiplierX(1.0),
453 mUserDeltaMultiplierY(1.0),
454 mHandledByAPZ(false),
455 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
456 mOverscrollBehaviorAllowsSwipe(false),
457 mSimulateMomentum(false),
458 mIsNoLineOrPageDelta(true) {}
460 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
461 int32_t aLineOrPageDeltaY
) {
462 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
463 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
464 mIsNoLineOrPageDelta
= false;
467 bool PanGestureInput::IsMomentum() const {
469 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
470 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
471 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
478 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
479 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
480 wheelEvent
.mModifiers
= this->modifiers
;
481 wheelEvent
.mTime
= mTime
;
482 wheelEvent
.mTimeStamp
= mTimeStamp
;
483 wheelEvent
.mLayersId
= mLayersId
;
484 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
486 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
487 wheelEvent
.mButtons
= 0;
488 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
489 wheelEvent
.mIsMomentum
= IsMomentum();
490 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
491 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
492 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
493 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
494 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
495 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
496 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
497 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
498 // widget/gtk is currently the only consumer that uses delta type
500 // Emulate legacy widget/gtk behavior
501 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
502 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
503 wheelEvent
.mDeltaX
*= 3;
504 wheelEvent
.mDeltaY
*= 3;
506 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
511 bool PanGestureInput::TransformToLocal(
512 const ScreenToParentLayerMatrix4x4
& aTransform
) {
513 Maybe
<ParentLayerPoint
> panStartPoint
=
514 UntransformBy(aTransform
, mPanStartPoint
);
515 if (!panStartPoint
) {
518 mLocalPanStartPoint
= *panStartPoint
;
520 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
521 // Skip transforming the pan displacement because we want
522 // raw page proportion counts.
523 mLocalPanDisplacement
.x
= mPanDisplacement
.x
;
524 mLocalPanDisplacement
.y
= mPanDisplacement
.y
;
528 Maybe
<ParentLayerPoint
> panDisplacement
=
529 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
530 if (!panDisplacement
) {
533 mLocalPanDisplacement
= *panDisplacement
;
537 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
538 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
539 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
542 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
543 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
544 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
547 static int32_t TakeLargestInt(gfx::Float
* aFloat
) {
548 int32_t result(*aFloat
); // truncate towards zero
553 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
554 bool aIsStart
, float x
, float y
) {
555 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
557 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
561 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
562 TakeLargestInt(&sAccumulator
.y
));
565 PinchGestureInput::PinchGestureInput()
566 : InputData(PINCHGESTURE_INPUT
),
567 mType(PINCHGESTURE_START
),
569 mHandledByAPZ(false) {}
571 PinchGestureInput::PinchGestureInput(
572 PinchGestureType aType
, PinchGestureSource aSource
, uint32_t aTime
,
573 TimeStamp aTimeStamp
, const ExternalPoint
& aScreenOffset
,
574 const ScreenPoint
& aFocusPoint
, ScreenCoord aCurrentSpan
,
575 ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
576 : InputData(PINCHGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
579 mFocusPoint(aFocusPoint
),
580 mScreenOffset(aScreenOffset
),
581 mCurrentSpan(aCurrentSpan
),
582 mPreviousSpan(aPreviousSpan
),
583 mLineOrPageDeltaY(0),
584 mHandledByAPZ(false) {}
586 bool PinchGestureInput::TransformToLocal(
587 const ScreenToParentLayerMatrix4x4
& aTransform
) {
588 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
592 mLocalFocusPoint
= *point
;
596 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
597 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
598 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
599 wheelEvent
.mTime
= mTime
;
600 wheelEvent
.mTimeStamp
= mTimeStamp
;
601 wheelEvent
.mLayersId
= mLayersId
;
602 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
604 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
605 wheelEvent
.mButtons
= 0;
606 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
607 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
609 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
611 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
613 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
618 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
619 #if defined(OS_MACOSX)
620 // This converts the pinch gesture value to a fake wheel event that has the
621 // control key pressed so that pages can implement custom pinch gesture
622 // handling. It may seem strange that this doesn't use a wheel event with
623 // the deltaZ property set, but this matches Chrome's behavior as described
624 // at https://code.google.com/p/chromium/issues/detail?id=289887
626 // The intent of the formula below is to produce numbers similar to Chrome's
627 // implementation of this feature. Chrome implements deltaY using the formula
628 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
629 // All deltas for a single pinch gesture should sum to 0 if the start and end
630 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
631 // because they followed Apple's misleading documentation, which implies that
632 // "1 + [event magnification]" is the scale factor. The scale factor is
633 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
634 // already in log space.
636 // The multiplication by the backing scale factor below counteracts the
637 // division by the backing scale factor in WheelEvent.
639 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
640 // is [event magnification] but [event magnification] is only available in the
641 // macOS widget code so we have to reverse engineer from mCurrentSpan and
642 // mPreviousSpan (which are derived from [event magnification]) to get it.
643 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
644 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
645 // for M in terms of mPreviousSpan and plugging that into to the formula for
647 return (mPreviousSpan
- 100.0) *
648 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
650 // This calculation is based on what the Windows and Linux widget code does.
651 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
652 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
653 // is the scale from the current OS event and lastScale is the scale when the
654 // previous OS event happened. On macOS [event magnification] is a relative
655 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
656 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
657 // calculate the relative scale change on Windows we would calculate |M =
658 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
659 // same formula as the macOS code
660 // (|-100.0 * M * GetDefaultScaleInternal()|).
662 return (mPreviousSpan
- mCurrentSpan
) *
663 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
667 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
668 double deltaY
= ComputeDeltaY(aWidget
);
669 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
672 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
673 (mType
== PINCHGESTURE_START
), 0, deltaY
);
674 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
675 if (mLineOrPageDeltaY
== 0) {
676 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
677 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
678 if (mType
== PINCHGESTURE_SCALE
) {
681 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
682 // defer the START event until we accumulate enough delta).
683 // The Linux widget code doesn't support this, so instead set the event's
684 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
686 if (mType
== PINCHGESTURE_START
) {
690 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
693 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
699 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
700 bool aIsStart
, float x
, float y
) {
701 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
703 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
707 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
708 TakeLargestInt(&sAccumulator
.y
));
711 TapGestureInput::TapGestureInput()
712 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
714 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
715 TimeStamp aTimeStamp
,
716 const ScreenIntPoint
& aPoint
,
717 Modifiers aModifiers
)
718 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
722 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
723 TimeStamp aTimeStamp
,
724 const ParentLayerPoint
& aLocalPoint
,
725 Modifiers aModifiers
)
726 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
728 mLocalPoint(aLocalPoint
) {}
730 bool TapGestureInput::TransformToLocal(
731 const ScreenToParentLayerMatrix4x4
& aTransform
) {
732 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
736 mLocalPoint
= *point
;
740 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
741 nsIWidget
* aWidget
) const {
742 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
745 event
.mTimeStamp
= mTimeStamp
;
746 event
.mLayersId
= mLayersId
;
747 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
749 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
751 event
.mClickCount
= 1;
752 event
.mModifiers
= modifiers
;
757 ScrollWheelInput::ScrollWheelInput()
758 : InputData(SCROLLWHEEL_INPUT
),
759 mDeltaType(SCROLLDELTA_LINE
),
760 mScrollMode(SCROLLMODE_INSTANT
),
761 mHandledByAPZ(false),
764 mLineOrPageDeltaX(0),
765 mLineOrPageDeltaY(0),
766 mScrollSeriesNumber(0),
767 mUserDeltaMultiplierX(1.0),
768 mUserDeltaMultiplierY(1.0),
769 mMayHaveMomentum(false),
771 mAPZAction(APZWheelAction::Scroll
) {}
773 ScrollWheelInput::ScrollWheelInput(
774 uint32_t aTime
, TimeStamp aTimeStamp
, Modifiers aModifiers
,
775 ScrollMode aScrollMode
, ScrollDeltaType aDeltaType
,
776 const ScreenPoint
& aOrigin
, double aDeltaX
, double aDeltaY
,
777 bool aAllowToOverrideSystemScrollSpeed
,
778 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
779 : InputData(SCROLLWHEEL_INPUT
, aTime
, aTimeStamp
, aModifiers
),
780 mDeltaType(aDeltaType
),
781 mScrollMode(aScrollMode
),
783 mHandledByAPZ(false),
786 mLineOrPageDeltaX(0),
787 mLineOrPageDeltaY(0),
788 mScrollSeriesNumber(0),
789 mUserDeltaMultiplierX(1.0),
790 mUserDeltaMultiplierY(1.0),
791 mMayHaveMomentum(false),
793 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
794 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
795 mAPZAction(APZWheelAction::Scroll
) {}
797 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
798 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTime
, aWheelEvent
.mTimeStamp
,
799 aWheelEvent
.mModifiers
),
800 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
801 mScrollMode(SCROLLMODE_INSTANT
),
802 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
803 mDeltaX(aWheelEvent
.mDeltaX
),
804 mDeltaY(aWheelEvent
.mDeltaY
),
805 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
806 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
807 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
808 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
809 mScrollSeriesNumber(0),
810 mUserDeltaMultiplierX(1.0),
811 mUserDeltaMultiplierY(1.0),
812 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
813 mIsMomentum(aWheelEvent
.mIsMomentum
),
814 mAllowToOverrideSystemScrollSpeed(
815 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
816 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
817 mAPZAction(APZWheelAction::Scroll
) {
818 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
819 aWheelEvent
.mRefPoint
,
820 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
823 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
824 uint32_t aDeltaMode
) {
825 switch (aDeltaMode
) {
826 case WheelEvent_Binding::DOM_DELTA_LINE
:
827 return SCROLLDELTA_LINE
;
828 case WheelEvent_Binding::DOM_DELTA_PAGE
:
829 return SCROLLDELTA_PAGE
;
830 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
831 return SCROLLDELTA_PIXEL
;
835 return SCROLLDELTA_LINE
;
838 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
839 switch (aDeltaType
) {
840 case ScrollWheelInput::SCROLLDELTA_LINE
:
841 return WheelEvent_Binding::DOM_DELTA_LINE
;
842 case ScrollWheelInput::SCROLLDELTA_PAGE
:
843 return WheelEvent_Binding::DOM_DELTA_PAGE
;
844 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
846 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
850 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
851 ScrollDeltaType aDeltaType
) {
852 switch (aDeltaType
) {
853 case SCROLLDELTA_LINE
:
854 return ScrollUnit::LINES
;
855 case SCROLLDELTA_PAGE
:
856 return ScrollUnit::PAGES
;
857 case SCROLLDELTA_PIXEL
:
858 return ScrollUnit::DEVICE_PIXELS
;
862 return ScrollUnit::LINES
;
865 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
866 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
867 wheelEvent
.mModifiers
= this->modifiers
;
868 wheelEvent
.mTime
= mTime
;
869 wheelEvent
.mTimeStamp
= mTimeStamp
;
870 wheelEvent
.mLayersId
= mLayersId
;
871 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
873 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
874 wheelEvent
.mButtons
= 0;
875 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
876 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
877 wheelEvent
.mIsMomentum
= mIsMomentum
;
878 wheelEvent
.mDeltaX
= mDeltaX
;
879 wheelEvent
.mDeltaY
= mDeltaY
;
880 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
881 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
882 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
883 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
884 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
885 mAllowToOverrideSystemScrollSpeed
;
886 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
887 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
891 bool ScrollWheelInput::TransformToLocal(
892 const ScreenToParentLayerMatrix4x4
& aTransform
) {
893 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
897 mLocalOrigin
= *point
;
901 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
902 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
905 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
906 : InputData(KEYBOARD_INPUT
, aEvent
.mTime
, aEvent
.mTimeStamp
,
908 mKeyCode(aEvent
.mKeyCode
),
909 mCharCode(aEvent
.mCharCode
),
910 mHandledByAPZ(false) {
911 switch (aEvent
.mMessage
) {
913 mType
= KeyboardInput::KEY_PRESS
;
917 mType
= KeyboardInput::KEY_UP
;
921 mType
= KeyboardInput::KEY_DOWN
;
925 mType
= KeyboardInput::KEY_OTHER
;
929 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
932 KeyboardInput::KeyboardInput()
933 : InputData(KEYBOARD_INPUT
),
937 mHandledByAPZ(false) {}
939 } // namespace mozilla