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 const int32_t xTranslation
= (int32_t)(aTranslation
.x
+ 0.5f
);
142 const int32_t yTranslation
= (int32_t)(aTranslation
.y
+ 0.5f
);
144 for (auto& touchData
: mTouches
) {
145 for (auto& historicalData
: touchData
.mHistoricalData
) {
146 historicalData
.mScreenPoint
.MoveBy(xTranslation
, yTranslation
);
148 touchData
.mScreenPoint
.MoveBy(xTranslation
, yTranslation
);
152 WidgetTouchEvent
MultiTouchInput::ToWidgetEvent(nsIWidget
* aWidget
,
153 uint16_t aInputSource
) const {
154 MOZ_ASSERT(NS_IsMainThread(),
155 "Can only convert To WidgetTouchEvent on main thread");
156 MOZ_ASSERT(aInputSource
==
157 mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
||
158 aInputSource
== mozilla::dom::MouseEvent_Binding::MOZ_SOURCE_PEN
);
160 EventMessage touchEventMessage
= eVoidEvent
;
162 case MULTITOUCH_START
:
163 touchEventMessage
= eTouchStart
;
165 case MULTITOUCH_MOVE
:
166 touchEventMessage
= eTouchMove
;
169 touchEventMessage
= eTouchEnd
;
171 case MULTITOUCH_CANCEL
:
172 touchEventMessage
= eTouchCancel
;
175 MOZ_ASSERT_UNREACHABLE(
176 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
180 WidgetTouchEvent
event(true, touchEventMessage
, aWidget
);
181 if (touchEventMessage
== eVoidEvent
) {
185 event
.mModifiers
= this->modifiers
;
186 event
.mTimeStamp
= this->mTimeStamp
;
187 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
188 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
189 event
.mLayersId
= mLayersId
;
190 event
.mInputSource
= aInputSource
;
191 event
.mButton
= mButton
;
192 event
.mButtons
= mButtons
;
194 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
195 *event
.mTouches
.AppendElement() = mTouches
[i
].ToNewDOMTouch();
201 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier
) {
202 for (size_t i
= 0; i
< mTouches
.Length(); i
++) {
203 if (mTouches
[i
].mIdentifier
== aTouchIdentifier
) {
210 bool MultiTouchInput::TransformToLocal(
211 const ScreenToParentLayerMatrix4x4
& aTransform
) {
212 for (auto& touchData
: mTouches
) {
213 for (auto& historicalData
: touchData
.mHistoricalData
) {
214 Maybe
<ParentLayerIntPoint
> historicalPoint
=
215 UntransformBy(aTransform
, historicalData
.mScreenPoint
);
216 if (!historicalPoint
) {
219 historicalData
.mLocalScreenPoint
= *historicalPoint
;
221 Maybe
<ParentLayerIntPoint
> point
=
222 UntransformBy(aTransform
, touchData
.mScreenPoint
);
226 touchData
.mLocalScreenPoint
= *point
;
231 MouseInput::MouseInput()
232 : InputData(MOUSE_INPUT
),
237 mHandledByAPZ(false),
238 mPreventClickEvent(false) {}
240 MouseInput::MouseInput(MouseType aType
, ButtonType aButtonType
,
241 uint16_t aInputSource
, int16_t aButtons
,
242 const ScreenPoint
& aPoint
, TimeStamp aTimeStamp
,
243 Modifiers aModifiers
)
244 : InputData(MOUSE_INPUT
, aTimeStamp
, aModifiers
),
246 mButtonType(aButtonType
),
247 mInputSource(aInputSource
),
250 mHandledByAPZ(false),
251 mPreventClickEvent(false) {}
253 MouseInput::MouseInput(const WidgetMouseEventBase
& aMouseEvent
)
254 : InputData(MOUSE_INPUT
, aMouseEvent
.mTimeStamp
, aMouseEvent
.mModifiers
),
257 mInputSource(aMouseEvent
.mInputSource
),
258 mButtons(aMouseEvent
.mButtons
),
259 mHandledByAPZ(aMouseEvent
.mFlags
.mHandledByAPZ
),
260 mPreventClickEvent(aMouseEvent
.mClass
== eMouseEventClass
&&
261 aMouseEvent
.AsMouseEvent()->mClickEventPrevented
) {
262 MOZ_ASSERT(NS_IsMainThread(),
263 "Can only copy from WidgetTouchEvent on main thread");
267 switch (aMouseEvent
.mButton
) {
268 case MouseButton::ePrimary
:
269 mButtonType
= MouseInput::PRIMARY_BUTTON
;
271 case MouseButton::eMiddle
:
272 mButtonType
= MouseInput::MIDDLE_BUTTON
;
274 case MouseButton::eSecondary
:
275 mButtonType
= MouseInput::SECONDARY_BUTTON
;
279 switch (aMouseEvent
.mMessage
) {
290 mType
= MOUSE_DRAG_START
;
293 mType
= MOUSE_DRAG_END
;
295 case eMouseEnterIntoWidget
:
296 mType
= MOUSE_WIDGET_ENTER
;
298 case eMouseExitFromWidget
:
299 mType
= MOUSE_WIDGET_EXIT
;
301 case eMouseExploreByTouch
:
302 mType
= MOUSE_EXPLORE_BY_TOUCH
;
305 mType
= MOUSE_HITTEST
;
308 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
312 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
313 aMouseEvent
.mRefPoint
,
314 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
317 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
319 bool MouseInput::TransformToLocal(
320 const ScreenToParentLayerMatrix4x4
& aTransform
) {
321 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
325 mLocalOrigin
= *point
;
330 WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
331 MOZ_ASSERT(NS_IsMainThread(),
332 "Can only convert To WidgetTouchEvent on main thread");
334 EventMessage msg
= eVoidEvent
;
335 uint32_t clickCount
= 0;
336 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
349 case MOUSE_DRAG_START
:
355 case MOUSE_WIDGET_ENTER
:
356 msg
= eMouseEnterIntoWidget
;
358 case MOUSE_WIDGET_EXIT
:
359 msg
= eMouseExitFromWidget
;
360 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
362 case MOUSE_EXPLORE_BY_TOUCH
:
363 msg
= eMouseExploreByTouch
;
369 MOZ_ASSERT_UNREACHABLE(
370 "Did not assign a type to WidgetMouseEvent in MouseInput");
374 WidgetMouseEvent
event(true, msg
, aWidget
, WidgetMouseEvent::eReal
,
375 WidgetMouseEvent::eNormal
);
377 if (msg
== eVoidEvent
) {
381 switch (mButtonType
) {
382 case MouseInput::PRIMARY_BUTTON
:
383 event
.mButton
= MouseButton::ePrimary
;
385 case MouseInput::MIDDLE_BUTTON
:
386 event
.mButton
= MouseButton::eMiddle
;
388 case MouseInput::SECONDARY_BUTTON
:
389 event
.mButton
= MouseButton::eSecondary
;
391 case MouseInput::NONE
:
396 event
.mButtons
= mButtons
;
397 event
.mModifiers
= modifiers
;
398 event
.mTimeStamp
= mTimeStamp
;
399 event
.mLayersId
= mLayersId
;
400 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
401 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
403 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
404 event
.mClickCount
= clickCount
;
405 event
.mInputSource
= mInputSource
;
406 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
407 event
.mExitFrom
= exitFrom
;
408 event
.mClickEventPrevented
= mPreventClickEvent
;
413 PanGestureInput::PanGestureInput()
414 : InputData(PANGESTURE_INPUT
),
415 mType(PANGESTURE_MAYSTART
),
416 mLineOrPageDeltaX(0),
417 mLineOrPageDeltaY(0),
418 mUserDeltaMultiplierX(1.0),
419 mUserDeltaMultiplierY(1.0),
420 mHandledByAPZ(false),
421 mOverscrollBehaviorAllowsSwipe(false),
422 mSimulateMomentum(false),
423 mIsNoLineOrPageDelta(true),
424 mMayTriggerSwipe(false) {}
426 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
427 const ScreenPoint
& aPanStartPoint
,
428 const ScreenPoint
& aPanDisplacement
,
429 Modifiers aModifiers
)
430 : InputData(PANGESTURE_INPUT
, aTimeStamp
, aModifiers
),
432 mPanStartPoint(aPanStartPoint
),
433 mPanDisplacement(aPanDisplacement
),
434 mLineOrPageDeltaX(0),
435 mLineOrPageDeltaY(0),
436 mUserDeltaMultiplierX(1.0),
437 mUserDeltaMultiplierY(1.0),
438 mHandledByAPZ(false),
439 mOverscrollBehaviorAllowsSwipe(false),
440 mSimulateMomentum(false),
441 mIsNoLineOrPageDelta(true) {
442 mMayTriggerSwipe
= SwipeTracker::CanTriggerSwipe(*this);
445 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
446 const ScreenPoint
& aPanStartPoint
,
447 const ScreenPoint
& aPanDisplacement
,
448 Modifiers aModifiers
,
449 IsEligibleForSwipe aIsEligibleForSwipe
)
450 : PanGestureInput(aType
, aTimeStamp
, aPanStartPoint
, aPanDisplacement
,
452 mMayTriggerSwipe
&= bool(aIsEligibleForSwipe
);
455 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
456 int32_t aLineOrPageDeltaY
) {
457 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
458 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
459 mIsNoLineOrPageDelta
= false;
462 bool PanGestureInput::IsMomentum() const {
464 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
465 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
466 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
473 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
474 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
475 wheelEvent
.mModifiers
= this->modifiers
;
476 wheelEvent
.mTimeStamp
= mTimeStamp
;
477 wheelEvent
.mLayersId
= mLayersId
;
478 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
480 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
481 wheelEvent
.mButtons
= 0;
482 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
483 wheelEvent
.mIsMomentum
= IsMomentum();
484 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
485 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
486 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
487 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
488 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
489 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
490 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
491 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
492 // widget/gtk is currently the only consumer that uses delta type
494 // Emulate legacy widget/gtk behavior
495 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
496 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
497 wheelEvent
.mDeltaX
*= 3;
498 wheelEvent
.mDeltaY
*= 3;
500 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
505 bool PanGestureInput::TransformToLocal(
506 const ScreenToParentLayerMatrix4x4
& aTransform
) {
507 Maybe
<ParentLayerPoint
> panStartPoint
=
508 UntransformBy(aTransform
, mPanStartPoint
);
509 if (!panStartPoint
) {
512 mLocalPanStartPoint
= *panStartPoint
;
514 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
515 // Skip transforming the pan displacement because we want
516 // raw page proportion counts.
517 mLocalPanDisplacement
= ViewAs
<ParentLayerPixel
>(
518 mPanDisplacement
, PixelCastJustification::DeltaIsPageProportion
);
522 Maybe
<ParentLayerPoint
> panDisplacement
=
523 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
524 if (!panDisplacement
) {
527 mLocalPanDisplacement
= *panDisplacement
;
531 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
532 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
533 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
536 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
537 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
538 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
541 static int32_t TakeLargestInt(gfx::Coord
* aCoord
) {
542 int32_t result(aCoord
->value
); // truncate towards zero
543 aCoord
->value
-= result
;
547 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
548 bool aIsStart
, float x
, float y
) {
549 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
551 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
555 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
556 TakeLargestInt(&sAccumulator
.y
));
559 PinchGestureInput::PinchGestureInput()
560 : InputData(PINCHGESTURE_INPUT
),
561 mType(PINCHGESTURE_START
),
563 mHandledByAPZ(false) {}
565 PinchGestureInput::PinchGestureInput(
566 PinchGestureType aType
, PinchGestureSource aSource
, TimeStamp aTimeStamp
,
567 const ExternalPoint
& aScreenOffset
, const ScreenPoint
& aFocusPoint
,
568 ScreenCoord aCurrentSpan
, ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
569 : InputData(PINCHGESTURE_INPUT
, aTimeStamp
, aModifiers
),
572 mFocusPoint(aFocusPoint
),
573 mScreenOffset(aScreenOffset
),
574 mCurrentSpan(aCurrentSpan
),
575 mPreviousSpan(aPreviousSpan
),
576 mLineOrPageDeltaY(0),
577 mHandledByAPZ(false) {}
579 bool PinchGestureInput::TransformToLocal(
580 const ScreenToParentLayerMatrix4x4
& aTransform
) {
581 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
585 mLocalFocusPoint
= *point
;
589 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
590 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
591 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
592 wheelEvent
.mTimeStamp
= mTimeStamp
;
593 wheelEvent
.mLayersId
= mLayersId
;
594 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
596 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
597 wheelEvent
.mButtons
= 0;
598 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
599 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
601 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
603 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
605 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
610 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
611 #if defined(OS_MACOSX)
612 // This converts the pinch gesture value to a fake wheel event that has the
613 // control key pressed so that pages can implement custom pinch gesture
614 // handling. It may seem strange that this doesn't use a wheel event with
615 // the deltaZ property set, but this matches Chrome's behavior as described
616 // at https://code.google.com/p/chromium/issues/detail?id=289887
618 // The intent of the formula below is to produce numbers similar to Chrome's
619 // implementation of this feature. Chrome implements deltaY using the formula
620 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
621 // All deltas for a single pinch gesture should sum to 0 if the start and end
622 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
623 // because they followed Apple's misleading documentation, which implies that
624 // "1 + [event magnification]" is the scale factor. The scale factor is
625 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
626 // already in log space.
628 // The multiplication by the backing scale factor below counteracts the
629 // division by the backing scale factor in WheelEvent.
631 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
632 // is [event magnification] but [event magnification] is only available in the
633 // macOS widget code so we have to reverse engineer from mCurrentSpan and
634 // mPreviousSpan (which are derived from [event magnification]) to get it.
635 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
636 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
637 // for M in terms of mPreviousSpan and plugging that into to the formula for
639 return (mPreviousSpan
- 100.0) *
640 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
642 // This calculation is based on what the Windows and Linux widget code does.
643 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
644 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
645 // is the scale from the current OS event and lastScale is the scale when the
646 // previous OS event happened. On macOS [event magnification] is a relative
647 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
648 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
649 // calculate the relative scale change on Windows we would calculate |M =
650 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
651 // same formula as the macOS code
652 // (|-100.0 * M * GetDefaultScaleInternal()|).
654 return (mPreviousSpan
- mCurrentSpan
) *
655 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
659 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
660 double deltaY
= ComputeDeltaY(aWidget
);
661 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
664 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
665 (mType
== PINCHGESTURE_START
), 0, deltaY
);
666 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
667 if (mLineOrPageDeltaY
== 0) {
668 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
669 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
670 if (mType
== PINCHGESTURE_SCALE
) {
673 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
674 // defer the START event until we accumulate enough delta).
675 // The Linux widget code doesn't support this, so instead set the event's
676 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
678 if (mType
== PINCHGESTURE_START
) {
682 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
685 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
691 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
692 bool aIsStart
, float x
, float y
) {
693 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
695 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
699 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
700 TakeLargestInt(&sAccumulator
.y
));
703 TapGestureInput::TapGestureInput()
704 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
706 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
707 const ScreenIntPoint
& aPoint
,
708 Modifiers aModifiers
)
709 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
713 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
714 const ParentLayerPoint
& aLocalPoint
,
715 Modifiers aModifiers
)
716 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
718 mLocalPoint(aLocalPoint
) {}
720 bool TapGestureInput::TransformToLocal(
721 const ScreenToParentLayerMatrix4x4
& aTransform
) {
722 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
726 mLocalPoint
= *point
;
730 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
731 nsIWidget
* aWidget
) const {
732 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
734 event
.mTimeStamp
= mTimeStamp
;
735 event
.mLayersId
= mLayersId
;
736 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
738 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
740 event
.mClickCount
= 1;
741 event
.mModifiers
= modifiers
;
746 ScrollWheelInput::ScrollWheelInput()
747 : InputData(SCROLLWHEEL_INPUT
),
748 mDeltaType(SCROLLDELTA_LINE
),
749 mScrollMode(SCROLLMODE_INSTANT
),
750 mHandledByAPZ(false),
753 mLineOrPageDeltaX(0),
754 mLineOrPageDeltaY(0),
755 mScrollSeriesNumber(0),
756 mUserDeltaMultiplierX(1.0),
757 mUserDeltaMultiplierY(1.0),
758 mMayHaveMomentum(false),
760 mAPZAction(APZWheelAction::Scroll
) {}
762 ScrollWheelInput::ScrollWheelInput(
763 TimeStamp aTimeStamp
, Modifiers aModifiers
, ScrollMode aScrollMode
,
764 ScrollDeltaType aDeltaType
, const ScreenPoint
& aOrigin
, double aDeltaX
,
765 double aDeltaY
, bool aAllowToOverrideSystemScrollSpeed
,
766 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
767 : InputData(SCROLLWHEEL_INPUT
, aTimeStamp
, aModifiers
),
768 mDeltaType(aDeltaType
),
769 mScrollMode(aScrollMode
),
771 mHandledByAPZ(false),
774 mLineOrPageDeltaX(0),
775 mLineOrPageDeltaY(0),
776 mScrollSeriesNumber(0),
777 mUserDeltaMultiplierX(1.0),
778 mUserDeltaMultiplierY(1.0),
779 mMayHaveMomentum(false),
781 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
782 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
783 mAPZAction(APZWheelAction::Scroll
) {}
785 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
786 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTimeStamp
,
787 aWheelEvent
.mModifiers
),
788 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
789 mScrollMode(SCROLLMODE_INSTANT
),
790 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
791 mDeltaX(aWheelEvent
.mDeltaX
),
792 mDeltaY(aWheelEvent
.mDeltaY
),
793 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
794 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
795 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
796 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
797 mScrollSeriesNumber(0),
798 mUserDeltaMultiplierX(1.0),
799 mUserDeltaMultiplierY(1.0),
800 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
801 mIsMomentum(aWheelEvent
.mIsMomentum
),
802 mAllowToOverrideSystemScrollSpeed(
803 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
804 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
805 mAPZAction(APZWheelAction::Scroll
) {
806 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
807 aWheelEvent
.mRefPoint
,
808 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
811 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
812 uint32_t aDeltaMode
) {
813 switch (aDeltaMode
) {
814 case WheelEvent_Binding::DOM_DELTA_LINE
:
815 return SCROLLDELTA_LINE
;
816 case WheelEvent_Binding::DOM_DELTA_PAGE
:
817 return SCROLLDELTA_PAGE
;
818 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
819 return SCROLLDELTA_PIXEL
;
823 return SCROLLDELTA_LINE
;
826 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
827 switch (aDeltaType
) {
828 case ScrollWheelInput::SCROLLDELTA_LINE
:
829 return WheelEvent_Binding::DOM_DELTA_LINE
;
830 case ScrollWheelInput::SCROLLDELTA_PAGE
:
831 return WheelEvent_Binding::DOM_DELTA_PAGE
;
832 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
834 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
838 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
839 ScrollDeltaType aDeltaType
) {
840 switch (aDeltaType
) {
841 case SCROLLDELTA_LINE
:
842 return ScrollUnit::LINES
;
843 case SCROLLDELTA_PAGE
:
844 return ScrollUnit::PAGES
;
845 case SCROLLDELTA_PIXEL
:
846 return ScrollUnit::DEVICE_PIXELS
;
850 return ScrollUnit::LINES
;
853 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
854 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
855 wheelEvent
.mModifiers
= this->modifiers
;
856 wheelEvent
.mTimeStamp
= mTimeStamp
;
857 wheelEvent
.mLayersId
= mLayersId
;
858 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
860 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
861 wheelEvent
.mButtons
= 0;
862 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
863 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
864 wheelEvent
.mIsMomentum
= mIsMomentum
;
865 wheelEvent
.mDeltaX
= mDeltaX
;
866 wheelEvent
.mDeltaY
= mDeltaY
;
867 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
868 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
869 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
870 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
871 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
872 mAllowToOverrideSystemScrollSpeed
;
873 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
874 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
878 bool ScrollWheelInput::TransformToLocal(
879 const ScreenToParentLayerMatrix4x4
& aTransform
) {
880 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
884 mLocalOrigin
= *point
;
888 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
889 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
892 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
893 : InputData(KEYBOARD_INPUT
, aEvent
.mTimeStamp
, aEvent
.mModifiers
),
894 mKeyCode(aEvent
.mKeyCode
),
895 mCharCode(aEvent
.mCharCode
),
896 mHandledByAPZ(false) {
897 switch (aEvent
.mMessage
) {
899 mType
= KeyboardInput::KEY_PRESS
;
903 mType
= KeyboardInput::KEY_UP
;
907 mType
= KeyboardInput::KEY_DOWN
;
911 mType
= KeyboardInput::KEY_OTHER
;
915 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
918 KeyboardInput::KeyboardInput()
919 : InputData(KEYBOARD_INPUT
),
923 mHandledByAPZ(false) {}
925 } // namespace mozilla