summaryrefslogtreecommitdiffstats
path: root/WebCore/page/EventHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/page/EventHandler.cpp')
-rw-r--r--WebCore/page/EventHandler.cpp147
1 files changed, 105 insertions, 42 deletions
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index 937f08f..6b4031e 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -87,6 +87,7 @@ namespace WebCore {
using namespace HTMLNames;
+#if ENABLE(DRAG_SUPPORT)
// The link drag hysteresis is much larger than the others because there
// needs to be enough space to cancel the link press without starting a link drag,
// and because dragging links is rare.
@@ -94,6 +95,7 @@ const int LinkDragHysteresis = 40;
const int ImageDragHysteresis = 5;
const int TextDragHysteresis = 3;
const int GeneralDragHysteresis = 3;
+#endif // ENABLE(DRAG_SUPPORT)
// Match key code of composition keydown event on windows.
// IE sends VK_PROCESSKEY which has value 229;
@@ -106,10 +108,9 @@ using namespace SVGNames;
// When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
const double autoscrollInterval = 0.05;
-static Frame* subframeForTargetNode(Node*);
static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);
-static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node)
+static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node, Node** stopNode)
{
if (!delta)
return;
@@ -118,12 +119,13 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir
RenderBox* enclosingBox = node->renderer()->enclosingBox();
if (e.granularity() == ScrollByPageWheelEvent) {
- if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1))
+ if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1, stopNode))
e.accept();
return;
- }
+ }
+
float pixelsToScroll = delta > 0 ? delta : -delta;
- if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll))
+ if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll, stopNode))
e.accept();
}
@@ -146,7 +148,9 @@ EventHandler::EventHandler(Frame* frame)
, m_mousePressed(false)
, m_capturesDragging(false)
, m_mouseDownMayStartSelect(false)
+#if ENABLE(DRAG_SUPPORT)
, m_mouseDownMayStartDrag(false)
+#endif
, m_mouseDownWasSingleClickInSelection(false)
, m_beganSelectingText(false)
, m_panScrollInProgress(false)
@@ -179,11 +183,13 @@ EventHandler::~EventHandler()
{
}
+#if ENABLE(DRAG_SUPPORT)
EventHandler::EventHandlerDragState& EventHandler::dragState()
{
DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ());
return state;
}
+#endif // ENABLE(DRAG_SUPPORT)
void EventHandler::clear()
{
@@ -203,13 +209,16 @@ void EventHandler::clear()
m_touch = 0;
#endif
m_frameSetBeingResized = 0;
+#if ENABLE(DRAG_SUPPORT)
m_dragTarget = 0;
+#endif
m_currentMousePosition = IntPoint();
m_mousePressNode = 0;
m_mousePressed = false;
m_capturesDragging = false;
m_capturingMouseEventsNode = 0;
m_latchedWheelEventNode = 0;
+ m_previousWheelScrolledNode = 0;
}
void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
@@ -357,8 +366,10 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event)
{
+#if ENABLE(DRAG_SUPPORT)
// Reset drag state.
dragState().m_dragSrc = 0;
+#endif
if (ScrollView* scrollView = m_frame->view()) {
if (scrollView->isPointInScrollbarCorner(event.event().pos()))
@@ -371,8 +382,10 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
// so it's allowed to start a drag or selection.
m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
+#if ENABLE(DRAG_SUPPORT)
// Careful that the drag starting logic stays in sync with eventMayStartDrag()
m_mouseDownMayStartDrag = singleClick;
+#endif
m_mouseDownWasSingleClickInSelection = false;
@@ -400,7 +413,9 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
Node* innerNode = event.targetNode();
m_mousePressNode = innerNode;
+#if ENABLE(DRAG_SUPPORT)
m_dragStartPos = event.event().pos();
+#endif
bool swallowEvent = false;
m_frame->selection()->setCaretBlinkingSuspended(true);
@@ -420,6 +435,7 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
return swallowEvent;
}
+#if ENABLE(DRAG_SUPPORT)
bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event)
{
if (handleDrag(event))
@@ -442,7 +458,7 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
// If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
// Otherwise, let the bridge handle it so the view can scroll itself.
RenderObject* renderer = targetNode->renderer();
- while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) {
+ while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) {
if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
renderer = renderer->document()->ownerElement()->renderer();
else
@@ -559,6 +575,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint&
m_frame->selection()->setSelection(newSelection);
}
}
+#endif // ENABLE(DRAG_SUPPORT)
bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
{
@@ -586,7 +603,9 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
m_frame->selection()->setCaretBlinkingSuspended(false);
m_mousePressed = false;
m_capturesDragging = false;
+#if ENABLE(DRAG_SUPPORT)
m_mouseDownMayStartDrag = false;
+#endif
m_mouseDownMayStartSelect = false;
m_mouseDownMayStartAutoscroll = false;
m_mouseDownWasInSubframe = false;
@@ -598,7 +617,9 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
// on the selection, the selection goes away. However, if we are
// editing, place the caret.
if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
+#if ENABLE(DRAG_SUPPORT)
&& m_dragStartPos == event.event().pos()
+#endif
&& m_frame->selection()->isRange()
&& event.event().button() != RightButton) {
VisibleSelection newSelection;
@@ -732,7 +753,7 @@ void EventHandler::updateAutoscrollRenderer()
if (Node* nodeAtPoint = hitTest.innerNode())
m_autoscrollRenderer = nodeAtPoint->renderer();
- while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeProgramaticallyScrolled(false)))
+ while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeScrolledAndHasScrollableArea()))
m_autoscrollRenderer = m_autoscrollRenderer->parent();
}
@@ -741,6 +762,7 @@ void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
m_autoscrollRenderer = renderer;
}
+#if ENABLE(DRAG_SUPPORT)
void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
{
flagDHTML = false;
@@ -761,6 +783,7 @@ void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
}
+#endif // ENABLE(DRAG_SUPPORT)
HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars)
{
@@ -883,8 +906,10 @@ bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g
if (node) {
RenderObject* r = node->renderer();
- if (r && !r->isListBox())
- return r->enclosingBox()->scroll(direction, granularity);
+ if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) {
+ setFrameWasScrolledByUser();
+ return true;
+ }
}
return false;
@@ -914,10 +939,10 @@ Frame* subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResul
{
if (!hitTestResult.isOverWidget())
return 0;
- return subframeForTargetNode(hitTestResult.targetNode());
+ return EventHandler::subframeForTargetNode(hitTestResult.targetNode());
}
-Frame* subframeForTargetNode(Node* node)
+Frame* EventHandler::subframeForTargetNode(Node* node)
{
if (!node)
return 0;
@@ -1117,7 +1142,9 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
m_capturesDragging = true;
m_currentMousePosition = mouseEvent.pos();
m_mouseDownTimestamp = mouseEvent.timestamp();
+#if ENABLE(DRAG_SUPPORT)
m_mouseDownMayStartDrag = false;
+#endif
m_mouseDownMayStartSelect = false;
m_mouseDownMayStartAutoscroll = false;
if (FrameView* view = m_frame->view())
@@ -1141,6 +1168,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
m_mousePressNode = mev.targetNode();
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page()) {
InspectorController* inspector = page->inspectorController();
if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) {
@@ -1149,6 +1177,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
return true;
}
}
+#endif
Frame* subframe = subframeForHitTestResult(mev);
if (subframe && passMousePressEventToSubframe(mev, subframe)) {
@@ -1172,7 +1201,7 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) {
RenderObject* renderer = mev.targetNode()->renderer();
- while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) {
+ while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())) {
if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
renderer = renderer->document()->ownerElement()->renderer();
else
@@ -1393,8 +1422,10 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
return true;
swallowEvent = dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true);
+#if ENABLE(DRAG_SUPPORT)
if (!swallowEvent)
swallowEvent = handleMouseDraggedEvent(mev);
+#endif // ENABLE(DRAG_SUPPORT)
return swallowEvent;
}
@@ -1464,6 +1495,7 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
}
+#if ENABLE(DRAG_SUPPORT)
bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
{
FrameView* view = m_frame->view();
@@ -1508,15 +1540,15 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
// it is sometimes incorrect when dragging within subframes, as seen with
// LayoutTests/fast/events/drag-in-frames.html.
if (newTarget) {
- if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
- accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
+ Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0;
+ if (frame)
+ accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
else
accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard);
}
if (m_dragTarget) {
- Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
- ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
+ Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
if (frame)
accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
else
@@ -1524,8 +1556,9 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
}
} else {
if (newTarget) {
- if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
- accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
+ Frame* frame = (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag)) ? static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame() : 0;
+ if (frame)
+ accept = frame->eventHandler()->updateDragAndDrop(event, clipboard);
else
accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard);
}
@@ -1571,6 +1604,7 @@ void EventHandler::clearDragState()
m_sendingEventToSubview = false;
#endif
}
+#endif // ENABLE(DRAG_SUPPORT)
void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
{
@@ -1692,12 +1726,15 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);
if (!swallowEvent && eventType == eventNames().mousedownEvent) {
+ // The layout needs to be up to date to determine if an element is focusable.
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
+
// Blur current focus node when a link/button is clicked; this
// is expected by some sites that rely on onChange handlers running
// from form fields before the button click is processed.
Node* node = m_nodeUnderMouse.get();
RenderObject* renderer = node ? node->renderer() : 0;
-
+
// Walk up the render tree to search for a node to focus.
// Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
while (renderer) {
@@ -1736,6 +1773,13 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
return swallowEvent;
}
+#if !PLATFORM(GTK)
+bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const
+{
+ return false;
+}
+#endif
+
bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
{
Document* doc = m_frame->document();
@@ -1749,35 +1793,39 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
FrameView* view = m_frame->view();
if (!view)
return false;
+ setFrameWasScrolledByUser();
IntPoint vPoint = view->windowToContents(e.pos());
Node* node;
bool isOverWidget;
bool didSetLatchedNode = false;
-
+
+ HitTestRequest request(HitTestRequest::ReadOnly);
+ HitTestResult result(vPoint);
+ doc->renderView()->layer()->hitTest(request, result);
+
if (m_useLatchedWheelEventNode) {
if (!m_latchedWheelEventNode) {
- HitTestRequest request(HitTestRequest::ReadOnly);
- HitTestResult result(vPoint);
- doc->renderView()->layer()->hitTest(request, result);
m_latchedWheelEventNode = result.innerNode();
m_widgetIsLatched = result.isOverWidget();
didSetLatchedNode = true;
}
-
+
node = m_latchedWheelEventNode.get();
isOverWidget = m_widgetIsLatched;
} else {
if (m_latchedWheelEventNode)
m_latchedWheelEventNode = 0;
-
- HitTestRequest request(HitTestRequest::ReadOnly);
- HitTestResult result(vPoint);
- doc->renderView()->layer()->hitTest(request, result);
+ if (m_previousWheelScrolledNode)
+ m_previousWheelScrolledNode = 0;
+
node = result.innerNode();
isOverWidget = result.isOverWidget();
}
-
+
+ if (shouldTurnVerticalTicksIntoHorizontal(result))
+ e.turnVerticalTicksIntoHorizontal();
+
if (node) {
// Figure out which view to send the event to.
RenderObject* target = node->renderer();
@@ -1794,17 +1842,20 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
node->dispatchWheelEvent(e);
if (e.isAccepted())
return true;
-
+
// 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.
while (node && !node->renderer())
node = node->parent();
-
+
if (node && node->renderer()) {
// Just break up into two scrolls if we need to. Diagonal movement on
// a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
- scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node);
- scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node);
+ Node* stopNode = m_previousWheelScrolledNode.get();
+ scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node, &stopNode);
+ scrollAndAcceptEvent(e.deltaY(), ScrollUp, ScrollDown, e, node, &stopNode);
+ if (!m_useLatchedWheelEventNode)
+ m_previousWheelScrolledNode = stopNode;
}
}
@@ -1819,6 +1870,7 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
return e.isAccepted();
}
+#if ENABLE(CONTEXT_MENUS)
bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
{
Document* doc = m_frame->document();
@@ -1849,6 +1901,7 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
return swallowEvent;
}
+#endif // ENABLE(CONTEXT_MENUS)
void EventHandler::scheduleHoverStateUpdate()
{
@@ -1868,12 +1921,13 @@ bool EventHandler::canMouseDownStartSelect(Node* node)
for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
if (Node* node = curr->node())
- return node->dispatchEvent(eventNames().selectstartEvent, true, true);
+ return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
}
return true;
}
+#if ENABLE(DRAG_SUPPORT)
bool EventHandler::canMouseDragExtendSelect(Node* node)
{
if (!node || !node->renderer())
@@ -1881,11 +1935,12 @@ bool EventHandler::canMouseDragExtendSelect(Node* node)
for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
if (Node* node = curr->node())
- return node->dispatchEvent(eventNames().selectstartEvent, true, true);
+ return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
}
return true;
}
+#endif // ENABLE(DRAG_SUPPORT)
void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
{
@@ -2109,6 +2164,7 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
}
}
+#if ENABLE(DRAG_SUPPORT)
bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const
{
IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y());
@@ -2142,7 +2198,7 @@ void EventHandler::freeClipboard()
bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
{
- if (!node || node->hasChildNodes() || !m_frame->view())
+ if (!node || !m_frame->view())
return false;
Page* page = m_frame->page();
return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point);
@@ -2308,6 +2364,7 @@ cleanupDrag:
// No more default handling (like selection), whether we're past the hysteresis bounds or not
return true;
}
+#endif // ENABLE(DRAG_SUPPORT)
bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, bool isLineBreak, bool isBackTab)
{
@@ -2339,7 +2396,7 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve
}
-#if !PLATFORM(MAC) && !PLATFORM(QT)
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(HAIKU)
bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
{
return false;
@@ -2440,22 +2497,28 @@ void EventHandler::capsLockStateMayHaveChanged()
void EventHandler::sendResizeEvent()
{
- m_frame->document()->dispatchWindowEvent(eventNames().resizeEvent, false, false);
+ m_frame->document()->dispatchWindowEvent(Event::create(eventNames().resizeEvent, false, false));
}
void EventHandler::sendScrollEvent()
{
+ setFrameWasScrolledByUser();
+ if (m_frame->view())
+ m_frame->document()->dispatchEvent(Event::create(eventNames().scrollEvent, true, false));
+}
+
+void EventHandler::setFrameWasScrolledByUser()
+{
FrameView* v = m_frame->view();
- if (!v)
- return;
- v->setWasScrolledByUser(true);
- m_frame->document()->dispatchEvent(eventNames().scrollEvent, true, false);
+ if (v)
+ v->setWasScrolledByUser(true);
}
bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar)
{
if (!scrollbar || !scrollbar->enabled())
return false;
+ setFrameWasScrolledByUser();
return scrollbar->mouseDown(mev.event());
}