1 /* 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 3 * Copyright (C) 2006 Alexey Proskuryakov (ap (at) webkit.org) 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "EventHandler.h" 29 30 #include "AXObjectCache.h" 31 #include "CachedImage.h" 32 #include "Chrome.h" 33 #include "ChromeClient.h" 34 #include "Cursor.h" 35 #include "CursorList.h" 36 #include "Document.h" 37 #include "DragController.h" 38 #include "Editor.h" 39 #include "EventNames.h" 40 #include "EventQueue.h" 41 #include "FloatPoint.h" 42 #include "FloatRect.h" 43 #include "FocusController.h" 44 #include "Frame.h" 45 #include "FrameLoader.h" 46 #include "FrameTree.h" 47 #include "FrameView.h" 48 #include "htmlediting.h" 49 #include "HTMLFrameElementBase.h" 50 #include "HTMLFrameSetElement.h" 51 #include "HTMLInputElement.h" 52 #include "HTMLNames.h" 53 #include "HitTestRequest.h" 54 #include "HitTestResult.h" 55 #include "Image.h" 56 #include "InspectorInstrumentation.h" 57 #include "KeyboardEvent.h" 58 #include "MouseEvent.h" 59 #include "MouseEventWithHitTestResults.h" 60 #include "Page.h" 61 #include "PlatformKeyboardEvent.h" 62 #include "PlatformWheelEvent.h" 63 #include "PluginDocument.h" 64 #if defined(ANDROID_PLUGINS) 65 #include "PluginView.h" 66 #endif 67 #include "RenderFrameSet.h" 68 #include "RenderLayer.h" 69 #include "RenderTextControlSingleLine.h" 70 #include "RenderView.h" 71 #include "RenderWidget.h" 72 #include "ScrollAnimator.h" 73 #include "Scrollbar.h" 74 #include "SelectionController.h" 75 #include "Settings.h" 76 #include "StyleCachedImage.h" 77 #include "TextEvent.h" 78 #include "TextIterator.h" 79 #include "UserGestureIndicator.h" 80 #include "UserTypingGestureIndicator.h" 81 #include "WheelEvent.h" 82 #include "WindowsKeyboardCodes.h" 83 #include <wtf/CurrentTime.h> 84 #include <wtf/StdLibExtras.h> 85 86 #if ENABLE(GESTURE_EVENTS) 87 #include "PlatformGestureEvent.h" 88 #endif 89 90 #if ENABLE(SVG) 91 #include "SVGDocument.h" 92 #include "SVGElementInstance.h" 93 #include "SVGNames.h" 94 #include "SVGUseElement.h" 95 #endif 96 97 #if ENABLE(TOUCH_EVENTS) 98 #include "PlatformTouchEvent.h" 99 #include "TouchEvent.h" 100 #endif 101 102 #if ENABLE(GESTURE_RECOGNIZER) 103 #include "PlatformGestureRecognizer.h" 104 #endif 105 106 #if defined(ANDROID_PLUGINS) 107 #include "WebViewCore.h" 108 #endif 109 110 namespace WebCore { 111 112 using namespace HTMLNames; 113 114 #if ENABLE(DRAG_SUPPORT) 115 // The link drag hysteresis is much larger than the others because there 116 // needs to be enough space to cancel the link press without starting a link drag, 117 // and because dragging links is rare. 118 const int LinkDragHysteresis = 40; 119 const int ImageDragHysteresis = 5; 120 const int TextDragHysteresis = 3; 121 const int GeneralDragHysteresis = 3; 122 #endif // ENABLE(DRAG_SUPPORT) 123 124 // Match key code of composition keydown event on windows. 125 // IE sends VK_PROCESSKEY which has value 229; 126 const int CompositionEventKeyCode = 229; 127 128 #if ENABLE(SVG) 129 using namespace SVGNames; 130 #endif 131 132 // When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth 133 const double autoscrollInterval = 0.05; 134 135 const double fakeMouseMoveInterval = 0.1; 136 137 static inline bool scrollNode(float delta, WheelEvent::Granularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode) 138 { 139 if (!delta) 140 return false; 141 142 if (!node->renderer()) 143 return false; 144 145 // Find the nearest enclosing box. 146 RenderBox* enclosingBox = node->renderer()->enclosingBox(); 147 148 float absDelta = delta > 0 ? delta : -delta; 149 150 if (granularity == WheelEvent::Page) 151 return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, absDelta, stopNode); 152 153 if (granularity == WheelEvent::Line) 154 return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByLine, absDelta, stopNode); 155 156 if (granularity == WheelEvent::Pixel) 157 return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, absDelta, stopNode); 158 159 return false; 160 } 161 162 #if !PLATFORM(MAC) 163 164 inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) 165 { 166 return false; 167 } 168 169 #if ENABLE(DRAG_SUPPORT) 170 inline bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&) 171 { 172 return false; 173 } 174 #endif 175 176 #endif 177 178 EventHandler::EventHandler(Frame* frame) 179 : m_frame(frame) 180 , m_mousePressed(false) 181 , m_capturesDragging(false) 182 , m_mouseDownMayStartSelect(false) 183 #if ENABLE(DRAG_SUPPORT) 184 , m_mouseDownMayStartDrag(false) 185 #endif 186 , m_mouseDownWasSingleClickInSelection(false) 187 , m_beganSelectingText(false) 188 , m_panScrollInProgress(false) 189 , m_panScrollButtonPressed(false) 190 , m_springLoadedPanScrollInProgress(false) 191 , m_hoverTimer(this, &EventHandler::hoverTimerFired) 192 , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired) 193 , m_autoscrollRenderer(0) 194 , m_autoscrollInProgress(false) 195 , m_mouseDownMayStartAutoscroll(false) 196 , m_mouseDownWasInSubframe(false) 197 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired) 198 #if ENABLE(SVG) 199 , m_svgPan(false) 200 #endif 201 , m_resizeLayer(0) 202 , m_eventHandlerWillResetCapturingMouseEventsNode(0) 203 , m_clickCount(0) 204 , m_mouseDownTimestamp(0) 205 , m_useLatchedWheelEventNode(false) 206 , m_widgetIsLatched(false) 207 #if PLATFORM(MAC) 208 , m_mouseDownView(nil) 209 , m_sendingEventToSubview(false) 210 , m_activationEventNumber(-1) 211 #endif 212 #if ENABLE(TOUCH_EVENTS) 213 , m_touchPressed(false) 214 #endif 215 #if ENABLE(GESTURE_RECOGNIZER) 216 , m_gestureRecognizer(PlatformGestureRecognizer::create()) 217 #endif 218 { 219 } 220 221 EventHandler::~EventHandler() 222 { 223 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); 224 } 225 226 #if ENABLE(DRAG_SUPPORT) 227 EventHandler::EventHandlerDragState& EventHandler::dragState() 228 { 229 DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ()); 230 return state; 231 } 232 #endif // ENABLE(DRAG_SUPPORT) 233 234 void EventHandler::clear() 235 { 236 m_hoverTimer.stop(); 237 m_fakeMouseMoveEventTimer.stop(); 238 m_resizeLayer = 0; 239 m_nodeUnderMouse = 0; 240 m_lastNodeUnderMouse = 0; 241 #if ENABLE(SVG) 242 m_instanceUnderMouse = 0; 243 m_lastInstanceUnderMouse = 0; 244 #endif 245 m_lastMouseMoveEventSubframe = 0; 246 m_lastScrollbarUnderMouse = 0; 247 m_clickCount = 0; 248 m_clickNode = 0; 249 m_frameSetBeingResized = 0; 250 #if ENABLE(DRAG_SUPPORT) 251 m_dragTarget = 0; 252 m_shouldOnlyFireDragOverEvent = false; 253 #endif 254 m_currentMousePosition = IntPoint(); 255 m_mousePressNode = 0; 256 m_mousePressed = false; 257 m_capturesDragging = false; 258 m_capturingMouseEventsNode = 0; 259 m_latchedWheelEventNode = 0; 260 m_previousWheelScrolledNode = 0; 261 #if ENABLE(TOUCH_EVENTS) 262 m_originatingTouchPointTargets.clear(); 263 #if PLATFORM(ANDROID) 264 m_capturingTouchEventsNode = 0; 265 #endif 266 #endif 267 } 268 269 static void setSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection) 270 { 271 ASSERT(selection); 272 if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection)) 273 selection->setSelection(newSelection); 274 } 275 276 static void setNonDirectionalSelectionIfNeeded(SelectionController* selection, const VisibleSelection& newSelection, TextGranularity granularity) 277 { 278 ASSERT(selection); 279 if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection)) 280 selection->setSelection(newSelection, granularity, MakeNonDirectionalSelection); 281 } 282 283 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) 284 { 285 Node* innerNode = targetNode(result); 286 VisibleSelection newSelection; 287 288 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) { 289 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 290 TextGranularity granularity = CharacterGranularity; 291 if (pos.isNotNull()) { 292 newSelection = VisibleSelection(pos); 293 newSelection.expandUsingGranularity(WordGranularity); 294 } 295 296 if (newSelection.isRange()) { 297 granularity = WordGranularity; 298 m_beganSelectingText = true; 299 if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled()) 300 newSelection.appendTrailingWhitespace(); 301 } 302 303 setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); 304 } 305 } 306 307 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result) 308 { 309 if (!result.hitTestResult().isLiveLink()) 310 return selectClosestWordFromMouseEvent(result); 311 312 Node* innerNode = targetNode(result); 313 314 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) { 315 VisibleSelection newSelection; 316 Element* URLElement = result.hitTestResult().URLElement(); 317 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 318 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement)) 319 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement); 320 321 TextGranularity granularity = CharacterGranularity; 322 if (newSelection.isRange()) { 323 granularity = WordGranularity; 324 m_beganSelectingText = true; 325 } 326 327 setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); 328 } 329 } 330 331 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event) 332 { 333 if (event.event().button() != LeftButton) 334 return false; 335 336 if (m_frame->selection()->isRange()) 337 // A double-click when range is already selected 338 // should not change the selection. So, do not call 339 // selectClosestWordFromMouseEvent, but do set 340 // m_beganSelectingText to prevent handleMouseReleaseEvent 341 // from setting caret selection. 342 m_beganSelectingText = true; 343 else 344 selectClosestWordFromMouseEvent(event); 345 346 return true; 347 } 348 349 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event) 350 { 351 if (event.event().button() != LeftButton) 352 return false; 353 354 Node* innerNode = targetNode(event); 355 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) 356 return false; 357 358 VisibleSelection newSelection; 359 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint())); 360 if (pos.isNotNull()) { 361 newSelection = VisibleSelection(pos); 362 newSelection.expandUsingGranularity(ParagraphGranularity); 363 } 364 365 TextGranularity granularity = CharacterGranularity; 366 if (newSelection.isRange()) { 367 granularity = ParagraphGranularity; 368 m_beganSelectingText = true; 369 } 370 371 setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); 372 373 return true; 374 } 375 376 static int textDistance(const Position& start, const Position& end) 377 { 378 RefPtr<Range> range = Range::create(start.anchorNode()->document(), start, end); 379 return TextIterator::rangeLength(range.get(), true); 380 } 381 382 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event) 383 { 384 Node* innerNode = targetNode(event); 385 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) 386 return false; 387 388 // Extend the selection if the Shift key is down, unless the click is in a link. 389 bool extendSelection = event.event().shiftKey() && !event.isOverLink(); 390 391 // Don't restart the selection when the mouse is pressed on an 392 // existing selection so we can allow for text dragging. 393 if (FrameView* view = m_frame->view()) { 394 IntPoint vPoint = view->windowToContents(event.event().pos()); 395 if (!extendSelection && m_frame->selection()->contains(vPoint)) { 396 m_mouseDownWasSingleClickInSelection = true; 397 return false; 398 } 399 } 400 401 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint())); 402 if (visiblePos.isNull()) 403 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM); 404 Position pos = visiblePos.deepEquivalent(); 405 406 VisibleSelection newSelection = m_frame->selection()->selection(); 407 TextGranularity granularity = CharacterGranularity; 408 409 if (extendSelection && newSelection.isCaretOrRange()) { 410 m_frame->selection()->setIsDirectional(false); 411 412 ASSERT(m_frame->settings()); 413 if (m_frame->settings()->editingBehaviorType() == EditingMacBehavior) { 414 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 415 // was created right-to-left 416 Position start = newSelection.start(); 417 Position end = newSelection.end(); 418 int distanceToStart = textDistance(start, pos); 419 int distanceToEnd = textDistance(pos, end); 420 if (distanceToStart <= distanceToEnd) 421 newSelection = VisibleSelection(end, pos); 422 else 423 newSelection = VisibleSelection(start, pos); 424 } else { 425 newSelection.setExtent(pos); 426 } 427 428 if (m_frame->selection()->granularity() != CharacterGranularity) { 429 granularity = m_frame->selection()->granularity(); 430 newSelection.expandUsingGranularity(m_frame->selection()->granularity()); 431 } 432 433 m_beganSelectingText = true; 434 } else 435 newSelection = VisibleSelection(visiblePos); 436 437 setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, granularity); 438 439 return true; 440 } 441 442 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event) 443 { 444 #if ENABLE(DRAG_SUPPORT) 445 // Reset drag state. 446 dragState().m_dragSrc = 0; 447 #endif 448 449 cancelFakeMouseMoveEvent(); 450 451 if (ScrollView* scrollView = m_frame->view()) { 452 if (scrollView->isPointInScrollbarCorner(event.event().pos())) 453 return false; 454 } 455 456 bool singleClick = event.event().clickCount() <= 1; 457 458 // If we got the event back, that must mean it wasn't prevented, 459 // so it's allowed to start a drag or selection. 460 m_mouseDownMayStartSelect = canMouseDownStartSelect(targetNode(event)); 461 462 #if ENABLE(DRAG_SUPPORT) 463 // Careful that the drag starting logic stays in sync with eventMayStartDrag() 464 m_mouseDownMayStartDrag = singleClick; 465 #endif 466 467 m_mouseDownWasSingleClickInSelection = false; 468 469 m_mouseDown = event.event(); 470 471 if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event)) 472 return true; 473 474 #if ENABLE(SVG) 475 if (m_frame->document()->isSVGDocument() 476 && static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) { 477 if (event.event().shiftKey() && singleClick) { 478 m_svgPan = true; 479 static_cast<SVGDocument*>(m_frame->document())->startPan(event.event().pos()); 480 return true; 481 } 482 } 483 #endif 484 485 // We don't do this at the start of mouse down handling, 486 // because we don't want to do it until we know we didn't hit a widget. 487 if (singleClick) 488 focusDocumentView(); 489 490 Node* innerNode = targetNode(event); 491 492 m_mousePressNode = innerNode; 493 #if ENABLE(DRAG_SUPPORT) 494 m_dragStartPos = event.event().pos(); 495 #endif 496 497 bool swallowEvent = false; 498 m_mousePressed = true; 499 m_beganSelectingText = false; 500 501 if (event.event().clickCount() == 2) 502 swallowEvent = handleMousePressEventDoubleClick(event); 503 else if (event.event().clickCount() >= 3) 504 swallowEvent = handleMousePressEventTripleClick(event); 505 else 506 swallowEvent = handleMousePressEventSingleClick(event); 507 508 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect 509 || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true)); 510 511 return swallowEvent; 512 } 513 514 // There are two kinds of renderer that can autoscroll. 515 static bool canAutoscroll(RenderObject* renderer) 516 { 517 if (!renderer->isBox()) 518 return false; 519 520 // Check for a box that can be scrolled in its own right. 521 if (toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) 522 return true; 523 524 // Check for a box that represents the top level of a web page. 525 // This can be scrolled by calling Chrome::scrollRectIntoView. 526 // This only has an effect on the Mac platform in applications 527 // that put web views into scrolling containers, such as Mac OS X Mail. 528 // The code for this is in RenderLayer::scrollRectToVisible. 529 if (renderer->node() != renderer->document()) 530 return false; 531 Frame* frame = renderer->frame(); 532 if (!frame) 533 return false; 534 Page* page = frame->page(); 535 return page && page->mainFrame() == frame; 536 } 537 538 #if ENABLE(DRAG_SUPPORT) 539 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) 540 { 541 if (handleDrag(event)) 542 return true; 543 544 if (!m_mousePressed) 545 return false; 546 547 Node* targetNode = EventHandler::targetNode(event); 548 if (event.event().button() != LeftButton || !targetNode || !targetNode->renderer()) 549 return false; 550 551 #if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms? 552 ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll); 553 #endif 554 555 m_mouseDownMayStartDrag = false; 556 557 if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) { 558 // Find a renderer that can autoscroll. 559 RenderObject* renderer = targetNode->renderer(); 560 while (renderer && !canAutoscroll(renderer)) { 561 if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) 562 renderer = renderer->document()->ownerElement()->renderer(); 563 else 564 renderer = renderer->parent(); 565 } 566 567 if (renderer) { 568 m_autoscrollInProgress = true; 569 handleAutoscroll(renderer); 570 } 571 572 m_mouseDownMayStartAutoscroll = false; 573 } 574 575 if (!m_beganSelectingText) { 576 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); 577 HitTestResult result(m_mouseDownPos); 578 m_frame->document()->renderView()->layer()->hitTest(request, result); 579 580 updateSelectionForMouseDrag(result); 581 } 582 updateSelectionForMouseDrag(event.hitTestResult()); 583 return true; 584 } 585 586 bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const 587 { 588 // This is a pre-flight check of whether the event might lead to a drag being started. Be careful 589 // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag 590 // in handleMousePressEvent 591 592 if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer()) 593 return false; 594 595 if (event.button() != LeftButton || event.clickCount() != 1) 596 return false; 597 598 bool DHTMLFlag; 599 bool UAFlag; 600 allowDHTMLDrag(DHTMLFlag, UAFlag); 601 if (!DHTMLFlag && !UAFlag) 602 return false; 603 604 FrameView* view = m_frame->view(); 605 if (!view) 606 return false; 607 608 HitTestRequest request(HitTestRequest::ReadOnly); 609 HitTestResult result(view->windowToContents(event.pos())); 610 m_frame->contentRenderer()->layer()->hitTest(request, result); 611 bool srcIsDHTML; 612 return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML); 613 } 614 615 void EventHandler::updateSelectionForMouseDrag() 616 { 617 FrameView* view = m_frame->view(); 618 if (!view) 619 return; 620 RenderView* renderer = m_frame->contentRenderer(); 621 if (!renderer) 622 return; 623 RenderLayer* layer = renderer->layer(); 624 if (!layer) 625 return; 626 627 HitTestRequest request(HitTestRequest::ReadOnly | 628 HitTestRequest::Active | 629 HitTestRequest::MouseMove); 630 HitTestResult result(view->windowToContents(m_currentMousePosition)); 631 layer->hitTest(request, result); 632 updateSelectionForMouseDrag(result); 633 } 634 635 static VisiblePosition selectionExtentRespectingEditingBoundary(const VisibleSelection& selection, const IntPoint& localPoint, Node* targetNode) 636 { 637 IntPoint selectionEndPoint = localPoint; 638 Element* editableElement = selection.rootEditableElement(); 639 640 if (!targetNode->renderer()) 641 return VisiblePosition(); 642 643 if (editableElement && !editableElement->contains(targetNode)) { 644 if (!editableElement->renderer()) 645 return VisiblePosition(); 646 647 FloatPoint absolutePoint = targetNode->renderer()->localToAbsolute(FloatPoint(selectionEndPoint)); 648 selectionEndPoint = roundedIntPoint(editableElement->renderer()->absoluteToLocal(absolutePoint)); 649 targetNode = editableElement; 650 } 651 652 return targetNode->renderer()->positionForPoint(selectionEndPoint); 653 } 654 655 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult) 656 { 657 if (!m_mouseDownMayStartSelect) 658 return; 659 660 Node* target = targetNode(hitTestResult); 661 if (!target) 662 return; 663 664 if (!canMouseDragExtendSelect(target)) 665 return; 666 667 VisiblePosition targetPosition = selectionExtentRespectingEditingBoundary(m_frame->selection()->selection(), hitTestResult.localPoint(), target); 668 669 // Don't modify the selection if we're not on a node. 670 if (targetPosition.isNull()) 671 return; 672 673 // Restart the selection if this is the first mouse move. This work is usually 674 // done in handleMousePressEvent, but not if the mouse press was on an existing selection. 675 VisibleSelection newSelection = m_frame->selection()->selection(); 676 677 #if ENABLE(SVG) 678 // Special case to limit selection to the containing block for SVG text. 679 // FIXME: Isn't there a better non-SVG-specific way to do this? 680 if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) 681 if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer()) 682 if (selectionBaseRenderer->isSVGText()) 683 if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock()) 684 return; 685 #endif 686 687 if (!m_beganSelectingText) { 688 m_beganSelectingText = true; 689 newSelection = VisibleSelection(targetPosition); 690 } 691 692 newSelection.setExtent(targetPosition); 693 if (m_frame->selection()->granularity() != CharacterGranularity) 694 newSelection.expandUsingGranularity(m_frame->selection()->granularity()); 695 696 setNonDirectionalSelectionIfNeeded(m_frame->selection(), newSelection, m_frame->selection()->granularity()); 697 } 698 #endif // ENABLE(DRAG_SUPPORT) 699 700 void EventHandler::lostMouseCapture() 701 { 702 m_frame->selection()->setCaretBlinkingSuspended(false); 703 } 704 705 bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event) 706 { 707 if (eventLoopHandleMouseUp(event)) 708 return true; 709 710 // If this was the first click in the window, we don't even want to clear the selection. 711 // This case occurs when the user clicks on a draggable element, since we have to process 712 // the mouse down and drag events to see if we might start a drag. For other first clicks 713 // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets 714 // ignored upstream of this layer. 715 return eventActivatedView(event.event()); 716 } 717 718 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event) 719 { 720 if (m_autoscrollInProgress) 721 stopAutoscrollTimer(); 722 723 if (handleMouseUp(event)) 724 return true; 725 726 // Used to prevent mouseMoveEvent from initiating a drag before 727 // the mouse is pressed again. 728 m_frame->selection()->setCaretBlinkingSuspended(false); 729 m_mousePressed = false; 730 m_capturesDragging = false; 731 #if ENABLE(DRAG_SUPPORT) 732 m_mouseDownMayStartDrag = false; 733 #endif 734 m_mouseDownMayStartSelect = false; 735 m_mouseDownMayStartAutoscroll = false; 736 m_mouseDownWasInSubframe = false; 737 738 bool handled = false; 739 740 // Clear the selection if the mouse didn't move after the last mouse 741 // press and it's not a context menu click. We do this so when clicking 742 // on the selection, the selection goes away. However, if we are 743 // editing, place the caret. 744 if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText 745 #if ENABLE(DRAG_SUPPORT) 746 && m_dragStartPos == event.event().pos() 747 #endif 748 && m_frame->selection()->isRange() 749 && event.event().button() != RightButton) { 750 VisibleSelection newSelection; 751 Node* node = targetNode(event); 752 bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled(); 753 if (node && (caretBrowsing || node->rendererIsEditable()) && node->renderer()) { 754 VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint()); 755 newSelection = VisibleSelection(pos); 756 } 757 758 setSelectionIfNeeded(m_frame->selection(), newSelection); 759 760 handled = true; 761 } 762 763 m_frame->selection()->notifyRendererOfSelectionChange(true); 764 765 m_frame->selection()->selectFrameElementInParentIfFullySelected(); 766 767 return handled; 768 } 769 770 void EventHandler::handleAutoscroll(RenderObject* renderer) 771 { 772 // We don't want to trigger the autoscroll or the panScroll if it's already active 773 if (m_autoscrollTimer.isActive()) 774 return; 775 776 setAutoscrollRenderer(renderer); 777 778 #if ENABLE(PAN_SCROLLING) 779 if (m_panScrollInProgress) { 780 m_panScrollStartPos = currentMousePosition(); 781 if (FrameView* view = m_frame->view()) 782 view->addPanScrollIcon(m_panScrollStartPos); 783 // If we're not in the top frame we notify it that we doing a panScroll. 784 if (Page* page = m_frame->page()) { 785 Frame* mainFrame = page->mainFrame(); 786 if (m_frame != mainFrame) 787 mainFrame->eventHandler()->setPanScrollInProgress(true); 788 } 789 } 790 #endif 791 792 startAutoscrollTimer(); 793 } 794 795 void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) 796 { 797 RenderObject* r = autoscrollRenderer(); 798 if (!r || !r->isBox()) { 799 stopAutoscrollTimer(); 800 return; 801 } 802 803 if (m_autoscrollInProgress) { 804 if (!m_mousePressed) { 805 stopAutoscrollTimer(); 806 return; 807 } 808 toRenderBox(r)->autoscroll(); 809 } else { 810 // we verify that the main frame hasn't received the order to stop the panScroll 811 if (Page* page = m_frame->page()) { 812 if (!page->mainFrame()->eventHandler()->panScrollInProgress()) { 813 stopAutoscrollTimer(); 814 return; 815 } 816 } 817 #if ENABLE(PAN_SCROLLING) 818 updatePanScrollState(); 819 toRenderBox(r)->panScroll(m_panScrollStartPos); 820 #endif 821 } 822 } 823 824 #if ENABLE(PAN_SCROLLING) 825 826 void EventHandler::startPanScrolling(RenderObject* renderer) 827 { 828 m_panScrollInProgress = true; 829 m_panScrollButtonPressed = true; 830 handleAutoscroll(renderer); 831 invalidateClick(); 832 } 833 834 void EventHandler::updatePanScrollState() 835 { 836 FrameView* view = m_frame->view(); 837 if (!view) 838 return; 839 840 // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll 841 // So we don't want to change the cursor over this area 842 bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - ScrollView::noPanScrollRadius); 843 bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + ScrollView::noPanScrollRadius); 844 bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + ScrollView::noPanScrollRadius); 845 bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - ScrollView::noPanScrollRadius); 846 847 if ((east || west || north || south) && m_panScrollButtonPressed) 848 m_springLoadedPanScrollInProgress = true; 849 850 if (north) { 851 if (east) 852 view->setCursor(northEastPanningCursor()); 853 else if (west) 854 view->setCursor(northWestPanningCursor()); 855 else 856 view->setCursor(northPanningCursor()); 857 } else if (south) { 858 if (east) 859 view->setCursor(southEastPanningCursor()); 860 else if (west) 861 view->setCursor(southWestPanningCursor()); 862 else 863 view->setCursor(southPanningCursor()); 864 } else if (east) 865 view->setCursor(eastPanningCursor()); 866 else if (west) 867 view->setCursor(westPanningCursor()); 868 else 869 view->setCursor(middlePanningCursor()); 870 } 871 872 #endif // ENABLE(PAN_SCROLLING) 873 874 RenderObject* EventHandler::autoscrollRenderer() const 875 { 876 return m_autoscrollRenderer; 877 } 878 879 void EventHandler::updateAutoscrollRenderer() 880 { 881 if (!m_autoscrollRenderer) 882 return; 883 884 HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true); 885 886 if (Node* nodeAtPoint = hitTest.innerNode()) 887 m_autoscrollRenderer = nodeAtPoint->renderer(); 888 889 while (m_autoscrollRenderer && !canAutoscroll(m_autoscrollRenderer)) 890 m_autoscrollRenderer = m_autoscrollRenderer->parent(); 891 } 892 893 void EventHandler::setAutoscrollRenderer(RenderObject* renderer) 894 { 895 m_autoscrollRenderer = renderer; 896 } 897 898 #if ENABLE(DRAG_SUPPORT) 899 void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const 900 { 901 flagDHTML = false; 902 flagUA = false; 903 904 if (!m_frame) 905 return; 906 907 Page* page = m_frame->page(); 908 if (!page) 909 return; 910 911 FrameView* view = m_frame->view(); 912 if (!view) 913 return; 914 915 unsigned mask = page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos)); 916 flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone; 917 flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection)); 918 } 919 #endif // ENABLE(DRAG_SUPPORT) 920 921 HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping, HitTestScrollbars testScrollbars, HitTestRequest::HitTestRequestType hitType, const IntSize& padding) 922 { 923 HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width()); 924 if (!m_frame->contentRenderer()) 925 return result; 926 if (ignoreClipping) 927 hitType |= HitTestRequest::IgnoreClipping; 928 m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), result); 929 930 while (true) { 931 Node* n = result.innerNode(); 932 if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget()) 933 break; 934 RenderWidget* renderWidget = toRenderWidget(n->renderer()); 935 Widget* widget = renderWidget->widget(); 936 if (!widget || !widget->isFrameView()) 937 break; 938 Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame(); 939 if (!frame || !frame->contentRenderer()) 940 break; 941 FrameView* view = static_cast<FrameView*>(widget); 942 IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(), 943 result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop()); 944 HitTestResult widgetHitTestResult(widgetPoint, padding.height(), padding.width(), padding.height(), padding.width()); 945 frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult); 946 result = widgetHitTestResult; 947 948 if (testScrollbars == ShouldHitTestScrollbars) { 949 Scrollbar* eventScrollbar = view->scrollbarAtPoint(point); 950 if (eventScrollbar) 951 result.setScrollbar(eventScrollbar); 952 } 953 } 954 955 // If our HitTestResult is not visible, then we started hit testing too far down the frame chain. 956 // Another hit test at the main frame level should get us the correct visible result. 957 Frame* resultFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : 0; 958 if (Page* page = m_frame->page()) { 959 Frame* mainFrame = page->mainFrame(); 960 if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) { 961 FrameView* resultView = resultFrame->view(); 962 FrameView* mainView = mainFrame->view(); 963 if (resultView && mainView) { 964 IntPoint windowPoint = resultView->contentsToWindow(result.point()); 965 IntPoint mainFramePoint = mainView->windowToContents(windowPoint); 966 result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping, testScrollbars, hitType, padding); 967 } 968 } 969 } 970 971 if (!allowShadowContent) 972 result.setToNonShadowAncestor(); 973 974 return result; 975 } 976 977 978 void EventHandler::startAutoscrollTimer() 979 { 980 m_autoscrollTimer.startRepeating(autoscrollInterval); 981 } 982 983 void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed) 984 { 985 if (m_autoscrollInProgress) { 986 if (m_mouseDownWasInSubframe) { 987 if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get())) 988 subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDestroyed); 989 return; 990 } 991 } 992 993 if (autoscrollRenderer()) { 994 if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress)) 995 toRenderBox(autoscrollRenderer())->stopAutoscroll(); 996 #if ENABLE(PAN_SCROLLING) 997 if (m_panScrollInProgress) { 998 if (FrameView* view = m_frame->view()) { 999 view->removePanScrollIcon(); 1000 view->setCursor(pointerCursor()); 1001 } 1002 } 1003 #endif 1004 1005 setAutoscrollRenderer(0); 1006 } 1007 1008 m_autoscrollTimer.stop(); 1009 1010 m_panScrollInProgress = false; 1011 m_springLoadedPanScrollInProgress = false; 1012 1013 // If we're not in the top frame we notify it that we are not doing a panScroll any more. 1014 if (Page* page = m_frame->page()) { 1015 Frame* mainFrame = page->mainFrame(); 1016 if (m_frame != mainFrame) 1017 mainFrame->eventHandler()->setPanScrollInProgress(false); 1018 } 1019 1020 m_autoscrollInProgress = false; 1021 } 1022 1023 Node* EventHandler::mousePressNode() const 1024 { 1025 return m_mousePressNode.get(); 1026 } 1027 1028 void EventHandler::setMousePressNode(PassRefPtr<Node> node) 1029 { 1030 m_mousePressNode = node; 1031 } 1032 1033 bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) 1034 { 1035 Node* node = startingNode; 1036 1037 if (!node) 1038 node = m_frame->document()->focusedNode(); 1039 1040 if (!node) 1041 node = m_mousePressNode.get(); 1042 1043 if (node) { 1044 RenderObject* r = node->renderer(); 1045 if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) { 1046 setFrameWasScrolledByUser(); 1047 return true; 1048 } 1049 } 1050 1051 return false; 1052 } 1053 1054 bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode) 1055 { 1056 Node* node = startingNode; 1057 1058 if (!node) 1059 node = m_frame->document()->focusedNode(); 1060 1061 if (!node) 1062 node = m_mousePressNode.get(); 1063 1064 if (node) { 1065 RenderObject* r = node->renderer(); 1066 if (r && !r->isListBox() && r->enclosingBox()->logicalScroll(direction, granularity)) { 1067 setFrameWasScrolledByUser(); 1068 return true; 1069 } 1070 } 1071 1072 return false; 1073 } 1074 1075 bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) 1076 { 1077 // The layout needs to be up to date to determine if we can scroll. We may be 1078 // here because of an onLoad event, in which case the final layout hasn't been performed yet. 1079 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1080 if (scrollOverflow(direction, granularity, startingNode)) 1081 return true; 1082 Frame* frame = m_frame; 1083 FrameView* view = frame->view(); 1084 if (view && view->scroll(direction, granularity)) 1085 return true; 1086 frame = frame->tree()->parent(); 1087 if (!frame) 1088 return false; 1089 return frame->eventHandler()->scrollRecursively(direction, granularity, m_frame->ownerElement()); 1090 } 1091 1092 bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode) 1093 { 1094 // The layout needs to be up to date to determine if we can scroll. We may be 1095 // here because of an onLoad event, in which case the final layout hasn't been performed yet. 1096 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1097 if (logicalScrollOverflow(direction, granularity, startingNode)) 1098 return true; 1099 Frame* frame = m_frame; 1100 FrameView* view = frame->view(); 1101 1102 bool scrolled = false; 1103 #if PLATFORM(MAC) 1104 // Mac also resets the scroll position in the inline direction. 1105 if (granularity == ScrollByDocument && view && view->logicalScroll(ScrollInlineDirectionBackward, ScrollByDocument)) 1106 scrolled = true; 1107 #endif 1108 if (view && view->logicalScroll(direction, granularity)) 1109 scrolled = true; 1110 1111 if (scrolled) 1112 return true; 1113 1114 frame = frame->tree()->parent(); 1115 if (!frame) 1116 return false; 1117 1118 return frame->eventHandler()->logicalScrollRecursively(direction, granularity, m_frame->ownerElement()); 1119 } 1120 1121 IntPoint EventHandler::currentMousePosition() const 1122 { 1123 return m_currentMousePosition; 1124 } 1125 1126 Frame* EventHandler::subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult) 1127 { 1128 if (!hitTestResult.isOverWidget()) 1129 return 0; 1130 return subframeForTargetNode(targetNode(hitTestResult)); 1131 } 1132 1133 Frame* EventHandler::subframeForTargetNode(Node* node) 1134 { 1135 if (!node) 1136 return 0; 1137 1138 RenderObject* renderer = node->renderer(); 1139 if (!renderer || !renderer->isWidget()) 1140 return 0; 1141 1142 Widget* widget = toRenderWidget(renderer)->widget(); 1143 if (!widget || !widget->isFrameView()) 1144 return 0; 1145 1146 return static_cast<FrameView*>(widget)->frame(); 1147 } 1148 1149 static bool isSubmitImage(Node* node) 1150 { 1151 return node && node->hasTagName(inputTag) && static_cast<HTMLInputElement*>(node)->isImageButton(); 1152 } 1153 1154 // Returns true if the node's editable block is not current focused for editing 1155 static bool nodeIsNotBeingEdited(Node* node, Frame* frame) 1156 { 1157 return frame->selection()->rootEditableElement() != node->rootEditableElement(); 1158 } 1159 1160 Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar) 1161 { 1162 Node* node = targetNode(event); 1163 RenderObject* renderer = node ? node->renderer() : 0; 1164 RenderStyle* style = renderer ? renderer->style() : 0; 1165 1166 bool horizontalText = !style || style->isHorizontalWritingMode(); 1167 const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor(); 1168 1169 // During selection, use an I-beam no matter what we're over. 1170 // If you're capturing mouse events for a particular node, don't treat this as a selection. 1171 if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode) 1172 return iBeam; 1173 1174 if (renderer && renderer->isFrameSet()) { 1175 RenderFrameSet* frameSetRenderer = toRenderFrameSet(renderer); 1176 if (frameSetRenderer->canResizeRow(event.localPoint())) 1177 return rowResizeCursor(); 1178 if (frameSetRenderer->canResizeColumn(event.localPoint())) 1179 return columnResizeCursor(); 1180 } 1181 1182 if (style && style->cursors()) { 1183 const CursorList* cursors = style->cursors(); 1184 for (unsigned i = 0; i < cursors->size(); ++i) { 1185 const CachedImage* cimage = 0; 1186 StyleImage* image = (*cursors)[i].image(); 1187 if (image && image->isCachedImage()) 1188 cimage = static_cast<StyleCachedImage*>(image)->cachedImage(); 1189 if (!cimage) 1190 continue; 1191 IntPoint hotSpot = (*cursors)[i].hotSpot(); 1192 // Limit the size of cursors so that they cannot be used to cover UI elements in chrome. 1193 IntSize size = cimage->image()->size(); 1194 if (size.width() > 128 || size.height() > 128) 1195 continue; 1196 if (cimage->image()->isNull()) 1197 break; 1198 if (!cimage->errorOccurred()) 1199 return Cursor(cimage->image(), hotSpot); 1200 } 1201 } 1202 1203 switch (style ? style->cursor() : CURSOR_AUTO) { 1204 case CURSOR_AUTO: { 1205 bool editable = (node && node->rendererIsEditable()); 1206 bool editableLinkEnabled = false; 1207 1208 // If the link is editable, then we need to check the settings to see whether or not the link should be followed 1209 if (editable) { 1210 ASSERT(m_frame->settings()); 1211 switch (m_frame->settings()->editableLinkBehavior()) { 1212 default: 1213 case EditableLinkDefaultBehavior: 1214 case EditableLinkAlwaysLive: 1215 editableLinkEnabled = true; 1216 break; 1217 1218 case EditableLinkNeverLive: 1219 editableLinkEnabled = false; 1220 break; 1221 1222 case EditableLinkLiveWhenNotFocused: 1223 editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || event.event().shiftKey(); 1224 break; 1225 1226 case EditableLinkOnlyLiveWithShiftKey: 1227 editableLinkEnabled = event.event().shiftKey(); 1228 break; 1229 } 1230 } 1231 1232 if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled)) 1233 return handCursor(); 1234 bool inResizer = false; 1235 if (renderer) { 1236 if (RenderLayer* layer = renderer->enclosingLayer()) { 1237 if (FrameView* view = m_frame->view()) 1238 inResizer = layer->isPointInResizeControl(view->windowToContents(event.event().pos())); 1239 } 1240 } 1241 if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar) 1242 return iBeam; 1243 return pointerCursor(); 1244 } 1245 case CURSOR_CROSS: 1246 return crossCursor(); 1247 case CURSOR_POINTER: 1248 return handCursor(); 1249 case CURSOR_MOVE: 1250 return moveCursor(); 1251 case CURSOR_ALL_SCROLL: 1252 return moveCursor(); 1253 case CURSOR_E_RESIZE: 1254 return eastResizeCursor(); 1255 case CURSOR_W_RESIZE: 1256 return westResizeCursor(); 1257 case CURSOR_N_RESIZE: 1258 return northResizeCursor(); 1259 case CURSOR_S_RESIZE: 1260 return southResizeCursor(); 1261 case CURSOR_NE_RESIZE: 1262 return northEastResizeCursor(); 1263 case CURSOR_SW_RESIZE: 1264 return southWestResizeCursor(); 1265 case CURSOR_NW_RESIZE: 1266 return northWestResizeCursor(); 1267 case CURSOR_SE_RESIZE: 1268 return southEastResizeCursor(); 1269 case CURSOR_NS_RESIZE: 1270 return northSouthResizeCursor(); 1271 case CURSOR_EW_RESIZE: 1272 return eastWestResizeCursor(); 1273 case CURSOR_NESW_RESIZE: 1274 return northEastSouthWestResizeCursor(); 1275 case CURSOR_NWSE_RESIZE: 1276 return northWestSouthEastResizeCursor(); 1277 case CURSOR_COL_RESIZE: 1278 return columnResizeCursor(); 1279 case CURSOR_ROW_RESIZE: 1280 return rowResizeCursor(); 1281 case CURSOR_TEXT: 1282 return iBeamCursor(); 1283 case CURSOR_WAIT: 1284 return waitCursor(); 1285 case CURSOR_HELP: 1286 return helpCursor(); 1287 case CURSOR_VERTICAL_TEXT: 1288 return verticalTextCursor(); 1289 case CURSOR_CELL: 1290 return cellCursor(); 1291 case CURSOR_CONTEXT_MENU: 1292 return contextMenuCursor(); 1293 case CURSOR_PROGRESS: 1294 return progressCursor(); 1295 case CURSOR_NO_DROP: 1296 return noDropCursor(); 1297 case CURSOR_ALIAS: 1298 return aliasCursor(); 1299 case CURSOR_COPY: 1300 return copyCursor(); 1301 case CURSOR_NONE: 1302 return noneCursor(); 1303 case CURSOR_NOT_ALLOWED: 1304 return notAllowedCursor(); 1305 case CURSOR_DEFAULT: 1306 return pointerCursor(); 1307 case CURSOR_WEBKIT_ZOOM_IN: 1308 return zoomInCursor(); 1309 case CURSOR_WEBKIT_ZOOM_OUT: 1310 return zoomOutCursor(); 1311 case CURSOR_WEBKIT_GRAB: 1312 return grabCursor(); 1313 case CURSOR_WEBKIT_GRABBING: 1314 return grabbingCursor(); 1315 } 1316 return pointerCursor(); 1317 } 1318 1319 static IntPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint) 1320 { 1321 FrameView* view = frame->view(); 1322 // FIXME: Is it really OK to use the wrong coordinates here when view is 0? 1323 // Historically the code would just crash; this is clearly no worse than that. 1324 return view ? view->windowToContents(windowPoint) : windowPoint; 1325 } 1326 1327 Node* EventHandler::targetNode(const MouseEventWithHitTestResults& event) 1328 { 1329 return targetNode(event.hitTestResult()); 1330 } 1331 1332 Node* EventHandler::targetNode(const HitTestResult& hitTestResult) 1333 { 1334 Node* node = hitTestResult.innerNode(); 1335 if (!node) 1336 return 0; 1337 if (node->inDocument()) 1338 return node; 1339 1340 Element* element = node->parentElement(); 1341 if (element && element->inDocument()) 1342 return element; 1343 1344 return node; 1345 1346 } 1347 1348 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) 1349 { 1350 RefPtr<FrameView> protector(m_frame->view()); 1351 1352 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 1353 1354 cancelFakeMouseMoveEvent(); 1355 m_mousePressed = true; 1356 m_capturesDragging = true; 1357 m_currentMousePosition = mouseEvent.pos(); 1358 m_mouseDownTimestamp = mouseEvent.timestamp(); 1359 #if ENABLE(DRAG_SUPPORT) 1360 m_mouseDownMayStartDrag = false; 1361 #endif 1362 m_mouseDownMayStartSelect = false; 1363 m_mouseDownMayStartAutoscroll = false; 1364 if (FrameView* view = m_frame->view()) 1365 m_mouseDownPos = view->windowToContents(mouseEvent.pos()); 1366 else { 1367 invalidateClick(); 1368 return false; 1369 } 1370 m_mouseDownWasInSubframe = false; 1371 1372 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 1373 // Add IgnoreClipping because fixed position elements are moved only on the 1374 // UI thread. Nodes in fixed position elements are clipped out by the view 1375 // without IgnoreClipping. 1376 HitTestRequest request(HitTestRequest::Active | HitTestRequest::IgnoreClipping); 1377 #else 1378 HitTestRequest request(HitTestRequest::Active); 1379 #endif 1380 // Save the document point we generate in case the window coordinate is invalidated by what happens 1381 // when we dispatch the event. 1382 IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.pos()); 1383 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1384 1385 if (!targetNode(mev)) { 1386 invalidateClick(); 1387 return false; 1388 } 1389 1390 m_mousePressNode = targetNode(mev); 1391 1392 if (InspectorInstrumentation::handleMousePress(m_frame->page())) { 1393 invalidateClick(); 1394 return true; 1395 } 1396 1397 Frame* subframe = subframeForHitTestResult(mev); 1398 if (subframe && passMousePressEventToSubframe(mev, subframe)) { 1399 // Start capturing future events for this frame. We only do this if we didn't clear 1400 // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop. 1401 m_capturesDragging = subframe->eventHandler()->capturesDragging(); 1402 if (m_mousePressed && m_capturesDragging) { 1403 m_capturingMouseEventsNode = targetNode(mev); 1404 m_eventHandlerWillResetCapturingMouseEventsNode = true; 1405 } 1406 invalidateClick(); 1407 return true; 1408 } 1409 1410 #if ENABLE(PAN_SCROLLING) 1411 // We store whether pan scrolling is in progress before calling stopAutoscrollTimer() 1412 // because it will set m_panScrollInProgress to false on return. 1413 bool isPanScrollInProgress = m_frame->page() && m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress(); 1414 if (isPanScrollInProgress || m_autoscrollInProgress) 1415 stopAutoscrollTimer(); 1416 if (isPanScrollInProgress) { 1417 // We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate 1418 // away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>. 1419 invalidateClick(); 1420 return true; 1421 } 1422 #endif 1423 1424 m_clickCount = mouseEvent.clickCount(); 1425 m_clickNode = targetNode(mev); 1426 1427 if (FrameView* view = m_frame->view()) { 1428 RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0; 1429 IntPoint p = view->windowToContents(mouseEvent.pos()); 1430 if (layer && layer->isPointInResizeControl(p)) { 1431 layer->setInResizeMode(true); 1432 m_resizeLayer = layer; 1433 m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p); 1434 invalidateClick(); 1435 return true; 1436 } 1437 } 1438 1439 m_frame->selection()->setCaretBlinkingSuspended(true); 1440 1441 bool swallowEvent = dispatchMouseEvent(eventNames().mousedownEvent, targetNode(mev), true, m_clickCount, mouseEvent, true); 1442 m_capturesDragging = !swallowEvent; 1443 1444 // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults 1445 // in case the scrollbar widget was destroyed when the mouse event was handled. 1446 if (mev.scrollbar()) { 1447 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get(); 1448 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); 1449 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1450 if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get()) 1451 m_lastScrollbarUnderMouse = 0; 1452 } 1453 1454 if (swallowEvent) { 1455 // scrollbars should get events anyway, even disabled controls might be scrollable 1456 Scrollbar* scrollbar = mev.scrollbar(); 1457 1458 updateLastScrollbarUnderMouse(scrollbar, true); 1459 1460 if (scrollbar) 1461 passMousePressEventToScrollbar(mev, scrollbar); 1462 } else { 1463 // Refetch the event target node if it currently is the shadow node inside an <input> element. 1464 // If a mouse event handler changes the input element type to one that has a widget associated, 1465 // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the 1466 // event target node can't still be the shadow node. 1467 if (targetNode(mev)->isShadowRoot() && targetNode(mev)->shadowHost()->hasTagName(inputTag)) { 1468 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); 1469 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1470 } 1471 1472 FrameView* view = m_frame->view(); 1473 Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.pos()) : 0; 1474 if (!scrollbar) 1475 scrollbar = mev.scrollbar(); 1476 1477 updateLastScrollbarUnderMouse(scrollbar, true); 1478 1479 if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar)) 1480 swallowEvent = true; 1481 else 1482 swallowEvent = handleMousePressEvent(mev); 1483 } 1484 1485 return swallowEvent; 1486 } 1487 1488 // This method only exists for platforms that don't know how to deliver 1489 bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent) 1490 { 1491 RefPtr<FrameView> protector(m_frame->view()); 1492 1493 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 1494 1495 // We get this instead of a second mouse-up 1496 m_mousePressed = false; 1497 m_currentMousePosition = mouseEvent.pos(); 1498 1499 HitTestRequest request(HitTestRequest::Active); 1500 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); 1501 Frame* subframe = subframeForHitTestResult(mev); 1502 if (m_eventHandlerWillResetCapturingMouseEventsNode) 1503 m_capturingMouseEventsNode = 0; 1504 if (subframe && passMousePressEventToSubframe(mev, subframe)) 1505 return true; 1506 1507 m_clickCount = mouseEvent.clickCount(); 1508 bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, targetNode(mev), true, m_clickCount, mouseEvent, false); 1509 1510 bool swallowClickEvent = mouseEvent.button() != RightButton && targetNode(mev) == m_clickNode && dispatchMouseEvent(eventNames().clickEvent, targetNode(mev), true, m_clickCount, mouseEvent, true); 1511 1512 if (m_lastScrollbarUnderMouse) 1513 swallowMouseUpEvent = m_lastScrollbarUnderMouse->mouseUp(); 1514 1515 bool swallowMouseReleaseEvent = !swallowMouseUpEvent && handleMouseReleaseEvent(mev); 1516 1517 invalidateClick(); 1518 1519 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; 1520 } 1521 1522 static RenderLayer* layerForNode(Node* node) 1523 { 1524 if (!node) 1525 return 0; 1526 1527 RenderObject* renderer = node->renderer(); 1528 if (!renderer) 1529 return 0; 1530 1531 RenderLayer* layer = renderer->enclosingLayer(); 1532 if (!layer) 1533 return 0; 1534 1535 return layer; 1536 } 1537 1538 bool EventHandler::mouseMoved(const PlatformMouseEvent& event) 1539 { 1540 HitTestResult hoveredNode = HitTestResult(IntPoint()); 1541 bool result = handleMouseMoveEvent(event, &hoveredNode); 1542 1543 Page* page = m_frame->page(); 1544 if (!page) 1545 return result; 1546 1547 if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) { 1548 if (page->containsScrollableArea(layer)) 1549 layer->scrollAnimator()->mouseMovedInContentArea(); 1550 } 1551 1552 if (FrameView* frameView = m_frame->view()) 1553 frameView->scrollAnimator()->mouseMovedInContentArea(); 1554 1555 hoveredNode.setToNonShadowAncestor(); 1556 page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags()); 1557 page->chrome()->setToolTip(hoveredNode); 1558 return result; 1559 } 1560 1561 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode) 1562 { 1563 // in Radar 3703768 we saw frequent crashes apparently due to the 1564 // part being null here, which seems impossible, so check for nil 1565 // but also assert so that we can try to figure this out in debug 1566 // builds, if it happens. 1567 ASSERT(m_frame); 1568 if (!m_frame) 1569 return false; 1570 1571 RefPtr<FrameView> protector(m_frame->view()); 1572 m_currentMousePosition = mouseEvent.pos(); 1573 1574 if (m_hoverTimer.isActive()) 1575 m_hoverTimer.stop(); 1576 1577 cancelFakeMouseMoveEvent(); 1578 1579 #if ENABLE(SVG) 1580 if (m_svgPan) { 1581 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition); 1582 return true; 1583 } 1584 #endif 1585 1586 if (m_frameSetBeingResized) 1587 return dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false); 1588 1589 // Send events right to a scrollbar if the mouse is pressed. 1590 if (m_lastScrollbarUnderMouse && m_mousePressed) 1591 return m_lastScrollbarUnderMouse->mouseMoved(mouseEvent); 1592 1593 // Treat mouse move events while the mouse is pressed as "read-only" in prepareMouseEvent 1594 // if we are allowed to select. 1595 // This means that :hover and :active freeze in the state they were in when the mouse 1596 // was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down. 1597 HitTestRequest::HitTestRequestType hitType = HitTestRequest::MouseMove; 1598 if (m_mousePressed && m_mouseDownMayStartSelect) 1599 hitType |= HitTestRequest::ReadOnly; 1600 if (m_mousePressed) 1601 hitType |= HitTestRequest::Active; 1602 1603 #if ENABLE(TOUCH_EVENTS) 1604 // Treat any mouse move events as readonly if the user is currently touching the screen. 1605 if (m_touchPressed) 1606 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; 1607 #endif 1608 HitTestRequest request(hitType); 1609 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); 1610 if (hoveredNode) 1611 *hoveredNode = mev.hitTestResult(); 1612 1613 Scrollbar* scrollbar = 0; 1614 1615 if (m_resizeLayer && m_resizeLayer->inResizeMode()) 1616 m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner); 1617 else { 1618 if (FrameView* view = m_frame->view()) 1619 scrollbar = view->scrollbarAtPoint(mouseEvent.pos()); 1620 1621 if (!scrollbar) 1622 scrollbar = mev.scrollbar(); 1623 1624 updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed); 1625 } 1626 1627 bool swallowEvent = false; 1628 RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); 1629 1630 // We want mouseouts to happen first, from the inside out. First send a move event to the last subframe so that it will fire mouseouts. 1631 if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe) 1632 passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get()); 1633 1634 if (newSubframe) { 1635 // Update over/out state before passing the event to the subframe. 1636 updateMouseEventTargetNode(targetNode(mev), mouseEvent, true); 1637 1638 // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target 1639 // node to be detached from its FrameView, in which case the event should not be passed. 1640 if (newSubframe->view()) 1641 swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode); 1642 } else { 1643 if (scrollbar && !m_mousePressed) 1644 scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering. 1645 if (Page* page = m_frame->page()) { 1646 if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) { 1647 // Plugins set cursor on their own. The only case WebKit intervenes is resetting cursor to arrow on mouse enter, 1648 // in case the particular plugin doesn't manipulate cursor at all. Thus, even a CSS cursor set on body has no 1649 // effect on plugins (which matches Firefox). 1650 bool overPluginElement = false; 1651 if (targetNode(mev) && targetNode(mev)->isHTMLElement()) { 1652 HTMLElement* el = toHTMLElement(targetNode(mev)); 1653 overPluginElement = el->hasTagName(appletTag) || el->hasTagName(objectTag) || el->hasTagName(embedTag); 1654 } 1655 if (!overPluginElement) { 1656 if (FrameView* view = m_frame->view()) 1657 view->setCursor(selectCursor(mev, scrollbar)); 1658 } 1659 } 1660 } 1661 } 1662 1663 m_lastMouseMoveEventSubframe = newSubframe; 1664 1665 if (swallowEvent) 1666 return true; 1667 1668 swallowEvent = dispatchMouseEvent(eventNames().mousemoveEvent, targetNode(mev), false, 0, mouseEvent, true); 1669 #if ENABLE(DRAG_SUPPORT) 1670 if (!swallowEvent) 1671 swallowEvent = handleMouseDraggedEvent(mev); 1672 #endif // ENABLE(DRAG_SUPPORT) 1673 1674 return swallowEvent; 1675 } 1676 1677 void EventHandler::invalidateClick() 1678 { 1679 m_clickCount = 0; 1680 m_clickNode = 0; 1681 } 1682 1683 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) 1684 { 1685 RefPtr<FrameView> protector(m_frame->view()); 1686 1687 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 1688 1689 #if ENABLE(PAN_SCROLLING) 1690 if (mouseEvent.button() == MiddleButton) 1691 m_panScrollButtonPressed = false; 1692 if (m_springLoadedPanScrollInProgress) 1693 stopAutoscrollTimer(); 1694 #endif 1695 1696 m_mousePressed = false; 1697 m_currentMousePosition = mouseEvent.pos(); 1698 1699 #if ENABLE(SVG) 1700 if (m_svgPan) { 1701 m_svgPan = false; 1702 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMousePosition); 1703 return true; 1704 } 1705 #endif 1706 1707 if (m_frameSetBeingResized) 1708 return dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false); 1709 1710 if (m_lastScrollbarUnderMouse) { 1711 invalidateClick(); 1712 return m_lastScrollbarUnderMouse->mouseUp(); 1713 } 1714 1715 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 1716 // Add IgnoreClipping because fixed position elements are moved only on the 1717 // UI thread. Nodes in fixed position elements are clipped out by the view 1718 // without IgnoreClipping. 1719 HitTestRequest request(HitTestRequest::MouseUp | HitTestRequest::IgnoreClipping); 1720 #else 1721 HitTestRequest request(HitTestRequest::MouseUp); 1722 #endif 1723 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); 1724 Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); 1725 if (m_eventHandlerWillResetCapturingMouseEventsNode) 1726 m_capturingMouseEventsNode = 0; 1727 if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) 1728 return true; 1729 1730 bool swallowMouseUpEvent = dispatchMouseEvent(eventNames().mouseupEvent, targetNode(mev), true, m_clickCount, mouseEvent, false); 1731 1732 bool swallowClickEvent = m_clickCount > 0 && mouseEvent.button() != RightButton && targetNode(mev) == m_clickNode && dispatchMouseEvent(eventNames().clickEvent, targetNode(mev), true, m_clickCount, mouseEvent, true); 1733 1734 if (m_resizeLayer) { 1735 m_resizeLayer->setInResizeMode(false); 1736 m_resizeLayer = 0; 1737 } 1738 1739 bool swallowMouseReleaseEvent = false; 1740 if (!swallowMouseUpEvent) 1741 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); 1742 1743 invalidateClick(); 1744 1745 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; 1746 } 1747 1748 #if ENABLE(DRAG_SUPPORT) 1749 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard) 1750 { 1751 FrameView* view = m_frame->view(); 1752 1753 // FIXME: We might want to dispatch a dragleave even if the view is gone. 1754 if (!view) 1755 return false; 1756 1757 view->resetDeferredRepaintDelay(); 1758 RefPtr<MouseEvent> me = MouseEvent::create(eventType, 1759 true, true, m_frame->document()->defaultView(), 1760 0, event.globalX(), event.globalY(), event.x(), event.y(), 1761 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), 1762 0, 0, clipboard); 1763 1764 ExceptionCode ec; 1765 dragTarget->dispatchEvent(me.get(), ec); 1766 return me->defaultPrevented(); 1767 } 1768 1769 bool EventHandler::canHandleDragAndDropForTarget(DragAndDropHandleType type, Node* target, const PlatformMouseEvent& event, Clipboard* clipboard, bool* accepted) 1770 { 1771 bool canHandle = false; 1772 bool wasAccepted = false; 1773 1774 if (target->hasTagName(frameTag) || target->hasTagName(iframeTag)) { 1775 Frame* frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame(); 1776 if (frame) { 1777 switch (type) { 1778 case UpdateDragAndDrop: 1779 wasAccepted = frame->eventHandler()->updateDragAndDrop(event, clipboard); 1780 break; 1781 case CancelDragAndDrop: 1782 frame->eventHandler()->cancelDragAndDrop(event, clipboard); 1783 break; 1784 case PerformDragAndDrop: 1785 wasAccepted = frame->eventHandler()->performDragAndDrop(event, clipboard); 1786 break; 1787 } 1788 } 1789 } else 1790 canHandle = true; 1791 1792 if (accepted) 1793 *accepted = wasAccepted; 1794 1795 return canHandle; 1796 } 1797 1798 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1799 { 1800 bool accept = false; 1801 1802 if (!m_frame->view()) 1803 return false; 1804 1805 HitTestRequest request(HitTestRequest::ReadOnly); 1806 MouseEventWithHitTestResults mev = prepareMouseEvent(request, event); 1807 1808 // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch) 1809 Node* newTarget = targetNode(mev); 1810 if (newTarget && newTarget->isTextNode()) 1811 newTarget = newTarget->parentNode(); 1812 if (newTarget) 1813 newTarget = newTarget->shadowAncestorNode(); 1814 1815 if (m_dragTarget != newTarget) { 1816 // FIXME: this ordering was explicitly chosen to match WinIE. However, 1817 // it is sometimes incorrect when dragging within subframes, as seen with 1818 // LayoutTests/fast/events/drag-in-frames.html. 1819 // 1820 // Moreover, this ordering conforms to section 7.9.4 of the HTML 5 spec. <http://dev.w3.org/html5/spec/Overview.html#drag-and-drop-processing-model>. 1821 if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { 1822 // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event. 1823 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { 1824 // for now we don't care if event handler cancels default behavior, since there is none 1825 dispatchDragSrcEvent(eventNames().dragEvent, event); 1826 } 1827 accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard); 1828 } 1829 1830 if (m_dragTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, m_dragTarget.get(), event, clipboard, &accept)) 1831 dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); 1832 1833 if (newTarget) { 1834 // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that 1835 // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function. 1836 m_shouldOnlyFireDragOverEvent = true; 1837 } 1838 } else { 1839 if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { 1840 // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. 1841 if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { 1842 // for now we don't care if event handler cancels default behavior, since there is none 1843 dispatchDragSrcEvent(eventNames().dragEvent, event); 1844 } 1845 accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard); 1846 m_shouldOnlyFireDragOverEvent = false; 1847 } 1848 } 1849 m_dragTarget = newTarget; 1850 1851 return accept; 1852 } 1853 1854 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1855 { 1856 if (m_dragTarget && canHandleDragAndDropForTarget(CancelDragAndDrop, m_dragTarget.get(), event, clipboard)) { 1857 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) 1858 dispatchDragSrcEvent(eventNames().dragEvent, event); 1859 dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); 1860 } 1861 clearDragState(); 1862 } 1863 1864 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1865 { 1866 bool accept = false; 1867 if (m_dragTarget && canHandleDragAndDropForTarget(PerformDragAndDrop, m_dragTarget.get(), event, clipboard, &accept)) 1868 dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard); 1869 clearDragState(); 1870 return accept; 1871 } 1872 1873 void EventHandler::clearDragState() 1874 { 1875 m_dragTarget = 0; 1876 m_capturingMouseEventsNode = 0; 1877 m_shouldOnlyFireDragOverEvent = false; 1878 #if PLATFORM(MAC) 1879 m_sendingEventToSubview = false; 1880 #endif 1881 } 1882 #endif // ENABLE(DRAG_SUPPORT) 1883 1884 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS) 1885 void EventHandler::setCapturingTouchEventsNode(PassRefPtr<Node> n) 1886 { 1887 m_capturingTouchEventsNode = n; 1888 } 1889 #endif 1890 1891 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n) 1892 { 1893 m_capturingMouseEventsNode = n; 1894 m_eventHandlerWillResetCapturingMouseEventsNode = false; 1895 } 1896 1897 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev) 1898 { 1899 ASSERT(m_frame); 1900 ASSERT(m_frame->document()); 1901 1902 return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.pos()), mev); 1903 } 1904 1905 #if ENABLE(SVG) 1906 static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode) 1907 { 1908 if (!referenceNode || !referenceNode->isSVGElement()) 1909 return 0; 1910 1911 Node* shadowTreeElement = referenceNode->shadowTreeRootNode(); 1912 if (!shadowTreeElement) 1913 return 0; 1914 1915 Element* shadowTreeParentElement = shadowTreeElement->shadowHost(); 1916 if (!shadowTreeParentElement) 1917 return 0; 1918 1919 ASSERT(shadowTreeParentElement->hasTagName(useTag)); 1920 return static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode); 1921 } 1922 #endif 1923 1924 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut) 1925 { 1926 Node* result = targetNode; 1927 1928 // If we're capturing, we always go right to that node. 1929 if (m_capturingMouseEventsNode) 1930 result = m_capturingMouseEventsNode.get(); 1931 else { 1932 // If the target node is a text node, dispatch on the parent node - rdar://4196646 1933 if (result && result->isTextNode()) 1934 result = result->parentNode(); 1935 } 1936 m_nodeUnderMouse = result; 1937 #if ENABLE(SVG) 1938 m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result); 1939 1940 // <use> shadow tree elements may have been recloned, update node under mouse in any case 1941 if (m_lastInstanceUnderMouse) { 1942 SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement(); 1943 SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement(); 1944 1945 if (lastCorrespondingElement && lastCorrespondingUseElement) { 1946 HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement(); 1947 1948 // Locate the recloned shadow tree element for our corresponding instance 1949 HashSet<SVGElementInstance*>::iterator end = instances.end(); 1950 for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) { 1951 SVGElementInstance* instance = (*it); 1952 ASSERT(instance->correspondingElement() == lastCorrespondingElement); 1953 1954 if (instance == m_lastInstanceUnderMouse) 1955 continue; 1956 1957 if (instance->correspondingUseElement() != lastCorrespondingUseElement) 1958 continue; 1959 1960 SVGElement* shadowTreeElement = instance->shadowTreeElement(); 1961 if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement) 1962 continue; 1963 1964 m_lastNodeUnderMouse = shadowTreeElement; 1965 m_lastInstanceUnderMouse = instance; 1966 break; 1967 } 1968 } 1969 } 1970 #endif 1971 1972 // Fire mouseout/mouseover if the mouse has shifted to a different node. 1973 if (fireMouseOverOut) { 1974 RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get()); 1975 RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get()); 1976 Page* page = m_frame->page(); 1977 1978 if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) { 1979 // The mouse has moved between frames. 1980 if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) { 1981 if (FrameView* frameView = frame->view()) 1982 frameView->scrollAnimator()->mouseExitedContentArea(); 1983 } 1984 } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) { 1985 // The mouse has moved between layers. 1986 if (page->containsScrollableArea(layerForLastNode)) 1987 layerForLastNode->scrollAnimator()->mouseExitedContentArea(); 1988 } 1989 1990 if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) { 1991 // The mouse has moved between frames. 1992 if (Frame* frame = m_nodeUnderMouse->document()->frame()) { 1993 if (FrameView* frameView = frame->view()) 1994 frameView->scrollAnimator()->mouseEnteredContentArea(); 1995 } 1996 } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) { 1997 // The mouse has moved between layers. 1998 if (page->containsScrollableArea(layerForNodeUnderMouse)) 1999 layerForNodeUnderMouse->scrollAnimator()->mouseEnteredContentArea(); 2000 } 2001 2002 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) { 2003 m_lastNodeUnderMouse = 0; 2004 m_lastScrollbarUnderMouse = 0; 2005 #if ENABLE(SVG) 2006 m_lastInstanceUnderMouse = 0; 2007 #endif 2008 } 2009 2010 if (m_lastNodeUnderMouse != m_nodeUnderMouse) { 2011 // send mouseout event to the old node 2012 if (m_lastNodeUnderMouse) 2013 m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get()); 2014 // send mouseover event to the new node 2015 if (m_nodeUnderMouse) 2016 m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get()); 2017 } 2018 m_lastNodeUnderMouse = m_nodeUnderMouse; 2019 #if ENABLE(SVG) 2020 m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get()); 2021 #endif 2022 } 2023 } 2024 2025 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) 2026 { 2027 if (FrameView* view = m_frame->view()) 2028 view->resetDeferredRepaintDelay(); 2029 2030 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); 2031 2032 bool swallowEvent = false; 2033 2034 if (m_nodeUnderMouse) 2035 swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount); 2036 2037 if (!swallowEvent && eventType == eventNames().mousedownEvent) { 2038 2039 // If clicking on a frame scrollbar, do not mess up with content focus. 2040 if (FrameView* view = m_frame->view()) { 2041 if (view->scrollbarAtPoint(mouseEvent.pos())) 2042 return false; 2043 } 2044 2045 // The layout needs to be up to date to determine if an element is focusable. 2046 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 2047 2048 // Blur current focus node when a link/button is clicked; this 2049 // is expected by some sites that rely on onChange handlers running 2050 // from form fields before the button click is processed. 2051 Node* node = m_nodeUnderMouse.get(); 2052 2053 // Walk up the DOM tree to search for a node to focus. 2054 while (node) { 2055 if (node->isMouseFocusable()) { 2056 // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a 2057 // node on mouse down if it's selected and inside a focused node. It will be 2058 // focused if the user does a mouseup over it, however, because the mouseup 2059 // will set a selection inside it, which will call setFocuseNodeIfNeeded. 2060 ExceptionCode ec = 0; 2061 Node* n = node->isShadowRoot() ? node->shadowHost() : node; 2062 if (m_frame->selection()->isRange() 2063 && m_frame->selection()->toNormalizedRange()->compareNode(n, ec) == Range::NODE_INSIDE 2064 && n->isDescendantOf(m_frame->document()->focusedNode())) 2065 return false; 2066 2067 break; 2068 } 2069 node = node->parentOrHostNode(); 2070 } 2071 2072 // If focus shift is blocked, we eat the event. Note we should never clear swallowEvent 2073 // if the page already set it (e.g., by canceling default behavior). 2074 if (Page* page = m_frame->page()) { 2075 if (node && node->isMouseFocusable()) { 2076 if (!page->focusController()->setFocusedNode(node, m_frame)) 2077 swallowEvent = true; 2078 } else if (!node || !node->focused()) { 2079 if (!page->focusController()->setFocusedNode(0, m_frame)) 2080 swallowEvent = true; 2081 } 2082 } 2083 } 2084 2085 return swallowEvent; 2086 } 2087 2088 #if !PLATFORM(GTK) && !(PLATFORM(CHROMIUM) && (OS(LINUX) || OS(FREEBSD))) 2089 bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult&) const 2090 { 2091 return false; 2092 } 2093 #endif 2094 2095 bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) 2096 { 2097 Document* doc = m_frame->document(); 2098 2099 RenderObject* docRenderer = doc->renderer(); 2100 if (!docRenderer) 2101 return false; 2102 2103 RefPtr<FrameView> protector(m_frame->view()); 2104 2105 FrameView* view = m_frame->view(); 2106 if (!view) 2107 return false; 2108 setFrameWasScrolledByUser(); 2109 IntPoint vPoint = view->windowToContents(e.pos()); 2110 2111 Node* node; 2112 bool isOverWidget; 2113 2114 HitTestRequest request(HitTestRequest::ReadOnly); 2115 HitTestResult result(vPoint); 2116 doc->renderView()->layer()->hitTest(request, result); 2117 2118 #if PLATFORM(MAC) 2119 m_useLatchedWheelEventNode = e.momentumPhase() == PlatformWheelEventPhaseBegan || e.momentumPhase() == PlatformWheelEventPhaseChanged; 2120 #endif 2121 2122 if (m_useLatchedWheelEventNode) { 2123 if (!m_latchedWheelEventNode) { 2124 m_latchedWheelEventNode = result.innerNode(); 2125 m_widgetIsLatched = result.isOverWidget(); 2126 } 2127 2128 node = m_latchedWheelEventNode.get(); 2129 isOverWidget = m_widgetIsLatched; 2130 } else { 2131 if (m_latchedWheelEventNode) 2132 m_latchedWheelEventNode = 0; 2133 if (m_previousWheelScrolledNode) 2134 m_previousWheelScrolledNode = 0; 2135 2136 node = result.innerNode(); 2137 isOverWidget = result.isOverWidget(); 2138 } 2139 2140 if (shouldTurnVerticalTicksIntoHorizontal(result)) 2141 e.turnVerticalTicksIntoHorizontal(); 2142 2143 if (node) { 2144 // Figure out which view to send the event to. 2145 RenderObject* target = node->renderer(); 2146 2147 if (isOverWidget && target && target->isWidget()) { 2148 Widget* widget = toRenderWidget(target)->widget(); 2149 if (widget && passWheelEventToWidget(e, widget)) { 2150 e.accept(); 2151 return true; 2152 } 2153 } 2154 2155 node = node->shadowAncestorNode(); 2156 if (!node->dispatchWheelEvent(e)) { 2157 e.accept(); 2158 return true; 2159 } 2160 } 2161 2162 if (e.isAccepted()) 2163 return true; 2164 2165 view = m_frame->view(); 2166 if (!view) 2167 return false; 2168 2169 view->wheelEvent(e); 2170 return e.isAccepted(); 2171 } 2172 2173 void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent) 2174 { 2175 if (!startNode || !wheelEvent) 2176 return; 2177 2178 Node* stopNode = m_previousWheelScrolledNode.get(); 2179 2180 // Break up into two scrolls if we need to. Diagonal movement on 2181 // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set). 2182 if (scrollNode(wheelEvent->rawDeltaX(), wheelEvent->granularity(), ScrollLeft, ScrollRight, startNode, &stopNode)) 2183 wheelEvent->setDefaultHandled(); 2184 2185 if (scrollNode(wheelEvent->rawDeltaY(), wheelEvent->granularity(), ScrollUp, ScrollDown, startNode, &stopNode)) 2186 wheelEvent->setDefaultHandled(); 2187 2188 if (!m_useLatchedWheelEventNode) 2189 m_previousWheelScrolledNode = stopNode; 2190 } 2191 2192 #if ENABLE(GESTURE_EVENTS) 2193 bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) 2194 { 2195 // FIXME: This should hit test and go to the correct subframe rather than 2196 // always sending gestures to the main frame only. We should also ensure 2197 // that if a frame gets a gesture begin gesture, it gets the corresponding 2198 // end gesture as well. 2199 2200 FrameView* view = m_frame->view(); 2201 if (!view) 2202 return false; 2203 2204 view->handleGestureEvent(gestureEvent); 2205 return true; 2206 } 2207 #endif 2208 2209 #if ENABLE(CONTEXT_MENUS) 2210 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) 2211 { 2212 Document* doc = m_frame->document(); 2213 FrameView* v = m_frame->view(); 2214 if (!v) 2215 return false; 2216 2217 bool swallowEvent; 2218 IntPoint viewportPos = v->windowToContents(event.pos()); 2219 HitTestRequest request(HitTestRequest::Active); 2220 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event); 2221 2222 if (m_frame->editor()->behavior().shouldSelectOnContextualMenuClick() 2223 && !m_frame->selection()->contains(viewportPos) 2224 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. 2225 // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items 2226 // available for text selections. But only if we're above text. 2227 && (m_frame->selection()->isContentEditable() || (targetNode(mev) && targetNode(mev)->isTextNode()))) { 2228 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection 2229 selectClosestWordOrLinkFromMouseEvent(mev); 2230 } 2231 2232 swallowEvent = dispatchMouseEvent(eventNames().contextmenuEvent, targetNode(mev), true, 0, event, false); 2233 2234 return swallowEvent; 2235 } 2236 2237 bool EventHandler::sendContextMenuEventForKey() 2238 { 2239 FrameView* view = m_frame->view(); 2240 if (!view) 2241 return false; 2242 2243 Document* doc = m_frame->document(); 2244 if (!doc) 2245 return false; 2246 2247 static const int kContextMenuMargin = 1; 2248 2249 #if OS(WINDOWS) && !OS(WINCE) 2250 int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT); 2251 #else 2252 int rightAligned = 0; 2253 #endif 2254 IntPoint location; 2255 2256 Node* focusedNode = doc->focusedNode(); 2257 SelectionController* selectionController = m_frame->selection(); 2258 Position start = selectionController->selection().start(); 2259 2260 if (start.deprecatedNode() && (selectionController->rootEditableElement() || selectionController->isRange())) { 2261 RefPtr<Range> selection = selectionController->toNormalizedRange(); 2262 IntRect firstRect = m_frame->editor()->firstRectForRange(selection.get()); 2263 2264 int x = rightAligned ? firstRect.maxX() : firstRect.x(); 2265 location = IntPoint(x, firstRect.maxY()); 2266 } else if (focusedNode) { 2267 RenderBoxModelObject* box = focusedNode->renderBoxModelObject(); 2268 if (!box) 2269 return false; 2270 IntRect clippedRect = box->absoluteClippedOverflowRect(); 2271 location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1); 2272 } else { 2273 location = IntPoint( 2274 rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin, 2275 kContextMenuMargin); 2276 } 2277 2278 m_frame->view()->setCursor(pointerCursor()); 2279 2280 IntPoint position = view->contentsToWindow(location); 2281 IntPoint globalPosition = view->contentsToScreen(IntRect(location, IntSize())).location(); 2282 2283 Node* targetNode = doc->focusedNode(); 2284 if (!targetNode) 2285 targetNode = doc; 2286 2287 // Use the focused node as the target for hover and active. 2288 HitTestResult result(position); 2289 result.setInnerNode(targetNode); 2290 HitTestRequest request(HitTestRequest::Active); 2291 doc->renderView()->layer()->updateHoverActiveState(request, result); 2292 doc->updateStyleIfNeeded(); 2293 2294 // The contextmenu event is a mouse event even when invoked using the keyboard. 2295 // This is required for web compatibility. 2296 2297 #if OS(WINDOWS) 2298 MouseEventType eventType = MouseEventReleased; 2299 #else 2300 MouseEventType eventType = MouseEventPressed; 2301 #endif 2302 2303 PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime()); 2304 2305 return dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, mouseEvent, false); 2306 } 2307 2308 #endif // ENABLE(CONTEXT_MENUS) 2309 2310 void EventHandler::scheduleHoverStateUpdate() 2311 { 2312 if (!m_hoverTimer.isActive()) 2313 m_hoverTimer.startOneShot(0); 2314 } 2315 2316 void EventHandler::dispatchFakeMouseMoveEventSoon() 2317 { 2318 if (m_mousePressed) 2319 return; 2320 2321 if (!m_fakeMouseMoveEventTimer.isActive()) 2322 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval); 2323 } 2324 2325 void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad) 2326 { 2327 FrameView* view = m_frame->view(); 2328 if (!view) 2329 return; 2330 2331 if (m_mousePressed || !quad.containsPoint(view->windowToContents(m_currentMousePosition))) 2332 return; 2333 2334 if (!m_fakeMouseMoveEventTimer.isActive()) 2335 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveInterval); 2336 } 2337 2338 void EventHandler::cancelFakeMouseMoveEvent() 2339 { 2340 m_fakeMouseMoveEventTimer.stop(); 2341 } 2342 2343 void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer) 2344 { 2345 ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer); 2346 ASSERT(!m_mousePressed); 2347 2348 FrameView* view = m_frame->view(); 2349 if (!view) 2350 return; 2351 2352 bool shiftKey; 2353 bool ctrlKey; 2354 bool altKey; 2355 bool metaKey; 2356 PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey); 2357 IntPoint globalPoint = view->contentsToScreen(IntRect(view->windowToContents(m_currentMousePosition), IntSize())).location(); 2358 PlatformMouseEvent fakeMouseMoveEvent(m_currentMousePosition, globalPoint, NoButton, MouseEventMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime()); 2359 mouseMoved(fakeMouseMoveEvent); 2360 } 2361 2362 // Whether or not a mouse down can begin the creation of a selection. Fires the selectStart event. 2363 bool EventHandler::canMouseDownStartSelect(Node* node) 2364 { 2365 if (!node || !node->renderer()) 2366 return true; 2367 2368 // Some controls and images can't start a select on a mouse down. 2369 if (!node->canStartSelection()) 2370 return false; 2371 2372 return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)); 2373 } 2374 2375 #if ENABLE(DRAG_SUPPORT) 2376 bool EventHandler::canMouseDragExtendSelect(Node* node) 2377 { 2378 if (!node || !node->renderer()) 2379 return true; 2380 2381 return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)); 2382 } 2383 #endif // ENABLE(DRAG_SUPPORT) 2384 2385 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet) 2386 { 2387 m_frameSetBeingResized = frameSet; 2388 } 2389 2390 void EventHandler::resizeLayerDestroyed() 2391 { 2392 ASSERT(m_resizeLayer); 2393 m_resizeLayer = 0; 2394 } 2395 2396 void EventHandler::hoverTimerFired(Timer<EventHandler>*) 2397 { 2398 m_hoverTimer.stop(); 2399 2400 ASSERT(m_frame); 2401 ASSERT(m_frame->document()); 2402 2403 if (RenderView* renderer = m_frame->contentRenderer()) { 2404 if (FrameView* view = m_frame->view()) { 2405 HitTestRequest request(HitTestRequest::MouseMove); 2406 HitTestResult result(view->windowToContents(m_currentMousePosition)); 2407 renderer->layer()->hitTest(request, result); 2408 m_frame->document()->updateStyleIfNeeded(); 2409 } 2410 } 2411 } 2412 2413 static Node* eventTargetNodeForDocument(Document* doc) 2414 { 2415 if (!doc) 2416 return 0; 2417 Node* node = doc->focusedNode(); 2418 #if defined(ANDROID_PLUGINS) 2419 if (!node && doc->frame() && doc->frame()->view()) 2420 node = android::WebViewCore::getWebViewCore(doc->frame()->view()) 2421 ->cursorNodeIsPlugin(); 2422 #else 2423 if (!node && doc->isPluginDocument()) { 2424 PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc); 2425 node = pluginDocument->pluginNode(); 2426 } 2427 #endif 2428 if (!node && doc->isHTMLDocument()) 2429 node = doc->body(); 2430 if (!node) 2431 node = doc->documentElement(); 2432 return node; 2433 } 2434 2435 bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt) 2436 { 2437 // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do. 2438 // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and 2439 // lower case variants are present in a document, the correct element is matched based on Shift key state. 2440 // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively. 2441 ASSERT(!(accessKeyModifiers() & PlatformKeyboardEvent::ShiftKey)); 2442 if ((evt.modifiers() & ~PlatformKeyboardEvent::ShiftKey) != accessKeyModifiers()) 2443 return false; 2444 String key = evt.unmodifiedText(); 2445 Element* elem = m_frame->document()->getElementByAccessKey(key.lower()); 2446 if (!elem) 2447 return false; 2448 elem->accessKeyAction(false); 2449 return true; 2450 } 2451 2452 #if !PLATFORM(MAC) 2453 bool EventHandler::needsKeyboardEventDisambiguationQuirks() const 2454 { 2455 return false; 2456 } 2457 #endif 2458 2459 bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) 2460 { 2461 RefPtr<FrameView> protector(m_frame->view()); 2462 2463 if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL) 2464 capsLockStateMayHaveChanged(); 2465 2466 #if ENABLE(PAN_SCROLLING) 2467 if (Page* page = m_frame->page()) { 2468 if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { 2469 // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop 2470 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown || initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) 2471 stopAutoscrollTimer(); 2472 2473 // If we were in autoscroll/panscroll mode, we swallow the key event 2474 return true; 2475 } 2476 } 2477 #endif 2478 2479 // Check for cases where we are too early for events -- possible unmatched key up 2480 // from pressing return in the location bar. 2481 RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document()); 2482 if (!node) 2483 return false; 2484 2485 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 2486 UserTypingGestureIndicator typingGestureIndicator(m_frame); 2487 2488 if (FrameView* view = m_frame->view()) 2489 view->resetDeferredRepaintDelay(); 2490 2491 // FIXME: what is this doing here, in keyboard event handler? 2492 m_frame->loader()->resetMultipleFormSubmissionProtection(); 2493 2494 // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match. 2495 // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict 2496 // with access keys. Then we dispatch keydown, but suppress its default handling. 2497 // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages. 2498 // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events. 2499 bool matchedAnAccessKey = false; 2500 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown) 2501 matchedAnAccessKey = handleAccessKey(initialKeyEvent); 2502 2503 // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch. 2504 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEvent.type() == PlatformKeyboardEvent::Char) 2505 return !node->dispatchKeyEvent(initialKeyEvent); 2506 2507 bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks(); 2508 2509 ExceptionCode ec; 2510 PlatformKeyboardEvent keyDownEvent = initialKeyEvent; 2511 if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown) 2512 keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode); 2513 RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView()); 2514 if (matchedAnAccessKey) 2515 keydown->setDefaultPrevented(true); 2516 keydown->setTarget(node); 2517 2518 if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) { 2519 node->dispatchEvent(keydown, ec); 2520 // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame. 2521 bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); 2522 return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; 2523 } 2524 2525 // Run input method in advance of DOM event handling. This may result in the IM 2526 // modifying the page prior the keydown event, but this behaviour is necessary 2527 // in order to match IE: 2528 // 1. preventing default handling of keydown and keypress events has no effect on IM input; 2529 // 2. if an input method handles the event, its keyCode is set to 229 in keydown event. 2530 m_frame->editor()->handleInputMethodKeydown(keydown.get()); 2531 2532 bool handledByInputMethod = keydown->defaultHandled(); 2533 2534 if (handledByInputMethod) { 2535 keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode); 2536 keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView()); 2537 keydown->setTarget(node); 2538 keydown->setDefaultHandled(); 2539 } 2540 2541 node->dispatchEvent(keydown, ec); 2542 // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame. 2543 bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController()->focusedOrMainFrame(); 2544 bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; 2545 if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode)) 2546 return keydownResult; 2547 2548 // Focus may have changed during keydown handling, so refetch node. 2549 // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node. 2550 if (!keydownResult) { 2551 node = eventTargetNodeForDocument(m_frame->document()); 2552 if (!node) 2553 return false; 2554 } 2555 2556 PlatformKeyboardEvent keyPressEvent = initialKeyEvent; 2557 keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backwardCompatibilityMode); 2558 if (keyPressEvent.text().isEmpty()) 2559 return keydownResult; 2560 RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView()); 2561 keypress->setTarget(node); 2562 if (keydownResult) 2563 keypress->setDefaultPrevented(true); 2564 #if PLATFORM(MAC) 2565 keypress->keypressCommands() = keydown->keypressCommands(); 2566 #endif 2567 node->dispatchEvent(keypress, ec); 2568 2569 return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled(); 2570 } 2571 2572 void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event) 2573 { 2574 if (!event) 2575 return; 2576 2577 const String& key = event->keyIdentifier(); 2578 bool isShifted = event->getModifierState("Shift"); 2579 bool isOptioned = event->getModifierState("Alt"); 2580 bool isCommanded = event->getModifierState("Meta"); 2581 2582 if (key == "Up") { 2583 m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionBackward, (isCommanded) ? DocumentBoundary : LineGranularity, true); 2584 event->setDefaultHandled(); 2585 } else if (key == "Down") { 2586 m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionForward, (isCommanded) ? DocumentBoundary : LineGranularity, true); 2587 event->setDefaultHandled(); 2588 } else if (key == "Left") { 2589 m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionLeft, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true); 2590 event->setDefaultHandled(); 2591 } else if (key == "Right") { 2592 m_frame->selection()->modify((isShifted) ? SelectionController::AlterationExtend : SelectionController::AlterationMove, DirectionRight, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true); 2593 event->setDefaultHandled(); 2594 } 2595 } 2596 2597 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) 2598 { 2599 if (event->type() == eventNames().keydownEvent) { 2600 m_frame->editor()->handleKeyboardEvent(event); 2601 if (event->defaultHandled()) 2602 return; 2603 if (event->keyIdentifier() == "U+0009") 2604 defaultTabEventHandler(event); 2605 else if (event->keyIdentifier() == "U+0008") 2606 defaultBackspaceEventHandler(event); 2607 else { 2608 FocusDirection direction = focusDirectionForKey(event->keyIdentifier()); 2609 if (direction != FocusDirectionNone) 2610 defaultArrowEventHandler(direction, event); 2611 } 2612 2613 // provides KB navigation and selection for enhanced accessibility users 2614 if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled()) 2615 handleKeyboardSelectionMovement(event); 2616 } 2617 if (event->type() == eventNames().keypressEvent) { 2618 m_frame->editor()->handleKeyboardEvent(event); 2619 if (event->defaultHandled()) 2620 return; 2621 if (event->charCode() == ' ') 2622 defaultSpaceEventHandler(event); 2623 } 2624 } 2625 2626 FocusDirection EventHandler::focusDirectionForKey(const AtomicString& keyIdentifier) const 2627 { 2628 DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down")); 2629 DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up")); 2630 DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left")); 2631 DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right")); 2632 2633 FocusDirection retVal = FocusDirectionNone; 2634 2635 if (keyIdentifier == Down) 2636 retVal = FocusDirectionDown; 2637 else if (keyIdentifier == Up) 2638 retVal = FocusDirectionUp; 2639 else if (keyIdentifier == Left) 2640 retVal = FocusDirectionLeft; 2641 else if (keyIdentifier == Right) 2642 retVal = FocusDirectionRight; 2643 2644 return retVal; 2645 } 2646 2647 #if ENABLE(DRAG_SUPPORT) 2648 bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLocation) const 2649 { 2650 IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)floatDragViewportLocation.y()); 2651 return dragHysteresisExceeded(dragViewportLocation); 2652 } 2653 2654 bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const 2655 { 2656 FrameView* view = m_frame->view(); 2657 if (!view) 2658 return false; 2659 IntPoint dragLocation = view->windowToContents(dragViewportLocation); 2660 IntSize delta = dragLocation - m_mouseDownPos; 2661 2662 int threshold = GeneralDragHysteresis; 2663 if (dragState().m_dragSrcIsImage) 2664 threshold = ImageDragHysteresis; 2665 else if (dragState().m_dragSrcIsLink) 2666 threshold = LinkDragHysteresis; 2667 else if (dragState().m_dragSrcInSelection) 2668 threshold = TextDragHysteresis; 2669 2670 return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold; 2671 } 2672 2673 void EventHandler::freeClipboard() 2674 { 2675 if (dragState().m_dragClipboard) 2676 dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb); 2677 } 2678 2679 bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const 2680 { 2681 if (!node || !m_frame->view()) 2682 return false; 2683 Page* page = m_frame->page(); 2684 return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point, node); 2685 } 2686 2687 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation) 2688 { 2689 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) { 2690 dragState().m_dragClipboard->setDestinationOperation(operation); 2691 // for now we don't care if event handler cancels default behavior, since there is none 2692 dispatchDragSrcEvent(eventNames().dragendEvent, event); 2693 } 2694 freeClipboard(); 2695 dragState().m_dragSrc = 0; 2696 // In case the drag was ended due to an escape key press we need to ensure 2697 // that consecutive mousemove events don't reinitiate the drag and drop. 2698 m_mouseDownMayStartDrag = false; 2699 } 2700 2701 // returns if we should continue "default processing", i.e., whether eventhandler canceled 2702 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event) 2703 { 2704 return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get()); 2705 } 2706 2707 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) 2708 { 2709 if (event.event().button() != LeftButton || event.event().eventType() != MouseEventMoved) { 2710 // If we allowed the other side of the bridge to handle a drag 2711 // last time, then m_mousePressed might still be set. So we 2712 // clear it now to make sure the next move after a drag 2713 // doesn't look like a drag. 2714 m_mousePressed = false; 2715 return false; 2716 } 2717 2718 if (eventLoopHandleMouseDragged(event)) 2719 return true; 2720 2721 // Careful that the drag starting logic stays in sync with eventMayStartDrag() 2722 2723 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) { 2724 allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA); 2725 if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA) 2726 m_mouseDownMayStartDrag = false; // no element is draggable 2727 } 2728 2729 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) { 2730 // try to find an element that wants to be dragged 2731 HitTestRequest request(HitTestRequest::ReadOnly); 2732 HitTestResult result(m_mouseDownPos); 2733 m_frame->contentRenderer()->layer()->hitTest(request, result); 2734 Node* node = result.innerNode(); 2735 if (node && node->renderer()) 2736 dragState().m_dragSrc = node->renderer()->draggableNode(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA, 2737 m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML); 2738 else 2739 dragState().m_dragSrc = 0; 2740 2741 if (!dragState().m_dragSrc) 2742 m_mouseDownMayStartDrag = false; // no element is draggable 2743 else { 2744 // remember some facts about this source, while we have a HitTestResult handy 2745 node = result.URLElement(); 2746 dragState().m_dragSrcIsLink = node && node->isLink(); 2747 2748 node = result.innerNonSharedNode(); 2749 dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage(); 2750 2751 dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos); 2752 } 2753 } 2754 2755 // For drags starting in the selection, the user must wait between the mousedown and mousedrag, 2756 // or else we bail on the dragging stuff and allow selection to occur 2757 if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) { 2758 m_mouseDownMayStartDrag = false; 2759 dragState().m_dragSrc = 0; 2760 // ...but if this was the first click in the window, we don't even want to start selection 2761 if (eventActivatedView(event.event())) 2762 m_mouseDownMayStartSelect = false; 2763 } 2764 2765 if (!m_mouseDownMayStartDrag) 2766 return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; 2767 2768 // We are starting a text/image/url drag, so the cursor should be an arrow 2769 if (FrameView* view = m_frame->view()) { 2770 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer). 2771 view->setCursor(pointerCursor()); 2772 } 2773 2774 if (!dragHysteresisExceeded(event.event().pos())) 2775 return true; 2776 2777 // Once we're past the hysteresis point, we don't want to treat this gesture as a click 2778 invalidateClick(); 2779 2780 DragOperation srcOp = DragOperationNone; 2781 2782 freeClipboard(); // would only happen if we missed a dragEnd. Do it anyway, just 2783 // to make sure it gets numbified 2784 dragState().m_dragClipboard = createDraggingClipboard(); 2785 2786 if (dragState().m_dragSrcMayBeDHTML) { 2787 // Check to see if the is a DOM based drag, if it is get the DOM specified drag 2788 // image and offset 2789 if (dragState().m_dragSrcIsDHTML) { 2790 if (RenderObject* renderer = dragState().m_dragSrc->renderer()) { 2791 // FIXME: This doesn't work correctly with transforms. 2792 FloatPoint absPos = renderer->localToAbsolute(); 2793 IntSize delta = m_mouseDownPos - roundedIntPoint(absPos); 2794 dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), toPoint(delta)); 2795 } else { 2796 // The renderer has disappeared, this can happen if the onStartDrag handler has hidden 2797 // the element in some way. In this case we just kill the drag. 2798 m_mouseDownMayStartDrag = false; 2799 goto cleanupDrag; 2800 } 2801 } 2802 2803 m_mouseDownMayStartDrag = dispatchDragSrcEvent(eventNames().dragstartEvent, m_mouseDown) 2804 && !m_frame->selection()->isInPasswordField(); 2805 2806 // Invalidate clipboard here against anymore pasteboard writing for security. The drag 2807 // image can still be changed as we drag, but not the pasteboard data. 2808 dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable); 2809 2810 if (m_mouseDownMayStartDrag) { 2811 // gather values from DHTML element, if it set any 2812 srcOp = dragState().m_dragClipboard->sourceOperation(); 2813 2814 // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the 2815 // drag with dragImage! Because of that dumb reentrancy, we may think we've not 2816 // started the drag when that happens. So we have to assume it's started before we 2817 // kick it off. 2818 dragState().m_dragClipboard->setDragHasStarted(); 2819 } 2820 } 2821 2822 if (m_mouseDownMayStartDrag) { 2823 Page* page = m_frame->page(); 2824 DragController* dragController = page ? page->dragController() : 0; 2825 bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML); 2826 if (!startedDrag && dragState().m_dragSrcMayBeDHTML) { 2827 // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event 2828 dispatchDragSrcEvent(eventNames().dragendEvent, event.event()); 2829 m_mouseDownMayStartDrag = false; 2830 } 2831 } 2832 2833 cleanupDrag: 2834 if (!m_mouseDownMayStartDrag) { 2835 // something failed to start the drag, cleanup 2836 freeClipboard(); 2837 dragState().m_dragSrc = 0; 2838 } 2839 2840 // No more default handling (like selection), whether we're past the hysteresis bounds or not 2841 return true; 2842 } 2843 #endif // ENABLE(DRAG_SUPPORT) 2844 2845 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType) 2846 { 2847 // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline), 2848 // and avoid dispatching text input events from keydown default handlers. 2849 ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || static_cast<KeyboardEvent*>(underlyingEvent)->type() == eventNames().keypressEvent); 2850 2851 if (!m_frame) 2852 return false; 2853 2854 EventTarget* target; 2855 if (underlyingEvent) 2856 target = underlyingEvent->target(); 2857 else 2858 target = eventTargetNodeForDocument(m_frame->document()); 2859 if (!target) 2860 return false; 2861 2862 if (FrameView* view = m_frame->view()) 2863 view->resetDeferredRepaintDelay(); 2864 2865 RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text, inputType); 2866 event->setUnderlyingEvent(underlyingEvent); 2867 2868 ExceptionCode ec; 2869 target->dispatchEvent(event, ec); 2870 return event->defaultHandled(); 2871 } 2872 2873 bool EventHandler::isKeyboardOptionTab(KeyboardEvent* event) 2874 { 2875 return event 2876 && (event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent) 2877 && event->altKey() 2878 && event->keyIdentifier() == "U+0009"; 2879 } 2880 2881 static bool eventInvertsTabsToLinksClientCallResult(KeyboardEvent* event) 2882 { 2883 #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(HAIKU) || PLATFORM(EFL) 2884 return EventHandler::isKeyboardOptionTab(event); 2885 #else 2886 return false; 2887 #endif 2888 } 2889 2890 bool EventHandler::tabsToLinks(KeyboardEvent* event) const 2891 { 2892 // FIXME: This function needs a better name. It can be called for keypresses other than Tab when spatial navigation is enabled. 2893 2894 Page* page = m_frame->page(); 2895 if (!page) 2896 return false; 2897 2898 bool tabsToLinksClientCallResult = page->chrome()->client()->keyboardUIMode() & KeyboardAccessTabsToLinks; 2899 return eventInvertsTabsToLinksClientCallResult(event) ? !tabsToLinksClientCallResult : tabsToLinksClientCallResult; 2900 } 2901 2902 void EventHandler::defaultTextInputEventHandler(TextEvent* event) 2903 { 2904 if (m_frame->editor()->handleTextEvent(event)) 2905 event->setDefaultHandled(); 2906 } 2907 2908 #if PLATFORM(QT) || PLATFORM(ANDROID) 2909 // Qt handles the space event in platform-specific WebKit code. 2910 // Eventually it would be good to eliminate that and use the code here instead. 2911 void EventHandler::defaultSpaceEventHandler(KeyboardEvent*) 2912 { 2913 } 2914 #else 2915 2916 void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event) 2917 { 2918 ASSERT(event->type() == eventNames().keypressEvent); 2919 2920 if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey()) 2921 return; 2922 2923 ScrollLogicalDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward; 2924 if (logicalScrollOverflow(direction, ScrollByPage)) { 2925 event->setDefaultHandled(); 2926 return; 2927 } 2928 2929 FrameView* view = m_frame->view(); 2930 if (!view) 2931 return; 2932 2933 if (view->logicalScroll(direction, ScrollByPage)) 2934 event->setDefaultHandled(); 2935 } 2936 2937 #endif 2938 2939 void EventHandler::defaultBackspaceEventHandler(KeyboardEvent* event) 2940 { 2941 ASSERT(event->type() == eventNames().keydownEvent); 2942 2943 if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey()) 2944 return; 2945 2946 Page* page = m_frame->page(); 2947 if (!page) 2948 return; 2949 2950 bool handledEvent = false; 2951 2952 if (event->shiftKey()) 2953 handledEvent = page->goForward(); 2954 else 2955 handledEvent = page->goBack(); 2956 2957 if (handledEvent) 2958 event->setDefaultHandled(); 2959 } 2960 2961 2962 void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent* event) 2963 { 2964 ASSERT(event->type() == eventNames().keydownEvent); 2965 2966 if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey()) 2967 return; 2968 2969 Page* page = m_frame->page(); 2970 if (!page) 2971 return; 2972 2973 if (!isSpatialNavigationEnabled(m_frame)) 2974 return; 2975 2976 // Arrows and other possible directional navigation keys can be used in design 2977 // mode editing. 2978 if (m_frame->document()->inDesignMode()) 2979 return; 2980 2981 if (page->focusController()->advanceFocus(focusDirection, event)) 2982 event->setDefaultHandled(); 2983 } 2984 2985 void EventHandler::defaultTabEventHandler(KeyboardEvent* event) 2986 { 2987 ASSERT(event->type() == eventNames().keydownEvent); 2988 2989 // We should only advance focus on tabs if no special modifier keys are held down. 2990 if (event->ctrlKey() || event->metaKey() || event->altGraphKey()) 2991 return; 2992 2993 Page* page = m_frame->page(); 2994 if (!page) 2995 return; 2996 if (!page->tabKeyCyclesThroughElements()) 2997 return; 2998 2999 FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward; 3000 3001 // Tabs can be used in design mode editing. 3002 if (m_frame->document()->inDesignMode()) 3003 return; 3004 3005 if (page->focusController()->advanceFocus(focusDirection, event)) 3006 event->setDefaultHandled(); 3007 } 3008 3009 void EventHandler::capsLockStateMayHaveChanged() 3010 { 3011 Document* d = m_frame->document(); 3012 if (Node* node = d->focusedNode()) { 3013 if (RenderObject* r = node->renderer()) { 3014 if (r->isTextField()) 3015 toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged(); 3016 } 3017 } 3018 } 3019 3020 void EventHandler::sendResizeEvent() 3021 { 3022 m_frame->document()->enqueueWindowEvent(Event::create(eventNames().resizeEvent, false, false)); 3023 } 3024 3025 void EventHandler::sendScrollEvent() 3026 { 3027 setFrameWasScrolledByUser(); 3028 if (m_frame->view() && m_frame->document()) 3029 m_frame->document()->eventQueue()->enqueueOrDispatchScrollEvent(m_frame->document(), EventQueue::ScrollEventDocumentTarget); 3030 } 3031 3032 void EventHandler::setFrameWasScrolledByUser() 3033 { 3034 FrameView* v = m_frame->view(); 3035 if (v) 3036 v->setWasScrolledByUser(true); 3037 } 3038 3039 bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar) 3040 { 3041 if (!scrollbar || !scrollbar->enabled()) 3042 return false; 3043 setFrameWasScrolledByUser(); 3044 return scrollbar->mouseDown(mev.event()); 3045 } 3046 3047 // If scrollbar (under mouse) is different from last, send a mouse exited. Set 3048 // last to scrollbar if setLast is true; else set last to 0. 3049 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast) 3050 { 3051 if (m_lastScrollbarUnderMouse != scrollbar) { 3052 // Send mouse exited to the old scrollbar. 3053 if (m_lastScrollbarUnderMouse) 3054 m_lastScrollbarUnderMouse->mouseExited(); 3055 m_lastScrollbarUnderMouse = setLast ? scrollbar : 0; 3056 } 3057 } 3058 3059 #if ENABLE(TOUCH_EVENTS) 3060 3061 static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state) 3062 { 3063 switch (state) { 3064 case PlatformTouchPoint::TouchReleased: 3065 return eventNames().touchendEvent; 3066 case PlatformTouchPoint::TouchCancelled: 3067 return eventNames().touchcancelEvent; 3068 case PlatformTouchPoint::TouchPressed: 3069 return eventNames().touchstartEvent; 3070 case PlatformTouchPoint::TouchMoved: 3071 return eventNames().touchmoveEvent; 3072 default: 3073 ASSERT_NOT_REACHED(); 3074 return emptyAtom; 3075 } 3076 } 3077 3078 bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) 3079 { 3080 // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes 3081 // in the JS event. See http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/ 3082 // for an overview of how these lists fit together. 3083 3084 // Holds the complete set of touches on the screen and will be used as the 'touches' list in the JS event. 3085 RefPtr<TouchList> touches = TouchList::create(); 3086 3087 // A different view on the 'touches' list above, filtered and grouped by event target. Used for the 3088 // 'targetTouches' list in the JS event. 3089 typedef HashMap<EventTarget*, RefPtr<TouchList> > TargetTouchesMap; 3090 TargetTouchesMap touchesByTarget; 3091 3092 // Array of touches per state, used to assemble the 'changedTouches' list in the JS event. 3093 typedef HashSet<RefPtr<EventTarget> > EventTargetSet; 3094 struct { 3095 // The touches corresponding to the particular change state this struct instance represents. 3096 RefPtr<TouchList> m_touches; 3097 // Set of targets involved in m_touches. 3098 EventTargetSet m_targets; 3099 } changedTouches[PlatformTouchPoint::TouchStateEnd]; 3100 3101 const Vector<PlatformTouchPoint>& points = event.touchPoints(); 3102 3103 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 3104 3105 for (unsigned i = 0; i < points.size(); ++i) { 3106 const PlatformTouchPoint& point = points[i]; 3107 PlatformTouchPoint::State pointState = point.state(); 3108 IntPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos()); 3109 3110 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Active | HitTestRequest::ReadOnly; 3111 // The HitTestRequest types used for mouse events map quite adequately 3112 // to touch events. Note that in addition to meaning that the hit test 3113 // should affect the active state of the current node if necessary, 3114 // HitTestRequest::Active signifies that the hit test is taking place 3115 // with the mouse (or finger in this case) being pressed. 3116 switch (pointState) { 3117 case PlatformTouchPoint::TouchPressed: 3118 hitType = HitTestRequest::Active; 3119 break; 3120 case PlatformTouchPoint::TouchMoved: 3121 hitType = HitTestRequest::Active | HitTestRequest::MouseMove | HitTestRequest::ReadOnly; 3122 break; 3123 case PlatformTouchPoint::TouchReleased: 3124 case PlatformTouchPoint::TouchCancelled: 3125 hitType = HitTestRequest::MouseUp; 3126 break; 3127 default: 3128 break; 3129 } 3130 #if PLATFORM(ANDROID) 3131 Node* node = 0; 3132 if (m_capturingTouchEventsNode) 3133 node = m_capturingTouchEventsNode.get(); 3134 else { 3135 HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType); 3136 node = result.innerNode(); 3137 ASSERT(node); 3138 3139 // Touch events should not go to text nodes 3140 if (node->isTextNode()) 3141 node = node->parentNode(); 3142 } 3143 #else 3144 HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType); 3145 Node* node = result.innerNode(); 3146 ASSERT(node); 3147 3148 // Touch events should not go to text nodes 3149 if (node->isTextNode()) 3150 node = node->parentNode(); 3151 #endif 3152 3153 3154 Document* doc = node->document(); 3155 if (!doc) 3156 continue; 3157 if (!doc->hasListenerType(Document::TOUCH_LISTENER)) 3158 continue; 3159 3160 if (m_frame != doc->frame()) { 3161 // pagePoint should always be relative to the target elements containing frame. 3162 pagePoint = documentPointForWindowPoint(doc->frame(), point.pos()); 3163 } 3164 3165 int adjustedPageX = lroundf(pagePoint.x() / m_frame->pageZoomFactor()); 3166 int adjustedPageY = lroundf(pagePoint.y() / m_frame->pageZoomFactor()); 3167 3168 // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. 3169 unsigned touchPointTargetKey = point.id() + 1; 3170 RefPtr<EventTarget> touchTarget; 3171 #if PLATFORM(ANDROID) 3172 if (m_capturingTouchEventsNode) 3173 touchTarget = node; 3174 else { 3175 #endif 3176 if (pointState == PlatformTouchPoint::TouchPressed) { 3177 m_originatingTouchPointTargets.set(touchPointTargetKey, node); 3178 touchTarget = node; 3179 } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) { 3180 // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel 3181 // we also remove it from the map. 3182 touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); 3183 } else 3184 touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey); 3185 #if PLATFORM(ANDROID) 3186 } 3187 #endif 3188 if (!touchTarget.get()) 3189 continue; 3190 3191 RefPtr<Touch> touch = Touch::create(doc->frame(), touchTarget.get(), point.id(), 3192 point.screenPos().x(), point.screenPos().y(), 3193 adjustedPageX, adjustedPageY); 3194 3195 // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below. 3196 TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get()); 3197 if (targetTouchesIterator == touchesByTarget.end()) 3198 targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).first; 3199 3200 // touches and targetTouches should only contain information about touches still on the screen, so if this point is 3201 // released or cancelled it will only appear in the changedTouches list. 3202 if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) { 3203 touches->append(touch); 3204 targetTouchesIterator->second->append(touch); 3205 } 3206 3207 // Now build up the correct list for changedTouches. 3208 // Note that any touches that are in the TouchStationary state (e.g. if 3209 // the user had several points touched but did not move them all) should 3210 // never be in the changedTouches list so we do not handle them explicitly here. 3211 // See https://bugs.webkit.org/show_bug.cgi?id=37609 for further discussion 3212 // about the TouchStationary state. 3213 if (pointState != PlatformTouchPoint::TouchStationary) { 3214 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); 3215 if (!changedTouches[pointState].m_touches) 3216 changedTouches[pointState].m_touches = TouchList::create(); 3217 changedTouches[pointState].m_touches->append(touch); 3218 changedTouches[pointState].m_targets.add(touchTarget); 3219 } 3220 } 3221 m_touchPressed = touches->length() > 0; 3222 3223 // Now iterate the changedTouches list and m_targets within it, sending events to the tagets as required. 3224 bool defaultPrevented = false; 3225 RefPtr<TouchList> emptyList = TouchList::create(); 3226 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) { 3227 if (!changedTouches[state].m_touches) 3228 continue; 3229 3230 // When sending a touch cancel event, use empty touches and targetTouches lists. 3231 bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled); 3232 RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches); 3233 #if PLATFORM(ANDROID) 3234 AtomicString stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); 3235 if (event.type() == TouchLongPress) 3236 stateName = eventNames().touchlongpressEvent; 3237 else if (event.type() == TouchDoubleTap) 3238 stateName = eventNames().touchdoubletapEvent; 3239 #else 3240 const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); 3241 #endif 3242 const EventTargetSet& targetsForState = changedTouches[state].m_targets; 3243 3244 for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) { 3245 EventTarget* touchEventTarget = it->get(); 3246 RefPtr<TouchList> targetTouches(isTouchCancelEvent ? emptyList : touchesByTarget.get(touchEventTarget)); 3247 ASSERT(targetTouches); 3248 3249 RefPtr<TouchEvent> touchEvent = 3250 TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(), 3251 stateName, touchEventTarget->toNode()->document()->defaultView(), 3252 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey()); 3253 ExceptionCode ec = 0; 3254 touchEventTarget->dispatchEvent(touchEvent.get(), ec); 3255 defaultPrevented |= touchEvent->defaultPrevented(); 3256 } 3257 } 3258 3259 #if ENABLE(GESTURE_RECOGNIZER) 3260 if (m_gestureRecognizer) 3261 m_gestureRecognizer->processTouchEventForGesture(event, this, defaultPrevented); 3262 #endif 3263 3264 return defaultPrevented; 3265 } 3266 #endif 3267 3268 } 3269