Skip to content
Permalink
Browse files
WebCore: Add the capability to create and dispatch a WheelEvent in Ja…
…vaScript.

Ensure the event's default handler is triggered in the same way as it is
during a PlatformWheelEvent.

Patch by Andy Estes <aestes@apple.com> on 2010-03-02
Reviewed by Maciej Stachowiak.

https://bugs.webkit.org/show_bug.cgi?id=35566

Test: fast/events/wheelevent-in-scrolling-div.html

* dom/Node.cpp: Ensure that the default behavior (scrolling) occurs for
wheel events originating both from the platform and from
JavaScript/ObjC.
(WebCore::Node::dispatchWheelEvent): Instantiate new WheelEvent with
the graunularity of the PlatformWheelEvent.
(WebCore::Node::defaultEventHandler): Add support for mousewheel events.
* dom/WheelEvent.cpp: Add three new member variables: m_deltaX, m_deltaY
and m_granularity.  m_deltaX and m_deltaY differ from m_wheelDeltaX and
m_wheelDeltaY, which are the number of wheel ticks multiplied by 120 for
IE compatibility.
(WebCore::WheelEvent::WheelEvent): Initialize new member variables.
(WebCore::WheelEvent::initWheelEvent): Same.
(WebCore::WheelEvent::initWebKitWheelEvent): Same.
* dom/WheelEvent.h: See WheelEvent.cpp.
(WebCore::WheelEvent::): Add Granularity enum (Pixel, Line, Page).
(WebCore::WheelEvent::create): Add new arguments.
(WebCore::WheelEvent::deltaX): Amount of scroll in x direction.
(WebCore::WheelEvent::deltaY): Amount of scroll in y direction.
(WebCore::WheelEvent::granularity): Units of deltaX and deltaY.
* dom/WheelEvent.idl: Add initWebKitWheelEvent() to JavaScript.  This is
the same as the initWheelEvent ObjC method.  As the DOM Level 3 Events
specification is still a working draft and subject to change, prefix
'WebKit' to the method signature to indicate experimental support.
* page/EventHandler.cpp: Move the scroll handling from
handleWheelEvent() to defaultWheelEventHandler(), which is executed on
both PlatformWheelEvents and JavaScript WheelEvents.
(WebCore::scrollNode): Renamed from scrollAndAcceptEvent().  Remove
the PlatformWheelEvent from the argument list and instead return a
boolean indicating if the scroll event was accepted.
(WebCore::EventHandler::handleWheelEvent): Move scrolling code from here
(WebCore::EventHandler::defaultWheelEventHandler): ...to here.
* page/EventHandler.h: Add function signature.

LayoutTests: Add a test for the patch to https://bugs.webkit.org/show_bug.cgi?id=35566.
These can be run manually or from DRT.

Patch by Andy Estes <aestes@apple.com> on 2010-03-02
Reviewed by Maciej Stachowiak.

* fast/events/wheelevent-in-scrolling-div-expected.txt: Added.
* fast/events/wheelevent-in-scrolling-div.html: Added.

Canonical link: https://commits.webkit.org/46737@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@55436 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
aestes authored and bdash committed Mar 2, 2010
1 parent 57f40e0 commit 1a4b086e1a5af1ef440568a620d6918636646c32
Showing 10 changed files with 274 additions and 45 deletions.
@@ -1,3 +1,13 @@
2010-03-02 Andy Estes <aestes@apple.com>

Reviewed by Maciej Stachowiak.

Add a test for the patch to https://bugs.webkit.org/show_bug.cgi?id=35566.
These can be run manually or from DRT.

* fast/events/wheelevent-in-scrolling-div-expected.txt: Added.
* fast/events/wheelevent-in-scrolling-div.html: Added.

2010-03-02 Mark Rowe <mrowe@apple.com>

Reviewed by Darin Adler.
@@ -0,0 +1,6 @@
scrollTop=200 (should be 200): PASS
scrollLeft=100 (should be 100): PASS
wheelDeltaY=-24000 (should be -24000): PASS
wheelDeltaX=-12000 (should be -12000): PASS
wheelDelta=-24000 (should be -24000): PASS

@@ -0,0 +1,84 @@
<head>
<script>
var expectedScrollTop = 200;
var expectedScrollLeft = 100;

