Bug 1641886 [wpt PR 23851] - Support interpolating contain-intrinsic-size, a=testonly
[gecko.git] / widget / InputData.cpp
blob0964d3654acdf62b0623b2455b0dc131f3b0e8b6
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/. */
6 #include "InputData.h"
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"
13 #include "nsDebug.h"
14 #include "nsThreadUtils.h"
15 #include "mozilla/MouseEvents.h"
16 #include "mozilla/TouchEvents.h"
17 #include "UnitTransforms.h"
19 namespace mozilla {
21 using namespace dom;
23 InputData::~InputData() = default;
25 InputData::InputData(InputType aInputType)
26 : mInputType(aInputType),
27 mTime(0),
28 mFocusSequenceNumber(0),
29 mLayersId{0},
30 modifiers(0) {}
32 InputData::InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
33 Modifiers aModifiers)
34 : mInputType(aInputType),
35 mTime(aTime),
36 mTimeStamp(aTimeStamp),
37 mFocusSequenceNumber(0),
38 mLayersId{0},
39 modifiers(aModifiers) {}
41 SingleTouchData::SingleTouchData(int32_t aIdentifier,
42 ScreenIntPoint aScreenPoint,
43 ScreenSize aRadius, float aRotationAngle,
44 float aForce)
45 : mIdentifier(aIdentifier),
46 mScreenPoint(aScreenPoint),
47 mRadius(aRadius),
48 mRotationAngle(aRotationAngle),
49 mForce(aForce) {}
51 SingleTouchData::SingleTouchData(int32_t aIdentifier,
52 ParentLayerPoint aLocalScreenPoint,
53 ScreenSize aRadius, float aRotationAngle,
54 float aForce)
55 : mIdentifier(aIdentifier),
56 mLocalScreenPoint(aLocalScreenPoint),
57 mRadius(aRadius),
58 mRotationAngle(aRotationAngle),
59 mForce(aForce) {}
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");
67 RefPtr<Touch> touch =
68 new Touch(mIdentifier,
69 LayoutDeviceIntPoint::Truncate(mScreenPoint.x, mScreenPoint.y),
70 LayoutDeviceIntPoint::Truncate(mRadius.width, mRadius.height),
71 mRotationAngle, mForce);
72 return touch.forget();
75 MultiTouchInput::MultiTouchInput(MultiTouchType aType, uint32_t aTime,
76 TimeStamp aTimeStamp, Modifiers aModifiers)
77 : InputData(MULTITOUCH_INPUT, aTime, aTimeStamp, aModifiers),
78 mType(aType),
79 mHandledByAPZ(false) {}
81 MultiTouchInput::MultiTouchInput()
82 : InputData(MULTITOUCH_INPUT),
83 mType(MULTITOUCH_START),
84 mHandledByAPZ(false) {}
86 MultiTouchInput::MultiTouchInput(const MultiTouchInput& aOther)
87 : InputData(MULTITOUCH_INPUT, aOther.mTime, aOther.mTimeStamp,
88 aOther.modifiers),
89 mType(aOther.mType),
90 mScreenOffset(aOther.mScreenOffset),
91 mHandledByAPZ(aOther.mHandledByAPZ) {
92 mTouches.AppendElements(aOther.mTouches);
95 MultiTouchInput::MultiTouchInput(const WidgetTouchEvent& aTouchEvent)
96 : InputData(MULTITOUCH_INPUT, aTouchEvent.mTime, aTouchEvent.mTimeStamp,
97 aTouchEvent.mModifiers),
98 mHandledByAPZ(aTouchEvent.mFlags.mHandledByAPZ) {
99 MOZ_ASSERT(NS_IsMainThread(),
100 "Can only copy from WidgetTouchEvent on main thread");
102 switch (aTouchEvent.mMessage) {
103 case eTouchStart:
104 mType = MULTITOUCH_START;
105 break;
106 case eTouchMove:
107 mType = MULTITOUCH_MOVE;
108 break;
109 case eTouchEnd:
110 mType = MULTITOUCH_END;
111 break;
112 case eTouchCancel:
113 mType = MULTITOUCH_CANCEL;
114 break;
115 default:
116 MOZ_ASSERT_UNREACHABLE("Did not assign a type to a MultiTouchInput");
117 break;
120 mScreenOffset = ViewAs<ExternalPixel>(
121 aTouchEvent.mWidget->WidgetToScreenOffset(),
122 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
124 for (size_t i = 0; i < aTouchEvent.mTouches.Length(); i++) {
125 const Touch* domTouch = aTouchEvent.mTouches[i];
127 // Extract data from weird interfaces.
128 int32_t identifier = domTouch->Identifier();
129 int32_t radiusX = domTouch->RadiusX(CallerType::System);
130 int32_t radiusY = domTouch->RadiusY(CallerType::System);
131 float rotationAngle = domTouch->RotationAngle(CallerType::System);
132 float force = domTouch->Force(CallerType::System);
134 SingleTouchData data(
135 identifier,
136 ViewAs<ScreenPixel>(
137 domTouch->mRefPoint,
138 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent),
139 ScreenSize(radiusX, radiusY), rotationAngle, force);
141 mTouches.AppendElement(data);
145 void MultiTouchInput::Translate(const ScreenPoint& aTranslation) {
146 const int32_t xTranslation = (int32_t)(aTranslation.x + 0.5f);
147 const int32_t yTranslation = (int32_t)(aTranslation.y + 0.5f);
149 for (auto iter = mTouches.begin(); iter != mTouches.end(); iter++) {
150 iter->mScreenPoint.MoveBy(xTranslation, yTranslation);
154 WidgetTouchEvent MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const {
155 MOZ_ASSERT(NS_IsMainThread(),
156 "Can only convert To WidgetTouchEvent on main thread");
158 EventMessage touchEventMessage = eVoidEvent;
159 switch (mType) {
160 case MULTITOUCH_START:
161 touchEventMessage = eTouchStart;
162 break;
163 case MULTITOUCH_MOVE:
164 touchEventMessage = eTouchMove;
165 break;
166 case MULTITOUCH_END:
167 touchEventMessage = eTouchEnd;
168 break;
169 case MULTITOUCH_CANCEL:
170 touchEventMessage = eTouchCancel;
171 break;
172 default:
173 MOZ_ASSERT_UNREACHABLE(
174 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
175 break;
178 WidgetTouchEvent event(true, touchEventMessage, aWidget);
179 if (touchEventMessage == eVoidEvent) {
180 return event;
183 event.mModifiers = this->modifiers;
184 event.mTime = this->mTime;
185 event.mTimeStamp = this->mTimeStamp;
186 event.mFlags.mHandledByAPZ = mHandledByAPZ;
187 event.mFocusSequenceNumber = mFocusSequenceNumber;
189 for (size_t i = 0; i < mTouches.Length(); i++) {
190 *event.mTouches.AppendElement() = mTouches[i].ToNewDOMTouch();
193 return event;
196 WidgetMouseEvent MultiTouchInput::ToWidgetMouseEvent(nsIWidget* aWidget) const {
197 MOZ_ASSERT(NS_IsMainThread(),
198 "Can only convert To WidgetMouseEvent on main thread");
200 EventMessage mouseEventMessage = eVoidEvent;
201 switch (mType) {
202 case MultiTouchInput::MULTITOUCH_START:
203 mouseEventMessage = eMouseDown;
204 break;
205 case MultiTouchInput::MULTITOUCH_MOVE:
206 mouseEventMessage = eMouseMove;
207 break;
208 case MultiTouchInput::MULTITOUCH_CANCEL:
209 case MultiTouchInput::MULTITOUCH_END:
210 mouseEventMessage = eMouseUp;
211 break;
212 default:
213 MOZ_ASSERT_UNREACHABLE("Did not assign a type to WidgetMouseEvent");
214 break;
217 WidgetMouseEvent event(true, mouseEventMessage, aWidget,
218 WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
220 const SingleTouchData& firstTouch = mTouches[0];
221 event.mRefPoint.x = firstTouch.mScreenPoint.x;
222 event.mRefPoint.y = firstTouch.mScreenPoint.y;
224 event.mTime = mTime;
225 event.mButton = MouseButton::eLeft;
226 event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_TOUCH;
227 event.mModifiers = modifiers;
228 event.mFlags.mHandledByAPZ = mHandledByAPZ;
229 event.mFocusSequenceNumber = mFocusSequenceNumber;
231 if (mouseEventMessage != eMouseMove) {
232 event.mClickCount = 1;
235 return event;
238 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier) {
239 for (size_t i = 0; i < mTouches.Length(); i++) {
240 if (mTouches[i].mIdentifier == aTouchIdentifier) {
241 return (int32_t)i;
244 return -1;
247 bool MultiTouchInput::TransformToLocal(
248 const ScreenToParentLayerMatrix4x4& aTransform) {
249 for (size_t i = 0; i < mTouches.Length(); i++) {
250 Maybe<ParentLayerIntPoint> point =
251 UntransformBy(aTransform, mTouches[i].mScreenPoint);
252 if (!point) {
253 return false;
255 mTouches[i].mLocalScreenPoint = *point;
257 return true;
260 MouseInput::MouseInput()
261 : InputData(MOUSE_INPUT),
262 mType(MOUSE_NONE),
263 mButtonType(NONE),
264 mInputSource(0),
265 mButtons(0),
266 mHandledByAPZ(false) {}
268 MouseInput::MouseInput(MouseType aType, ButtonType aButtonType,
269 uint16_t aInputSource, int16_t aButtons,
270 const ScreenPoint& aPoint, uint32_t aTime,
271 TimeStamp aTimeStamp, Modifiers aModifiers)
272 : InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers),
273 mType(aType),
274 mButtonType(aButtonType),
275 mInputSource(aInputSource),
276 mButtons(aButtons),
277 mOrigin(aPoint),
278 mHandledByAPZ(false) {}
280 MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
281 : InputData(MOUSE_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
282 aMouseEvent.mModifiers),
283 mType(MOUSE_NONE),
284 mButtonType(NONE),
285 mInputSource(aMouseEvent.mInputSource),
286 mButtons(aMouseEvent.mButtons),
287 mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ) {
288 MOZ_ASSERT(NS_IsMainThread(),
289 "Can only copy from WidgetTouchEvent on main thread");
291 mButtonType = NONE;
293 switch (aMouseEvent.mButton) {
294 case MouseButton::eLeft:
295 mButtonType = MouseInput::LEFT_BUTTON;
296 break;
297 case MouseButton::eMiddle:
298 mButtonType = MouseInput::MIDDLE_BUTTON;
299 break;
300 case MouseButton::eRight:
301 mButtonType = MouseInput::RIGHT_BUTTON;
302 break;
305 switch (aMouseEvent.mMessage) {
306 case eMouseMove:
307 mType = MOUSE_MOVE;
308 break;
309 case eMouseUp:
310 mType = MOUSE_UP;
311 break;
312 case eMouseDown:
313 mType = MOUSE_DOWN;
314 break;
315 case eDragStart:
316 mType = MOUSE_DRAG_START;
317 break;
318 case eDragEnd:
319 mType = MOUSE_DRAG_END;
320 break;
321 case eMouseEnterIntoWidget:
322 mType = MOUSE_WIDGET_ENTER;
323 break;
324 case eMouseExitFromWidget:
325 mType = MOUSE_WIDGET_EXIT;
326 break;
327 case eMouseHitTest:
328 mType = MOUSE_HITTEST;
329 break;
330 default:
331 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
332 break;
335 mOrigin = ScreenPoint(ViewAs<ScreenPixel>(
336 aMouseEvent.mRefPoint,
337 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
340 bool MouseInput::IsLeftButton() const { return mButtonType == LEFT_BUTTON; }
342 bool MouseInput::TransformToLocal(
343 const ScreenToParentLayerMatrix4x4& aTransform) {
344 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
345 if (!point) {
346 return false;
348 mLocalOrigin = *point;
350 return true;
353 WidgetMouseEvent MouseInput::ToWidgetMouseEvent(nsIWidget* aWidget) const {
354 MOZ_ASSERT(NS_IsMainThread(),
355 "Can only convert To WidgetTouchEvent on main thread");
357 EventMessage msg = eVoidEvent;
358 uint32_t clickCount = 0;
359 switch (mType) {
360 case MOUSE_MOVE:
361 msg = eMouseMove;
362 break;
363 case MOUSE_UP:
364 msg = eMouseUp;
365 clickCount = 1;
366 break;
367 case MOUSE_DOWN:
368 msg = eMouseDown;
369 clickCount = 1;
370 break;
371 case MOUSE_DRAG_START:
372 msg = eDragStart;
373 break;
374 case MOUSE_DRAG_END:
375 msg = eDragEnd;
376 break;
377 case MOUSE_WIDGET_ENTER:
378 msg = eMouseEnterIntoWidget;
379 break;
380 case MOUSE_WIDGET_EXIT:
381 msg = eMouseExitFromWidget;
382 break;
383 case MOUSE_HITTEST:
384 msg = eMouseHitTest;
385 break;
386 default:
387 MOZ_ASSERT_UNREACHABLE(
388 "Did not assign a type to WidgetMouseEvent in MouseInput");
389 break;
392 WidgetMouseEvent event(true, msg, aWidget, WidgetMouseEvent::eReal,
393 WidgetMouseEvent::eNormal);
395 if (msg == eVoidEvent) {
396 return event;
399 switch (mButtonType) {
400 case MouseInput::LEFT_BUTTON:
401 event.mButton = MouseButton::eLeft;
402 break;
403 case MouseInput::MIDDLE_BUTTON:
404 event.mButton = MouseButton::eMiddle;
405 break;
406 case MouseInput::RIGHT_BUTTON:
407 event.mButton = MouseButton::eRight;
408 break;
409 case MouseInput::NONE:
410 default:
411 break;
414 event.mButtons = mButtons;
415 event.mModifiers = modifiers;
416 event.mTime = mTime;
417 event.mTimeStamp = mTimeStamp;
418 event.mFlags.mHandledByAPZ = mHandledByAPZ;
419 event.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
420 mOrigin,
421 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
422 event.mClickCount = clickCount;
423 event.mInputSource = mInputSource;
424 event.mFocusSequenceNumber = mFocusSequenceNumber;
426 return event;
429 PanGestureInput::PanGestureInput()
430 : InputData(PANGESTURE_INPUT),
431 mType(PANGESTURE_MAYSTART),
432 mLineOrPageDeltaX(0),
433 mLineOrPageDeltaY(0),
434 mUserDeltaMultiplierX(1.0),
435 mUserDeltaMultiplierY(1.0),
436 mHandledByAPZ(false),
437 mFollowedByMomentum(false),
438 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
439 mOverscrollBehaviorAllowsSwipe(false),
440 mSimulateMomentum(false) {}
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),
448 mType(aType),
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) {}
461 bool PanGestureInput::IsMomentum() const {
462 switch (mType) {
463 case PanGestureInput::PANGESTURE_MOMENTUMSTART:
464 case PanGestureInput::PANGESTURE_MOMENTUMPAN:
465 case PanGestureInput::PANGESTURE_MOMENTUMEND:
466 return true;
467 default:
468 return false;
472 WidgetWheelEvent PanGestureInput::ToWidgetWheelEvent(nsIWidget* aWidget) const {
473 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
474 wheelEvent.mModifiers = this->modifiers;
475 wheelEvent.mTime = mTime;
476 wheelEvent.mTimeStamp = mTimeStamp;
477 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
478 mPanStartPoint,
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 if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
490 // Emulate legacy widget/gtk behavior
491 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_LINE;
492 wheelEvent.mIsNoLineOrPageDelta = true;
493 wheelEvent.mScrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
494 wheelEvent.mDeltaX *= 3;
495 wheelEvent.mDeltaY *= 3;
496 } else {
497 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
499 return wheelEvent;
502 bool PanGestureInput::TransformToLocal(
503 const ScreenToParentLayerMatrix4x4& aTransform) {
504 Maybe<ParentLayerPoint> panStartPoint =
505 UntransformBy(aTransform, mPanStartPoint);
506 if (!panStartPoint) {
507 return false;
509 mLocalPanStartPoint = *panStartPoint;
511 if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
512 // Skip transforming the pan displacement because we want
513 // raw page proportion counts.
514 mLocalPanDisplacement.x = mPanDisplacement.x;
515 mLocalPanDisplacement.y = mPanDisplacement.y;
516 return true;
519 Maybe<ParentLayerPoint> panDisplacement =
520 UntransformVector(aTransform, mPanDisplacement, mPanStartPoint);
521 if (!panDisplacement) {
522 return false;
524 mLocalPanDisplacement = *panDisplacement;
525 return true;
528 ScreenPoint PanGestureInput::UserMultipliedPanDisplacement() const {
529 return ScreenPoint(mPanDisplacement.x * mUserDeltaMultiplierX,
530 mPanDisplacement.y * mUserDeltaMultiplierY);
533 ParentLayerPoint PanGestureInput::UserMultipliedLocalPanDisplacement() const {
534 return ParentLayerPoint(mLocalPanDisplacement.x * mUserDeltaMultiplierX,
535 mLocalPanDisplacement.y * mUserDeltaMultiplierY);
538 PinchGestureInput::PinchGestureInput()
539 : InputData(PINCHGESTURE_INPUT),
540 mType(PINCHGESTURE_START),
541 mHandledByAPZ(false) {}
543 PinchGestureInput::PinchGestureInput(
544 PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp,
545 const ExternalPoint& aScreenOffset, const ScreenPoint& aFocusPoint,
546 ScreenCoord aCurrentSpan, ScreenCoord aPreviousSpan, Modifiers aModifiers)
547 : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
548 mType(aType),
549 mFocusPoint(aFocusPoint),
550 mScreenOffset(aScreenOffset),
551 mCurrentSpan(aCurrentSpan),
552 mPreviousSpan(aPreviousSpan),
553 mHandledByAPZ(false) {}
555 bool PinchGestureInput::TransformToLocal(
556 const ScreenToParentLayerMatrix4x4& aTransform) {
557 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mFocusPoint);
558 if (!point) {
559 return false;
561 mLocalFocusPoint = *point;
562 return true;
565 WidgetWheelEvent PinchGestureInput::ToWidgetWheelEvent(
566 nsIWidget* aWidget) const {
567 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
568 wheelEvent.mModifiers = this->modifiers | MODIFIER_CONTROL;
569 wheelEvent.mTime = mTime;
570 wheelEvent.mTimeStamp = mTimeStamp;
571 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
572 mFocusPoint,
573 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
574 wheelEvent.mButtons = 0;
575 wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
576 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
578 #if defined(OS_MACOSX)
579 // This converts the pinch gesture value to a fake wheel event that has the
580 // control key pressed so that pages can implement custom pinch gesture
581 // handling. It may seem strange that this doesn't use a wheel event with
582 // the deltaZ property set, but this matches Chrome's behavior as described
583 // at https://code.google.com/p/chromium/issues/detail?id=289887
585 // The intent of the formula below is to produce numbers similar to Chrome's
586 // implementation of this feature. Chrome implements deltaY using the formula
587 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
588 // All deltas for a single pinch gesture should sum to 0 if the start and end
589 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
590 // because they followed Apple's misleading documentation, which implies that
591 // "1 + [event magnification]" is the scale factor. The scale factor is
592 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
593 // already in log space.
595 // The multiplication by the backing scale factor below counteracts the
596 // division by the backing scale factor in WheelEvent.
598 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
599 // is [event magnification] but [event magnification] is only available in the
600 // macOS widget code so we have to reverse engineer from mCurrentSpan and
601 // mPreviousSpan (which are derived from [event magnification]) to get it.
602 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
603 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
604 // for M in terms of mPreviousSpan and plugging that into to the formula for
605 // deltaY.
606 wheelEvent.mDeltaY = (mPreviousSpan - 100.0) *
607 (aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
608 #else
609 // This calculation is based on what the Windows widget code does.
610 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
611 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
612 // is the scale from the current OS event and lastScale is the scale when the
613 // previous OS event happened. It then seems reasonable to calculate |M =
614 // currentScale / lastScale| and use the same formula as the macOS code
615 // (|-100.0 * M * GetDefaultScaleInternal()|).
617 // XXX When we write the code for other platforms to do the same we'll need to
618 // make sure this calculation is reasonable.
620 if (mPreviousSpan != 0.f) {
621 wheelEvent.mDeltaY = -100.0 * (mCurrentSpan / mPreviousSpan) *
622 (aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
623 } else {
624 // Not sure what makes sense here, this seems reasonable.
625 wheelEvent.mDeltaY = -100.0 * mCurrentSpan *
626 (aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
628 #endif
630 return wheelEvent;
633 TapGestureInput::TapGestureInput()
634 : InputData(TAPGESTURE_INPUT), mType(TAPGESTURE_LONG) {}
636 TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
637 TimeStamp aTimeStamp,
638 const ScreenIntPoint& aPoint,
639 Modifiers aModifiers)
640 : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
641 mType(aType),
642 mPoint(aPoint) {}
644 TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
645 TimeStamp aTimeStamp,
646 const ParentLayerPoint& aLocalPoint,
647 Modifiers aModifiers)
648 : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
649 mType(aType),
650 mLocalPoint(aLocalPoint) {}
652 bool TapGestureInput::TransformToLocal(
653 const ScreenToParentLayerMatrix4x4& aTransform) {
654 Maybe<ParentLayerIntPoint> point = UntransformBy(aTransform, mPoint);
655 if (!point) {
656 return false;
658 mLocalPoint = *point;
659 return true;
662 ScrollWheelInput::ScrollWheelInput()
663 : InputData(SCROLLWHEEL_INPUT),
664 mDeltaType(SCROLLDELTA_LINE),
665 mScrollMode(SCROLLMODE_INSTANT),
666 mHandledByAPZ(false),
667 mDeltaX(0.0),
668 mDeltaY(0.0),
669 mLineOrPageDeltaX(0),
670 mLineOrPageDeltaY(0),
671 mScrollSeriesNumber(0),
672 mUserDeltaMultiplierX(1.0),
673 mUserDeltaMultiplierY(1.0),
674 mMayHaveMomentum(false),
675 mIsMomentum(false),
676 mAPZAction(APZWheelAction::Scroll) {}
678 ScrollWheelInput::ScrollWheelInput(
679 uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers,
680 ScrollMode aScrollMode, ScrollDeltaType aDeltaType,
681 const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY,
682 bool aAllowToOverrideSystemScrollSpeed,
683 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy)
684 : InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers),
685 mDeltaType(aDeltaType),
686 mScrollMode(aScrollMode),
687 mOrigin(aOrigin),
688 mHandledByAPZ(false),
689 mDeltaX(aDeltaX),
690 mDeltaY(aDeltaY),
691 mLineOrPageDeltaX(0),
692 mLineOrPageDeltaY(0),
693 mScrollSeriesNumber(0),
694 mUserDeltaMultiplierX(1.0),
695 mUserDeltaMultiplierY(1.0),
696 mMayHaveMomentum(false),
697 mIsMomentum(false),
698 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed),
699 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy),
700 mAPZAction(APZWheelAction::Scroll) {}
702 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent& aWheelEvent)
703 : InputData(SCROLLWHEEL_INPUT, aWheelEvent.mTime, aWheelEvent.mTimeStamp,
704 aWheelEvent.mModifiers),
705 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent.mDeltaMode)),
706 mScrollMode(SCROLLMODE_INSTANT),
707 mHandledByAPZ(aWheelEvent.mFlags.mHandledByAPZ),
708 mDeltaX(aWheelEvent.mDeltaX),
709 mDeltaY(aWheelEvent.mDeltaY),
710 mLineOrPageDeltaX(aWheelEvent.mLineOrPageDeltaX),
711 mLineOrPageDeltaY(aWheelEvent.mLineOrPageDeltaY),
712 mScrollSeriesNumber(0),
713 mUserDeltaMultiplierX(1.0),
714 mUserDeltaMultiplierY(1.0),
715 mMayHaveMomentum(aWheelEvent.mMayHaveMomentum),
716 mIsMomentum(aWheelEvent.mIsMomentum),
717 mAllowToOverrideSystemScrollSpeed(
718 aWheelEvent.mAllowToOverrideSystemScrollSpeed),
719 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone),
720 mAPZAction(APZWheelAction::Scroll) {
721 mOrigin = ScreenPoint(ViewAs<ScreenPixel>(
722 aWheelEvent.mRefPoint,
723 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
726 ScrollWheelInput::ScrollDeltaType ScrollWheelInput::DeltaTypeForDeltaMode(
727 uint32_t aDeltaMode) {
728 switch (aDeltaMode) {
729 case WheelEvent_Binding::DOM_DELTA_LINE:
730 return SCROLLDELTA_LINE;
731 case WheelEvent_Binding::DOM_DELTA_PAGE:
732 return SCROLLDELTA_PAGE;
733 case WheelEvent_Binding::DOM_DELTA_PIXEL:
734 return SCROLLDELTA_PIXEL;
735 default:
736 MOZ_CRASH();
738 return SCROLLDELTA_LINE;
741 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType) {
742 switch (aDeltaType) {
743 case ScrollWheelInput::SCROLLDELTA_LINE:
744 return WheelEvent_Binding::DOM_DELTA_LINE;
745 case ScrollWheelInput::SCROLLDELTA_PAGE:
746 return WheelEvent_Binding::DOM_DELTA_PAGE;
747 case ScrollWheelInput::SCROLLDELTA_PIXEL:
748 default:
749 return WheelEvent_Binding::DOM_DELTA_PIXEL;
753 ScrollUnit ScrollWheelInput::ScrollUnitForDeltaType(
754 ScrollDeltaType aDeltaType) {
755 switch (aDeltaType) {
756 case SCROLLDELTA_LINE:
757 return ScrollUnit::LINES;
758 case SCROLLDELTA_PAGE:
759 return ScrollUnit::PAGES;
760 case SCROLLDELTA_PIXEL:
761 return ScrollUnit::DEVICE_PIXELS;
762 default:
763 MOZ_CRASH();
765 return ScrollUnit::LINES;
768 WidgetWheelEvent ScrollWheelInput::ToWidgetWheelEvent(
769 nsIWidget* aWidget) const {
770 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
771 wheelEvent.mModifiers = this->modifiers;
772 wheelEvent.mTime = mTime;
773 wheelEvent.mTimeStamp = mTimeStamp;
774 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
775 mOrigin,
776 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
777 wheelEvent.mButtons = 0;
778 wheelEvent.mDeltaMode = DeltaModeForDeltaType(mDeltaType);
779 wheelEvent.mMayHaveMomentum = mMayHaveMomentum;
780 wheelEvent.mIsMomentum = mIsMomentum;
781 wheelEvent.mDeltaX = mDeltaX;
782 wheelEvent.mDeltaY = mDeltaY;
783 wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
784 wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
785 wheelEvent.mAllowToOverrideSystemScrollSpeed =
786 mAllowToOverrideSystemScrollSpeed;
787 wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
788 wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
789 return wheelEvent;
792 bool ScrollWheelInput::TransformToLocal(
793 const ScreenToParentLayerMatrix4x4& aTransform) {
794 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
795 if (!point) {
796 return false;
798 mLocalOrigin = *point;
799 return true;
802 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
803 return mUserDeltaMultiplierX != 1.0 || mUserDeltaMultiplierY != 1.0;
806 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent& aEvent)
807 : InputData(KEYBOARD_INPUT, aEvent.mTime, aEvent.mTimeStamp,
808 aEvent.mModifiers),
809 mKeyCode(aEvent.mKeyCode),
810 mCharCode(aEvent.mCharCode),
811 mHandledByAPZ(false) {
812 switch (aEvent.mMessage) {
813 case eKeyPress: {
814 mType = KeyboardInput::KEY_PRESS;
815 break;
817 case eKeyUp: {
818 mType = KeyboardInput::KEY_UP;
819 break;
821 case eKeyDown: {
822 mType = KeyboardInput::KEY_DOWN;
823 break;
825 default:
826 mType = KeyboardInput::KEY_OTHER;
827 break;
830 aEvent.GetShortcutKeyCandidates(mShortcutCandidates);
833 KeyboardInput::KeyboardInput()
834 : InputData(KEYBOARD_INPUT),
835 mType(KEY_DOWN),
836 mKeyCode(0),
837 mCharCode(0),
838 mHandledByAPZ(false) {}
840 } // namespace mozilla