| 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_accumulatedRootOverscroll(FloatSize()) | 231 , m_accumulatedRootOverscroll(FloatSize()) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 266 visitor->trace(m_frameSetBeingResized); | 262 visitor->trace(m_frameSetBeingResized); |
| 267 visitor->trace(m_latchedWheelEventNode); | 263 visitor->trace(m_latchedWheelEventNode); |
| 268 visitor->trace(m_previousWheelScrolledNode); | 264 visitor->trace(m_previousWheelScrolledNode); |
| 269 visitor->trace(m_scrollbarHandlingScrollGesture); | 265 visitor->trace(m_scrollbarHandlingScrollGesture); |
| 270 visitor->trace(m_targetForTouchID); | 266 visitor->trace(m_targetForTouchID); |
| 271 visitor->trace(m_touchSequenceDocument); | 267 visitor->trace(m_touchSequenceDocument); |
| 272 visitor->trace(m_scrollGestureHandlingNode); | 268 visitor->trace(m_scrollGestureHandlingNode); |
| 273 visitor->trace(m_previousGestureScrolledNode); | 269 visitor->trace(m_previousGestureScrolledNode); |
| 274 visitor->trace(m_lastDeferredTapElement); | 270 visitor->trace(m_lastDeferredTapElement); |
| 275 visitor->trace(m_currentScrollChain); | 271 visitor->trace(m_currentScrollChain); |
| 272 visitor->trace(m_selectionController); |
| 276 #endif | 273 #endif |
| 277 } | 274 } |
| 278 | 275 |
| 279 DragState& EventHandler::dragState() | 276 DragState& EventHandler::dragState() |
| 280 { | 277 { |
| 281 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); | 278 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); |
| 282 return *state; | 279 return *state; |
| 283 } | 280 } |
| 284 | 281 |
| 285 void EventHandler::clear() | 282 void EventHandler::clear() |
| (...skipping 24 matching lines...) Expand all Loading... |
| 310 m_previousWheelScrolledNode = nullptr; | 307 m_previousWheelScrolledNode = nullptr; |
| 311 m_targetForTouchID.clear(); | 308 m_targetForTouchID.clear(); |
| 312 m_touchSequenceDocument.clear(); | 309 m_touchSequenceDocument.clear(); |
| 313 m_touchSequenceUserGestureToken.clear(); | 310 m_touchSequenceUserGestureToken.clear(); |
| 314 m_scrollGestureHandlingNode = nullptr; | 311 m_scrollGestureHandlingNode = nullptr; |
| 315 m_lastGestureScrollOverWidget = false; | 312 m_lastGestureScrollOverWidget = false; |
| 316 m_previousGestureScrolledNode = nullptr; | 313 m_previousGestureScrolledNode = nullptr; |
| 317 m_scrollbarHandlingScrollGesture = nullptr; | 314 m_scrollbarHandlingScrollGesture = nullptr; |
| 318 m_maxMouseMovedDuration = 0; | 315 m_maxMouseMovedDuration = 0; |
| 319 m_touchPressed = false; | 316 m_touchPressed = false; |
| 320 m_mouseDownMayStartSelect = false; | |
| 321 m_mouseDownMayStartDrag = false; | 317 m_mouseDownMayStartDrag = false; |
| 322 m_lastShowPressTimestamp = 0; | 318 m_lastShowPressTimestamp = 0; |
| 323 m_lastDeferredTapElement = nullptr; | 319 m_lastDeferredTapElement = nullptr; |
| 324 m_eventHandlerWillResetCapturingMouseEventsNode = false; | 320 m_eventHandlerWillResetCapturingMouseEventsNode = false; |
| 325 m_mouseDownWasSingleClickInSelection = false; | |
| 326 m_selectionInitiationState = HaveNotStartedSelection; | |
| 327 m_mouseDownMayStartAutoscroll = false; | 321 m_mouseDownMayStartAutoscroll = false; |
| 328 m_svgPan = false; | 322 m_svgPan = false; |
| 329 m_mouseDownPos = IntPoint(); | 323 m_mouseDownPos = IntPoint(); |
| 330 m_mouseDownTimestamp = 0; | 324 m_mouseDownTimestamp = 0; |
| 331 m_longTapShouldInvokeContextMenu = false; | 325 m_longTapShouldInvokeContextMenu = false; |
| 332 m_dragStartPos = LayoutPoint(); | 326 m_dragStartPos = LayoutPoint(); |
| 333 m_offsetFromResizeCorner = LayoutSize(); | 327 m_offsetFromResizeCorner = LayoutSize(); |
| 334 m_mouseDown = PlatformMouseEvent(); | 328 m_mouseDown = PlatformMouseEvent(); |
| 335 } | 329 } |
| 336 | 330 |
| 337 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) | 331 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
| 338 { | 332 { |
| 339 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { | 333 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { |
| 340 // We don't dispatch click events if the mousedown node is removed | 334 // We don't dispatch click events if the mousedown node is removed |
| 341 // before a mouseup event. It is compatible with IE and Firefox. | 335 // before a mouseup event. It is compatible with IE and Firefox. |
| 342 m_clickNode = nullptr; | 336 m_clickNode = nullptr; |
| 343 } | 337 } |
| 344 } | 338 } |
| 345 | 339 |
| 346 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti
on& newSelection) | |
| 347 { | |
| 348 if (selection.selection() != newSelection) | |
| 349 selection.setSelection(newSelection); | |
| 350 } | |
| 351 | |
| 352 static inline bool dispatchSelectStart(Node* node) | |
| 353 { | |
| 354 if (!node || !node->layoutObject()) | |
| 355 return true; | |
| 356 | |
| 357 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel
ectstart)); | |
| 358 } | |
| 359 | |
| 360 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode,
const VisibleSelection& selection) | |
| 361 { | |
| 362 Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode); | |
| 363 if (!rootUserSelectAll) | |
| 364 return selection; | |
| 365 | |
| 366 VisibleSelection newSelection(selection); | |
| 367 newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCross
EditingBoundary)); | |
| 368 newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCr
ossEditingBoundary)); | |
| 369 | |
| 370 return newSelection; | |
| 371 } | |
| 372 | |
| 373 bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targe
tNode, const VisibleSelection& selection, TextGranularity granularity) | |
| 374 { | |
| 375 if (Position::nodeIsUserSelectNone(targetNode)) | |
| 376 return false; | |
| 377 | |
| 378 if (!dispatchSelectStart(targetNode)) | |
| 379 return false; | |
| 380 | |
| 381 if (selection.isRange()) { | |
| 382 m_selectionInitiationState = ExtendedSelection; | |
| 383 } else { | |
| 384 granularity = CharacterGranularity; | |
| 385 m_selectionInitiationState = PlacedCaret; | |
| 386 } | |
| 387 | |
| 388 m_frame->selection().setNonDirectionalSelectionIfNeeded(selection, granulari
ty); | |
| 389 | |
| 390 return true; | |
| 391 } | |
| 392 | |
| 393 void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& resul
t, AppendTrailingWhitespace appendTrailingWhitespace) | |
| 394 { | |
| 395 Node* innerNode = result.innerNode(); | |
| 396 VisibleSelection newSelection; | |
| 397 | |
| 398 if (innerNode && innerNode->layoutObject()) { | |
| 399 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l
ocalPoint())); | |
| 400 if (pos.isNotNull()) { | |
| 401 newSelection = VisibleSelection(pos); | |
| 402 newSelection.expandUsingGranularity(WordGranularity); | |
| 403 } | |
| 404 | |
| 405 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel
ection.isRange()) | |
| 406 newSelection.appendTrailingWhitespace(); | |
| 407 | |
| 408 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult
& result, AppendTrailingWhitespace appendTrailingWhitespace) | |
| 413 { | |
| 414 Node* innerNode = result.innerNode(); | |
| 415 VisibleSelection newSelection; | |
| 416 | |
| 417 if (innerNode && innerNode->layoutObject()) { | |
| 418 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l
ocalPoint())); | |
| 419 Position start = pos.deepEquivalent(); | |
| 420 Position end = pos.deepEquivalent(); | |
| 421 if (pos.isNotNull()) { | |
| 422 DocumentMarkerVector markers = innerNode->document().markers().marke
rsInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers()); | |
| 423 if (markers.size() == 1) { | |
| 424 start.moveToOffset(markers[0]->startOffset()); | |
| 425 end.moveToOffset(markers[0]->endOffset()); | |
| 426 newSelection = VisibleSelection(start, end); | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel
ection.isRange()) | |
| 431 newSelection.appendTrailingWhitespace(); | |
| 432 | |
| 433 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 434 } | |
| 435 } | |
| 436 | |
| 437 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe
sults& result) | |
| 438 { | |
| 439 if (m_mouseDownMayStartSelect) { | |
| 440 selectClosestWordFromHitTestResult(result.hitTestResult(), | |
| 441 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail
ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi
tespace); | |
| 442 } | |
| 443 } | |
| 444 | |
| 445 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHi
tTestResults& result) | |
| 446 { | |
| 447 if (m_mouseDownMayStartSelect) { | |
| 448 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), | |
| 449 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail
ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi
tespace); | |
| 450 } | |
| 451 } | |
| 452 | |
| 453 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit
TestResults& result) | |
| 454 { | |
| 455 if (!result.hitTestResult().isLiveLink()) | |
| 456 return selectClosestWordFromMouseEvent(result); | |
| 457 | |
| 458 Node* innerNode = result.innerNode(); | |
| 459 | |
| 460 if (innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect) { | |
| 461 VisibleSelection newSelection; | |
| 462 Element* URLElement = result.hitTestResult().URLElement(); | |
| 463 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l
ocalPoint())); | |
| 464 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescenda
ntOf(URLElement)) | |
| 465 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElem
ent); | |
| 466 | |
| 467 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec
tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestR
esults& event) | |
| 472 { | |
| 473 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventDoubleClick"); | |
| 474 | |
| 475 if (event.event().button() != LeftButton) | |
| 476 return false; | |
| 477 | |
| 478 if (m_frame->selection().isRange()) { | |
| 479 // A double-click when range is already selected | |
| 480 // should not change the selection. So, do not call | |
| 481 // selectClosestWordFromMouseEvent, but do set | |
| 482 // m_beganSelectingText to prevent handleMouseReleaseEvent | |
| 483 // from setting caret selection. | |
| 484 m_selectionInitiationState = ExtendedSelection; | |
| 485 } else { | |
| 486 selectClosestWordFromMouseEvent(event); | |
| 487 } | |
| 488 return true; | |
| 489 } | |
| 490 | |
| 491 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR
esults& event) | |
| 492 { | |
| 493 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventTripleClick"); | |
| 494 | |
| 495 if (event.event().button() != LeftButton) | |
| 496 return false; | |
| 497 | |
| 498 Node* innerNode = event.innerNode(); | |
| 499 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | |
| 500 return false; | |
| 501 | |
| 502 VisibleSelection newSelection; | |
| 503 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localP
oint())); | |
| 504 if (pos.isNotNull()) { | |
| 505 newSelection = VisibleSelection(pos); | |
| 506 newSelection.expandUsingGranularity(ParagraphGranularity); | |
| 507 } | |
| 508 | |
| 509 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe
lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); | |
| 510 } | |
| 511 | |
| 512 static int textDistance(const Position& start, const Position& end) | |
| 513 { | |
| 514 RefPtrWillBeRawPtr<Range> range = Range::create(*start.document(), start, en
d); | |
| 515 return TextIterator::rangeLength(range->startPosition(), range->endPosition(
), true); | |
| 516 } | |
| 517 | |
| 518 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
esults& event) | |
| 519 { | |
| 520 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventSingleClick"); | |
| 521 | |
| 522 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | |
| 523 Node* innerNode = event.innerNode(); | |
| 524 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | |
| 525 return false; | |
| 526 | |
| 527 // Extend the selection if the Shift key is down, unless the click is in a l
ink. | |
| 528 bool extendSelection = event.event().shiftKey() && !event.isOverLink(); | |
| 529 | |
| 530 // Don't restart the selection when the mouse is pressed on an | |
| 531 // existing selection so we can allow for text dragging. | |
| 532 if (FrameView* view = m_frame->view()) { | |
| 533 LayoutPoint vPoint = view->rootFrameToContents(event.event().position())
; | |
| 534 if (!extendSelection && m_frame->selection().contains(vPoint)) { | |
| 535 m_mouseDownWasSingleClickInSelection = true; | |
| 536 return false; | |
| 537 } | |
| 538 } | |
| 539 | |
| 540 VisiblePosition visiblePos(innerNode->layoutObject()->positionForPoint(event
.localPoint())); | |
| 541 if (visiblePos.isNull()) | |
| 542 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW
NSTREAM); | |
| 543 Position pos = visiblePos.deepEquivalent(); | |
| 544 | |
| 545 VisibleSelection newSelection = m_frame->selection().selection(); | |
| 546 TextGranularity granularity = CharacterGranularity; | |
| 547 | |
| 548 if (extendSelection && newSelection.isCaretOrRange()) { | |
| 549 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe
lectAll(innerNode, VisibleSelection(VisiblePosition(pos)))); | |
| 550 if (selectionInUserSelectAll.isRange()) { | |
| 551 if (comparePositions(selectionInUserSelectAll.start(), newSelection.
start()) < 0) | |
| 552 pos = selectionInUserSelectAll.start(); | |
| 553 else if (comparePositions(newSelection.end(), selectionInUserSelectA
ll.end()) < 0) | |
| 554 pos = selectionInUserSelectAll.end(); | |
| 555 } | |
| 556 | |
| 557 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()
) { | |
| 558 if (pos.isNotNull()) { | |
| 559 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d
eselects when selection | |
| 560 // was created right-to-left | |
| 561 Position start = newSelection.start(); | |
| 562 Position end = newSelection.end(); | |
| 563 int distanceToStart = textDistance(start, pos); | |
| 564 int distanceToEnd = textDistance(pos, end); | |
| 565 if (distanceToStart <= distanceToEnd) | |
| 566 newSelection = VisibleSelection(end, pos); | |
| 567 else | |
| 568 newSelection = VisibleSelection(start, pos); | |
| 569 } | |
| 570 } else { | |
| 571 newSelection.setExtent(pos); | |
| 572 } | |
| 573 | |
| 574 if (m_frame->selection().granularity() != CharacterGranularity) { | |
| 575 granularity = m_frame->selection().granularity(); | |
| 576 newSelection.expandUsingGranularity(m_frame->selection().granularity
()); | |
| 577 } | |
| 578 } else { | |
| 579 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS
election(visiblePos)); | |
| 580 } | |
| 581 | |
| 582 // Updating the selection is considered side-effect of the event and so it d
oesn't impact the handled state. | |
| 583 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g
ranularity); | |
| 584 return false; | |
| 585 } | |
| 586 | |
| 587 static inline bool canMouseDownStartSelect(Node* node) | |
| 588 { | |
| 589 if (!node || !node->layoutObject()) | |
| 590 return true; | |
| 591 | |
| 592 if (!node->canStartSelection()) | |
| 593 return false; | |
| 594 | |
| 595 return true; | |
| 596 } | |
| 597 | |
| 598 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
nt) | 340 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
nt) |
| 599 { | 341 { |
| 600 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); | 342 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); |
| 601 | 343 |
| 602 // Reset drag state. | 344 // Reset drag state. |
| 603 dragState().m_dragSrc = nullptr; | 345 dragState().m_dragSrc = nullptr; |
| 604 | 346 |
| 605 cancelFakeMouseMoveEvent(); | 347 cancelFakeMouseMoveEvent(); |
| 606 | 348 |
| 607 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | 349 m_frame->document()->updateLayoutIgnorePendingStylesheets(); |
| 608 | 350 |
| 609 if (FrameView* frameView = m_frame->view()) { | 351 if (FrameView* frameView = m_frame->view()) { |
| 610 if (frameView->isPointInScrollbarCorner(event.event().position())) | 352 if (frameView->isPointInScrollbarCorner(event.event().position())) |
| 611 return false; | 353 return false; |
| 612 } | 354 } |
| 613 | 355 |
| 614 bool singleClick = event.event().clickCount() <= 1; | 356 bool singleClick = event.event().clickCount() <= 1; |
| 615 | 357 |
| 616 // If we got the event back, that must mean it wasn't prevented, | |
| 617 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | |
| 618 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !e
vent.scrollbar(); | |
| 619 | |
| 620 m_mouseDownMayStartDrag = singleClick; | 358 m_mouseDownMayStartDrag = singleClick; |
| 621 | 359 |
| 622 m_mouseDownWasSingleClickInSelection = false; | 360 selectionController().handleMousePressEvent(event); |
| 623 | 361 |
| 624 m_mouseDown = event.event(); | 362 m_mouseDown = event.event(); |
| 625 | 363 |
| 626 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx
tensions().zoomAndPanEnabled()) { | 364 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx
tensions().zoomAndPanEnabled()) { |
| 627 if (event.event().shiftKey() && singleClick) { | 365 if (event.event().shiftKey() && singleClick) { |
| 628 m_svgPan = true; | 366 m_svgPan = true; |
| 629 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()-
>rootFrameToContents(event.event().position())); | 367 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()-
>rootFrameToContents(event.event().position())); |
| 630 return true; | 368 return true; |
| 631 } | 369 } |
| 632 } | 370 } |
| 633 | 371 |
| 634 // We don't do this at the start of mouse down handling, | 372 // We don't do this at the start of mouse down handling, |
| 635 // because we don't want to do it until we know we didn't hit a widget. | 373 // because we don't want to do it until we know we didn't hit a widget. |
| 636 if (singleClick) | 374 if (singleClick) |
| 637 focusDocumentView(); | 375 focusDocumentView(); |
| 638 | 376 |
| 639 Node* innerNode = event.innerNode(); | 377 Node* innerNode = event.innerNode(); |
| 640 | 378 |
| 641 m_mousePressNode = innerNode; | 379 m_mousePressNode = innerNode; |
| 642 m_dragStartPos = event.event().position(); | 380 m_dragStartPos = event.event().position(); |
| 643 | 381 |
| 644 bool swallowEvent = false; | 382 bool swallowEvent = false; |
| 645 m_mousePressed = true; | 383 m_mousePressed = true; |
| 646 m_selectionInitiationState = HaveNotStartedSelection; | 384 selectionController().initializeSelectionState(); |
| 647 | 385 |
| 648 if (event.event().clickCount() == 2) | 386 if (event.event().clickCount() == 2) |
| 649 swallowEvent = handleMousePressEventDoubleClick(event); | 387 swallowEvent = selectionController().handleMousePressEventDoubleClick(ev
ent); |
| 650 else if (event.event().clickCount() >= 3) | 388 else if (event.event().clickCount() >= 3) |
| 651 swallowEvent = handleMousePressEventTripleClick(event); | 389 swallowEvent = selectionController().handleMousePressEventTripleClick(ev
ent); |
| 652 else | 390 else |
| 653 swallowEvent = handleMousePressEventSingleClick(event); | 391 swallowEvent = selectionController().handleMousePressEventSingleClick(ev
ent); |
| 654 | 392 |
| 655 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect | 393 m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelec
t() |
| 656 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod
e->layoutBox()->canBeProgramaticallyScrolled()); | 394 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod
e->layoutBox()->canBeProgramaticallyScrolled()); |
| 657 | 395 |
| 658 return swallowEvent; | 396 return swallowEvent; |
| 659 } | 397 } |
| 660 | 398 |
| 661 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
vent) | 399 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
vent) |
| 662 { | 400 { |
| 663 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); | 401 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); |
| 664 | 402 |
| 665 // While resetting m_mousePressed here may seem out of place, it turns out | 403 // 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... |
| 702 | 440 |
| 703 m_mouseDownMayStartDrag = false; | 441 m_mouseDownMayStartDrag = false; |
| 704 | 442 |
| 705 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { | 443 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { |
| 706 if (AutoscrollController* controller = autoscrollController()) { | 444 if (AutoscrollController* controller = autoscrollController()) { |
| 707 controller->startAutoscrollForSelection(layoutObject); | 445 controller->startAutoscrollForSelection(layoutObject); |
| 708 m_mouseDownMayStartAutoscroll = false; | 446 m_mouseDownMayStartAutoscroll = false; |
| 709 } | 447 } |
| 710 } | 448 } |
| 711 | 449 |
| 712 if (m_selectionInitiationState != ExtendedSelection) { | 450 selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragS
tartPos, m_mousePressNode.get(), m_lastKnownMousePosition); |
| 713 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active
); | |
| 714 HitTestResult result(request, m_mouseDownPos); | |
| 715 m_frame->document()->layoutView()->hitTest(result); | |
| 716 | |
| 717 updateSelectionForMouseDrag(result); | |
| 718 } | |
| 719 updateSelectionForMouseDrag(event.hitTestResult()); | |
| 720 return true; | 451 return true; |
| 721 } | 452 } |
| 722 | 453 |
| 723 void EventHandler::updateSelectionForMouseDrag() | 454 void EventHandler::updateSelectionForMouseDrag() |
| 724 { | 455 { |
| 725 FrameView* view = m_frame->view(); | 456 selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_
dragStartPos, m_lastKnownMousePosition); |
| 726 if (!view) | |
| 727 return; | |
| 728 LayoutView* layoutObject = m_frame->contentLayoutObject(); | |
| 729 if (!layoutObject) | |
| 730 return; | |
| 731 | |
| 732 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H
itTestRequest::Move); | |
| 733 HitTestResult result(request, view->rootFrameToContents(m_lastKnownMousePosi
tion)); | |
| 734 layoutObject->hitTest(result); | |
| 735 updateSelectionForMouseDrag(result); | |
| 736 } | |
| 737 | |
| 738 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
t) | |
| 739 { | |
| 740 if (!m_mouseDownMayStartSelect) | |
| 741 return; | |
| 742 | |
| 743 Node* target = hitTestResult.innerNode(); | |
| 744 if (!target) | |
| 745 return; | |
| 746 | |
| 747 VisiblePosition targetPosition = m_frame->selection().selection().visiblePos
itionRespectingEditingBoundary(hitTestResult.localPoint(), target); | |
| 748 // Don't modify the selection if we're not on a node. | |
| 749 if (targetPosition.isNull()) | |
| 750 return; | |
| 751 | |
| 752 // Restart the selection if this is the first mouse move. This work is usual
ly | |
| 753 // done in handleMousePressEvent, but not if the mouse press was on an exist
ing selection. | |
| 754 VisibleSelection newSelection = m_frame->selection().selection(); | |
| 755 | |
| 756 // Special case to limit selection to the containing block for SVG text. | |
| 757 // FIXME: Isn't there a better non-SVG-specific way to do this? | |
| 758 if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) { | |
| 759 if (LayoutObject* selectionBaseLayoutObject = selectionBaseNode->layoutO
bject()) { | |
| 760 if (selectionBaseLayoutObject->isSVGText()) { | |
| 761 if (target->layoutObject()->containingBlock() != selectionBaseLa
youtObject->containingBlock()) | |
| 762 return; | |
| 763 } | |
| 764 } | |
| 765 } | |
| 766 | |
| 767 if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelect
Start(target)) | |
| 768 return; | |
| 769 | |
| 770 if (m_selectionInitiationState != ExtendedSelection) { | |
| 771 // Always extend selection here because it's caused by a mouse drag | |
| 772 m_selectionInitiationState = ExtendedSelection; | |
| 773 newSelection = VisibleSelection(targetPosition); | |
| 774 } | |
| 775 | |
| 776 if (RuntimeEnabledFeatures::userSelectAllEnabled()) { | |
| 777 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllFo
rNode(m_mousePressNode.get()); | |
| 778 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePress
Node == Position::rootUserSelectAllForNode(target)) { | |
| 779 newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePre
ssNode).upstream(CanCrossEditingBoundary)); | |
| 780 newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePr
essNode).downstream(CanCrossEditingBoundary)); | |
| 781 } else { | |
| 782 // Reset base for user select all when base is inside user-select-al
l area and extent < base. | |
| 783 if (rootUserSelectAllForMousePressNode && comparePositions(target->l
ayoutObject()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->l
ayoutObject()->positionForPoint(m_dragStartPos)) < 0) | |
| 784 newSelection.setBase(positionAfterNode(rootUserSelectAllForMouse
PressNode).downstream(CanCrossEditingBoundary)); | |
| 785 | |
| 786 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNod
e(target); | |
| 787 if (rootUserSelectAllForTarget && m_mousePressNode->layoutObject() &
& comparePositions(target->layoutObject()->positionForPoint(hitTestResult.localP
oint()), m_mousePressNode->layoutObject()->positionForPoint(m_dragStartPos)) < 0
) | |
| 788 newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTa
rget).upstream(CanCrossEditingBoundary)); | |
| 789 else if (rootUserSelectAllForTarget && m_mousePressNode->layoutObjec
t()) | |
| 790 newSelection.setExtent(positionAfterNode(rootUserSelectAllForTar
get).downstream(CanCrossEditingBoundary)); | |
| 791 else | |
| 792 newSelection.setExtent(targetPosition); | |
| 793 } | |
| 794 } else { | |
| 795 newSelection.setExtent(targetPosition); | |
| 796 } | |
| 797 | |
| 798 if (m_frame->selection().granularity() != CharacterGranularity) | |
| 799 newSelection.expandUsingGranularity(m_frame->selection().granularity()); | |
| 800 | |
| 801 m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_fram
e->selection().granularity(), | |
| 802 FrameSelection::AdjustEndpointsAtBidiBoundary); | |
| 803 } | 457 } |
| 804 | 458 |
| 805 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
vent) | 459 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
vent) |
| 806 { | 460 { |
| 807 AutoscrollController* controller = autoscrollController(); | 461 AutoscrollController* controller = autoscrollController(); |
| 808 if (controller && controller->autoscrollInProgress()) | 462 if (controller && controller->autoscrollInProgress()) |
| 809 stopAutoscroll(); | 463 stopAutoscroll(); |
| 810 | 464 |
| 811 // Used to prevent mouseMoveEvent from initiating a drag before | 465 // Used to prevent mouseMoveEvent from initiating a drag before |
| 812 // the mouse is pressed again. | 466 // the mouse is pressed again. |
| 813 m_mousePressed = false; | 467 m_mousePressed = false; |
| 814 m_capturesDragging = false; | 468 m_capturesDragging = false; |
| 815 m_mouseDownMayStartDrag = false; | 469 m_mouseDownMayStartDrag = false; |
| 816 m_mouseDownMayStartSelect = false; | |
| 817 m_mouseDownMayStartAutoscroll = false; | 470 m_mouseDownMayStartAutoscroll = false; |
| 818 | 471 |
| 819 bool handled = false; | 472 return selectionController().handleMouseReleaseEvent(event, m_dragStartPos); |
| 820 | |
| 821 // Clear the selection if the mouse didn't move after the last mouse | |
| 822 // press and it's not a context menu click. We do this so when clicking | |
| 823 // on the selection, the selection goes away. However, if we are | |
| 824 // editing, place the caret. | |
| 825 if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != Ex
tendedSelection | |
| 826 && m_dragStartPos == event.event().position() | |
| 827 && m_frame->selection().isRange() | |
| 828 && event.event().button() != RightButton) { | |
| 829 VisibleSelection newSelection; | |
| 830 Node* node = event.innerNode(); | |
| 831 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr
owsingEnabled(); | |
| 832 if (node && node->layoutObject() && (caretBrowsing || node->hasEditableS
tyle())) { | |
| 833 VisiblePosition pos = VisiblePosition(node->layoutObject()->position
ForPoint(event.localPoint())); | |
| 834 newSelection = VisibleSelection(pos); | |
| 835 } | |
| 836 | |
| 837 setSelectionIfNeeded(m_frame->selection(), newSelection); | |
| 838 | |
| 839 handled = true; | |
| 840 } | |
| 841 | |
| 842 m_frame->selection().notifyLayoutObjectOfSelectionChange(UserTriggered); | |
| 843 | |
| 844 m_frame->selection().selectFrameElementInParentIfFullySelected(); | |
| 845 | |
| 846 if (event.event().button() == MiddleButton && !event.isOverLink()) { | |
| 847 // Ignore handled, since we want to paste to where the caret was placed
anyway. | |
| 848 handled = handlePasteGlobalSelection(event.event()) || handled; | |
| 849 } | |
| 850 | |
| 851 return handled; | |
| 852 } | 473 } |
| 853 | 474 |
| 854 #if OS(WIN) | 475 #if OS(WIN) |
| 855 | 476 |
| 856 void EventHandler::startPanScrolling(LayoutObject* layoutObject) | 477 void EventHandler::startPanScrolling(LayoutObject* layoutObject) |
| 857 { | 478 { |
| 858 if (!layoutObject->isBox()) | 479 if (!layoutObject->isBox()) |
| 859 return; | 480 return; |
| 860 AutoscrollController* controller = autoscrollController(); | 481 AutoscrollController* controller = autoscrollController(); |
| 861 if (!controller) | 482 if (!controller) |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 | 854 |
| 1234 bool inResizer = false; | 855 bool inResizer = false; |
| 1235 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; | 856 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; |
| 1236 if (layoutObject && m_frame->view()) { | 857 if (layoutObject && m_frame->view()) { |
| 1237 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); | 858 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); |
| 1238 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI
nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); | 859 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI
nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); |
| 1239 } | 860 } |
| 1240 | 861 |
| 1241 // During selection, use an I-beam no matter what we're over. | 862 // During selection, use an I-beam no matter what we're over. |
| 1242 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. | 863 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. |
| 1243 if (m_mousePressed && m_mouseDownMayStartSelect | 864 if (m_mousePressed && selectionController().mouseDownMayStartSelect() |
| 1244 && !m_mouseDownMayStartDrag | 865 && !m_mouseDownMayStartDrag |
| 1245 && m_frame->selection().isCaretOrRange() | 866 && m_frame->selection().isCaretOrRange() |
| 1246 && !m_capturingMouseEventsNode) { | 867 && !m_capturingMouseEventsNode) { |
| 1247 return iBeam; | 868 return iBeam; |
| 1248 } | 869 } |
| 1249 | 870 |
| 1250 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe
lection())) && !inResizer && !result.scrollbar()) | 871 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe
lection())) && !inResizer && !result.scrollbar()) |
| 1251 return iBeam; | 872 return iBeam; |
| 1252 return pointerCursor(); | 873 return pointerCursor(); |
| 1253 } | 874 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1270 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken =
gestureIndicator.currentToken(); | 891 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken =
gestureIndicator.currentToken(); |
| 1271 | 892 |
| 1272 cancelFakeMouseMoveEvent(); | 893 cancelFakeMouseMoveEvent(); |
| 1273 if (m_eventHandlerWillResetCapturingMouseEventsNode) | 894 if (m_eventHandlerWillResetCapturingMouseEventsNode) |
| 1274 m_capturingMouseEventsNode = nullptr; | 895 m_capturingMouseEventsNode = nullptr; |
| 1275 m_mousePressed = true; | 896 m_mousePressed = true; |
| 1276 m_capturesDragging = true; | 897 m_capturesDragging = true; |
| 1277 setLastKnownMousePosition(mouseEvent); | 898 setLastKnownMousePosition(mouseEvent); |
| 1278 m_mouseDownTimestamp = mouseEvent.timestamp(); | 899 m_mouseDownTimestamp = mouseEvent.timestamp(); |
| 1279 m_mouseDownMayStartDrag = false; | 900 m_mouseDownMayStartDrag = false; |
| 1280 m_mouseDownMayStartSelect = false; | 901 selectionController().setMouseDownMayStartSelect(false); |
| 1281 m_mouseDownMayStartAutoscroll = false; | 902 m_mouseDownMayStartAutoscroll = false; |
| 1282 if (FrameView* view = m_frame->view()) { | 903 if (FrameView* view = m_frame->view()) { |
| 1283 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); | 904 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); |
| 1284 } else { | 905 } else { |
| 1285 invalidateClick(); | 906 invalidateClick(); |
| 1286 return false; | 907 return false; |
| 1287 } | 908 } |
| 1288 | 909 |
| 1289 HitTestRequest request(HitTestRequest::Active); | 910 HitTestRequest request(HitTestRequest::Active); |
| 1290 // Save the document point we generate in case the window coordinate is inva
lidated by what happens | 911 // 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... |
| 1641 | 1262 |
| 1642 bool swallowMouseReleaseEvent = false; | 1263 bool swallowMouseReleaseEvent = false; |
| 1643 if (!swallowMouseUpEvent) | 1264 if (!swallowMouseUpEvent) |
| 1644 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); | 1265 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); |
| 1645 | 1266 |
| 1646 invalidateClick(); | 1267 invalidateClick(); |
| 1647 | 1268 |
| 1648 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; | 1269 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; |
| 1649 } | 1270 } |
| 1650 | 1271 |
| 1651 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEve
nt) | |
| 1652 { | |
| 1653 // If the event was a middle click, attempt to copy global selection in afte
r | |
| 1654 // the newly set caret position. | |
| 1655 // | |
| 1656 // This code is called from either the mouse up or mouse down handling. Ther
e | |
| 1657 // is some debate about when the global selection is pasted: | |
| 1658 // xterm: pastes on up. | |
| 1659 // GTK: pastes on down. | |
| 1660 // Qt: pastes on up. | |
| 1661 // Firefox: pastes on up. | |
| 1662 // Chromium: pastes on up. | |
| 1663 // | |
| 1664 // There is something of a webcompat angle to this well, as highlighted by | |
| 1665 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on | |
| 1666 // down then the text is pasted just before the onclick handler runs and | |
| 1667 // clears the text box. So it's important this happens after the event | |
| 1668 // handlers have been fired. | |
| 1669 if (mouseEvent.type() != PlatformEvent::MouseReleased) | |
| 1670 return false; | |
| 1671 | |
| 1672 if (!m_frame->page()) | |
| 1673 return false; | |
| 1674 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); | |
| 1675 // Do not paste here if the focus was moved somewhere else. | |
| 1676 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele
ction()) | |
| 1677 return m_frame->editor().command("PasteGlobalSelection").execute(); | |
| 1678 | |
| 1679 return false; | |
| 1680 } | |
| 1681 | |
| 1682 | |
| 1683 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa
rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) | 1272 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa
rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
| 1684 { | 1273 { |
| 1685 FrameView* view = m_frame->view(); | 1274 FrameView* view = m_frame->view(); |
| 1686 | 1275 |
| 1687 // FIXME: We might want to dispatch a dragleave even if the view is gone. | 1276 // FIXME: We might want to dispatch a dragleave even if the view is gone. |
| 1688 if (!view) | 1277 if (!view) |
| 1689 return false; | 1278 return false; |
| 1690 | 1279 |
| 1691 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, | 1280 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, |
| 1692 true, true, m_frame->document()->domWindow(), | 1281 true, true, m_frame->document()->domWindow(), |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2508 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE
vent); | 2097 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE
vent); |
| 2509 m_mouseDownMayStartDrag = true; | 2098 m_mouseDownMayStartDrag = true; |
| 2510 dragState().m_dragSrc = nullptr; | 2099 dragState().m_dragSrc = nullptr; |
| 2511 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos
ition()); | 2100 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos
ition()); |
| 2512 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); | 2101 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
| 2513 if (handleDrag(mev, DragInitiator::Touch)) { | 2102 if (handleDrag(mev, DragInitiator::Touch)) { |
| 2514 m_longTapShouldInvokeContextMenu = true; | 2103 m_longTapShouldInvokeContextMenu = true; |
| 2515 return true; | 2104 return true; |
| 2516 } | 2105 } |
| 2517 } | 2106 } |
| 2518 #if OS(ANDROID) | 2107 |
| 2519 bool shouldLongPressSelectWord = true; | 2108 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po
sition()); |
| 2520 #else | 2109 HitTestResult result = hitTestResultAtPoint(hitTestPoint); |
| 2521 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()-
>touchEditingEnabled(); | 2110 if (selectionController().handleGestureLongPress(gestureEvent, result)) { |
| 2522 #endif | 2111 focusDocumentView(); |
| 2523 if (shouldLongPressSelectWord) { | 2112 return true; |
| 2524 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEven
t.position()); | |
| 2525 HitTestResult result = hitTestResultAtPoint(hitTestPoint); | |
| 2526 Node* innerNode = result.innerNode(); | |
| 2527 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable()
|| innerNode->isTextNode() | |
| 2528 #if OS(ANDROID) | |
| 2529 || innerNode->canStartSelection() | |
| 2530 #endif | |
| 2531 )) { | |
| 2532 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitesp
ace); | |
| 2533 if (m_frame->selection().isRange()) { | |
| 2534 focusDocumentView(); | |
| 2535 return true; | |
| 2536 } | |
| 2537 } | |
| 2538 } | 2113 } |
| 2114 |
| 2539 return sendContextMenuEventForGesture(targetedEvent); | 2115 return sendContextMenuEventForGesture(targetedEvent); |
| 2540 } | 2116 } |
| 2541 | 2117 |
| 2542 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) | 2118 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) |
| 2543 { | 2119 { |
| 2544 #if !OS(ANDROID) | 2120 #if !OS(ANDROID) |
| 2545 if (m_longTapShouldInvokeContextMenu) { | 2121 if (m_longTapShouldInvokeContextMenu) { |
| 2546 m_longTapShouldInvokeContextMenu = false; | 2122 m_longTapShouldInvokeContextMenu = false; |
| 2547 return sendContextMenuEventForGesture(targetedEvent); | 2123 return sendContextMenuEventForGesture(targetedEvent); |
| 2548 } | 2124 } |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3034 FrameView* v = m_frame->view(); | 2610 FrameView* v = m_frame->view(); |
| 3035 if (!v) | 2611 if (!v) |
| 3036 return false; | 2612 return false; |
| 3037 | 2613 |
| 3038 // Clear mouse press state to avoid initiating a drag while context menu is
up. | 2614 // Clear mouse press state to avoid initiating a drag while context menu is
up. |
| 3039 m_mousePressed = false; | 2615 m_mousePressed = false; |
| 3040 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); | 2616 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); |
| 3041 HitTestRequest request(HitTestRequest::Active); | 2617 HitTestRequest request(HitTestRequest::Active); |
| 3042 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re
quest, positionInContents, event); | 2618 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re
quest, positionInContents, event); |
| 3043 | 2619 |
| 3044 if (!m_frame->selection().contains(positionInContents) | 2620 selectionController().sendContextMenuEvent(mev, positionInContents); |
| 3045 && !mev.scrollbar() | |
| 3046 // FIXME: In the editable case, word selection sometimes selects content
that isn't underneath the mouse. | |
| 3047 // If the selection is non-editable, we do word selection to make it eas
ier to use the contextual menu items | |
| 3048 // available for text selections. But only if we're above text. | |
| 3049 && (m_frame->selection().isContentEditable() || (mev.innerNode() && mev.
innerNode()->isTextNode()))) { | |
| 3050 m_mouseDownMayStartSelect = true; // context menu events are always allo
wed to perform a selection | |
| 3051 | |
| 3052 if (mev.hitTestResult().isMisspelled()) | |
| 3053 selectClosestMisspellingFromMouseEvent(mev); | |
| 3054 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick(
)) | |
| 3055 selectClosestWordOrLinkFromMouseEvent(mev); | |
| 3056 } | |
| 3057 | 2621 |
| 3058 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode()
; | 2622 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode()
; |
| 3059 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event
, false); | 2623 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event
, false); |
| 3060 } | 2624 } |
| 3061 | 2625 |
| 3062 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) | 2626 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
| 3063 { | 2627 { |
| 3064 FrameView* view = m_frame->view(); | 2628 FrameView* view = m_frame->view(); |
| 3065 if (!view) | 2629 if (!view) |
| 3066 return false; | 2630 return false; |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3555 dragState().m_dragSrc = m_frame->page()->dragController().draggableN
ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); | 3119 dragState().m_dragSrc = m_frame->page()->dragController().draggableN
ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); |
| 3556 } else { | 3120 } else { |
| 3557 dragState().m_dragSrc = nullptr; | 3121 dragState().m_dragSrc = nullptr; |
| 3558 } | 3122 } |
| 3559 | 3123 |
| 3560 if (!dragState().m_dragSrc) | 3124 if (!dragState().m_dragSrc) |
| 3561 m_mouseDownMayStartDrag = false; // no element is draggable | 3125 m_mouseDownMayStartDrag = false; // no element is draggable |
| 3562 } | 3126 } |
| 3563 | 3127 |
| 3564 if (!m_mouseDownMayStartDrag) | 3128 if (!m_mouseDownMayStartDrag) |
| 3565 return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() &
& !m_mouseDownMayStartAutoscroll; | 3129 return initiator == DragInitiator::Mouse && !selectionController().mouse
DownMayStartSelect() && !m_mouseDownMayStartAutoscroll; |
| 3566 | 3130 |
| 3567 // We are starting a text/image/url drag, so the cursor should be an arrow | 3131 // We are starting a text/image/url drag, so the cursor should be an arrow |
| 3568 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d
rop (default to pointer). | 3132 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d
rop (default to pointer). |
| 3569 m_frame->view()->setCursor(pointerCursor()); | 3133 m_frame->view()->setCursor(pointerCursor()); |
| 3570 | 3134 |
| 3571 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event
().position())) | 3135 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event
().position())) |
| 3572 return true; | 3136 return true; |
| 3573 | 3137 |
| 3574 // Once we're past the hysteresis point, we don't want to treat this gesture
as a click | 3138 // Once we're past the hysteresis point, we don't want to treat this gesture
as a click |
| 3575 invalidateClick(); | 3139 invalidateClick(); |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4140 | 3704 |
| 4141 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) | 3705 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
| 4142 { | 3706 { |
| 4143 m_mousePositionIsUnknown = false; | 3707 m_mousePositionIsUnknown = false; |
| 4144 m_lastKnownMousePosition = event.position(); | 3708 m_lastKnownMousePosition = event.position(); |
| 4145 m_lastKnownMouseGlobalPosition = event.globalPosition(); | 3709 m_lastKnownMouseGlobalPosition = event.globalPosition(); |
| 4146 } | 3710 } |
| 4147 | 3711 |
| 4148 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m
ev, LocalFrame* subframe) | 3712 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m
ev, LocalFrame* subframe) |
| 4149 { | 3713 { |
| 4150 // If we're clicking into a frame that is selected, the frame will appear | 3714 selectionController().passMousePressEventToSubframe(mev); |
| 4151 // greyed out even though we're clicking on the selection. This looks | |
| 4152 // really strange (having the whole frame be greyed out), so we deselect the | |
| 4153 // selection. | |
| 4154 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | |
| 4155 if (m_frame->selection().contains(p)) { | |
| 4156 VisiblePosition visiblePos( | |
| 4157 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint()))
; | |
| 4158 VisibleSelection newSelection(visiblePos); | |
| 4159 m_frame->selection().setSelection(newSelection); | |
| 4160 } | |
| 4161 | |
| 4162 subframe->eventHandler().handleMousePressEvent(mev.event()); | 3715 subframe->eventHandler().handleMousePressEvent(mev.event()); |
| 4163 return true; | 3716 return true; |
| 4164 } | 3717 } |
| 4165 | 3718 |
| 4166 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me
v, LocalFrame* subframe, HitTestResult* hoveredNode) | 3719 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me
v, LocalFrame* subframe, HitTestResult* hoveredNode) |
| 4167 { | 3720 { |
| 4168 if (m_mouseDownMayStartDrag) | 3721 if (m_mouseDownMayStartDrag) |
| 4169 return false; | 3722 return false; |
| 4170 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod
e); | 3723 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod
e); |
| 4171 return true; | 3724 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4203 unsigned EventHandler::accessKeyModifiers() | 3756 unsigned EventHandler::accessKeyModifiers() |
| 4204 { | 3757 { |
| 4205 #if OS(MACOSX) | 3758 #if OS(MACOSX) |
| 4206 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; | 3759 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; |
| 4207 #else | 3760 #else |
| 4208 return PlatformEvent::AltKey; | 3761 return PlatformEvent::AltKey; |
| 4209 #endif | 3762 #endif |
| 4210 } | 3763 } |
| 4211 | 3764 |
| 4212 } // namespace blink | 3765 } // namespace blink |
| OLD | NEW |