if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}

function dispatchWheelEvent()
{
var overflowElement = document.getElementById("overflow");
if (overflowElement) {
overflowElement.addEventListener("mousewheel", mousewheelHandler, false);
var wheelEvent = document.createEvent("WheelEvent");
if (wheelEvent) {
wheelEvent.initWebKitWheelEvent(-window.expectedScrollLeft, -window.expectedScrollTop, window, 0, 0, 0, 0, false, false, false, false);
overflowElement.dispatchEvent(wheelEvent);
}
}

setTimeout('printScrollOffsets();', 100);
}

function passFailString(p)
{
var color = p?"green":"red";
var text = p?"PASS":"FAIL";
return "<span style='color:"+color+"'>"+text+"</span>";
}

function printScrollOffsets()
{
var consoleDiv = document.getElementById("offsetConsole");
var overflowDiv = document.getElementById("overflow");
if (consoleDiv && overflowDiv) {
consoleDiv.innerHTML = "";

consoleDiv.innerHTML += "scrollTop=" + overflowDiv.scrollTop + " (should be " + window.expectedScrollTop + "): ";
consoleDiv.innerHTML += passFailString(overflowDiv.scrollTop == window.expectedScrollTop);
consoleDiv.innerHTML += "<br>"

consoleDiv.innerHTML += "scrollLeft=" + overflowDiv.scrollLeft + " (should be " + window.expectedScrollLeft + "): ";
consoleDiv.innerHTML += passFailString(overflowDiv.scrollLeft == window.expectedScrollLeft);
consoleDiv.innerHTML += "<br>"
}

if (window.layoutTestController)
window.layoutTestController.notifyDone();
}

function mousewheelHandler(e)
{
var consoleDiv = document.getElementById("mousewheelConsole");
if (consoleDiv) {
consoleDiv.innerHTML = "";

consoleDiv.innerHTML += "wheelDeltaY=" + e.wheelDeltaY + " (should be " + window.expectedScrollTop*-120 + "): ";
consoleDiv.innerHTML += passFailString(e.wheelDeltaY == window.expectedScrollTop*-120);
consoleDiv.innerHTML += "<br>"

consoleDiv.innerHTML += "wheelDeltaX=" + e.wheelDeltaX + " (should be " + window.expectedScrollLeft*-120 + "): ";
consoleDiv.innerHTML += passFailString(e.wheelDeltaX == window.expectedScrollLeft*-120);
consoleDiv.innerHTML += "<br>"

var expectedScroll = e.wheelDeltaY?window.expectedScrollTop:window.expectedScrollLeft;
consoleDiv.innerHTML += "wheelDelta=" + e.wheelDelta + " (should be " + expectedScroll*-120 + "): ";
consoleDiv.innerHTML += passFailString(e.wheelDelta == expectedScroll*-120);
consoleDiv.innerHTML += "<br>"
}
}
</script>
</head>

<body style="margin:0" onload="setTimeout('dispatchWheelEvent();', 100)">
<div id="overflow" style="border:2px solid black;overflow:auto;height:200px;width:200px;">
<div style="background-color:red;height:200px;width:400px;"></div>
<div style="background-color:green;height:200px;width:400px;"></div>
<div style="background-color:red;height:200px;width:400px;"></div>
</div>
<div id="offsetConsole"><span style="color:red">FAIL</span></div>
<div id="mousewheelConsole"><span style="color:red">FAIL</span></div>
</body>
@@ -1,3 +1,48 @@
2010-03-02 Andy Estes <aestes@apple.com>

Reviewed by Maciej Stachowiak.

Add the capability to create and dispatch a WheelEvent in JavaScript.
Ensure the event's default handler is triggered in the same way as it is
during a PlatformWheelEvent.

https://bugs.webkit.org/show_bug.cgi?id=35566

Test: fast/events/wheelevent-in-scrolling-div.html

