Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. |
| 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 #include "config.h" | 28 #include "config.h" |
| 29 #include "core/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" | |
| 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 213 | 211 |
| 214 // FIXME: we should exclude the document in some cases, as part | 212 // FIXME: we should exclude the document in some cases, as part |
| 215 // of crbug.com/410974. | 213 // of crbug.com/410974. |
| 216 scrollChain.prepend(frame.document()->documentElement()); | 214 scrollChain.prepend(frame.document()->documentElement()); |
| 217 } | 215 } |
| 218 | 216 |
| 219 EventHandler::EventHandler(LocalFrame* frame) | 217 EventHandler::EventHandler(LocalFrame* frame) |
| 220 : m_frame(frame) | 218 : m_frame(frame) |
| 221 , m_mousePressed(false) | 219 , m_mousePressed(false) |
| 222 , m_capturesDragging(false) | 220 , m_capturesDragging(false) |
| 223 , m_mouseDownMayStartSelect(false) | |
| 224 , m_mouseDownMayStartDrag(false) | 221 , m_mouseDownMayStartDrag(false) |
| 225 , m_mouseDownWasSingleClickInSelection(false) | 222 , m_selectionController(SelectionController::create(frame)) |
| 226 , m_selectionInitiationState(HaveNotStartedSelection) | |
| 227 , m_hoverTimer(this, &EventHandler::hoverTimerFired) | 223 , m_hoverTimer(this, &EventHandler::hoverTimerFired) |
| 228 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) | 224 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) |
| 229 , m_mouseDownMayStartAutoscroll(false) | 225 , m_mouseDownMayStartAutoscroll(false) |
| 230 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) | 226 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) |
| 231 , m_svgPan(false) | 227 , m_svgPan(false) |
| 232 , m_resizeScrollableArea(nullptr) | 228 , m_resizeScrollableArea(nullptr) |
| 233 , m_eventHandlerWillResetCapturingMouseEventsNode(0) | 229 , m_eventHandlerWillResetCapturingMouseEventsNode(0) |
| 234 , m_clickCount(0) | 230 , m_clickCount(0) |
| 235 , m_shouldOnlyFireDragOverEvent(false) | 231 , m_shouldOnlyFireDragOverEvent(false) |
| 236 , m_mousePositionIsUnknown(true) | 232 , m_mousePositionIsUnknown(true) |
| (...skipping 29 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_lastKnownMouseGlobalPosition); |
|
Miyoung Shin(g)
2015/05/24 14:05:55
I figured out that I set the wrong |m_lastKnownMou
| |
| 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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1227 | 848 |
| 1228 bool inResizer = false; | 849 bool inResizer = false; |
| 1229 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; | 850 LayoutObject* layoutObject = node ? node->layoutObject() : nullptr; |
| 1230 if (layoutObject && m_frame->view()) { | 851 if (layoutObject && m_frame->view()) { |
| 1231 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); | 852 DeprecatedPaintLayer* layer = layoutObject->enclosingLayer(); |
| 1232 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); | 853 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); |
| 1233 } | 854 } |
| 1234 | 855 |
| 1235 // During selection, use an I-beam no matter what we're over. | 856 // During selection, use an I-beam no matter what we're over. |
| 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. | 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. |
| 1237 if (m_mousePressed && m_mouseDownMayStartSelect | 858 if (m_mousePressed && selectionController().mouseDownMayStartSelect() |
| 1238 && !m_mouseDownMayStartDrag | 859 && !m_mouseDownMayStartDrag |
| 1239 && m_frame->selection().isCaretOrRange() | 860 && m_frame->selection().isCaretOrRange() |
| 1240 && !m_capturingMouseEventsNode) { | 861 && !m_capturingMouseEventsNode) { |
| 1241 return iBeam; | 862 return iBeam; |
| 1242 } | 863 } |
| 1243 | 864 |
| 1244 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe lection())) && !inResizer && !result.scrollbar()) | 865 if ((editable || (layoutObject && layoutObject->isText() && node->canStartSe lection())) && !inResizer && !result.scrollbar()) |
| 1245 return iBeam; | 866 return iBeam; |
| 1246 return pointerCursor(); | 867 return pointerCursor(); |
| 1247 } | 868 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1264 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); | 885 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); |
| 1265 | 886 |
| 1266 cancelFakeMouseMoveEvent(); | 887 cancelFakeMouseMoveEvent(); |
| 1267 if (m_eventHandlerWillResetCapturingMouseEventsNode) | 888 if (m_eventHandlerWillResetCapturingMouseEventsNode) |
| 1268 m_capturingMouseEventsNode = nullptr; | 889 m_capturingMouseEventsNode = nullptr; |
| 1269 m_mousePressed = true; | 890 m_mousePressed = true; |
| 1270 m_capturesDragging = true; | 891 m_capturesDragging = true; |
| 1271 setLastKnownMousePosition(mouseEvent); | 892 setLastKnownMousePosition(mouseEvent); |
| 1272 m_mouseDownTimestamp = mouseEvent.timestamp(); | 893 m_mouseDownTimestamp = mouseEvent.timestamp(); |
| 1273 m_mouseDownMayStartDrag = false; | 894 m_mouseDownMayStartDrag = false; |
| 1274 m_mouseDownMayStartSelect = false; | 895 selectionController().setMouseDownMayStartSelect(false); |
| 1275 m_mouseDownMayStartAutoscroll = false; | 896 m_mouseDownMayStartAutoscroll = false; |
| 1276 if (FrameView* view = m_frame->view()) { | 897 if (FrameView* view = m_frame->view()) { |
| 1277 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); | 898 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); |
| 1278 } else { | 899 } else { |
| 1279 invalidateClick(); | 900 invalidateClick(); |
| 1280 return false; | 901 return false; |
| 1281 } | 902 } |
| 1282 | 903 |
| 1283 HitTestRequest request(HitTestRequest::Active); | 904 HitTestRequest request(HitTestRequest::Active); |
| 1284 // Save the document point we generate in case the window coordinate is inva lidated by what happens | 905 // 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... | |
| 1636 | 1257 |
| 1637 bool swallowMouseReleaseEvent = false; | 1258 bool swallowMouseReleaseEvent = false; |
| 1638 if (!swallowMouseUpEvent) | 1259 if (!swallowMouseUpEvent) |
| 1639 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); | 1260 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); |
| 1640 | 1261 |
| 1641 invalidateClick(); | 1262 invalidateClick(); |
| 1642 | 1263 |
| 1643 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; | 1264 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; |
| 1644 } | 1265 } |
| 1645 | 1266 |
| 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 | |
| 1678 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) | 1267 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) |
| 1679 { | 1268 { |
| 1680 FrameView* view = m_frame->view(); | 1269 FrameView* view = m_frame->view(); |
| 1681 | 1270 |
| 1682 // FIXME: We might want to dispatch a dragleave even if the view is gone. | 1271 // FIXME: We might want to dispatch a dragleave even if the view is gone. |
| 1683 if (!view) | 1272 if (!view) |
| 1684 return false; | 1273 return false; |
| 1685 | 1274 |
| 1686 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, | 1275 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, |
| 1687 true, true, m_frame->document()->domWindow(), | 1276 true, true, m_frame->document()->domWindow(), |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2503 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE vent); | 2092 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseDragE vent); |
| 2504 m_mouseDownMayStartDrag = true; | 2093 m_mouseDownMayStartDrag = true; |
| 2505 dragState().m_dragSrc = nullptr; | 2094 dragState().m_dragSrc = nullptr; |
| 2506 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos ition()); | 2095 m_mouseDownPos = m_frame->view()->rootFrameToContents(mouseDragEvent.pos ition()); |
| 2507 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); | 2096 RefPtrWillBeRawPtr<FrameView> protector(m_frame->view()); |
| 2508 if (handleDrag(mev, DragInitiator::Touch)) { | 2097 if (handleDrag(mev, DragInitiator::Touch)) { |
| 2509 m_longTapShouldInvokeContextMenu = true; | 2098 m_longTapShouldInvokeContextMenu = true; |
| 2510 return true; | 2099 return true; |
| 2511 } | 2100 } |
| 2512 } | 2101 } |
| 2513 #if OS(ANDROID) | 2102 |
| 2514 bool shouldLongPressSelectWord = true; | 2103 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEvent.po sition()); |
| 2515 #else | 2104 HitTestResult result = hitTestResultAtPoint(hitTestPoint); |
| 2516 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled(); | 2105 if (selectionController().handleGestureLongPress(gestureEvent, result)) |
| 2517 #endif | 2106 return true; |
| 2518 if (shouldLongPressSelectWord) { | 2107 |
| 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 } | |
| 2534 return sendContextMenuEventForGesture(targetedEvent); | 2108 return sendContextMenuEventForGesture(targetedEvent); |
| 2535 } | 2109 } |
| 2536 | 2110 |
| 2537 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent) | 2111 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent) |
| 2538 { | 2112 { |
| 2539 #if !OS(ANDROID) | 2113 #if !OS(ANDROID) |
| 2540 if (m_longTapShouldInvokeContextMenu) { | 2114 if (m_longTapShouldInvokeContextMenu) { |
| 2541 m_longTapShouldInvokeContextMenu = false; | 2115 m_longTapShouldInvokeContextMenu = false; |
| 2542 return sendContextMenuEventForGesture(targetedEvent); | 2116 return sendContextMenuEventForGesture(targetedEvent); |
| 2543 } | 2117 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3000 FrameView* v = m_frame->view(); | 2574 FrameView* v = m_frame->view(); |
| 3001 if (!v) | 2575 if (!v) |
| 3002 return false; | 2576 return false; |
| 3003 | 2577 |
| 3004 // Clear mouse press state to avoid initiating a drag while context menu is up. | 2578 // Clear mouse press state to avoid initiating a drag while context menu is up. |
| 3005 m_mousePressed = false; | 2579 m_mousePressed = false; |
| 3006 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); | 2580 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); |
| 3007 HitTestRequest request(HitTestRequest::Active); | 2581 HitTestRequest request(HitTestRequest::Active); |
| 3008 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, positionInContents, event); | 2582 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, positionInContents, event); |
| 3009 | 2583 |
| 3010 if (!m_frame->selection().contains(positionInContents) | 2584 selectionController().prepareForContextMenu(mev, 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 } | |
| 3023 | 2585 |
| 3024 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode() ; | 2586 Node* targetNode = overrideTargetNode ? overrideTargetNode : mev.innerNode() ; |
| 3025 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event , false); | 2587 return !dispatchMouseEvent(EventTypeNames::contextmenu, targetNode, 0, event , false); |
| 3026 } | 2588 } |
| 3027 | 2589 |
| 3028 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) | 2590 bool EventHandler::sendContextMenuEventForKey(Element* overrideTargetElement) |
| 3029 { | 2591 { |
| 3030 FrameView* view = m_frame->view(); | 2592 FrameView* view = m_frame->view(); |
| 3031 if (!view) | 2593 if (!view) |
| 3032 return false; | 2594 return false; |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3521 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); | 3083 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); |
| 3522 } else { | 3084 } else { |
| 3523 dragState().m_dragSrc = nullptr; | 3085 dragState().m_dragSrc = nullptr; |
| 3524 } | 3086 } |
| 3525 | 3087 |
| 3526 if (!dragState().m_dragSrc) | 3088 if (!dragState().m_dragSrc) |
| 3527 m_mouseDownMayStartDrag = false; // no element is draggable | 3089 m_mouseDownMayStartDrag = false; // no element is draggable |
| 3528 } | 3090 } |
| 3529 | 3091 |
| 3530 if (!m_mouseDownMayStartDrag) | 3092 if (!m_mouseDownMayStartDrag) |
| 3531 return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() & & !m_mouseDownMayStartAutoscroll; | 3093 return initiator == DragInitiator::Mouse && !selectionController().mouse DownMayStartSelect() && !m_mouseDownMayStartAutoscroll; |
| 3532 | 3094 |
| 3533 // We are starting a text/image/url drag, so the cursor should be an arrow | 3095 // We are starting a text/image/url drag, so the cursor should be an arrow |
| 3534 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer). | 3096 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer). |
| 3535 m_frame->view()->setCursor(pointerCursor()); | 3097 m_frame->view()->setCursor(pointerCursor()); |
| 3536 | 3098 |
| 3537 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position())) | 3099 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position())) |
| 3538 return true; | 3100 return true; |
| 3539 | 3101 |
| 3540 // Once we're past the hysteresis point, we don't want to treat this gesture as a click | 3102 // Once we're past the hysteresis point, we don't want to treat this gesture as a click |
| 3541 invalidateClick(); | 3103 invalidateClick(); |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4106 | 3668 |
| 4107 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) | 3669 void EventHandler::setLastKnownMousePosition(const PlatformMouseEvent& event) |
| 4108 { | 3670 { |
| 4109 m_mousePositionIsUnknown = false; | 3671 m_mousePositionIsUnknown = false; |
| 4110 m_lastKnownMousePosition = event.position(); | 3672 m_lastKnownMousePosition = event.position(); |
| 4111 m_lastKnownMouseGlobalPosition = event.globalPosition(); | 3673 m_lastKnownMouseGlobalPosition = event.globalPosition(); |
| 4112 } | 3674 } |
| 4113 | 3675 |
| 4114 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe) | 3676 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe) |
| 4115 { | 3677 { |
| 4116 // If we're clicking into a frame that is selected, the frame will appear | 3678 selectionController().preparePassMousePressEventToSubframe(mev); |
| 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 | |
| 4128 subframe->eventHandler().handleMousePressEvent(mev.event()); | 3679 subframe->eventHandler().handleMousePressEvent(mev.event()); |
| 4129 return true; | 3680 return true; |
| 4130 } | 3681 } |
| 4131 | 3682 |
| 4132 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode) | 3683 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode) |
| 4133 { | 3684 { |
| 4134 if (m_mouseDownMayStartDrag) | 3685 if (m_mouseDownMayStartDrag) |
| 4135 return false; | 3686 return false; |
| 4136 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e); | 3687 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e); |
| 4137 return true; | 3688 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4169 unsigned EventHandler::accessKeyModifiers() | 3720 unsigned EventHandler::accessKeyModifiers() |
| 4170 { | 3721 { |
| 4171 #if OS(MACOSX) | 3722 #if OS(MACOSX) |
| 4172 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; | 3723 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; |
| 4173 #else | 3724 #else |
| 4174 return PlatformEvent::AltKey; | 3725 return PlatformEvent::AltKey; |
| 4175 #endif | 3726 #endif |
| 4176 } | 3727 } |
| 4177 | 3728 |
| 4178 } // namespace blink | 3729 } // namespace blink |
| OLD | NEW |