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 * Copyright (C) 2015 Google Inc. All rights reserved. | 5 * Copyright (C) 2015 Google Inc. All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 } | 266 } |
| 267 | 267 |
| 268 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart(Node * targetNode, const VisibleSelectionInFlatTree& selection, TextGranularity granu larity) | 268 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart(Node * targetNode, const VisibleSelectionInFlatTree& selection, TextGranularity granu larity) |
| 269 { | 269 { |
| 270 if (targetNode && targetNode->layoutObject() && !targetNode->layoutObject()- >isSelectable()) | 270 if (targetNode && targetNode->layoutObject() && !targetNode->layoutObject()- >isSelectable()) |
| 271 return false; | 271 return false; |
| 272 | 272 |
| 273 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) | 273 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) |
| 274 return false; | 274 return false; |
| 275 | 275 |
| 276 if (!selection.isValidFor(*m_frame->document())) | 276 // |dispatchSelectStart()| can change document hosted by |m_frame|. |
| 277 if (!this->selection().isAvailable()) | |
| 278 return false; | |
| 279 | |
| 280 if (!selection.isValidFor(this->selection().document())) | |
| 277 return false; | 281 return false; |
| 278 | 282 |
| 279 if (selection.isRange()) { | 283 if (selection.isRange()) { |
| 280 m_selectionState = SelectionState::ExtendedSelection; | 284 m_selectionState = SelectionState::ExtendedSelection; |
| 281 } else { | 285 } else { |
| 282 granularity = CharacterGranularity; | 286 granularity = CharacterGranularity; |
| 283 m_selectionState = SelectionState::PlacedCaret; | 287 m_selectionState = SelectionState::PlacedCaret; |
| 284 } | 288 } |
| 285 | 289 |
| 286 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ; | 290 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 if (pos.isNotNull() && pos.deepEquivalent().anchorNode()->isDescendantOf(URL Element)) | 391 if (pos.isNotNull() && pos.deepEquivalent().anchorNode()->isDescendantOf(URL Element)) |
| 388 newSelection = VisibleSelectionInFlatTree::selectionFromContentsOfNode(U RLElement); | 392 newSelection = VisibleSelectionInFlatTree::selectionFromContentsOfNode(U RLElement); |
| 389 | 393 |
| 390 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 394 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); |
| 391 } | 395 } |
| 392 | 396 |
| 393 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event) | 397 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event) |
| 394 { | 398 { |
| 395 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick "); | 399 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick "); |
| 396 | 400 |
| 401 if (!selection().isAvailable()) | |
| 402 return false; | |
| 403 | |
| 397 if (!m_mouseDownAllowsMultiClick) | 404 if (!m_mouseDownAllowsMultiClick) |
| 398 return handleMousePressEventSingleClick(event); | 405 return handleMousePressEventSingleClick(event); |
| 399 | 406 |
| 400 if (event.event().button() != LeftButton) | 407 if (event.event().button() != LeftButton) |
| 401 return false; | 408 return false; |
| 402 | 409 |
| 403 if (selection().isRange()) { | 410 if (selection().isRange()) { |
| 404 // A double-click when range is already selected | 411 // A double-click when range is already selected |
| 405 // should not change the selection. So, do not call | 412 // should not change the selection. So, do not call |
| 406 // selectClosestWordFromMouseEvent, but do set | 413 // selectClosestWordFromMouseEvent, but do set |
| 407 // m_beganSelectingText to prevent handleMouseReleaseEvent | 414 // m_beganSelectingText to prevent handleMouseReleaseEvent |
| 408 // from setting caret selection. | 415 // from setting caret selection. |
| 409 m_selectionState = SelectionState::ExtendedSelection; | 416 m_selectionState = SelectionState::ExtendedSelection; |
| 410 } else { | 417 } else { |
| 411 selectClosestWordFromMouseEvent(event); | 418 selectClosestWordFromMouseEvent(event); |
| 412 } | 419 } |
| 413 return true; | 420 return true; |
| 414 } | 421 } |
| 415 | 422 |
| 416 bool SelectionController::handleMousePressEventTripleClick(const MouseEventWithH itTestResults& event) | 423 bool SelectionController::handleMousePressEventTripleClick(const MouseEventWithH itTestResults& event) |
| 417 { | 424 { |
| 418 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventTripleClick "); | 425 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventTripleClick "); |
| 419 | 426 |
| 427 if (!selection().isAvailable()) { | |
| 428 // editing/shadow/doubleclick-on-meter-in-shadow-crash.html reach here. | |
| 429 return false; | |
| 430 } | |
| 431 | |
| 420 if (!m_mouseDownAllowsMultiClick) | 432 if (!m_mouseDownAllowsMultiClick) |
| 421 return handleMousePressEventSingleClick(event); | 433 return handleMousePressEventSingleClick(event); |
| 422 | 434 |
| 423 if (event.event().button() != LeftButton) | 435 if (event.event().button() != LeftButton) |
| 424 return false; | 436 return false; |
| 425 | 437 |
| 426 Node* innerNode = event.innerNode(); | 438 Node* innerNode = event.innerNode(); |
| 427 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | 439 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) |
| 428 return false; | 440 return false; |
| 429 | 441 |
| 430 VisibleSelectionInFlatTree newSelection; | 442 VisibleSelectionInFlatTree newSelection; |
| 431 const VisiblePositionInFlatTree& pos = visiblePositionOfHitTestResult(event. hitTestResult()); | 443 const VisiblePositionInFlatTree& pos = visiblePositionOfHitTestResult(event. hitTestResult()); |
| 432 if (pos.isNotNull()) { | 444 if (pos.isNotNull()) { |
| 433 newSelection = VisibleSelectionInFlatTree(pos); | 445 newSelection = VisibleSelectionInFlatTree(pos); |
| 434 newSelection.expandUsingGranularity(ParagraphGranularity); | 446 newSelection.expandUsingGranularity(ParagraphGranularity); |
| 435 } | 447 } |
| 436 | 448 |
| 437 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); | 449 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity); |
| 438 } | 450 } |
| 439 | 451 |
| 440 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event) | 452 void SelectionController::handleMousePressEvent(const MouseEventWithHitTestResul ts& event) |
| 441 { | 453 { |
| 442 // If we got the event back, that must mean it wasn't prevented, | 454 // If we got the event back, that must mean it wasn't prevented, |
| 443 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | 455 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. |
| 444 m_mouseDownMayStartSelect = (canMouseDownStartSelect(event.innerNode()) || i sLinkSelection(event)) | 456 m_mouseDownMayStartSelect = (canMouseDownStartSelect(event.innerNode()) || i sLinkSelection(event)) |
| 445 && !event.scrollbar(); | 457 && !event.scrollbar(); |
| 446 m_mouseDownWasSingleClickInSelection = false; | 458 m_mouseDownWasSingleClickInSelection = false; |
| 459 if (!selection().isAvailable()) { | |
| 460 // "gesture-tap-frame-removed.html" reaches here. | |
| 461 m_mouseDownAllowsMultiClick = !event.event().fromTouch(); | |
| 462 return; | |
| 463 } | |
| 464 | |
| 447 // Avoid double-tap touch gesture confusion by restricting multi-click side | 465 // Avoid double-tap touch gesture confusion by restricting multi-click side |
| 448 // effects, e.g., word selection, to editable regions. | 466 // effects, e.g., word selection, to editable regions. |
| 449 m_mouseDownAllowsMultiClick = !event.event().fromTouch() || selection().hasE ditableStyle(); | 467 m_mouseDownAllowsMultiClick = !event.event().fromTouch() || selection().hasE ditableStyle(); |
| 468 | |
|
tkent
2016/06/07 23:41:59
nit: This change is unnecessary.
yosin_UTC9
2016/06/08 04:06:10
Done.
| |
| 450 } | 469 } |
| 451 | 470 |
| 452 void SelectionController::handleMouseDraggedEvent(const MouseEventWithHitTestRes ults& event, const IntPoint& mouseDownPos, const LayoutPoint& dragStartPos, Node * mousePressNode, const IntPoint& lastKnownMousePosition) | 471 void SelectionController::handleMouseDraggedEvent(const MouseEventWithHitTestRes ults& event, const IntPoint& mouseDownPos, const LayoutPoint& dragStartPos, Node * mousePressNode, const IntPoint& lastKnownMousePosition) |
| 453 { | 472 { |
| 473 if (!selection().isAvailable()) | |
| 474 return; | |
| 454 if (m_selectionState != SelectionState::ExtendedSelection) { | 475 if (m_selectionState != SelectionState::ExtendedSelection) { |
| 455 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active ); | 476 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active ); |
| 456 HitTestResult result(request, mouseDownPos); | 477 HitTestResult result(request, mouseDownPos); |
| 457 m_frame->document()->layoutViewItem().hitTest(result); | 478 m_frame->document()->layoutViewItem().hitTest(result); |
| 458 | 479 |
| 459 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKn ownMousePosition); | 480 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKn ownMousePosition); |
| 460 } | 481 } |
| 461 updateSelectionForMouseDrag(event.hitTestResult(), mousePressNode, dragStart Pos, lastKnownMousePosition); | 482 updateSelectionForMouseDrag(event.hitTestResult(), mousePressNode, dragStart Pos, lastKnownMousePosition); |
| 462 } | 483 } |
| 463 | 484 |
| 464 void SelectionController::updateSelectionForMouseDrag(Node* mousePressNode, cons t LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition) | 485 void SelectionController::updateSelectionForMouseDrag(Node* mousePressNode, cons t LayoutPoint& dragStartPos, const IntPoint& lastKnownMousePosition) |
| 465 { | 486 { |
| 466 FrameView* view = m_frame->view(); | 487 FrameView* view = m_frame->view(); |
| 467 if (!view) | 488 if (!view) |
| 468 return; | 489 return; |
| 469 LayoutViewItem layoutItem = m_frame->contentLayoutItem(); | 490 LayoutViewItem layoutItem = m_frame->contentLayoutItem(); |
| 470 if (layoutItem.isNull()) | 491 if (layoutItem.isNull()) |
| 471 return; | 492 return; |
| 472 | 493 |
| 473 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H itTestRequest::Move); | 494 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H itTestRequest::Move); |
| 474 HitTestResult result(request, view->rootFrameToContents(lastKnownMousePositi on)); | 495 HitTestResult result(request, view->rootFrameToContents(lastKnownMousePositi on)); |
| 475 layoutItem.hitTest(result); | 496 layoutItem.hitTest(result); |
| 476 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition); | 497 updateSelectionForMouseDrag(result, mousePressNode, dragStartPos, lastKnownM ousePosition); |
| 477 } | 498 } |
| 478 | 499 |
| 479 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos) | 500 bool SelectionController::handleMouseReleaseEvent(const MouseEventWithHitTestRes ults& event, const LayoutPoint& dragStartPos) |
| 480 { | 501 { |
| 502 if (!selection().isAvailable()) | |
| 503 return false; | |
| 504 | |
| 481 bool handled = false; | 505 bool handled = false; |
| 482 m_mouseDownMayStartSelect = false; | 506 m_mouseDownMayStartSelect = false; |
| 483 // Clear the selection if the mouse didn't move after the last mouse | 507 // Clear the selection if the mouse didn't move after the last mouse |
| 484 // press and it's not a context menu click. We do this so when clicking | 508 // press and it's not a context menu click. We do this so when clicking |
| 485 // on the selection, the selection goes away. However, if we are | 509 // on the selection, the selection goes away. However, if we are |
| 486 // editing, place the caret. | 510 // editing, place the caret. |
| 487 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection | 511 if (m_mouseDownWasSingleClickInSelection && m_selectionState != SelectionSta te::ExtendedSelection |
| 488 && dragStartPos == event.event().position() | 512 && dragStartPos == event.event().position() |
| 489 && selection().isRange() | 513 && selection().isRange() |
| 490 && event.event().button() != RightButton) { | 514 && event.event().button() != RightButton) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); | 563 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame(); |
| 540 // Do not paste here if the focus was moved somewhere else. | 564 // Do not paste here if the focus was moved somewhere else. |
| 541 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction()) | 565 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction()) |
| 542 return m_frame->editor().createCommand("PasteGlobalSelection").execute() ; | 566 return m_frame->editor().createCommand("PasteGlobalSelection").execute() ; |
| 543 | 567 |
| 544 return false; | 568 return false; |
| 545 } | 569 } |
| 546 | 570 |
| 547 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult) | 571 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult) |
| 548 { | 572 { |
| 573 if (!selection().isAvailable()) | |
| 574 return false; | |
| 549 if (hitTestResult.isLiveLink()) | 575 if (hitTestResult.isLiveLink()) |
| 550 return false; | 576 return false; |
| 551 | 577 |
| 552 Node* innerNode = hitTestResult.innerNode(); | 578 Node* innerNode = hitTestResult.innerNode(); |
| 553 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() || innerNode->canStartSelection()); | 579 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() || innerNode->canStartSelection()); |
| 554 if (!innerNodeIsSelectable) | 580 if (!innerNodeIsSelectable) |
| 555 return false; | 581 return false; |
| 556 | 582 |
| 557 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace:: DontAppend, SelectInputEventType::GestureLongPress); | 583 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace:: DontAppend, SelectInputEventType::GestureLongPress); |
| 584 if (!selection().isAvailable()) { | |
| 585 // "editing/selection/longpress-selection-in-iframe-removed-crash.html" | |
| 586 // reach here. | |
| 587 return false; | |
| 588 } | |
| 558 return selection().isRange(); | 589 return selection().isRange(); |
| 559 } | 590 } |
| 560 | 591 |
| 561 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position) | 592 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position) |
| 562 { | 593 { |
| 594 if (!selection().isAvailable()) | |
| 595 return; | |
| 563 if (selection().contains(position) | 596 if (selection().contains(position) |
| 564 || mev.scrollbar() | 597 || mev.scrollbar() |
| 565 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. | 598 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. |
| 566 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items | 599 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items |
| 567 // available for text selections. But only if we're above text. | 600 // available for text selections. But only if we're above text. |
| 568 || !(selection().isContentEditable() || (mev.innerNode() && mev.innerNod e()->isTextNode()))) | 601 || !(selection().isContentEditable() || (mev.innerNode() && mev.innerNod e()->isTextNode()))) |
| 569 return; | 602 return; |
| 570 | 603 |
| 571 // Context menu events are always allowed to perform a selection. | 604 // Context menu events are always allowed to perform a selection. |
| 572 TemporaryChange<bool> mouseDownMayStartSelectChange(m_mouseDownMayStartSelec t, true); | 605 TemporaryChange<bool> mouseDownMayStartSelectChange(m_mouseDownMayStartSelec t, true); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 629 { | 662 { |
| 630 return m_frame->selection(); | 663 return m_frame->selection(); |
| 631 } | 664 } |
| 632 | 665 |
| 633 bool isLinkSelection(const MouseEventWithHitTestResults& event) | 666 bool isLinkSelection(const MouseEventWithHitTestResults& event) |
| 634 { | 667 { |
| 635 return event.event().altKey() && event.isOverLink(); | 668 return event.event().altKey() && event.isOverLink(); |
| 636 } | 669 } |
| 637 | 670 |
| 638 } // namespace blink | 671 } // namespace blink |
| OLD | NEW |