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 "mozilla/SwipeTracker.h"
18 #include "UnitTransforms.h"
24 InputData::~InputData() = default;
26 InputData::InputData(InputType aInputType
)
27 : mInputType(aInputType
),
28 mFocusSequenceNumber(0),
32 InputData::InputData(InputType aInputType
, TimeStamp aTimeStamp
,
34 : mInputType(aInputType
),
35 mTimeStamp(aTimeStamp
),
36 mFocusSequenceNumber(0),
38 modifiers(aModifiers
) {}
40 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
41 ScreenIntPoint aScreenPoint
,
42 ScreenSize aRadius
, float aRotationAngle
,
44 : mIdentifier(aIdentifier
),
45 mScreenPoint(aScreenPoint
),
47 mRotationAngle(aRotationAngle
),
50 SingleTouchData::SingleTouchData(int32_t aIdentifier
,
51 ParentLayerPoint aLocalScreenPoint
,
52 ScreenSize aRadius
, float aRotationAngle
,
54 : mIdentifier(aIdentifier
),
55 mLocalScreenPoint(aLocalScreenPoint
),
57 mRotationAngle(aRotationAngle
),
60 SingleTouchData::SingleTouchData()
61 : mIdentifier(0), mRotationAngle(0.0), mForce(0.0) {}
63 already_AddRefed
<Touch
> SingleTouchData::ToNewDOMTouch() const {
64 MOZ_ASSERT(NS_IsMainThread(),
65 "Can only create dom::Touch instances on main thread");
67 new Touch(mIdentifier
,
68 LayoutDeviceIntPoint::Truncate(mScreenPoint
.x
, mScreenPoint
.y
),
69 LayoutDeviceIntPoint::Truncate(mRadius
.width
, mRadius
.height
),
70 mRotationAngle
, mForce
);
71 touch
->tiltX
= mTiltX
;
72 touch
->tiltY
= mTiltY
;
73 touch
->twist
= mTwist
;
74 return touch
.forget();
77 MultiTouchInput::MultiTouchInput(MultiTouchType aType
, uint32_t aTime
,
78 TimeStamp aTimeStamp
, Modifiers aModifiers
)
79 : InputData(MULTITOUCH_INPUT
, aTimeStamp
, aModifiers
),
81 mHandledByAPZ(false) {}
83 MultiTouchInput::MultiTouchInput()
84 : InputData(MULTITOUCH_INPUT
),
85 mType(MULTITOUCH_START
),
86 mHandledByAPZ(false) {}
88 MultiTouchInput::MultiTouchInput(const WidgetTouchEvent
& aTouchEvent
)
89 : InputData(MULTITOUCH_INPUT
, aTouchEvent
.mTimeStamp
,
90 aTouchEvent
.mModifiers
),
91 mHandledByAPZ(aTouchEvent
.mFlags
.mHandledByAPZ
),
92 mButton(aTouchEvent
.mButton
),
93 mButtons(aTouchEvent
.mButtons
) {
94 MOZ_ASSERT(NS_IsMainThread(),
95 "Can only copy from WidgetTouchEvent on main thread");
97 switch (aTouchEvent
.mMessage
) {
99 mType
= MULTITOUCH_START
;
102 mType
= MULTITOUCH_MOVE
;
105 mType
= MULTITOUCH_END
;
108 mType
= MULTITOUCH_CANCEL
;
111 MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
115 mScreenOffset
= ViewAs
<ExternalPixel
>(
116 aTouchEvent
.mWidget
->WidgetToScreenOffset(),
117 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
119 for (size_t i
= 0; i
< aTouchEvent
.mTouches
.Length(); i
++) {
120 const Touch
* domTouch
= aTouchEvent
.mTouches
[i
];
122 // Extract data from weird interfaces.
123 int32_t identifier
= domTouch
->Identifier();
124 int32_t radiusX
= domTouch
->RadiusX(CallerType::System
);
125 int32_t radiusY
= domTouch
->RadiusY(CallerType::System
);
126 float rotationAngle
= domTouch
->RotationAngle(CallerType::System
);
127 float force
= domTouch
->Force(CallerType::System
);
129 SingleTouchData
data(
133 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
),
134 ScreenSize((float)radiusX
, (float)radiusY
), rotationAngle
, force
);
136 mTouches
.AppendElement(data
);
140 void MultiTouchInput::Translate(const ScreenPoint
& aTranslation
) {
141 ScreenIntPoint translation
= RoundedToInt(aTranslation
);
143 for (auto& touchData
: mTouches
) {
144 for (auto& historicalData
: touchData
.mHistoricalData
) {
145 historicalData
.mScreenPoint
.MoveBy(translation
.x
, translation
.y
);
147 touchData
.mScreenPoint
.MoveBy(translation
.x
, translation
.y
);
151 WidgetTouchEvent
MultiTouchInput::ToWidgetEvent(nsIWidget
* aWidget
,
152 uint16_t aInputSource
) const {
153 MOZ_ASSERT(NS_IsMainThread(),
154 "Can only convert To WidgetTouchEvent on main thread");
155 MOZ_ASSERT(aInputSource
==
156 mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
||
157 aInputSource
== mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_PEN
);
159 EventMessage touchEventMessage
= eVoidEvent
;
161 case MULTITOUCH_START
:
162 touchEventMessage
= eTouchStart
;
164 case MULTITOUCH_MOVE
:
165 touchEventMessage
= eTouchMove
;
168 touchEventMessage
= eTouchEnd
;
170 case MULTITOUCH_CANCEL
:
171 touchEventMessage
= eTouchCancel
;
174 MOZ_ASSERT_UNREACHABLE(
175 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
179 WidgetTouchEvent
event(true, touchEventMessage
, aWidget
);
180 if (touchEventMessage
== eVoidEvent
) {
184 event
.mModifiers
= this->modifiers
;
185 event
.mTimeStamp
= this->mTimeStamp
;
186 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
187 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
188 event
.mLayersId
= mLayersId
;
189 event
.mInputSource
= aInputSource
;
190 event
.mButton
= mButton
;
191 event
.mButtons
= mButtons
;
193 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
194 *event
.mTouches
.AppendElement() = mTouches
[i
].ToNewDOMTouch();
200 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier
) {
201 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
202 if (mTouches
[i
].mIdentifier
== aTouchIdentifier
) {
209 bool MultiTouchInput::TransformToLocal(
210 const ScreenToParentLayerMatrix4x4
& aTransform
) {
211 for (auto& touchData
: mTouches
) {
212 for (auto& historicalData
: touchData
.mHistoricalData
) {
213 Maybe
<ParentLayerIntPoint
> historicalPoint
=
214 UntransformBy(aTransform
, historicalData
.mScreenPoint
);
215 if (!historicalPoint
) {
218 historicalData
.mLocalScreenPoint
= *historicalPoint
;
220 Maybe
<ParentLayerIntPoint
> point
=
221 UntransformBy(aTransform
, touchData
.mScreenPoint
);
225 touchData
.mLocalScreenPoint
= *point
;
230 MouseInput::MouseInput()
231 : InputData(MOUSE_INPUT
),
236 mHandledByAPZ(false),
237 mPreventClickEvent(false) {}
239 MouseInput::MouseInput(MouseType aType
, ButtonType aButtonType
,
240 uint16_t aInputSource
, int16_t aButtons
,
241 const ScreenPoint
& aPoint
, TimeStamp aTimeStamp
,
242 Modifiers aModifiers
)
243 : InputData(MOUSE_INPUT
, aTimeStamp
, aModifiers
),
245 mButtonType(aButtonType
),
246 mInputSource(aInputSource
),
249 mHandledByAPZ(false),
250 mPreventClickEvent(false) {}
252 MouseInput::MouseInput(const WidgetMouseEventBase
& aMouseEvent
)
253 : InputData(MOUSE_INPUT
, aMouseEvent
.mTimeStamp
, aMouseEvent
.mModifiers
),
256 mInputSource(aMouseEvent
.mInputSource
),
257 mButtons(aMouseEvent
.mButtons
),
258 mHandledByAPZ(aMouseEvent
.mFlags
.mHandledByAPZ
),
259 mPreventClickEvent(aMouseEvent
.mClass
== eMouseEventClass
&&
260 aMouseEvent
.AsMouseEvent()->mClickEventPrevented
) {
261 MOZ_ASSERT(NS_IsMainThread(),
262 "Can only copy from WidgetTouchEvent on main thread");
266 switch (aMouseEvent
.mButton
) {
267 case MouseButton::ePrimary
:
268 mButtonType
= MouseInput::PRIMARY_BUTTON
;
270 case MouseButton::eMiddle
:
271 mButtonType
= MouseInput::MIDDLE_BUTTON
;
273 case MouseButton::eSecondary
:
274 mButtonType
= MouseInput::SECONDARY_BUTTON
;
278 switch (aMouseEvent
.mMessage
) {
289 mType
= MOUSE_DRAG_START
;
292 mType
= MOUSE_DRAG_END
;
294 case eMouseEnterIntoWidget
:
295 mType
= MOUSE_WIDGET_ENTER
;
297 case eMouseExitFromWidget
:
298 mType
= MOUSE_WIDGET_EXIT
;
300 case eMouseExploreByTouch
:
301 mType
= MOUSE_EXPLORE_BY_TOUCH
;
304 mType
= MOUSE_HITTEST
;
307 mType
= MOUSE_CONTEXTMENU
;
310 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
314 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
315 aMouseEvent
.mRefPoint
,
316 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
319 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
321 bool MouseInput::TransformToLocal(
322 const ScreenToParentLayerMatrix4x4
& aTransform
) {
323 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
327 mLocalOrigin
= *point
;
332 WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
333 MOZ_ASSERT(NS_IsMainThread(),
334 "Can only convert To WidgetTouchEvent on main thread");
336 EventMessage msg
= eVoidEvent
;
337 uint32_t clickCount
= 0;
338 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
351 case MOUSE_DRAG_START
:
357 case MOUSE_WIDGET_ENTER
:
358 msg
= eMouseEnterIntoWidget
;
360 case MOUSE_WIDGET_EXIT
:
361 msg
= eMouseExitFromWidget
;
362 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
364 case MOUSE_EXPLORE_BY_TOUCH
:
365 msg
= eMouseExploreByTouch
;
370 case MOUSE_CONTEXTMENU
:
374 MOZ_ASSERT_UNREACHABLE(
375 "Did not assign a type to WidgetMouseEvent in MouseInput");
379 WidgetMouseEvent
event(true, msg
, aWidget
, WidgetMouseEvent::eReal
,
380 WidgetMouseEvent::eNormal
);
382 if (msg
== eVoidEvent
) {
386 switch (mButtonType
) {
387 case MouseInput::PRIMARY_BUTTON
:
388 event
.mButton
= MouseButton::ePrimary
;
390 case MouseInput::MIDDLE_BUTTON
:
391 event
.mButton
= MouseButton::eMiddle
;
393 case MouseInput::SECONDARY_BUTTON
:
394 event
.mButton
= MouseButton::eSecondary
;
396 case MouseInput::NONE
:
401 event
.mButtons
= mButtons
;
402 event
.mModifiers
= modifiers
;
403 event
.mTimeStamp
= mTimeStamp
;
404 event
.mLayersId
= mLayersId
;
405 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
406 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
408 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
409 event
.mClickCount
= clickCount
;
410 event
.mInputSource
= mInputSource
;
411 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
412 event
.mExitFrom
= exitFrom
;
413 event
.mClickEventPrevented
= mPreventClickEvent
;
418 PanGestureInput::PanGestureInput()
419 : InputData(PANGESTURE_INPUT
),
420 mType(PANGESTURE_MAYSTART
),
421 mLineOrPageDeltaX(0),
422 mLineOrPageDeltaY(0),
423 mUserDeltaMultiplierX(1.0),
424 mUserDeltaMultiplierY(1.0),
425 mHandledByAPZ(false),
426 mOverscrollBehaviorAllowsSwipe(false),
427 mSimulateMomentum(false),
428 mIsNoLineOrPageDelta(true),
429 mMayTriggerSwipe(false) {}
431 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
432 const ScreenPoint
& aPanStartPoint
,
433 const ScreenPoint
& aPanDisplacement
,
434 Modifiers aModifiers
)
435 : InputData(PANGESTURE_INPUT
, aTimeStamp
, aModifiers
),
437 mPanStartPoint(aPanStartPoint
),
438 mPanDisplacement(aPanDisplacement
),
439 mLineOrPageDeltaX(0),
440 mLineOrPageDeltaY(0),
441 mUserDeltaMultiplierX(1.0),
442 mUserDeltaMultiplierY(1.0),
443 mHandledByAPZ(false),
444 mOverscrollBehaviorAllowsSwipe(false),
445 mSimulateMomentum(false),
446 mIsNoLineOrPageDelta(true) {
447 mMayTriggerSwipe
= SwipeTracker::CanTriggerSwipe(*this);
450 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
451 const ScreenPoint
& aPanStartPoint
,
452 const ScreenPoint
& aPanDisplacement
,
453 Modifiers aModifiers
,
454 IsEligibleForSwipe aIsEligibleForSwipe
)
455 : PanGestureInput(aType
, aTimeStamp
, aPanStartPoint
, aPanDisplacement
,
457 mMayTriggerSwipe
&= bool(aIsEligibleForSwipe
);
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
.mTimeStamp
= mTimeStamp
;
482 wheelEvent
.mLayersId
= mLayersId
;
483 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
485 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
486 wheelEvent
.mButtons
= 0;
487 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
488 wheelEvent
.mIsMomentum
= IsMomentum();
489 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
490 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
491 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
492 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
493 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
494 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
495 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
496 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
497 // widget/gtk is currently the only consumer that uses delta type
499 // Emulate legacy widget/gtk behavior
500 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
501 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
502 wheelEvent
.mDeltaX
*= 3;
503 wheelEvent
.mDeltaY
*= 3;
505 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
510 bool PanGestureInput::TransformToLocal(
511 const ScreenToParentLayerMatrix4x4
& aTransform
) {
512 Maybe
<ParentLayerPoint
> panStartPoint
=
513 UntransformBy(aTransform
, mPanStartPoint
);
514 if (!panStartPoint
) {
517 mLocalPanStartPoint
= *panStartPoint
;
519 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
520 // Skip transforming the pan displacement because we want
521 // raw page proportion counts.
522 mLocalPanDisplacement
= ViewAs
<ParentLayerPixel
>(
523 mPanDisplacement
, PixelCastJustification::DeltaIsPageProportion
);
527 Maybe
<ParentLayerPoint
> panDisplacement
=
528 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
529 if (!panDisplacement
) {
532 mLocalPanDisplacement
= *panDisplacement
;
536 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
537 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
538 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
541 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
542 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
543 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
546 static int32_t TakeLargestInt(gfx::Coord
* aCoord
) {
547 int32_t result(aCoord
->value
); // truncate towards zero
548 aCoord
->value
-= result
;
552 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
553 bool aIsStart
, float x
, float y
) {
554 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
556 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
560 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
561 TakeLargestInt(&sAccumulator
.y
));
564 PinchGestureInput::PinchGestureInput()
565 : InputData(PINCHGESTURE_INPUT
),
566 mType(PINCHGESTURE_START
),
568 mHandledByAPZ(false) {}
570 PinchGestureInput::PinchGestureInput(
571 PinchGestureType aType
, PinchGestureSource aSource
, TimeStamp aTimeStamp
,
572 const ExternalPoint
& aScreenOffset
, const ScreenPoint
& aFocusPoint
,
573 ScreenCoord aCurrentSpan
, ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
574 : InputData(PINCHGESTURE_INPUT
, aTimeStamp
, aModifiers
),
577 mFocusPoint(aFocusPoint
),
578 mScreenOffset(aScreenOffset
),
579 mCurrentSpan(aCurrentSpan
),
580 mPreviousSpan(aPreviousSpan
),
581 mLineOrPageDeltaY(0),
582 mHandledByAPZ(false) {}
584 bool PinchGestureInput::TransformToLocal(
585 const ScreenToParentLayerMatrix4x4
& aTransform
) {
586 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
590 mLocalFocusPoint
= *point
;
594 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
595 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
596 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
597 wheelEvent
.mTimeStamp
= mTimeStamp
;
598 wheelEvent
.mLayersId
= mLayersId
;
599 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
601 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
602 wheelEvent
.mButtons
= 0;
603 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
604 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
606 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
608 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
610 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
615 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
616 #if defined(XP_DARWIN)
617 // This converts the pinch gesture value to a fake wheel event that has the
618 // control key pressed so that pages can implement custom pinch gesture
619 // handling. It may seem strange that this doesn't use a wheel event with
620 // the deltaZ property set, but this matches Chrome's behavior as described
621 // at https://code.google.com/p/chromium/issues/detail?id=289887
623 // The intent of the formula below is to produce numbers similar to Chrome's
624 // implementation of this feature. Chrome implements deltaY using the formula
625 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
626 // All deltas for a single pinch gesture should sum to 0 if the start and end
627 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
628 // because they followed Apple's misleading documentation, which implies that
629 // "1 + [event magnification]" is the scale factor. The scale factor is
630 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
631 // already in log space.
633 // The multiplication by the backing scale factor below counteracts the
634 // division by the backing scale factor in WheelEvent.
636 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
637 // is [event magnification] but [event magnification] is only available in the
638 // macOS widget code so we have to reverse engineer from mCurrentSpan and
639 // mPreviousSpan (which are derived from [event magnification]) to get it.
640 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
641 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
642 // for M in terms of mPreviousSpan and plugging that into to the formula for
644 return (mPreviousSpan
- 100.0) *
645 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
647 // This calculation is based on what the Windows and Linux widget code does.
648 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
649 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
650 // is the scale from the current OS event and lastScale is the scale when the
651 // previous OS event happened. On macOS [event magnification] is a relative
652 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
653 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
654 // calculate the relative scale change on Windows we would calculate |M =
655 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
656 // same formula as the macOS code
657 // (|-100.0 * M * GetDefaultScaleInternal()|).
659 return (mPreviousSpan
- mCurrentSpan
) *
660 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
664 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
665 double deltaY
= ComputeDeltaY(aWidget
);
666 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
669 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
670 (mType
== PINCHGESTURE_START
), 0, deltaY
);
671 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
672 if (mLineOrPageDeltaY
== 0) {
673 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
674 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
675 if (mType
== PINCHGESTURE_SCALE
) {
678 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
679 // defer the START event until we accumulate enough delta).
680 // The Linux widget code doesn't support this, so instead set the event's
681 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
683 if (mType
== PINCHGESTURE_START
) {
687 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
690 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
696 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
697 bool aIsStart
, float x
, float y
) {
698 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
700 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
704 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
705 TakeLargestInt(&sAccumulator
.y
));
708 TapGestureInput::TapGestureInput()
709 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
711 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
712 const ScreenIntPoint
& aPoint
,
713 Modifiers aModifiers
)
714 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
718 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
719 const ParentLayerPoint
& aLocalPoint
,
720 Modifiers aModifiers
)
721 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
723 mLocalPoint(aLocalPoint
) {}
725 bool TapGestureInput::TransformToLocal(
726 const ScreenToParentLayerMatrix4x4
& aTransform
) {
727 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
731 mLocalPoint
= *point
;
735 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
736 nsIWidget
* aWidget
) const {
737 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
739 event
.mTimeStamp
= mTimeStamp
;
740 event
.mLayersId
= mLayersId
;
741 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
743 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
745 event
.mClickCount
= 1;
746 event
.mModifiers
= modifiers
;
751 ScrollWheelInput::ScrollWheelInput()
752 : InputData(SCROLLWHEEL_INPUT
),
753 mDeltaType(SCROLLDELTA_LINE
),
754 mScrollMode(SCROLLMODE_INSTANT
),
755 mHandledByAPZ(false),
758 mLineOrPageDeltaX(0),
759 mLineOrPageDeltaY(0),
760 mScrollSeriesNumber(0),
761 mUserDeltaMultiplierX(1.0),
762 mUserDeltaMultiplierY(1.0),
763 mMayHaveMomentum(false),
765 mAPZAction(APZWheelAction::Scroll
) {}
767 ScrollWheelInput::ScrollWheelInput(
768 TimeStamp aTimeStamp
, Modifiers aModifiers
, ScrollMode aScrollMode
,
769 ScrollDeltaType aDeltaType
, const ScreenPoint
& aOrigin
, double aDeltaX
,
770 double aDeltaY
, bool aAllowToOverrideSystemScrollSpeed
,
771 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
772 : InputData(SCROLLWHEEL_INPUT
, aTimeStamp
, aModifiers
),
773 mDeltaType(aDeltaType
),
774 mScrollMode(aScrollMode
),
776 mHandledByAPZ(false),
779 mLineOrPageDeltaX(0),
780 mLineOrPageDeltaY(0),
781 mScrollSeriesNumber(0),
782 mUserDeltaMultiplierX(1.0),
783 mUserDeltaMultiplierY(1.0),
784 mMayHaveMomentum(false),
786 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
787 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
788 mAPZAction(APZWheelAction::Scroll
) {}
790 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
791 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTimeStamp
,
792 aWheelEvent
.mModifiers
),
793 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
794 mScrollMode(SCROLLMODE_INSTANT
),
795 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
796 mDeltaX(aWheelEvent
.mDeltaX
),
797 mDeltaY(aWheelEvent
.mDeltaY
),
798 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
799 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
800 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
801 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
802 mScrollSeriesNumber(0),
803 mUserDeltaMultiplierX(1.0),
804 mUserDeltaMultiplierY(1.0),
805 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
806 mIsMomentum(aWheelEvent
.mIsMomentum
),
807 mAllowToOverrideSystemScrollSpeed(
808 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
809 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
810 mAPZAction(APZWheelAction::Scroll
) {
811 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
812 aWheelEvent
.mRefPoint
,
813 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
816 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
817 uint32_t aDeltaMode
) {
818 switch (aDeltaMode
) {
819 case WheelEvent_Binding::DOM_DELTA_LINE
:
820 return SCROLLDELTA_LINE
;
821 case WheelEvent_Binding::DOM_DELTA_PAGE
:
822 return SCROLLDELTA_PAGE
;
823 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
824 return SCROLLDELTA_PIXEL
;
828 return SCROLLDELTA_LINE
;
831 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
832 switch (aDeltaType
) {
833 case ScrollWheelInput::SCROLLDELTA_LINE
:
834 return WheelEvent_Binding::DOM_DELTA_LINE
;
835 case ScrollWheelInput::SCROLLDELTA_PAGE
:
836 return WheelEvent_Binding::DOM_DELTA_PAGE
;
837 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
839 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
843 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
844 ScrollDeltaType aDeltaType
) {
845 switch (aDeltaType
) {
846 case SCROLLDELTA_LINE
:
847 return ScrollUnit::LINES
;
848 case SCROLLDELTA_PAGE
:
849 return ScrollUnit::PAGES
;
850 case SCROLLDELTA_PIXEL
:
851 return ScrollUnit::DEVICE_PIXELS
;
855 return ScrollUnit::LINES
;
858 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
859 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
860 wheelEvent
.mModifiers
= this->modifiers
;
861 wheelEvent
.mTimeStamp
= mTimeStamp
;
862 wheelEvent
.mLayersId
= mLayersId
;
863 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
865 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
866 wheelEvent
.mButtons
= 0;
867 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
868 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
869 wheelEvent
.mIsMomentum
= mIsMomentum
;
870 wheelEvent
.mDeltaX
= mDeltaX
;
871 wheelEvent
.mDeltaY
= mDeltaY
;
872 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
873 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
874 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
875 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
876 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
877 mAllowToOverrideSystemScrollSpeed
;
878 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
879 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
883 bool ScrollWheelInput::TransformToLocal(
884 const ScreenToParentLayerMatrix4x4
& aTransform
) {
885 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
889 mLocalOrigin
= *point
;
893 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
894 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
897 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
898 : InputData(KEYBOARD_INPUT
, aEvent
.mTimeStamp
, aEvent
.mModifiers
),
899 mKeyCode(aEvent
.mKeyCode
),
900 mCharCode(aEvent
.mCharCode
),
901 mHandledByAPZ(false) {
902 switch (aEvent
.mMessage
) {
904 mType
= KeyboardInput::KEY_PRESS
;
908 mType
= KeyboardInput::KEY_UP
;
912 mType
= KeyboardInput::KEY_DOWN
;
916 mType
= KeyboardInput::KEY_OTHER
;
920 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
923 KeyboardInput::KeyboardInput()
924 : InputData(KEYBOARD_INPUT
),
928 mHandledByAPZ(false) {}
930 } // namespace mozilla