Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. |
| 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 #include "config.h" | 28 #include "config.h" |
| 29 #include "core/input/EventHandler.h" | 29 #include "core/input/EventHandler.h" |
| 30 | 30 |
| 31 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 31 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| 32 #include "core/HTMLNames.h" | 32 #include "core/HTMLNames.h" |
| 33 #include "core/InputTypeNames.h" | 33 #include "core/InputTypeNames.h" |
| 34 #include "core/clipboard/DataObject.h" | 34 #include "core/clipboard/DataObject.h" |
| 35 #include "core/clipboard/DataTransfer.h" | 35 #include "core/clipboard/DataTransfer.h" |
| 36 #include "core/dom/Document.h" | 36 #include "core/dom/Document.h" |
| 37 #include "core/dom/DocumentMarkerController.h" | |
| 38 #include "core/dom/TouchList.h" | 37 #include "core/dom/TouchList.h" |
| 39 #include "core/dom/shadow/ComposedTreeTraversal.h" | 38 #include "core/dom/shadow/ComposedTreeTraversal.h" |
| 40 #include "core/dom/shadow/ShadowRoot.h" | 39 #include "core/dom/shadow/ShadowRoot.h" |
| 41 #include "core/editing/Editor.h" | 40 #include "core/editing/Editor.h" |
| 42 #include "core/editing/FrameSelection.h" | 41 #include "core/editing/FrameSelection.h" |
| 43 #include "core/editing/htmlediting.h" | 42 #include "core/editing/SelectionController.h" |
| 44 #include "core/editing/iterators/TextIterator.h" | |
| 45 #include "core/events/EventPath.h" | 43 #include "core/events/EventPath.h" |
| 46 #include "core/events/KeyboardEvent.h" | 44 #include "core/events/KeyboardEvent.h" |
| 47 #include "core/events/MouseEvent.h" | 45 #include "core/events/MouseEvent.h" |
| 48 #include "core/events/TextEvent.h" | 46 #include "core/events/TextEvent.h" |
| 49 #include "core/events/TouchEvent.h" | 47 #include "core/events/TouchEvent.h" |
| 50 #include "core/events/WheelEvent.h" | 48 #include "core/events/WheelEvent.h" |
| 51 #include "core/fetch/ImageResource.h" | 49 #include "core/fetch/ImageResource.h" |
| 52 #include "core/frame/EventHandlerRegistry.h" | 50 #include "core/frame/EventHandlerRegistry.h" |
| 53 #include "core/frame/FrameHost.h" | 51 #include "core/frame/FrameHost.h" |
| 54 #include "core/frame/FrameView.h" | 52 #include "core/frame/FrameView.h" |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 | 210 |
| 213 // FIXME: we should exclude the document in some cases, as part | 211 // FIXME: we should exclude the document in some cases, as part |
| 214 // of crbug.com/410974. | 212 // of crbug.com/410974. |
| 215 scrollChain.prepend(frame.document()->documentElement()); | 213 scrollChain.prepend(frame.document()->documentElement()); |
| 216 } | 214 } |
| 217 | 215 |
| 218 EventHandler::EventHandler(LocalFrame* frame) | 216 EventHandler::EventHandler(LocalFrame* frame) |
| 219 : m_frame(frame) | 217 : m_frame(frame) |
| 220 , m_mousePressed(false) | 218 , m_mousePressed(false) |
| 221 , m_capturesDragging(false) | 219 , m_capturesDragging(false) |
| 222 , m_mouseDownMayStartSelect(false) | |
| 223 , m_mouseDownMayStartDrag(false) | 220 , m_mouseDownMayStartDrag(false) |
| 224 , m_mouseDownWasSingleClickInSelection(false) | 221 , m_selectionController(SelectionController::create(*frame)) |
| 225 , m_selectionInitiationState(HaveNotStartedSelection) | |
| 226 , m_hoverTimer(this, &EventHandler::hoverTimerFired) | 222 , m_hoverTimer(this, &EventHandler::hoverTimerFired) |
| 227 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) | 223 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) |
| 228 , m_mouseDownMayStartAutoscroll(false) | 224 , m_mouseDownMayStartAutoscroll(false) |
| 229 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) | 225 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) |
| 230 , m_svgPan(false) | 226 , m_svgPan(false) |
| 231 , m_resizeScrollableArea(nullptr) | 227 , m_resizeScrollableArea(nullptr) |
| 232 , m_eventHandlerWillResetCapturingMouseEventsNode(0) | 228 , m_eventHandlerWillResetCapturingMouseEventsNode(0) |
| 233 , m_clickCount(0) | 229 , m_clickCount(0) |
| 234 , m_shouldOnlyFireDragOverEvent(false) | 230 , m_shouldOnlyFireDragOverEvent(false) |
| 235 , m_mousePositionIsUnknown(true) | 231 , m_mousePositionIsUnknown(true) |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 265 visitor->trace(m_frameSetBeingResized); | 261 visitor->trace(m_frameSetBeingResized); |
| 266 visitor->trace(m_latchedWheelEventNode); | 262 visitor->trace(m_latchedWheelEventNode); |
| 267 visitor->trace(m_previousWheelScrolledNode); | 263 visitor->trace(m_previousWheelScrolledNode); |
| 268 visitor->trace(m_scrollbarHandlingScrollGesture); | 264 visitor->trace(m_scrollbarHandlingScrollGesture); |
| 269 visitor->trace(m_targetForTouchID); | 265 visitor->trace(m_targetForTouchID); |
| 270 visitor->trace(m_touchSequenceDocument); | 266 visitor->trace(m_touchSequenceDocument); |
| 271 visitor->trace(m_scrollGestureHandlingNode); | 267 visitor->trace(m_scrollGestureHandlingNode); |
| 272 visitor->trace(m_previousGestureScrolledNode); | 268 visitor->trace(m_previousGestureScrolledNode); |
| 273 visitor->trace(m_lastDeferredTapElement); | 269 visitor->trace(m_lastDeferredTapElement); |
| 274 visitor->trace(m_currentScrollChain); | 270 visitor->trace(m_currentScrollChain); |
| 271 visitor->trace(m_selectionController); | |
| 275 #endif | 272 #endif |
| 276 } | 273 } |
| 277 | 274 |
| 278 DragState& EventHandler::dragState() | 275 DragState& EventHandler::dragState() |
| 279 { | 276 { |
| 280 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); | 277 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); |
| 281 return *state; | 278 return *state; |
| 282 } | 279 } |
| 283 | 280 |
| 284 void EventHandler::clear() | 281 void EventHandler::clear() |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 309 m_previousWheelScrolledNode = nullptr; | 306 m_previousWheelScrolledNode = nullptr; |
| 310 m_targetForTouchID.clear(); | 307 m_targetForTouchID.clear(); |
| 311 m_touchSequenceDocument.clear(); | 308 m_touchSequenceDocument.clear(); |
| 312 m_touchSequenceUserGestureToken.clear(); | 309 m_touchSequenceUserGestureToken.clear(); |
| 313 m_scrollGestureHandlingNode = nullptr; | 310 m_scrollGestureHandlingNode = nullptr; |
| 314 m_lastGestureScrollOverWidget = false; | 311 m_lastGestureScrollOverWidget = false; |
| 315 m_previousGestureScrolledNode = nullptr; | 312 m_previousGestureScrolledNode = nullptr; |
| 316 m_scrollbarHandlingScrollGesture = nullptr; | 313 m_scrollbarHandlingScrollGesture = nullptr; |
| 317 m_maxMouseMovedDuration = 0; | 314 m_maxMouseMovedDuration = 0; |
| 318 m_touchPressed = false; | 315 m_touchPressed = false; |
| 319 m_mouseDownMayStartSelect = false; | |
| 320 m_mouseDownMayStartDrag = false; | 316 m_mouseDownMayStartDrag = false; |
| 321 m_lastShowPressTimestamp = 0; | 317 m_lastShowPressTimestamp = 0; |
| 322 m_lastDeferredTapElement = nullptr; | 318 m_lastDeferredTapElement = nullptr; |
| 323 m_eventHandlerWillResetCapturingMouseEventsNode = false; | 319 m_eventHandlerWillResetCapturingMouseEventsNode = false; |
| 324 m_mouseDownWasSingleClickInSelection = false; | |
| 325 m_selectionInitiationState = HaveNotStartedSelection; | |
| 326 m_mouseDownMayStartAutoscroll = false; | 320 m_mouseDownMayStartAutoscroll = false; |
| 327 m_svgPan = false; | 321 m_svgPan = false; |
| 328 m_mouseDownPos = IntPoint(); | 322 m_mouseDownPos = IntPoint(); |
| 329 m_mouseDownTimestamp = 0; | 323 m_mouseDownTimestamp = 0; |
| 330 m_longTapShouldInvokeContextMenu = false; | 324 m_longTapShouldInvokeContextMenu = false; |
| 331 m_dragStartPos = LayoutPoint(); | 325 m_dragStartPos = LayoutPoint(); |
| 332 m_offsetFromResizeCorner = LayoutSize(); | 326 m_offsetFromResizeCorner = LayoutSize(); |
| 333 m_mouseDown = PlatformMouseEvent(); | 327 m_mouseDown = PlatformMouseEvent(); |
| 334 } | 328 } |
| 335 | 329 |
| 336 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) | 330 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
| 337 { | 331 { |
| 338 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { | 332 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { |
| 339 // We don't dispatch click events if the mousedown node is removed | 333 // We don't dispatch click events if the mousedown node is removed |
| 340 // before a mouseup event. It is compatible with IE and Firefox. | 334 // before a mouseup event. It is compatible with IE and Firefox. |
| 341 m_clickNode = nullptr; | 335 m_clickNode = nullptr; |
| 342 } | 336 } |
| 343 } | 337 } |
| 344 | 338 |
| 345 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti on& newSelection) | |
| 346 { | |
| 347 if (selection.selection() != newSelection) | |
| 348 selection.setSelection(newSelection); | |
| 349 } | |
| 350 | |
| 351 static inline bool dispatchSelectStart(Node* node) | |
| 352 { | |
| 353 if (!node || !node->layoutObject()) | |
| 354 return true; | |
| 355 | |
| 356 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart)); | |
| 357 } | |
| 358 | |
| 359 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection) | |
| 360 { | |
| 361 Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode); | |
| 362 if (!rootUserSelectAll) | |
| 363 return selection; | |
| 364 | |
| 365 VisibleSelection newSelection(selection); | |
| 366 newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCross EditingBoundary)); | |
| 367 newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCr ossEditingBoundary)); | |
| 368 | |
| 369 return newSelection; | |
| 370 } | |
| 371 | |
| 372 bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targe tNode, const VisibleSelection& selection, TextGranularity granularity) | |
| 373 { | |
| 374 if (Position::nodeIsUserSelectNone(targetNode)) | |
| 375 return false; | |
| 376 | |
| 377 if (!dispatchSelectStart(targetNode)) | |
| 378 return false; | |
| 379 | |
| 380 if (selection.isRange()) { | |
| 381 m_selectionInitiationState = ExtendedSelection; | |
| 382 } else { | |
| 383 granularity = CharacterGranularity; | |
| 384 m_selectionInitiationState = PlacedCaret; | |
| 385 } | |
| 386 | |
| 387 m_frame->selection().setNonDirectionalSelectionIfNeeded(selection, granulari ty); | |
| 388 | |
| 389 return true; | |
| 390 } | |
| 391 | |
| 392 void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& resul t, AppendTrailingWhitespace appendTrailingWhitespace) | |
| 393 { | |
| 394 Node* innerNode = result.innerNode(); | |
| 395 VisibleSelection newSelection; | |
| 396 | |
| 397 if (innerNode && innerNode->layoutObject()) { | |
| 398 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | |
| 399 if (pos.isNotNull()) { | |
| 400 newSelection = VisibleSelection(pos); | |
| 401 newSelection.expandUsingGranularity(WordGranularity); | |
| 402 } | |
| 403 | |
| 404 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel ection.isRange()) | |
| 405 newSelection.appendTrailingWhitespace(); | |
| 406 | |
| 407 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 408 } | |
| 409 } | |
| 410 | |
| 411 void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace) | |
| 412 { | |
| 413 Node* innerNode = result.innerNode(); | |
| 414 VisibleSelection newSelection; | |
| 415 | |
| 416 if (innerNode && innerNode->layoutObject()) { | |
| 417 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | |
| 418 Position start = pos.deepEquivalent(); | |
| 419 Position end = pos.deepEquivalent(); | |
| 420 if (pos.isNotNull()) { | |
| 421 DocumentMarkerVector markers = innerNode->document().markers().marke rsInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers()); | |
| 422 if (markers.size() == 1) { | |
| 423 start.moveToOffset(markers[0]->startOffset()); | |
| 424 end.moveToOffset(markers[0]->endOffset()); | |
| 425 newSelection = VisibleSelection(start, end); | |
| 426 } | |
| 427 } | |
| 428 | |
| 429 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel ection.isRange()) | |
| 430 newSelection.appendTrailingWhitespace(); | |
| 431 | |
| 432 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe sults& result) | |
| 437 { | |
| 438 if (m_mouseDownMayStartSelect) { | |
| 439 selectClosestWordFromHitTestResult(result.hitTestResult(), | |
| 440 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi tespace); | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHi tTestResults& result) | |
| 445 { | |
| 446 if (m_mouseDownMayStartSelect) { | |
| 447 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), | |
| 448 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi tespace); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit TestResults& result) | |
| 453 { | |
| 454 if (!result.hitTestResult().isLiveLink()) | |
| 455 return selectClosestWordFromMouseEvent(result); | |
| 456 | |
| 457 Node* innerNode = result.innerNode(); | |
| 458 | |
| 459 if (innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect) { | |
| 460 VisibleSelection newSelection; | |
| 461 Element* URLElement = result.hitTestResult().URLElement(); | |
| 462 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | |
| 463 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescenda ntOf(URLElement)) | |
| 464 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElem ent); | |
| 465 | |
| 466 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 467 } | |
| 468 } | |
| 469 | |
| 470 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestR esults& event) | |
| 471 { | |
| 472 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventDoubleClick"); | |
| 473 | |
| 474 if (event.event().button() != LeftButton) | |
| 475 return false; | |
| 476 | |
| 477 if (m_frame->selection().isRange()) { | |
| 478 // A double-click when range is already selected | |
| 479 // should not change the selection. So, do not call | |
| 480 // selectClosestWordFromMouseEvent, but do set | |
| 481 // m_beganSelectingText to prevent handleMouseReleaseEvent | |
| 482 // from setting caret selection. | |
| 483 m_selectionInitiationState = ExtendedSelection; | |
| 484 } else { | |
| 485 selectClosestWordFromMouseEvent(event); | |
| 486 } | |
| 487 return true; | |
| 488 } | |
| 489 | |
| 490 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR esults& event) | |
| 491 { | |
| 492 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventTripleClick"); | |
| 493 | |
| 494 if (event.event().button() != LeftButton) | |
| 495 return false; | |
| 496 | |
| 497 Node* innerNode = event.innerNode(); | |
| 498 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | |
| 499 return false; | |
| 500 | |
| 501 VisibleSelection newSelection; | |
| 502 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localP oint())); | |
| 503 if (pos.isNotNull()) { | |
| 504 newSelection = VisibleSelection(pos); | |
| 505 newSelection.expandUsingGranularity(ParagraphGranularity); | |
| 506 } | |
| 507 | |
| 508 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); | |
| 509 } | |
| 510 | |
| 511 static int textDistance(const Position& start, const Position& end) | |
| 512 { | |
| 513 RefPtrWillBeRawPtr<Range> range = Range::create(*start.document(), start, en d); | |
| 514 return TextIterator::rangeLength(range->startPosition(), range->endPosition( ), true); | |
| 515 } | |
| 516 | |
| 517 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR esults& event) | |
| 518 { | |
| 519 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventSingleClick"); | |
| 520 | |
| 521 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | |
| 522 Node* innerNode = event.innerNode(); | |
| 523 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | |
| 524 return false; | |
| 525 | |
| 526 // Extend the selection if the Shift key is down, unless the click is in a l ink. | |
| 527 bool extendSelection = event.event().shiftKey() && !event.isOverLink(); | |
| 528 | |
| 529 // Don't restart the selection when the mouse is pressed on an | |
| 530 // existing selection so we can allow for text dragging. | |
| 531 if (FrameView* view = m_frame->view()) { | |
| 532 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ; | |
| 533 if (!extendSelection && m_frame->selection().contains(vPoint)) { | |
| 534 m_mouseDownWasSingleClickInSelection = true; | |
| 535 return false; | |
| 536 } | |
| 537 } | |
| 538 | |
| 539 VisiblePosition visiblePos(innerNode->layoutObject()->positionForPoint(event .localPoint())); | |
| 540 if (visiblePos.isNull()) | |
| 541 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW NSTREAM); | |
| 542 Position pos = visiblePos.deepEquivalent(); | |
| 543 | |
| 544 VisibleSelection newSelection = m_frame->selection().selection(); | |
| 545 TextGranularity granularity = CharacterGranularity; | |
| 546 | |
| 547 if (extendSelection && newSelection.isCaretOrRange()) { | |
| 548 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe lectAll(innerNode, VisibleSelection(VisiblePosition(pos)))); | |
| 549 if (selectionInUserSelectAll.isRange()) { | |
| 550 if (comparePositions(selectionInUserSelectAll.start(), newSelection. start()) < 0) | |
| 551 pos = selectionInUserSelectAll.start(); | |
| 552 else if (comparePositions(newSelection.end(), selectionInUserSelectA ll.end()) < 0) | |
| 553 pos = selectionInUserSelectAll.end(); | |
| 554 } | |
| 555 | |
| 556 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) { | |
| 557 if (pos.isNotNull()) { | |
| 558 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d eselects when selection | |
| 559 // was created right-to-left | |
| 560 Position start = newSelection.start(); | |
| 561 Position end = newSelection.end(); | |
| 562 int distanceToStart = textDistance(start, pos); | |
| 563 int distanceToEnd = textDistance(pos, end); | |
| 564 if (distanceToStart <= distanceToEnd) | |
| 565 newSelection = VisibleSelection(end, pos); | |
| 566 else | |
| 567 newSelection = VisibleSelection(start, pos); | |
| 568 } | |
| 569 } else { | |
| 570 newSelection.setExtent(pos); | |
| 571 } | |
| 572 | |
| 573 if (m_frame->selection().granularity() != CharacterGranularity) { | |
| 574 granularity = m_frame->selection().granularity(); | |
| 575 newSelection.expandUsingGranularity(m_frame->selection().granularity ()); | |
| 576 } | |
| 577 } else { | |
| 578 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS election(visiblePos)); | |
| 579 } | |
| 580 | |
| 581 // Updating the selection is considered side-effect of the event and so it d oesn't impact the handled state. | |
| 582 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g ranularity); | |
| 583 return false; | |
| 584 } | |
| 585 | |
| 586 static inline bool canMouseDownStartSelect(Node* node) | |
| 587 { | |
| 588 if (!node || !node->layoutObject()) | |
| 589 return true; | |
| 590 | |
| 591 if (!node->canStartSelection()) | |
| 592 return false; | |
| 593 | |
| 594 return true; | |
| 595 } | |
| 596 | |
| 597 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve nt) | 339 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve nt) |
| 598 { | 340 { |
| 599 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); | 341 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); |
| 600 | 342 |
| 601 // Reset drag state. | 343 // Reset drag state. |
| 602 dragState().m_dragSrc = nullptr; | 344 dragState().m_dragSrc = nullptr; |
| 603 | 345 |
| 604 cancelFakeMouseMoveEvent(); | 346 cancelFakeMouseMoveEvent(); |
| 605 | 347 |
| 606 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | 348 m_frame->document()->updateLayoutIgnorePendingStylesheets(); |
| 607 | 349 |
| 608 if (FrameView* frameView = m_frame->view()) { | 350 if (FrameView* frameView = m_frame->view()) { |
| 609 if (frameView->isPointInScrollbarCorner(event.event().position())) | 351 if (frameView->isPointInScrollbarCorner(event.event().position())) |
| 610 return false; | 352 return false; |
| 611 } | 353 } |
| 612 | 354 |
| 613 bool singleClick = event.event().clickCount() <= 1; | 355 bool singleClick = event.event().clickCount() <= 1; |
| 614 | 356 |
| 615 // If we got the event back, that must mean it wasn't prevented, | |
| 616 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | |
| 617 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !e vent.scrollbar(); | |
| 618 | |
| 619 m_mouseDownMayStartDrag = singleClick; | 357 m_mouseDownMayStartDrag = singleClick; |
| 620 | 358 |
| 621 m_mouseDownWasSingleClickInSelection = false; | 359 selectionController().handleMousePressEvent(event); |
| 622 | 360 |
| 623 m_mouseDown = event.event(); | 361 m_mouseDown = event.event(); |
| 624 | 362 |
| 625 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx tensions().zoomAndPanEnabled()) { | 363 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx tensions().zoomAndPanEnabled()) { |
| 626 if (event.event().shiftKey() && singleClick) { | 364 if (event.event().shiftKey() && singleClick) { |
| 627 m_svgPan = true; | 365 m_svgPan = true; |
| 628 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()- >rootFrameToContents(event.event().position())); | 366 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()- >rootFrameToContents(event.event().position())); |
| 629 return true; | 367 return true; |
| 630 } | 368 } |
| 631 } | 369 } |
| 632 | 370 |
| 633 // We don't do this at the start of mouse down handling, | 371 // We don't do this at the start of mouse down handling, |
| 634 // because we don't want to do it until we know we didn't hit a widget. | 372 // because we don't want to do it until we know we didn't hit a widget. |
| 635 if (singleClick) | 373 if (singleClick) |
| 636 focusDocumentView(); | 374 focusDocumentView(); |
| 637 | 375 |
| 638 Node* innerNode = event.innerNode(); | 376 Node* innerNode = event.innerNode(); |
| 639 | 377 |
| 640 m_mousePressNode = innerNode; | 378 m_mousePressNode = innerNode; |
| 641 m_dragStartPos = event.event().position(); | 379 m_dragStartPos = event.event().position(); |
| 642 | 380 |
| 643 bool swallowEvent = false; | 381 bool swallowEvent = false; |
| 644 m_mousePressed = true; | 382 m_mousePressed = true; |
| 645 m_selectionInitiationState = HaveNotStartedSelection; | 383 selectionController().initializeSelectionState(); |
| 646 | 384 |
| 647 if (event.event().clickCount() == 2) | 385 if (event.event().clickCount() == 2) |
| 648 swallowEvent = handleMousePressEventDoubleClick(event); | 386 swallowEvent = selectionController().handleMousePressEventDoubleClick(ev ent); |
| 649 else if (event.event().clickCount() >= 3) | 387 else if (event.event().clickCount() >= 3) |
| 650 swallowEvent = handleMousePressEventTripleClick(event); | 388 swallowEvent = selectionController().handleMousePressEventTripleClick(ev ent); |
| 651 else | 389 else |
| 652 swallowEvent = handleMousePressEventSingleClick(event); | 390 swallowEvent = selectionController().handleMousePressEventSingleClick(ev ent); |
| 653 | 391 |
| 654 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect | 392 m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelec t() |
| 655 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod e->layoutBox()->canBeProgramaticallyScrolled()); | 393 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod e->layoutBox()->canBeProgramaticallyScrolled()); |
| 656 | 394 |
| 657 return swallowEvent; | 395 return swallowEvent; |
| 658 } | 396 } |
| 659 | 397 |
| 660 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e vent) | 398 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e vent) |
| 661 { | 399 { |
| 662 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); | 400 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); |
| 663 | 401 |
| 664 // While resetting m_mousePressed here may seem out of place, it turns out | 402 // While resetting m_mousePressed here may seem out of place, it turns out |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 | 439 |
| 702 m_mouseDownMayStartDrag = false; | 440 m_mouseDownMayStartDrag = false; |
| 703 | 441 |
| 704 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { | 442 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { |
| 705 if (AutoscrollController* controller = autoscrollController()) { | 443 if (AutoscrollController* controller = autoscrollController()) { |
| 706 controller->startAutoscrollForSelection(layoutObject); | 444 controller->startAutoscrollForSelection(layoutObject); |
| 707 m_mouseDownMayStartAutoscroll = false; | 445 m_mouseDownMayStartAutoscroll = false; |
| 708 } | 446 } |
| 709 } | 447 } |
| 710 | 448 |
| 711 if (m_selectionInitiationState != ExtendedSelection) { | 449 selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragS tartPos, m_mousePressNode.get(), m_lastKnownMousePosition); |
| 712 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active ); | |
| 713 HitTestResult result(request, m_mouseDownPos); | |
| 714 m_frame->document()->layoutView()->hitTest(result); | |
| 715 | |
| 716 updateSelectionForMouseDrag(result); | |
| 717 } | |
| 718 updateSelectionForMouseDrag(event.hitTestResult()); | |
| 719 return true; | 450 return true; |
| 720 } | 451 } |
| 721 | 452 |
| 722 void EventHandler::updateSelectionForMouseDrag() | 453 void EventHandler::updateSelectionForMouseDrag() |
| 723 { | 454 { |
| 724 FrameView* view = m_frame->view(); | 455 selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_ dragStartPos, m_lastKnownMousePosition); |
| 725 if (!view) | |
| 726 return; | |
| 727 LayoutView* layoutObject = m_frame->contentLayoutObject(); | |
| 728 if (!layoutObject) | |
| 729 return; | |
| 730 | |
| 731 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H itTestRequest::Move); | |
| 732 HitTestResult result(request, view->rootFrameToContents(m_lastKnownMousePosi tion)); | |
| 733 layoutObject->hitTest(result); | |
| 734 updateSelectionForMouseDrag(result); | |
| 735 } | |
| 736 | |
| 737 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul t) | |
| 738 { | |
| 739 if (!m_mouseDownMayStartSelect) | |
| 740 return; | |
| 741 | |
| 742 Node* target = hitTestResult.innerNode(); | |
| 743 if (!target) | |
| 744 return; | |
| 745 | |
| 746 VisiblePosition targetPosition = m_frame->selection().selection().visiblePos itionRespectingEditingBoundary(hitTestResult.localPoint(), target); | |
| 747 // Don't modify the selection if we're not on a node. | |
| 748 if (targetPosition.isNull()) | |
| 749 return; | |
| 750 | |
| 751 // Restart the selection if this is the first mouse move. This work is usual ly | |
| 752 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection. | |
| 753 VisibleSelection newSelection = m_frame->selection().selection(); | |
| 754 | |
| 755 // Special case to limit selection to the containing block for SVG text. | |
| 756 // FIXME: Isn't there a better non-SVG-specific way to do this? | |
| 757 if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) { | |
| 758 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO bject()) { | |
| 759 if (selectionBaseLayoutObject->isSVGText()) { | |
| 760 if (target->layoutObject()->containingBlock() != selectionBaseLa youtObject->containingBlock()) | |
| 761 return; | |
| 762 } | |
| 763 } | |
| 764 } | |
| 765 | |
| 766 if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelect Start(target)) | |
| 767 return; | |
| 768 | |
| 769 if (m_selectionInitiationState != ExtendedSelection) { | |
| 770 // Always extend selection here because it's caused by a mouse drag | |
| 771 m_selectionInitiationState = ExtendedSelection; | |
| 772 newSelection = VisibleSelection(targetPosition); | |
| 773 } | |
| 774 | |
| 775 if (RuntimeEnabledFeatures::userSelectAllEnabled()) { | |
| 776 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllFo rNode(m_mousePressNode.get()); | |
| 777 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePress Node == Position::rootUserSelectAllForNode(target)) { | |
| 778 newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePre ssNode).upstream(CanCrossEditingBoundary)); | |
| 779 newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePr essNode).downstream(CanCrossEditingBoundary)); | |
| 780 } else { | |
| 781 // Reset base for user select all when base is inside user-select-al l area and extent < base. | |
| 782 if (rootUserSelectAllForMousePressNode && comparePositions(target->l ayoutObject()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->l ayoutObject()->positionForPoint(m_dragStartPos)) < 0) | |
| 783 newSelection.setBase(positionAfterNode(rootUserSelectAllForMouse PressNode).downstream(CanCrossEditingBoundary)); | |
| 784 | |
| 785 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNod e(target); | |
| 786 if (rootUserSelectAllForTarget && m_mousePressNode->layoutObject() & & comparePositions(target->layoutObject()->positionForPoint(hitTestResult.localP oint()), m_mousePressNode->layoutObject()->positionForPoint(m_dragStartPos)) < 0 ) | |
| 787 newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTa rget).upstream(CanCrossEditingBoundary)); | |
| 788 else if (rootUserSelectAllForTarget && m_mousePressNode->layoutObjec t()) | |
| 789 newSelection.setExtent(positionAfterNode(rootUserSelectAllForTar get).downstream(CanCrossEditingBoundary)); | |
| 790 else | |
| 791 newSelection.setExtent(targetPosition); | |
| 792 } | |
| 793 } else { | |
| 794 newSelection.setExtent(targetPosition); | |
| 795 } | |
| 796 | |
| 797 if (m_frame->selection().granularity() != CharacterGranularity) | |
| 798 newSelection.expandUsingGranularity(m_frame->selection().granularity()); | |
| 799 | |
| 800 m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_fram e->selection().granularity(), | |
| 801 FrameSelection::AdjustEndpointsAtBidiBoundary); | |
| 802 } | 456 } |
| 803 | 457 |
| 804 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e vent) | 458 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e vent) |
| 805 { | 459 { |
| 806 AutoscrollController* controller = autoscrollController(); | 460 AutoscrollController* controller = autoscrollController(); |
| 807 if (controller && controller->autoscrollInProgress()) | 461 if (controller && controller->autoscrollInProgress()) |
| 808 stopAutoscroll(); | 462 stopAutoscroll(); |
| 809 | 463 |
| 810 // Used to prevent mouseMoveEvent from initiating a drag before | 464 // Used to prevent mouseMoveEvent from initiating a drag before |
| 811 // the mouse is pressed again. | 465 // the mouse is pressed again. |
| 812 m_mousePressed = false; | 466 m_mousePressed = false; |
| 813 m_capturesDragging = false; | 467 m_capturesDragging = false; |
| 814 m_mouseDownMayStartDrag = false; | 468 m_mouseDownMayStartDrag = false; |
| 815 m_mouseDownMayStartSelect = false; | |
| 816 m_mouseDownMayStartAutoscroll = false; | 469 m_mouseDownMayStartAutoscroll = false; |
| 817 | 470 |
| 818 bool handled = false; | 471 return selectionController().handleMouseReleaseEvent(event, m_dragStartPos); |
| 819 | |
| 820 // Clear the selection if the mouse didn't move after the last mouse | |
| 821 // press and it's not a context menu click. We do this so when clicking | |
| 822 // on the selection, the selection goes away. However, if we are | |
| 823 // editing, place the caret. | |
| 824 if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != Ex tendedSelection | |
| 825 && m_dragStartPos == event.event().position() | |
| 826 && m_frame->selection().isRange() | |
| 827 && event.event().button() != RightButton) { | |
| 828 VisibleSelection newSelection; | |
| 829 Node* node = event.innerNode(); | |
| 830 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr owsingEnabled(); | |
| 831 if (node && node->layoutObject() && (caretBrowsing || node->hasEditableS tyle())) { | |
| 832 VisiblePosition pos = VisiblePosition(node->layoutObject()->position ForPoint(event.localPoint())); | |
| 833 newSelection = VisibleSelection(pos); | |
| 834 } | |
| 835 | |
| 836 setSelectionIfNeeded(m_frame->selection(), newSelection); | |
| 837 | |
| 838 handled = true; | |
| 839 } | |
| 840 | |
| 841 m_frame->selection().notifyLayoutObjectOfSelectionChange(UserTriggered); | |
| 842 | |
| 843 m_frame->selection().selectFrameElementInParentIfFullySelected(); | |
| 844 | |
| 845 if (event.event().button() == MiddleButton && !event.isOverLink()) { | |
| 846 // Ignore handled, since we want to paste to where the caret was placed anyway. | |
| 847 handled = handlePasteGlobalSelection(event.event()) || handled; | |
| 848 } | |
| 849 | |
| 850 return handled; | |
| 851 } | 472 } |
| 852 | 473 |
| 853 #if OS(WIN) | 474 #if OS(WIN) |
| 854 | 475 |
| 855 void EventHandler::startPanScrolling(LayoutObject* layoutObject) | 476 void EventHandler::startPanScrolling(LayoutObject* layoutObject) |
| 856 { | 477 { |
| 857 if (!layoutObject->isBox()) | 478 if (!layoutObject->isBox()) |
| 858 return; | 479 return; |
| 859 AutoscrollController* controller = autoscrollController(); | 480 AutoscrollController* controller = autoscrollController(); |
| 860 if (!controller) | 481 if (!controller) |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1231 | 852 |
| 1232 bool inResizer = false; | 853 bool inResizer = false; |
| 1233 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; | 854 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; |
| 1234 if (layoutObject && m_frame->view()) { | 855 if (layoutObject && m_frame->view()) { |
| 1235 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); | 856 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); |
| 1236 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); | 857 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); |
| 1237 } | 858 } |
| 1238 | 859 |
| 1239 // During selection, use an I-beam no matter what we're over. | 860 // During selection, use an I-beam no matter what we're over. |
| 1240 // If a drag may be starting or we're capturing mouse events for a particula r node, don't treat this as a selection. | 861 // If a drag may be starting or we're capturing mouse events for a particula r node, don't treat this as a selection. |
| 1241 if (m_mousePressed && m_mouseDownMayStartSelect | 862 if (m_mousePressed && selectionController().mouseDownMayStartSelect() |
| 1242 && !m_mouseDownMayStartDrag | 863 && !m_mouseDownMayStartDrag |
| 1243 && m_frame->selection().isCaretOrRange() | 864 && m_frame->selection().isCaretOrRange() |
| 1244 && !m_capturingMouseEventsNode) { | 865 && !m_capturingMouseEventsNode) { |
| 1245 return iBeam; | 866 return iBeam; |
| 1246 } | 867 } |
| 1247 | 868 |
| 1248 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe lection())) && !inResizer && !result.scrollbar()) | 869 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe lection())) && !inResizer && !result.scrollbar()) |
| 1249 return iBeam; | 870 return iBeam; |
| 1250 return pointerCursor(); | 871 return pointerCursor(); |
| 1251 } | 872 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1268 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); | 889 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); |
| 1269 | 890 |
| 1270 cancelFakeMouseMoveEvent(); | 891 cancelFakeMouseMoveEvent(); |
| 1271 if (m_eventHandlerWillResetCapturingMouseEventsNode) | 892 if (m_eventHandlerWillResetCapturingMouseEventsNode) |
| 1272 m_capturingMouseEventsNode = nullptr; | 893 m_capturingMouseEventsNode = nullptr; |
| 1273 m_mousePressed = true; | 894 m_mousePressed = true; |
| 1274 m_capturesDragging = true; | 895 m_capturesDragging = true; |
| 1275 setLastKnownMousePosition(mouseEvent); | 896 setLastKnownMousePosition(mouseEvent); |
| 1276 m_mouseDownTimestamp = mouseEvent.timestamp(); | 897 m_mouseDownTimestamp = mouseEvent.timestamp(); |
| 1277 m_mouseDownMayStartDrag = false; | 898 m_mouseDownMayStartDrag = false; |
| 1278 m_mouseDownMayStartSelect = false; | 899 selectionController().setMouseDownMayStartSelect(false); |
| 1279 m_mouseDownMayStartAutoscroll = false; | 900 m_mouseDownMayStartAutoscroll = false; |
| 1280 if (FrameView* view = m_frame->view()) { | 901 if (FrameView* view = m_frame->view()) { |
| 1281 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); | 902 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); |
| 1282 } else { | 903 } else { |
| 1283 invalidateClick(); | 904 invalidateClick(); |
| 1284 return false; | 905 return false; |
| 1285 } | 906 } |
| 1286 | 907 |
| 1287 HitTestRequest request(HitTestRequest::Active); | 908 HitTestRequest request(HitTestRequest::Active); |
| 1288 // Save the document point we generate in case the window coordinate is inva lidated by what happens | 909 // Save the document point we generate in case the window coordinate is inva lidated by what happens |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1639 | 1260 |
| 1640 bool swallowMouseReleaseEvent = false; | 1261 bool swallowMouseReleaseEvent = false; |
| 1641 if (!swallowMouseUpEvent) | 1262 if (!swallowMouseUpEvent) |
| 1642 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); | 1263 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); |
| 1643 | 1264 |
| 1644 invalidateClick(); | 1265 invalidateClick(); |
| 1645 | 1266 |
| 1646 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; | 1267 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; |
| 1647 } | 1268 } |
| 1648 | 1269 |
| 1649 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEve nt) | |
| 1650 { | |
| 1651 // If the event was a middle click, attempt to copy global selection in afte r | |
| 1652 // the newly set caret position. | |
| 1653 // | |
| 1654 // This code is called from either the mouse up or mouse down handling. Ther e | |
| 1655 // is some debate about when the global selection is pasted: | |
| 1656 // xterm: pastes on up. | |
| 1657 // GTK: pastes on down. | |
| 1658 // Qt: pastes on up. | |
| 1659 // Firefox: pastes on up. | |
| 1660 // Chromium: pastes on up. | |
| 1661 // | |
| 1662 // There is something of a webcompat angle to this well, as highlighted by | |
| 1663 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on | |
| 1664 // down then the text is pasted just before the onclick handler runs and | |
| 1665 // clears the text box. So it's important this happens after the event | |
| 1666 // handlers have been fired. | |
| 1667 if (mouseEvent.type() != PlatformEvent::MouseReleased) | |
| 1668 return false; | |
| 1669 | |
| 1670 if (!m_frame->page()) | |
| 1671 return false; | |
| 1672 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); | |
| 1673 // Do not paste here if the focus was moved somewhere else. | |
| 1674 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction()) | |
| 1675 return m_frame->editor().command("PasteGlobalSelection").execute(); | |
| 1676 | |
| 1677 return false; | |
| 1678 } | |
| 1679 | |
| 1680 | |
| 1681 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) | 1270 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
| 1682 { | 1271 { |
| 1683 FrameView* view = m_frame->view(); | 1272 FrameView* view = m_frame->view(); |
| 1684 | 1273 |
| 1685 // FIXME: We might want to dispatch a dragleave even if the view is gone. | 1274 // FIXME: We might want to dispatch a dragleave even if the view is gone. |
| 1686 if (!view) | 1275 if (!view) |
| 1687 return false; | 1276 return false; |
| 1688 | 1277 |
| 1689 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, | 1278 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, |
| 1690 true, true, m_frame->document()->domWindow(), | 1279 true, true, m_frame->document()->domWindow(), |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2482 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE vent); | 2071 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE vent); |
| 2483 m_mouseDownMayStartDrag = true; | 2072 m_mouseDownMayStartDrag = true; |
| 2484 dragState().m_dragSrc = nullptr; | 2073 dragState().m_dragSrc = nullptr; |
| 2485 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos ition()); | 2074 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos ition()); |
| 2486 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); | 2075 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
| 2487 if (handleDrag(mev, DragInitiator::Touch)) { | 2076 if (handleDrag(mev, DragInitiator::Touch)) { |
| 2488 m_longTapShouldInvokeContextMenu = true; | 2077 m_longTapShouldInvokeContextMenu = true; |
| 2489 return true; | 2078 return true; |
| 2490 } | 2079 } |
| 2491 } | 2080 } |
| 2492 #if OS(ANDROID) | 2081 |
| 2493 bool shouldLongPressSelectWord = true; | 2082 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po sition()); |
| 2494 #else | 2083 HitTestResult result = hitTestResultAtPoint(hitTestPoint); |
| 2495 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled(); | 2084 if (selectionController().handleGestureLongPress(gestureEvent, result)) |
| 2496 #endif | 2085 return true; |
|
tkent
2015/06/10 01:21:34
Add focusDocumentView().
Miyoung Shin(g)
2015/06/10 05:10:47
Ah. I caught your point now.
| |
| 2497 if (shouldLongPressSelectWord) { | 2086 |
| 2498 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEven t.position()); | |
| 2499 HitTestResult result = hitTestResultAtPoint(hitTestPoint); | |
| 2500 Node* innerNode = result.innerNode(); | |
| 2501 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() | |
| 2502 #if OS(ANDROID) | |
| 2503 || innerNode->canStartSelection() | |
| 2504 #endif | |
| 2505 )) { | |
| 2506 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitesp ace); | |
| 2507 if (m_frame->selection().isRange()) { | |
| 2508 focusDocumentView(); | |
| 2509 return true; | |
| 2510 } | |
| 2511 } | |
| 2512 } | |
| 2513 return sendContextMenuEventForGesture(targetedEvent); | 2087 return sendContextMenuEventForGesture(targetedEvent); |
| 2514 } | 2088 } |
| 2515 | 2089 |
| 2516 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent) | 2090 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent) |
| 2517 { | 2091 { |
| 2518 #if !OS(ANDROID) | 2092 #if !OS(ANDROID) |
| 2519 if (m_longTapShouldInvokeContextMenu) { | 2093 if (m_longTapShouldInvokeContextMenu) { |
| 2520 m_longTapShouldInvokeContextMenu = false; | 2094 m_longTapShouldInvokeContextMenu = false; |
| 2521 return sendContextMenuEventForGesture(targetedEvent); | 2095 return sendContextMenuEventForGesture(targetedEvent); |
| 2522 } | 2096 } |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2977 FrameView* v = m_frame->view(); | 2551 FrameView* v = m_frame->view(); |
| 2978 if (!v) | 2552 if (!v) |
| 2979 return false; | 2553 return false; |
| 2980 | 2554 |
| 2981 // Clear mouse press state to avoid initiating a drag while context menu is up. | 2555 // Clear mouse press state to avoid initiating a drag while context menu is up. |
| 2982 m_mousePressed = false; | 2556 m_mousePressed = false; |
| 2983 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); | 2557 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); |
| 2984 HitTestRequest request(HitTestRequest::Active); | 2558 HitTestRequest request(HitTestRequest::Active); |
| 2985 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, positionInContents, event); | 2559 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, positionInContents, event); |
| 2986 | 2560 |
| 2987 if (!m_frame->selection().contains(positionInContents) | 2561 selectionController().sendContextMenuEvent(mev, positionInContents); |
| 2988 && !mev.scrollbar() | |
| 2989 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. | |
| 2990 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items | |
| 2991 // available for text selections. But only if we're above text. | |
| 2992 && (m_frame->selection().isContentEditable() || (mev.innerNode() && mev. innerNode()->isTextNode()))) { | |
| 2993 m_mouseDownMayStartSelect = true; // context menu events are always allo wed to perform a selection | |
| 2994 | |
| 2995 if (mev.hitTestResult().isMisspelled()) | |
| 2996 selectClosestMisspellingFromMouseEvent(mev); | |
| 2997 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick( )) | |
| 2998 selectClosestWordOrLinkFromMouseEvent(mev); | |
| 2999 } | |
| 3000 | 2562 |
| 3001 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode() ; | 2563 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode() ; |
| 3002 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event , false); | 2564 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event , false); |
| 3003 } | 2565 } |
| 3004 | 2566 |
| 3005 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) | 2567 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
| 3006 { | 2568 { |
| 3007 FrameView* view = m_frame->view(); | 2569 FrameView* view = m_frame->view(); |
| 3008 if (!view) | 2570 if (!view) |
| 3009 return false; | 2571 return false; |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3498 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); | 3060 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); |
| 3499 } else { | 3061 } else { |
| 3500 dragState().m_dragSrc = nullptr; | 3062 dragState().m_dragSrc = nullptr; |
| 3501 } | 3063 } |
| 3502 | 3064 |
| 3503 if (!dragState().m_dragSrc) | 3065 if (!dragState().m_dragSrc) |
| 3504 m_mouseDownMayStartDrag = false; // no element is draggable | 3066 m_mouseDownMayStartDrag = false; // no element is draggable |
| 3505 } | 3067 } |
| 3506 | 3068 |
| 3507 if (!m_mouseDownMayStartDrag) | 3069 if (!m_mouseDownMayStartDrag) |
| 3508 return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() & & !m_mouseDownMayStartAutoscroll; | 3070 return initiator == DragInitiator::Mouse && !selectionController().mouse DownMayStartSelect() && !m_mouseDownMayStartAutoscroll; |
| 3509 | 3071 |
| 3510 // We are starting a text/image/url drag, so the cursor should be an arrow | 3072 // We are starting a text/image/url drag, so the cursor should be an arrow |
| 3511 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer). | 3073 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer). |
| 3512 m_frame->view()->setCursor(pointerCursor()); | 3074 m_frame->view()->setCursor(pointerCursor()); |
| 3513 | 3075 |
| 3514 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position())) | 3076 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position())) |
| 3515 return true; | 3077 return true; |
| 3516 | 3078 |
| 3517 // Once we're past the hysteresis point, we don't want to treat this gesture as a click | 3079 // Once we're past the hysteresis point, we don't want to treat this gesture as a click |
| 3518 invalidateClick(); | 3080 invalidateClick(); |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4083 | 3645 |
| 4084 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) | 3646 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
| 4085 { | 3647 { |
| 4086 m_mousePositionIsUnknown = false; | 3648 m_mousePositionIsUnknown = false; |
| 4087 m_lastKnownMousePosition = event.position(); | 3649 m_lastKnownMousePosition = event.position(); |
| 4088 m_lastKnownMouseGlobalPosition = event.globalPosition(); | 3650 m_lastKnownMouseGlobalPosition = event.globalPosition(); |
| 4089 } | 3651 } |
| 4090 | 3652 |
| 4091 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe) | 3653 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe) |
| 4092 { | 3654 { |
| 4093 // If we're clicking into a frame that is selected, the frame will appear | 3655 selectionController().passMousePressEventToSubframe(mev); |
| 4094 // greyed out even though we're clicking on the selection. This looks | |
| 4095 // really strange (having the whole frame be greyed out), so we deselect the | |
| 4096 // selection. | |
| 4097 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | |
| 4098 if (m_frame->selection().contains(p)) { | |
| 4099 VisiblePosition visiblePos( | |
| 4100 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint())) ; | |
| 4101 VisibleSelection newSelection(visiblePos); | |
| 4102 m_frame->selection().setSelection(newSelection); | |
| 4103 } | |
| 4104 | |
| 4105 subframe->eventHandler().handleMousePressEvent(mev.event()); | 3656 subframe->eventHandler().handleMousePressEvent(mev.event()); |
| 4106 return true; | 3657 return true; |
| 4107 } | 3658 } |
| 4108 | 3659 |
| 4109 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode) | 3660 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode) |
| 4110 { | 3661 { |
| 4111 if (m_mouseDownMayStartDrag) | 3662 if (m_mouseDownMayStartDrag) |
| 4112 return false; | 3663 return false; |
| 4113 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e); | 3664 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e); |
| 4114 return true; | 3665 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4146 unsigned EventHandler::accessKeyModifiers() | 3697 unsigned EventHandler::accessKeyModifiers() |
| 4147 { | 3698 { |
| 4148 #if OS(MACOSX) | 3699 #if OS(MACOSX) |
| 4149 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; | 3700 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; |
| 4150 #else | 3701 #else |
| 4151 return PlatformEvent::AltKey; | 3702 return PlatformEvent::AltKey; |
| 4152 #endif | 3703 #endif |
| 4153 } | 3704 } |
| 4154 | 3705 |
| 4155 } // namespace blink | 3706 } // namespace blink |
| OLD | NEW |