Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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
23 {
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
30 };
32 namespace mozilla {
34 namespace dom {
35 class PBrowserParent;
36 class PBrowserChild;
37 } // namespace dom
39 /******************************************************************************
40 * mozilla::WidgetPointerHelper
41 ******************************************************************************/
43 class WidgetPointerHelper
44 {
45 public:
46 bool convertToPointer;
47 uint32_t pointerId;
48 uint32_t tiltX;
49 uint32_t tiltY;
51 WidgetPointerHelper() : convertToPointer(true), pointerId(0), tiltX(0), tiltY(0) {}
53 void AssignPointerHelperData(const WidgetPointerHelper& aEvent)
54 {
55 convertToPointer = aEvent.convertToPointer;
56 pointerId = aEvent.pointerId;
57 tiltX = aEvent.tiltX;
58 tiltY = aEvent.tiltY;
59 }
60 };
62 /******************************************************************************
63 * mozilla::WidgetMouseEventBase
64 ******************************************************************************/
66 class WidgetMouseEventBase : public WidgetInputEvent
67 {
68 private:
69 friend class dom::PBrowserParent;
70 friend class dom::PBrowserChild;
72 protected:
73 WidgetMouseEventBase()
74 {
75 }
77 WidgetMouseEventBase(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
78 nsEventStructType aStructType) :
79 WidgetInputEvent(aIsTrusted, aMessage, aWidget, aStructType),
80 button(0), buttons(0), pressure(0),
81 inputSource(nsIDOMMouseEvent::MOZ_SOURCE_MOUSE)
82 {
83 }
85 public:
86 virtual WidgetMouseEventBase* AsMouseEventBase() MOZ_OVERRIDE { return this; }
88 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
89 {
90 MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
91 return nullptr;
92 }
94 /// The possible related target
95 nsCOMPtr<nsISupports> relatedTarget;
97 enum buttonType
98 {
99 eLeftButton = 0,
100 eMiddleButton = 1,
101 eRightButton = 2
102 };
103 // Pressed button ID of mousedown or mouseup event.
104 // This is set only when pressing a button causes the event.
105 int16_t button;
107 enum buttonsFlag {
108 eLeftButtonFlag = 0x01,
109 eRightButtonFlag = 0x02,
110 eMiddleButtonFlag = 0x04,
111 // typicall, "back" button being left side of 5-button
112 // mice, see "buttons" attribute document of DOM3 Events.
113 e4thButtonFlag = 0x08,
114 // typicall, "forward" button being right side of 5-button
115 // mice, see "buttons" attribute document of DOM3 Events.
116 e5thButtonFlag = 0x10
117 };
119 // Flags of all pressed buttons at the event fired.
120 // This is set at any mouse event, don't be confused with |button|.
121 int16_t buttons;
123 // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
124 float pressure;
126 // Possible values at nsIDOMMouseEvent
127 uint16_t inputSource;
129 void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
130 bool aCopyTargets)
131 {
132 AssignInputEventData(aEvent, aCopyTargets);
134 relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr;
135 button = aEvent.button;
136 buttons = aEvent.buttons;
137 pressure = aEvent.pressure;
138 inputSource = aEvent.inputSource;
139 }
141 /**
142 * Returns true if left click event.
143 */
144 bool IsLeftClickEvent() const
145 {
146 return message == NS_MOUSE_CLICK && button == eLeftButton;
147 }
148 };
150 /******************************************************************************
151 * mozilla::WidgetMouseEvent
152 ******************************************************************************/
154 class WidgetMouseEvent : public WidgetMouseEventBase, public WidgetPointerHelper
155 {
156 private:
157 friend class mozilla::dom::PBrowserParent;
158 friend class mozilla::dom::PBrowserChild;
160 public:
161 enum reasonType
162 {
163 eReal,
164 eSynthesized
165 };
167 enum contextType
168 {
169 eNormal,
170 eContextMenuKey
171 };
173 enum exitType
174 {
175 eChild,
176 eTopLevel
177 };
179 protected:
180 WidgetMouseEvent()
181 {
182 }
184 WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
185 nsEventStructType aStructType, reasonType aReason) :
186 WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aStructType),
187 acceptActivation(false), ignoreRootScrollFrame(false),
188 reason(aReason), context(eNormal), exit(eChild), clickCount(0)
189 {
190 switch (aMessage) {
191 case NS_MOUSEENTER:
192 case NS_MOUSELEAVE:
193 mFlags.mBubbles = false;
194 mFlags.mCancelable = false;
195 break;
196 default:
197 break;
198 }
199 }
201 public:
202 virtual WidgetMouseEvent* AsMouseEvent() MOZ_OVERRIDE { return this; }
204 WidgetMouseEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget,
205 reasonType aReason, contextType aContext = eNormal) :
206 WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_EVENT),
207 acceptActivation(false), ignoreRootScrollFrame(false),
208 reason(aReason), context(aContext), exit(eChild), clickCount(0)
209 {
210 switch (aMessage) {
211 case NS_MOUSEENTER:
212 case NS_MOUSELEAVE:
213 mFlags.mBubbles = false;
214 mFlags.mCancelable = false;
215 break;
216 case NS_CONTEXTMENU:
217 button = (context == eNormal) ? eRightButton : eLeftButton;
218 break;
219 default:
220 break;
221 }
222 }
224 #ifdef DEBUG
225 virtual ~WidgetMouseEvent()
226 {
227 NS_WARN_IF_FALSE(message != NS_CONTEXTMENU ||
228 button ==
229 ((context == eNormal) ? eRightButton : eLeftButton),
230 "Wrong button set to NS_CONTEXTMENU event?");
231 }
232 #endif
234 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
235 {
236 MOZ_ASSERT(eventStructType == NS_MOUSE_EVENT,
237 "Duplicate() must be overridden by sub class");
238 // Not copying widget, it is a weak reference.
239 WidgetMouseEvent* result =
240 new WidgetMouseEvent(false, message, nullptr, reason, context);
241 result->AssignMouseEventData(*this, true);
242 result->mFlags = mFlags;
243 return result;
244 }
246 // Special return code for MOUSE_ACTIVATE to signal.
247 // If the target accepts activation (1), or denies it (0).
248 bool acceptActivation;
249 // Whether the event should ignore scroll frame bounds during dispatch.
250 bool ignoreRootScrollFrame;
252 reasonType reason : 4;
253 contextType context : 4;
254 exitType exit;
256 /// The number of mouse clicks.
257 uint32_t clickCount;
259 void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets)
260 {
261 AssignMouseEventBaseData(aEvent, aCopyTargets);
262 AssignPointerHelperData(aEvent);
264 acceptActivation = aEvent.acceptActivation;
265 ignoreRootScrollFrame = aEvent.ignoreRootScrollFrame;
266 clickCount = aEvent.clickCount;
267 }
269 /**
270 * Returns true if the event is a context menu event caused by key.
271 */
272 bool IsContextMenuKeyEvent() const
273 {
274 return message == NS_CONTEXTMENU && context == eContextMenuKey;
275 }
277 /**
278 * Returns true if the event is a real mouse event. Otherwise, i.e., it's
279 * a synthesized event by scroll or something, returns false.
280 */
281 bool IsReal() const
282 {
283 return reason == eReal;
284 }
285 };
287 /******************************************************************************
288 * mozilla::WidgetDragEvent
289 ******************************************************************************/
291 class WidgetDragEvent : public WidgetMouseEvent
292 {
293 public:
294 virtual WidgetDragEvent* AsDragEvent() MOZ_OVERRIDE { return this; }
296 WidgetDragEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
297 WidgetMouseEvent(aIsTrusted, aMessage, aWidget, NS_DRAG_EVENT, eReal),
298 userCancelled(false), mDefaultPreventedOnContent(false)
299 {
300 mFlags.mCancelable =
301 (aMessage != NS_DRAGDROP_EXIT_SYNTH &&
302 aMessage != NS_DRAGDROP_LEAVE_SYNTH &&
303 aMessage != NS_DRAGDROP_END);
304 }
306 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
307 {
308 MOZ_ASSERT(eventStructType == NS_DRAG_EVENT,
309 "Duplicate() must be overridden by sub class");
310 // Not copying widget, it is a weak reference.
311 WidgetDragEvent* result = new WidgetDragEvent(false, message, nullptr);
312 result->AssignDragEventData(*this, true);
313 result->mFlags = mFlags;
314 return result;
315 }
317 // The dragging data.
318 nsCOMPtr<dom::DataTransfer> dataTransfer;
320 // If this is true, user has cancelled the drag operation.
321 bool userCancelled;
322 // If this is true, the drag event's preventDefault() is called on content.
323 bool mDefaultPreventedOnContent;
325 // XXX Not tested by test_assign_event_data.html
326 void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets)
327 {
328 AssignMouseEventData(aEvent, aCopyTargets);
330 dataTransfer = aEvent.dataTransfer;
331 // XXX userCancelled isn't copied, is this instentionally?
332 userCancelled = false;
333 mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
334 }
335 };
337 /******************************************************************************
338 * mozilla::WidgetMouseScrollEvent
339 *
340 * This is used for legacy DOM mouse scroll events, i.e.,
341 * DOMMouseScroll and MozMousePixelScroll event. These events are NOT hanbled
342 * by ESM even if widget dispatches them. Use new WidgetWheelEvent instead.
343 ******************************************************************************/
345 class WidgetMouseScrollEvent : public WidgetMouseEventBase
346 {
347 private:
348 WidgetMouseScrollEvent()
349 {
350 }
352 public:
353 virtual WidgetMouseScrollEvent* AsMouseScrollEvent() MOZ_OVERRIDE
354 {
355 return this;
356 }
358 WidgetMouseScrollEvent(bool aIsTrusted, uint32_t aMessage,
359 nsIWidget* aWidget) :
360 WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_MOUSE_SCROLL_EVENT),
361 delta(0), isHorizontal(false)
362 {
363 }
365 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
366 {
367 MOZ_ASSERT(eventStructType == NS_MOUSE_SCROLL_EVENT,
368 "Duplicate() must be overridden by sub class");
369 // Not copying widget, it is a weak reference.
370 WidgetMouseScrollEvent* result =
371 new WidgetMouseScrollEvent(false, message, nullptr);
372 result->AssignMouseScrollEventData(*this, true);
373 result->mFlags = mFlags;
374 return result;
375 }
377 // The delta value of mouse scroll event.
378 // If the event message is NS_MOUSE_SCROLL, the value indicates scroll amount
379 // in lines. However, if the value is nsIDOMUIEvent::SCROLL_PAGE_UP or
380 // nsIDOMUIEvent::SCROLL_PAGE_DOWN, the value inducates one page scroll.
381 // If the event message is NS_MOUSE_PIXEL_SCROLL, the value indicates scroll
382 // amount in pixels.
383 int32_t delta;
385 // If this is true, it may cause to scroll horizontally.
386 // Otherwise, vertically.
387 bool isHorizontal;
389 void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
390 bool aCopyTargets)
391 {
392 AssignMouseEventBaseData(aEvent, aCopyTargets);
394 delta = aEvent.delta;
395 isHorizontal = aEvent.isHorizontal;
396 }
397 };
399 /******************************************************************************
400 * mozilla::WidgetWheelEvent
401 ******************************************************************************/
403 class WidgetWheelEvent : public WidgetMouseEventBase
404 {
405 private:
406 friend class mozilla::dom::PBrowserParent;
407 friend class mozilla::dom::PBrowserChild;
409 WidgetWheelEvent()
410 {
411 }
413 public:
414 virtual WidgetWheelEvent* AsWheelEvent() MOZ_OVERRIDE { return this; }
416 WidgetWheelEvent(bool aIsTrusted, uint32_t aMessage, nsIWidget* aWidget) :
417 WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, NS_WHEEL_EVENT),
418 deltaX(0.0), deltaY(0.0), deltaZ(0.0),
419 deltaMode(nsIDOMWheelEvent::DOM_DELTA_PIXEL),
420 customizedByUserPrefs(false), isMomentum(false), isPixelOnlyDevice(false),
421 lineOrPageDeltaX(0), lineOrPageDeltaY(0), scrollType(SCROLL_DEFAULT),
422 overflowDeltaX(0.0), overflowDeltaY(0.0),
423 mViewPortIsOverscrolled(false)
424 {
425 }
427 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
428 {
429 MOZ_ASSERT(eventStructType == NS_WHEEL_EVENT,
430 "Duplicate() must be overridden by sub class");
431 // Not copying widget, it is a weak reference.
432 WidgetWheelEvent* result = new WidgetWheelEvent(false, message, nullptr);
433 result->AssignWheelEventData(*this, true);
434 result->mFlags = mFlags;
435 return result;
436 }
438 // NOTE: deltaX, deltaY and deltaZ may be customized by
439 // mousewheel.*.delta_multiplier_* prefs which are applied by
440 // EventStateManager. So, after widget dispatches this event,
441 // these delta values may have different values than before.
442 double deltaX;
443 double deltaY;
444 double deltaZ;
446 // Should be one of nsIDOMWheelEvent::DOM_DELTA_*
447 uint32_t deltaMode;
449 // Following members are for internal use only, not for DOM event.
451 // If the delta values are computed from prefs, this value is true.
452 // Otherwise, i.e., they are computed from native events, false.
453 bool customizedByUserPrefs;
455 // true if the event is caused by momentum.
456 bool isMomentum;
458 // If device event handlers don't know when they should set lineOrPageDeltaX
459 // and lineOrPageDeltaY, this is true. Otherwise, false.
460 // If isPixelOnlyDevice is true, ESM will generate NS_MOUSE_SCROLL events
461 // when accumulated pixel delta values reach a line height.
462 bool isPixelOnlyDevice;
464 // If widget sets lineOrPageDelta, EventStateManager will dispatch
465 // NS_MOUSE_SCROLL event for compatibility. Note that the delta value means
466 // pages if the deltaMode is DOM_DELTA_PAGE, otherwise, lines.
467 int32_t lineOrPageDeltaX;
468 int32_t lineOrPageDeltaY;
470 // When the default action for an wheel event is moving history or zooming,
471 // need to chose a delta value for doing it.
472 int32_t GetPreferredIntDelta()
473 {
474 if (!lineOrPageDeltaX && !lineOrPageDeltaY) {
475 return 0;
476 }
477 if (lineOrPageDeltaY && !lineOrPageDeltaX) {
478 return lineOrPageDeltaY;
479 }
480 if (lineOrPageDeltaX && !lineOrPageDeltaY) {
481 return lineOrPageDeltaX;
482 }
483 if ((lineOrPageDeltaX < 0 && lineOrPageDeltaY > 0) ||
484 (lineOrPageDeltaX > 0 && lineOrPageDeltaY < 0)) {
485 return 0; // We cannot guess the answer in this case.
486 }
487 return (Abs(lineOrPageDeltaX) > Abs(lineOrPageDeltaY)) ?
488 lineOrPageDeltaX : lineOrPageDeltaY;
489 }
491 // Scroll type
492 // The default value is SCROLL_DEFAULT, which means EventStateManager will
493 // select preferred scroll type automatically.
494 enum ScrollType
495 {
496 SCROLL_DEFAULT,
497 SCROLL_SYNCHRONOUSLY,
498 SCROLL_ASYNCHRONOUSELY,
499 SCROLL_SMOOTHLY
500 };
501 ScrollType scrollType;
503 // overflowed delta values for scroll, these values are set by
504 // nsEventStateManger. If the default action of the wheel event isn't scroll,
505 // these values always zero. Otherwise, remaning delta values which are
506 // not used by scroll are set.
507 // NOTE: deltaX, deltaY and deltaZ may be modified by EventStateManager.
508 // However, overflowDeltaX and overflowDeltaY indicate unused original
509 // delta values which are not applied the delta_multiplier prefs.
510 // So, if widget wanted to know the actual direction to be scrolled,
511 // it would need to check the deltaX and deltaY.
512 double overflowDeltaX;
513 double overflowDeltaY;
515 // Whether or not the parent of the currently overscrolled frame is the
516 // ViewPort. This is false in situations when an element on the page is being
517 // overscrolled (such as a text field), but true when the 'page' is being
518 // overscrolled.
519 bool mViewPortIsOverscrolled;
521 void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets)
522 {
523 AssignMouseEventBaseData(aEvent, aCopyTargets);
525 deltaX = aEvent.deltaX;
526 deltaY = aEvent.deltaY;
527 deltaZ = aEvent.deltaZ;
528 deltaMode = aEvent.deltaMode;
529 customizedByUserPrefs = aEvent.customizedByUserPrefs;
530 isMomentum = aEvent.isMomentum;
531 isPixelOnlyDevice = aEvent.isPixelOnlyDevice;
532 lineOrPageDeltaX = aEvent.lineOrPageDeltaX;
533 lineOrPageDeltaY = aEvent.lineOrPageDeltaY;
534 scrollType = aEvent.scrollType;
535 overflowDeltaX = aEvent.overflowDeltaX;
536 overflowDeltaY = aEvent.overflowDeltaY;
537 mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
538 }
539 };
541 /******************************************************************************
542 * mozilla::WidgetPointerEvent
543 ******************************************************************************/
545 class WidgetPointerEvent : public WidgetMouseEvent
546 {
547 friend class mozilla::dom::PBrowserParent;
548 friend class mozilla::dom::PBrowserChild;
550 WidgetPointerEvent()
551 {
552 }
554 public:
555 virtual WidgetPointerEvent* AsPointerEvent() MOZ_OVERRIDE { return this; }
557 WidgetPointerEvent(bool aIsTrusted, uint32_t aMsg, nsIWidget* w)
558 : WidgetMouseEvent(aIsTrusted, aMsg, w, NS_POINTER_EVENT, eReal)
559 , width(0)
560 , height(0)
561 , isPrimary(true)
562 {
563 UpdateFlags();
564 }
566 WidgetPointerEvent(const WidgetMouseEvent& aEvent)
567 : WidgetMouseEvent(aEvent)
568 , width(0)
569 , height(0)
570 , isPrimary(true)
571 {
572 eventStructType = NS_POINTER_EVENT;
573 UpdateFlags();
574 }
576 void UpdateFlags()
577 {
578 switch (message) {
579 case NS_POINTER_ENTER:
580 case NS_POINTER_LEAVE:
581 mFlags.mBubbles = false;
582 mFlags.mCancelable = false;
583 break;
584 case NS_POINTER_CANCEL:
585 case NS_POINTER_GOT_CAPTURE:
586 case NS_POINTER_LOST_CAPTURE:
587 mFlags.mCancelable = false;
588 break;
589 default:
590 break;
591 }
592 }
594 virtual WidgetEvent* Duplicate() const MOZ_OVERRIDE
595 {
596 MOZ_ASSERT(eventStructType == NS_POINTER_EVENT,
597 "Duplicate() must be overridden by sub class");
598 // Not copying widget, it is a weak reference.
599 WidgetPointerEvent* result =
600 new WidgetPointerEvent(false, message, nullptr);
601 result->AssignPointerEventData(*this, true);
602 result->mFlags = mFlags;
603 return result;
604 }
606 uint32_t width;
607 uint32_t height;
608 bool isPrimary;
610 // XXX Not tested by test_assign_event_data.html
611 void AssignPointerEventData(const WidgetPointerEvent& aEvent,
612 bool aCopyTargets)
613 {
614 AssignMouseEventData(aEvent, aCopyTargets);
616 width = aEvent.width;
617 height = aEvent.height;
618 isPrimary = aEvent.isPrimary;
619 }
620 };
622 } // namespace mozilla
624 #endif // mozilla_MouseEvents_h__