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 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "config.h" 29 #include "core/page/EventHandler.h" 30 31 #include "HTMLNames.h" 32 #include "RuntimeEnabledFeatures.h" 33 #include "SVGNames.h" 34 #include "bindings/v8/ExceptionStatePlaceholder.h" 35 #include "core/dom/Document.h" 36 #include "core/dom/DocumentEventQueue.h" 37 #include "core/dom/DocumentMarkerController.h" 38 #include "core/dom/EventNames.h" 39 #include "core/dom/EventPathWalker.h" 40 #include "core/dom/FullscreenElementStack.h" 41 #include "core/dom/KeyboardEvent.h" 42 #include "core/dom/MouseEvent.h" 43 #include "core/dom/TextEvent.h" 44 #include "core/dom/TouchEvent.h" 45 #include "core/dom/TouchList.h" 46 #include "core/dom/UserTypingGestureIndicator.h" 47 #include "core/dom/WheelEvent.h" 48 #include "core/dom/shadow/ShadowRoot.h" 49 #include "core/editing/Editor.h" 50 #include "core/editing/FrameSelection.h" 51 #include "core/editing/TextIterator.h" 52 #include "core/editing/htmlediting.h" 53 #include "core/history/BackForwardController.h" 54 #include "core/html/HTMLFrameElementBase.h" 55 #include "core/html/HTMLFrameSetElement.h" 56 #include "core/html/HTMLInputElement.h" 57 #include "core/loader/FrameLoader.h" 58 #include "core/loader/cache/ImageResource.h" 59 #include "core/page/Chrome.h" 60 #include "core/page/DragController.h" 61 #include "core/page/DragState.h" 62 #include "core/page/EditorClient.h" 63 #include "core/page/FocusController.h" 64 #include "core/page/Frame.h" 65 #include "core/page/FrameTree.h" 66 #include "core/page/FrameView.h" 67 #include "core/page/MouseEventWithHitTestResults.h" 68 #include "core/page/Page.h" 69 #include "core/page/Settings.h" 70 #include "core/page/SpatialNavigation.h" 71 #include "core/page/TouchAdjustment.h" 72 #include "core/platform/Cursor.h" 73 #include "core/platform/PlatformEvent.h" 74 #include "core/platform/PlatformGestureEvent.h" 75 #include "core/platform/PlatformKeyboardEvent.h" 76 #include "core/platform/PlatformTouchEvent.h" 77 #include "core/platform/PlatformWheelEvent.h" 78 #include "core/platform/ScrollAnimator.h" 79 #include "core/platform/Scrollbar.h" 80 #include "core/platform/WindowsKeyboardCodes.h" 81 #include "core/platform/chromium/ChromiumDataObject.h" 82 #include "core/platform/chromium/ClipboardChromium.h" 83 #include "core/platform/graphics/FloatPoint.h" 84 #include "core/platform/graphics/Image.h" 85 #include "core/rendering/HitTestRequest.h" 86 #include "core/rendering/HitTestResult.h" 87 #include "core/rendering/RenderLayer.h" 88 #include "core/rendering/RenderTextControlSingleLine.h" 89 #include "core/rendering/RenderView.h" 90 #include "core/rendering/RenderWidget.h" 91 #include "core/rendering/style/CursorList.h" 92 #include "core/svg/SVGDocument.h" 93 #include "core/svg/SVGElementInstance.h" 94 #include "core/svg/SVGUseElement.h" 95 #include "wtf/Assertions.h" 96 #include "wtf/CurrentTime.h" 97 #include "wtf/StdLibExtras.h" 98 #include "wtf/TemporaryChange.h" 99 100 namespace WebCore { 101 102 using namespace HTMLNames; 103 104 // The link drag hysteresis is much larger than the others because there 105 // needs to be enough space to cancel the link press without starting a link drag, 106 // and because dragging links is rare. 107 const int LinkDragHysteresis = 40; 108 const int ImageDragHysteresis = 5; 109 const int TextDragHysteresis = 3; 110 const int GeneralDragHysteresis = 3; 111 112 // Match key code of composition keydown event on windows. 113 // IE sends VK_PROCESSKEY which has value 229; 114 const int CompositionEventKeyCode = 229; 115 116 using namespace SVGNames; 117 118 // The amount of time to wait before sending a fake mouse event, triggered 119 // during a scroll. The short interval is used if the content responds to the mouse events quickly enough, 120 // otherwise the long interval is used. 121 const double fakeMouseMoveShortInterval = 0.1; 122 const double fakeMouseMoveLongInterval = 0.250; 123 124 const int maximumCursorSize = 128; 125 126 // It's pretty unlikely that a scale of less than one would ever be used. But all we really 127 // need to ensure here is that the scale isn't so small that integer overflow can occur when 128 // dividing cursor sizes (limited above) by the scale. 129 const double minimumCursorScale = 0.001; 130 131 #if OS(DARWIN) 132 const double EventHandler::TextDragDelay = 0.15; 133 #else 134 const double EventHandler::TextDragDelay = 0.0; 135 #endif 136 137 138 enum NoCursorChangeType { NoCursorChange }; 139 140 class OptionalCursor { 141 public: 142 OptionalCursor(NoCursorChangeType) : m_isCursorChange(false) { } 143 OptionalCursor(const Cursor& cursor) : m_isCursorChange(true), m_cursor(cursor) { } 144 145 bool isCursorChange() const { return m_isCursorChange; } 146 const Cursor& cursor() const { ASSERT(m_isCursorChange); return m_cursor; } 147 148 private: 149 bool m_isCursorChange; 150 Cursor m_cursor; 151 }; 152 153 class MaximumDurationTracker { 154 public: 155 explicit MaximumDurationTracker(double *maxDuration) 156 : m_maxDuration(maxDuration) 157 , m_start(monotonicallyIncreasingTime()) 158 { 159 } 160 161 ~MaximumDurationTracker() 162 { 163 *m_maxDuration = max(*m_maxDuration, monotonicallyIncreasingTime() - m_start); 164 } 165 166 private: 167 double* m_maxDuration; 168 double m_start; 169 }; 170 171 class SyntheticTouchPoint : public PlatformTouchPoint { 172 public: 173 174 // The default values are based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html 175 explicit SyntheticTouchPoint(const PlatformMouseEvent& event) 176 { 177 const static int idDefaultValue = 0; 178 const static int radiusYDefaultValue = 1; 179 const static int radiusXDefaultValue = 1; 180 const static float rotationAngleDefaultValue = 0.0f; 181 const static float forceDefaultValue = 1.0f; 182 183 m_id = idDefaultValue; // There is only one active TouchPoint. 184 m_screenPos = event.globalPosition(); 185 m_pos = event.position(); 186 m_radiusY = radiusYDefaultValue; 187 m_radiusX = radiusXDefaultValue; 188 m_rotationAngle = rotationAngleDefaultValue; 189 m_force = forceDefaultValue; 190 191 PlatformEvent::Type type = event.type(); 192 ASSERT(type == PlatformEvent::MouseMoved || type == PlatformEvent::MousePressed || type == PlatformEvent::MouseReleased); 193 194 switch (type) { 195 case PlatformEvent::MouseMoved: 196 m_state = TouchMoved; 197 break; 198 case PlatformEvent::MousePressed: 199 m_state = TouchPressed; 200 break; 201 case PlatformEvent::MouseReleased: 202 m_state = TouchReleased; 203 break; 204 default: 205 ASSERT_NOT_REACHED(); 206 break; 207 } 208 } 209 }; 210 211 class SyntheticSingleTouchEvent : public PlatformTouchEvent { 212 public: 213 explicit SyntheticSingleTouchEvent(const PlatformMouseEvent& event) 214 { 215 switch (event.type()) { 216 case PlatformEvent::MouseMoved: 217 m_type = TouchMove; 218 break; 219 case PlatformEvent::MousePressed: 220 m_type = TouchStart; 221 break; 222 case PlatformEvent::MouseReleased: 223 m_type = TouchEnd; 224 break; 225 default: 226 ASSERT_NOT_REACHED(); 227 m_type = NoType; 228 break; 229 } 230 m_timestamp = event.timestamp(); 231 m_modifiers = event.modifiers(); 232 m_touchPoints.append(SyntheticTouchPoint(event)); 233 } 234 }; 235 236 static inline ScrollGranularity wheelGranularityToScrollGranularity(unsigned deltaMode) 237 { 238 switch (deltaMode) { 239 case WheelEvent::DOM_DELTA_PAGE: 240 return ScrollByPage; 241 case WheelEvent::DOM_DELTA_LINE: 242 return ScrollByLine; 243 case WheelEvent::DOM_DELTA_PIXEL: 244 return ScrollByPixel; 245 default: 246 return ScrollByPixel; 247 } 248 } 249 250 static inline bool scrollNode(float delta, ScrollGranularity granularity, ScrollDirection positiveDirection, ScrollDirection negativeDirection, Node* node, Node** stopNode) 251 { 252 if (!delta) 253 return false; 254 if (!node->renderer()) 255 return false; 256 RenderBox* enclosingBox = node->renderer()->enclosingBox(); 257 float absDelta = delta > 0 ? delta : -delta; 258 return enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, granularity, absDelta, stopNode); 259 } 260 261 static inline bool shouldGesturesTriggerActive() 262 { 263 // If the platform we're on supports GestureTapDown and GestureTapCancel then we'll 264 // rely on them to set the active state. Unfortunately there's no generic way to 265 // know in advance what event types are supported. 266 return true; 267 } 268 269 // Refetch the event target node if it is removed or currently is the shadow node inside an <input> element. 270 // If a mouse event handler changes the input element type to one that has a widget associated, 271 // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the 272 // event target node can't still be the shadow node. 273 static inline bool shouldRefetchEventTarget(const MouseEventWithHitTestResults& mev) 274 { 275 Node* targetNode = mev.targetNode(); 276 ASSERT(targetNode); 277 if (!targetNode->parentNode()) 278 return true; 279 return targetNode->isShadowRoot() && toShadowRoot(targetNode)->host()->hasTagName(inputTag); 280 } 281 282 EventHandler::EventHandler(Frame* frame) 283 : m_frame(frame) 284 , m_mousePressed(false) 285 , m_capturesDragging(false) 286 , m_mouseDownMayStartSelect(false) 287 , m_mouseDownMayStartDrag(false) 288 , m_dragMayStartSelectionInstead(false) 289 , m_mouseDownWasSingleClickInSelection(false) 290 , m_selectionInitiationState(HaveNotStartedSelection) 291 , m_hoverTimer(this, &EventHandler::hoverTimerFired) 292 , m_mouseDownMayStartAutoscroll(false) 293 , m_mouseDownWasInSubframe(false) 294 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFired) 295 , m_svgPan(false) 296 , m_resizeLayer(0) 297 , m_eventHandlerWillResetCapturingMouseEventsNode(0) 298 , m_clickCount(0) 299 , m_mousePositionIsUnknown(true) 300 , m_mouseDownTimestamp(0) 301 , m_widgetIsLatched(false) 302 , m_originatingTouchPointTargetKey(0) 303 , m_touchPressed(false) 304 , m_scrollGestureHandlingNode(0) 305 , m_lastHitTestResultOverWidget(false) 306 , m_maxMouseMovedDuration(0) 307 , m_baseEventType(PlatformEvent::NoType) 308 , m_didStartDrag(false) 309 , m_longTapShouldInvokeContextMenu(false) 310 { 311 } 312 313 EventHandler::~EventHandler() 314 { 315 ASSERT(!m_fakeMouseMoveEventTimer.isActive()); 316 } 317 318 DragState& EventHandler::dragState() 319 { 320 DEFINE_STATIC_LOCAL(DragState, state, ()); 321 return state; 322 } 323 324 void EventHandler::clear() 325 { 326 m_hoverTimer.stop(); 327 m_fakeMouseMoveEventTimer.stop(); 328 m_resizeLayer = 0; 329 m_nodeUnderMouse = 0; 330 m_lastNodeUnderMouse = 0; 331 m_instanceUnderMouse = 0; 332 m_lastInstanceUnderMouse = 0; 333 m_lastMouseMoveEventSubframe = 0; 334 m_lastScrollbarUnderMouse = 0; 335 m_clickCount = 0; 336 m_clickNode = 0; 337 m_frameSetBeingResized = 0; 338 m_dragTarget = 0; 339 m_shouldOnlyFireDragOverEvent = false; 340 m_mousePositionIsUnknown = true; 341 m_lastKnownMousePosition = IntPoint(); 342 m_lastKnownMouseGlobalPosition = IntPoint(); 343 m_lastMouseDownUserGestureToken.clear(); 344 m_mousePressNode = 0; 345 m_mousePressed = false; 346 m_capturesDragging = false; 347 m_capturingMouseEventsNode = 0; 348 m_latchedWheelEventNode = 0; 349 m_previousWheelScrolledNode = 0; 350 m_originatingTouchPointTargets.clear(); 351 m_originatingTouchPointDocument.clear(); 352 m_originatingTouchPointTargetKey = 0; 353 m_scrollGestureHandlingNode = 0; 354 m_lastHitTestResultOverWidget = false; 355 m_previousGestureScrolledNode = 0; 356 m_scrollbarHandlingScrollGesture = 0; 357 m_maxMouseMovedDuration = 0; 358 m_baseEventType = PlatformEvent::NoType; 359 m_didStartDrag = false; 360 m_touchPressed = false; 361 } 362 363 void EventHandler::nodeWillBeRemoved(Node* nodeToBeRemoved) 364 { 365 if (nodeToBeRemoved->contains(m_clickNode.get())) 366 m_clickNode = 0; 367 } 368 369 static void setSelectionIfNeeded(FrameSelection* selection, const VisibleSelection& newSelection) 370 { 371 ASSERT(selection); 372 if (selection->selection() != newSelection && selection->shouldChangeSelection(newSelection)) 373 selection->setSelection(newSelection); 374 } 375 376 static inline bool dispatchSelectStart(Node* node) 377 { 378 if (!node || !node->renderer()) 379 return true; 380 381 return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)); 382 } 383 384 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection) 385 { 386 Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode); 387 if (!rootUserSelectAll) 388 return selection; 389 390 VisibleSelection newSelection(selection); 391 newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary)); 392 newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary)); 393 394 return newSelection; 395 } 396 397 bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targetNode, const VisibleSelection& selection, TextGranularity granularity) 398 { 399 if (Position::nodeIsUserSelectNone(targetNode)) 400 return false; 401 402 if (!dispatchSelectStart(targetNode)) 403 return false; 404 405 if (selection.isRange()) 406 m_selectionInitiationState = ExtendedSelection; 407 else { 408 granularity = CharacterGranularity; 409 m_selectionInitiationState = PlacedCaret; 410 } 411 412 m_frame->selection()->setNonDirectionalSelectionIfNeeded(selection, granularity); 413 414 return true; 415 } 416 417 void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace) 418 { 419 Node* innerNode = result.targetNode(); 420 VisibleSelection newSelection; 421 422 if (innerNode && innerNode->renderer()) { 423 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 424 if (pos.isNotNull()) { 425 newSelection = VisibleSelection(pos); 426 newSelection.expandUsingGranularity(WordGranularity); 427 } 428 429 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange()) 430 newSelection.appendTrailingWhitespace(); 431 432 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 433 } 434 } 435 436 void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult& result, AppendTrailingWhitespace appendTrailingWhitespace) 437 { 438 Node* innerNode = result.targetNode(); 439 VisibleSelection newSelection; 440 441 if (innerNode && innerNode->renderer()) { 442 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 443 Position start = pos.deepEquivalent(); 444 Position end = pos.deepEquivalent(); 445 if (pos.isNotNull()) { 446 Vector<DocumentMarker*> markers = innerNode->document()->markers()->markersInRange( 447 makeRange(pos, pos).get(), DocumentMarker::Spelling | DocumentMarker::Grammar); 448 if (markers.size() == 1) { 449 start.moveToOffset(markers[0]->startOffset()); 450 end.moveToOffset(markers[0]->endOffset()); 451 newSelection = VisibleSelection(start, end); 452 } 453 } 454 455 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSelection.isRange()) 456 newSelection.appendTrailingWhitespace(); 457 458 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 459 } 460 } 461 462 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) 463 { 464 if (m_mouseDownMayStartSelect) { 465 selectClosestWordFromHitTestResult(result.hitTestResult(), 466 (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace); 467 } 468 } 469 470 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHitTestResults& result) 471 { 472 if (m_mouseDownMayStartSelect) { 473 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), 474 (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhitespace); 475 } 476 } 477 478 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result) 479 { 480 if (!result.hitTestResult().isLiveLink()) 481 return selectClosestWordFromMouseEvent(result); 482 483 Node* innerNode = result.targetNode(); 484 485 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) { 486 VisibleSelection newSelection; 487 Element* URLElement = result.hitTestResult().URLElement(); 488 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 489 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf(URLElement)) 490 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement); 491 492 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); 493 } 494 } 495 496 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event) 497 { 498 if (event.event().button() != LeftButton) 499 return false; 500 501 if (m_frame->selection()->isRange()) 502 // A double-click when range is already selected 503 // should not change the selection. So, do not call 504 // selectClosestWordFromMouseEvent, but do set 505 // m_beganSelectingText to prevent handleMouseReleaseEvent 506 // from setting caret selection. 507 m_selectionInitiationState = ExtendedSelection; 508 else 509 selectClosestWordFromMouseEvent(event); 510 511 return true; 512 } 513 514 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event) 515 { 516 if (event.event().button() != LeftButton) 517 return false; 518 519 Node* innerNode = event.targetNode(); 520 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) 521 return false; 522 523 VisibleSelection newSelection; 524 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint())); 525 if (pos.isNotNull()) { 526 newSelection = VisibleSelection(pos); 527 newSelection.expandUsingGranularity(ParagraphGranularity); 528 } 529 530 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); 531 } 532 533 static int textDistance(const Position& start, const Position& end) 534 { 535 RefPtr<Range> range = Range::create(start.anchorNode()->document(), start, end); 536 return TextIterator::rangeLength(range.get(), true); 537 } 538 539 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event) 540 { 541 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 542 Node* innerNode = event.targetNode(); 543 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect)) 544 return false; 545 546 // Extend the selection if the Shift key is down, unless the click is in a link. 547 bool extendSelection = event.event().shiftKey() && !event.isOverLink(); 548 549 // Don't restart the selection when the mouse is pressed on an 550 // existing selection so we can allow for text dragging. 551 if (FrameView* view = m_frame->view()) { 552 LayoutPoint vPoint = view->windowToContents(event.event().position()); 553 if (!extendSelection && m_frame->selection()->contains(vPoint)) { 554 m_mouseDownWasSingleClickInSelection = true; 555 return false; 556 } 557 } 558 559 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint())); 560 if (visiblePos.isNull()) 561 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOWNSTREAM); 562 Position pos = visiblePos.deepEquivalent(); 563 564 VisibleSelection newSelection = m_frame->selection()->selection(); 565 TextGranularity granularity = CharacterGranularity; 566 567 if (extendSelection && newSelection.isCaretOrRange()) { 568 VisibleSelection selectionInUserSelectAll = expandSelectionToRespectUserSelectAll(innerNode, VisibleSelection(pos)); 569 if (selectionInUserSelectAll.isRange()) { 570 if (comparePositions(selectionInUserSelectAll.start(), newSelection.start()) < 0) 571 pos = selectionInUserSelectAll.start(); 572 else if (comparePositions(newSelection.end(), selectionInUserSelectAll.end()) < 0) 573 pos = selectionInUserSelectAll.end(); 574 } 575 576 if (!m_frame->editor()->behavior().shouldConsiderSelectionAsDirectional()) { 577 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection 578 // was created right-to-left 579 Position start = newSelection.start(); 580 Position end = newSelection.end(); 581 int distanceToStart = textDistance(start, pos); 582 int distanceToEnd = textDistance(pos, end); 583 if (distanceToStart <= distanceToEnd) 584 newSelection = VisibleSelection(end, pos); 585 else 586 newSelection = VisibleSelection(start, pos); 587 } else 588 newSelection.setExtent(pos); 589 590 if (m_frame->selection()->granularity() != CharacterGranularity) { 591 granularity = m_frame->selection()->granularity(); 592 newSelection.expandUsingGranularity(m_frame->selection()->granularity()); 593 } 594 } else 595 newSelection = expandSelectionToRespectUserSelectAll(innerNode, visiblePos); 596 597 bool handled = updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, granularity); 598 return handled; 599 } 600 601 static inline bool canMouseDownStartSelect(Node* node) 602 { 603 if (!node || !node->renderer()) 604 return true; 605 606 if (!node->canStartSelection()) 607 return false; 608 609 return true; 610 } 611 612 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event) 613 { 614 // Reset drag state. 615 dragState().m_dragSrc = 0; 616 617 cancelFakeMouseMoveEvent(); 618 619 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 620 621 if (ScrollView* scrollView = m_frame->view()) { 622 if (scrollView->isPointInScrollbarCorner(event.event().position())) 623 return false; 624 } 625 626 bool singleClick = event.event().clickCount() <= 1; 627 628 // If we got the event back, that must mean it wasn't prevented, 629 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. 630 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode()) && !event.scrollbar(); 631 632 m_mouseDownMayStartDrag = singleClick; 633 634 m_mouseDownWasSingleClickInSelection = false; 635 636 m_mouseDown = event.event(); 637 638 if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event)) 639 return true; 640 641 if (m_frame->document()->isSVGDocument() 642 && toSVGDocument(m_frame->document())->zoomAndPanEnabled()) { 643 if (event.event().shiftKey() && singleClick) { 644 m_svgPan = true; 645 toSVGDocument(m_frame->document())->startPan(m_frame->view()->windowToContents(event.event().position())); 646 return true; 647 } 648 } 649 650 // We don't do this at the start of mouse down handling, 651 // because we don't want to do it until we know we didn't hit a widget. 652 if (singleClick) 653 focusDocumentView(); 654 655 Node* innerNode = event.targetNode(); 656 657 m_mousePressNode = innerNode; 658 m_dragStartPos = event.event().position(); 659 660 bool swallowEvent = false; 661 m_mousePressed = true; 662 m_selectionInitiationState = HaveNotStartedSelection; 663 664 if (event.event().clickCount() == 2) 665 swallowEvent = handleMousePressEventDoubleClick(event); 666 else if (event.event().clickCount() >= 3) 667 swallowEvent = handleMousePressEventTripleClick(event); 668 else 669 swallowEvent = handleMousePressEventSingleClick(event); 670 671 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect 672 || (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled()); 673 674 return swallowEvent; 675 } 676 677 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& event) 678 { 679 if (!m_mousePressed) 680 return false; 681 682 if (handleDrag(event, ShouldCheckDragHysteresis)) 683 return true; 684 685 Node* targetNode = event.targetNode(); 686 if (event.event().button() != LeftButton || !targetNode) 687 return false; 688 689 RenderObject* renderer = targetNode->renderer(); 690 if (!renderer) { 691 Node* parent = EventPathWalker::parent(targetNode); 692 if (!parent) 693 return false; 694 695 renderer = parent->renderer(); 696 if (!renderer || !renderer->isListBox()) 697 return false; 698 } 699 700 m_mouseDownMayStartDrag = false; 701 702 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { 703 if (Page* page = m_frame->page()) { 704 page->startAutoscrollForSelection(renderer); 705 m_mouseDownMayStartAutoscroll = false; 706 } 707 } 708 709 if (m_selectionInitiationState != ExtendedSelection) { 710 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 711 HitTestResult result(m_mouseDownPos); 712 m_frame->document()->renderView()->hitTest(request, result); 713 714 updateSelectionForMouseDrag(result); 715 } 716 updateSelectionForMouseDrag(event.hitTestResult()); 717 return true; 718 } 719 720 void EventHandler::updateSelectionForMouseDrag() 721 { 722 FrameView* view = m_frame->view(); 723 if (!view) 724 return; 725 RenderView* renderer = m_frame->contentRenderer(); 726 if (!renderer) 727 return; 728 729 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::Move | HitTestRequest::DisallowShadowContent); 730 HitTestResult result(view->windowToContents(m_lastKnownMousePosition)); 731 renderer->hitTest(request, result); 732 updateSelectionForMouseDrag(result); 733 } 734 735 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResult) 736 { 737 if (!m_mouseDownMayStartSelect) 738 return; 739 740 Node* target = hitTestResult.targetNode(); 741 if (!target) 742 return; 743 744 VisiblePosition targetPosition = m_frame->selection()->selection().visiblePositionRespectingEditingBoundary(hitTestResult.localPoint(), target); 745 // Don't modify the selection if we're not on a node. 746 if (targetPosition.isNull()) 747 return; 748 749 // Restart the selection if this is the first mouse move. This work is usually 750 // done in handleMousePressEvent, but not if the mouse press was on an existing selection. 751 VisibleSelection newSelection = m_frame->selection()->selection(); 752 753 // Special case to limit selection to the containing block for SVG text. 754 // FIXME: Isn't there a better non-SVG-specific way to do this? 755 if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) 756 if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer()) 757 if (selectionBaseRenderer->isSVGText()) 758 if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock()) 759 return; 760 761 if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target)) 762 return; 763 764 if (m_selectionInitiationState != ExtendedSelection) { 765 // Always extend selection here because it's caused by a mouse drag 766 m_selectionInitiationState = ExtendedSelection; 767 newSelection = VisibleSelection(targetPosition); 768 } 769 770 if (RuntimeEnabledFeatures::userSelectAllEnabled()) { 771 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllForNode(m_mousePressNode.get()); 772 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePressNode == Position::rootUserSelectAllForNode(target)) { 773 newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePressNode).upstream(CanCrossEditingBoundary)); 774 newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary)); 775 } else { 776 // Reset base for user select all when base is inside user-select-all area and extent < base. 777 if (rootUserSelectAllForMousePressNode && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0) 778 newSelection.setBase(positionAfterNode(rootUserSelectAllForMousePressNode).downstream(CanCrossEditingBoundary)); 779 780 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNode(target); 781 if (rootUserSelectAllForTarget && m_mousePressNode->renderer() && comparePositions(target->renderer()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->renderer()->positionForPoint(m_dragStartPos)) < 0) 782 newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTarget).upstream(CanCrossEditingBoundary)); 783 else if (rootUserSelectAllForTarget && m_mousePressNode->renderer()) 784 newSelection.setExtent(positionAfterNode(rootUserSelectAllForTarget).downstream(CanCrossEditingBoundary)); 785 else 786 newSelection.setExtent(targetPosition); 787 } 788 } else { 789 newSelection.setExtent(targetPosition); 790 } 791 792 if (m_frame->selection()->granularity() != CharacterGranularity) 793 newSelection.expandUsingGranularity(m_frame->selection()->granularity()); 794 795 m_frame->selection()->setNonDirectionalSelectionIfNeeded(newSelection, m_frame->selection()->granularity(), 796 FrameSelection::AdjustEndpointsAtBidiBoundary); 797 } 798 799 void EventHandler::lostMouseCapture() 800 { 801 m_frame->selection()->setCaretBlinkingSuspended(false); 802 } 803 804 bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event) 805 { 806 // If this was the first click in the window, we don't even want to clear the selection. 807 // This case occurs when the user clicks on a draggable element, since we have to process 808 // the mouse down and drag events to see if we might start a drag. For other first clicks 809 // in a window, we just don't acceptFirstMouse, and the whole down-drag-up sequence gets 810 // ignored upstream of this layer. 811 return false; 812 } 813 814 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& event) 815 { 816 Page* page = m_frame->page(); 817 if (page && page->autoscrollInProgress()) 818 stopAutoscrollTimer(); 819 820 if (handleMouseUp(event)) 821 return true; 822 823 // Used to prevent mouseMoveEvent from initiating a drag before 824 // the mouse is pressed again. 825 m_mousePressed = false; 826 m_capturesDragging = false; 827 m_mouseDownMayStartDrag = false; 828 m_mouseDownMayStartSelect = false; 829 m_mouseDownMayStartAutoscroll = false; 830 m_mouseDownWasInSubframe = false; 831 832 bool handled = false; 833 834 // Clear the selection if the mouse didn't move after the last mouse 835 // press and it's not a context menu click. We do this so when clicking 836 // on the selection, the selection goes away. However, if we are 837 // editing, place the caret. 838 if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != ExtendedSelection 839 && m_dragStartPos == event.event().position() 840 && m_frame->selection()->isRange() 841 && event.event().button() != RightButton) { 842 VisibleSelection newSelection; 843 Node* node = event.targetNode(); 844 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled(); 845 if (node && (caretBrowsing || node->rendererIsEditable()) && node->renderer()) { 846 VisiblePosition pos = VisiblePosition(node->renderer()->positionForPoint(event.localPoint())); 847 newSelection = VisibleSelection(pos); 848 } 849 850 setSelectionIfNeeded(m_frame->selection(), newSelection); 851 852 handled = true; 853 } 854 855 m_frame->selection()->notifyRendererOfSelectionChange(UserTriggered); 856 857 m_frame->selection()->selectFrameElementInParentIfFullySelected(); 858 859 if (event.event().button() == MiddleButton && !event.isOverLink()) { 860 // Ignore handled, since we want to paste to where the caret was placed anyway. 861 handled = handlePasteGlobalSelection(event.event()) || handled; 862 } 863 864 return handled; 865 } 866 867 #if OS(WINDOWS) 868 869 void EventHandler::startPanScrolling(RenderObject* renderer) 870 { 871 if (!renderer->isBox()) 872 return; 873 Page* page = m_frame->page(); 874 if (!page) 875 return; 876 page->startPanScrolling(toRenderBox(renderer), lastKnownMousePosition()); 877 invalidateClick(); 878 } 879 880 #endif // OS(WINDOWS) 881 882 bool EventHandler::panScrollInProgress() const 883 { 884 Page* page = m_frame->page(); 885 return page && page->panScrollInProgress(); 886 } 887 888 HitTestResult EventHandler::hitTestResultAtPoint(const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType, const LayoutSize& padding) 889 { 890 // We always send hitTestResultAtPoint to the main frame if we have one, 891 // otherwise we might hit areas that are obscured by higher frames. 892 if (Page* page = m_frame->page()) { 893 Frame* mainFrame = page->mainFrame(); 894 if (m_frame != mainFrame) { 895 FrameView* frameView = m_frame->view(); 896 FrameView* mainView = mainFrame->view(); 897 if (frameView && mainView) { 898 IntPoint mainFramePoint = mainView->rootViewToContents(frameView->contentsToRootView(roundedIntPoint(point))); 899 return mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, hitType, padding); 900 } 901 } 902 } 903 904 HitTestResult result(point, padding.height(), padding.width(), padding.height(), padding.width()); 905 906 // RenderView::hitTest causes a layout, and we don't want to hit that until the first 907 // layout because until then, there is nothing shown on the screen - the user can't 908 // have intentionally clicked on something belonging to this page. Furthermore, 909 // mousemove events before the first layout should not lead to a premature layout() 910 // happening, which could show a flash of white. 911 // See also the similar code in Document::prepareMouseEvent. 912 if (!m_frame->contentRenderer() || !m_frame->view() || !m_frame->view()->didFirstLayout()) 913 return result; 914 915 // hitTestResultAtPoint is specifically used to hitTest into all frames, thus it always allows child frame content. 916 HitTestRequest request(hitType | HitTestRequest::AllowChildFrameContent); 917 m_frame->contentRenderer()->hitTest(request, result); 918 if (!request.readOnly()) 919 m_frame->document()->updateHoverActiveState(request, result.innerElement()); 920 921 if (request.disallowsShadowContent()) 922 result.setToNodesInDocumentTreeScope(); 923 924 return result; 925 } 926 927 void EventHandler::stopAutoscrollTimer() 928 { 929 Page* page = m_frame->page(); 930 if (!page) 931 return; 932 page->stopAutoscrollTimer(); 933 } 934 935 Node* EventHandler::mousePressNode() const 936 { 937 return m_mousePressNode.get(); 938 } 939 940 void EventHandler::setMousePressNode(PassRefPtr<Node> node) 941 { 942 m_mousePressNode = node; 943 } 944 945 bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) 946 { 947 Node* node = startingNode; 948 949 if (!node) 950 node = m_frame->document()->focusedElement(); 951 952 if (!node) 953 node = m_mousePressNode.get(); 954 955 if (node) { 956 RenderObject* r = node->renderer(); 957 if (r && !r->isListBox() && r->enclosingBox()->scroll(direction, granularity)) { 958 setFrameWasScrolledByUser(); 959 return true; 960 } 961 } 962 963 return false; 964 } 965 966 bool EventHandler::logicalScrollOverflow(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode) 967 { 968 Node* node = startingNode; 969 970 if (!node) 971 node = m_frame->document()->focusedElement(); 972 973 if (!node) 974 node = m_mousePressNode.get(); 975 976 if (node) { 977 RenderObject* r = node->renderer(); 978 if (r && !r->isListBox() && r->enclosingBox()->logicalScroll(direction, granularity)) { 979 setFrameWasScrolledByUser(); 980 return true; 981 } 982 } 983 984 return false; 985 } 986 987 bool EventHandler::scrollRecursively(ScrollDirection direction, ScrollGranularity granularity, Node* startingNode) 988 { 989 // The layout needs to be up to date to determine if we can scroll. We may be 990 // here because of an onLoad event, in which case the final layout hasn't been performed yet. 991 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 992 if (scrollOverflow(direction, granularity, startingNode)) 993 return true; 994 Frame* frame = m_frame; 995 FrameView* view = frame->view(); 996 if (view && view->scroll(direction, granularity)) 997 return true; 998 frame = frame->tree()->parent(); 999 if (!frame) 1000 return false; 1001 return frame->eventHandler()->scrollRecursively(direction, granularity, m_frame->ownerElement()); 1002 } 1003 1004 bool EventHandler::logicalScrollRecursively(ScrollLogicalDirection direction, ScrollGranularity granularity, Node* startingNode) 1005 { 1006 // The layout needs to be up to date to determine if we can scroll. We may be 1007 // here because of an onLoad event, in which case the final layout hasn't been performed yet. 1008 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1009 if (logicalScrollOverflow(direction, granularity, startingNode)) 1010 return true; 1011 Frame* frame = m_frame; 1012 FrameView* view = frame->view(); 1013 1014 bool scrolled = false; 1015 if (view && view->logicalScroll(direction, granularity)) 1016 scrolled = true; 1017 1018 if (scrolled) 1019 return true; 1020 1021 frame = frame->tree()->parent(); 1022 if (!frame) 1023 return false; 1024 1025 return frame->eventHandler()->logicalScrollRecursively(direction, granularity, m_frame->ownerElement()); 1026 } 1027 1028 IntPoint EventHandler::lastKnownMousePosition() const 1029 { 1030 return m_lastKnownMousePosition; 1031 } 1032 1033 Frame* EventHandler::subframeForHitTestResult(const MouseEventWithHitTestResults& hitTestResult) 1034 { 1035 if (!hitTestResult.isOverWidget()) 1036 return 0; 1037 return subframeForTargetNode(hitTestResult.targetNode()); 1038 } 1039 1040 Frame* EventHandler::subframeForTargetNode(Node* node) 1041 { 1042 if (!node) 1043 return 0; 1044 1045 RenderObject* renderer = node->renderer(); 1046 if (!renderer || !renderer->isWidget()) 1047 return 0; 1048 1049 Widget* widget = toRenderWidget(renderer)->widget(); 1050 if (!widget || !widget->isFrameView()) 1051 return 0; 1052 1053 return toFrameView(widget)->frame(); 1054 } 1055 1056 static bool isSubmitImage(Node* node) 1057 { 1058 return node && node->hasTagName(inputTag) && toHTMLInputElement(node)->isImageButton(); 1059 } 1060 1061 // Returns true if the node's editable block is not current focused for editing 1062 static bool nodeIsNotBeingEdited(Node* node, Frame* frame) 1063 { 1064 return frame->selection()->rootEditableElement() != node->rootEditableElement(); 1065 } 1066 1067 bool EventHandler::useHandCursor(Node* node, bool isOverLink, bool shiftKey) 1068 { 1069 if (!node) 1070 return false; 1071 1072 bool editable = node->rendererIsEditable(); 1073 bool editableLinkEnabled = false; 1074 1075 // If the link is editable, then we need to check the settings to see whether or not the link should be followed 1076 if (editable) { 1077 ASSERT(m_frame->settings()); 1078 switch (m_frame->settings()->editableLinkBehavior()) { 1079 default: 1080 case EditableLinkDefaultBehavior: 1081 case EditableLinkAlwaysLive: 1082 editableLinkEnabled = true; 1083 break; 1084 1085 case EditableLinkNeverLive: 1086 editableLinkEnabled = false; 1087 break; 1088 1089 case EditableLinkLiveWhenNotFocused: 1090 editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame) || shiftKey; 1091 break; 1092 1093 case EditableLinkOnlyLiveWithShiftKey: 1094 editableLinkEnabled = shiftKey; 1095 break; 1096 } 1097 } 1098 1099 return ((isOverLink || isSubmitImage(node)) && (!editable || editableLinkEnabled)); 1100 } 1101 1102 OptionalCursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scrollbar* scrollbar) 1103 { 1104 if (m_resizeLayer && m_resizeLayer->inResizeMode()) 1105 return NoCursorChange; 1106 1107 Page* page = m_frame->page(); 1108 if (!page) 1109 return NoCursorChange; 1110 #if OS(WINDOWS) 1111 if (panScrollInProgress()) 1112 return NoCursorChange; 1113 #endif 1114 1115 Node* node = event.targetNode(); 1116 RenderObject* renderer = node ? node->renderer() : 0; 1117 RenderStyle* style = renderer ? renderer->style() : 0; 1118 bool horizontalText = !style || style->isHorizontalWritingMode(); 1119 const Cursor& iBeam = horizontalText ? iBeamCursor() : verticalTextCursor(); 1120 1121 // During selection, use an I-beam no matter what we're over. 1122 // If a drag may be starting or we're capturing mouse events for a particular node, don't treat this as a selection. 1123 if (m_mousePressed && m_mouseDownMayStartSelect 1124 && !m_mouseDownMayStartDrag 1125 && m_frame->selection()->isCaretOrRange() && !m_capturingMouseEventsNode) 1126 return iBeam; 1127 1128 if (renderer) { 1129 Cursor overrideCursor; 1130 switch (renderer->getCursor(roundedIntPoint(event.localPoint()), overrideCursor)) { 1131 case SetCursorBasedOnStyle: 1132 break; 1133 case SetCursor: 1134 return overrideCursor; 1135 case DoNotSetCursor: 1136 return NoCursorChange; 1137 } 1138 } 1139 1140 if (style && style->cursors()) { 1141 const CursorList* cursors = style->cursors(); 1142 for (unsigned i = 0; i < cursors->size(); ++i) { 1143 StyleImage* styleImage = (*cursors)[i].image(); 1144 if (!styleImage) 1145 continue; 1146 ImageResource* cachedImage = styleImage->cachedImage(); 1147 if (!cachedImage) 1148 continue; 1149 float scale = styleImage->imageScaleFactor(); 1150 // Get hotspot and convert from logical pixels to physical pixels. 1151 IntPoint hotSpot = (*cursors)[i].hotSpot(); 1152 hotSpot.scale(scale, scale); 1153 IntSize size = cachedImage->imageForRenderer(renderer)->size(); 1154 if (cachedImage->errorOccurred()) 1155 continue; 1156 // Limit the size of cursors (in UI pixels) so that they cannot be 1157 // used to cover UI elements in chrome. 1158 size.scale(1 / scale); 1159 if (size.width() > maximumCursorSize || size.height() > maximumCursorSize) 1160 continue; 1161 1162 Image* image = cachedImage->imageForRenderer(renderer); 1163 // Ensure no overflow possible in calculations above. 1164 if (scale < minimumCursorScale) 1165 continue; 1166 return Cursor(image, hotSpot, scale); 1167 } 1168 } 1169 1170 switch (style ? style->cursor() : CURSOR_AUTO) { 1171 case CURSOR_AUTO: { 1172 bool editable = (node && node->rendererIsEditable()); 1173 1174 if (useHandCursor(node, event.isOverLink(), event.event().shiftKey())) 1175 return handCursor(); 1176 1177 bool inResizer = false; 1178 if (renderer) { 1179 if (RenderLayer* layer = renderer->enclosingLayer()) { 1180 if (FrameView* view = m_frame->view()) 1181 inResizer = layer->isPointInResizeControl(view->windowToContents(event.event().position()), RenderLayer::ResizerForPointer); 1182 } 1183 } 1184 if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar) 1185 return iBeam; 1186 return pointerCursor(); 1187 } 1188 case CURSOR_CROSS: 1189 return crossCursor(); 1190 case CURSOR_POINTER: 1191 return handCursor(); 1192 case CURSOR_MOVE: 1193 return moveCursor(); 1194 case CURSOR_ALL_SCROLL: 1195 return moveCursor(); 1196 case CURSOR_E_RESIZE: 1197 return eastResizeCursor(); 1198 case CURSOR_W_RESIZE: 1199 return westResizeCursor(); 1200 case CURSOR_N_RESIZE: 1201 return northResizeCursor(); 1202 case CURSOR_S_RESIZE: 1203 return southResizeCursor(); 1204 case CURSOR_NE_RESIZE: 1205 return northEastResizeCursor(); 1206 case CURSOR_SW_RESIZE: 1207 return southWestResizeCursor(); 1208 case CURSOR_NW_RESIZE: 1209 return northWestResizeCursor(); 1210 case CURSOR_SE_RESIZE: 1211 return southEastResizeCursor(); 1212 case CURSOR_NS_RESIZE: 1213 return northSouthResizeCursor(); 1214 case CURSOR_EW_RESIZE: 1215 return eastWestResizeCursor(); 1216 case CURSOR_NESW_RESIZE: 1217 return northEastSouthWestResizeCursor(); 1218 case CURSOR_NWSE_RESIZE: 1219 return northWestSouthEastResizeCursor(); 1220 case CURSOR_COL_RESIZE: 1221 return columnResizeCursor(); 1222 case CURSOR_ROW_RESIZE: 1223 return rowResizeCursor(); 1224 case CURSOR_TEXT: 1225 return iBeamCursor(); 1226 case CURSOR_WAIT: 1227 return waitCursor(); 1228 case CURSOR_HELP: 1229 return helpCursor(); 1230 case CURSOR_VERTICAL_TEXT: 1231 return verticalTextCursor(); 1232 case CURSOR_CELL: 1233 return cellCursor(); 1234 case CURSOR_CONTEXT_MENU: 1235 return contextMenuCursor(); 1236 case CURSOR_PROGRESS: 1237 return progressCursor(); 1238 case CURSOR_NO_DROP: 1239 return noDropCursor(); 1240 case CURSOR_ALIAS: 1241 return aliasCursor(); 1242 case CURSOR_COPY: 1243 return copyCursor(); 1244 case CURSOR_NONE: 1245 return noneCursor(); 1246 case CURSOR_NOT_ALLOWED: 1247 return notAllowedCursor(); 1248 case CURSOR_DEFAULT: 1249 return pointerCursor(); 1250 case CURSOR_WEBKIT_ZOOM_IN: 1251 return zoomInCursor(); 1252 case CURSOR_WEBKIT_ZOOM_OUT: 1253 return zoomOutCursor(); 1254 case CURSOR_WEBKIT_GRAB: 1255 return grabCursor(); 1256 case CURSOR_WEBKIT_GRABBING: 1257 return grabbingCursor(); 1258 } 1259 return pointerCursor(); 1260 } 1261 1262 static LayoutPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint) 1263 { 1264 FrameView* view = frame->view(); 1265 // FIXME: Is it really OK to use the wrong coordinates here when view is 0? 1266 // Historically the code would just crash; this is clearly no worse than that. 1267 return view ? view->windowToContents(windowPoint) : windowPoint; 1268 } 1269 1270 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) 1271 { 1272 RefPtr<FrameView> protector(m_frame->view()); 1273 1274 bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent); 1275 if (defaultPrevented) 1276 return true; 1277 1278 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 1279 m_frame->tree()->top()->eventHandler()->m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); 1280 1281 // FIXME (bug 68185): this call should be made at another abstraction layer 1282 m_frame->loader()->resetMultipleFormSubmissionProtection(); 1283 1284 cancelFakeMouseMoveEvent(); 1285 if (m_eventHandlerWillResetCapturingMouseEventsNode) 1286 m_capturingMouseEventsNode = 0; 1287 m_mousePressed = true; 1288 m_capturesDragging = true; 1289 setLastKnownMousePosition(mouseEvent); 1290 m_mouseDownTimestamp = mouseEvent.timestamp(); 1291 m_mouseDownMayStartDrag = false; 1292 m_mouseDownMayStartSelect = false; 1293 m_mouseDownMayStartAutoscroll = false; 1294 if (FrameView* view = m_frame->view()) 1295 m_mouseDownPos = view->windowToContents(mouseEvent.position()); 1296 else { 1297 invalidateClick(); 1298 return false; 1299 } 1300 m_mouseDownWasInSubframe = false; 1301 1302 HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 1303 // Save the document point we generate in case the window coordinate is invalidated by what happens 1304 // when we dispatch the event. 1305 LayoutPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.position()); 1306 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1307 1308 if (!mev.targetNode()) { 1309 invalidateClick(); 1310 return false; 1311 } 1312 1313 m_mousePressNode = mev.targetNode(); 1314 1315 RefPtr<Frame> subframe = subframeForHitTestResult(mev); 1316 if (subframe && passMousePressEventToSubframe(mev, subframe.get())) { 1317 // Start capturing future events for this frame. We only do this if we didn't clear 1318 // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop. 1319 m_capturesDragging = subframe->eventHandler()->capturesDragging(); 1320 if (m_mousePressed && m_capturesDragging) { 1321 m_capturingMouseEventsNode = mev.targetNode(); 1322 m_eventHandlerWillResetCapturingMouseEventsNode = true; 1323 } 1324 invalidateClick(); 1325 return true; 1326 } 1327 1328 #if OS(WINDOWS) 1329 // We store whether pan scrolling is in progress before calling stopAutoscrollTimer() 1330 // because it will set m_autoscrollType to NoAutoscroll on return. 1331 bool isPanScrollInProgress = panScrollInProgress(); 1332 stopAutoscrollTimer(); 1333 if (isPanScrollInProgress) { 1334 // We invalidate the click when exiting pan scrolling so that we don't inadvertently navigate 1335 // away from the current page (e.g. the click was on a hyperlink). See <rdar://problem/6095023>. 1336 invalidateClick(); 1337 return true; 1338 } 1339 #endif 1340 1341 m_clickCount = mouseEvent.clickCount(); 1342 m_clickNode = mev.targetNode(); 1343 1344 if (FrameView* view = m_frame->view()) { 1345 RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0; 1346 IntPoint p = view->windowToContents(mouseEvent.position()); 1347 if (layer && layer->isPointInResizeControl(p, RenderLayer::ResizerForPointer)) { 1348 layer->setInResizeMode(true); 1349 m_resizeLayer = layer; 1350 m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p); 1351 invalidateClick(); 1352 return true; 1353 } 1354 } 1355 1356 m_frame->selection()->setCaretBlinkingSuspended(true); 1357 1358 bool swallowEvent = !dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true); 1359 m_capturesDragging = !swallowEvent || mev.scrollbar(); 1360 1361 // If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults 1362 // in case the scrollbar widget was destroyed when the mouse event was handled. 1363 if (mev.scrollbar()) { 1364 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get(); 1365 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 1366 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1367 if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get()) 1368 m_lastScrollbarUnderMouse = 0; 1369 } 1370 1371 if (swallowEvent) { 1372 // scrollbars should get events anyway, even disabled controls might be scrollable 1373 Scrollbar* scrollbar = mev.scrollbar(); 1374 1375 updateLastScrollbarUnderMouse(scrollbar, true); 1376 1377 if (scrollbar) 1378 passMousePressEventToScrollbar(mev, scrollbar); 1379 } else { 1380 if (shouldRefetchEventTarget(mev)) { 1381 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 1382 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); 1383 } 1384 1385 FrameView* view = m_frame->view(); 1386 Scrollbar* scrollbar = view ? view->scrollbarAtPoint(mouseEvent.position()) : 0; 1387 if (!scrollbar) 1388 scrollbar = mev.scrollbar(); 1389 1390 updateLastScrollbarUnderMouse(scrollbar, true); 1391 1392 if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar)) 1393 swallowEvent = true; 1394 else 1395 swallowEvent = handleMousePressEvent(mev); 1396 } 1397 1398 return swallowEvent; 1399 } 1400 1401 static RenderLayer* layerForNode(Node* node) 1402 { 1403 if (!node) 1404 return 0; 1405 1406 RenderObject* renderer = node->renderer(); 1407 if (!renderer) 1408 return 0; 1409 1410 RenderLayer* layer = renderer->enclosingLayer(); 1411 if (!layer) 1412 return 0; 1413 1414 return layer; 1415 } 1416 1417 bool EventHandler::mouseMoved(const PlatformMouseEvent& event) 1418 { 1419 RefPtr<FrameView> protector(m_frame->view()); 1420 MaximumDurationTracker maxDurationTracker(&m_maxMouseMovedDuration); 1421 1422 HitTestResult hoveredNode = HitTestResult(LayoutPoint()); 1423 bool result = handleMouseMoveEvent(event, &hoveredNode); 1424 1425 Page* page = m_frame->page(); 1426 if (!page) 1427 return result; 1428 1429 if (RenderLayer* layer = layerForNode(hoveredNode.innerNode())) { 1430 if (FrameView* frameView = m_frame->view()) { 1431 if (frameView->containsScrollableArea(layer)) 1432 layer->mouseMovedInContentArea(); 1433 } 1434 } 1435 1436 if (FrameView* frameView = m_frame->view()) 1437 frameView->mouseMovedInContentArea(); 1438 1439 hoveredNode.setToShadowHostIfInUserAgentShadowRoot(); 1440 page->chrome().mouseDidMoveOverElement(hoveredNode, event.modifierFlags()); 1441 page->chrome().setToolTip(hoveredNode); 1442 1443 return result; 1444 } 1445 1446 static Cursor& syntheticTouchCursor() 1447 { 1448 DEFINE_STATIC_LOCAL(Cursor, c, (Image::loadPlatformResource("syntheticTouchCursor").get(), IntPoint(10, 10))); 1449 return c; 1450 } 1451 1452 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, HitTestResult* hoveredNode, bool onlyUpdateScrollbars) 1453 { 1454 ASSERT(m_frame); 1455 ASSERT(m_frame->view()); 1456 1457 bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent); 1458 if (defaultPrevented) { 1459 m_frame->view()->setCursor(syntheticTouchCursor()); 1460 return true; 1461 } 1462 1463 // FIXME: Both mouseMoved() and handleMouseMoveEvent() are publicly exposed. Fix eternal 1464 // callers to use mouseMoved() instead, and remove the need to double-protect FrameView 1465 // when handleMouseMoveEvent() is called by mouseMoved(). 1466 RefPtr<FrameView> protector(m_frame->view()); 1467 1468 setLastKnownMousePosition(mouseEvent); 1469 1470 if (m_hoverTimer.isActive()) 1471 m_hoverTimer.stop(); 1472 1473 cancelFakeMouseMoveEvent(); 1474 1475 if (m_svgPan) { 1476 toSVGDocument(m_frame->document())->updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition)); 1477 return true; 1478 } 1479 1480 if (m_frameSetBeingResized) 1481 return !dispatchMouseEvent(eventNames().mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false); 1482 1483 // Send events right to a scrollbar if the mouse is pressed. 1484 if (m_lastScrollbarUnderMouse && m_mousePressed) { 1485 m_lastScrollbarUnderMouse->mouseMoved(mouseEvent); 1486 return true; 1487 } 1488 1489 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Move | HitTestRequest::DisallowShadowContent; 1490 if (m_mousePressed) 1491 hitType |= HitTestRequest::Active; 1492 else if (onlyUpdateScrollbars) { 1493 // Mouse events should be treated as "read-only" if we're updating only scrollbars. This 1494 // means that :hover and :active freeze in the state they were in, rather than updating 1495 // for nodes the mouse moves while the window is not key (which will be the case if 1496 // onlyUpdateScrollbars is true). 1497 hitType |= HitTestRequest::ReadOnly; 1498 } 1499 1500 // Treat any mouse move events as readonly if the user is currently touching the screen. 1501 if (m_touchPressed) 1502 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; 1503 HitTestRequest request(hitType); 1504 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); 1505 if (hoveredNode) 1506 *hoveredNode = mev.hitTestResult(); 1507 1508 Scrollbar* scrollbar = 0; 1509 1510 if (m_resizeLayer && m_resizeLayer->inResizeMode()) 1511 m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner); 1512 else { 1513 if (FrameView* view = m_frame->view()) 1514 scrollbar = view->scrollbarAtPoint(mouseEvent.position()); 1515 1516 if (!scrollbar) 1517 scrollbar = mev.scrollbar(); 1518 1519 updateLastScrollbarUnderMouse(scrollbar, !m_mousePressed); 1520 if (onlyUpdateScrollbars) 1521 return true; 1522 } 1523 1524 bool swallowEvent = false; 1525 RefPtr<Frame> newSubframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); 1526 1527 // 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. 1528 if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->isDescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe) 1529 passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get()); 1530 1531 if (newSubframe) { 1532 // Update over/out state before passing the event to the subframe. 1533 updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true); 1534 1535 // Event dispatch in updateMouseEventTargetNode may have caused the subframe of the target 1536 // node to be detached from its FrameView, in which case the event should not be passed. 1537 if (newSubframe->view()) 1538 swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode); 1539 } else { 1540 if (scrollbar && !m_mousePressed) 1541 scrollbar->mouseMoved(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering. 1542 if (FrameView* view = m_frame->view()) { 1543 OptionalCursor optionalCursor = selectCursor(mev, scrollbar); 1544 if (optionalCursor.isCursorChange()) { 1545 m_currentMouseCursor = optionalCursor.cursor(); 1546 view->setCursor(m_currentMouseCursor); 1547 } 1548 } 1549 } 1550 1551 m_lastMouseMoveEventSubframe = newSubframe; 1552 1553 if (swallowEvent) 1554 return true; 1555 1556 swallowEvent = !dispatchMouseEvent(eventNames().mousemoveEvent, mev.targetNode(), false, 0, mouseEvent, true); 1557 if (!swallowEvent) 1558 swallowEvent = handleMouseDraggedEvent(mev); 1559 1560 return swallowEvent; 1561 } 1562 1563 void EventHandler::invalidateClick() 1564 { 1565 m_clickCount = 0; 1566 m_clickNode = 0; 1567 } 1568 1569 inline static bool mouseIsReleasedOnPressedElement(Node* targetNode, Node* clickNode) 1570 { 1571 if (targetNode == clickNode) 1572 return true; 1573 1574 if (!targetNode) 1575 return false; 1576 1577 ShadowRoot* containingShadowRoot = targetNode->containingShadowRoot(); 1578 if (!containingShadowRoot) 1579 return false; 1580 1581 // FIXME: When an element in UA ShadowDOM (e.g. inner element in <input>) is clicked, 1582 // we assume that the host element is clicked. This is necessary for implementing <input type="range"> etc. 1583 // However, we should not check ShadowRoot type basically. 1584 // https://bugs.webkit.org/show_bug.cgi?id=108047 1585 if (containingShadowRoot->type() != ShadowRoot::UserAgentShadowRoot) 1586 return false; 1587 1588 Node* adjustedTargetNode = targetNode->shadowHost(); 1589 Node* adjustedClickNode = clickNode ? clickNode->shadowHost() : 0; 1590 return adjustedTargetNode == adjustedClickNode; 1591 } 1592 1593 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) 1594 { 1595 RefPtr<FrameView> protector(m_frame->view()); 1596 1597 m_frame->selection()->setCaretBlinkingSuspended(false); 1598 1599 bool defaultPrevented = dispatchSyntheticTouchEventIfEnabled(mouseEvent); 1600 if (defaultPrevented) 1601 return true; 1602 1603 OwnPtr<UserGestureIndicator> gestureIndicator; 1604 1605 if (m_frame->tree()->top()->eventHandler()->m_lastMouseDownUserGestureToken) 1606 gestureIndicator = adoptPtr(new UserGestureIndicator(m_frame->tree()->top()->eventHandler()->m_lastMouseDownUserGestureToken.release())); 1607 else 1608 gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingUserGesture)); 1609 1610 #if OS(WINDOWS) 1611 if (Page* page = m_frame->page()) 1612 page->handleMouseReleaseForPanScrolling(m_frame, mouseEvent); 1613 #endif 1614 1615 m_mousePressed = false; 1616 setLastKnownMousePosition(mouseEvent); 1617 1618 if (m_svgPan) { 1619 m_svgPan = false; 1620 toSVGDocument(m_frame->document())->updatePan(m_frame->view()->windowToContents(m_lastKnownMousePosition)); 1621 return true; 1622 } 1623 1624 if (m_frameSetBeingResized) 1625 return !dispatchMouseEvent(eventNames().mouseupEvent, m_frameSetBeingResized.get(), true, m_clickCount, mouseEvent, false); 1626 1627 if (m_lastScrollbarUnderMouse) { 1628 invalidateClick(); 1629 m_lastScrollbarUnderMouse->mouseUp(mouseEvent); 1630 bool cancelable = true; 1631 bool setUnder = false; 1632 return !dispatchMouseEvent(eventNames().mouseupEvent, m_lastNodeUnderMouse.get(), cancelable, m_clickCount, mouseEvent, setUnder); 1633 } 1634 1635 HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowShadowContent); 1636 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); 1637 Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); 1638 if (m_eventHandlerWillResetCapturingMouseEventsNode) 1639 m_capturingMouseEventsNode = 0; 1640 if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) 1641 return true; 1642 1643 bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mev.targetNode(), true, m_clickCount, mouseEvent, false); 1644 1645 bool contextMenuEvent = mouseEvent.button() == RightButton; 1646 #if OS(DARWIN) 1647 // FIXME: The Mac port achieves the same behavior by checking whether the context menu is currently open in WebPage::mouseEvent(). Consider merging the implementations. 1648 if (mouseEvent.button() == LeftButton && mouseEvent.modifiers() & PlatformEvent::CtrlKey) 1649 contextMenuEvent = true; 1650 #endif 1651 1652 bool swallowClickEvent = m_clickCount > 0 && !contextMenuEvent && mouseIsReleasedOnPressedElement(mev.targetNode(), m_clickNode.get()) && !dispatchMouseEvent(eventNames().clickEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true); 1653 1654 if (m_resizeLayer) { 1655 m_resizeLayer->setInResizeMode(false); 1656 m_resizeLayer = 0; 1657 } 1658 1659 bool swallowMouseReleaseEvent = false; 1660 if (!swallowMouseUpEvent) 1661 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); 1662 1663 invalidateClick(); 1664 1665 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; 1666 } 1667 1668 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEvent) 1669 { 1670 // If the event was a middle click, attempt to copy global selection in after 1671 // the newly set caret position. 1672 // 1673 // This code is called from either the mouse up or mouse down handling. There 1674 // is some debate about when the global selection is pasted: 1675 // xterm: pastes on up. 1676 // GTK: pastes on down. 1677 // Qt: pastes on up. 1678 // Firefox: pastes on up. 1679 // Chromium: pastes on up. 1680 // 1681 // There is something of a webcompat angle to this well, as highlighted by 1682 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on 1683 // down then the text is pasted just before the onclick handler runs and 1684 // clears the text box. So it's important this happens after the event 1685 // handlers have been fired. 1686 if (mouseEvent.type() != PlatformEvent::MouseReleased) 1687 return false; 1688 1689 if (!m_frame->page()) 1690 return false; 1691 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); 1692 // Do not paste here if the focus was moved somewhere else. 1693 if (m_frame == focusFrame && m_frame->editor()->client()->supportsGlobalSelection()) 1694 return m_frame->editor()->command("PasteGlobalSelection").execute(); 1695 1696 return false; 1697 } 1698 1699 1700 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard) 1701 { 1702 FrameView* view = m_frame->view(); 1703 1704 // FIXME: We might want to dispatch a dragleave even if the view is gone. 1705 if (!view) 1706 return false; 1707 1708 view->resetDeferredRepaintDelay(); 1709 RefPtr<MouseEvent> me = MouseEvent::create(eventType, 1710 true, true, m_frame->document()->defaultView(), 1711 0, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), 1712 event.movementDelta().x(), event.movementDelta().y(), 1713 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), 1714 0, 0, clipboard); 1715 1716 dragTarget->dispatchEvent(me.get(), IGNORE_EXCEPTION); 1717 return me->defaultPrevented(); 1718 } 1719 1720 static bool targetIsFrame(Node* target, Frame*& frame) 1721 { 1722 if (!target) 1723 return false; 1724 1725 if (!target->hasTagName(frameTag) && !target->hasTagName(iframeTag)) 1726 return false; 1727 1728 frame = static_cast<HTMLFrameElementBase*>(target)->contentFrame(); 1729 1730 return true; 1731 } 1732 1733 static bool findDropZone(Node* target, Clipboard* clipboard) 1734 { 1735 Element* element = target->isElementNode() ? toElement(target) : target->parentElement(); 1736 for (; element; element = element->parentElement()) { 1737 bool matched = false; 1738 String dropZoneStr = element->fastGetAttribute(webkitdropzoneAttr); 1739 1740 if (dropZoneStr.isEmpty()) 1741 continue; 1742 1743 dropZoneStr.makeLower(); 1744 1745 SpaceSplitString keywords(dropZoneStr, false); 1746 if (keywords.isNull()) 1747 continue; 1748 1749 DragOperation dragOperation = DragOperationNone; 1750 for (unsigned int i = 0; i < keywords.size(); i++) { 1751 DragOperation op = convertDropZoneOperationToDragOperation(keywords[i]); 1752 if (op != DragOperationNone) { 1753 if (dragOperation == DragOperationNone) 1754 dragOperation = op; 1755 } else 1756 matched = matched || clipboard->hasDropZoneType(keywords[i].string()); 1757 1758 if (matched && dragOperation != DragOperationNone) 1759 break; 1760 } 1761 if (matched) { 1762 clipboard->setDropEffect(convertDragOperationToDropZoneOperation(dragOperation)); 1763 return true; 1764 } 1765 } 1766 return false; 1767 } 1768 1769 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1770 { 1771 bool accept = false; 1772 1773 if (!m_frame->view()) 1774 return false; 1775 1776 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 1777 MouseEventWithHitTestResults mev = prepareMouseEvent(request, event); 1778 1779 // Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch) 1780 RefPtr<Node> newTarget = mev.targetNode(); 1781 if (newTarget && newTarget->isTextNode()) 1782 newTarget = EventPathWalker::parent(newTarget.get()); 1783 1784 if (Page* page = m_frame->page()) 1785 page->updateDragAndDrop(newTarget.get(), event.position(), event.timestamp()); 1786 1787 if (m_dragTarget != newTarget) { 1788 // FIXME: this ordering was explicitly chosen to match WinIE. However, 1789 // it is sometimes incorrect when dragging within subframes, as seen with 1790 // LayoutTests/fast/events/drag-in-frames.html. 1791 // 1792 // 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>. 1793 Frame* targetFrame; 1794 if (targetIsFrame(newTarget.get(), targetFrame)) { 1795 if (targetFrame) 1796 accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard); 1797 } else if (newTarget) { 1798 // 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. 1799 if (dragState().m_dragSrc) { 1800 // for now we don't care if event handler cancels default behavior, since there is none 1801 dispatchDragSrcEvent(eventNames().dragEvent, event); 1802 } 1803 accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget.get(), event, clipboard); 1804 if (!accept) 1805 accept = findDropZone(newTarget.get(), clipboard); 1806 } 1807 1808 if (targetIsFrame(m_dragTarget.get(), targetFrame)) { 1809 if (targetFrame) 1810 accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard); 1811 } else if (m_dragTarget) 1812 dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); 1813 1814 if (newTarget) { 1815 // We do not explicitly call dispatchDragEvent here because it could ultimately result in the appearance that 1816 // two dragover events fired. So, we mark that we should only fire a dragover event on the next call to this function. 1817 m_shouldOnlyFireDragOverEvent = true; 1818 } 1819 } else { 1820 Frame* targetFrame; 1821 if (targetIsFrame(newTarget.get(), targetFrame)) { 1822 if (targetFrame) 1823 accept = targetFrame->eventHandler()->updateDragAndDrop(event, clipboard); 1824 } else if (newTarget) { 1825 // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. 1826 if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc) { 1827 // for now we don't care if event handler cancels default behavior, since there is none 1828 dispatchDragSrcEvent(eventNames().dragEvent, event); 1829 } 1830 accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget.get(), event, clipboard); 1831 if (!accept) 1832 accept = findDropZone(newTarget.get(), clipboard); 1833 m_shouldOnlyFireDragOverEvent = false; 1834 } 1835 } 1836 m_dragTarget = newTarget; 1837 1838 return accept; 1839 } 1840 1841 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1842 { 1843 Frame* targetFrame; 1844 if (targetIsFrame(m_dragTarget.get(), targetFrame)) { 1845 if (targetFrame) 1846 targetFrame->eventHandler()->cancelDragAndDrop(event, clipboard); 1847 } else if (m_dragTarget.get()) { 1848 if (dragState().m_dragSrc) 1849 dispatchDragSrcEvent(eventNames().dragEvent, event); 1850 dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); 1851 } 1852 clearDragState(); 1853 } 1854 1855 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard) 1856 { 1857 Frame* targetFrame; 1858 bool preventedDefault = false; 1859 if (targetIsFrame(m_dragTarget.get(), targetFrame)) { 1860 if (targetFrame) 1861 preventedDefault = targetFrame->eventHandler()->performDragAndDrop(event, clipboard); 1862 } else if (m_dragTarget.get()) 1863 preventedDefault = dispatchDragEvent(eventNames().dropEvent, m_dragTarget.get(), event, clipboard); 1864 clearDragState(); 1865 return preventedDefault; 1866 } 1867 1868 void EventHandler::clearDragState() 1869 { 1870 stopAutoscrollTimer(); 1871 m_dragTarget = 0; 1872 m_capturingMouseEventsNode = 0; 1873 m_shouldOnlyFireDragOverEvent = false; 1874 } 1875 1876 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n) 1877 { 1878 m_capturingMouseEventsNode = n; 1879 m_eventHandlerWillResetCapturingMouseEventsNode = false; 1880 } 1881 1882 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestRequest& request, const PlatformMouseEvent& mev) 1883 { 1884 ASSERT(m_frame); 1885 ASSERT(m_frame->document()); 1886 1887 return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.position()), mev); 1888 } 1889 1890 static inline SVGElementInstance* instanceAssociatedWithShadowTreeElement(Node* referenceNode) 1891 { 1892 if (!referenceNode || !referenceNode->isSVGElement()) 1893 return 0; 1894 1895 ShadowRoot* shadowRoot = referenceNode->containingShadowRoot(); 1896 if (!shadowRoot) 1897 return 0; 1898 1899 Element* shadowTreeParentElement = shadowRoot->host(); 1900 if (!shadowTreeParentElement || !shadowTreeParentElement->hasTagName(useTag)) 1901 return 0; 1902 1903 return toSVGUseElement(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode); 1904 } 1905 1906 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMouseEvent& mouseEvent, bool fireMouseOverOut) 1907 { 1908 Node* result = targetNode; 1909 1910 // If we're capturing, we always go right to that node. 1911 if (m_capturingMouseEventsNode) 1912 result = m_capturingMouseEventsNode.get(); 1913 else { 1914 // If the target node is a text node, dispatch on the parent node - rdar://4196646 1915 if (result && result->isTextNode()) 1916 result = EventPathWalker::parent(result); 1917 } 1918 m_nodeUnderMouse = result; 1919 m_instanceUnderMouse = instanceAssociatedWithShadowTreeElement(result); 1920 1921 // <use> shadow tree elements may have been recloned, update node under mouse in any case 1922 if (m_lastInstanceUnderMouse) { 1923 SVGElement* lastCorrespondingElement = m_lastInstanceUnderMouse->correspondingElement(); 1924 SVGElement* lastCorrespondingUseElement = m_lastInstanceUnderMouse->correspondingUseElement(); 1925 1926 if (lastCorrespondingElement && lastCorrespondingUseElement) { 1927 HashSet<SVGElementInstance*> instances = lastCorrespondingElement->instancesForElement(); 1928 1929 // Locate the recloned shadow tree element for our corresponding instance 1930 HashSet<SVGElementInstance*>::iterator end = instances.end(); 1931 for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) { 1932 SVGElementInstance* instance = (*it); 1933 ASSERT(instance->correspondingElement() == lastCorrespondingElement); 1934 1935 if (instance == m_lastInstanceUnderMouse) 1936 continue; 1937 1938 if (instance->correspondingUseElement() != lastCorrespondingUseElement) 1939 continue; 1940 1941 SVGElement* shadowTreeElement = instance->shadowTreeElement(); 1942 if (!shadowTreeElement->inDocument() || m_lastNodeUnderMouse == shadowTreeElement) 1943 continue; 1944 1945 m_lastNodeUnderMouse = shadowTreeElement; 1946 m_lastInstanceUnderMouse = instance; 1947 break; 1948 } 1949 } 1950 } 1951 1952 // Fire mouseout/mouseover if the mouse has shifted to a different node. 1953 if (fireMouseOverOut) { 1954 RenderLayer* layerForLastNode = layerForNode(m_lastNodeUnderMouse.get()); 1955 RenderLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderMouse.get()); 1956 Page* page = m_frame->page(); 1957 1958 if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->document() != m_frame->document())) { 1959 // The mouse has moved between frames. 1960 if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) { 1961 if (FrameView* frameView = frame->view()) 1962 frameView->mouseExitedContentArea(); 1963 } 1964 } else if (page && (layerForLastNode && (!layerForNodeUnderMouse || layerForNodeUnderMouse != layerForLastNode))) { 1965 // The mouse has moved between layers. 1966 if (Frame* frame = m_lastNodeUnderMouse->document()->frame()) { 1967 if (FrameView* frameView = frame->view()) { 1968 if (frameView->containsScrollableArea(layerForLastNode)) 1969 layerForLastNode->mouseExitedContentArea(); 1970 } 1971 } 1972 } 1973 1974 if (m_nodeUnderMouse && (!m_lastNodeUnderMouse || m_lastNodeUnderMouse->document() != m_frame->document())) { 1975 // The mouse has moved between frames. 1976 if (Frame* frame = m_nodeUnderMouse->document()->frame()) { 1977 if (FrameView* frameView = frame->view()) 1978 frameView->mouseEnteredContentArea(); 1979 } 1980 } else if (page && (layerForNodeUnderMouse && (!layerForLastNode || layerForNodeUnderMouse != layerForLastNode))) { 1981 // The mouse has moved between layers. 1982 if (Frame* frame = m_nodeUnderMouse->document()->frame()) { 1983 if (FrameView* frameView = frame->view()) { 1984 if (frameView->containsScrollableArea(layerForNodeUnderMouse)) 1985 layerForNodeUnderMouse->mouseEnteredContentArea(); 1986 } 1987 } 1988 } 1989 1990 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame->document()) { 1991 m_lastNodeUnderMouse = 0; 1992 m_lastScrollbarUnderMouse = 0; 1993 m_lastInstanceUnderMouse = 0; 1994 } 1995 1996 if (m_lastNodeUnderMouse != m_nodeUnderMouse) { 1997 // send mouseout event to the old node 1998 if (m_lastNodeUnderMouse) 1999 m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get()); 2000 // send mouseover event to the new node 2001 if (m_nodeUnderMouse) 2002 m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get()); 2003 } 2004 m_lastNodeUnderMouse = m_nodeUnderMouse; 2005 m_lastInstanceUnderMouse = instanceAssociatedWithShadowTreeElement(m_nodeUnderMouse.get()); 2006 } 2007 } 2008 2009 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) 2010 { 2011 if (FrameView* view = m_frame->view()) 2012 view->resetDeferredRepaintDelay(); 2013 2014 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); 2015 2016 bool swallowEvent = false; 2017 2018 if (m_nodeUnderMouse) 2019 swallowEvent = !(m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount)); 2020 2021 if (swallowEvent || eventType != eventNames().mousedownEvent) 2022 return !swallowEvent; 2023 2024 // If clicking on a frame scrollbar, do not mess up with content focus. 2025 if (FrameView* view = m_frame->view()) { 2026 if (view->scrollbarAtPoint(mouseEvent.position())) 2027 return true; 2028 } 2029 2030 // The layout needs to be up to date to determine if an element is focusable. 2031 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 2032 2033 Element* element = 0; 2034 if (m_nodeUnderMouse) 2035 element = m_nodeUnderMouse->isElementNode() ? toElement(m_nodeUnderMouse.get()) : m_nodeUnderMouse->parentOrShadowHostElement(); 2036 for (; element; element = element->parentOrShadowHostElement()) { 2037 if (element->isFocusable()) 2038 break; 2039 } 2040 ASSERT(!element || element->isFocusable()); 2041 2042 // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus 2043 // a node on mouse down if it's selected and inside a focused node. It will 2044 // be focused if the user does a mouseup over it, however, because the 2045 // mouseup will set a selection inside it, which will call 2046 // FrameSelection::setFocusedNodeIfNeeded. 2047 if (element 2048 && m_frame->selection()->isRange() 2049 && m_frame->selection()->toNormalizedRange()->compareNode(element, IGNORE_EXCEPTION) == Range::NODE_INSIDE 2050 && element->isDescendantOf(m_frame->document()->focusedElement())) 2051 return true; 2052 2053 bool elementIsMouseFocusable = element && element->isMouseFocusable(); 2054 2055 // Only change the focus when clicking scrollbars if it can transfered to a 2056 // mouse focusable node. 2057 if (!elementIsMouseFocusable && isInsideScrollbar(mouseEvent.position())) 2058 return false; 2059 2060 if (Page* page = m_frame->page()) { 2061 // If focus shift is blocked, we eat the event. Note we should never 2062 // clear swallowEvent if the page already set it (e.g., by canceling 2063 // default behavior). 2064 if (elementIsMouseFocusable) { 2065 if (!page->focusController().setFocusedElement(element, m_frame, FocusDirectionMouse)) 2066 swallowEvent = true; 2067 } else if (!element || !element->focused()) { 2068 // We call setFocusedElement even with !element in order to blur 2069 // current focus element when a link is clicked; this is expected by 2070 // some sites that rely on onChange handlers running from form 2071 // fields before the button click is processed. 2072 if (!page->focusController().setFocusedElement(0, m_frame)) 2073 swallowEvent = true; 2074 } 2075 } 2076 2077 return !swallowEvent; 2078 } 2079 2080 bool EventHandler::isInsideScrollbar(const IntPoint& windowPoint) const 2081 { 2082 if (RenderView* renderView = m_frame->contentRenderer()) { 2083 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 2084 HitTestResult result(windowPoint); 2085 renderView->hitTest(request, result); 2086 return result.scrollbar(); 2087 } 2088 2089 return false; 2090 } 2091 2092 bool EventHandler::shouldTurnVerticalTicksIntoHorizontal(const HitTestResult& result, const PlatformWheelEvent& event) const 2093 { 2094 #if OS(UNIX) && !OS(DARWIN) 2095 // GTK+ must scroll horizontally if the mouse pointer is on top of the 2096 // horizontal scrollbar while scrolling with the wheel. 2097 // This code comes from gtk/EventHandlerGtk.cpp. 2098 return !event.hasPreciseScrollingDeltas() && result.scrollbar() && result.scrollbar()->orientation() == HorizontalScrollbar; 2099 #else 2100 UNUSED_PARAM(result); 2101 UNUSED_PARAM(event); 2102 return false; 2103 #endif 2104 } 2105 2106 bool EventHandler::handleWheelEvent(const PlatformWheelEvent& e) 2107 { 2108 #define RETURN_WHEEL_EVENT_HANDLED() \ 2109 { \ 2110 setFrameWasScrolledByUser(); \ 2111 return true; \ 2112 } 2113 2114 Document* doc = m_frame->document(); 2115 2116 if (!doc->renderer()) 2117 return false; 2118 2119 RefPtr<FrameView> protector(m_frame->view()); 2120 2121 FrameView* view = m_frame->view(); 2122 if (!view) 2123 return false; 2124 2125 LayoutPoint vPoint = view->windowToContents(e.position()); 2126 2127 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 2128 HitTestResult result(vPoint); 2129 doc->renderView()->hitTest(request, result); 2130 2131 Node* node = result.innerNode(); 2132 // Wheel events should not dispatch to text nodes. 2133 if (node && node->isTextNode()) 2134 node = EventPathWalker::parent(node); 2135 2136 bool isOverWidget; 2137 if (e.useLatchedEventNode()) { 2138 if (!m_latchedWheelEventNode) { 2139 m_latchedWheelEventNode = node; 2140 m_widgetIsLatched = result.isOverWidget(); 2141 } else 2142 node = m_latchedWheelEventNode.get(); 2143 2144 isOverWidget = m_widgetIsLatched; 2145 } else { 2146 if (m_latchedWheelEventNode) 2147 m_latchedWheelEventNode = 0; 2148 if (m_previousWheelScrolledNode) 2149 m_previousWheelScrolledNode = 0; 2150 2151 isOverWidget = result.isOverWidget(); 2152 } 2153 2154 // FIXME: It should not be necessary to do this mutation here. 2155 // Instead, the handlers should know convert vertical scrolls 2156 // appropriately. 2157 PlatformWheelEvent event = e; 2158 if (m_baseEventType == PlatformEvent::NoType && shouldTurnVerticalTicksIntoHorizontal(result, e)) 2159 event = event.copyTurningVerticalTicksIntoHorizontalTicks(); 2160 2161 if (node) { 2162 // Figure out which view to send the event to. 2163 RenderObject* target = node->renderer(); 2164 2165 if (isOverWidget && target && target->isWidget()) { 2166 Widget* widget = toRenderWidget(target)->widget(); 2167 if (widget && passWheelEventToWidget(e, widget)) 2168 RETURN_WHEEL_EVENT_HANDLED(); 2169 } 2170 2171 if (node && !node->dispatchWheelEvent(event)) 2172 RETURN_WHEEL_EVENT_HANDLED(); 2173 } 2174 2175 2176 // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed. 2177 view = m_frame->view(); 2178 if (!view || !view->wheelEvent(event)) 2179 return false; 2180 2181 RETURN_WHEEL_EVENT_HANDLED(); 2182 2183 #undef RETURN_WHEEL_EVENT_HANDLED 2184 } 2185 2186 void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent) 2187 { 2188 if (!startNode || !wheelEvent) 2189 return; 2190 2191 Node* stopNode = m_previousWheelScrolledNode.get(); 2192 ScrollGranularity granularity = wheelGranularityToScrollGranularity(wheelEvent->deltaMode()); 2193 2194 // Break up into two scrolls if we need to. Diagonal movement on 2195 // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set). 2196 if (scrollNode(wheelEvent->rawDeltaX(), granularity, ScrollLeft, ScrollRight, startNode, &stopNode)) 2197 wheelEvent->setDefaultHandled(); 2198 2199 if (scrollNode(wheelEvent->rawDeltaY(), granularity, ScrollUp, ScrollDown, startNode, &stopNode)) 2200 wheelEvent->setDefaultHandled(); 2201 2202 if (!m_latchedWheelEventNode) 2203 m_previousWheelScrolledNode = stopNode; 2204 } 2205 2206 bool EventHandler::handleGestureTapDown() 2207 { 2208 FrameView* view = m_frame->view(); 2209 if (!view) 2210 return false; 2211 if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator()) 2212 scrollAnimator->cancelAnimations(); 2213 const FrameView::ScrollableAreaSet* areas = view->scrollableAreas(); 2214 if (!areas) 2215 return false; 2216 for (FrameView::ScrollableAreaSet::const_iterator it = areas->begin(); it != areas->end(); ++it) { 2217 ScrollableArea* sa = *it; 2218 ScrollAnimator* animator = sa->scrollAnimator(); 2219 if (animator) 2220 animator->cancelAnimations(); 2221 } 2222 return false; 2223 } 2224 2225 bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent) 2226 { 2227 Node* eventTarget = 0; 2228 Scrollbar* scrollbar = 0; 2229 if (gestureEvent.type() == PlatformEvent::GestureScrollEnd 2230 || gestureEvent.type() == PlatformEvent::GestureScrollUpdate 2231 || gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation) { 2232 scrollbar = m_scrollbarHandlingScrollGesture.get(); 2233 eventTarget = m_scrollGestureHandlingNode.get(); 2234 } 2235 2236 IntPoint adjustedPoint = gestureEvent.position(); 2237 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent; 2238 if (gestureEvent.type() == PlatformEvent::GestureTapDown || 2239 gestureEvent.type() == PlatformEvent::GestureTapUnconfirmed) { 2240 adjustGesturePosition(gestureEvent, adjustedPoint); 2241 hitType |= HitTestRequest::Active; 2242 } else if (gestureEvent.type() == PlatformEvent::GestureTapDownCancel) 2243 hitType |= HitTestRequest::Release; 2244 else if (gestureEvent.type() == PlatformEvent::GestureTap) { 2245 // The mouseup event synthesized for this gesture will clear the active state of the 2246 // targeted node, so performing a ReadOnly hit test here is fine. 2247 hitType |= HitTestRequest::ReadOnly; 2248 } 2249 else 2250 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; 2251 2252 if (!shouldGesturesTriggerActive()) 2253 hitType |= HitTestRequest::ReadOnly; 2254 2255 if ((!scrollbar && !eventTarget) || !(hitType & HitTestRequest::ReadOnly)) { 2256 IntPoint hitTestPoint = m_frame->view()->windowToContents(adjustedPoint); 2257 HitTestResult result = hitTestResultAtPoint(hitTestPoint, hitType | HitTestRequest::AllowFrameScrollbars); 2258 eventTarget = result.targetNode(); 2259 if (!scrollbar) { 2260 FrameView* view = m_frame->view(); 2261 scrollbar = view ? view->scrollbarAtPoint(gestureEvent.position()) : 0; 2262 } 2263 if (!scrollbar) 2264 scrollbar = result.scrollbar(); 2265 } 2266 2267 if (scrollbar) { 2268 bool eventSwallowed = scrollbar->gestureEvent(gestureEvent); 2269 if (gestureEvent.type() == PlatformEvent::GestureScrollBegin && eventSwallowed) 2270 m_scrollbarHandlingScrollGesture = scrollbar; 2271 else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd || !eventSwallowed) 2272 m_scrollbarHandlingScrollGesture = 0; 2273 2274 if (eventSwallowed) 2275 return true; 2276 } 2277 2278 if (eventTarget) { 2279 bool eventSwallowed = false; 2280 if (handleScrollGestureOnResizer(eventTarget, gestureEvent)) 2281 eventSwallowed = true; 2282 else 2283 eventSwallowed = eventTarget->dispatchGestureEvent(gestureEvent); 2284 if (gestureEvent.type() == PlatformEvent::GestureScrollBegin || gestureEvent.type() == PlatformEvent::GestureScrollEnd) { 2285 if (eventSwallowed) 2286 m_scrollGestureHandlingNode = eventTarget; 2287 } 2288 2289 if (eventSwallowed) 2290 return true; 2291 } 2292 2293 // FIXME: A more general scroll system (https://bugs.webkit.org/show_bug.cgi?id=80596) will 2294 // eliminate the need for this. 2295 TemporaryChange<PlatformEvent::Type> baseEventType(m_baseEventType, gestureEvent.type()); 2296 2297 switch (gestureEvent.type()) { 2298 case PlatformEvent::GestureScrollBegin: 2299 return handleGestureScrollBegin(gestureEvent); 2300 case PlatformEvent::GestureScrollUpdate: 2301 case PlatformEvent::GestureScrollUpdateWithoutPropagation: 2302 return handleGestureScrollUpdate(gestureEvent); 2303 case PlatformEvent::GestureScrollEnd: 2304 return handleGestureScrollEnd(gestureEvent); 2305 case PlatformEvent::GestureTap: 2306 return handleGestureTap(gestureEvent); 2307 case PlatformEvent::GestureTapDown: 2308 return handleGestureTapDown(); 2309 case PlatformEvent::GestureLongPress: 2310 return handleGestureLongPress(gestureEvent); 2311 case PlatformEvent::GestureLongTap: 2312 return handleGestureLongTap(gestureEvent); 2313 case PlatformEvent::GestureTwoFingerTap: 2314 return handleGestureTwoFingerTap(gestureEvent); 2315 case PlatformEvent::GesturePinchBegin: 2316 case PlatformEvent::GesturePinchEnd: 2317 case PlatformEvent::GesturePinchUpdate: 2318 case PlatformEvent::GestureTapDownCancel: 2319 case PlatformEvent::GestureTapUnconfirmed: 2320 break; 2321 default: 2322 ASSERT_NOT_REACHED(); 2323 } 2324 2325 return false; 2326 } 2327 2328 bool EventHandler::handleGestureTap(const PlatformGestureEvent& gestureEvent) 2329 { 2330 // FIXME: Refactor this code to not hit test multiple times. We use the adjusted position to ensure that the correct node is targeted by the later redundant hit tests. 2331 IntPoint adjustedPoint = gestureEvent.position(); 2332 adjustGesturePosition(gestureEvent, adjustedPoint); 2333 2334 PlatformMouseEvent fakeMouseMove(adjustedPoint, gestureEvent.globalPosition(), 2335 NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0, 2336 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); 2337 mouseMoved(fakeMouseMove); 2338 2339 int tapCount = 1; 2340 // FIXME: deletaX is overloaded to mean different things for different gestures. 2341 // http://wkb.ug/93123 2342 if (gestureEvent.deltaX() > 0) 2343 tapCount = static_cast<int>(gestureEvent.deltaX()); 2344 2345 bool defaultPrevented = false; 2346 PlatformMouseEvent fakeMouseDown(adjustedPoint, gestureEvent.globalPosition(), 2347 LeftButton, PlatformEvent::MousePressed, tapCount, 2348 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); 2349 defaultPrevented |= handleMousePressEvent(fakeMouseDown); 2350 2351 PlatformMouseEvent fakeMouseUp(adjustedPoint, gestureEvent.globalPosition(), 2352 LeftButton, PlatformEvent::MouseReleased, tapCount, 2353 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); 2354 defaultPrevented |= handleMouseReleaseEvent(fakeMouseUp); 2355 2356 return defaultPrevented; 2357 } 2358 2359 bool EventHandler::handleGestureLongPress(const PlatformGestureEvent& gestureEvent) 2360 { 2361 IntPoint adjustedPoint = gestureEvent.position(); 2362 adjustGesturePosition(gestureEvent, adjustedPoint); 2363 RefPtr<Frame> subframe = getSubFrameForGestureEvent(adjustedPoint, gestureEvent); 2364 if (subframe && subframe->eventHandler()->handleGestureLongPress(gestureEvent)) 2365 return true; 2366 2367 m_longTapShouldInvokeContextMenu = false; 2368 if (m_frame->settings() && m_frame->settings()->touchDragDropEnabled() && m_frame->view()) { 2369 PlatformMouseEvent mouseDownEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, 1, 2370 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), WTF::currentTime()); 2371 m_mouseDown = mouseDownEvent; 2372 2373 PlatformMouseEvent mouseDragEvent(adjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MouseMoved, 1, 2374 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), WTF::currentTime()); 2375 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 2376 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragEvent); 2377 m_didStartDrag = false; 2378 m_mouseDownMayStartDrag = true; 2379 dragState().m_dragSrc = 0; 2380 m_mouseDownPos = m_frame->view()->windowToContents(mouseDragEvent.position()); 2381 RefPtr<FrameView> protector(m_frame->view()); 2382 handleDrag(mev, DontCheckDragHysteresis); 2383 if (m_didStartDrag) { 2384 m_longTapShouldInvokeContextMenu = true; 2385 return true; 2386 } 2387 } 2388 #if OS(ANDROID) 2389 bool shouldLongPressSelectWord = true; 2390 #else 2391 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()->touchEditingEnabled(); 2392 #endif 2393 if (shouldLongPressSelectWord) { 2394 IntPoint hitTestPoint = m_frame->view()->windowToContents(gestureEvent.position()); 2395 HitTestResult result = hitTestResultAtPoint(hitTestPoint); 2396 Node* innerNode = result.targetNode(); 2397 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode())) { 2398 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitespace); 2399 if (m_frame->selection()->isRange()) { 2400 focusDocumentView(); 2401 return true; 2402 } 2403 } 2404 } 2405 return sendContextMenuEventForGesture(gestureEvent); 2406 } 2407 2408 bool EventHandler::handleGestureLongTap(const PlatformGestureEvent& gestureEvent) 2409 { 2410 IntPoint adjustedPoint = gestureEvent.position(); 2411 adjustGesturePosition(gestureEvent, adjustedPoint); 2412 RefPtr<Frame> subframe = getSubFrameForGestureEvent(adjustedPoint, gestureEvent); 2413 if (subframe && subframe->eventHandler()->handleGestureLongTap(gestureEvent)) 2414 return true; 2415 #if !OS(ANDROID) 2416 if (m_longTapShouldInvokeContextMenu) { 2417 m_longTapShouldInvokeContextMenu = false; 2418 return sendContextMenuEventForGesture(gestureEvent); 2419 } 2420 #endif 2421 return false; 2422 } 2423 2424 bool EventHandler::handleScrollGestureOnResizer(Node* eventTarget, const PlatformGestureEvent& gestureEvent) { 2425 if (gestureEvent.type() == PlatformEvent::GestureScrollBegin) { 2426 RenderLayer* layer = eventTarget->renderer() ? eventTarget->renderer()->enclosingLayer() : 0; 2427 IntPoint p = m_frame->view()->windowToContents(gestureEvent.position()); 2428 if (layer && layer->isPointInResizeControl(p, RenderLayer::ResizerForTouch)) { 2429 layer->setInResizeMode(true); 2430 m_resizeLayer = layer; 2431 m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p); 2432 return true; 2433 } 2434 } else if (gestureEvent.type() == PlatformEvent::GestureScrollUpdate || 2435 gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation) { 2436 if (m_resizeLayer && m_resizeLayer->inResizeMode()) { 2437 m_resizeLayer->resize(gestureEvent, m_offsetFromResizeCorner); 2438 return true; 2439 } 2440 } else if (gestureEvent.type() == PlatformEvent::GestureScrollEnd) { 2441 if (m_resizeLayer && m_resizeLayer->inResizeMode()) { 2442 m_resizeLayer->setInResizeMode(false); 2443 m_resizeLayer = 0; 2444 return false; 2445 } 2446 } 2447 2448 return false; 2449 } 2450 2451 bool EventHandler::handleGestureTwoFingerTap(const PlatformGestureEvent& gestureEvent) 2452 { 2453 return sendContextMenuEventForGesture(gestureEvent); 2454 } 2455 2456 bool EventHandler::passGestureEventToWidget(const PlatformGestureEvent& gestureEvent, Widget* widget) 2457 { 2458 if (!widget) 2459 return false; 2460 2461 if (!widget->isFrameView()) 2462 return false; 2463 2464 return toFrameView(widget)->frame()->eventHandler()->handleGestureEvent(gestureEvent); 2465 } 2466 2467 bool EventHandler::passGestureEventToWidgetIfPossible(const PlatformGestureEvent& gestureEvent, RenderObject* renderer) 2468 { 2469 if (m_lastHitTestResultOverWidget && renderer && renderer->isWidget()) { 2470 Widget* widget = toRenderWidget(renderer)->widget(); 2471 return widget && passGestureEventToWidget(gestureEvent, widget); 2472 } 2473 return false; 2474 } 2475 2476 bool EventHandler::handleGestureScrollEnd(const PlatformGestureEvent& gestureEvent) { 2477 Node* node = m_scrollGestureHandlingNode.get(); 2478 clearGestureScrollNodes(); 2479 2480 if (node) 2481 passGestureEventToWidgetIfPossible(gestureEvent, node->renderer()); 2482 2483 return false; 2484 } 2485 2486 bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent) 2487 { 2488 Document* document = m_frame->document(); 2489 RenderObject* documentRenderer = document->renderer(); 2490 if (!documentRenderer) 2491 return false; 2492 2493 FrameView* view = m_frame->view(); 2494 if (!view) 2495 return false; 2496 2497 LayoutPoint viewPoint = view->windowToContents(gestureEvent.position()); 2498 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 2499 HitTestResult result(viewPoint); 2500 document->renderView()->hitTest(request, result); 2501 2502 m_lastHitTestResultOverWidget = result.isOverWidget(); 2503 m_scrollGestureHandlingNode = result.innerNode(); 2504 m_previousGestureScrolledNode = 0; 2505 2506 Node* node = m_scrollGestureHandlingNode.get(); 2507 if (node) 2508 passGestureEventToWidgetIfPossible(gestureEvent, node->renderer()); 2509 2510 return node && node->renderer(); 2511 } 2512 2513 bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent) 2514 { 2515 FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY()); 2516 if (delta.isZero()) 2517 return false; 2518 2519 const float scaleFactor = m_frame->pageZoomFactor(); 2520 delta.scale(1 / scaleFactor, 1 / scaleFactor); 2521 2522 Node* node = m_scrollGestureHandlingNode.get(); 2523 if (!node) 2524 return sendScrollEventToView(gestureEvent, delta); 2525 2526 // Ignore this event if the targeted node does not have a valid renderer. 2527 RenderObject* renderer = node->renderer(); 2528 if (!renderer) 2529 return false; 2530 2531 RefPtr<FrameView> protector(m_frame->view()); 2532 2533 Node* stopNode = 0; 2534 bool scrollShouldNotPropagate = gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation; 2535 2536 // Try to send the event to the correct view. 2537 if (passGestureEventToWidgetIfPossible(gestureEvent, renderer)) { 2538 if(scrollShouldNotPropagate) 2539 m_previousGestureScrolledNode = m_scrollGestureHandlingNode; 2540 2541 return true; 2542 } 2543 2544 if (scrollShouldNotPropagate) 2545 stopNode = m_previousGestureScrolledNode.get(); 2546 2547 // First try to scroll the closest scrollable RenderBox ancestor of |node|. 2548 ScrollGranularity granularity = ScrollByPixel; 2549 bool horizontalScroll = scrollNode(delta.width(), granularity, ScrollLeft, ScrollRight, node, &stopNode); 2550 bool verticalScroll = scrollNode(delta.height(), granularity, ScrollUp, ScrollDown, node, &stopNode); 2551 2552 if (scrollShouldNotPropagate) 2553 m_previousGestureScrolledNode = stopNode; 2554 2555 if (horizontalScroll || verticalScroll) { 2556 setFrameWasScrolledByUser(); 2557 return true; 2558 } 2559 2560 // Otherwise try to scroll the view. 2561 return sendScrollEventToView(gestureEvent, delta); 2562 } 2563 2564 bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEvent, const FloatSize& scaledDelta) 2565 { 2566 FrameView* view = m_frame->view(); 2567 if (!view) 2568 return false; 2569 2570 const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier); 2571 IntPoint point(gestureEvent.position().x(), gestureEvent.position().y()); 2572 IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalPosition().y()); 2573 PlatformWheelEvent syntheticWheelEvent(point, globalPoint, 2574 scaledDelta.width(), scaledDelta.height(), 2575 scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor, 2576 ScrollByPixelWheelEvent, 2577 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey()); 2578 syntheticWheelEvent.setHasPreciseScrollingDeltas(true); 2579 2580 bool scrolledFrame = view->wheelEvent(syntheticWheelEvent); 2581 if (scrolledFrame) 2582 setFrameWasScrolledByUser(); 2583 2584 return scrolledFrame; 2585 } 2586 2587 Frame* EventHandler::getSubFrameForGestureEvent(const IntPoint& touchAdjustedPoint, const PlatformGestureEvent& gestureEvent) 2588 { 2589 PlatformMouseEvent mouseDown(touchAdjustedPoint, gestureEvent.globalPosition(), LeftButton, PlatformEvent::MousePressed, 1, 2590 gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey(), gestureEvent.timestamp()); 2591 HitTestRequest request(HitTestRequest::ReadOnly); 2592 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDown); 2593 return EventHandler::subframeForHitTestResult(mev); 2594 } 2595 2596 void EventHandler::clearGestureScrollNodes() 2597 { 2598 m_scrollGestureHandlingNode = 0; 2599 m_previousGestureScrolledNode = 0; 2600 } 2601 2602 bool EventHandler::isScrollbarHandlingGestures() const 2603 { 2604 return m_scrollbarHandlingScrollGesture.get(); 2605 } 2606 2607 bool EventHandler::shouldApplyTouchAdjustment(const PlatformGestureEvent& event) const 2608 { 2609 if (m_frame->settings() && !m_frame->settings()->touchAdjustmentEnabled()) 2610 return false; 2611 return !event.area().isEmpty(); 2612 } 2613 2614 2615 bool EventHandler::bestClickableNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode) 2616 { 2617 IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter); 2618 HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius); 2619 2620 IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); 2621 Vector<RefPtr<Node>, 11> nodes; 2622 copyToVector(result.rectBasedTestResult(), nodes); 2623 2624 // FIXME: Should be able to handle targetNode being a shadow DOM node to avoid performing uncessary hit tests 2625 // in the case where further processing on the node is required. Returning the shadow ancestor prevents a 2626 // regression in touchadjustment/html-label.html. Some refinement is required to testing/internals to 2627 // handle targetNode being a shadow DOM node. 2628 bool success = findBestClickableCandidate(targetNode, targetPoint, touchCenter, touchRect, nodes); 2629 if (success && targetNode) 2630 targetNode = targetNode->deprecatedShadowAncestorNode(); 2631 return success; 2632 } 2633 2634 bool EventHandler::bestContextMenuNodeForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntPoint& targetPoint, Node*& targetNode) 2635 { 2636 IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter); 2637 HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active, touchRadius); 2638 2639 IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); 2640 Vector<RefPtr<Node>, 11> nodes; 2641 copyToVector(result.rectBasedTestResult(), nodes); 2642 return findBestContextMenuCandidate(targetNode, targetPoint, touchCenter, touchRect, nodes); 2643 } 2644 2645 bool EventHandler::bestZoomableAreaForTouchPoint(const IntPoint& touchCenter, const IntSize& touchRadius, IntRect& targetArea, Node*& targetNode) 2646 { 2647 IntPoint hitTestPoint = m_frame->view()->windowToContents(touchCenter); 2648 HitTestResult result = hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent, touchRadius); 2649 2650 IntRect touchRect(touchCenter - touchRadius, touchRadius + touchRadius); 2651 Vector<RefPtr<Node>, 11> nodes; 2652 copyToVector(result.rectBasedTestResult(), nodes); 2653 return findBestZoomableArea(targetNode, targetArea, touchCenter, touchRect, nodes); 2654 } 2655 2656 bool EventHandler::adjustGesturePosition(const PlatformGestureEvent& gestureEvent, IntPoint& adjustedPoint) 2657 { 2658 if (!shouldApplyTouchAdjustment(gestureEvent)) 2659 return false; 2660 2661 Node* targetNode = 0; 2662 switch (gestureEvent.type()) { 2663 case PlatformEvent::GestureTap: 2664 case PlatformEvent::GestureTapUnconfirmed: 2665 case PlatformEvent::GestureTapDown: 2666 bestClickableNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode); 2667 break; 2668 case PlatformEvent::GestureLongPress: 2669 case PlatformEvent::GestureLongTap: 2670 case PlatformEvent::GestureTwoFingerTap: 2671 bestContextMenuNodeForTouchPoint(gestureEvent.position(), IntSize(gestureEvent.area().width() / 2, gestureEvent.area().height() / 2), adjustedPoint, targetNode); 2672 break; 2673 default: 2674 // FIXME: Implement handling for other types as needed. 2675 ASSERT_NOT_REACHED(); 2676 } 2677 return targetNode; 2678 } 2679 2680 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event) 2681 { 2682 Document* doc = m_frame->document(); 2683 FrameView* v = m_frame->view(); 2684 if (!v) 2685 return false; 2686 2687 // Clear mouse press state to avoid initiating a drag while context menu is up. 2688 m_mousePressed = false; 2689 bool swallowEvent; 2690 LayoutPoint viewportPos = v->windowToContents(event.position()); 2691 HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 2692 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event); 2693 2694 if (!m_frame->selection()->contains(viewportPos) 2695 && !mev.scrollbar() 2696 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. 2697 // If the selection is non-editable, we do word selection to make it easier to use the contextual menu items 2698 // available for text selections. But only if we're above text. 2699 && (m_frame->selection()->isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) { 2700 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection 2701 2702 if (mev.hitTestResult().isMisspelled()) 2703 selectClosestMisspellingFromMouseEvent(mev); 2704 else if (m_frame->editor()->behavior().shouldSelectOnContextualMenuClick()) 2705 selectClosestWordOrLinkFromMouseEvent(mev); 2706 } 2707 2708 swallowEvent = !dispatchMouseEvent(eventNames().contextmenuEvent, mev.targetNode(), true, 0, event, false); 2709 2710 return swallowEvent; 2711 } 2712 2713 bool EventHandler::sendContextMenuEventForKey() 2714 { 2715 FrameView* view = m_frame->view(); 2716 if (!view) 2717 return false; 2718 2719 Document* doc = m_frame->document(); 2720 if (!doc) 2721 return false; 2722 2723 // Clear mouse press state to avoid initiating a drag while context menu is up. 2724 m_mousePressed = false; 2725 2726 static const int kContextMenuMargin = 1; 2727 2728 #if OS(WINDOWS) 2729 int rightAligned = ::GetSystemMetrics(SM_MENUDROPALIGNMENT); 2730 #else 2731 int rightAligned = 0; 2732 #endif 2733 IntPoint location; 2734 2735 Element* focusedElement = doc->focusedElement(); 2736 FrameSelection* selection = m_frame->selection(); 2737 Position start = selection->selection().start(); 2738 2739 if (start.deprecatedNode() && (selection->rootEditableElement() || selection->isRange())) { 2740 RefPtr<Range> selectionRange = selection->toNormalizedRange(); 2741 IntRect firstRect = m_frame->editor()->firstRectForRange(selectionRange.get()); 2742 2743 int x = rightAligned ? firstRect.maxX() : firstRect.x(); 2744 // In a multiline edit, firstRect.maxY() would endup on the next line, so -1. 2745 int y = firstRect.maxY() ? firstRect.maxY() - 1 : 0; 2746 location = IntPoint(x, y); 2747 } else if (focusedElement) { 2748 RenderBoxModelObject* box = focusedElement->renderBoxModelObject(); 2749 if (!box) 2750 return false; 2751 IntRect clippedRect = box->pixelSnappedAbsoluteClippedOverflowRect(); 2752 location = IntPoint(clippedRect.x(), clippedRect.maxY() - 1); 2753 } else { 2754 location = IntPoint( 2755 rightAligned ? view->contentsWidth() - kContextMenuMargin : kContextMenuMargin, 2756 kContextMenuMargin); 2757 } 2758 2759 m_frame->view()->setCursor(pointerCursor()); 2760 2761 IntPoint position = view->contentsToRootView(location); 2762 IntPoint globalPosition = view->hostWindow()->rootViewToScreen(IntRect(position, IntSize())).location(); 2763 2764 Node* targetNode = doc->focusedElement(); 2765 if (!targetNode) 2766 targetNode = doc; 2767 2768 // Use the focused node as the target for hover and active. 2769 HitTestResult result(position); 2770 result.setInnerNode(targetNode); 2771 doc->updateHoverActiveState(HitTestRequest::Active | HitTestRequest::DisallowShadowContent, result.innerElement()); 2772 2773 // The contextmenu event is a mouse event even when invoked using the keyboard. 2774 // This is required for web compatibility. 2775 2776 #if OS(WINDOWS) 2777 PlatformEvent::Type eventType = PlatformEvent::MouseReleased; 2778 #else 2779 PlatformEvent::Type eventType = PlatformEvent::MousePressed; 2780 #endif 2781 2782 PlatformMouseEvent mouseEvent(position, globalPosition, RightButton, eventType, 1, false, false, false, false, WTF::currentTime()); 2783 2784 return !dispatchMouseEvent(eventNames().contextmenuEvent, targetNode, true, 0, mouseEvent, false); 2785 } 2786 2787 bool EventHandler::sendContextMenuEventForGesture(const PlatformGestureEvent& event) 2788 { 2789 #if OS(WINDOWS) 2790 PlatformEvent::Type eventType = PlatformEvent::MouseReleased; 2791 #else 2792 PlatformEvent::Type eventType = PlatformEvent::MousePressed; 2793 #endif 2794 2795 IntPoint adjustedPoint = event.position(); 2796 adjustGesturePosition(event, adjustedPoint); 2797 PlatformMouseEvent mouseEvent(adjustedPoint, event.globalPosition(), RightButton, eventType, 1, false, false, false, false, WTF::currentTime()); 2798 // To simulate right-click behavior, we send a right mouse down and then 2799 // context menu event. 2800 handleMousePressEvent(mouseEvent); 2801 return sendContextMenuEvent(mouseEvent); 2802 // We do not need to send a corresponding mouse release because in case of 2803 // right-click, the context menu takes capture and consumes all events. 2804 } 2805 2806 void EventHandler::scheduleHoverStateUpdate() 2807 { 2808 if (!m_hoverTimer.isActive()) 2809 m_hoverTimer.startOneShot(0); 2810 } 2811 2812 void EventHandler::dispatchFakeMouseMoveEventSoon() 2813 { 2814 if (m_mousePressed) 2815 return; 2816 2817 if (m_mousePositionIsUnknown) 2818 return; 2819 2820 Settings* settings = m_frame->settings(); 2821 if (settings && !settings->deviceSupportsMouse()) 2822 return; 2823 2824 // If the content has ever taken longer than fakeMouseMoveShortInterval we 2825 // reschedule the timer and use a longer time. This will cause the content 2826 // to receive these moves only after the user is done scrolling, reducing 2827 // pauses during the scroll. 2828 if (m_maxMouseMovedDuration > fakeMouseMoveShortInterval) { 2829 if (m_fakeMouseMoveEventTimer.isActive()) 2830 m_fakeMouseMoveEventTimer.stop(); 2831 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveLongInterval); 2832 } else { 2833 if (!m_fakeMouseMoveEventTimer.isActive()) 2834 m_fakeMouseMoveEventTimer.startOneShot(fakeMouseMoveShortInterval); 2835 } 2836 } 2837 2838 void EventHandler::dispatchFakeMouseMoveEventSoonInQuad(const FloatQuad& quad) 2839 { 2840 FrameView* view = m_frame->view(); 2841 if (!view) 2842 return; 2843 2844 if (!quad.containsPoint(view->windowToContents(m_lastKnownMousePosition))) 2845 return; 2846 2847 dispatchFakeMouseMoveEventSoon(); 2848 } 2849 2850 void EventHandler::fakeMouseMoveEventTimerFired(Timer<EventHandler>* timer) 2851 { 2852 ASSERT_UNUSED(timer, timer == &m_fakeMouseMoveEventTimer); 2853 ASSERT(!m_mousePressed); 2854 2855 Settings* settings = m_frame->settings(); 2856 if (settings && !settings->deviceSupportsMouse()) 2857 return; 2858 2859 FrameView* view = m_frame->view(); 2860 if (!view) 2861 return; 2862 2863 if (!m_frame->page() || !m_frame->page()->focusController().isActive()) 2864 return; 2865 2866 // Don't dispatch a synthetic mouse move event if the mouse cursor is not visible to the user. 2867 if (!isCursorVisible()) 2868 return; 2869 2870 bool shiftKey; 2871 bool ctrlKey; 2872 bool altKey; 2873 bool metaKey; 2874 PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey); 2875 PlatformMouseEvent fakeMouseMoveEvent(m_lastKnownMousePosition, m_lastKnownMouseGlobalPosition, NoButton, PlatformEvent::MouseMoved, 0, shiftKey, ctrlKey, altKey, metaKey, currentTime()); 2876 mouseMoved(fakeMouseMoveEvent); 2877 } 2878 2879 void EventHandler::cancelFakeMouseMoveEvent() 2880 { 2881 m_fakeMouseMoveEventTimer.stop(); 2882 } 2883 2884 bool EventHandler::isCursorVisible() const 2885 { 2886 return m_frame->page()->isCursorVisible(); 2887 } 2888 2889 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet) 2890 { 2891 m_frameSetBeingResized = frameSet; 2892 } 2893 2894 void EventHandler::resizeLayerDestroyed() 2895 { 2896 ASSERT(m_resizeLayer); 2897 m_resizeLayer = 0; 2898 } 2899 2900 void EventHandler::hoverTimerFired(Timer<EventHandler>*) 2901 { 2902 m_hoverTimer.stop(); 2903 2904 ASSERT(m_frame); 2905 ASSERT(m_frame->document()); 2906 2907 if (RenderView* renderer = m_frame->contentRenderer()) { 2908 if (FrameView* view = m_frame->view()) { 2909 HitTestRequest request(HitTestRequest::Move | HitTestRequest::DisallowShadowContent); 2910 HitTestResult result(view->windowToContents(m_lastKnownMousePosition)); 2911 renderer->hitTest(request, result); 2912 m_frame->document()->updateHoverActiveState(request, result.innerElement()); 2913 } 2914 } 2915 } 2916 2917 bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt) 2918 { 2919 // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do. 2920 // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and 2921 // lower case variants are present in a document, the correct element is matched based on Shift key state. 2922 // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively. 2923 ASSERT(!(accessKeyModifiers() & PlatformEvent::ShiftKey)); 2924 if ((evt.modifiers() & ~PlatformEvent::ShiftKey) != accessKeyModifiers()) 2925 return false; 2926 String key = evt.unmodifiedText(); 2927 Element* elem = m_frame->document()->getElementByAccessKey(key.lower()); 2928 if (!elem) 2929 return false; 2930 elem->accessKeyAction(false); 2931 return true; 2932 } 2933 2934 bool EventHandler::isKeyEventAllowedInFullScreen(FullscreenElementStack* fullscreen, const PlatformKeyboardEvent& keyEvent) const 2935 { 2936 if (fullscreen->webkitFullScreenKeyboardInputAllowed()) 2937 return true; 2938 2939 if (keyEvent.type() == PlatformKeyboardEvent::Char) { 2940 if (keyEvent.text().length() != 1) 2941 return false; 2942 UChar character = keyEvent.text()[0]; 2943 return character == ' '; 2944 } 2945 2946 int keyCode = keyEvent.windowsVirtualKeyCode(); 2947 return (keyCode >= VK_BACK && keyCode <= VK_CAPITAL) 2948 || (keyCode >= VK_SPACE && keyCode <= VK_DELETE) 2949 || (keyCode >= VK_OEM_1 && keyCode <= VK_OEM_PLUS) 2950 || (keyCode >= VK_MULTIPLY && keyCode <= VK_OEM_8); 2951 } 2952 2953 bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) 2954 { 2955 RefPtr<FrameView> protector(m_frame->view()); 2956 2957 if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(m_frame->document())) { 2958 if (fullscreen->webkitIsFullScreen() && !isKeyEventAllowedInFullScreen(fullscreen, initialKeyEvent)) 2959 return false; 2960 } 2961 2962 if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL) 2963 capsLockStateMayHaveChanged(); 2964 2965 #if OS(WINDOWS) 2966 if (panScrollInProgress()) { 2967 // If a key is pressed while the panScroll is in progress then we want to stop 2968 if (initialKeyEvent.type() == PlatformEvent::KeyDown || initialKeyEvent.type() == PlatformEvent::RawKeyDown) 2969 stopAutoscrollTimer(); 2970 2971 // If we were in panscroll mode, we swallow the key event 2972 return true; 2973 } 2974 #endif 2975 2976 // Check for cases where we are too early for events -- possible unmatched key up 2977 // from pressing return in the location bar. 2978 RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document()); 2979 if (!node) 2980 return false; 2981 2982 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 2983 UserTypingGestureIndicator typingGestureIndicator(m_frame); 2984 2985 if (FrameView* view = m_frame->view()) 2986 view->resetDeferredRepaintDelay(); 2987 2988 // FIXME (bug 68185): this call should be made at another abstraction layer 2989 m_frame->loader()->resetMultipleFormSubmissionProtection(); 2990 2991 // In IE, access keys are special, they are handled after default keydown processing, but cannot be canceled - this is hard to match. 2992 // On Mac OS X, we process them before dispatching keydown, as the default keydown handler implements Emacs key bindings, which may conflict 2993 // with access keys. Then we dispatch keydown, but suppress its default handling. 2994 // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatching a keypress event for WM_SYSCHAR messages. 2995 // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events. 2996 bool matchedAnAccessKey = false; 2997 if (initialKeyEvent.type() == PlatformEvent::KeyDown) 2998 matchedAnAccessKey = handleAccessKey(initialKeyEvent); 2999 3000 // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch. 3001 if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char) 3002 return !node->dispatchKeyEvent(initialKeyEvent); 3003 3004 PlatformKeyboardEvent keyDownEvent = initialKeyEvent; 3005 if (keyDownEvent.type() != PlatformEvent::RawKeyDown) 3006 keyDownEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown); 3007 RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defaultView()); 3008 if (matchedAnAccessKey) 3009 keydown->setDefaultPrevented(true); 3010 keydown->setTarget(node); 3011 3012 if (initialKeyEvent.type() == PlatformEvent::RawKeyDown) { 3013 node->dispatchEvent(keydown, IGNORE_EXCEPTION); 3014 // If frame changed as a result of keydown dispatch, then return true to avoid sending a subsequent keypress message to the new frame. 3015 bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame(); 3016 return keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; 3017 } 3018 3019 node->dispatchEvent(keydown, IGNORE_EXCEPTION); 3020 // If frame changed as a result of keydown dispatch, then return early to avoid sending a subsequent keypress message to the new frame. 3021 bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->focusController().focusedOrMainFrame(); 3022 bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented() || changedFocusedFrame; 3023 if (keydownResult) 3024 return keydownResult; 3025 3026 // Focus may have changed during keydown handling, so refetch node. 3027 // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node. 3028 node = eventTargetNodeForDocument(m_frame->document()); 3029 if (!node) 3030 return false; 3031 3032 PlatformKeyboardEvent keyPressEvent = initialKeyEvent; 3033 keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char); 3034 if (keyPressEvent.text().isEmpty()) 3035 return keydownResult; 3036 RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_frame->document()->defaultView()); 3037 keypress->setTarget(node); 3038 if (keydownResult) 3039 keypress->setDefaultPrevented(true); 3040 node->dispatchEvent(keypress, IGNORE_EXCEPTION); 3041 3042 return keydownResult || keypress->defaultPrevented() || keypress->defaultHandled(); 3043 } 3044 3045 static FocusDirection focusDirectionForKey(const AtomicString& keyIdentifier) 3046 { 3047 DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down", AtomicString::ConstructFromLiteral)); 3048 DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up", AtomicString::ConstructFromLiteral)); 3049 DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left", AtomicString::ConstructFromLiteral)); 3050 DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right", AtomicString::ConstructFromLiteral)); 3051 3052 FocusDirection retVal = FocusDirectionNone; 3053 3054 if (keyIdentifier == Down) 3055 retVal = FocusDirectionDown; 3056 else if (keyIdentifier == Up) 3057 retVal = FocusDirectionUp; 3058 else if (keyIdentifier == Left) 3059 retVal = FocusDirectionLeft; 3060 else if (keyIdentifier == Right) 3061 retVal = FocusDirectionRight; 3062 3063 return retVal; 3064 } 3065 3066 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) 3067 { 3068 if (event->type() == eventNames().keydownEvent) { 3069 m_frame->editor()->handleKeyboardEvent(event); 3070 if (event->defaultHandled()) 3071 return; 3072 if (event->keyIdentifier() == "U+0009") 3073 defaultTabEventHandler(event); 3074 else if (event->keyIdentifier() == "U+0008") 3075 defaultBackspaceEventHandler(event); 3076 else { 3077 FocusDirection direction = focusDirectionForKey(event->keyIdentifier()); 3078 if (direction != FocusDirectionNone) 3079 defaultArrowEventHandler(direction, event); 3080 } 3081 } 3082 if (event->type() == eventNames().keypressEvent) { 3083 m_frame->editor()->handleKeyboardEvent(event); 3084 if (event->defaultHandled()) 3085 return; 3086 if (event->charCode() == ' ') 3087 defaultSpaceEventHandler(event); 3088 } 3089 } 3090 3091 bool EventHandler::dragHysteresisExceeded(const IntPoint& floatDragViewportLocation) const 3092 { 3093 FloatPoint dragViewportLocation(floatDragViewportLocation.x(), floatDragViewportLocation.y()); 3094 return dragHysteresisExceeded(dragViewportLocation); 3095 } 3096 3097 bool EventHandler::dragHysteresisExceeded(const FloatPoint& dragViewportLocation) const 3098 { 3099 FrameView* view = m_frame->view(); 3100 if (!view) 3101 return false; 3102 IntPoint dragLocation = view->windowToContents(flooredIntPoint(dragViewportLocation)); 3103 IntSize delta = dragLocation - m_mouseDownPos; 3104 3105 int threshold = GeneralDragHysteresis; 3106 switch (dragState().m_dragType) { 3107 case DragSourceActionSelection: 3108 threshold = TextDragHysteresis; 3109 break; 3110 case DragSourceActionImage: 3111 threshold = ImageDragHysteresis; 3112 break; 3113 case DragSourceActionLink: 3114 threshold = LinkDragHysteresis; 3115 break; 3116 case DragSourceActionDHTML: 3117 break; 3118 case DragSourceActionNone: 3119 ASSERT_NOT_REACHED(); 3120 } 3121 3122 return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold; 3123 } 3124 3125 void EventHandler::freeClipboard() 3126 { 3127 if (dragState().m_dragClipboard) 3128 dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb); 3129 } 3130 3131 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation) 3132 { 3133 // Send a hit test request so that RenderLayer gets a chance to update the :hover and :active pseudoclasses. 3134 HitTestRequest request(HitTestRequest::Release | HitTestRequest::DisallowShadowContent); 3135 prepareMouseEvent(request, event); 3136 3137 if (dragState().m_dragSrc) { 3138 dragState().m_dragClipboard->setDestinationOperation(operation); 3139 // for now we don't care if event handler cancels default behavior, since there is none 3140 dispatchDragSrcEvent(eventNames().dragendEvent, event); 3141 } 3142 freeClipboard(); 3143 dragState().m_dragSrc = 0; 3144 // In case the drag was ended due to an escape key press we need to ensure 3145 // that consecutive mousemove events don't reinitiate the drag and drop. 3146 m_mouseDownMayStartDrag = false; 3147 } 3148 3149 void EventHandler::updateDragStateAfterEditDragIfNeeded(Element* rootEditableElement) 3150 { 3151 // If inserting the dragged contents removed the drag source, we still want to fire dragend at the root editble element. 3152 if (dragState().m_dragSrc && !dragState().m_dragSrc->inDocument()) 3153 dragState().m_dragSrc = rootEditableElement; 3154 } 3155 3156 // returns if we should continue "default processing", i.e., whether eventhandler canceled 3157 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event) 3158 { 3159 return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dragState().m_dragClipboard.get()); 3160 } 3161 3162 static bool exactlyOneBitSet(DragSourceAction n) 3163 { 3164 return n && !(n & (n - 1)); 3165 } 3166 3167 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDragHysteresis checkDragHysteresis) 3168 { 3169 // Callers must protect the reference to FrameView, since this function may dispatch DOM 3170 // events, causing Frame/FrameView to go away. 3171 ASSERT(m_frame); 3172 ASSERT(m_frame->view()); 3173 if (!m_frame->page()) 3174 return false; 3175 3176 if (event.event().button() != LeftButton || event.event().type() != PlatformEvent::MouseMoved) { 3177 // If we allowed the other side of the bridge to handle a drag 3178 // last time, then m_mousePressed might still be set. So we 3179 // clear it now to make sure the next move after a drag 3180 // doesn't look like a drag. 3181 m_mousePressed = false; 3182 return false; 3183 } 3184 3185 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) { 3186 // try to find an element that wants to be dragged 3187 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::DisallowShadowContent); 3188 HitTestResult result(m_mouseDownPos); 3189 m_frame->contentRenderer()->hitTest(request, result); 3190 Node* node = result.innerNode(); 3191 if (node) 3192 dragState().m_dragSrc = m_frame->page()->dragController().draggableNode(m_frame, node, m_mouseDownPos, dragState()); 3193 else 3194 dragState().m_dragSrc = 0; 3195 3196 if (!dragState().m_dragSrc) 3197 m_mouseDownMayStartDrag = false; // no element is draggable 3198 else 3199 m_dragMayStartSelectionInstead = (dragState().m_dragType & DragSourceActionSelection); 3200 } 3201 3202 // For drags starting in the selection, the user must wait between the mousedown and mousedrag, 3203 // or else we bail on the dragging stuff and allow selection to occur 3204 if (m_mouseDownMayStartDrag && m_dragMayStartSelectionInstead && (dragState().m_dragType & DragSourceActionSelection) && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) { 3205 ASSERT(event.event().type() == PlatformEvent::MouseMoved); 3206 if ((dragState().m_dragType & DragSourceActionImage)) { 3207 // ... unless the mouse is over an image, then we start dragging just the image 3208 dragState().m_dragType = DragSourceActionImage; 3209 } else if (!(dragState().m_dragType & (DragSourceActionDHTML | DragSourceActionLink))) { 3210 // ... but only bail if we're not over an unselectable element. 3211 m_mouseDownMayStartDrag = false; 3212 dragState().m_dragSrc = 0; 3213 } else { 3214 // Prevent the following case from occuring: 3215 // 1. User starts a drag immediately after mouse down over an unselectable element. 3216 // 2. We enter this block and decided that since we're over an unselectable element, 3217 // don't cancel the drag. 3218 // 3. The drag gets resolved as a potential selection drag below /but/ we haven't 3219 // exceeded the drag hysteresis yet. 3220 // 4. We enter this block again, and since it's now marked as a selection drag, we 3221 // cancel the drag. 3222 m_dragMayStartSelectionInstead = false; 3223 } 3224 } 3225 3226 if (!m_mouseDownMayStartDrag) 3227 return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; 3228 3229 if (!exactlyOneBitSet(dragState().m_dragType)) { 3230 ASSERT((dragState().m_dragType & DragSourceActionSelection)); 3231 ASSERT((dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionDHTML 3232 || (dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionImage 3233 || (dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionLink); 3234 dragState().m_dragType = DragSourceActionSelection; 3235 } 3236 3237 // We are starting a text/image/url drag, so the cursor should be an arrow 3238 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and drop (default to pointer). 3239 m_frame->view()->setCursor(pointerCursor()); 3240 3241 if (checkDragHysteresis == ShouldCheckDragHysteresis && !dragHysteresisExceeded(event.event().position())) 3242 return true; 3243 3244 // Once we're past the hysteresis point, we don't want to treat this gesture as a click 3245 invalidateClick(); 3246 3247 if (!tryStartDrag(event)) { 3248 // Something failed to start the drag, clean up. 3249 freeClipboard(); 3250 dragState().m_dragSrc = 0; 3251 } 3252 3253 m_mouseDownMayStartDrag = false; 3254 // Whether or not the drag actually started, no more default handling (like selection). 3255 return true; 3256 } 3257 3258 bool EventHandler::tryStartDrag(const MouseEventWithHitTestResults& event) 3259 { 3260 freeClipboard(); // would only happen if we missed a dragEnd. Do it anyway, just 3261 // to make sure it gets numbified 3262 dragState().m_dragClipboard = createDraggingClipboard(); 3263 3264 // Check to see if this a DOM based drag, if it is get the DOM specified drag 3265 // image and offset 3266 if (dragState().m_dragType == DragSourceActionDHTML) { 3267 if (RenderObject* renderer = dragState().m_dragSrc->renderer()) { 3268 // FIXME: This doesn't work correctly with transforms. 3269 FloatPoint absPos = renderer->localToAbsolute(); 3270 IntSize delta = m_mouseDownPos - roundedIntPoint(absPos); 3271 dragState().m_dragClipboard->setDragImageElement(dragState().m_dragSrc.get(), IntPoint(delta)); 3272 } else { 3273 // The renderer has disappeared, this can happen if the onStartDrag handler has hidden 3274 // the element in some way. In this case we just kill the drag. 3275 return false; 3276 } 3277 } 3278 3279 DragController& dragController = m_frame->page()->dragController(); 3280 if (!dragController.populateDragClipboard(m_frame, dragState(), m_mouseDownPos)) 3281 return false; 3282 m_mouseDownMayStartDrag = dispatchDragSrcEvent(eventNames().dragstartEvent, m_mouseDown) 3283 && !m_frame->selection()->isInPasswordField(); 3284 3285 // Invalidate clipboard here against anymore pasteboard writing for security. The drag 3286 // image can still be changed as we drag, but not the pasteboard data. 3287 dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable); 3288 3289 if (m_mouseDownMayStartDrag) { 3290 // Yuck, a draggedImage:moveTo: message can be fired as a result of kicking off the 3291 // drag with dragImage! Because of that dumb reentrancy, we may think we've not 3292 // started the drag when that happens. So we have to assume it's started before we 3293 // kick it off. 3294 dragState().m_dragClipboard->setDragHasStarted(); 3295 3296 // Dispatching the event could cause Page to go away. Make sure it's still valid before trying to use DragController. 3297 m_didStartDrag = m_frame->page() && dragController.startDrag(m_frame, dragState(), event.event(), m_mouseDownPos); 3298 // FIXME: This seems pretty useless now. The gesture code uses this as a signal for 3299 // whether or not the drag started, but perhaps it can simply use the return value from 3300 // handleDrag(), even though it doesn't mean exactly the same thing. 3301 if (m_didStartDrag) 3302 return true; 3303 // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event 3304 dispatchDragSrcEvent(eventNames().dragendEvent, event.event()); 3305 } 3306 3307 return false; 3308 } 3309 3310 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEvent, TextEventInputType inputType) 3311 { 3312 // Platforms should differentiate real commands like selectAll from text input in disguise (like insertNewline), 3313 // and avoid dispatching text input events from keydown default handlers. 3314 ASSERT(!underlyingEvent || !underlyingEvent->isKeyboardEvent() || toKeyboardEvent(underlyingEvent)->type() == eventNames().keypressEvent); 3315 3316 if (!m_frame) 3317 return false; 3318 3319 EventTarget* target; 3320 if (underlyingEvent) 3321 target = underlyingEvent->target(); 3322 else 3323 target = eventTargetNodeForDocument(m_frame->document()); 3324 if (!target) 3325 return false; 3326 3327 if (FrameView* view = m_frame->view()) 3328 view->resetDeferredRepaintDelay(); 3329 3330 RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text, inputType); 3331 event->setUnderlyingEvent(underlyingEvent); 3332 3333 target->dispatchEvent(event, IGNORE_EXCEPTION); 3334 return event->defaultHandled(); 3335 } 3336 3337 bool EventHandler::isKeyboardOptionTab(KeyboardEvent* event) 3338 { 3339 return event 3340 && (event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent) 3341 && event->altKey() 3342 && event->keyIdentifier() == "U+0009"; 3343 } 3344 3345 void EventHandler::defaultTextInputEventHandler(TextEvent* event) 3346 { 3347 if (m_frame->editor()->handleTextEvent(event)) 3348 event->setDefaultHandled(); 3349 } 3350 3351 void EventHandler::defaultSpaceEventHandler(KeyboardEvent* event) 3352 { 3353 ASSERT(event->type() == eventNames().keypressEvent); 3354 3355 if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey()) 3356 return; 3357 3358 ScrollLogicalDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward; 3359 if (logicalScrollOverflow(direction, ScrollByPage)) { 3360 event->setDefaultHandled(); 3361 return; 3362 } 3363 3364 FrameView* view = m_frame->view(); 3365 if (!view) 3366 return; 3367 3368 if (view->logicalScroll(direction, ScrollByPage)) 3369 event->setDefaultHandled(); 3370 } 3371 3372 void EventHandler::defaultBackspaceEventHandler(KeyboardEvent* event) 3373 { 3374 ASSERT(event->type() == eventNames().keydownEvent); 3375 3376 if (event->ctrlKey() || event->metaKey() || event->altKey() || event->altGraphKey()) 3377 return; 3378 3379 if (!m_frame->editor()->behavior().shouldNavigateBackOnBackspace()) 3380 return; 3381 3382 Page* page = m_frame->page(); 3383 if (!page) 3384 return; 3385 3386 bool handledEvent = false; 3387 3388 if (event->shiftKey()) 3389 handledEvent = page->backForward()->goForward(); 3390 else 3391 handledEvent = page->backForward()->goBack(); 3392 3393 if (handledEvent) 3394 event->setDefaultHandled(); 3395 } 3396 3397 3398 void EventHandler::defaultArrowEventHandler(FocusDirection focusDirection, KeyboardEvent* event) 3399 { 3400 ASSERT(event->type() == eventNames().keydownEvent); 3401 3402 if (event->ctrlKey() || event->metaKey() || event->altGraphKey() || event->shiftKey()) 3403 return; 3404 3405 Page* page = m_frame->page(); 3406 if (!page) 3407 return; 3408 3409 if (!isSpatialNavigationEnabled(m_frame)) 3410 return; 3411 3412 // Arrows and other possible directional navigation keys can be used in design 3413 // mode editing. 3414 if (m_frame->document()->inDesignMode()) 3415 return; 3416 3417 if (page->focusController().advanceFocus(focusDirection)) 3418 event->setDefaultHandled(); 3419 } 3420 3421 void EventHandler::defaultTabEventHandler(KeyboardEvent* event) 3422 { 3423 ASSERT(event->type() == eventNames().keydownEvent); 3424 3425 // We should only advance focus on tabs if no special modifier keys are held down. 3426 if (event->ctrlKey() || event->metaKey() || event->altGraphKey()) 3427 return; 3428 3429 Page* page = m_frame->page(); 3430 if (!page) 3431 return; 3432 if (!page->tabKeyCyclesThroughElements()) 3433 return; 3434 3435 FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward; 3436 3437 // Tabs can be used in design mode editing. 3438 if (m_frame->document()->inDesignMode()) 3439 return; 3440 3441 if (page->focusController().advanceFocus(focusDirection)) 3442 event->setDefaultHandled(); 3443 } 3444 3445 void EventHandler::capsLockStateMayHaveChanged() 3446 { 3447 if (Element* element = m_frame->document()->focusedElement()) { 3448 if (RenderObject* r = element->renderer()) { 3449 if (r->isTextField()) 3450 toRenderTextControlSingleLine(r)->capsLockStateMayHaveChanged(); 3451 } 3452 } 3453 } 3454 3455 void EventHandler::sendResizeEvent() 3456 { 3457 m_frame->document()->enqueueWindowEvent(Event::create(eventNames().resizeEvent, false, false)); 3458 } 3459 3460 void EventHandler::sendScrollEvent() 3461 { 3462 setFrameWasScrolledByUser(); 3463 if (m_frame->view() && m_frame->document()) 3464 m_frame->document()->eventQueue()->enqueueOrDispatchScrollEvent(m_frame->document(), DocumentEventQueue::ScrollEventDocumentTarget); 3465 } 3466 3467 void EventHandler::setFrameWasScrolledByUser() 3468 { 3469 FrameView* v = m_frame->view(); 3470 if (v) 3471 v->setWasScrolledByUser(true); 3472 } 3473 3474 bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar) 3475 { 3476 if (!scrollbar || !scrollbar->enabled()) 3477 return false; 3478 setFrameWasScrolledByUser(); 3479 scrollbar->mouseDown(mev.event()); 3480 return true; 3481 } 3482 3483 // If scrollbar (under mouse) is different from last, send a mouse exited. Set 3484 // last to scrollbar if setLast is true; else set last to 0. 3485 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setLast) 3486 { 3487 if (m_lastScrollbarUnderMouse != scrollbar) { 3488 // Send mouse exited to the old scrollbar. 3489 if (m_lastScrollbarUnderMouse) 3490 m_lastScrollbarUnderMouse->mouseExited(); 3491 3492 // Send mouse entered if we're setting a new scrollbar. 3493 if (scrollbar && setLast) 3494 scrollbar->mouseEntered(); 3495 3496 m_lastScrollbarUnderMouse = setLast ? scrollbar : 0; 3497 } 3498 } 3499 3500 static const AtomicString& eventNameForTouchPointState(PlatformTouchPoint::State state) 3501 { 3502 switch (state) { 3503 case PlatformTouchPoint::TouchReleased: 3504 return eventNames().touchendEvent; 3505 case PlatformTouchPoint::TouchCancelled: 3506 return eventNames().touchcancelEvent; 3507 case PlatformTouchPoint::TouchPressed: 3508 return eventNames().touchstartEvent; 3509 case PlatformTouchPoint::TouchMoved: 3510 return eventNames().touchmoveEvent; 3511 case PlatformTouchPoint::TouchStationary: 3512 // TouchStationary state is not converted to touch events, so fall through to assert. 3513 default: 3514 ASSERT_NOT_REACHED(); 3515 return emptyAtom; 3516 } 3517 } 3518 3519 HitTestResult EventHandler::hitTestResultInFrame(Frame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType) 3520 { 3521 HitTestResult result(point); 3522 3523 if (!frame || !frame->contentRenderer()) 3524 return result; 3525 if (frame->view()) { 3526 IntRect rect = frame->view()->visibleContentRect(); 3527 if (!rect.contains(roundedIntPoint(point))) 3528 return result; 3529 } 3530 frame->contentRenderer()->hitTest(HitTestRequest(hitType), result); 3531 return result; 3532 } 3533 3534 bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event) 3535 { 3536 // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes 3537 // in the JS event. See http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/ 3538 // for an overview of how these lists fit together. 3539 3540 // Holds the complete set of touches on the screen and will be used as the 'touches' list in the JS event. 3541 RefPtr<TouchList> touches = TouchList::create(); 3542 3543 // A different view on the 'touches' list above, filtered and grouped by event target. Used for the 3544 // 'targetTouches' list in the JS event. 3545 typedef HashMap<EventTarget*, RefPtr<TouchList> > TargetTouchesMap; 3546 TargetTouchesMap touchesByTarget; 3547 3548 // Array of touches per state, used to assemble the 'changedTouches' list in the JS event. 3549 typedef HashSet<RefPtr<EventTarget> > EventTargetSet; 3550 struct { 3551 // The touches corresponding to the particular change state this struct instance represents. 3552 RefPtr<TouchList> m_touches; 3553 // Set of targets involved in m_touches. 3554 EventTargetSet m_targets; 3555 } changedTouches[PlatformTouchPoint::TouchStateEnd]; 3556 3557 const Vector<PlatformTouchPoint>& points = event.touchPoints(); 3558 3559 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 3560 3561 unsigned i; 3562 bool freshTouchEvents = true; 3563 bool allTouchReleased = true; 3564 for (i = 0; i < points.size(); ++i) { 3565 const PlatformTouchPoint& point = points[i]; 3566 if (point.state() != PlatformTouchPoint::TouchPressed) 3567 freshTouchEvents = false; 3568 if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled) 3569 allTouchReleased = false; 3570 } 3571 3572 for (i = 0; i < points.size(); ++i) { 3573 const PlatformTouchPoint& point = points[i]; 3574 PlatformTouchPoint::State pointState = point.state(); 3575 LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos()); 3576 3577 HitTestRequest::HitTestRequestType hitType = HitTestRequest::TouchEvent; 3578 // The HitTestRequest types used for mouse events map quite adequately 3579 // to touch events. Note that in addition to meaning that the hit test 3580 // should affect the active state of the current node if necessary, 3581 // HitTestRequest::Active signifies that the hit test is taking place 3582 // with the mouse (or finger in this case) being pressed. 3583 switch (pointState) { 3584 case PlatformTouchPoint::TouchPressed: 3585 hitType |= HitTestRequest::Active; 3586 break; 3587 case PlatformTouchPoint::TouchMoved: 3588 hitType |= HitTestRequest::Active | HitTestRequest::Move | HitTestRequest::ReadOnly; 3589 break; 3590 case PlatformTouchPoint::TouchReleased: 3591 case PlatformTouchPoint::TouchCancelled: 3592 hitType |= HitTestRequest::Release; 3593 break; 3594 case PlatformTouchPoint::TouchStationary: 3595 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; 3596 break; 3597 default: 3598 ASSERT_NOT_REACHED(); 3599 break; 3600 } 3601 3602 if (shouldGesturesTriggerActive()) 3603 hitType |= HitTestRequest::ReadOnly; 3604 3605 // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. 3606 unsigned touchPointTargetKey = point.id() + 1; 3607 RefPtr<EventTarget> touchTarget; 3608 if (pointState == PlatformTouchPoint::TouchPressed) { 3609 HitTestResult result; 3610 if (freshTouchEvents) { 3611 result = hitTestResultAtPoint(pagePoint, hitType); 3612 m_originatingTouchPointTargetKey = touchPointTargetKey; 3613 } else if (m_originatingTouchPointDocument.get() && m_originatingTouchPointDocument->frame()) { 3614 LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(m_originatingTouchPointDocument->frame(), point.pos()); 3615 result = hitTestResultInFrame(m_originatingTouchPointDocument->frame(), pagePointInOriginatingDocument, hitType); 3616 } else 3617 continue; 3618 3619 Node* node = result.innerNode(); 3620 if (!node) 3621 continue; 3622 3623 // Touch events should not go to text nodes 3624 if (node->isTextNode()) 3625 node = EventPathWalker::parent(node); 3626 3627 Document* doc = node->document(); 3628 // Record the originating touch document even if it does not have a touch listener. 3629 if (freshTouchEvents) { 3630 m_originatingTouchPointDocument = doc; 3631 freshTouchEvents = false; 3632 } 3633 if (!doc) 3634 continue; 3635 if (!doc->hasTouchEventHandlers()) 3636 continue; 3637 m_originatingTouchPointTargets.set(touchPointTargetKey, node); 3638 touchTarget = node; 3639 } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) { 3640 // We only perform a hittest on release or cancel to unset :active or :hover state. 3641 if (touchPointTargetKey == m_originatingTouchPointTargetKey) { 3642 hitTestResultAtPoint(pagePoint, hitType); 3643 m_originatingTouchPointTargetKey = 0; 3644 } else if (m_originatingTouchPointDocument.get() && m_originatingTouchPointDocument->frame()) { 3645 LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(m_originatingTouchPointDocument->frame(), point.pos()); 3646 hitTestResultInFrame(m_originatingTouchPointDocument->frame(), pagePointInOriginatingDocument, hitType); 3647 } 3648 // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel 3649 // we also remove it from the map. 3650 touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); 3651 } else 3652 // No hittest is performed on move or stationary, since the target is not allowed to change anyway. 3653 touchTarget = m_originatingTouchPointTargets.get(touchPointTargetKey); 3654 3655 if (!touchTarget.get()) 3656 continue; 3657 Document* doc = touchTarget->toNode()->document(); 3658 if (!doc) 3659 continue; 3660 if (!doc->hasTouchEventHandlers()) 3661 continue; 3662 Frame* targetFrame = doc->frame(); 3663 if (!targetFrame) 3664 continue; 3665 3666 if (m_frame != targetFrame) { 3667 // pagePoint should always be relative to the target elements containing frame. 3668 pagePoint = documentPointForWindowPoint(targetFrame, point.pos()); 3669 } 3670 3671 float scaleFactor = targetFrame->pageZoomFactor(); 3672 3673 int adjustedPageX = lroundf(pagePoint.x() / scaleFactor); 3674 int adjustedPageY = lroundf(pagePoint.y() / scaleFactor); 3675 3676 RefPtr<Touch> touch = Touch::create(targetFrame, touchTarget.get(), point.id(), 3677 point.screenPos().x(), point.screenPos().y(), 3678 adjustedPageX, adjustedPageY, 3679 point.radiusX(), point.radiusY(), point.rotationAngle(), point.force()); 3680 3681 // Ensure this target's touch list exists, even if it ends up empty, so it can always be passed to TouchEvent::Create below. 3682 TargetTouchesMap::iterator targetTouchesIterator = touchesByTarget.find(touchTarget.get()); 3683 if (targetTouchesIterator == touchesByTarget.end()) 3684 targetTouchesIterator = touchesByTarget.set(touchTarget.get(), TouchList::create()).iterator; 3685 3686 // touches and targetTouches should only contain information about touches still on the screen, so if this point is 3687 // released or cancelled it will only appear in the changedTouches list. 3688 if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) { 3689 touches->append(touch); 3690 targetTouchesIterator->value->append(touch); 3691 } 3692 3693 // Now build up the correct list for changedTouches. 3694 // Note that any touches that are in the TouchStationary state (e.g. if 3695 // the user had several points touched but did not move them all) should 3696 // never be in the changedTouches list so we do not handle them explicitly here. 3697 // See https://bugs.webkit.org/show_bug.cgi?id=37609 for further discussion 3698 // about the TouchStationary state. 3699 if (pointState != PlatformTouchPoint::TouchStationary) { 3700 ASSERT(pointState < PlatformTouchPoint::TouchStateEnd); 3701 if (!changedTouches[pointState].m_touches) 3702 changedTouches[pointState].m_touches = TouchList::create(); 3703 changedTouches[pointState].m_touches->append(touch); 3704 changedTouches[pointState].m_targets.add(touchTarget); 3705 } 3706 } 3707 m_touchPressed = touches->length() > 0; 3708 if (allTouchReleased) 3709 m_originatingTouchPointDocument.clear(); 3710 3711 // Now iterate the changedTouches list and m_targets within it, sending events to the targets as required. 3712 bool swallowedEvent = false; 3713 RefPtr<TouchList> emptyList = TouchList::create(); 3714 for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) { 3715 if (!changedTouches[state].m_touches) 3716 continue; 3717 3718 // When sending a touch cancel event, use empty touches and targetTouches lists. 3719 bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled); 3720 RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches); 3721 const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state))); 3722 const EventTargetSet& targetsForState = changedTouches[state].m_targets; 3723 3724 for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) { 3725 EventTarget* touchEventTarget = it->get(); 3726 RefPtr<TouchList> targetTouches(isTouchCancelEvent ? emptyList : touchesByTarget.get(touchEventTarget)); 3727 ASSERT(targetTouches); 3728 3729 RefPtr<TouchEvent> touchEvent = 3730 TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(), 3731 stateName, touchEventTarget->toNode()->document()->defaultView(), 3732 0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey()); 3733 touchEventTarget->toNode()->dispatchTouchEvent(touchEvent.get()); 3734 swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled(); 3735 } 3736 } 3737 3738 return swallowedEvent; 3739 } 3740 3741 bool EventHandler::dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent& event) 3742 { 3743 if (!m_frame || !m_frame->settings() || !m_frame->settings()->isTouchEventEmulationEnabled()) 3744 return false; 3745 3746 PlatformEvent::Type eventType = event.type(); 3747 if (eventType != PlatformEvent::MouseMoved && eventType != PlatformEvent::MousePressed && eventType != PlatformEvent::MouseReleased) 3748 return false; 3749 3750 HitTestRequest request(HitTestRequest::Active | HitTestRequest::DisallowShadowContent); 3751 MouseEventWithHitTestResults mev = prepareMouseEvent(request, event); 3752 if (mev.scrollbar() || subframeForHitTestResult(mev)) 3753 return false; 3754 3755 // The order is important. This check should follow the subframe test: http://webkit.org/b/111292. 3756 if (eventType == PlatformEvent::MouseMoved && !m_touchPressed) 3757 return true; 3758 3759 SyntheticSingleTouchEvent touchEvent(event); 3760 return handleTouchEvent(touchEvent); 3761 } 3762 3763 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) 3764 { 3765 m_mousePositionIsUnknown = false; 3766 m_lastKnownMousePosition = event.position(); 3767 m_lastKnownMouseGlobalPosition = event.globalPosition(); 3768 } 3769 3770 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) 3771 { 3772 // If we're clicking into a frame that is selected, the frame will appear 3773 // greyed out even though we're clicking on the selection. This looks 3774 // really strange (having the whole frame be greyed out), so we deselect the 3775 // selection. 3776 IntPoint p = m_frame->view()->windowToContents(mev.event().position()); 3777 if (m_frame->selection()->contains(p)) { 3778 VisiblePosition visiblePos( 3779 mev.targetNode()->renderer()->positionForPoint(mev.localPoint())); 3780 VisibleSelection newSelection(visiblePos); 3781 if (m_frame->selection()->shouldChangeSelection(newSelection)) 3782 m_frame->selection()->setSelection(newSelection); 3783 } 3784 3785 subframe->eventHandler()->handleMousePressEvent(mev.event()); 3786 return true; 3787 } 3788 3789 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe, HitTestResult* hoveredNode) 3790 { 3791 if (m_mouseDownMayStartDrag && !m_mouseDownWasInSubframe) 3792 return false; 3793 subframe->eventHandler()->handleMouseMoveEvent(mev.event(), hoveredNode); 3794 return true; 3795 } 3796 3797 bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) 3798 { 3799 subframe->eventHandler()->handleMouseReleaseEvent(mev.event()); 3800 return true; 3801 } 3802 3803 bool EventHandler::passWheelEventToWidget(const PlatformWheelEvent& wheelEvent, Widget* widget) 3804 { 3805 // We can sometimes get a null widget! EventHandlerMac handles a null 3806 // widget by returning false, so we do the same. 3807 if (!widget) 3808 return false; 3809 3810 // If not a FrameView, then probably a plugin widget. Those will receive 3811 // the event via an EventTargetNode dispatch when this returns false. 3812 if (!widget->isFrameView()) 3813 return false; 3814 3815 return toFrameView(widget)->frame()->eventHandler()->handleWheelEvent(wheelEvent); 3816 } 3817 3818 bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event) 3819 { 3820 // Figure out which view to send the event to. 3821 if (!event.targetNode() || !event.targetNode()->renderer() || !event.targetNode()->renderer()->isWidget()) 3822 return false; 3823 return false; 3824 } 3825 3826 PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const 3827 { 3828 RefPtr<ChromiumDataObject> dataObject = ChromiumDataObject::create(); 3829 return ClipboardChromium::create(Clipboard::DragAndDrop, dataObject.get(), ClipboardWritable, m_frame); 3830 } 3831 3832 void EventHandler::focusDocumentView() 3833 { 3834 Page* page = m_frame->page(); 3835 if (!page) 3836 return; 3837 page->focusController().setFocusedFrame(m_frame); 3838 } 3839 3840 unsigned EventHandler::accessKeyModifiers() 3841 { 3842 #if OS(DARWIN) 3843 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; 3844 #else 3845 return PlatformEvent::AltKey; 3846 #endif 3847 } 3848 3849 } // namespace WebCore 3850