* dom/Node.cpp: Ensure that the default behavior (scrolling) occurs for
wheel events originating both from the platform and from
JavaScript/ObjC.
(WebCore::Node::dispatchWheelEvent): Instantiate new WheelEvent with
the graunularity of the PlatformWheelEvent.
(WebCore::Node::defaultEventHandler): Add support for mousewheel events.
* dom/WheelEvent.cpp: Add three new member variables: m_deltaX, m_deltaY
and m_granularity. m_deltaX and m_deltaY differ from m_wheelDeltaX and
m_wheelDeltaY, which are the number of wheel ticks multiplied by 120 for
IE compatibility.
(WebCore::WheelEvent::WheelEvent): Initialize new member variables.
(WebCore::WheelEvent::initWheelEvent): Same.
(WebCore::WheelEvent::initWebKitWheelEvent): Same.
* dom/WheelEvent.h: See WheelEvent.cpp.
(WebCore::WheelEvent::): Add Granularity enum (Pixel, Line, Page).
(WebCore::WheelEvent::create): Add new arguments.
(WebCore::WheelEvent::deltaX): Amount of scroll in x direction.
(WebCore::WheelEvent::deltaY): Amount of scroll in y direction.
(WebCore::WheelEvent::granularity): Units of deltaX and deltaY.
* dom/WheelEvent.idl: Add initWebKitWheelEvent() to JavaScript. This is
the same as the initWheelEvent ObjC method. As the DOM Level 3 Events
specification is still a working draft and subject to change, prefix
'WebKit' to the method signature to indicate experimental support.
* page/EventHandler.cpp: Move the scroll handling from
handleWheelEvent() to defaultWheelEventHandler(), which is executed on
both PlatformWheelEvents and JavaScript WheelEvents.
(WebCore::scrollNode): Renamed from scrollAndAcceptEvent(). Remove
the PlatformWheelEvent from the argument list and instead return a
boolean indicating if the scroll event was accepted.
(WebCore::EventHandler::handleWheelEvent): Move scrolling code from here
(WebCore::EventHandler::defaultWheelEventHandler): ...to here.
* page/EventHandler.h: Add function signature.

2010-03-02 Mark Rowe <mrowe@apple.com>

Reviewed by Darin Adler.
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
@@ -2902,14 +2902,27 @@ void Node::dispatchWheelEvent(PlatformWheelEvent& e)
}
}

RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(),
WheelEvent::Granularity granularity;
switch (e.granularity()) {
case ScrollByPageWheelEvent:
granularity = WheelEvent::Page;
break;
case ScrollByPixelWheelEvent:
default:
granularity = WheelEvent::Pixel;
break;
}

RefPtr<WheelEvent> we = WheelEvent::create(e.wheelTicksX(), e.wheelTicksY(), e.deltaX(), e.deltaY(), granularity,
document()->defaultView(), e.globalX(), e.globalY(), adjustedPageX, adjustedPageY,
e.ctrlKey(), e.altKey(), e.shiftKey(), e.metaKey());

we->setAbsoluteLocation(IntPoint(pos.x(), pos.y()));

if (!dispatchEvent(we.release()))
if (!dispatchEvent(we) || we->defaultHandled())
e.accept();

we.release();
}

void Node::dispatchFocusEvent()
@@ -2966,6 +2979,18 @@ void Node::defaultEventHandler(Event* event)
}
}
#endif
} else if (eventType == eventNames().mousewheelEvent && event->isWheelEvent()) {
WheelEvent* wheelEvent = static_cast<WheelEvent*>(event);

// If we don't have a renderer, send the wheel event to the first node we find with a renderer.
// This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
Node* startNode = this;
while (startNode && !startNode->renderer())
startNode = startNode->parent();

if (startNode && startNode->renderer())
if (Frame* frame = document()->frame())
frame->eventHandler()->defaultWheelEventHandler(startNode, wheelEvent);
}
}

