| 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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 } else { | 280 } else { |
| 281 granularity = CharacterGranularity; | 281 granularity = CharacterGranularity; |
| 282 m_selectionState = SelectionState::PlacedCaret; | 282 m_selectionState = SelectionState::PlacedCaret; |
| 283 } | 283 } |
| 284 | 284 |
| 285 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity)
; | 285 this->selection().setNonDirectionalSelectionIfNeeded(selection, granularity)
; |
| 286 | 286 |
| 287 return true; | 287 return true; |
| 288 } | 288 } |
| 289 | 289 |
| 290 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult
& result, AppendTrailingWhitespace appendTrailingWhitespace) | 290 void SelectionController::selectClosestWordFromHitTestResult(const HitTestResult
& result, AppendTrailingWhitespace appendTrailingWhitespace, SelectInputEventTyp
e selectInputEventType) |
| 291 { | 291 { |
| 292 Node* innerNode = result.innerNode(); | 292 Node* innerNode = result.innerNode(); |
| 293 VisibleSelectionInFlatTree newSelection; | 293 VisibleSelectionInFlatTree newSelection; |
| 294 | 294 |
| 295 if (!innerNode || !innerNode->layoutObject()) | 295 if (!innerNode || !innerNode->layoutObject()) |
| 296 return; | 296 return; |
| 297 | 297 |
| 298 const VisiblePositionInFlatTree& pos = visiblePositionOfHitTestResult(result
); | 298 // Special-case image local offset to always be zero, to avoid triggering |
| 299 // LayoutReplaced::positionFromPoint's advancement of the position at the |
| 300 // mid-point of the the image (which was intended for mouse-drag selection |
| 301 // and isn't desirable for long-press). |
| 302 HitTestResult adjustedHitTestResult = result; |
| 303 if (selectInputEventType == SelectInputEventType::GestureLongPress && result
.image()) |
| 304 adjustedHitTestResult.setNodeAndPosition(result.innerNode(), LayoutPoint
(0, 0)); |
| 305 |
| 306 const VisiblePositionInFlatTree& pos = visiblePositionOfHitTestResult(adjust
edHitTestResult); |
| 299 if (pos.isNotNull()) { | 307 if (pos.isNotNull()) { |
| 300 newSelection = VisibleSelectionInFlatTree(pos); | 308 newSelection = VisibleSelectionInFlatTree(pos); |
| 301 newSelection.expandUsingGranularity(WordGranularity); | 309 newSelection.expandUsingGranularity(WordGranularity); |
| 302 } | 310 } |
| 303 | 311 |
| 304 #if OS(ANDROID) | 312 if (selectInputEventType == SelectInputEventType::GestureLongPress) { |
| 305 // If node doesn't have text except space, tab or line break, do not | 313 // If node doesn't have text except space, tab or line break, do not |
| 306 // select that 'empty' area. | 314 // select that 'empty' area. |
| 307 EphemeralRangeInFlatTree range = EphemeralRangeInFlatTree(newSelection.start
(), newSelection.end()); | 315 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end())
; |
| 308 const String& str = plainText(range, TextIteratorDefaultBehavior); | 316 const String& str = plainText(range, TextIteratorEmitsObjectReplacementC
haracter); |
| 309 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) | 317 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) |
| 310 return; | 318 return; |
| 311 #endif | 319 } |
| 312 | 320 |
| 313 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne
wSelection.isRange()) | 321 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend && ne
wSelection.isRange()) |
| 314 newSelection.appendTrailingWhitespace(); | 322 newSelection.appendTrailingWhitespace(); |
| 315 | 323 |
| 316 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection
ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 324 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection
ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); |
| 317 } | 325 } |
| 318 | 326 |
| 319 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes
tResult& result, AppendTrailingWhitespace appendTrailingWhitespace) | 327 void SelectionController::selectClosestMisspellingFromHitTestResult(const HitTes
tResult& result, AppendTrailingWhitespace appendTrailingWhitespace) |
| 320 { | 328 { |
| 321 Node* innerNode = result.innerNode(); | 329 Node* innerNode = result.innerNode(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 342 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection
ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); | 350 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelection
ToRespectUserSelectAll(innerNode, newSelection), WordGranularity); |
| 343 } | 351 } |
| 344 | 352 |
| 345 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi
tTestResults& result) | 353 void SelectionController::selectClosestWordFromMouseEvent(const MouseEventWithHi
tTestResults& result) |
| 346 { | 354 { |
| 347 if (!m_mouseDownMayStartSelect) | 355 if (!m_mouseDownMayStartSelect) |
| 348 return; | 356 return; |
| 349 | 357 |
| 350 AppendTrailingWhitespace appendTrailingWhitespace = (result.event().clickCou
nt() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? AppendTrai
lingWhitespace::ShouldAppend : AppendTrailingWhitespace::DontAppend; | 358 AppendTrailingWhitespace appendTrailingWhitespace = (result.event().clickCou
nt() == 2 && m_frame->editor().isSelectTrailingWhitespaceEnabled()) ? AppendTrai
lingWhitespace::ShouldAppend : AppendTrailingWhitespace::DontAppend; |
| 351 | 359 |
| 352 return selectClosestWordFromHitTestResult(result.hitTestResult(), appendTrai
lingWhitespace); | 360 return selectClosestWordFromHitTestResult(result.hitTestResult(), appendTrai
lingWhitespace, SelectInputEventType::Mouse); |
| 353 } | 361 } |
| 354 | 362 |
| 355 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven
tWithHitTestResults& result) | 363 void SelectionController::selectClosestMisspellingFromMouseEvent(const MouseEven
tWithHitTestResults& result) |
| 356 { | 364 { |
| 357 if (!m_mouseDownMayStartSelect) | 365 if (!m_mouseDownMayStartSelect) |
| 358 return; | 366 return; |
| 359 | 367 |
| 360 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), | 368 selectClosestMisspellingFromHitTestResult(result.hitTestResult(), |
| 361 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW
hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi
tespace::DontAppend); | 369 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrailingW
hitespaceEnabled()) ? AppendTrailingWhitespace::ShouldAppend : AppendTrailingWhi
tespace::DontAppend); |
| 362 | 370 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 | 541 |
| 534 return false; | 542 return false; |
| 535 } | 543 } |
| 536 | 544 |
| 537 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges
tureEvent, const HitTestResult& hitTestResult) | 545 bool SelectionController::handleGestureLongPress(const PlatformGestureEvent& ges
tureEvent, const HitTestResult& hitTestResult) |
| 538 { | 546 { |
| 539 if (hitTestResult.isLiveLink()) | 547 if (hitTestResult.isLiveLink()) |
| 540 return false; | 548 return false; |
| 541 | 549 |
| 542 Node* innerNode = hitTestResult.innerNode(); | 550 Node* innerNode = hitTestResult.innerNode(); |
| 543 #if OS(ANDROID) | |
| 544 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() ||
innerNode->isTextNode() || innerNode->canStartSelection()); | 551 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() ||
innerNode->isTextNode() || innerNode->canStartSelection()); |
| 545 #else | |
| 546 bool innerNodeIsSelectable = innerNode && (innerNode->isContentEditable() ||
innerNode->isTextNode()); | |
| 547 #endif | |
| 548 if (!innerNodeIsSelectable) | 552 if (!innerNodeIsSelectable) |
| 549 return false; | 553 return false; |
| 550 | 554 |
| 551 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace::
DontAppend); | 555 selectClosestWordFromHitTestResult(hitTestResult, AppendTrailingWhitespace::
DontAppend, SelectInputEventType::GestureLongPress); |
| 552 return selection().isRange(); | 556 return selection().isRange(); |
| 553 } | 557 } |
| 554 | 558 |
| 555 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult
s& mev, const LayoutPoint& position) | 559 void SelectionController::sendContextMenuEvent(const MouseEventWithHitTestResult
s& mev, const LayoutPoint& position) |
| 556 { | 560 { |
| 557 if (selection().contains(position) | 561 if (selection().contains(position) |
| 558 || mev.scrollbar() | 562 || mev.scrollbar() |
| 559 // FIXME: In the editable case, word selection sometimes selects content
that isn't underneath the mouse. | 563 // FIXME: In the editable case, word selection sometimes selects content
that isn't underneath the mouse. |
| 560 // If the selection is non-editable, we do word selection to make it eas
ier to use the contextual menu items | 564 // If the selection is non-editable, we do word selection to make it eas
ier to use the contextual menu items |
| 561 // available for text selections. But only if we're above text. | 565 // available for text selections. But only if we're above text. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 else | 621 else |
| 618 m_selectionState = SelectionState::HaveNotStartedSelection; | 622 m_selectionState = SelectionState::HaveNotStartedSelection; |
| 619 } | 623 } |
| 620 | 624 |
| 621 FrameSelection& SelectionController::selection() const | 625 FrameSelection& SelectionController::selection() const |
| 622 { | 626 { |
| 623 return m_frame->selection(); | 627 return m_frame->selection(); |
| 624 } | 628 } |
| 625 | 629 |
| 626 } // namespace blink | 630 } // namespace blink |
| OLD | NEW |