| 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/page/EventHandler.h" | 29 #include "core/page/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" |
| 37 #include "core/dom/TouchList.h" | 38 #include "core/dom/TouchList.h" |
| 38 #include "core/dom/shadow/ComposedTreeTraversal.h" | 39 #include "core/dom/shadow/ComposedTreeTraversal.h" |
| 39 #include "core/dom/shadow/ShadowRoot.h" | 40 #include "core/dom/shadow/ShadowRoot.h" |
| 40 #include "core/editing/Editor.h" | 41 #include "core/editing/Editor.h" |
| 41 #include "core/editing/FrameSelection.h" | 42 #include "core/editing/FrameSelection.h" |
| 42 #include "core/editing/SelectionController.h" | 43 #include "core/editing/htmlediting.h" |
| 44 #include "core/editing/iterators/TextIterator.h" |
| 43 #include "core/events/EventPath.h" | 45 #include "core/events/EventPath.h" |
| 44 #include "core/events/KeyboardEvent.h" | 46 #include "core/events/KeyboardEvent.h" |
| 45 #include "core/events/MouseEvent.h" | 47 #include "core/events/MouseEvent.h" |
| 46 #include "core/events/TextEvent.h" | 48 #include "core/events/TextEvent.h" |
| 47 #include "core/events/TouchEvent.h" | 49 #include "core/events/TouchEvent.h" |
| 48 #include "core/events/WheelEvent.h" | 50 #include "core/events/WheelEvent.h" |
| 49 #include "core/fetch/ImageResource.h" | 51 #include "core/fetch/ImageResource.h" |
| 50 #include "core/frame/EventHandlerRegistry.h" | 52 #include "core/frame/EventHandlerRegistry.h" |
| 51 #include "core/frame/FrameHost.h" | 53 #include "core/frame/FrameHost.h" |
| 52 #include "core/frame/FrameView.h" | 54 #include "core/frame/FrameView.h" |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 | 213 |
| 212 // FIXME: we should exclude the document in some cases, as part | 214 // FIXME: we should exclude the document in some cases, as part |
| 213 // of crbug.com/410974. | 215 // of crbug.com/410974. |
| 214 scrollChain.prepend(frame.document()->documentElement()); | 216 scrollChain.prepend(frame.document()->documentElement()); |
| 215 } | 217 } |
| 216 | 218 |
| 217 EventHandler::EventHandler(LocalFrame* frame) | 219 EventHandler::EventHandler(LocalFrame* frame) |
| 218 : m_frame(frame) | 220 : m_frame(frame) |
| 219 , m_mousePressed(false) | 221 , m_mousePressed(false) |
| 220 , m_capturesDragging(false) | 222 , m_capturesDragging(false) |
| 223 , m_mouseDownMayStartSelect(false) |
| 221 , m_mouseDownMayStartDrag(false) | 224 , m_mouseDownMayStartDrag(false) |
| 222 , m_selectionController(SelectionController::create(frame)) | 225 , m_mouseDownWasSingleClickInSelection(false) |
| 226 , m_selectionInitiationState(HaveNotStartedSelection) |
| 223 , m_hoverTimer(this, &EventHandler::hoverTimerFired) | 227 , m_hoverTimer(this, &EventHandler::hoverTimerFired) |
| 224 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) | 228 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) |
| 225 , m_mouseDownMayStartAutoscroll(false) | 229 , m_mouseDownMayStartAutoscroll(false) |
| 226 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire
d) | 230 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire
d) |
| 227 , m_svgPan(false) | 231 , m_svgPan(false) |
| 228 , m_resizeScrollableArea(nullptr) | 232 , m_resizeScrollableArea(nullptr) |
| 229 , m_eventHandlerWillResetCapturingMouseEventsNode(0) | 233 , m_eventHandlerWillResetCapturingMouseEventsNode(0) |
| 230 , m_clickCount(0) | 234 , m_clickCount(0) |
| 231 , m_shouldOnlyFireDragOverEvent(false) | 235 , m_shouldOnlyFireDragOverEvent(false) |
| 232 , m_mousePositionIsUnknown(true) | 236 , m_mousePositionIsUnknown(true) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 262 visitor->trace(m_frameSetBeingResized); | 266 visitor->trace(m_frameSetBeingResized); |
| 263 visitor->trace(m_latchedWheelEventNode); | 267 visitor->trace(m_latchedWheelEventNode); |
| 264 visitor->trace(m_previousWheelScrolledNode); | 268 visitor->trace(m_previousWheelScrolledNode); |
| 265 visitor->trace(m_scrollbarHandlingScrollGesture); | 269 visitor->trace(m_scrollbarHandlingScrollGesture); |
| 266 visitor->trace(m_targetForTouchID); | 270 visitor->trace(m_targetForTouchID); |
| 267 visitor->trace(m_touchSequenceDocument); | 271 visitor->trace(m_touchSequenceDocument); |
| 268 visitor->trace(m_scrollGestureHandlingNode); | 272 visitor->trace(m_scrollGestureHandlingNode); |
| 269 visitor->trace(m_previousGestureScrolledNode); | 273 visitor->trace(m_previousGestureScrolledNode); |
| 270 visitor->trace(m_lastDeferredTapElement); | 274 visitor->trace(m_lastDeferredTapElement); |
| 271 visitor->trace(m_currentScrollChain); | 275 visitor->trace(m_currentScrollChain); |
| 272 visitor->trace(m_selectionController); | |
| 273 #endif | 276 #endif |
| 274 } | 277 } |
| 275 | 278 |
| 276 DragState& EventHandler::dragState() | 279 DragState& EventHandler::dragState() |
| 277 { | 280 { |
| 278 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); | 281 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); |
| 279 return *state; | 282 return *state; |
| 280 } | 283 } |
| 281 | 284 |
| 282 void EventHandler::clear() | 285 void EventHandler::clear() |
| (...skipping 24 matching lines...) Expand all Loading... |
| 307 m_previousWheelScrolledNode = nullptr; | 310 m_previousWheelScrolledNode = nullptr; |
| 308 m_targetForTouchID.clear(); | 311 m_targetForTouchID.clear(); |
| 309 m_touchSequenceDocument.clear(); | 312 m_touchSequenceDocument.clear(); |
| 310 m_touchSequenceUserGestureToken.clear(); | 313 m_touchSequenceUserGestureToken.clear(); |
| 311 m_scrollGestureHandlingNode = nullptr; | 314 m_scrollGestureHandlingNode = nullptr; |
| 312 m_lastGestureScrollOverWidget = false; | 315 m_lastGestureScrollOverWidget = false; |
| 313 m_previousGestureScrolledNode = nullptr; | 316 m_previousGestureScrolledNode = nullptr; |
| 314 m_scrollbarHandlingScrollGesture = nullptr; | 317 m_scrollbarHandlingScrollGesture = nullptr; |
| 315 m_maxMouseMovedDuration = 0; | 318 m_maxMouseMovedDuration = 0; |
| 316 m_touchPressed = false; | 319 m_touchPressed = false; |
| 320 m_mouseDownMayStartSelect = false; |
| 317 m_mouseDownMayStartDrag = false; | 321 m_mouseDownMayStartDrag = false; |
| 318 m_lastShowPressTimestamp = 0; | 322 m_lastShowPressTimestamp = 0; |
| 319 m_lastDeferredTapElement = nullptr; | 323 m_lastDeferredTapElement = nullptr; |
| 320 m_eventHandlerWillResetCapturingMouseEventsNode = false; | 324 m_eventHandlerWillResetCapturingMouseEventsNode = false; |
| 325 m_mouseDownWasSingleClickInSelection = false; |
| 326 m_selectionInitiationState = HaveNotStartedSelection; |
| 321 m_mouseDownMayStartAutoscroll = false; | 327 m_mouseDownMayStartAutoscroll = false; |
| 322 m_svgPan = false; | 328 m_svgPan = false; |
| 323 m_mouseDownPos = IntPoint(); | 329 m_mouseDownPos = IntPoint(); |
| 324 m_mouseDownTimestamp = 0; | 330 m_mouseDownTimestamp = 0; |
| 325 m_longTapShouldInvokeContextMenu = false; | 331 m_longTapShouldInvokeContextMenu = false; |
| 326 m_dragStartPos = LayoutPoint(); | 332 m_dragStartPos = LayoutPoint(); |
| 327 m_offsetFromResizeCorner = LayoutSize(); | 333 m_offsetFromResizeCorner = LayoutSize(); |
| 328 m_mouseDown = PlatformMouseEvent(); | 334 m_mouseDown = PlatformMouseEvent(); |
| 329 } | 335 } |
| 330 | 336 |
| 331 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) | 337 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) |
| 332 { | 338 { |
| 333 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { | 339 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { |
| 334 // We don't dispatch click events if the mousedown node is removed | 340 // We don't dispatch click events if the mousedown node is removed |
| 335 // before a mouseup event. It is compatible with IE and Firefox. | 341 // before a mouseup event. It is compatible with IE and Firefox. |
| 336 m_clickNode = nullptr; | 342 m_clickNode = nullptr; |
| 337 } | 343 } |
| 338 } | 344 } |
| 339 | 345 |
| 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 |
| 340 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
nt) | 598 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
nt) |
| 341 { | 599 { |
| 342 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); | 600 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); |
| 343 | 601 |
| 344 // Reset drag state. | 602 // Reset drag state. |
| 345 dragState().m_dragSrc = nullptr; | 603 dragState().m_dragSrc = nullptr; |
| 346 | 604 |
| 347 cancelFakeMouseMoveEvent(); | 605 cancelFakeMouseMoveEvent(); |
| 348 | 606 |
| 349 m_frame->document()->updateLayoutIgnorePendingStylesheets(); | 607 m_frame->document()->updateLayoutIgnorePendingStylesheets(); |
| 350 | 608 |
| 351 if (FrameView* frameView = m_frame->view()) { | 609 if (FrameView* frameView = m_frame->view()) { |
| 352 if (frameView->isPointInScrollbarCorner(event.event().position())) | 610 if (frameView->isPointInScrollbarCorner(event.event().position())) |
| 353 return false; | 611 return false; |
| 354 } | 612 } |
| 355 | 613 |
| 356 bool singleClick = event.event().clickCount() <= 1; | 614 bool singleClick = event.event().clickCount() <= 1; |
| 357 | 615 |
| 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 |
| 358 m_mouseDownMayStartDrag = singleClick; | 620 m_mouseDownMayStartDrag = singleClick; |
| 359 | 621 |
| 360 selectionController().handleMousePressEvent(event); | 622 m_mouseDownWasSingleClickInSelection = false; |
| 361 | 623 |
| 362 m_mouseDown = event.event(); | 624 m_mouseDown = event.event(); |
| 363 | 625 |
| 364 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx
tensions().zoomAndPanEnabled()) { | 626 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx
tensions().zoomAndPanEnabled()) { |
| 365 if (event.event().shiftKey() && singleClick) { | 627 if (event.event().shiftKey() && singleClick) { |
| 366 m_svgPan = true; | 628 m_svgPan = true; |
| 367 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()-
>rootFrameToContents(event.event().position())); | 629 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()-
>rootFrameToContents(event.event().position())); |
| 368 return true; | 630 return true; |
| 369 } | 631 } |
| 370 } | 632 } |
| 371 | 633 |
| 372 // We don't do this at the start of mouse down handling, | 634 // We don't do this at the start of mouse down handling, |
| 373 // because we don't want to do it until we know we didn't hit a widget. | 635 // because we don't want to do it until we know we didn't hit a widget. |
| 374 if (singleClick) | 636 if (singleClick) |
| 375 focusDocumentView(); | 637 focusDocumentView(); |
| 376 | 638 |
| 377 Node* innerNode = event.innerNode(); | 639 Node* innerNode = event.innerNode(); |
| 378 | 640 |
| 379 m_mousePressNode = innerNode; | 641 m_mousePressNode = innerNode; |
| 380 m_dragStartPos = event.event().position(); | 642 m_dragStartPos = event.event().position(); |
| 381 | 643 |
| 382 bool swallowEvent = false; | 644 bool swallowEvent = false; |
| 383 m_mousePressed = true; | 645 m_mousePressed = true; |
| 384 selectionController().initializeSelectionState(); | 646 m_selectionInitiationState = HaveNotStartedSelection; |
| 385 | 647 |
| 386 if (event.event().clickCount() == 2) | 648 if (event.event().clickCount() == 2) |
| 387 swallowEvent = selectionController().handleMousePressEventDoubleClick(ev
ent); | 649 swallowEvent = handleMousePressEventDoubleClick(event); |
| 388 else if (event.event().clickCount() >= 3) | 650 else if (event.event().clickCount() >= 3) |
| 389 swallowEvent = selectionController().handleMousePressEventTripleClick(ev
ent); | 651 swallowEvent = handleMousePressEventTripleClick(event); |
| 390 else | 652 else |
| 391 swallowEvent = selectionController().handleMousePressEventSingleClick(ev
ent); | 653 swallowEvent = handleMousePressEventSingleClick(event); |
| 392 | 654 |
| 393 m_mouseDownMayStartAutoscroll = selectionController().mouseDownMayStartSelec
t() | 655 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect |
| 394 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod
e->layoutBox()->canBeProgramaticallyScrolled()); | 656 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod
e->layoutBox()->canBeProgramaticallyScrolled()); |
| 395 | 657 |
| 396 return swallowEvent; | 658 return swallowEvent; |
| 397 } | 659 } |
| 398 | 660 |
| 399 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
vent) | 661 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e
vent) |
| 400 { | 662 { |
| 401 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); | 663 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); |
| 402 | 664 |
| 403 // While resetting m_mousePressed here may seem out of place, it turns out | 665 // 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... |
| 440 | 702 |
| 441 m_mouseDownMayStartDrag = false; | 703 m_mouseDownMayStartDrag = false; |
| 442 | 704 |
| 443 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { | 705 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { |
| 444 if (AutoscrollController* controller = autoscrollController()) { | 706 if (AutoscrollController* controller = autoscrollController()) { |
| 445 controller->startAutoscrollForSelection(layoutObject); | 707 controller->startAutoscrollForSelection(layoutObject); |
| 446 m_mouseDownMayStartAutoscroll = false; | 708 m_mouseDownMayStartAutoscroll = false; |
| 447 } | 709 } |
| 448 } | 710 } |
| 449 | 711 |
| 450 selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragS
tartPos, m_mousePressNode.get(), m_lastKnownMousePosition); | 712 if (m_selectionInitiationState != ExtendedSelection) { |
| 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()); |
| 451 return true; | 720 return true; |
| 452 } | 721 } |
| 453 | 722 |
| 454 void EventHandler::updateSelectionForMouseDrag() | 723 void EventHandler::updateSelectionForMouseDrag() |
| 455 { | 724 { |
| 456 selectionController().updateSelectionForMouseDrag(m_mousePressNode.get(), m_
dragStartPos, m_lastKnownMouseGlobalPosition); | 725 FrameView* view = m_frame->view(); |
| 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); |
| 457 } | 803 } |
| 458 | 804 |
| 459 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
vent) | 805 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
vent) |
| 460 { | 806 { |
| 461 AutoscrollController* controller = autoscrollController(); | 807 AutoscrollController* controller = autoscrollController(); |
| 462 if (controller && controller->autoscrollInProgress()) | 808 if (controller && controller->autoscrollInProgress()) |
| 463 stopAutoscroll(); | 809 stopAutoscroll(); |
| 464 | 810 |
| 465 // Used to prevent mouseMoveEvent from initiating a drag before | 811 // Used to prevent mouseMoveEvent from initiating a drag before |
| 466 // the mouse is pressed again. | 812 // the mouse is pressed again. |
| 467 m_mousePressed = false; | 813 m_mousePressed = false; |
| 468 m_capturesDragging = false; | 814 m_capturesDragging = false; |
| 469 m_mouseDownMayStartDrag = false; | 815 m_mouseDownMayStartDrag = false; |
| 816 m_mouseDownMayStartSelect = false; |
| 470 m_mouseDownMayStartAutoscroll = false; | 817 m_mouseDownMayStartAutoscroll = false; |
| 471 | 818 |
| 472 return selectionController().handleMouseReleaseEvent(event, m_dragStartPos); | 819 bool handled = false; |
| 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; |
| 473 } | 852 } |
| 474 | 853 |
| 475 #if OS(WIN) | 854 #if OS(WIN) |
| 476 | 855 |
| 477 void EventHandler::startPanScrolling(LayoutObject* layoutObject) | 856 void EventHandler::startPanScrolling(LayoutObject* layoutObject) |
| 478 { | 857 { |
| 479 if (!layoutObject->isBox()) | 858 if (!layoutObject->isBox()) |
| 480 return; | 859 return; |
| 481 AutoscrollController* controller = autoscrollController(); | 860 AutoscrollController* controller = autoscrollController(); |
| 482 if (!controller) | 861 if (!controller) |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 | 1227 |
| 849 bool inResizer = false; | 1228 bool inResizer = false; |
| 850 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; | 1229 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; |
| 851 if (layoutObject && m_frame->view()) { | 1230 if (layoutObject && m_frame->view()) { |
| 852 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); | 1231 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); |
| 853 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI
nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); | 1232 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI
nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); |
| 854 } | 1233 } |
| 855 | 1234 |
| 856 // During selection, use an I-beam no matter what we're over. | 1235 // During selection, use an I-beam no matter what we're over. |
| 857 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. | 1236 // If a drag may be starting or we're capturing mouse events for a particula
r node, don't treat this as a selection. |
| 858 if (m_mousePressed && selectionController().mouseDownMayStartSelect() | 1237 if (m_mousePressed && m_mouseDownMayStartSelect |
| 859 && !m_mouseDownMayStartDrag | 1238 && !m_mouseDownMayStartDrag |
| 860 && m_frame->selection().isCaretOrRange() | 1239 && m_frame->selection().isCaretOrRange() |
| 861 && !m_capturingMouseEventsNode) { | 1240 && !m_capturingMouseEventsNode) { |
| 862 return iBeam; | 1241 return iBeam; |
| 863 } | 1242 } |
| 864 | 1243 |
| 865 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe
lection())) && !inResizer && !result.scrollbar()) | 1244 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe
lection())) && !inResizer && !result.scrollbar()) |
| 866 return iBeam; | 1245 return iBeam; |
| 867 return pointerCursor(); | 1246 return pointerCursor(); |
| 868 } | 1247 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 885 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken =
gestureIndicator.currentToken(); | 1264 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken =
gestureIndicator.currentToken(); |
| 886 | 1265 |
| 887 cancelFakeMouseMoveEvent(); | 1266 cancelFakeMouseMoveEvent(); |
| 888 if (m_eventHandlerWillResetCapturingMouseEventsNode) | 1267 if (m_eventHandlerWillResetCapturingMouseEventsNode) |
| 889 m_capturingMouseEventsNode = nullptr; | 1268 m_capturingMouseEventsNode = nullptr; |
| 890 m_mousePressed = true; | 1269 m_mousePressed = true; |
| 891 m_capturesDragging = true; | 1270 m_capturesDragging = true; |
| 892 setLastKnownMousePosition(mouseEvent); | 1271 setLastKnownMousePosition(mouseEvent); |
| 893 m_mouseDownTimestamp = mouseEvent.timestamp(); | 1272 m_mouseDownTimestamp = mouseEvent.timestamp(); |
| 894 m_mouseDownMayStartDrag = false; | 1273 m_mouseDownMayStartDrag = false; |
| 895 selectionController().setMouseDownMayStartSelect(false); | 1274 m_mouseDownMayStartSelect = false; |
| 896 m_mouseDownMayStartAutoscroll = false; | 1275 m_mouseDownMayStartAutoscroll = false; |
| 897 if (FrameView* view = m_frame->view()) { | 1276 if (FrameView* view = m_frame->view()) { |
| 898 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); | 1277 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); |
| 899 } else { | 1278 } else { |
| 900 invalidateClick(); | 1279 invalidateClick(); |
| 901 return false; | 1280 return false; |
| 902 } | 1281 } |
| 903 | 1282 |
| 904 HitTestRequest request(HitTestRequest::Active); | 1283 HitTestRequest request(HitTestRequest::Active); |
| 905 // Save the document point we generate in case the window coordinate is inva
lidated by what happens | 1284 // Save the document point we generate in case the window coordinate is inva
lidated by what happens |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 | 1636 |
| 1258 bool swallowMouseReleaseEvent = false; | 1637 bool swallowMouseReleaseEvent = false; |
| 1259 if (!swallowMouseUpEvent) | 1638 if (!swallowMouseUpEvent) |
| 1260 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); | 1639 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); |
| 1261 | 1640 |
| 1262 invalidateClick(); | 1641 invalidateClick(); |
| 1263 | 1642 |
| 1264 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; | 1643 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; |
| 1265 } | 1644 } |
| 1266 | 1645 |
| 1646 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEve
nt) |
| 1647 { |
| 1648 // If the event was a middle click, attempt to copy global selection in afte
r |
| 1649 // the newly set caret position. |
| 1650 // |
| 1651 // This code is called from either the mouse up or mouse down handling. Ther
e |
| 1652 // is some debate about when the global selection is pasted: |
| 1653 // xterm: pastes on up. |
| 1654 // GTK: pastes on down. |
| 1655 // Qt: pastes on up. |
| 1656 // Firefox: pastes on up. |
| 1657 // Chromium: pastes on up. |
| 1658 // |
| 1659 // There is something of a webcompat angle to this well, as highlighted by |
| 1660 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on |
| 1661 // down then the text is pasted just before the onclick handler runs and |
| 1662 // clears the text box. So it's important this happens after the event |
| 1663 // handlers have been fired. |
| 1664 if (mouseEvent.type() != PlatformEvent::MouseReleased) |
| 1665 return false; |
| 1666 |
| 1667 if (!m_frame->page()) |
| 1668 return false; |
| 1669 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); |
| 1670 // Do not paste here if the focus was moved somewhere else. |
| 1671 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele
ction()) |
| 1672 return m_frame->editor().command("PasteGlobalSelection").execute(); |
| 1673 |
| 1674 return false; |
| 1675 } |
| 1676 |
| 1677 |
| 1267 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa
rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) | 1678 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa
rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
| 1268 { | 1679 { |
| 1269 FrameView* view = m_frame->view(); | 1680 FrameView* view = m_frame->view(); |
| 1270 | 1681 |
| 1271 // FIXME: We might want to dispatch a dragleave even if the view is gone. | 1682 // FIXME: We might want to dispatch a dragleave even if the view is gone. |
| 1272 if (!view) | 1683 if (!view) |
| 1273 return false; | 1684 return false; |
| 1274 | 1685 |
| 1275 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, | 1686 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, |
| 1276 true, true, m_frame->document()->domWindow(), | 1687 true, true, m_frame->document()->domWindow(), |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE
vent); | 2503 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE
vent); |
| 2093 m_mouseDownMayStartDrag = true; | 2504 m_mouseDownMayStartDrag = true; |
| 2094 dragState().m_dragSrc = nullptr; | 2505 dragState().m_dragSrc = nullptr; |
| 2095 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos
ition()); | 2506 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos
ition()); |
| 2096 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); | 2507 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
| 2097 if (handleDrag(mev, DragInitiator::Touch)) { | 2508 if (handleDrag(mev, DragInitiator::Touch)) { |
| 2098 m_longTapShouldInvokeContextMenu = true; | 2509 m_longTapShouldInvokeContextMenu = true; |
| 2099 return true; | 2510 return true; |
| 2100 } | 2511 } |
| 2101 } | 2512 } |
| 2102 | 2513 #if OS(ANDROID) |
| 2103 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po
sition()); | 2514 bool shouldLongPressSelectWord = true; |
| 2104 HitTestResult result = hitTestResultAtPoint(hitTestPoint); | 2515 #else |
| 2105 if (selectionController().handleGestureLongPress(gestureEvent, result)) | 2516 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()-
>touchEditingEnabled(); |
| 2106 return true; | 2517 #endif |
| 2107 | 2518 if (shouldLongPressSelectWord) { |
| 2519 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEven
t.position()); |
| 2520 HitTestResult result = hitTestResultAtPoint(hitTestPoint); |
| 2521 Node* innerNode = result.innerNode(); |
| 2522 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable()
|| innerNode->isTextNode() |
| 2523 #if OS(ANDROID) |
| 2524 || innerNode->canStartSelection() |
| 2525 #endif |
| 2526 )) { |
| 2527 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitesp
ace); |
| 2528 if (m_frame->selection().isRange()) { |
| 2529 focusDocumentView(); |
| 2530 return true; |
| 2531 } |
| 2532 } |
| 2533 } |
| 2108 return sendContextMenuEventForGesture(targetedEvent); | 2534 return sendContextMenuEventForGesture(targetedEvent); |
| 2109 } | 2535 } |
| 2110 | 2536 |
| 2111 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) | 2537 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta
rgetedEvent) |
| 2112 { | 2538 { |
| 2113 #if !OS(ANDROID) | 2539 #if !OS(ANDROID) |
| 2114 if (m_longTapShouldInvokeContextMenu) { | 2540 if (m_longTapShouldInvokeContextMenu) { |
| 2115 m_longTapShouldInvokeContextMenu = false; | 2541 m_longTapShouldInvokeContextMenu = false; |
| 2116 return sendContextMenuEventForGesture(targetedEvent); | 2542 return sendContextMenuEventForGesture(targetedEvent); |
| 2117 } | 2543 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 FrameView* v = m_frame->view(); | 3000 FrameView* v = m_frame->view(); |
| 2575 if (!v) | 3001 if (!v) |
| 2576 return false; | 3002 return false; |
| 2577 | 3003 |
| 2578 // Clear mouse press state to avoid initiating a drag while context menu is
up. | 3004 // Clear mouse press state to avoid initiating a drag while context menu is
up. |
| 2579 m_mousePressed = false; | 3005 m_mousePressed = false; |
| 2580 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); | 3006 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); |
| 2581 HitTestRequest request(HitTestRequest::Active); | 3007 HitTestRequest request(HitTestRequest::Active); |
| 2582 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re
quest, positionInContents, event); | 3008 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re
quest, positionInContents, event); |
| 2583 | 3009 |
| 2584 selectionController().prepareForContextMenu(mev, positionInContents); | 3010 if (!m_frame->selection().contains(positionInContents) |
| 3011 && !mev.scrollbar() |
| 3012 // FIXME: In the editable case, word selection sometimes selects content
that isn't underneath the mouse. |
| 3013 // If the selection is non-editable, we do word selection to make it eas
ier to use the contextual menu items |
| 3014 // available for text selections. But only if we're above text. |
| 3015 && (m_frame->selection().isContentEditable() || (mev.innerNode() && mev.
innerNode()->isTextNode()))) { |
| 3016 m_mouseDownMayStartSelect = true; // context menu events are always allo
wed to perform a selection |
| 3017 |
| 3018 if (mev.hitTestResult().isMisspelled()) |
| 3019 selectClosestMisspellingFromMouseEvent(mev); |
| 3020 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick(
)) |
| 3021 selectClosestWordOrLinkFromMouseEvent(mev); |
| 3022 } |
| 2585 | 3023 |
| 2586 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode()
; | 3024 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode()
; |
| 2587 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event
, false); | 3025 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event
, false); |
| 2588 } | 3026 } |
| 2589 | 3027 |
| 2590 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) | 3028 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
| 2591 { | 3029 { |
| 2592 FrameView* view = m_frame->view(); | 3030 FrameView* view = m_frame->view(); |
| 2593 if (!view) | 3031 if (!view) |
| 2594 return false; | 3032 return false; |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 dragState().m_dragSrc = m_frame->page()->dragController().draggableN
ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); | 3521 dragState().m_dragSrc = m_frame->page()->dragController().draggableN
ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); |
| 3084 } else { | 3522 } else { |
| 3085 dragState().m_dragSrc = nullptr; | 3523 dragState().m_dragSrc = nullptr; |
| 3086 } | 3524 } |
| 3087 | 3525 |
| 3088 if (!dragState().m_dragSrc) | 3526 if (!dragState().m_dragSrc) |
| 3089 m_mouseDownMayStartDrag = false; // no element is draggable | 3527 m_mouseDownMayStartDrag = false; // no element is draggable |
| 3090 } | 3528 } |
| 3091 | 3529 |
| 3092 if (!m_mouseDownMayStartDrag) | 3530 if (!m_mouseDownMayStartDrag) |
| 3093 return initiator == DragInitiator::Mouse && !selectionController().mouse
DownMayStartSelect() && !m_mouseDownMayStartAutoscroll; | 3531 return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() &
& !m_mouseDownMayStartAutoscroll; |
| 3094 | 3532 |
| 3095 // We are starting a text/image/url drag, so the cursor should be an arrow | 3533 // We are starting a text/image/url drag, so the cursor should be an arrow |
| 3096 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d
rop (default to pointer). | 3534 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d
rop (default to pointer). |
| 3097 m_frame->view()->setCursor(pointerCursor()); | 3535 m_frame->view()->setCursor(pointerCursor()); |
| 3098 | 3536 |
| 3099 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event
().position())) | 3537 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event
().position())) |
| 3100 return true; | 3538 return true; |
| 3101 | 3539 |
| 3102 // Once we're past the hysteresis point, we don't want to treat this gesture
as a click | 3540 // Once we're past the hysteresis point, we don't want to treat this gesture
as a click |
| 3103 invalidateClick(); | 3541 invalidateClick(); |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3668 | 4106 |
| 3669 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) | 4107 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
| 3670 { | 4108 { |
| 3671 m_mousePositionIsUnknown = false; | 4109 m_mousePositionIsUnknown = false; |
| 3672 m_lastKnownMousePosition = event.position(); | 4110 m_lastKnownMousePosition = event.position(); |
| 3673 m_lastKnownMouseGlobalPosition = event.globalPosition(); | 4111 m_lastKnownMouseGlobalPosition = event.globalPosition(); |
| 3674 } | 4112 } |
| 3675 | 4113 |
| 3676 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m
ev, LocalFrame* subframe) | 4114 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m
ev, LocalFrame* subframe) |
| 3677 { | 4115 { |
| 3678 selectionController().preparePassMousePressEventToSubframe(mev); | 4116 // If we're clicking into a frame that is selected, the frame will appear |
| 4117 // greyed out even though we're clicking on the selection. This looks |
| 4118 // really strange (having the whole frame be greyed out), so we deselect the |
| 4119 // selection. |
| 4120 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); |
| 4121 if (m_frame->selection().contains(p)) { |
| 4122 VisiblePosition visiblePos( |
| 4123 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint()))
; |
| 4124 VisibleSelection newSelection(visiblePos); |
| 4125 m_frame->selection().setSelection(newSelection); |
| 4126 } |
| 4127 |
| 3679 subframe->eventHandler().handleMousePressEvent(mev.event()); | 4128 subframe->eventHandler().handleMousePressEvent(mev.event()); |
| 3680 return true; | 4129 return true; |
| 3681 } | 4130 } |
| 3682 | 4131 |
| 3683 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me
v, LocalFrame* subframe, HitTestResult* hoveredNode) | 4132 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me
v, LocalFrame* subframe, HitTestResult* hoveredNode) |
| 3684 { | 4133 { |
| 3685 if (m_mouseDownMayStartDrag) | 4134 if (m_mouseDownMayStartDrag) |
| 3686 return false; | 4135 return false; |
| 3687 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod
e); | 4136 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod
e); |
| 3688 return true; | 4137 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3720 unsigned EventHandler::accessKeyModifiers() | 4169 unsigned EventHandler::accessKeyModifiers() |
| 3721 { | 4170 { |
| 3722 #if OS(MACOSX) | 4171 #if OS(MACOSX) |
| 3723 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; | 4172 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; |
| 3724 #else | 4173 #else |
| 3725 return PlatformEvent::AltKey; | 4174 return PlatformEvent::AltKey; |
| 3726 #endif | 4175 #endif |
| 3727 } | 4176 } |
| 3728 | 4177 |
| 3729 } // namespace blink | 4178 } // namespace blink |
| OLD | NEW |