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 mFollowedByMomentum(false),
437 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
438 mOverscrollBehaviorAllowsSwipe(false),
439 mSimulateMomentum(false),
440 mIsNoLineOrPageDelta(true) {}
442 PanGestureInput::PanGestureInput(PanGestureType aType
, uint32_t aTime
,
443 TimeStamp aTimeStamp
,
444 const ScreenPoint
& aPanStartPoint
,
445 const ScreenPoint
& aPanDisplacement
,
446 Modifiers aModifiers
)
447 : InputData(PANGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
449 mPanStartPoint(aPanStartPoint
),
450 mPanDisplacement(aPanDisplacement
),
451 mLineOrPageDeltaX(0),
452 mLineOrPageDeltaY(0),
453 mUserDeltaMultiplierX(1.0),
454 mUserDeltaMultiplierY(1.0),
455 mHandledByAPZ(false),
456 mFollowedByMomentum(false),
457 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
458 mOverscrollBehaviorAllowsSwipe(false),
459 mSimulateMomentum(false),
460 mIsNoLineOrPageDelta(true) {}
462 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
463 int32_t aLineOrPageDeltaY
) {
464 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
465 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
466 mIsNoLineOrPageDelta
= false;
469 bool PanGestureInput::IsMomentum() const {
471 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
472 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
473 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
480 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
481 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
482 wheelEvent
.mModifiers
= this->modifiers
;
483 wheelEvent
.mTime
= mTime
;
484 wheelEvent
.mTimeStamp
= mTimeStamp
;
485 wheelEvent
.mLayersId
= mLayersId
;
486 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
488 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
489 wheelEvent
.mButtons
= 0;
490 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
491 wheelEvent
.mIsMomentum
= IsMomentum();
492 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
493 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
494 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
495 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
496 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
497 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
498 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
499 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
500 // widget/gtk is currently the only consumer that uses delta type
502 // Emulate legacy widget/gtk behavior
503 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
504 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
505 wheelEvent
.mDeltaX
*= 3;
506 wheelEvent
.mDeltaY
*= 3;
508 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
513 bool PanGestureInput::TransformToLocal(
514 const ScreenToParentLayerMatrix4x4
& aTransform
) {
515 Maybe
<ParentLayerPoint
> panStartPoint
=
516 UntransformBy(aTransform
, mPanStartPoint
);
517 if (!panStartPoint
) {
520 mLocalPanStartPoint
= *panStartPoint
;
522 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
523 // Skip transforming the pan displacement because we want
524 // raw page proportion counts.
525 mLocalPanDisplacement
.x
= mPanDisplacement
.x
;
526 mLocalPanDisplacement
.y
= mPanDisplacement
.y
;
530 Maybe
<ParentLayerPoint
> panDisplacement
=
531 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
532 if (!panDisplacement
) {
535 mLocalPanDisplacement
= *panDisplacement
;
539 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
540 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
541 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
544 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
545 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
546 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
549 static int32_t TakeLargestInt(gfx::Float
* aFloat
) {
550 int32_t result(*aFloat
); // truncate towards zero
555 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
556 bool aIsStart
, float x
, float y
) {
557 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
559 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
563 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
564 TakeLargestInt(&sAccumulator
.y
));
567 PinchGestureInput::PinchGestureInput()
568 : InputData(PINCHGESTURE_INPUT
),
569 mType(PINCHGESTURE_START
),
571 mHandledByAPZ(false) {}
573 PinchGestureInput::PinchGestureInput(
574 PinchGestureType aType
, PinchGestureSource aSource
, uint32_t aTime
,
575 TimeStamp aTimeStamp
, const ExternalPoint
& aScreenOffset
,
576 const ScreenPoint
& aFocusPoint
, ScreenCoord aCurrentSpan
,
577 ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
578 : InputData(PINCHGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
581 mFocusPoint(aFocusPoint
),
582 mScreenOffset(aScreenOffset
),
583 mCurrentSpan(aCurrentSpan
),
584 mPreviousSpan(aPreviousSpan
),
585 mLineOrPageDeltaY(0),
586 mHandledByAPZ(false) {}
588 bool PinchGestureInput::TransformToLocal(
589 const ScreenToParentLayerMatrix4x4
& aTransform
) {
590 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
594 mLocalFocusPoint
= *point
;
598 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
599 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
600 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
601 wheelEvent
.mTime
= mTime
;
602 wheelEvent
.mTimeStamp
= mTimeStamp
;
603 wheelEvent
.mLayersId
= mLayersId
;
604 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
606 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
607 wheelEvent
.mButtons
= 0;
608 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
609 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
611 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
613 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
615 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
620 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
621 #if defined(OS_MACOSX)
622 // This converts the pinch gesture value to a fake wheel event that has the
623 // control key pressed so that pages can implement custom pinch gesture
624 // handling. It may seem strange that this doesn't use a wheel event with
625 // the deltaZ property set, but this matches Chrome's behavior as described
626 // at https://code.google.com/p/chromium/issues/detail?id=289887
628 // The intent of the formula below is to produce numbers similar to Chrome's
629 // implementation of this feature. Chrome implements deltaY using the formula
630 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
631 // All deltas for a single pinch gesture should sum to 0 if the start and end
632 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
633 // because they followed Apple's misleading documentation, which implies that
634 // "1 + [event magnification]" is the scale factor. The scale factor is
635 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
636 // already in log space.
638 // The multiplication by the backing scale factor below counteracts the
639 // division by the backing scale factor in WheelEvent.
641 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
642 // is [event magnification] but [event magnification] is only available in the
643 // macOS widget code so we have to reverse engineer from mCurrentSpan and
644 // mPreviousSpan (which are derived from [event magnification]) to get it.
645 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
646 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
647 // for M in terms of mPreviousSpan and plugging that into to the formula for
649 return (mPreviousSpan
- 100.0) *
650 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
652 // This calculation is based on what the Windows and Linux widget code does.
653 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
654 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
655 // is the scale from the current OS event and lastScale is the scale when the
656 // previous OS event happened. On macOS [event magnification] is a relative
657 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
658 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
659 // calculate the relative scale change on Windows we would calculate |M =
660 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
661 // same formula as the macOS code
662 // (|-100.0 * M * GetDefaultScaleInternal()|).
664 return (mPreviousSpan
- mCurrentSpan
) *
665 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
669 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
670 double deltaY
= ComputeDeltaY(aWidget
);
671 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
674 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
675 (mType
== PINCHGESTURE_START
), 0, deltaY
);
676 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
677 if (mLineOrPageDeltaY
== 0) {
678 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
679 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
680 if (mType
== PINCHGESTURE_SCALE
) {
683 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
684 // defer the START event until we accumulate enough delta).
685 // The Linux widget code doesn't support this, so instead set the event's
686 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
688 if (mType
== PINCHGESTURE_START
) {
692 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
695 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
701 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
702 bool aIsStart
, float x
, float y
) {
703 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
705 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
709 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
710 TakeLargestInt(&sAccumulator
.y
));
713 TapGestureInput::TapGestureInput()
714 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
716 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
717 TimeStamp aTimeStamp
,
718 const ScreenIntPoint
& aPoint
,
719 Modifiers aModifiers
)
720 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
724 TapGestureInput::TapGestureInput(TapGestureType aType
, uint32_t aTime
,
725 TimeStamp aTimeStamp
,
726 const ParentLayerPoint
& aLocalPoint
,
727 Modifiers aModifiers
)
728 : InputData(TAPGESTURE_INPUT
, aTime
, aTimeStamp
, aModifiers
),
730 mLocalPoint(aLocalPoint
) {}
732 bool TapGestureInput::TransformToLocal(
733 const ScreenToParentLayerMatrix4x4
& aTransform
) {
734 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
738 mLocalPoint
= *point
;
742 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
743 nsIWidget
* aWidget
) const {
744 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
747 event
.mTimeStamp
= mTimeStamp
;
748 event
.mLayersId
= mLayersId
;
749 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
751 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
753 event
.mClickCount
= 1;
754 event
.mModifiers
= modifiers
;
759 ScrollWheelInput::ScrollWheelInput()
760 : InputData(SCROLLWHEEL_INPUT
),
761 mDeltaType(SCROLLDELTA_LINE
),
762 mScrollMode(SCROLLMODE_INSTANT
),
763 mHandledByAPZ(false),
766 mLineOrPageDeltaX(0),
767 mLineOrPageDeltaY(0),
768 mScrollSeriesNumber(0),
769 mUserDeltaMultiplierX(1.0),
770 mUserDeltaMultiplierY(1.0),
771 mMayHaveMomentum(false),
773 mAPZAction(APZWheelAction::Scroll
) {}
775 ScrollWheelInput::ScrollWheelInput(
776 uint32_t aTime
, TimeStamp aTimeStamp
, Modifiers aModifiers
,
777 ScrollMode aScrollMode
, ScrollDeltaType aDeltaType
,
778 const ScreenPoint
& aOrigin
, double aDeltaX
, double aDeltaY
,
779 bool aAllowToOverrideSystemScrollSpeed
,
780 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
781 : InputData(SCROLLWHEEL_INPUT
, aTime
, aTimeStamp
, aModifiers
),
782 mDeltaType(aDeltaType
),
783 mScrollMode(aScrollMode
),
785 mHandledByAPZ(false),
788 mLineOrPageDeltaX(0),
789 mLineOrPageDeltaY(0),
790 mScrollSeriesNumber(0),
791 mUserDeltaMultiplierX(1.0),
792 mUserDeltaMultiplierY(1.0),
793 mMayHaveMomentum(false),
795 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
796 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
797 mAPZAction(APZWheelAction::Scroll
) {}
799 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
800 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTime
, aWheelEvent
.mTimeStamp
,
801 aWheelEvent
.mModifiers
),
802 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
803 mScrollMode(SCROLLMODE_INSTANT
),
804 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
805 mDeltaX(aWheelEvent
.mDeltaX
),
806 mDeltaY(aWheelEvent
.mDeltaY
),
807 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
808 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
809 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
810 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
811 mScrollSeriesNumber(0),
812 mUserDeltaMultiplierX(1.0),
813 mUserDeltaMultiplierY(1.0),
814 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
815 mIsMomentum(aWheelEvent
.mIsMomentum
),
816 mAllowToOverrideSystemScrollSpeed(
817 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
818 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
819 mAPZAction(APZWheelAction::Scroll
) {
820 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
821 aWheelEvent
.mRefPoint
,
822 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
825 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
826 uint32_t aDeltaMode
) {
827 switch (aDeltaMode
) {
828 case WheelEvent_Binding::DOM_DELTA_LINE
:
829 return SCROLLDELTA_LINE
;
830 case WheelEvent_Binding::DOM_DELTA_PAGE
:
831 return SCROLLDELTA_PAGE
;
832 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
833 return SCROLLDELTA_PIXEL
;
837 return SCROLLDELTA_LINE
;
840 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
841 switch (aDeltaType
) {
842 case ScrollWheelInput::SCROLLDELTA_LINE
:
843 return WheelEvent_Binding::DOM_DELTA_LINE
;
844 case ScrollWheelInput::SCROLLDELTA_PAGE
:
845 return WheelEvent_Binding::DOM_DELTA_PAGE
;
846 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
848 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
852 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
853 ScrollDeltaType aDeltaType
) {
854 switch (aDeltaType
) {
855 case SCROLLDELTA_LINE
:
856 return ScrollUnit::LINES
;
857 case SCROLLDELTA_PAGE
:
858 return ScrollUnit::PAGES
;
859 case SCROLLDELTA_PIXEL
:
860 return ScrollUnit::DEVICE_PIXELS
;
864 return ScrollUnit::LINES
;
867 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
868 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
869 wheelEvent
.mModifiers
= this->modifiers
;
870 wheelEvent
.mTime
= mTime
;
871 wheelEvent
.mTimeStamp
= mTimeStamp
;
872 wheelEvent
.mLayersId
= mLayersId
;
873 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
875 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
876 wheelEvent
.mButtons
= 0;
877 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
878 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
879 wheelEvent
.mIsMomentum
= mIsMomentum
;
880 wheelEvent
.mDeltaX
= mDeltaX
;
881 wheelEvent
.mDeltaY
= mDeltaY
;
882 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
883 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
884 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
885 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
886 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
887 mAllowToOverrideSystemScrollSpeed
;
888 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
889 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
893 bool ScrollWheelInput::TransformToLocal(
894 const ScreenToParentLayerMatrix4x4
& aTransform
) {
895 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
899 mLocalOrigin
= *point
;
903 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
904 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
907 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
908 : InputData(KEYBOARD_INPUT
, aEvent
.mTime
, aEvent
.mTimeStamp
,
910 mKeyCode(aEvent
.mKeyCode
),
911 mCharCode(aEvent
.mCharCode
),
912 mHandledByAPZ(false) {
913 switch (aEvent
.mMessage
) {
915 mType
= KeyboardInput::KEY_PRESS
;
919 mType
= KeyboardInput::KEY_UP
;
923 mType
= KeyboardInput::KEY_DOWN
;
927 mType
= KeyboardInput::KEY_OTHER
;
931 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
934 KeyboardInput::KeyboardInput()
935 : InputData(KEYBOARD_INPUT
),
939 mHandledByAPZ(false) {}
941 } // namespace mozilla