From 29aa65403986ab1fa37ec58d57be9199bd77c598 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Sun, 12 Aug 2012 10:42:36 +0900 Subject: [PATCH] Bug 719320 part.9 Implement nsIDOMWindowUtils::sendWheelEvent() for tests r=smaug, sr=jst --- dom/base/nsDOMWindowUtils.cpp | 68 ++++++++------- dom/interfaces/base/nsIDOMWindowUtils.idl | 54 +++++++----- .../mochitest/tests/SimpleTest/EventUtils.js | 83 +++++++++---------- .../tests/test_sanityEventUtils.html | 4 +- 4 files changed, 116 insertions(+), 93 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 03054cf2748..8014122c340 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -583,13 +583,16 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType, } NS_IMETHODIMP -nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType, - float aX, - float aY, - PRInt32 aButton, - PRInt32 aScrollFlags, - PRInt32 aDelta, - PRInt32 aModifiers) +nsDOMWindowUtils::SendWheelEvent(float aX, + float aY, + double aDeltaX, + double aDeltaY, + double aDeltaZ, + PRUint32 aDeltaMode, + PRInt32 aModifiers, + PRInt32 aLineOrPageDeltaX, + PRInt32 aLineOrPageDeltaY, + PRUint32 aOptions) { if (!IsUniversalXPConnectCapable()) { return NS_ERROR_DOM_SECURITY_ERR; @@ -598,37 +601,46 @@ nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType, // get the widget to send the event to nsPoint offset; nsCOMPtr widget = GetWidget(&offset); - if (!widget) + if (!widget) { return NS_ERROR_NULL_POINTER; + } - PRInt32 msg; - if (aType.EqualsLiteral("DOMMouseScroll")) - msg = NS_MOUSE_SCROLL; - else if (aType.EqualsLiteral("MozMousePixelScroll")) - msg = NS_MOUSE_PIXEL_SCROLL; - else - return NS_ERROR_UNEXPECTED; + widget::WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, widget); + wheelEvent.modifiers = GetWidgetModifiers(aModifiers); + wheelEvent.deltaX = aDeltaX; + wheelEvent.deltaY = aDeltaY; + wheelEvent.deltaZ = aDeltaZ; + wheelEvent.deltaMode = aDeltaMode; + wheelEvent.isMomentum = + (aOptions & WHEEL_EVENT_CAUSED_BY_MOMENTUM) != 0; + wheelEvent.isPixelOnlyDevice = + (aOptions & WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE) != 0; + NS_ENSURE_TRUE( + !wheelEvent.isPixelOnlyDevice || + aDeltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL, + NS_ERROR_INVALID_ARG); + wheelEvent.customizedByUserPrefs = + (aOptions & WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS) != 0; + wheelEvent.lineOrPageDeltaX = aLineOrPageDeltaX; + wheelEvent.lineOrPageDeltaY = aLineOrPageDeltaY; + wheelEvent.widget = widget; - nsMouseScrollEvent event(true, msg, widget); - event.modifiers = GetWidgetModifiers(aModifiers); - event.button = aButton; - event.widget = widget; - event.delta = aDelta; - event.scrollFlags = aScrollFlags; - - event.time = PR_IntervalNow(); + wheelEvent.time = PR_Now() / 1000; nsPresContext* presContext = GetPresContext(); - if (!presContext) - return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE); - event.refPoint = ToWidgetPoint(aX, aY, offset, presContext); + wheelEvent.refPoint = ToWidgetPoint(aX, aY, offset, presContext); nsEventStatus status; - return widget->DispatchEvent(&event, status); + nsresult rv = widget->DispatchEvent(&wheelEvent, status); + NS_ENSURE_SUCCESS(rv, rv); + // ESM must not return negative values for overflow. + NS_ENSURE_TRUE(wheelEvent.overflowDeltaX >= 0.0, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(wheelEvent.overflowDeltaY >= 0.0, NS_ERROR_FAILURE); + return rv; } - NS_IMETHODIMP nsDOMWindowUtils::SendTouchEvent(const nsAString& aType, PRUint32 *aIdentifiers, diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 3eab8a8e0d0..56ee2c71e0f 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -40,7 +40,7 @@ interface nsIDOMTouch; interface nsIDOMClientRect; interface mozIDOMApplication; -[scriptable, uuid(b276a71e-21ee-4be6-894d-4039523e1ad8)] +[scriptable, uuid(97548ee0-9def-421a-ab2a-c6c98efa9a3c)] interface nsIDOMWindowUtils : nsISupports { /** @@ -275,10 +275,8 @@ interface nsIDOMWindowUtils : nsISupports { in long aModifiers, [optional] in boolean aIgnoreRootScrollFrame); - /** Synthesize a mouse scroll event for a window. The event types supported - * are: - * DOMMouseScroll - * MozMousePixelScroll + /** Synthesize a wheel event for a window. The event types supported is only + * wheel. * * Events are sent in coordinates offset by aX and aY from the window. * @@ -286,22 +284,38 @@ interface nsIDOMWindowUtils : nsISupports { * Will throw a DOM security error if called without UniversalXPConnect * privileges. * - * @param aType event type - * @param aX x offset in CSS pixels - * @param aY y offset in CSS pixels - * @param aButton button to synthesize - * @param aScrollFlags flag bits --- see nsMouseScrollFlags in nsGUIEvent.h - * @param aDelta the direction and amount to scroll (in lines or pixels, - * depending on the event type) - * @param aModifiers modifiers pressed, using constants defined as MODIFIER_* + * @param aX x offset in CSS pixels + * @param aY y offset in CSS pixels + * @param aDeltaX deltaX value. + * @param aDeltaY deltaY value. + * @param aDeltaZ deltaZ value. + * @param aDeltaMode deltaMode value which must be one of + * nsIDOMWheelEvent::DOM_DELTA_*. + * @param aModifiers modifiers pressed, using constants defined as + * MODIFIER_* + * @param aLineOrPageDeltaX If you set this value non-zero for + * DOM_DELTA_PIXEL event, nsEventStateManager will + * dispatch NS_MOUSE_SCROLL event for horizontal + * scroll. + * @param aLineOrPageDeltaY If you set this value non-zero for + * DOM_DELTA_PIXEL event, nsEventStateManager will + * dispatch NS_MOUSE_SCROLL event for vertical + * scroll. + * @param aOptions Set following flags. */ - void sendMouseScrollEvent(in AString aType, - in float aX, - in float aY, - in long aButton, - in long aScrollFlags, - in long aDelta, - in long aModifiers); + const unsigned long WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE = 0x0001; + const unsigned long WHEEL_EVENT_CAUSED_BY_MOMENTUM = 0x0002; + const unsigned long WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS = 0x0004; + void sendWheelEvent(in float aX, + in float aY, + in double aDeltaX, + in double aDeltaY, + in double aDeltaZ, + in unsigned long aDeltaMode, + in long aModifiers, + in long aLineOrPageDeltaX, + in long aLineOrPageDeltaY, + in unsigned long aOptions); /** * Synthesize a key event to the window. The event types supported are: diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index 4e0539b93ac..225f6e32956 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -7,7 +7,7 @@ * sendKey * synthesizeMouse * synthesizeMouseAtCenter - * synthesizeMouseScroll + * synthesizeWheel * synthesizeKey * synthesizeMouseExpectEvent * synthesizeKeyExpectEvent @@ -248,60 +248,57 @@ function synthesizeTouchAtCenter(aTarget, aEvent, aWindow) synthesizeTouch(aTarget, rect.width / 2, rect.height / 2, aEvent, aWindow); } + /** - * Synthesize a mouse scroll event on a target. The actual client point is determined + * Synthesize a wheel event on a target. The actual client point is determined * by taking the aTarget's client box and offseting it by aOffsetX and * aOffsetY. * * aEvent is an object which may contain the properties: - * shiftKey, ctrlKey, altKey, metaKey, accessKey, button, type, axis, delta, hasPixels + * shiftKey, ctrlKey, altKey, metaKey, accessKey, deltaX, deltaY, deltaZ, + * deltaMode, lineOrPageDeltaX, lineOrPageDeltaY, isMomentum, isPixelOnlyDevice, + * isCustomizedByPrefs * - * If the type is specified, a mouse scroll event of that type is fired. Otherwise, - * "DOMMouseScroll" is used. - * - * If the axis is specified, it must be one of "horizontal" or "vertical". If not specified, - * "vertical" is used. - * - * 'delta' is the amount to scroll by (can be positive or negative). It must - * be specified. - * - * 'hasPixels' specifies whether kHasPixels should be set in the scrollFlags. - * - * 'isMomentum' specifies whether kIsMomentum should be set in the scrollFlags. + * deltaMode must be defined, others are ok even if undefined. * * aWindow is optional, and defaults to the current window object. */ -function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) +function synthesizeWheel(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) { var utils = _getDOMWindowUtils(aWindow); - - if (utils) { - // See nsMouseScrollFlags in nsGUIEvent.h - const kIsVertical = 0x02; - const kIsHorizontal = 0x04; - const kHasPixels = 0x08; - const kIsMomentum = 0x40; - - var button = aEvent.button || 0; - var modifiers = _parseModifiers(aEvent); - - var rect = aTarget.getBoundingClientRect(); - - var left = rect.left; - var top = rect.top; - - var type = (("type" in aEvent) && aEvent.type) || "DOMMouseScroll"; - var axis = aEvent.axis || "vertical"; - var scrollFlags = (axis == "horizontal") ? kIsHorizontal : kIsVertical; - if (aEvent.hasPixels) { - scrollFlags |= kHasPixels; - } - if (aEvent.isMomentum) { - scrollFlags |= kIsMomentum; - } - utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button, - scrollFlags, aEvent.delta, modifiers); + if (!utils) { + return; } + + var modifiers = _parseModifiers(aEvent); + var options = 0; + if (aEvent.isPixelOnlyDevice && + (aEvent.deltaMode == WheelEvent.DOM_DELTA_PIXEL)) { + options |= utils.WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE; + } + if (aEvent.isMomentum) { + options |= utils.WHEEL_EVENT_CAUSED_BY_MOMENTUM; + } + if (aEvent.isCustomizedByPrefs) { + options |= utils.WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS; + } + var isPixelOnlyDevice = + aEvent.isPixelOnlyDevice && aEvent.deltaMode == WheelEvent.DOM_DELTA_PIXEL; + var lineOrPageDeltaX = + aEvent.lineOrPageDeltaX != null ? aEvent.lineOrPageDeltaX : + aEvent.deltaX > 0 ? Math.floor(aEvent.deltaX) : + Math.ceil(aEvent.deltaX); + var lineOrPageDeltaY = + aEvent.lineOrPageDeltaY != null ? aEvent.lineOrPageDeltaY : + aEvent.deltaY > 0 ? Math.floor(aEvent.deltaY) : + Math.ceil(aEvent.deltaY); + var rect = aTarget.getBoundingClientRect(); + utils.sendWheelEvent(rect.left + aOffsetX, rect.top + aOffsetY, + aEvent.deltaX ? aEvent.deltaX : 0.0, + aEvent.deltaY ? aEvent.deltaY : 0.0, + aEvent.deltaZ ? aEvent.deltaZ : 0.0, + aEvent.deltaMode, modifiers, + lineOrPageDeltaX, lineOrPageDeltaY, options); } function _computeKeyCodeFromChar(aChar) diff --git a/testing/mochitest/tests/test_sanityEventUtils.html b/testing/mochitest/tests/test_sanityEventUtils.html index 32e212b1a0c..57a7522e835 100644 --- a/testing/mochitest/tests/test_sanityEventUtils.html +++ b/testing/mochitest/tests/test_sanityEventUtils.html @@ -91,13 +91,13 @@ function starttest() { $("textBoxA").focus(); /** - * TODO: testing synthesizeMouseScroll requires a setTimeout + * TODO: testing synthesizeWheel requires a setTimeout * since there is delay between the scroll event and a check, so for now just test * that we can successfully call it to avoid having setTimeout vary the runtime metric. * Testing of this method is currently done here: * toolkit/content/tests/chrome/test_mousescroll.xul */ - synthesizeMouseScroll($("scrollB"), 5, 5, {'delta': 10, 'type': "DOMMouseScroll"}); + synthesizeWheel($("scrollB"), 5, 5, {'deltaY': 10.0, deltaMode: WheelEvent.DOM_DELTA_LINE}); /* test synthesizeKey* */ check = false;