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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 { | 59 { |
| 60 } | 60 } |
| 61 | 61 |
| 62 DEFINE_TRACE(SelectionController) | 62 DEFINE_TRACE(SelectionController) |
| 63 { | 63 { |
| 64 visitor->trace(m_frame); | 64 visitor->trace(m_frame); |
| 65 } | 65 } |
| 66 | 66 |
| 67 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti on& newSelection) | 67 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti on& newSelection) |
| 68 { | 68 { |
| 69 if (!VisibleSelection::InDOMTree::equalSelections(selection.selection(), new Selection)) | 69 if (VisibleSelection::InDOMTree::equalSelections(selection.selection(), newS election)) |
| 70 selection.setSelection(newSelection); | 70 return; |
| 71 selection.setSelection(newSelection); | |
| 71 } | 72 } |
| 72 | 73 |
| 73 static inline bool dispatchSelectStart(Node* node) | 74 static inline bool dispatchSelectStart(Node* node) |
| 74 { | 75 { |
| 75 if (!node || !node->layoutObject()) | 76 if (!node || !node->layoutObject()) |
| 76 return true; | 77 return true; |
| 77 | 78 |
| 78 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart)); | 79 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart)); |
| 79 } | 80 } |
| 80 | 81 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ; | 127 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity) ; |
| 127 | 128 |
| 128 return true; | 129 return true; |
| 129 } | 130 } |
| 130 | 131 |
| 131 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace) | 132 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace) |
| 132 { | 133 { |
| 133 Node* innerNode = result.innerNode(); | 134 Node* innerNode = result.innerNode(); |
| 134 VisibleSelection newSelection; | 135 VisibleSelection newSelection; |
| 135 | 136 |
| 136 if (innerNode && innerNode->layoutObject()) { | 137 if (!innerNode || !innerNode->layoutObject()) |
| 137 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | 138 return; |
| 138 if (pos.isNotNull()) { | |
| 139 newSelection = VisibleSelection(pos); | |
| 140 expandSelectionUsingGranularity(newSelection, WordGranularity); | |
| 141 } | |
| 142 | 139 |
| 143 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend & & newSelection.isRange()) | 140 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.local Point())); |
| 144 newSelection.appendTrailingWhitespace(); | 141 if (pos.isNotNull()) { |
| 142 newSelection = VisibleSelection(pos); | |
| 143 expandSelectionUsingGranularity(newSelection, WordGranularity); | |
| 144 } | |
| 145 | 145 |
| 146 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 146 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange()) |
| 147 } | 147 newSelection.appendTrailingWhitespace(); |
| 148 | |
| 149 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 148 } | 150 } |
| 149 | 151 |
| 150 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes tResult& result, AppendTrailingWhitespace appendTrailingWhitespace) | 152 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes tResult& result, AppendTrailingWhitespace appendTrailingWhitespace) |
| 151 { | 153 { |
| 152 Node* innerNode = result.innerNode(); | 154 Node* innerNode = result.innerNode(); |
| 153 VisibleSelection newSelection; | 155 VisibleSelection newSelection; |
| 154 | 156 |
| 155 if (innerNode && innerNode->layoutObject()) { | 157 if (!innerNode || !innerNode->layoutObject()) |
| 156 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | 158 return; |
| 157 Position start = pos.deepEquivalent(); | 159 |
| 158 Position end = pos.deepEquivalent(); | 160 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.local Point())); |
| 159 if (pos.isNotNull()) { | 161 Position start = pos.deepEquivalent(); |
| 160 DocumentMarkerVector markers = innerNode->document().markers().marke rsInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers()); | 162 Position end = pos.deepEquivalent(); |
| 161 if (markers.size() == 1) { | 163 if (pos.isNotNull()) { |
| 162 start.moveToOffset(markers[0]->startOffset()); | 164 DocumentMarkerVector markers = innerNode->document().markers().markersIn Range(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers()); |
| 163 end.moveToOffset(markers[0]->endOffset()); | 165 if (markers.size() == 1) { |
| 164 newSelection = VisibleSelection(start, end); | 166 start.moveToOffset(markers[0]->startOffset()); |
| 165 } | 167 end.moveToOffset(markers[0]->endOffset()); |
| 168 newSelection = VisibleSelection(start, end); | |
| 166 } | 169 } |
| 170 } | |
| 167 | 171 |
| 168 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend & & newSelection.isRange()) | 172 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne wSelection.isRange()) |
| 169 newSelection.appendTrailingWhitespace(); | 173 newSelection.appendTrailingWhitespace(); |
| 170 | 174 |
| 171 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 175 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); |
| 172 } | |
| 173 } | 176 } |
| 174 | 177 |
| 175 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi tTestResults& result) | 178 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi tTestResults& result) |
| 176 { | 179 { |
| 177 if (m_mouseDownMayStartSelect) { | 180 if (!m_mouseDownMayStartSelect) |
| 178 selectClosestWordFromHitTestResult(result.hitTestResult(), | 181 return; |
| 179 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailin gWhitespace::DontAppend); | 182 |
| 180 } | 183 selectClosestWordFromHitTestResult(result.hitTestResult(), |
| 184 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi tespace::DontAppend); | |
| 181 } | 185 } |
| 182 | 186 |
| 183 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven tWithHitTestResults& result) | 187 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven tWithHitTestResults& result) |
| 184 { | 188 { |
| 185 if (m_mouseDownMayStartSelect) { | 189 if (!m_mouseDownMayStartSelect) |
| 186 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), | 190 return; |
| 187 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailin gWhitespace::DontAppend); | 191 |
| 188 } | 192 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), |
| 193 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi tespace::DontAppend); | |
| 194 | |
| 189 } | 195 } |
| 190 | 196 |
| 191 void SelectionController::selectClosestWordOrLinkFromMouseEvent(const MouseEvent WithHitTestResults& result) | 197 void SelectionController::selectClosestWordOrLinkFromMouseEvent(const MouseEvent WithHitTestResults& result) |
| 192 { | 198 { |
| 193 if (!result.hitTestResult().isLiveLink()) | 199 if (!result.hitTestResult().isLiveLink()) |
| 194 return selectClosestWordFromMouseEvent(result); | 200 return selectClosestWordFromMouseEvent(result); |
| 195 | 201 |
| 196 Node* innerNode = result.innerNode(); | 202 Node* innerNode = result.innerNode(); |
| 197 | 203 |
| 198 if (innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect) { | 204 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) |
|
yosin_UTC9
2015/06/26 01:00:28
nit: Since other parts expand Boolean expression,
Miyoung Shin(c)
2015/06/26 04:44:20
Done.
| |
| 199 VisibleSelection newSelection; | 205 return; |
| 200 Element* URLElement = result.hitTestResult().URLElement(); | |
| 201 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint())); | |
| 202 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescenda ntOf(URLElement)) | |
| 203 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElem ent); | |
| 204 | 206 |
| 205 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 207 VisibleSelection newSelection; |
| 206 } | 208 Element* URLElement = result.hitTestResult().URLElement(); |
| 209 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.local Point())); | |
| 210 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescendantOf (URLElement)) | |
| 211 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement) ; | |
| 212 | |
| 213 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | |
| 207 } | 214 } |
| 208 | 215 |
| 209 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event) | 216 bool SelectionController::handleMousePressEventDoubleClick(const MouseEventWithH itTestResults& event) |
| 210 { | 217 { |
| 211 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick "); | 218 TRACE_EVENT0("blink", "SelectionController::handleMousePressEventDoubleClick "); |
| 212 | 219 |
| 213 if (event.event().button() != LeftButton) | 220 if (event.event().button() != LeftButton) |
| 214 return false; | 221 return false; |
| 215 | 222 |
| 216 if (selection().isRange()) { | 223 if (selection().isRange()) { |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 return false; | 536 return false; |
| 530 } | 537 } |
| 531 | 538 |
| 532 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult) | 539 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges tureEvent, const HitTestResult& hitTestResult) |
| 533 { | 540 { |
| 534 #if OS(ANDROID) | 541 #if OS(ANDROID) |
| 535 bool shouldLongPressSelectWord = true; | 542 bool shouldLongPressSelectWord = true; |
| 536 #else | 543 #else |
| 537 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled(); | 544 bool shouldLongPressSelectWord = m_frame->settings() && m_frame->settings()- >touchEditingEnabled(); |
| 538 #endif | 545 #endif |
| 539 if (shouldLongPressSelectWord) { | 546 if (!shouldLongPressSelectWord) |
| 547 return false; | |
| 540 | 548 |
| 549 Node* innerNode = hitTestResult.innerNode(); | |
| 550 if (hitTestResult.isLiveLink() || !innerNode || !(innerNode->isContentEditab le() || innerNode->isTextNode() | |
| 551 #if OS(ANDROID) | |
| 552 || innerNode->canStartSelection() | |
| 553 #endif | |
| 554 )) | |
| 555 return false; | |
| 541 | 556 |
| 542 Node* innerNode = hitTestResult.innerNode(); | 557 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace:: DontAppend); |
| 543 if (!hitTestResult.isLiveLink() && innerNode && (innerNode->isContentEdi table() || innerNode->isTextNode() | 558 if (!selection().isRange()) |
| 544 #if OS(ANDROID) | 559 return false; |
| 545 || innerNode->canStartSelection() | 560 return true; |
| 546 #endif | |
| 547 )) { | |
| 548 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhit espace::DontAppend); | |
| 549 if (selection().isRange()) | |
| 550 return true; | |
| 551 } | |
| 552 } | |
| 553 return false; | |
| 554 } | 561 } |
| 555 | 562 |
| 556 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position) | 563 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult s& mev, const LayoutPoint& position) |
| 557 { | 564 { |
| 558 if (!selection().contains(position) | 565 if (selection().contains(position) |
| 559 && !mev.scrollbar() | 566 || mev.scrollbar() |
| 560 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. | 567 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse. |
| 561 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items | 568 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items |
| 562 // available for text selections. But only if we're above text. | 569 // available for text selections. But only if we're above text. |
| 563 && (selection().isContentEditable() || (mev.innerNode() && mev.innerNode ()->isTextNode()))) { | 570 || !(selection().isContentEditable() || (mev.innerNode() && mev.innerNod e()->isTextNode()))) |
| 564 m_mouseDownMayStartSelect = true; // context menu events are always allo wed to perform a selection | 571 return; |
| 565 | 572 |
| 566 if (mev.hitTestResult().isMisspelled()) | 573 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection |
| 567 selectClosestMisspellingFromMouseEvent(mev); | 574 |
| 568 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick( )) | 575 if (mev.hitTestResult().isMisspelled()) |
| 569 selectClosestWordOrLinkFromMouseEvent(mev); | 576 selectClosestMisspellingFromMouseEvent(mev); |
| 570 } | 577 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) |
| 578 selectClosestWordOrLinkFromMouseEvent(mev); | |
| 571 } | 579 } |
| 572 | 580 |
| 573 void SelectionController::passMousePressEventToSubframe(const MouseEventWithHitT estResults& mev) | 581 void SelectionController::passMousePressEventToSubframe(const MouseEventWithHitT estResults& mev) |
| 574 { | 582 { |
| 575 // If we're clicking into a frame that is selected, the frame will appear | 583 // If we're clicking into a frame that is selected, the frame will appear |
| 576 // greyed out even though we're clicking on the selection. This looks | 584 // greyed out even though we're clicking on the selection. This looks |
| 577 // really strange (having the whole frame be greyed out), so we deselect the | 585 // really strange (having the whole frame be greyed out), so we deselect the |
| 578 // selection. | 586 // selection. |
| 579 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | 587 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); |
| 580 if (selection().contains(p)) { | 588 if (!selection().contains(p)) |
| 581 VisiblePosition visiblePos( | 589 return; |
| 582 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint())) ; | 590 |
| 583 VisibleSelection newSelection(visiblePos); | 591 VisiblePosition visiblePos( |
| 584 selection().setSelection(newSelection); | 592 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint())); |
| 585 } | 593 VisibleSelection newSelection(visiblePos); |
| 594 selection().setSelection(newSelection); | |
| 586 } | 595 } |
| 587 | 596 |
| 588 void SelectionController::initializeSelectionState() | 597 void SelectionController::initializeSelectionState() |
| 589 { | 598 { |
| 590 m_selectionState = SelectionState::HaveNotStartedSelection; | 599 m_selectionState = SelectionState::HaveNotStartedSelection; |
| 591 } | 600 } |
| 592 | 601 |
| 593 void SelectionController::setMouseDownMayStartSelect(bool mayStartSelect) | 602 void SelectionController::setMouseDownMayStartSelect(bool mayStartSelect) |
| 594 { | 603 { |
| 595 m_mouseDownMayStartSelect = mayStartSelect; | 604 m_mouseDownMayStartSelect = mayStartSelect; |
| 596 } | 605 } |
| 597 | 606 |
| 598 bool SelectionController::mouseDownMayStartSelect() const | 607 bool SelectionController::mouseDownMayStartSelect() const |
| 599 { | 608 { |
| 600 return m_mouseDownMayStartSelect; | 609 return m_mouseDownMayStartSelect; |
| 601 } | 610 } |
| 602 | 611 |
| 603 bool SelectionController::mouseDownWasSingleClickInSelection() const | 612 bool SelectionController::mouseDownWasSingleClickInSelection() const |
| 604 { | 613 { |
| 605 return m_mouseDownWasSingleClickInSelection; | 614 return m_mouseDownWasSingleClickInSelection; |
| 606 } | 615 } |
| 607 | 616 |
| 608 FrameSelection& SelectionController::selection() const | 617 FrameSelection& SelectionController::selection() const |
| 609 { | 618 { |
| 610 return m_frame->selection(); | 619 return m_frame->selection(); |
| 611 } | 620 } |
| 612 | 621 |
| 613 } // namespace blink | 622 } // namespace blink |
| OLD | NEW |