Bug 719320 part.9 Implement nsIDOMWindowUtils::sendWheelEvent() for tests r=smaug, sr=jst

This commit is contained in:
Masayuki Nakano 2012-08-12 10:42:36 +09:00
parent f666bb683a
commit 29aa654039
4 changed files with 116 additions and 93 deletions

View File

@ -583,13 +583,16 @@ nsDOMWindowUtils::SendMouseEventCommon(const nsAString& aType,
}
NS_IMETHODIMP
nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType,
float aX,
nsDOMWindowUtils::SendWheelEvent(float aX,
float aY,
PRInt32 aButton,
PRInt32 aScrollFlags,
PRInt32 aDelta,
PRInt32 aModifiers)
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,36 +601,45 @@ nsDOMWindowUtils::SendMouseScrollEvent(const nsAString& aType,
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> 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;
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();
nsPresContext* presContext = GetPresContext();
if (!presContext)
return NS_ERROR_FAILURE;
event.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
nsEventStatus status;
return widget->DispatchEvent(&event, status);
}
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;
wheelEvent.time = PR_Now() / 1000;
nsPresContext* presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
wheelEvent.refPoint = ToWidgetPoint(aX, aY, offset, presContext);
nsEventStatus 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,

View File

@ -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 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,
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 long aButton,
in long aScrollFlags,
in long aDelta,
in long aModifiers);
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:

View File

@ -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) {
return;
}
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;
var options = 0;
if (aEvent.isPixelOnlyDevice &&
(aEvent.deltaMode == WheelEvent.DOM_DELTA_PIXEL)) {
options |= utils.WHEEL_EVENT_CAUSED_BY_PIXEL_ONLY_DEVICE;
}
if (aEvent.isMomentum) {
scrollFlags |= kIsMomentum;
options |= utils.WHEEL_EVENT_CAUSED_BY_MOMENTUM;
}
utils.sendMouseScrollEvent(type, left + aOffsetX, top + aOffsetY, button,
scrollFlags, aEvent.delta, modifiers);
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)

View File

@ -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;