Bumping manifests a=b2g-bump
[gecko.git] / widget / MouseEvents.h
blobb3efd3d1c57ceba566790cb3915c1f9e8b32f94d
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 #ifndef mozilla_MouseEvents_h__
7 #define mozilla_MouseEvents_h__
9 #include <stdint.h>
11 #include "mozilla/BasicEvents.h"
12 #include "mozilla/MathAlgorithms.h"
13 #include "mozilla/dom/DataTransfer.h"
14 #include "nsCOMPtr.h"
15 #include "nsIDOMMouseEvent.h"
16 #include "nsIDOMWheelEvent.h"
18 /******************************************************************************
19 * nsDragDropEventStatus
20 ******************************************************************************/
22 enum nsDragDropEventStatus
24 // The event is a enter
25 nsDragDropEventStatus_eDragEntered,
26 // The event is exit
27 nsDragDropEventStatus_eDragExited,
28 // The event is drop
29 nsDragDropEventStatus_eDrop
32 namespace mozilla {
34 namespace dom {
35 class PBrowserParent;
36 class PBrowserChild;
37 } // namespace dom
39 /******************************************************************************
40 * mozilla::WidgetPointerHelper
41 ******************************************************************************/
43 class WidgetPointerHelper
45 public:
46 bool convertToPointer;
47 uint32_t pointerId;
48 uint32_t tiltX;
49 uint32_t tiltY;
50 bool retargetedByPointerCapture;
52 WidgetPointerHelper() : convertToPointer(true), pointerId(0), tiltX(0), tiltY(0),
53 retargetedByPointerCapture(false) {}
55 void AssignPointerHelperData(const WidgetPointerHelper& aEvent)
57 convertToPointer = aEvent.convertToPointer;
58 pointerId = aEvent.pointerId;
59 tiltX = aEvent.tiltX;
60 tiltY = aEvent.tiltY;
61 retargetedByPointerCapture = aEvent.retargetedByPointerCapture;
65 /******************************************************************************
66 * mozilla::WidgetMouseEventBase
67 ******************************************************************************/
69 class WidgetMouseEventBase : public WidgetInputEvent
71 private:
72 friend class dom::PBrowserParent;
73 friend class dom::PBrowserChild;
75 protected:
76 WidgetMouseEventBase()
80 WidgetMouseEventBase(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
81 EventClassID aEventClassID)
82 : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
83 , button(0)
84 , buttons(0)
85 , pressure(0)
86 , inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
90 public:
91 virtual WidgetMouseEventBase* AsMouseEventBase() MOZ_OVERRIDE { return this; }
93 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
95 MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
96 return nullptr;
99 /// The possible related target
100 nsCOMPtr<nsISupports> relatedTarget;
102 enum buttonType
104 eLeftButton = 0,
105 eMiddleButton = 1,
106 eRightButton = 2
108 // Pressed button ID of mousedown or mouseup event.
109 // This is set only when pressing a button causes the event.
110 int16_t button;
112 enum buttonsFlag {
113 eLeftButtonFlag = 0x01,
114 eRightButtonFlag = 0x02,
115 eMiddleButtonFlag = 0x04,
116 // typicall, "back" button being left side of 5-button
117 // mice, see "buttons" attribute document of DOM3 Events.
118 e4thButtonFlag = 0x08,
119 // typicall, "forward" button being right side of 5-button
120 // mice, see "buttons" attribute document of DOM3 Events.
121 e5thButtonFlag = 0x10
124 // Flags of all pressed buttons at the event fired.
125 // This is set at any mouse event, don't be confused with |button|.
126 int16_t buttons;
128 // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
129 float pressure;
131 // Possible values at nsIDOMMouseEvent
132 uint16_t inputSource;
134 // ID of the canvas HitRegion
135 nsString region;
137 void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
138 bool aCopyTargets)
140 AssignInputEventData(aEvent, aCopyTargets);
142 relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr;
143 button = aEvent.button;
144 buttons = aEvent.buttons;
145 pressure = aEvent.pressure;
146 inputSource = aEvent.inputSource;
150 * Returns true if left click event.
152 bool IsLeftClickEvent() const
154 return message == NS_MOUSE_CLICK && button == eLeftButton;
158 /******************************************************************************
159 * mozilla::WidgetMouseEvent
160 ******************************************************************************/
162 class WidgetMouseEvent : public WidgetMouseEventBase, public WidgetPointerHelper
164 private:
165 friend class mozilla::dom::PBrowserParent;
166 friend class mozilla::dom::PBrowserChild;
168 public:
169 enum reasonType
171 eReal,
172 eSynthesized
175 enum contextType
177 eNormal,
178 eContextMenuKey
181 enum exitType
183 eChild,
184 eTopLevel
187 protected:
188 WidgetMouseEvent()
192 WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
193 EventClassID aEventClassID, reasonType aReason)
194 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID)
195 , acceptActivation(false)
196 , ignoreRootScrollFrame(false)
197 , reason(aReason)
198 , context(eNormal)
199 , exit(eChild)
200 , clickCount(0)
202 switch (aMessage) {
203 case NS_MOUSEENTER:
204 case NS_MOUSELEAVE:
205 mFlags.mBubbles = false;
206 mFlags.mCancelable = false;
207 break;
208 default:
209 break;
213 public:
214 virtual WidgetMouseEvent* AsMouseEvent() MOZ_OVERRIDE { return this; }
216 WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
217 reasonType aReason, contextType aContext = eNormal) :
218 WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass),
219 acceptActivation(false), ignoreRootScrollFrame(false),
220 reason(aReason), context(aContext), exit(eChild), clickCount(0)
222 switch (aMessage) {
223 case NS_MOUSEENTER:
224 case NS_MOUSELEAVE:
225 mFlags.mBubbles = false;
226 mFlags.mCancelable = false;
227 break;
228 case NS_CONTEXTMENU:
229 button = (context == eNormal) ? eRightButton : eLeftButton;
230 break;
231 default:
232 break;
236 #ifdef DEBUG
237 virtual ~WidgetMouseEvent()
239 NS_WARN_IF_FALSE(message != NS_CONTEXTMENU ||
240 button ==
241 ((context == eNormal) ? eRightButton : eLeftButton),
242 "Wrong button set to NS_CONTEXTMENU event?");
244 #endif
246 virtual WidgetEvent* Duplicate() const MOZ_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 =
252 new WidgetMouseEvent(false, message, nullptr, reason, context);
253 result->AssignMouseEventData(*this, true);
254 result->mFlags = mFlags;
255 return result;
258 // Special return code for MOUSE_ACTIVATE to signal.
259 // If the target accepts activation (1), or denies it (0).
260 bool acceptActivation;
261 // Whether the event should ignore scroll frame bounds during dispatch.
262 bool ignoreRootScrollFrame;
264 reasonType reason : 4;
265 contextType context : 4;
266 exitType exit;
268 /// The number of mouse clicks.
269 uint32_t clickCount;
271 void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets)
273 AssignMouseEventBaseData(aEvent, aCopyTargets);
274 AssignPointerHelperData(aEvent);
276 acceptActivation = aEvent.acceptActivation;
277 ignoreRootScrollFrame = aEvent.ignoreRootScrollFrame;
278 clickCount = aEvent.clickCount;
282 * Returns true if the event is a context menu event caused by key.
284 bool IsContextMenuKeyEvent() const
286 return message == NS_CONTEXTMENU && context == eContextMenuKey;
290 * Returns true if the event is a real mouse event. Otherwise, i.e., it's
291 * a synthesized event by scroll or something, returns false.
293 bool IsReal() const
295 return reason == eReal;
299 /******************************************************************************
300 * mozilla::WidgetDragEvent
301 ******************************************************************************/
303 class WidgetDragEvent : public WidgetMouseEvent
305 public:
306 virtual WidgetDragEvent* AsDragEvent() MOZ_OVERRIDE { return this; }
308 WidgetDragEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
309 : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal)
310 , userCancelled(false)
311 , mDefaultPreventedOnContent(false)
313 mFlags.mCancelable =
314 (aMessage != NS_DRAGDROP_EXIT_SYNTH &&
315 aMessage != NS_DRAGDROP_LEAVE_SYNTH &&
316 aMessage != NS_DRAGDROP_END);
319 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
321 MOZ_ASSERT(mClass == eDragEventClass,
322 "Duplicate() must be overridden by sub class");
323 // Not copying widget, it is a weak reference.
324 WidgetDragEvent* result = new WidgetDragEvent(false, message, nullptr);
325 result->AssignDragEventData(*this, true);
326 result->mFlags = mFlags;
327 return result;
330 // The dragging data.
331 nsCOMPtr<dom::DataTransfer> dataTransfer;
333 // If this is true, user has cancelled the drag operation.
334 bool userCancelled;
335 // If this is true, the drag event's preventDefault() is called on content.
336 bool mDefaultPreventedOnContent;
338 // XXX Not tested by test_assign_event_data.html
339 void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets)
341 AssignMouseEventData(aEvent, aCopyTargets);
343 dataTransfer = aEvent.dataTransfer;
344 // XXX userCancelled isn't copied, is this instentionally?
345 userCancelled = false;
346 mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
350 /******************************************************************************
351 * mozilla::WidgetMouseScrollEvent
353 * This is used for legacy DOM mouse scroll events, i.e.,
354 * DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled
355 * by ESM even if widget dispatches them. Use new WidgetWheelEvent instead.
356 ******************************************************************************/
358 class WidgetMouseScrollEvent : public WidgetMouseEventBase
360 private:
361 WidgetMouseScrollEvent()
365 public:
366 virtual WidgetMouseScrollEvent* AsMouseScrollEvent() MOZ_OVERRIDE
368 return this;
371 WidgetMouseScrollEvent(bool aIsTrusted, uint32_t aMessage,
372 nsIWidget* aWidget)
373 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
374 eMouseScrollEventClass)
375 , delta(0)
376 , isHorizontal(false)
380 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
382 MOZ_ASSERT(mClass == eMouseScrollEventClass,
383 "Duplicate() must be overridden by sub class");
384 // Not copying widget, it is a weak reference.
385 WidgetMouseScrollEvent* result =
386 new WidgetMouseScrollEvent(false, message, nullptr);
387 result->AssignMouseScrollEventData(*this, true);
388 result->mFlags = mFlags;
389 return result;
392 // The delta value of mouse scroll event.
393 // If the event message is NS_MOUSE_SCROLL, the value indicates scroll amount
394 // in lines. However, if the value is nsIDOMUIEvent::SCROLL_PAGE_UP or
395 // nsIDOMUIEvent::SCROLL_PAGE_DOWN, the value inducates one page scroll.
396 // If the event message is NS_MOUSE_PIXEL_SCROLL, the value indicates scroll
397 // amount in pixels.
398 int32_t delta;
400 // If this is true, it may cause to scroll horizontally.
401 // Otherwise, vertically.
402 bool isHorizontal;
404 void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
405 bool aCopyTargets)
407 AssignMouseEventBaseData(aEvent, aCopyTargets);
409 delta = aEvent.delta;
410 isHorizontal = aEvent.isHorizontal;
414 /******************************************************************************
415 * mozilla::WidgetWheelEvent
416 ******************************************************************************/
418 class WidgetWheelEvent : public WidgetMouseEventBase
420 private:
421 friend class mozilla::dom::PBrowserParent;
422 friend class mozilla::dom::PBrowserChild;
424 WidgetWheelEvent()
428 public:
429 virtual WidgetWheelEvent* AsWheelEvent() MOZ_OVERRIDE { return this; }
431 WidgetWheelEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget)
432 : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass)
433 , deltaX(0.0)
434 , deltaY(0.0)
435 , deltaZ(0.0)
436 , deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL)
437 , customizedByUserPrefs(false)
438 , isMomentum(false)
439 , mIsNoLineOrPageDelta(false)
440 , lineOrPageDeltaX(0)
441 , lineOrPageDeltaY(0)
442 , scrollType(SCROLL_DEFAULT)
443 , overflowDeltaX(0.0)
444 , overflowDeltaY(0.0)
445 , mViewPortIsOverscrolled(false)
449 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
451 MOZ_ASSERT(mClass == eWheelEventClass,
452 "Duplicate() must be overridden by sub class");
453 // Not copying widget, it is a weak reference.
454 WidgetWheelEvent* result = new WidgetWheelEvent(false, message, nullptr);
455 result->AssignWheelEventData(*this, true);
456 result->mFlags = mFlags;
457 return result;
460 // NOTE: deltaX, deltaY and deltaZ may be customized by
461 // mousewheel.*.delta_multiplier_* prefs which are applied by
462 // EventStateManager. So, after widget dispatches this event,
463 // these delta values may have different values than before.
464 double deltaX;
465 double deltaY;
466 double deltaZ;
468 // Should be one of nsIDOMWheelEvent::DOM_DELTA_*
469 uint32_t deltaMode;
471 // Following members are for internal use only, not for DOM event.
473 // If the delta values are computed from prefs, this value is true.
474 // Otherwise, i.e., they are computed from native events, false.
475 bool customizedByUserPrefs;
477 // true if the event is caused by momentum.
478 bool isMomentum;
480 // If device event handlers don't know when they should set lineOrPageDeltaX
481 // and lineOrPageDeltaY, this is true. Otherwise, false.
482 // If mIsNoLineOrPageDelta is true, ESM will generate NS_MOUSE_SCROLL events
483 // when accumulated delta values reach a line height.
484 bool mIsNoLineOrPageDelta;
486 // If widget sets lineOrPageDelta, EventStateManager will dispatch
487 // NS_MOUSE_SCROLL event for compatibility. Note that the delta value means
488 // pages if the deltaMode is DOM_DELTA_PAGE, otherwise, lines.
489 int32_t lineOrPageDeltaX;
490 int32_t lineOrPageDeltaY;
492 // When the default action for an wheel event is moving history or zooming,
493 // need to chose a delta value for doing it.
494 int32_t GetPreferredIntDelta()
496 if (!lineOrPageDeltaX && !lineOrPageDeltaY) {
497 return 0;
499 if (lineOrPageDeltaY && !lineOrPageDeltaX) {
500 return lineOrPageDeltaY;
502 if (lineOrPageDeltaX && !lineOrPageDeltaY) {
503 return lineOrPageDeltaX;
505 if ((lineOrPageDeltaX < 0 && lineOrPageDeltaY > 0) ||
506 (lineOrPageDeltaX > 0 && lineOrPageDeltaY < 0)) {
507 return 0; // We cannot guess the answer in this case.
509 return (Abs(lineOrPageDeltaX) > Abs(lineOrPageDeltaY)) ?
510 lineOrPageDeltaX : lineOrPageDeltaY;
513 // Scroll type
514 // The default value is SCROLL_DEFAULT, which means EventStateManager will
515 // select preferred scroll type automatically.
516 enum ScrollType
518 SCROLL_DEFAULT,
519 SCROLL_SYNCHRONOUSLY,
520 SCROLL_ASYNCHRONOUSELY,
521 SCROLL_SMOOTHLY
523 ScrollType scrollType;
525 // overflowed delta values for scroll, these values are set by
526 // nsEventStateManger. If the default action of the wheel event isn't scroll,
527 // these values always zero. Otherwise, remaning delta values which are
528 // not used by scroll are set.
529 // NOTE: deltaX, deltaY and deltaZ may be modified by EventStateManager.
530 // However, overflowDeltaX and overflowDeltaY indicate unused original
531 // delta values which are not applied the delta_multiplier prefs.
532 // So, if widget wanted to know the actual direction to be scrolled,
533 // it would need to check the deltaX and deltaY.
534 double overflowDeltaX;
535 double overflowDeltaY;
537 // Whether or not the parent of the currently overscrolled frame is the
538 // ViewPort. This is false in situations when an element on the page is being
539 // overscrolled (such as a text field), but true when the 'page' is being
540 // overscrolled.
541 bool mViewPortIsOverscrolled;
543 void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
545 AssignMouseEventBaseData(aEvent, aCopyTargets);
547 deltaX = aEvent.deltaX;
548 deltaY = aEvent.deltaY;
549 deltaZ = aEvent.deltaZ;
550 deltaMode = aEvent.deltaMode;
551 customizedByUserPrefs = aEvent.customizedByUserPrefs;
552 isMomentum = aEvent.isMomentum;
553 mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
554 lineOrPageDeltaX = aEvent.lineOrPageDeltaX;
555 lineOrPageDeltaY = aEvent.lineOrPageDeltaY;
556 scrollType = aEvent.scrollType;
557 overflowDeltaX = aEvent.overflowDeltaX;
558 overflowDeltaY = aEvent.overflowDeltaY;
559 mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
563 /******************************************************************************
564 * mozilla::WidgetPointerEvent
565 ******************************************************************************/
567 class WidgetPointerEvent : public WidgetMouseEvent
569 friend class mozilla::dom::PBrowserParent;
570 friend class mozilla::dom::PBrowserChild;
572 WidgetPointerEvent()
576 public:
577 virtual WidgetPointerEvent* AsPointerEvent() MOZ_OVERRIDE { return this; }
579 WidgetPointerEvent(bool aIsTrusted, uint32_t aMsg, nsIWidget* w)
580 : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal)
581 , width(0)
582 , height(0)
583 , isPrimary(true)
585 UpdateFlags();
588 explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
589 : WidgetMouseEvent(aEvent)
590 , width(0)
591 , height(0)
592 , isPrimary(true)
594 mClass = ePointerEventClass;
595 UpdateFlags();
598 void UpdateFlags()
600 switch (message) {
601 case NS_POINTER_ENTER:
602 case NS_POINTER_LEAVE:
603 mFlags.mBubbles = false;
604 mFlags.mCancelable = false;
605 break;
606 case NS_POINTER_CANCEL:
607 case NS_POINTER_GOT_CAPTURE:
608 case NS_POINTER_LOST_CAPTURE:
609 mFlags.mCancelable = false;
610 break;
611 default:
612 break;
616 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
618 MOZ_ASSERT(mClass == ePointerEventClass,
619 "Duplicate() must be overridden by sub class");
620 // Not copying widget, it is a weak reference.
621 WidgetPointerEvent* result =
622 new WidgetPointerEvent(false, message, nullptr);
623 result->AssignPointerEventData(*this, true);
624 result->mFlags = mFlags;
625 return result;
628 uint32_t width;
629 uint32_t height;
630 bool isPrimary;
632 // XXX Not tested by test_assign_event_data.html
633 void AssignPointerEventData(const WidgetPointerEvent& aEvent,
634 bool aCopyTargets)
636 AssignMouseEventData(aEvent, aCopyTargets);
638 width = aEvent.width;
639 height = aEvent.height;
640 isPrimary = aEvent.isPrimary;
644 } // namespace mozilla
646 #endif // mozilla_MouseEvents_h__