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/. */ 5 6 #ifndef mozilla_MouseEvents_h__ 7 #define mozilla_MouseEvents_h__ 8 9 #include <stdint.h> 10 11 #include "mozilla/BasicEvents.h" 12 #include "mozilla/MathAlgorithms.h" 13 #include "mozilla/dom/DataTransfer.h" 14 #include "nsCOMPtr.h" 15 16 namespace mozilla { 17 18 namespace dom { 19 class PBrowserParent; 20 class PBrowserChild; 21 class PBrowserBridgeParent; 22 } // namespace dom 23 24 class WidgetPointerEvent; 25 } // namespace mozilla 26 27 namespace mozilla { 28 class WidgetPointerEventHolder final { 29 public: 30 nsTArray<WidgetPointerEvent> mEvents; 31 NS_INLINE_DECL_REFCOUNTING(WidgetPointerEventHolder) 32 33 private: 34 virtual ~WidgetPointerEventHolder() = default; 35 }; 36 37 /****************************************************************************** 38 * mozilla::WidgetPointerHelper 39 ******************************************************************************/ 40 41 class WidgetPointerHelper { 42 public: 43 uint32_t pointerId; 44 uint32_t tiltX; 45 uint32_t tiltY; 46 uint32_t twist; 47 float tangentialPressure; 48 bool convertToPointer; 49 RefPtr<WidgetPointerEventHolder> mCoalescedWidgetEvents; 50 WidgetPointerHelper()51 WidgetPointerHelper() 52 : pointerId(0), 53 tiltX(0), 54 tiltY(0), 55 twist(0), 56 tangentialPressure(0), 57 convertToPointer(true) {} 58 59 WidgetPointerHelper(uint32_t aPointerId, uint32_t aTiltX, uint32_t aTiltY, 60 uint32_t aTwist = 0, float aTangentialPressure = 0) pointerId(aPointerId)61 : pointerId(aPointerId), 62 tiltX(aTiltX), 63 tiltY(aTiltY), 64 twist(aTwist), 65 tangentialPressure(aTangentialPressure), 66 convertToPointer(true) {} 67 68 explicit WidgetPointerHelper(const WidgetPointerHelper& aHelper) = default; 69 70 void AssignPointerHelperData(const WidgetPointerHelper& aEvent, 71 bool aCopyCoalescedEvents = false) { 72 pointerId = aEvent.pointerId; 73 tiltX = aEvent.tiltX; 74 tiltY = aEvent.tiltY; 75 twist = aEvent.twist; 76 tangentialPressure = aEvent.tangentialPressure; 77 convertToPointer = aEvent.convertToPointer; 78 if (aCopyCoalescedEvents) { 79 mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents; 80 } 81 } 82 }; 83 84 /****************************************************************************** 85 * mozilla::WidgetMouseEventBase 86 ******************************************************************************/ 87 88 class WidgetMouseEventBase : public WidgetInputEvent { 89 private: 90 friend class dom::PBrowserParent; 91 friend class dom::PBrowserChild; 92 friend class dom::PBrowserBridgeParent; 93 94 protected: WidgetMouseEventBase()95 WidgetMouseEventBase() 96 : mPressure(0), 97 mButton(0), 98 mButtons(0), 99 mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {} 100 // Including MouseEventBinding.h here leads to an include loop, so 101 // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE. 102 WidgetMouseEventBase(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget,EventClassID aEventClassID)103 WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage, 104 nsIWidget* aWidget, EventClassID aEventClassID) 105 : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID), 106 mPressure(0), 107 mButton(0), 108 mButtons(0), 109 mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {} 110 // Including MouseEventBinding.h here leads to an include loop, so 111 // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE. 112 113 public: AsMouseEventBase()114 virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; } 115 Duplicate()116 virtual WidgetEvent* Duplicate() const override { 117 MOZ_CRASH("WidgetMouseEventBase must not be most-subclass"); 118 } 119 120 // ID of the canvas HitRegion 121 nsString mRegion; 122 123 // Finger or touch pressure of event. It ranges between 0.0 and 1.0. 124 float mPressure; 125 126 // Pressed button ID of mousedown or mouseup event. 127 // This is set only when pressing a button causes the event. 128 int16_t mButton; 129 130 // Flags of all pressed buttons at the event fired. 131 // This is set at any mouse event, don't be confused with |mButton|. 132 int16_t mButtons; 133 134 // Possible values a in MouseEvent 135 uint16_t mInputSource; 136 IsLeftButtonPressed()137 bool IsLeftButtonPressed() const { 138 return !!(mButtons & MouseButtonsFlag::ePrimaryFlag); 139 } IsRightButtonPressed()140 bool IsRightButtonPressed() const { 141 return !!(mButtons & MouseButtonsFlag::eSecondaryFlag); 142 } IsMiddleButtonPressed()143 bool IsMiddleButtonPressed() const { 144 return !!(mButtons & MouseButtonsFlag::eMiddleFlag); 145 } Is4thButtonPressed()146 bool Is4thButtonPressed() const { 147 return !!(mButtons & MouseButtonsFlag::e4thFlag); 148 } Is5thButtonPressed()149 bool Is5thButtonPressed() const { 150 return !!(mButtons & MouseButtonsFlag::e5thFlag); 151 } 152 AssignMouseEventBaseData(const WidgetMouseEventBase & aEvent,bool aCopyTargets)153 void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent, 154 bool aCopyTargets) { 155 AssignInputEventData(aEvent, aCopyTargets); 156 157 mButton = aEvent.mButton; 158 mButtons = aEvent.mButtons; 159 mPressure = aEvent.mPressure; 160 mInputSource = aEvent.mInputSource; 161 } 162 163 /** 164 * Returns true if left click event. 165 */ IsLeftClickEvent()166 bool IsLeftClickEvent() const { 167 return mMessage == eMouseClick && mButton == MouseButton::ePrimary; 168 } 169 }; 170 171 /****************************************************************************** 172 * mozilla::WidgetMouseEvent 173 ******************************************************************************/ 174 175 class WidgetMouseEvent : public WidgetMouseEventBase, 176 public WidgetPointerHelper { 177 private: 178 friend class dom::PBrowserParent; 179 friend class dom::PBrowserChild; 180 friend class dom::PBrowserBridgeParent; 181 182 public: 183 typedef bool ReasonType; 184 enum Reason : ReasonType { eReal, eSynthesized }; 185 186 typedef uint8_t ContextMenuTriggerType; 187 enum ContextMenuTrigger : ContextMenuTriggerType { 188 eNormal, 189 eContextMenuKey, 190 eControlClick 191 }; 192 193 typedef uint8_t ExitFromType; 194 enum ExitFrom : ExitFromType { 195 ePlatformChild, 196 ePlatformTopLevel, 197 ePuppet, 198 ePuppetParentToPuppetChild 199 }; 200 201 protected: WidgetMouseEvent()202 WidgetMouseEvent() 203 : mReason(eReal), 204 mContextMenuTrigger(eNormal), 205 mClickCount(0), 206 mIgnoreRootScrollFrame(false), 207 mUseLegacyNonPrimaryDispatch(false), 208 mClickEventPrevented(false) {} 209 WidgetMouseEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget,EventClassID aEventClassID,Reason aReason)210 WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget, 211 EventClassID aEventClassID, Reason aReason) 212 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID), 213 mReason(aReason), 214 mContextMenuTrigger(eNormal), 215 mClickCount(0), 216 mIgnoreRootScrollFrame(false), 217 mUseLegacyNonPrimaryDispatch(false), 218 mClickEventPrevented(false) {} 219 220 #ifdef DEBUG 221 void AssertContextMenuEventButtonConsistency() const; 222 #endif 223 224 public: AsMouseEvent()225 virtual WidgetMouseEvent* AsMouseEvent() override { return this; } 226 227 WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget, 228 Reason aReason, 229 ContextMenuTrigger aContextMenuTrigger = eNormal) WidgetMouseEventBase(aIsTrusted,aMessage,aWidget,eMouseEventClass)230 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass), 231 mReason(aReason), 232 mContextMenuTrigger(aContextMenuTrigger), 233 mClickCount(0), 234 mIgnoreRootScrollFrame(false), 235 mUseLegacyNonPrimaryDispatch(false), 236 mClickEventPrevented(false) { 237 if (aMessage == eContextMenu) { 238 mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary 239 : MouseButton::ePrimary; 240 } 241 } 242 243 #ifdef DEBUG ~WidgetMouseEvent()244 virtual ~WidgetMouseEvent() { AssertContextMenuEventButtonConsistency(); } 245 #endif 246 Duplicate()247 virtual WidgetEvent* Duplicate() const override { 248 MOZ_ASSERT(mClass == eMouseEventClass, 249 "Duplicate() must be overridden by sub class"); 250 // Not copying widget, it is a weak reference. 251 WidgetMouseEvent* result = new WidgetMouseEvent( 252 false, mMessage, nullptr, mReason, mContextMenuTrigger); 253 result->AssignMouseEventData(*this, true); 254 result->mFlags = mFlags; 255 return result; 256 } 257 258 // If during mouseup handling we detect that click event might need to be 259 // dispatched, this is setup to be the target of the click event. 260 nsCOMPtr<dom::EventTarget> mClickTarget; 261 262 // mReason indicates the reason why the event is fired: 263 // - Representing mouse operation. 264 // - Synthesized for emulating mousemove event when the content under the 265 // mouse cursor is scrolled. 266 Reason mReason; 267 268 // mContextMenuTrigger is valid only when mMessage is eContextMenu. 269 // This indicates if the context menu event is caused by context menu key or 270 // other reasons (typically, a click of right mouse button). 271 ContextMenuTrigger mContextMenuTrigger; 272 273 // mExitFrom contains a value only when mMessage is eMouseExitFromWidget. 274 // This indicates if the mouse cursor exits from a top level platform widget, 275 // a child widget or a puppet widget. 276 Maybe<ExitFrom> mExitFrom; 277 278 // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp, 279 // eMouseClick or eMouseDoubleClick. The number is count of mouse clicks. 280 // Otherwise, this must be 0. 281 uint32_t mClickCount; 282 283 // Whether the event should ignore scroll frame bounds during dispatch. 284 bool mIgnoreRootScrollFrame; 285 286 // Indicates whether the event should dispatch click events for non-primary 287 // mouse buttons on window and document. 288 bool mUseLegacyNonPrimaryDispatch; 289 290 // Whether the event shouldn't cause click event. 291 bool mClickEventPrevented; 292 AssignMouseEventData(const WidgetMouseEvent & aEvent,bool aCopyTargets)293 void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets) { 294 AssignMouseEventBaseData(aEvent, aCopyTargets); 295 AssignPointerHelperData(aEvent, /* aCopyCoalescedEvents */ true); 296 297 mExitFrom = aEvent.mExitFrom; 298 mClickCount = aEvent.mClickCount; 299 mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame; 300 mUseLegacyNonPrimaryDispatch = aEvent.mUseLegacyNonPrimaryDispatch; 301 mClickEventPrevented = aEvent.mClickEventPrevented; 302 } 303 304 /** 305 * Returns true if the event is a context menu event caused by key. 306 */ IsContextMenuKeyEvent()307 bool IsContextMenuKeyEvent() const { 308 return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey; 309 } 310 311 /** 312 * Returns true if the event is a real mouse event. Otherwise, i.e., it's 313 * a synthesized event by scroll or something, returns false. 314 */ IsReal()315 bool IsReal() const { return mReason == eReal; } 316 317 /** 318 * Returns true if middle click paste is enabled. 319 */ 320 static bool IsMiddleClickPasteEnabled(); 321 }; 322 323 /****************************************************************************** 324 * mozilla::WidgetDragEvent 325 ******************************************************************************/ 326 327 class WidgetDragEvent : public WidgetMouseEvent { 328 private: 329 friend class mozilla::dom::PBrowserParent; 330 friend class mozilla::dom::PBrowserChild; 331 332 protected: WidgetDragEvent()333 WidgetDragEvent() 334 : mUserCancelled(false), mDefaultPreventedOnContent(false) {} 335 336 public: AsDragEvent()337 virtual WidgetDragEvent* AsDragEvent() override { return this; } 338 WidgetDragEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)339 WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget) 340 : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal), 341 mUserCancelled(false), 342 mDefaultPreventedOnContent(false) {} 343 Duplicate()344 virtual WidgetEvent* Duplicate() const override { 345 MOZ_ASSERT(mClass == eDragEventClass, 346 "Duplicate() must be overridden by sub class"); 347 // Not copying widget, it is a weak reference. 348 WidgetDragEvent* result = new WidgetDragEvent(false, mMessage, nullptr); 349 result->AssignDragEventData(*this, true); 350 result->mFlags = mFlags; 351 return result; 352 } 353 354 // The dragging data. 355 nsCOMPtr<dom::DataTransfer> mDataTransfer; 356 357 // If this is true, user has cancelled the drag operation. 358 bool mUserCancelled; 359 // If this is true, the drag event's preventDefault() is called on content. 360 bool mDefaultPreventedOnContent; 361 362 // XXX Not tested by test_assign_event_data.html AssignDragEventData(const WidgetDragEvent & aEvent,bool aCopyTargets)363 void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets) { 364 AssignMouseEventData(aEvent, aCopyTargets); 365 366 mDataTransfer = aEvent.mDataTransfer; 367 // XXX mUserCancelled isn't copied, is this intentionally? 368 mUserCancelled = false; 369 mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent; 370 } 371 372 /** 373 * Should be called before dispatching the DOM tree if this event is 374 * synthesized for tests because drop effect is initialized before 375 * dispatching from widget if it's not synthesized event, but synthesized 376 * events are not initialized in the path. 377 */ 378 void InitDropEffectForTests(); 379 }; 380 381 /****************************************************************************** 382 * mozilla::WidgetMouseScrollEvent 383 * 384 * This is used for legacy DOM mouse scroll events, i.e., 385 * DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled 386 * by ESM even if widget dispatches them. Use new WidgetWheelEvent instead. 387 ******************************************************************************/ 388 389 class WidgetMouseScrollEvent : public WidgetMouseEventBase { 390 private: WidgetMouseScrollEvent()391 WidgetMouseScrollEvent() : mDelta(0), mIsHorizontal(false) {} 392 393 public: AsMouseScrollEvent()394 virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override { return this; } 395 WidgetMouseScrollEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)396 WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage, 397 nsIWidget* aWidget) 398 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, 399 eMouseScrollEventClass), 400 mDelta(0), 401 mIsHorizontal(false) {} 402 Duplicate()403 virtual WidgetEvent* Duplicate() const override { 404 MOZ_ASSERT(mClass == eMouseScrollEventClass, 405 "Duplicate() must be overridden by sub class"); 406 // Not copying widget, it is a weak reference. 407 WidgetMouseScrollEvent* result = 408 new WidgetMouseScrollEvent(false, mMessage, nullptr); 409 result->AssignMouseScrollEventData(*this, true); 410 result->mFlags = mFlags; 411 return result; 412 } 413 414 // The delta value of mouse scroll event. 415 // If the event message is eLegacyMouseLineOrPageScroll, the value indicates 416 // scroll amount in lines. However, if the value is 417 // UIEvent::SCROLL_PAGE_UP or UIEvent::SCROLL_PAGE_DOWN, the 418 // value inducates one page scroll. If the event message is 419 // eLegacyMousePixelScroll, the value indicates scroll amount in pixels. 420 int32_t mDelta; 421 422 // If this is true, it may cause to scroll horizontally. 423 // Otherwise, vertically. 424 bool mIsHorizontal; 425 AssignMouseScrollEventData(const WidgetMouseScrollEvent & aEvent,bool aCopyTargets)426 void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent, 427 bool aCopyTargets) { 428 AssignMouseEventBaseData(aEvent, aCopyTargets); 429 430 mDelta = aEvent.mDelta; 431 mIsHorizontal = aEvent.mIsHorizontal; 432 } 433 }; 434 435 /****************************************************************************** 436 * mozilla::WidgetWheelEvent 437 ******************************************************************************/ 438 439 class WidgetWheelEvent : public WidgetMouseEventBase { 440 private: 441 friend class mozilla::dom::PBrowserParent; 442 friend class mozilla::dom::PBrowserChild; 443 WidgetWheelEvent()444 WidgetWheelEvent() 445 : mDeltaX(0.0), 446 mDeltaY(0.0), 447 mDeltaZ(0.0), 448 mOverflowDeltaX(0.0), 449 mOverflowDeltaY(0.0) 450 // Including WheelEventBinding.h here leads to an include loop, so 451 // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL. 452 , 453 mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0), 454 mLineOrPageDeltaX(0), 455 mLineOrPageDeltaY(0), 456 mScrollType(SCROLL_DEFAULT), 457 mCustomizedByUserPrefs(false), 458 mMayHaveMomentum(false), 459 mIsMomentum(false), 460 mIsNoLineOrPageDelta(false), 461 mViewPortIsOverscrolled(false), 462 mCanTriggerSwipe(false), 463 mAllowToOverrideSystemScrollSpeed(false), 464 mDeltaValuesHorizontalizedForDefaultHandler(false) {} 465 466 public: AsWheelEvent()467 virtual WidgetWheelEvent* AsWheelEvent() override { return this; } 468 WidgetWheelEvent(bool aIsTrusted,EventMessage aMessage,nsIWidget * aWidget)469 WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget) 470 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass), 471 mDeltaX(0.0), 472 mDeltaY(0.0), 473 mDeltaZ(0.0), 474 mOverflowDeltaX(0.0), 475 mOverflowDeltaY(0.0) 476 // Including WheelEventBinding.h here leads to an include loop, so 477 // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL. 478 , 479 mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0), 480 mLineOrPageDeltaX(0), 481 mLineOrPageDeltaY(0), 482 mScrollType(SCROLL_DEFAULT), 483 mCustomizedByUserPrefs(false), 484 mMayHaveMomentum(false), 485 mIsMomentum(false), 486 mIsNoLineOrPageDelta(false), 487 mViewPortIsOverscrolled(false), 488 mCanTriggerSwipe(false), 489 mAllowToOverrideSystemScrollSpeed(true), 490 mDeltaValuesHorizontalizedForDefaultHandler(false) {} 491 Duplicate()492 virtual WidgetEvent* Duplicate() const override { 493 MOZ_ASSERT(mClass == eWheelEventClass, 494 "Duplicate() must be overridden by sub class"); 495 // Not copying widget, it is a weak reference. 496 WidgetWheelEvent* result = new WidgetWheelEvent(false, mMessage, nullptr); 497 result->AssignWheelEventData(*this, true); 498 result->mFlags = mFlags; 499 return result; 500 } 501 502 // On OS X, scroll gestures that start at the edge of the scrollable range 503 // can result in a swipe gesture. For the first wheel event of such a 504 // gesture, call TriggersSwipe() after the event has been processed 505 // in order to find out whether a swipe should be started. TriggersSwipe()506 bool TriggersSwipe() const { 507 return mCanTriggerSwipe && mViewPortIsOverscrolled && 508 this->mOverflowDeltaX != 0.0; 509 } 510 511 // NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by 512 // mousewheel.*.delta_multiplier_* prefs which are applied by 513 // EventStateManager. So, after widget dispatches this event, 514 // these delta values may have different values than before. 515 double mDeltaX; 516 double mDeltaY; 517 double mDeltaZ; 518 519 // The mousewheel tick counts. 520 double mWheelTicksX = 0.0; 521 double mWheelTicksY = 0.0; 522 523 enum class DeltaModeCheckingState : uint8_t { 524 // Neither deltaMode nor the delta values have been accessed. 525 Unknown, 526 // The delta values have been accessed, without checking deltaMode first. 527 Unchecked, 528 // The deltaMode has been checked. 529 Checked, 530 }; 531 532 // For compat reasons, we might expose a DOM_DELTA_LINE event as 533 // DOM_DELTA_PIXEL instead. Whether we do that depends on whether the event 534 // has been asked for the deltaMode before the deltas. If it has, we assume 535 // that the page will correctly handle DOM_DELTA_LINE. This variable tracks 536 // that state. See bug 1392460. 537 DeltaModeCheckingState mDeltaModeCheckingState = 538 DeltaModeCheckingState::Unknown; 539 540 // The amount of scrolling per line or page, without accounting for mouse 541 // wheel transactions etc. 542 // 543 // Computed by EventStateManager::DeltaAccumulator::InitLineOrPageDelta. 544 nsSize mScrollAmount; 545 546 // overflowed delta values for scroll, these values are set by 547 // EventStateManger. If the default action of the wheel event isn't scroll, 548 // these values are always zero. Otherwise, remaining delta values which are 549 // not used by scroll are set. 550 // NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager. 551 // However, mOverflowDeltaX and mOverflowDeltaY indicate unused original 552 // delta values which are not applied the delta_multiplier prefs. 553 // So, if widget wanted to know the actual direction to be scrolled, 554 // it would need to check the mDeltaX and mDeltaY. 555 double mOverflowDeltaX; 556 double mOverflowDeltaY; 557 558 // Should be one of WheelEvent_Binding::DOM_DELTA_* 559 uint32_t mDeltaMode; 560 561 // If widget sets mLineOrPageDelta, EventStateManager will dispatch 562 // eLegacyMouseLineOrPageScroll event for compatibility. Note that the delta 563 // value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines. 564 int32_t mLineOrPageDeltaX; 565 int32_t mLineOrPageDeltaY; 566 567 // When the default action for an wheel event is moving history or zooming, 568 // need to chose a delta value for doing it. GetPreferredIntDelta()569 int32_t GetPreferredIntDelta() { 570 if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) { 571 return 0; 572 } 573 if (mLineOrPageDeltaY && !mLineOrPageDeltaX) { 574 return mLineOrPageDeltaY; 575 } 576 if (mLineOrPageDeltaX && !mLineOrPageDeltaY) { 577 return mLineOrPageDeltaX; 578 } 579 if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) || 580 (mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) { 581 return 0; // We cannot guess the answer in this case. 582 } 583 return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY)) 584 ? mLineOrPageDeltaX 585 : mLineOrPageDeltaY; 586 } 587 588 // Scroll type 589 // The default value is SCROLL_DEFAULT, which means EventStateManager will 590 // select preferred scroll type automatically. 591 enum ScrollType : uint8_t { 592 SCROLL_DEFAULT, 593 SCROLL_SYNCHRONOUSLY, 594 SCROLL_ASYNCHRONOUSELY, 595 SCROLL_SMOOTHLY 596 }; 597 ScrollType mScrollType; 598 599 // If the delta values are computed from prefs, this value is true. 600 // Otherwise, i.e., they are computed from native events, false. 601 bool mCustomizedByUserPrefs; 602 603 // true if the momentum events directly tied to this event may follow it. 604 bool mMayHaveMomentum; 605 // true if the event is caused by momentum. 606 bool mIsMomentum; 607 608 // If device event handlers don't know when they should set mLineOrPageDeltaX 609 // and mLineOrPageDeltaY, this is true. Otherwise, false. 610 // If mIsNoLineOrPageDelta is true, ESM will generate 611 // eLegacyMouseLineOrPageScroll events when accumulated delta values reach 612 // a line height. 613 bool mIsNoLineOrPageDelta; 614 615 // Whether or not the parent of the currently overscrolled frame is the 616 // ViewPort. This is false in situations when an element on the page is being 617 // overscrolled (such as a text field), but true when the 'page' is being 618 // overscrolled. 619 bool mViewPortIsOverscrolled; 620 621 // The wheel event can trigger a swipe to start if it's overscrolling the 622 // viewport. 623 bool mCanTriggerSwipe; 624 625 // If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be 626 // overridden. Otherwise, the scroll speed won't be overridden even if 627 // it's enabled by the pref. 628 bool mAllowToOverrideSystemScrollSpeed; 629 630 // After the event's default action handler has adjusted its delta's values 631 // for horizontalizing a vertical wheel scroll, this variable will be set to 632 // true. 633 bool mDeltaValuesHorizontalizedForDefaultHandler; 634 AssignWheelEventData(const WidgetWheelEvent & aEvent,bool aCopyTargets)635 void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets) { 636 AssignMouseEventBaseData(aEvent, aCopyTargets); 637 638 mDeltaX = aEvent.mDeltaX; 639 mDeltaY = aEvent.mDeltaY; 640 mDeltaZ = aEvent.mDeltaZ; 641 mDeltaMode = aEvent.mDeltaMode; 642 mScrollAmount = aEvent.mScrollAmount; 643 mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs; 644 mMayHaveMomentum = aEvent.mMayHaveMomentum; 645 mIsMomentum = aEvent.mIsMomentum; 646 mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta; 647 mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX; 648 mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY; 649 mScrollType = aEvent.mScrollType; 650 mOverflowDeltaX = aEvent.mOverflowDeltaX; 651 mOverflowDeltaY = aEvent.mOverflowDeltaY; 652 mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled; 653 mCanTriggerSwipe = aEvent.mCanTriggerSwipe; 654 mAllowToOverrideSystemScrollSpeed = 655 aEvent.mAllowToOverrideSystemScrollSpeed; 656 mDeltaValuesHorizontalizedForDefaultHandler = 657 aEvent.mDeltaValuesHorizontalizedForDefaultHandler; 658 } 659 660 // System scroll speed settings may be too slow at using Gecko. In such 661 // case, we should override the scroll speed computed with system settings. 662 // Following methods return preferred delta values which are multiplied by 663 // factors specified by prefs. If system scroll speed shouldn't be 664 // overridden (e.g., this feature is disabled by pref), they return raw 665 // delta values. 666 double OverriddenDeltaX() const; 667 double OverriddenDeltaY() const; 668 669 // Compute the overridden delta value. This may be useful for suppressing 670 // too fast scroll by system scroll speed overriding when widget sets 671 // mAllowToOverrideSystemScrollSpeed. 672 static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical); 673 674 private: 675 static bool sInitialized; 676 static bool sIsSystemScrollSpeedOverrideEnabled; 677 static int32_t sOverrideFactorX; 678 static int32_t sOverrideFactorY; 679 static void Initialize(); 680 }; 681 682 /****************************************************************************** 683 * mozilla::WidgetPointerEvent 684 ******************************************************************************/ 685 686 class WidgetPointerEvent : public WidgetMouseEvent { 687 friend class mozilla::dom::PBrowserParent; 688 friend class mozilla::dom::PBrowserChild; 689 WidgetPointerEvent()690 WidgetPointerEvent() 691 : mWidth(1), mHeight(1), mIsPrimary(true), mFromTouchEvent(false) {} 692 693 public: AsPointerEvent()694 virtual WidgetPointerEvent* AsPointerEvent() override { return this; } 695 WidgetPointerEvent(bool aIsTrusted,EventMessage aMsg,nsIWidget * w)696 WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w) 697 : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal), 698 mWidth(1), 699 mHeight(1), 700 mIsPrimary(true), 701 mFromTouchEvent(false) {} 702 WidgetPointerEvent(const WidgetMouseEvent & aEvent)703 explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent) 704 : WidgetMouseEvent(aEvent), 705 mWidth(1), 706 mHeight(1), 707 mIsPrimary(true), 708 mFromTouchEvent(false) { 709 mClass = ePointerEventClass; 710 } 711 Duplicate()712 virtual WidgetEvent* Duplicate() const override { 713 MOZ_ASSERT(mClass == ePointerEventClass, 714 "Duplicate() must be overridden by sub class"); 715 // Not copying widget, it is a weak reference. 716 WidgetPointerEvent* result = 717 new WidgetPointerEvent(false, mMessage, nullptr); 718 result->AssignPointerEventData(*this, true); 719 result->mFlags = mFlags; 720 return result; 721 } 722 723 uint32_t mWidth; 724 uint32_t mHeight; 725 bool mIsPrimary; 726 bool mFromTouchEvent; 727 728 // XXX Not tested by test_assign_event_data.html AssignPointerEventData(const WidgetPointerEvent & aEvent,bool aCopyTargets)729 void AssignPointerEventData(const WidgetPointerEvent& aEvent, 730 bool aCopyTargets) { 731 AssignMouseEventData(aEvent, aCopyTargets); 732 733 mWidth = aEvent.mWidth; 734 mHeight = aEvent.mHeight; 735 mIsPrimary = aEvent.mIsPrimary; 736 mFromTouchEvent = aEvent.mFromTouchEvent; 737 } 738 }; 739 740 } // namespace mozilla 741 742 #endif // mozilla_MouseEvents_h__ 743