@@ -2,7 +2,7 @@
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
* Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
* Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2003, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -31,21 +31,28 @@ namespace WebCore {
WheelEvent::WheelEvent()
: m_wheelDeltaX(0)
, m_wheelDeltaY(0)
, m_rawDeltaX(0)
, m_rawDeltaY(0)
, m_granularity(Pixel)
{
}

WheelEvent::WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view,
WheelEvent::WheelEvent(float wheelTicksX, float wheelTicksY, float rawDeltaX, float rawDeltaY,
Granularity granularity, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
: MouseRelatedEvent(eventNames().mousewheelEvent,
true, true, view, 0, screenX, screenY, pageX, pageY,
true, true, view, 0, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey)
, m_wheelDeltaX(lroundf(wheelTicksX * 120))
, m_wheelDeltaY(lroundf(wheelTicksY * 120)) // Normalize to the Windows 120 multiple
, m_rawDeltaX(rawDeltaX)
, m_rawDeltaY(rawDeltaY)
, m_granularity(granularity)
{
}

void WheelEvent::initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<AbstractView> view,
void WheelEvent::initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
{
@@ -60,12 +67,25 @@ void WheelEvent::initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<Abs
m_altKey = altKey;
m_shiftKey = shiftKey;
m_metaKey = metaKey;
m_wheelDeltaX = wheelDeltaX;
m_wheelDeltaY = wheelDeltaY;

// Normalize to the Windows 120 multiple
m_wheelDeltaX = rawDeltaX * 120;
m_wheelDeltaY = rawDeltaY * 120;

m_rawDeltaX = rawDeltaX;
m_rawDeltaY = rawDeltaY;
m_granularity = Pixel;

initCoordinates(pageX, pageY);
}

void WheelEvent::initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
{
initWheelEvent(rawDeltaX, rawDeltaY, view, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey);
}

bool WheelEvent::isWheelEvent() const
{
@@ -2,7 +2,7 @@
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
* Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
* Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
* Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -31,39 +31,55 @@ namespace WebCore {
// extension: mouse wheel event
class WheelEvent : public MouseRelatedEvent {
public:
enum Granularity { Pixel, Line, Page };

static PassRefPtr<WheelEvent> create()
{
return adoptRef(new WheelEvent);
}
static PassRefPtr<WheelEvent> create(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView> view,
static PassRefPtr<WheelEvent> create(float wheelTicksX, float wheelTicksY,
float rawDeltaX, float rawDeltaY, Granularity granularity, PassRefPtr<AbstractView> view,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey)
{
return adoptRef(new WheelEvent(wheelTicksX, wheelTicksY, view, screenX, screenY, pageX, pageY,
return adoptRef(new WheelEvent(wheelTicksX, wheelTicksY, rawDeltaX, rawDeltaY,
granularity, view, screenX, screenY, pageX, pageY,
ctrlKey, altKey, shiftKey, metaKey));
}

void initWheelEvent(int wheelDeltaX, int wheelDeltaY, PassRefPtr<AbstractView>,
void initWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);

void initWebKitWheelEvent(int rawDeltaX, int rawDeltaY, PassRefPtr<AbstractView>,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);

int wheelDelta() const { if (m_wheelDeltaY == 0) return m_wheelDeltaX; return m_wheelDeltaY; }
int wheelDeltaX() const { return m_wheelDeltaX; }
int wheelDeltaY() const { return m_wheelDeltaY; }
int rawDeltaX() const { return m_rawDeltaX; }
int rawDeltaY() const { return m_rawDeltaY; }
Granularity granularity() const { return m_granularity; }

// Needed for Objective-C legacy support
bool isHorizontal() const { return m_wheelDeltaX; }

private:
WheelEvent();
WheelEvent(float wheelTicksX, float wheelTicksY, PassRefPtr<AbstractView>,
WheelEvent(float wheelTicksX, float wheelTicksY, float rawDeltaX, float rawDeltaY,
Granularity granularity, PassRefPtr<AbstractView>,
int screenX, int screenY, int pageX, int pageY,
bool ctrlKey, bool altKey, bool shiftKey, bool metaKey);

virtual bool isWheelEvent() const;

int m_wheelDeltaX;
int m_wheelDeltaY;

int m_rawDeltaX;
int m_rawDeltaY;
Granularity m_granularity;
};

} // namespace WebCore
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -57,6 +57,19 @@ module events {
in boolean shiftKey,
in boolean metaKey);
#endif /* !defined(LANGUAGE_JAVASCRIPT) */
};

#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
void initWebKitWheelEvent(in long wheelDeltaX,
in long wheelDeltaY,
in DOMWindow view,
in long screenX,
in long screenY,
in long clientX,
in long clientY,
in boolean ctrlKey,
in boolean altKey,
in boolean shiftKey,
in boolean metaKey);
#endif /* defined(LANGUAGE_JAVASCRIPT) */
};
}

0 comments on commit 1a4b086

Please sign in to comment.