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 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
311 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
312 aMouseEvent
.mRefPoint
,
313 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
316 bool MouseInput::IsLeftButton() const { return mButtonType
== PRIMARY_BUTTON
; }
318 bool MouseInput::TransformToLocal(
319 const ScreenToParentLayerMatrix4x4
& aTransform
) {
320 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
324 mLocalOrigin
= *point
;
329 WidgetMouseEvent
MouseInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
330 MOZ_ASSERT(NS_IsMainThread(),
331 "Can only convert To WidgetTouchEvent on main thread");
333 EventMessage msg
= eVoidEvent
;
334 uint32_t clickCount
= 0;
335 Maybe
<WidgetMouseEvent::ExitFrom
> exitFrom
;
348 case MOUSE_DRAG_START
:
354 case MOUSE_WIDGET_ENTER
:
355 msg
= eMouseEnterIntoWidget
;
357 case MOUSE_WIDGET_EXIT
:
358 msg
= eMouseExitFromWidget
;
359 exitFrom
= Some(WidgetMouseEvent::ePlatformChild
);
361 case MOUSE_EXPLORE_BY_TOUCH
:
362 msg
= eMouseExploreByTouch
;
368 MOZ_ASSERT_UNREACHABLE(
369 "Did not assign a type to WidgetMouseEvent in MouseInput");
373 WidgetMouseEvent
event(true, msg
, aWidget
, WidgetMouseEvent::eReal
,
374 WidgetMouseEvent::eNormal
);
376 if (msg
== eVoidEvent
) {
380 switch (mButtonType
) {
381 case MouseInput::PRIMARY_BUTTON
:
382 event
.mButton
= MouseButton::ePrimary
;
384 case MouseInput::MIDDLE_BUTTON
:
385 event
.mButton
= MouseButton::eMiddle
;
387 case MouseInput::SECONDARY_BUTTON
:
388 event
.mButton
= MouseButton::eSecondary
;
390 case MouseInput::NONE
:
395 event
.mButtons
= mButtons
;
396 event
.mModifiers
= modifiers
;
397 event
.mTimeStamp
= mTimeStamp
;
398 event
.mLayersId
= mLayersId
;
399 event
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
400 event
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
402 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
403 event
.mClickCount
= clickCount
;
404 event
.mInputSource
= mInputSource
;
405 event
.mFocusSequenceNumber
= mFocusSequenceNumber
;
406 event
.mExitFrom
= exitFrom
;
407 event
.mClickEventPrevented
= mPreventClickEvent
;
412 PanGestureInput::PanGestureInput()
413 : InputData(PANGESTURE_INPUT
),
414 mType(PANGESTURE_MAYSTART
),
415 mLineOrPageDeltaX(0),
416 mLineOrPageDeltaY(0),
417 mUserDeltaMultiplierX(1.0),
418 mUserDeltaMultiplierY(1.0),
419 mHandledByAPZ(false),
420 mOverscrollBehaviorAllowsSwipe(false),
421 mSimulateMomentum(false),
422 mIsNoLineOrPageDelta(true),
423 mMayTriggerSwipe(false) {}
425 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
426 const ScreenPoint
& aPanStartPoint
,
427 const ScreenPoint
& aPanDisplacement
,
428 Modifiers aModifiers
)
429 : InputData(PANGESTURE_INPUT
, aTimeStamp
, aModifiers
),
431 mPanStartPoint(aPanStartPoint
),
432 mPanDisplacement(aPanDisplacement
),
433 mLineOrPageDeltaX(0),
434 mLineOrPageDeltaY(0),
435 mUserDeltaMultiplierX(1.0),
436 mUserDeltaMultiplierY(1.0),
437 mHandledByAPZ(false),
438 mOverscrollBehaviorAllowsSwipe(false),
439 mSimulateMomentum(false),
440 mIsNoLineOrPageDelta(true) {
441 mMayTriggerSwipe
= SwipeTracker::CanTriggerSwipe(*this);
444 PanGestureInput::PanGestureInput(PanGestureType aType
, TimeStamp aTimeStamp
,
445 const ScreenPoint
& aPanStartPoint
,
446 const ScreenPoint
& aPanDisplacement
,
447 Modifiers aModifiers
,
448 IsEligibleForSwipe aIsEligibleForSwipe
)
449 : PanGestureInput(aType
, aTimeStamp
, aPanStartPoint
, aPanDisplacement
,
451 mMayTriggerSwipe
&= bool(aIsEligibleForSwipe
);
454 void PanGestureInput::SetLineOrPageDeltas(int32_t aLineOrPageDeltaX
,
455 int32_t aLineOrPageDeltaY
) {
456 mLineOrPageDeltaX
= aLineOrPageDeltaX
;
457 mLineOrPageDeltaY
= aLineOrPageDeltaY
;
458 mIsNoLineOrPageDelta
= false;
461 bool PanGestureInput::IsMomentum() const {
463 case PanGestureInput::PANGESTURE_MOMENTUMSTART
:
464 case PanGestureInput::PANGESTURE_MOMENTUMPAN
:
465 case PanGestureInput::PANGESTURE_MOMENTUMEND
:
472 WidgetWheelEvent
PanGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
473 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
474 wheelEvent
.mModifiers
= this->modifiers
;
475 wheelEvent
.mTimeStamp
= mTimeStamp
;
476 wheelEvent
.mLayersId
= mLayersId
;
477 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
479 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
480 wheelEvent
.mButtons
= 0;
481 wheelEvent
.mMayHaveMomentum
= true; // pan inputs may have momentum
482 wheelEvent
.mIsMomentum
= IsMomentum();
483 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
484 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
485 wheelEvent
.mDeltaX
= mPanDisplacement
.x
;
486 wheelEvent
.mDeltaY
= mPanDisplacement
.y
;
487 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
488 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
489 wheelEvent
.mIsNoLineOrPageDelta
= mIsNoLineOrPageDelta
;
490 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
491 // widget/gtk is currently the only consumer that uses delta type
493 // Emulate legacy widget/gtk behavior
494 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_LINE
;
495 wheelEvent
.mScrollType
= WidgetWheelEvent::SCROLL_ASYNCHRONOUSLY
;
496 wheelEvent
.mDeltaX
*= 3;
497 wheelEvent
.mDeltaY
*= 3;
499 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
504 bool PanGestureInput::TransformToLocal(
505 const ScreenToParentLayerMatrix4x4
& aTransform
) {
506 Maybe
<ParentLayerPoint
> panStartPoint
=
507 UntransformBy(aTransform
, mPanStartPoint
);
508 if (!panStartPoint
) {
511 mLocalPanStartPoint
= *panStartPoint
;
513 if (mDeltaType
== PanGestureInput::PANDELTA_PAGE
) {
514 // Skip transforming the pan displacement because we want
515 // raw page proportion counts.
516 mLocalPanDisplacement
= ViewAs
<ParentLayerPixel
>(
517 mPanDisplacement
, PixelCastJustification::DeltaIsPageProportion
);
521 Maybe
<ParentLayerPoint
> panDisplacement
=
522 UntransformVector(aTransform
, mPanDisplacement
, mPanStartPoint
);
523 if (!panDisplacement
) {
526 mLocalPanDisplacement
= *panDisplacement
;
530 ScreenPoint
PanGestureInput::UserMultipliedPanDisplacement() const {
531 return ScreenPoint(mPanDisplacement
.x
* mUserDeltaMultiplierX
,
532 mPanDisplacement
.y
* mUserDeltaMultiplierY
);
535 ParentLayerPoint
PanGestureInput::UserMultipliedLocalPanDisplacement() const {
536 return ParentLayerPoint(mLocalPanDisplacement
.x
* mUserDeltaMultiplierX
,
537 mLocalPanDisplacement
.y
* mUserDeltaMultiplierY
);
540 static int32_t TakeLargestInt(gfx::Coord
* aCoord
) {
541 int32_t result(aCoord
->value
); // truncate towards zero
542 aCoord
->value
-= result
;
546 /* static */ gfx::IntPoint
PanGestureInput::GetIntegerDeltaForEvent(
547 bool aIsStart
, float x
, float y
) {
548 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
550 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
554 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
555 TakeLargestInt(&sAccumulator
.y
));
558 PinchGestureInput::PinchGestureInput()
559 : InputData(PINCHGESTURE_INPUT
),
560 mType(PINCHGESTURE_START
),
562 mHandledByAPZ(false) {}
564 PinchGestureInput::PinchGestureInput(
565 PinchGestureType aType
, PinchGestureSource aSource
, TimeStamp aTimeStamp
,
566 const ExternalPoint
& aScreenOffset
, const ScreenPoint
& aFocusPoint
,
567 ScreenCoord aCurrentSpan
, ScreenCoord aPreviousSpan
, Modifiers aModifiers
)
568 : InputData(PINCHGESTURE_INPUT
, aTimeStamp
, aModifiers
),
571 mFocusPoint(aFocusPoint
),
572 mScreenOffset(aScreenOffset
),
573 mCurrentSpan(aCurrentSpan
),
574 mPreviousSpan(aPreviousSpan
),
575 mLineOrPageDeltaY(0),
576 mHandledByAPZ(false) {}
578 bool PinchGestureInput::TransformToLocal(
579 const ScreenToParentLayerMatrix4x4
& aTransform
) {
580 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mFocusPoint
);
584 mLocalFocusPoint
= *point
;
588 WidgetWheelEvent
PinchGestureInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
589 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
590 wheelEvent
.mModifiers
= this->modifiers
| MODIFIER_CONTROL
;
591 wheelEvent
.mTimeStamp
= mTimeStamp
;
592 wheelEvent
.mLayersId
= mLayersId
;
593 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
595 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
596 wheelEvent
.mButtons
= 0;
597 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
598 wheelEvent
.mDeltaMode
= WheelEvent_Binding::DOM_DELTA_PIXEL
;
600 wheelEvent
.mDeltaY
= ComputeDeltaY(aWidget
);
602 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
604 MOZ_ASSERT(mType
== PINCHGESTURE_END
|| wheelEvent
.mDeltaY
!= 0.0);
609 double PinchGestureInput::ComputeDeltaY(nsIWidget
* aWidget
) const {
610 #if defined(XP_DARWIN)
611 // This converts the pinch gesture value to a fake wheel event that has the
612 // control key pressed so that pages can implement custom pinch gesture
613 // handling. It may seem strange that this doesn't use a wheel event with
614 // the deltaZ property set, but this matches Chrome's behavior as described
615 // at https://code.google.com/p/chromium/issues/detail?id=289887
617 // The intent of the formula below is to produce numbers similar to Chrome's
618 // implementation of this feature. Chrome implements deltaY using the formula
619 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
620 // All deltas for a single pinch gesture should sum to 0 if the start and end
621 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
622 // because they followed Apple's misleading documentation, which implies that
623 // "1 + [event magnification]" is the scale factor. The scale factor is
624 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
625 // already in log space.
627 // The multiplication by the backing scale factor below counteracts the
628 // division by the backing scale factor in WheelEvent.
630 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
631 // is [event magnification] but [event magnification] is only available in the
632 // macOS widget code so we have to reverse engineer from mCurrentSpan and
633 // mPreviousSpan (which are derived from [event magnification]) to get it.
634 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
635 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
636 // for M in terms of mPreviousSpan and plugging that into to the formula for
638 return (mPreviousSpan
- 100.0) *
639 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
641 // This calculation is based on what the Windows and Linux widget code does.
642 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
643 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
644 // is the scale from the current OS event and lastScale is the scale when the
645 // previous OS event happened. On macOS [event magnification] is a relative
646 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
647 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
648 // calculate the relative scale change on Windows we would calculate |M =
649 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
650 // same formula as the macOS code
651 // (|-100.0 * M * GetDefaultScaleInternal()|).
653 return (mPreviousSpan
- mCurrentSpan
) *
654 (aWidget
? aWidget
->GetDefaultScaleInternal() : 1.f
);
658 bool PinchGestureInput::SetLineOrPageDeltaY(nsIWidget
* aWidget
) {
659 double deltaY
= ComputeDeltaY(aWidget
);
660 if (deltaY
== 0 && mType
!= PINCHGESTURE_END
) {
663 gfx::IntPoint lineOrPageDelta
= PinchGestureInput::GetIntegerDeltaForEvent(
664 (mType
== PINCHGESTURE_START
), 0, deltaY
);
665 mLineOrPageDeltaY
= lineOrPageDelta
.y
;
666 if (mLineOrPageDeltaY
== 0) {
667 // For PINCHGESTURE_SCALE events, don't dispatch them. Note that the delta
668 // isn't lost; it remains in the accumulator in GetIntegerDeltaForEvent().
669 if (mType
== PINCHGESTURE_SCALE
) {
672 // On Windows, drop PINCHGESTURE_START as well (the Windows widget code will
673 // defer the START event until we accumulate enough delta).
674 // The Linux widget code doesn't support this, so instead set the event's
675 // mLineOrPageDeltaY to the smallest nonzero amount in the relevant
677 if (mType
== PINCHGESTURE_START
) {
681 mLineOrPageDeltaY
= (deltaY
>= 0) ? 1 : -1;
684 // For PINCHGESTURE_END events, not dispatching a DOMMouseScroll for them is
690 /* static */ gfx::IntPoint
PinchGestureInput::GetIntegerDeltaForEvent(
691 bool aIsStart
, float x
, float y
) {
692 static gfx::Point
sAccumulator(0.0f
, 0.0f
);
694 sAccumulator
= gfx::Point(0.0f
, 0.0f
);
698 return gfx::IntPoint(TakeLargestInt(&sAccumulator
.x
),
699 TakeLargestInt(&sAccumulator
.y
));
702 TapGestureInput::TapGestureInput()
703 : InputData(TAPGESTURE_INPUT
), mType(TAPGESTURE_LONG
) {}
705 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
706 const ScreenIntPoint
& aPoint
,
707 Modifiers aModifiers
)
708 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
712 TapGestureInput::TapGestureInput(TapGestureType aType
, TimeStamp aTimeStamp
,
713 const ParentLayerPoint
& aLocalPoint
,
714 Modifiers aModifiers
)
715 : InputData(TAPGESTURE_INPUT
, aTimeStamp
, aModifiers
),
717 mLocalPoint(aLocalPoint
) {}
719 bool TapGestureInput::TransformToLocal(
720 const ScreenToParentLayerMatrix4x4
& aTransform
) {
721 Maybe
<ParentLayerIntPoint
> point
= UntransformBy(aTransform
, mPoint
);
725 mLocalPoint
= *point
;
729 WidgetSimpleGestureEvent
TapGestureInput::ToWidgetEvent(
730 nsIWidget
* aWidget
) const {
731 WidgetSimpleGestureEvent
event(true, eTapGesture
, aWidget
);
733 event
.mTimeStamp
= mTimeStamp
;
734 event
.mLayersId
= mLayersId
;
735 event
.mRefPoint
= ViewAs
<LayoutDevicePixel
>(
737 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
);
739 event
.mClickCount
= 1;
740 event
.mModifiers
= modifiers
;
745 ScrollWheelInput::ScrollWheelInput()
746 : InputData(SCROLLWHEEL_INPUT
),
747 mDeltaType(SCROLLDELTA_LINE
),
748 mScrollMode(SCROLLMODE_INSTANT
),
749 mHandledByAPZ(false),
752 mLineOrPageDeltaX(0),
753 mLineOrPageDeltaY(0),
754 mScrollSeriesNumber(0),
755 mUserDeltaMultiplierX(1.0),
756 mUserDeltaMultiplierY(1.0),
757 mMayHaveMomentum(false),
759 mAPZAction(APZWheelAction::Scroll
) {}
761 ScrollWheelInput::ScrollWheelInput(
762 TimeStamp aTimeStamp
, Modifiers aModifiers
, ScrollMode aScrollMode
,
763 ScrollDeltaType aDeltaType
, const ScreenPoint
& aOrigin
, double aDeltaX
,
764 double aDeltaY
, bool aAllowToOverrideSystemScrollSpeed
,
765 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy
)
766 : InputData(SCROLLWHEEL_INPUT
, aTimeStamp
, aModifiers
),
767 mDeltaType(aDeltaType
),
768 mScrollMode(aScrollMode
),
770 mHandledByAPZ(false),
773 mLineOrPageDeltaX(0),
774 mLineOrPageDeltaY(0),
775 mScrollSeriesNumber(0),
776 mUserDeltaMultiplierX(1.0),
777 mUserDeltaMultiplierY(1.0),
778 mMayHaveMomentum(false),
780 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed
),
781 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy
),
782 mAPZAction(APZWheelAction::Scroll
) {}
784 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent
& aWheelEvent
)
785 : InputData(SCROLLWHEEL_INPUT
, aWheelEvent
.mTimeStamp
,
786 aWheelEvent
.mModifiers
),
787 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent
.mDeltaMode
)),
788 mScrollMode(SCROLLMODE_INSTANT
),
789 mHandledByAPZ(aWheelEvent
.mFlags
.mHandledByAPZ
),
790 mDeltaX(aWheelEvent
.mDeltaX
),
791 mDeltaY(aWheelEvent
.mDeltaY
),
792 mWheelTicksX(aWheelEvent
.mWheelTicksX
),
793 mWheelTicksY(aWheelEvent
.mWheelTicksX
),
794 mLineOrPageDeltaX(aWheelEvent
.mLineOrPageDeltaX
),
795 mLineOrPageDeltaY(aWheelEvent
.mLineOrPageDeltaY
),
796 mScrollSeriesNumber(0),
797 mUserDeltaMultiplierX(1.0),
798 mUserDeltaMultiplierY(1.0),
799 mMayHaveMomentum(aWheelEvent
.mMayHaveMomentum
),
800 mIsMomentum(aWheelEvent
.mIsMomentum
),
801 mAllowToOverrideSystemScrollSpeed(
802 aWheelEvent
.mAllowToOverrideSystemScrollSpeed
),
803 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone
),
804 mAPZAction(APZWheelAction::Scroll
) {
805 mOrigin
= ScreenPoint(ViewAs
<ScreenPixel
>(
806 aWheelEvent
.mRefPoint
,
807 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
810 ScrollWheelInput::ScrollDeltaType
ScrollWheelInput::DeltaTypeForDeltaMode(
811 uint32_t aDeltaMode
) {
812 switch (aDeltaMode
) {
813 case WheelEvent_Binding::DOM_DELTA_LINE
:
814 return SCROLLDELTA_LINE
;
815 case WheelEvent_Binding::DOM_DELTA_PAGE
:
816 return SCROLLDELTA_PAGE
;
817 case WheelEvent_Binding::DOM_DELTA_PIXEL
:
818 return SCROLLDELTA_PIXEL
;
822 return SCROLLDELTA_LINE
;
825 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType
) {
826 switch (aDeltaType
) {
827 case ScrollWheelInput::SCROLLDELTA_LINE
:
828 return WheelEvent_Binding::DOM_DELTA_LINE
;
829 case ScrollWheelInput::SCROLLDELTA_PAGE
:
830 return WheelEvent_Binding::DOM_DELTA_PAGE
;
831 case ScrollWheelInput::SCROLLDELTA_PIXEL
:
833 return WheelEvent_Binding::DOM_DELTA_PIXEL
;
837 ScrollUnit
ScrollWheelInput::ScrollUnitForDeltaType(
838 ScrollDeltaType aDeltaType
) {
839 switch (aDeltaType
) {
840 case SCROLLDELTA_LINE
:
841 return ScrollUnit::LINES
;
842 case SCROLLDELTA_PAGE
:
843 return ScrollUnit::PAGES
;
844 case SCROLLDELTA_PIXEL
:
845 return ScrollUnit::DEVICE_PIXELS
;
849 return ScrollUnit::LINES
;
852 WidgetWheelEvent
ScrollWheelInput::ToWidgetEvent(nsIWidget
* aWidget
) const {
853 WidgetWheelEvent
wheelEvent(true, eWheel
, aWidget
);
854 wheelEvent
.mModifiers
= this->modifiers
;
855 wheelEvent
.mTimeStamp
= mTimeStamp
;
856 wheelEvent
.mLayersId
= mLayersId
;
857 wheelEvent
.mRefPoint
= RoundedToInt(ViewAs
<LayoutDevicePixel
>(
859 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent
));
860 wheelEvent
.mButtons
= 0;
861 wheelEvent
.mDeltaMode
= DeltaModeForDeltaType(mDeltaType
);
862 wheelEvent
.mMayHaveMomentum
= mMayHaveMomentum
;
863 wheelEvent
.mIsMomentum
= mIsMomentum
;
864 wheelEvent
.mDeltaX
= mDeltaX
;
865 wheelEvent
.mDeltaY
= mDeltaY
;
866 wheelEvent
.mWheelTicksX
= mWheelTicksX
;
867 wheelEvent
.mWheelTicksY
= mWheelTicksY
;
868 wheelEvent
.mLineOrPageDeltaX
= mLineOrPageDeltaX
;
869 wheelEvent
.mLineOrPageDeltaY
= mLineOrPageDeltaY
;
870 wheelEvent
.mAllowToOverrideSystemScrollSpeed
=
871 mAllowToOverrideSystemScrollSpeed
;
872 wheelEvent
.mFlags
.mHandledByAPZ
= mHandledByAPZ
;
873 wheelEvent
.mFocusSequenceNumber
= mFocusSequenceNumber
;
877 bool ScrollWheelInput::TransformToLocal(
878 const ScreenToParentLayerMatrix4x4
& aTransform
) {
879 Maybe
<ParentLayerPoint
> point
= UntransformBy(aTransform
, mOrigin
);
883 mLocalOrigin
= *point
;
887 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
888 return mUserDeltaMultiplierX
!= 1.0 || mUserDeltaMultiplierY
!= 1.0;
891 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent
& aEvent
)
892 : InputData(KEYBOARD_INPUT
, aEvent
.mTimeStamp
, aEvent
.mModifiers
),
893 mKeyCode(aEvent
.mKeyCode
),
894 mCharCode(aEvent
.mCharCode
),
895 mHandledByAPZ(false) {
896 switch (aEvent
.mMessage
) {
898 mType
= KeyboardInput::KEY_PRESS
;
902 mType
= KeyboardInput::KEY_UP
;
906 mType
= KeyboardInput::KEY_DOWN
;
910 mType
= KeyboardInput::KEY_OTHER
;
914 aEvent
.GetShortcutKeyCandidates(mShortcutCandidates
);
917 KeyboardInput::KeyboardInput()
918 : InputData(KEYBOARD_INPUT
),
922 mHandledByAPZ(false) {}
924 } // namespace mozilla