Bug 1698786: part 1) Add some logging to `mozInlineSpellChecker`. r=masayuki
[gecko.git] / widget / InputData.cpp
blob9d3726bed3af8197de733ea592e7c70da5de1024
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& touchData : mTouches) {
150 for (auto& historicalData : touchData.mHistoricalData) {
151 historicalData.mScreenPoint.MoveBy(xTranslation, yTranslation);
153 touchData.mScreenPoint.MoveBy(xTranslation, yTranslation);
157 WidgetTouchEvent MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const {
158 MOZ_ASSERT(NS_IsMainThread(),
159 "Can only convert To WidgetTouchEvent on main thread");
161 EventMessage touchEventMessage = eVoidEvent;
162 switch (mType) {
163 case MULTITOUCH_START:
164 touchEventMessage = eTouchStart;
165 break;
166 case MULTITOUCH_MOVE:
167 touchEventMessage = eTouchMove;
168 break;
169 case MULTITOUCH_END:
170 touchEventMessage = eTouchEnd;
171 break;
172 case MULTITOUCH_CANCEL:
173 touchEventMessage = eTouchCancel;
174 break;
175 default:
176 MOZ_ASSERT_UNREACHABLE(
177 "Did not assign a type to WidgetTouchEvent in MultiTouchInput");
178 break;
181 WidgetTouchEvent event(true, touchEventMessage, aWidget);
182 if (touchEventMessage == eVoidEvent) {
183 return event;
186 event.mModifiers = this->modifiers;
187 event.mTime = this->mTime;
188 event.mTimeStamp = this->mTimeStamp;
189 event.mFlags.mHandledByAPZ = mHandledByAPZ;
190 event.mFocusSequenceNumber = mFocusSequenceNumber;
191 event.mLayersId = mLayersId;
193 for (size_t i = 0; i < mTouches.Length(); i++) {
194 *event.mTouches.AppendElement() = mTouches[i].ToNewDOMTouch();
197 return event;
200 int32_t MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier) {
201 for (size_t i = 0; i < mTouches.Length(); i++) {
202 if (mTouches[i].mIdentifier == aTouchIdentifier) {
203 return (int32_t)i;
206 return -1;
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) {
216 return false;
218 historicalData.mLocalScreenPoint = *historicalPoint;
220 Maybe<ParentLayerIntPoint> point =
221 UntransformBy(aTransform, touchData.mScreenPoint);
222 if (!point) {
223 return false;
225 touchData.mLocalScreenPoint = *point;
227 return true;
230 MouseInput::MouseInput()
231 : InputData(MOUSE_INPUT),
232 mType(MOUSE_NONE),
233 mButtonType(NONE),
234 mInputSource(0),
235 mButtons(0),
236 mHandledByAPZ(false) {}
238 MouseInput::MouseInput(MouseType aType, ButtonType aButtonType,
239 uint16_t aInputSource, int16_t aButtons,
240 const ScreenPoint& aPoint, uint32_t aTime,
241 TimeStamp aTimeStamp, Modifiers aModifiers)
242 : InputData(MOUSE_INPUT, aTime, aTimeStamp, aModifiers),
243 mType(aType),
244 mButtonType(aButtonType),
245 mInputSource(aInputSource),
246 mButtons(aButtons),
247 mOrigin(aPoint),
248 mHandledByAPZ(false) {}
250 MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
251 : InputData(MOUSE_INPUT, aMouseEvent.mTime, aMouseEvent.mTimeStamp,
252 aMouseEvent.mModifiers),
253 mType(MOUSE_NONE),
254 mButtonType(NONE),
255 mInputSource(aMouseEvent.mInputSource),
256 mButtons(aMouseEvent.mButtons),
257 mHandledByAPZ(aMouseEvent.mFlags.mHandledByAPZ) {
258 MOZ_ASSERT(NS_IsMainThread(),
259 "Can only copy from WidgetTouchEvent on main thread");
261 mButtonType = NONE;
263 switch (aMouseEvent.mButton) {
264 case MouseButton::ePrimary:
265 mButtonType = MouseInput::PRIMARY_BUTTON;
266 break;
267 case MouseButton::eMiddle:
268 mButtonType = MouseInput::MIDDLE_BUTTON;
269 break;
270 case MouseButton::eSecondary:
271 mButtonType = MouseInput::SECONDARY_BUTTON;
272 break;
275 switch (aMouseEvent.mMessage) {
276 case eMouseMove:
277 mType = MOUSE_MOVE;
278 break;
279 case eMouseUp:
280 mType = MOUSE_UP;
281 break;
282 case eMouseDown:
283 mType = MOUSE_DOWN;
284 break;
285 case eDragStart:
286 mType = MOUSE_DRAG_START;
287 break;
288 case eDragEnd:
289 mType = MOUSE_DRAG_END;
290 break;
291 case eMouseEnterIntoWidget:
292 mType = MOUSE_WIDGET_ENTER;
293 break;
294 case eMouseExitFromWidget:
295 mType = MOUSE_WIDGET_EXIT;
296 break;
297 case eMouseHitTest:
298 mType = MOUSE_HITTEST;
299 break;
300 default:
301 MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
302 break;
305 mOrigin = ScreenPoint(ViewAs<ScreenPixel>(
306 aMouseEvent.mRefPoint,
307 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
310 bool MouseInput::IsLeftButton() const { return mButtonType == PRIMARY_BUTTON; }
312 bool MouseInput::TransformToLocal(
313 const ScreenToParentLayerMatrix4x4& aTransform) {
314 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
315 if (!point) {
316 return false;
318 mLocalOrigin = *point;
320 return true;
323 WidgetMouseEvent MouseInput::ToWidgetEvent(nsIWidget* aWidget) const {
324 MOZ_ASSERT(NS_IsMainThread(),
325 "Can only convert To WidgetTouchEvent on main thread");
327 EventMessage msg = eVoidEvent;
328 uint32_t clickCount = 0;
329 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
330 switch (mType) {
331 case MOUSE_MOVE:
332 msg = eMouseMove;
333 break;
334 case MOUSE_UP:
335 msg = eMouseUp;
336 clickCount = 1;
337 break;
338 case MOUSE_DOWN:
339 msg = eMouseDown;
340 clickCount = 1;
341 break;
342 case MOUSE_DRAG_START:
343 msg = eDragStart;
344 break;
345 case MOUSE_DRAG_END:
346 msg = eDragEnd;
347 break;
348 case MOUSE_WIDGET_ENTER:
349 msg = eMouseEnterIntoWidget;
350 break;
351 case MOUSE_WIDGET_EXIT:
352 msg = eMouseExitFromWidget;
353 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
354 break;
355 case MOUSE_HITTEST:
356 msg = eMouseHitTest;
357 break;
358 default:
359 MOZ_ASSERT_UNREACHABLE(
360 "Did not assign a type to WidgetMouseEvent in MouseInput");
361 break;
364 WidgetMouseEvent event(true, msg, aWidget, WidgetMouseEvent::eReal,
365 WidgetMouseEvent::eNormal);
367 if (msg == eVoidEvent) {
368 return event;
371 switch (mButtonType) {
372 case MouseInput::PRIMARY_BUTTON:
373 event.mButton = MouseButton::ePrimary;
374 break;
375 case MouseInput::MIDDLE_BUTTON:
376 event.mButton = MouseButton::eMiddle;
377 break;
378 case MouseInput::SECONDARY_BUTTON:
379 event.mButton = MouseButton::eSecondary;
380 break;
381 case MouseInput::NONE:
382 default:
383 break;
386 event.mButtons = mButtons;
387 event.mModifiers = modifiers;
388 event.mTime = mTime;
389 event.mTimeStamp = mTimeStamp;
390 event.mLayersId = mLayersId;
391 event.mFlags.mHandledByAPZ = mHandledByAPZ;
392 event.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
393 mOrigin,
394 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
395 event.mClickCount = clickCount;
396 event.mInputSource = mInputSource;
397 event.mFocusSequenceNumber = mFocusSequenceNumber;
398 event.mExitFrom = exitFrom;
400 return event;
403 PanGestureInput::PanGestureInput()
404 : InputData(PANGESTURE_INPUT),
405 mType(PANGESTURE_MAYSTART),
406 mLineOrPageDeltaX(0),
407 mLineOrPageDeltaY(0),
408 mUserDeltaMultiplierX(1.0),
409 mUserDeltaMultiplierY(1.0),
410 mHandledByAPZ(false),
411 mFollowedByMomentum(false),
412 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
413 mOverscrollBehaviorAllowsSwipe(false),
414 mSimulateMomentum(false) {}
416 PanGestureInput::PanGestureInput(PanGestureType aType, uint32_t aTime,
417 TimeStamp aTimeStamp,
418 const ScreenPoint& aPanStartPoint,
419 const ScreenPoint& aPanDisplacement,
420 Modifiers aModifiers)
421 : InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
422 mType(aType),
423 mPanStartPoint(aPanStartPoint),
424 mPanDisplacement(aPanDisplacement),
425 mLineOrPageDeltaX(0),
426 mLineOrPageDeltaY(0),
427 mUserDeltaMultiplierX(1.0),
428 mUserDeltaMultiplierY(1.0),
429 mHandledByAPZ(false),
430 mFollowedByMomentum(false),
431 mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection(false),
432 mOverscrollBehaviorAllowsSwipe(false),
433 mSimulateMomentum(false) {}
435 bool PanGestureInput::IsMomentum() const {
436 switch (mType) {
437 case PanGestureInput::PANGESTURE_MOMENTUMSTART:
438 case PanGestureInput::PANGESTURE_MOMENTUMPAN:
439 case PanGestureInput::PANGESTURE_MOMENTUMEND:
440 return true;
441 default:
442 return false;
446 WidgetWheelEvent PanGestureInput::ToWidgetEvent(nsIWidget* aWidget) const {
447 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
448 wheelEvent.mModifiers = this->modifiers;
449 wheelEvent.mTime = mTime;
450 wheelEvent.mTimeStamp = mTimeStamp;
451 wheelEvent.mLayersId = mLayersId;
452 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
453 mPanStartPoint,
454 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
455 wheelEvent.mButtons = 0;
456 wheelEvent.mMayHaveMomentum = true; // pan inputs may have momentum
457 wheelEvent.mIsMomentum = IsMomentum();
458 wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
459 wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
460 wheelEvent.mDeltaX = mPanDisplacement.x;
461 wheelEvent.mDeltaY = mPanDisplacement.y;
462 wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
463 wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
464 if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
465 // Emulate legacy widget/gtk behavior
466 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_LINE;
467 wheelEvent.mIsNoLineOrPageDelta = true;
468 wheelEvent.mScrollType = WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY;
469 wheelEvent.mDeltaX *= 3;
470 wheelEvent.mDeltaY *= 3;
471 } else {
472 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
474 return wheelEvent;
477 bool PanGestureInput::TransformToLocal(
478 const ScreenToParentLayerMatrix4x4& aTransform) {
479 Maybe<ParentLayerPoint> panStartPoint =
480 UntransformBy(aTransform, mPanStartPoint);
481 if (!panStartPoint) {
482 return false;
484 mLocalPanStartPoint = *panStartPoint;
486 if (mDeltaType == PanGestureInput::PANDELTA_PAGE) {
487 // Skip transforming the pan displacement because we want
488 // raw page proportion counts.
489 mLocalPanDisplacement.x = mPanDisplacement.x;
490 mLocalPanDisplacement.y = mPanDisplacement.y;
491 return true;
494 Maybe<ParentLayerPoint> panDisplacement =
495 UntransformVector(aTransform, mPanDisplacement, mPanStartPoint);
496 if (!panDisplacement) {
497 return false;
499 mLocalPanDisplacement = *panDisplacement;
500 return true;
503 ScreenPoint PanGestureInput::UserMultipliedPanDisplacement() const {
504 return ScreenPoint(mPanDisplacement.x * mUserDeltaMultiplierX,
505 mPanDisplacement.y * mUserDeltaMultiplierY);
508 ParentLayerPoint PanGestureInput::UserMultipliedLocalPanDisplacement() const {
509 return ParentLayerPoint(mLocalPanDisplacement.x * mUserDeltaMultiplierX,
510 mLocalPanDisplacement.y * mUserDeltaMultiplierY);
513 static int32_t TakeLargestInt(gfx::Float* aFloat) {
514 int32_t result(*aFloat); // truncate towards zero
515 *aFloat -= result;
516 return result;
519 /* static */ gfx::IntPoint PanGestureInput::GetIntegerDeltaForEvent(
520 bool aIsStart, float x, float y) {
521 static gfx::Point sAccumulator(0.0f, 0.0f);
522 if (aIsStart) {
523 sAccumulator = gfx::Point(0.0f, 0.0f);
525 sAccumulator.x += x;
526 sAccumulator.y += y;
527 return gfx::IntPoint(TakeLargestInt(&sAccumulator.x),
528 TakeLargestInt(&sAccumulator.y));
531 PinchGestureInput::PinchGestureInput()
532 : InputData(PINCHGESTURE_INPUT),
533 mType(PINCHGESTURE_START),
534 mSource(UNKNOWN),
535 mHandledByAPZ(false) {}
537 PinchGestureInput::PinchGestureInput(
538 PinchGestureType aType, PinchGestureSource aSource, uint32_t aTime,
539 TimeStamp aTimeStamp, const ExternalPoint& aScreenOffset,
540 const ScreenPoint& aFocusPoint, ScreenCoord aCurrentSpan,
541 ScreenCoord aPreviousSpan, Modifiers aModifiers)
542 : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
543 mType(aType),
544 mSource(aSource),
545 mFocusPoint(aFocusPoint),
546 mScreenOffset(aScreenOffset),
547 mCurrentSpan(aCurrentSpan),
548 mPreviousSpan(aPreviousSpan),
549 mLineOrPageDeltaY(0),
550 mHandledByAPZ(false) {}
552 bool PinchGestureInput::TransformToLocal(
553 const ScreenToParentLayerMatrix4x4& aTransform) {
554 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mFocusPoint);
555 if (!point) {
556 return false;
558 mLocalFocusPoint = *point;
559 return true;
562 WidgetWheelEvent PinchGestureInput::ToWidgetEvent(nsIWidget* aWidget) const {
563 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
564 wheelEvent.mModifiers = this->modifiers | MODIFIER_CONTROL;
565 wheelEvent.mTime = mTime;
566 wheelEvent.mTimeStamp = mTimeStamp;
567 wheelEvent.mLayersId = mLayersId;
568 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
569 mFocusPoint,
570 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
571 wheelEvent.mButtons = 0;
572 wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
573 wheelEvent.mDeltaMode = WheelEvent_Binding::DOM_DELTA_PIXEL;
575 wheelEvent.mDeltaY = ComputeDeltaY(aWidget);
577 wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
579 MOZ_ASSERT(mType == PINCHGESTURE_END || wheelEvent.mDeltaY != 0.0);
581 return wheelEvent;
584 double PinchGestureInput::ComputeDeltaY(nsIWidget* aWidget) const {
585 #if defined(OS_MACOSX)
586 // This converts the pinch gesture value to a fake wheel event that has the
587 // control key pressed so that pages can implement custom pinch gesture
588 // handling. It may seem strange that this doesn't use a wheel event with
589 // the deltaZ property set, but this matches Chrome's behavior as described
590 // at https://code.google.com/p/chromium/issues/detail?id=289887
592 // The intent of the formula below is to produce numbers similar to Chrome's
593 // implementation of this feature. Chrome implements deltaY using the formula
594 // "-100 * log(1 + [event magnification])" which is unfortunately incorrect.
595 // All deltas for a single pinch gesture should sum to 0 if the start and end
596 // of a pinch gesture end up in the same place. This doesn't happen in Chrome
597 // because they followed Apple's misleading documentation, which implies that
598 // "1 + [event magnification]" is the scale factor. The scale factor is
599 // instead "pow(ratio, [event magnification])" so "[event magnification]" is
600 // already in log space.
602 // The multiplication by the backing scale factor below counteracts the
603 // division by the backing scale factor in WheelEvent.
605 // We want to set deltaY to |-100.0 * M * GetDefaultScaleInternal()| where M
606 // is [event magnification] but [event magnification] is only available in the
607 // macOS widget code so we have to reverse engineer from mCurrentSpan and
608 // mPreviousSpan (which are derived from [event magnification]) to get it.
609 // Specifically, we know |mCurrentSpan == 100.0| and |mPreviousSpan == 100.0 *
610 // (1.0 - M)|. We can calculate deltaY by solving the mPreviousSpan equation
611 // for M in terms of mPreviousSpan and plugging that into to the formula for
612 // deltaY.
613 return (mPreviousSpan - 100.0) *
614 (aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
615 #else
616 // This calculation is based on what the Windows and Linux widget code does.
617 // Specifically, it creates a PinchGestureInput with |mCurrentSpan == 100.0 *
618 // currentScale| and |mPreviousSpan == 100.0 * lastScale| where currentScale
619 // is the scale from the current OS event and lastScale is the scale when the
620 // previous OS event happened. On macOS [event magnification] is a relative
621 // change in scale factor, ie if the scale factor changed from 1 to 1.1 it
622 // will be 0.1, similarly if it changed from 1 to 0.9 it will be -0.1. To
623 // calculate the relative scale change on Windows we would calculate |M =
624 // currentScale - lastScale = (mCurrentSpan-mPreviousSpan)/100| and use the
625 // same formula as the macOS code
626 // (|-100.0 * M * GetDefaultScaleInternal()|).
628 return (mPreviousSpan - mCurrentSpan) *
629 (aWidget ? aWidget->GetDefaultScaleInternal() : 1.f);
630 #endif
633 /* static */ gfx::IntPoint PinchGestureInput::GetIntegerDeltaForEvent(
634 bool aIsStart, float x, float y) {
635 static gfx::Point sAccumulator(0.0f, 0.0f);
636 if (aIsStart) {
637 sAccumulator = gfx::Point(0.0f, 0.0f);
639 sAccumulator.x += x;
640 sAccumulator.y += y;
641 return gfx::IntPoint(TakeLargestInt(&sAccumulator.x),
642 TakeLargestInt(&sAccumulator.y));
645 TapGestureInput::TapGestureInput()
646 : InputData(TAPGESTURE_INPUT), mType(TAPGESTURE_LONG) {}
648 TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
649 TimeStamp aTimeStamp,
650 const ScreenIntPoint& aPoint,
651 Modifiers aModifiers)
652 : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
653 mType(aType),
654 mPoint(aPoint) {}
656 TapGestureInput::TapGestureInput(TapGestureType aType, uint32_t aTime,
657 TimeStamp aTimeStamp,
658 const ParentLayerPoint& aLocalPoint,
659 Modifiers aModifiers)
660 : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
661 mType(aType),
662 mLocalPoint(aLocalPoint) {}
664 bool TapGestureInput::TransformToLocal(
665 const ScreenToParentLayerMatrix4x4& aTransform) {
666 Maybe<ParentLayerIntPoint> point = UntransformBy(aTransform, mPoint);
667 if (!point) {
668 return false;
670 mLocalPoint = *point;
671 return true;
674 WidgetSimpleGestureEvent TapGestureInput::ToWidgetEvent(
675 nsIWidget* aWidget) const {
676 WidgetSimpleGestureEvent event(true, eTapGesture, aWidget);
678 event.mTime = mTime;
679 event.mTimeStamp = mTimeStamp;
680 event.mLayersId = mLayersId;
681 event.mRefPoint = ViewAs<LayoutDevicePixel>(
682 mPoint,
683 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
684 event.mButtons = 0;
685 event.mClickCount = 1;
686 event.mModifiers = modifiers;
688 return event;
691 ScrollWheelInput::ScrollWheelInput()
692 : InputData(SCROLLWHEEL_INPUT),
693 mDeltaType(SCROLLDELTA_LINE),
694 mScrollMode(SCROLLMODE_INSTANT),
695 mHandledByAPZ(false),
696 mDeltaX(0.0),
697 mDeltaY(0.0),
698 mLineOrPageDeltaX(0),
699 mLineOrPageDeltaY(0),
700 mScrollSeriesNumber(0),
701 mUserDeltaMultiplierX(1.0),
702 mUserDeltaMultiplierY(1.0),
703 mMayHaveMomentum(false),
704 mIsMomentum(false),
705 mAPZAction(APZWheelAction::Scroll) {}
707 ScrollWheelInput::ScrollWheelInput(
708 uint32_t aTime, TimeStamp aTimeStamp, Modifiers aModifiers,
709 ScrollMode aScrollMode, ScrollDeltaType aDeltaType,
710 const ScreenPoint& aOrigin, double aDeltaX, double aDeltaY,
711 bool aAllowToOverrideSystemScrollSpeed,
712 WheelDeltaAdjustmentStrategy aWheelDeltaAdjustmentStrategy)
713 : InputData(SCROLLWHEEL_INPUT, aTime, aTimeStamp, aModifiers),
714 mDeltaType(aDeltaType),
715 mScrollMode(aScrollMode),
716 mOrigin(aOrigin),
717 mHandledByAPZ(false),
718 mDeltaX(aDeltaX),
719 mDeltaY(aDeltaY),
720 mLineOrPageDeltaX(0),
721 mLineOrPageDeltaY(0),
722 mScrollSeriesNumber(0),
723 mUserDeltaMultiplierX(1.0),
724 mUserDeltaMultiplierY(1.0),
725 mMayHaveMomentum(false),
726 mIsMomentum(false),
727 mAllowToOverrideSystemScrollSpeed(aAllowToOverrideSystemScrollSpeed),
728 mWheelDeltaAdjustmentStrategy(aWheelDeltaAdjustmentStrategy),
729 mAPZAction(APZWheelAction::Scroll) {}
731 ScrollWheelInput::ScrollWheelInput(const WidgetWheelEvent& aWheelEvent)
732 : InputData(SCROLLWHEEL_INPUT, aWheelEvent.mTime, aWheelEvent.mTimeStamp,
733 aWheelEvent.mModifiers),
734 mDeltaType(DeltaTypeForDeltaMode(aWheelEvent.mDeltaMode)),
735 mScrollMode(SCROLLMODE_INSTANT),
736 mHandledByAPZ(aWheelEvent.mFlags.mHandledByAPZ),
737 mDeltaX(aWheelEvent.mDeltaX),
738 mDeltaY(aWheelEvent.mDeltaY),
739 mLineOrPageDeltaX(aWheelEvent.mLineOrPageDeltaX),
740 mLineOrPageDeltaY(aWheelEvent.mLineOrPageDeltaY),
741 mScrollSeriesNumber(0),
742 mUserDeltaMultiplierX(1.0),
743 mUserDeltaMultiplierY(1.0),
744 mMayHaveMomentum(aWheelEvent.mMayHaveMomentum),
745 mIsMomentum(aWheelEvent.mIsMomentum),
746 mAllowToOverrideSystemScrollSpeed(
747 aWheelEvent.mAllowToOverrideSystemScrollSpeed),
748 mWheelDeltaAdjustmentStrategy(WheelDeltaAdjustmentStrategy::eNone),
749 mAPZAction(APZWheelAction::Scroll) {
750 mOrigin = ScreenPoint(ViewAs<ScreenPixel>(
751 aWheelEvent.mRefPoint,
752 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
755 ScrollWheelInput::ScrollDeltaType ScrollWheelInput::DeltaTypeForDeltaMode(
756 uint32_t aDeltaMode) {
757 switch (aDeltaMode) {
758 case WheelEvent_Binding::DOM_DELTA_LINE:
759 return SCROLLDELTA_LINE;
760 case WheelEvent_Binding::DOM_DELTA_PAGE:
761 return SCROLLDELTA_PAGE;
762 case WheelEvent_Binding::DOM_DELTA_PIXEL:
763 return SCROLLDELTA_PIXEL;
764 default:
765 MOZ_CRASH();
767 return SCROLLDELTA_LINE;
770 uint32_t ScrollWheelInput::DeltaModeForDeltaType(ScrollDeltaType aDeltaType) {
771 switch (aDeltaType) {
772 case ScrollWheelInput::SCROLLDELTA_LINE:
773 return WheelEvent_Binding::DOM_DELTA_LINE;
774 case ScrollWheelInput::SCROLLDELTA_PAGE:
775 return WheelEvent_Binding::DOM_DELTA_PAGE;
776 case ScrollWheelInput::SCROLLDELTA_PIXEL:
777 default:
778 return WheelEvent_Binding::DOM_DELTA_PIXEL;
782 ScrollUnit ScrollWheelInput::ScrollUnitForDeltaType(
783 ScrollDeltaType aDeltaType) {
784 switch (aDeltaType) {
785 case SCROLLDELTA_LINE:
786 return ScrollUnit::LINES;
787 case SCROLLDELTA_PAGE:
788 return ScrollUnit::PAGES;
789 case SCROLLDELTA_PIXEL:
790 return ScrollUnit::DEVICE_PIXELS;
791 default:
792 MOZ_CRASH();
794 return ScrollUnit::LINES;
797 WidgetWheelEvent ScrollWheelInput::ToWidgetEvent(nsIWidget* aWidget) const {
798 WidgetWheelEvent wheelEvent(true, eWheel, aWidget);
799 wheelEvent.mModifiers = this->modifiers;
800 wheelEvent.mTime = mTime;
801 wheelEvent.mTimeStamp = mTimeStamp;
802 wheelEvent.mLayersId = mLayersId;
803 wheelEvent.mRefPoint = RoundedToInt(ViewAs<LayoutDevicePixel>(
804 mOrigin,
805 PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent));
806 wheelEvent.mButtons = 0;
807 wheelEvent.mDeltaMode = DeltaModeForDeltaType(mDeltaType);
808 wheelEvent.mMayHaveMomentum = mMayHaveMomentum;
809 wheelEvent.mIsMomentum = mIsMomentum;
810 wheelEvent.mDeltaX = mDeltaX;
811 wheelEvent.mDeltaY = mDeltaY;
812 wheelEvent.mLineOrPageDeltaX = mLineOrPageDeltaX;
813 wheelEvent.mLineOrPageDeltaY = mLineOrPageDeltaY;
814 wheelEvent.mAllowToOverrideSystemScrollSpeed =
815 mAllowToOverrideSystemScrollSpeed;
816 wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
817 wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
818 return wheelEvent;
821 bool ScrollWheelInput::TransformToLocal(
822 const ScreenToParentLayerMatrix4x4& aTransform) {
823 Maybe<ParentLayerPoint> point = UntransformBy(aTransform, mOrigin);
824 if (!point) {
825 return false;
827 mLocalOrigin = *point;
828 return true;
831 bool ScrollWheelInput::IsCustomizedByUserPrefs() const {
832 return mUserDeltaMultiplierX != 1.0 || mUserDeltaMultiplierY != 1.0;
835 KeyboardInput::KeyboardInput(const WidgetKeyboardEvent& aEvent)
836 : InputData(KEYBOARD_INPUT, aEvent.mTime, aEvent.mTimeStamp,
837 aEvent.mModifiers),
838 mKeyCode(aEvent.mKeyCode),
839 mCharCode(aEvent.mCharCode),
840 mHandledByAPZ(false) {
841 switch (aEvent.mMessage) {
842 case eKeyPress: {
843 mType = KeyboardInput::KEY_PRESS;
844 break;
846 case eKeyUp: {
847 mType = KeyboardInput::KEY_UP;
848 break;
850 case eKeyDown: {
851 mType = KeyboardInput::KEY_DOWN;
852 break;
854 default:
855 mType = KeyboardInput::KEY_OTHER;
856 break;
859 aEvent.GetShortcutKeyCandidates(mShortcutCandidates);
862 KeyboardInput::KeyboardInput()
863 : InputData(KEYBOARD_INPUT),
864 mType(KEY_DOWN),
865 mKeyCode(0),
866 mCharCode(0),
867 mHandledByAPZ(false) {}
869 } // namespace mozilla