| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights |
| 3 * reserved. | 3 * reserved. |
| 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
| 5 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 5 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
| 6 * Copyright (C) 2015 Google Inc. All rights reserved. | 6 * Copyright (C) 2015 Google Inc. All rights reserved. |
| 7 * | 7 * |
| 8 * Redistribution and use in source and binary forms, with or without | 8 * Redistribution and use in source and binary forms, with or without |
| 9 * modification, are permitted provided that the following conditions | 9 * modification, are permitted provided that the following conditions |
| 10 * are met: | 10 * are met: |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 | 157 |
| 158 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); | 158 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); |
| 159 Node* innerNode = event.innerNode(); | 159 Node* innerNode = event.innerNode(); |
| 160 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | 160 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) |
| 161 return false; | 161 return false; |
| 162 | 162 |
| 163 // Extend the selection if the Shift key is down, unless the click is in a | 163 // Extend the selection if the Shift key is down, unless the click is in a |
| 164 // link or image. | 164 // link or image. |
| 165 bool extendSelection = isExtendingSelection(event); | 165 bool extendSelection = isExtendingSelection(event); |
| 166 | 166 |
| 167 // Don't restart the selection when the mouse is pressed on an | |
| 168 // existing selection so we can allow for text dragging. | |
| 169 if (FrameView* view = m_frame->view()) { | |
| 170 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()); | |
| 171 if (!extendSelection && selection().contains(vPoint)) { | |
| 172 m_mouseDownWasSingleClickInSelection = true; | |
| 173 return false; | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 const VisiblePositionInFlatTree& visibleHitPos = | 167 const VisiblePositionInFlatTree& visibleHitPos = |
| 178 visiblePositionOfHitTestResult(event.hitTestResult()); | 168 visiblePositionOfHitTestResult(event.hitTestResult()); |
| 179 const VisiblePositionInFlatTree& visiblePos = | 169 const VisiblePositionInFlatTree& visiblePos = |
| 180 visibleHitPos.isNull() | 170 visibleHitPos.isNull() |
| 181 ? createVisiblePosition( | 171 ? createVisiblePosition( |
| 182 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) | 172 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) |
| 183 : visibleHitPos; | 173 : visibleHitPos; |
| 184 const VisibleSelectionInFlatTree& selection = | 174 const VisibleSelectionInFlatTree& selection = |
| 185 this->selection().visibleSelection<EditingInFlatTreeStrategy>(); | 175 this->selection().visibleSelection<EditingInFlatTreeStrategy>(); |
| 186 | 176 |
| 177 // Don't restart the selection when the mouse is pressed on an |
| 178 // existing selection so we can allow for text dragging. |
| 179 if (!extendSelection && this->selection().contains(event.hitTestResult())) { |
| 180 m_mouseDownWasSingleClickInSelection = true; |
| 181 if (!event.event().fromTouch()) |
| 182 return false; |
| 183 |
| 184 if (!this->selection().isHandleVisible()) { |
| 185 updateSelectionForMouseDownDispatchingSelectStart( |
| 186 innerNode, selection, CharacterGranularity, |
| 187 HandleVisibility::Visible); |
| 188 return false; |
| 189 } |
| 190 } |
| 191 |
| 187 if (extendSelection && !selection.isNone()) { | 192 if (extendSelection && !selection.isNone()) { |
| 188 // Note: "fast/events/shift-click-user-select-none.html" makes | 193 // Note: "fast/events/shift-click-user-select-none.html" makes |
| 189 // |pos.isNull()| true. | 194 // |pos.isNull()| true. |
| 190 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll( | 195 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll( |
| 191 innerNode, selection.start(), selection.end(), | 196 innerNode, selection.start(), selection.end(), |
| 192 visiblePos.deepEquivalent()); | 197 visiblePos.deepEquivalent()); |
| 193 SelectionInFlatTree::Builder builder; | 198 SelectionInFlatTree::Builder builder; |
| 194 builder.setGranularity(this->selection().granularity()); | 199 builder.setGranularity(this->selection().granularity()); |
| 195 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) { | 200 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) { |
| 196 builder.setBaseAndExtent(selection.base(), pos); | 201 builder.setBaseAndExtent(selection.base(), pos); |
| 197 } else if (pos.isNull()) { | 202 } else if (pos.isNull()) { |
| 198 builder.setBaseAndExtent(selection.base(), selection.extent()); | 203 builder.setBaseAndExtent(selection.base(), selection.extent()); |
| 199 } else { | 204 } else { |
| 200 // Shift+Click deselects when selection was created right-to-left | 205 // Shift+Click deselects when selection was created right-to-left |
| 201 const PositionInFlatTree& start = selection.start(); | 206 const PositionInFlatTree& start = selection.start(); |
| 202 const PositionInFlatTree& end = selection.end(); | 207 const PositionInFlatTree& end = selection.end(); |
| 203 const int distanceToStart = textDistance(start, pos); | 208 const int distanceToStart = textDistance(start, pos); |
| 204 const int distanceToEnd = textDistance(pos, end); | 209 const int distanceToEnd = textDistance(pos, end); |
| 205 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start, | 210 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start, |
| 206 pos); | 211 pos); |
| 207 } | 212 } |
| 208 | 213 |
| 209 updateSelectionForMouseDownDispatchingSelectStart( | 214 updateSelectionForMouseDownDispatchingSelectStart( |
| 210 innerNode, createVisibleSelection(builder.build()), | 215 innerNode, createVisibleSelection(builder.build()), |
| 211 this->selection().granularity()); | 216 this->selection().granularity(), HandleVisibility::NotVisible); |
| 212 return false; | 217 return false; |
| 213 } | 218 } |
| 214 | 219 |
| 215 if (m_selectionState == SelectionState::ExtendedSelection) { | 220 if (m_selectionState == SelectionState::ExtendedSelection) { |
| 216 updateSelectionForMouseDownDispatchingSelectStart(innerNode, selection, | 221 updateSelectionForMouseDownDispatchingSelectStart( |
| 217 CharacterGranularity); | 222 innerNode, selection, CharacterGranularity, |
| 223 HandleVisibility::NotVisible); |
| 218 return false; | 224 return false; |
| 219 } | 225 } |
| 220 | 226 |
| 221 if (visiblePos.isNull()) { | 227 if (visiblePos.isNull()) { |
| 222 updateSelectionForMouseDownDispatchingSelectStart( | 228 updateSelectionForMouseDownDispatchingSelectStart( |
| 223 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity); | 229 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity, |
| 230 HandleVisibility::NotVisible); |
| 224 return false; | 231 return false; |
| 225 } | 232 } |
| 226 | 233 |
| 234 bool isHandleVisible = false; |
| 235 if (hasEditableStyle(*innerNode)) { |
| 236 const bool isTextBoxEmpty = |
| 237 createVisibleSelection(SelectionInFlatTree::Builder() |
| 238 .selectAllChildren(*innerNode) |
| 239 .build()) |
| 240 .isCaret(); |
| 241 const bool notLeftClick = event.event().pointerProperties().button != |
| 242 WebPointerProperties::Button::Left; |
| 243 if (!isTextBoxEmpty || notLeftClick) |
| 244 isHandleVisible = event.event().fromTouch(); |
| 245 } |
| 246 |
| 227 updateSelectionForMouseDownDispatchingSelectStart( | 247 updateSelectionForMouseDownDispatchingSelectStart( |
| 228 innerNode, | 248 innerNode, |
| 229 expandSelectionToRespectUserSelectAll( | 249 expandSelectionToRespectUserSelectAll( |
| 230 innerNode, createVisibleSelection( | 250 innerNode, createVisibleSelection( |
| 231 SelectionInFlatTree::Builder() | 251 SelectionInFlatTree::Builder() |
| 232 .collapse(visiblePos.toPositionWithAffinity()) | 252 .collapse(visiblePos.toPositionWithAffinity()) |
| 233 .build())), | 253 .build())), |
| 234 CharacterGranularity); | 254 CharacterGranularity, isHandleVisible ? HandleVisibility::Visible |
| 255 : HandleVisibility::NotVisible); |
| 235 return false; | 256 return false; |
| 236 } | 257 } |
| 237 | 258 |
| 238 void SelectionController::updateSelectionForMouseDrag( | 259 void SelectionController::updateSelectionForMouseDrag( |
| 239 const HitTestResult& hitTestResult, | 260 const HitTestResult& hitTestResult, |
| 240 Node* mousePressNode, | 261 Node* mousePressNode, |
| 241 const LayoutPoint& dragStartPos, | 262 const LayoutPoint& dragStartPos, |
| 242 const IntPoint& lastKnownMousePosition) { | 263 const IntPoint& lastKnownMousePosition) { |
| 243 if (!m_mouseDownMayStartSelect) | 264 if (!m_mouseDownMayStartSelect) |
| 244 return; | 265 return; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 // |newSelection|. | 375 // |newSelection|. |
| 355 if (selection().granularity() != CharacterGranularity) { | 376 if (selection().granularity() != CharacterGranularity) { |
| 356 newSelection = createVisibleSelection( | 377 newSelection = createVisibleSelection( |
| 357 SelectionInFlatTree::Builder() | 378 SelectionInFlatTree::Builder() |
| 358 .setBaseAndExtent(newSelection.base(), newSelection.extent()) | 379 .setBaseAndExtent(newSelection.base(), newSelection.extent()) |
| 359 .setGranularity(selection().granularity()) | 380 .setGranularity(selection().granularity()) |
| 360 .build()); | 381 .build()); |
| 361 } | 382 } |
| 362 | 383 |
| 363 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), | 384 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), |
| 364 AdjustEndpointsAtBidiBoundary); | 385 AdjustEndpointsAtBidiBoundary, |
| 386 HandleVisibility::NotVisible); |
| 365 } | 387 } |
| 366 | 388 |
| 367 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( | 389 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( |
| 368 Node* targetNode, | 390 Node* targetNode, |
| 369 const VisibleSelectionInFlatTree& selection, | 391 const VisibleSelectionInFlatTree& selection, |
| 370 TextGranularity granularity) { | 392 TextGranularity granularity, |
| 393 HandleVisibility handleVisibility) { |
| 371 if (targetNode && targetNode->layoutObject() && | 394 if (targetNode && targetNode->layoutObject() && |
| 372 !targetNode->layoutObject()->isSelectable()) | 395 !targetNode->layoutObject()->isSelectable()) |
| 373 return false; | 396 return false; |
| 374 | 397 |
| 375 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) | 398 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) |
| 376 return false; | 399 return false; |
| 377 | 400 |
| 378 // |dispatchSelectStart()| can change document hosted by |m_frame|. | 401 // |dispatchSelectStart()| can change document hosted by |m_frame|. |
| 379 if (!this->selection().isAvailable()) | 402 if (!this->selection().isAvailable()) |
| 380 return false; | 403 return false; |
| 381 | 404 |
| 382 if (!selection.isValidFor(this->selection().document())) | 405 if (!selection.isValidFor(this->selection().document())) |
| 383 return false; | 406 return false; |
| 384 | 407 |
| 385 if (selection.isRange()) { | 408 if (selection.isRange()) { |
| 386 m_selectionState = SelectionState::ExtendedSelection; | 409 m_selectionState = SelectionState::ExtendedSelection; |
| 387 } else { | 410 } else { |
| 388 granularity = CharacterGranularity; | 411 granularity = CharacterGranularity; |
| 389 m_selectionState = SelectionState::PlacedCaret; | 412 m_selectionState = SelectionState::PlacedCaret; |
| 390 } | 413 } |
| 391 | 414 |
| 392 setNonDirectionalSelectionIfNeeded(selection, granularity, | 415 setNonDirectionalSelectionIfNeeded(selection, granularity, |
| 393 DoNotAdjustEndpoints); | 416 DoNotAdjustEndpoints, handleVisibility); |
| 394 | 417 |
| 395 return true; | 418 return true; |
| 396 } | 419 } |
| 397 | 420 |
| 398 void SelectionController::selectClosestWordFromHitTestResult( | 421 void SelectionController::selectClosestWordFromHitTestResult( |
| 399 const HitTestResult& result, | 422 const HitTestResult& result, |
| 400 AppendTrailingWhitespace appendTrailingWhitespace, | 423 AppendTrailingWhitespace appendTrailingWhitespace, |
| 401 SelectInputEventType selectInputEventType) { | 424 SelectInputEventType selectInputEventType) { |
| 402 Node* innerNode = result.innerNode(); | 425 Node* innerNode = result.innerNode(); |
| 403 VisibleSelectionInFlatTree newSelection; | 426 VisibleSelectionInFlatTree newSelection; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 417 const VisiblePositionInFlatTree& pos = | 440 const VisiblePositionInFlatTree& pos = |
| 418 visiblePositionOfHitTestResult(adjustedHitTestResult); | 441 visiblePositionOfHitTestResult(adjustedHitTestResult); |
| 419 if (pos.isNotNull()) { | 442 if (pos.isNotNull()) { |
| 420 newSelection = | 443 newSelection = |
| 421 createVisibleSelection(SelectionInFlatTree::Builder() | 444 createVisibleSelection(SelectionInFlatTree::Builder() |
| 422 .collapse(pos.toPositionWithAffinity()) | 445 .collapse(pos.toPositionWithAffinity()) |
| 423 .setGranularity(WordGranularity) | 446 .setGranularity(WordGranularity) |
| 424 .build()); | 447 .build()); |
| 425 } | 448 } |
| 426 | 449 |
| 450 HandleVisibility visibility = HandleVisibility::NotVisible; |
| 427 if (selectInputEventType == SelectInputEventType::Touch) { | 451 if (selectInputEventType == SelectInputEventType::Touch) { |
| 428 // If node doesn't have text except space, tab or line break, do not | 452 // If node doesn't have text except space, tab or line break, do not |
| 429 // select that 'empty' area. | 453 // select that 'empty' area. |
| 430 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end()); | 454 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end()); |
| 431 const String& str = | 455 const String& str = |
| 432 plainText(range, hasEditableStyle(*innerNode) | 456 plainText(range, hasEditableStyle(*innerNode) |
| 433 ? TextIteratorEmitsObjectReplacementCharacter | 457 ? TextIteratorEmitsObjectReplacementCharacter |
| 434 : TextIteratorDefaultBehavior); | 458 : TextIteratorDefaultBehavior); |
| 435 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) | 459 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) |
| 436 return; | 460 return; |
| 437 | 461 |
| 438 if (newSelection.rootEditableElement() && | 462 if (newSelection.rootEditableElement() && |
| 439 pos.deepEquivalent() == | 463 pos.deepEquivalent() == |
| 440 VisiblePositionInFlatTree::lastPositionInNode( | 464 VisiblePositionInFlatTree::lastPositionInNode( |
| 441 newSelection.rootEditableElement()) | 465 newSelection.rootEditableElement()) |
| 442 .deepEquivalent()) | 466 .deepEquivalent()) |
| 443 return; | 467 return; |
| 468 visibility = HandleVisibility::Visible; |
| 444 } | 469 } |
| 445 | 470 |
| 446 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) | 471 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) |
| 447 newSelection.appendTrailingWhitespace(); | 472 newSelection.appendTrailingWhitespace(); |
| 448 | 473 |
| 449 updateSelectionForMouseDownDispatchingSelectStart( | 474 updateSelectionForMouseDownDispatchingSelectStart( |
| 450 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 475 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 451 WordGranularity); | 476 WordGranularity, visibility); |
| 452 } | 477 } |
| 453 | 478 |
| 454 void SelectionController::selectClosestMisspellingFromHitTestResult( | 479 void SelectionController::selectClosestMisspellingFromHitTestResult( |
| 455 const HitTestResult& result, | 480 const HitTestResult& result, |
| 456 AppendTrailingWhitespace appendTrailingWhitespace) { | 481 AppendTrailingWhitespace appendTrailingWhitespace) { |
| 457 Node* innerNode = result.innerNode(); | 482 Node* innerNode = result.innerNode(); |
| 458 VisibleSelectionInFlatTree newSelection; | 483 VisibleSelectionInFlatTree newSelection; |
| 459 | 484 |
| 460 if (!innerNode || !innerNode->layoutObject()) | 485 if (!innerNode || !innerNode->layoutObject()) |
| 461 return; | 486 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 475 newSelection = createVisibleSelection( | 500 newSelection = createVisibleSelection( |
| 476 SelectionInFlatTree::Builder().collapse(start).extend(end).build()); | 501 SelectionInFlatTree::Builder().collapse(start).extend(end).build()); |
| 477 } | 502 } |
| 478 } | 503 } |
| 479 | 504 |
| 480 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) | 505 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) |
| 481 newSelection.appendTrailingWhitespace(); | 506 newSelection.appendTrailingWhitespace(); |
| 482 | 507 |
| 483 updateSelectionForMouseDownDispatchingSelectStart( | 508 updateSelectionForMouseDownDispatchingSelectStart( |
| 484 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 509 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 485 WordGranularity); | 510 WordGranularity, HandleVisibility::NotVisible); |
| 486 } | 511 } |
| 487 | 512 |
| 488 void SelectionController::selectClosestWordFromMouseEvent( | 513 void SelectionController::selectClosestWordFromMouseEvent( |
| 489 const MouseEventWithHitTestResults& result) { | 514 const MouseEventWithHitTestResults& result) { |
| 490 if (!m_mouseDownMayStartSelect) | 515 if (!m_mouseDownMayStartSelect) |
| 491 return; | 516 return; |
| 492 | 517 |
| 493 AppendTrailingWhitespace appendTrailingWhitespace = | 518 AppendTrailingWhitespace appendTrailingWhitespace = |
| 494 (result.event().clickCount() == 2 && | 519 (result.event().clickCount() == 2 && |
| 495 m_frame->editor().isSelectTrailingWhitespaceEnabled()) | 520 m_frame->editor().isSelectTrailingWhitespaceEnabled()) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 const VisiblePositionInFlatTree pos = | 557 const VisiblePositionInFlatTree pos = |
| 533 visiblePositionOfHitTestResult(result.hitTestResult()); | 558 visiblePositionOfHitTestResult(result.hitTestResult()); |
| 534 if (pos.isNotNull() && | 559 if (pos.isNotNull() && |
| 535 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) { | 560 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) { |
| 536 newSelection = createVisibleSelection( | 561 newSelection = createVisibleSelection( |
| 537 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build()); | 562 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build()); |
| 538 } | 563 } |
| 539 | 564 |
| 540 updateSelectionForMouseDownDispatchingSelectStart( | 565 updateSelectionForMouseDownDispatchingSelectStart( |
| 541 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 566 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 542 WordGranularity); | 567 WordGranularity, HandleVisibility::NotVisible); |
| 543 } | 568 } |
| 544 | 569 |
| 545 // TODO(xiaochengh): We should not use reference to return value. | 570 // TODO(xiaochengh): We should not use reference to return value. |
| 546 static void adjustEndpointsAtBidiBoundary( | 571 static void adjustEndpointsAtBidiBoundary( |
| 547 VisiblePositionInFlatTree& visibleBase, | 572 VisiblePositionInFlatTree& visibleBase, |
| 548 VisiblePositionInFlatTree& visibleExtent) { | 573 VisiblePositionInFlatTree& visibleExtent) { |
| 549 DCHECK(visibleBase.isValid()); | 574 DCHECK(visibleBase.isValid()); |
| 550 DCHECK(visibleExtent.isValid()); | 575 DCHECK(visibleExtent.isValid()); |
| 551 | 576 |
| 552 RenderedPosition base(visibleBase); | 577 RenderedPosition base(visibleBase); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { | 615 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { |
| 591 visibleExtent = createVisiblePosition( | 616 visibleExtent = createVisiblePosition( |
| 592 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun())); | 617 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun())); |
| 593 return; | 618 return; |
| 594 } | 619 } |
| 595 } | 620 } |
| 596 | 621 |
| 597 void SelectionController::setNonDirectionalSelectionIfNeeded( | 622 void SelectionController::setNonDirectionalSelectionIfNeeded( |
| 598 const VisibleSelectionInFlatTree& passedNewSelection, | 623 const VisibleSelectionInFlatTree& passedNewSelection, |
| 599 TextGranularity granularity, | 624 TextGranularity granularity, |
| 600 EndPointsAdjustmentMode endpointsAdjustmentMode) { | 625 EndPointsAdjustmentMode endpointsAdjustmentMode, |
| 626 HandleVisibility handleVisibility) { |
| 601 VisibleSelectionInFlatTree newSelection = passedNewSelection; | 627 VisibleSelectionInFlatTree newSelection = passedNewSelection; |
| 602 bool isDirectional = | 628 bool isDirectional = |
| 603 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || | 629 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || |
| 604 newSelection.isDirectional(); | 630 newSelection.isDirectional(); |
| 605 | 631 |
| 606 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 632 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 607 // needs to be audited. See http://crbug.com/590369 for more details. | 633 // needs to be audited. See http://crbug.com/590369 for more details. |
| 608 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 634 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 609 | 635 |
| 610 const PositionInFlatTree& basePosition = | 636 const PositionInFlatTree& basePosition = |
| (...skipping 18 matching lines...) Expand all Loading... |
| 629 newSelection.setExtent(newExtent); | 655 newSelection.setExtent(newExtent); |
| 630 } else if (originalBase.isNotNull()) { | 656 } else if (originalBase.isNotNull()) { |
| 631 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() == | 657 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() == |
| 632 newSelection.base()) | 658 newSelection.base()) |
| 633 newSelection.setBase(originalBase); | 659 newSelection.setBase(originalBase); |
| 634 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); | 660 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); |
| 635 } | 661 } |
| 636 | 662 |
| 637 // Adjusting base and extent will make newSelection always directional | 663 // Adjusting base and extent will make newSelection always directional |
| 638 newSelection.setIsDirectional(isDirectional); | 664 newSelection.setIsDirectional(isDirectional); |
| 639 if (selection().visibleSelection<EditingInFlatTreeStrategy>() == newSelection) | 665 const bool isHandleVisible = handleVisibility == HandleVisibility::Visible; |
| 666 if (selection().visibleSelection<EditingInFlatTreeStrategy>() == |
| 667 newSelection && |
| 668 selection().isHandleVisible() == isHandleVisible) |
| 640 return; | 669 return; |
| 641 | 670 |
| 642 const FrameSelection::SetSelectionOptions options = | 671 FrameSelection::SetSelectionOptions options = |
| 643 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; | 672 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; |
| 673 if (isHandleVisible) |
| 674 options |= FrameSelection::HandleVisible; |
| 644 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, | 675 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, |
| 645 granularity); | 676 granularity); |
| 646 } | 677 } |
| 647 | 678 |
| 648 bool SelectionController::handleMousePressEventDoubleClick( | 679 bool SelectionController::handleMousePressEventDoubleClick( |
| 649 const MouseEventWithHitTestResults& event) { | 680 const MouseEventWithHitTestResults& event) { |
| 650 TRACE_EVENT0("blink", | 681 TRACE_EVENT0("blink", |
| 651 "SelectionController::handleMousePressEventDoubleClick"); | 682 "SelectionController::handleMousePressEventDoubleClick"); |
| 652 | 683 |
| 653 if (!selection().isAvailable()) | 684 if (!selection().isAvailable()) |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 const VisiblePositionInFlatTree& pos = | 729 const VisiblePositionInFlatTree& pos = |
| 699 visiblePositionOfHitTestResult(event.hitTestResult()); | 730 visiblePositionOfHitTestResult(event.hitTestResult()); |
| 700 if (pos.isNotNull()) { | 731 if (pos.isNotNull()) { |
| 701 newSelection = | 732 newSelection = |
| 702 createVisibleSelection(SelectionInFlatTree::Builder() | 733 createVisibleSelection(SelectionInFlatTree::Builder() |
| 703 .collapse(pos.toPositionWithAffinity()) | 734 .collapse(pos.toPositionWithAffinity()) |
| 704 .setGranularity(ParagraphGranularity) | 735 .setGranularity(ParagraphGranularity) |
| 705 .build()); | 736 .build()); |
| 706 } | 737 } |
| 707 | 738 |
| 739 bool isHandleVisible = event.event().fromTouch() && newSelection.isRange(); |
| 740 |
| 708 return updateSelectionForMouseDownDispatchingSelectStart( | 741 return updateSelectionForMouseDownDispatchingSelectStart( |
| 709 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 742 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 710 ParagraphGranularity); | 743 ParagraphGranularity, isHandleVisible ? HandleVisibility::Visible |
| 744 : HandleVisibility::NotVisible); |
| 711 } | 745 } |
| 712 | 746 |
| 713 void SelectionController::handleMousePressEvent( | 747 void SelectionController::handleMousePressEvent( |
| 714 const MouseEventWithHitTestResults& event) { | 748 const MouseEventWithHitTestResults& event) { |
| 715 // If we got the event back, that must mean it wasn't prevented, | 749 // If we got the event back, that must mean it wasn't prevented, |
| 716 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | 750 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. |
| 717 m_mouseDownMayStartSelect = | 751 m_mouseDownMayStartSelect = |
| 718 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) && | 752 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) && |
| 719 !event.scrollbar(); | 753 !event.scrollbar(); |
| 720 m_mouseDownWasSingleClickInSelection = false; | 754 m_mouseDownWasSingleClickInSelection = false; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 pos.deepEquivalent().parentAnchoredEquivalent()), | 936 pos.deepEquivalent().parentAnchoredEquivalent()), |
| 903 DocumentMarker::MisspellingMarkers()) | 937 DocumentMarker::MisspellingMarkers()) |
| 904 .size() > 0; | 938 .size() > 0; |
| 905 } | 939 } |
| 906 | 940 |
| 907 void SelectionController::sendContextMenuEvent( | 941 void SelectionController::sendContextMenuEvent( |
| 908 const MouseEventWithHitTestResults& mev, | 942 const MouseEventWithHitTestResults& mev, |
| 909 const LayoutPoint& position) { | 943 const LayoutPoint& position) { |
| 910 if (!selection().isAvailable()) | 944 if (!selection().isAvailable()) |
| 911 return; | 945 return; |
| 912 if (selection().contains(position) || mev.scrollbar() || | 946 if (selection().contains(mev.hitTestResult()) || mev.scrollbar() || |
| 913 // FIXME: In the editable case, word selection sometimes selects content | 947 // FIXME: In the editable case, word selection sometimes selects content |
| 914 // that isn't underneath the mouse. | 948 // that isn't underneath the mouse. |
| 915 // If the selection is non-editable, we do word selection to make it | 949 // If the selection is non-editable, we do word selection to make it |
| 916 // easier to use the contextual menu items available for text selections. | 950 // easier to use the contextual menu items available for text selections. |
| 917 // But only if we're above text. | 951 // But only if we're above text. |
| 918 !(selection().isContentEditable() || | 952 !(selection().isContentEditable() || |
| 919 (mev.innerNode() && mev.innerNode()->isTextNode()))) | 953 (mev.innerNode() && mev.innerNode()->isTextNode()))) |
| 920 return; | 954 return; |
| 921 | 955 |
| 922 // Context menu events are always allowed to perform a selection. | 956 // Context menu events are always allowed to perform a selection. |
| 923 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, | 957 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, |
| 924 true); | 958 true); |
| 925 | 959 |
| 926 if (hitTestResultIsMisspelled(mev.hitTestResult())) | 960 if (hitTestResultIsMisspelled(mev.hitTestResult())) |
| 927 return selectClosestMisspellingFromMouseEvent(mev); | 961 return selectClosestMisspellingFromMouseEvent(mev); |
| 928 | 962 |
| 929 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) | 963 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) |
| 930 return; | 964 return; |
| 931 | 965 |
| 932 selectClosestWordOrLinkFromMouseEvent(mev); | 966 selectClosestWordOrLinkFromMouseEvent(mev); |
| 933 } | 967 } |
| 934 | 968 |
| 935 void SelectionController::passMousePressEventToSubframe( | 969 void SelectionController::passMousePressEventToSubframe( |
| 936 const MouseEventWithHitTestResults& mev) { | 970 const MouseEventWithHitTestResults& mev) { |
| 937 // If we're clicking into a frame that is selected, the frame will appear | 971 // If we're clicking into a frame that is selected, the frame will appear |
| 938 // greyed out even though we're clicking on the selection. This looks | 972 // greyed out even though we're clicking on the selection. This looks |
| 939 // really strange (having the whole frame be greyed out), so we deselect the | 973 // really strange (having the whole frame be greyed out), so we deselect the |
| 940 // selection. | 974 // selection. |
| 941 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | 975 if (!selection().contains(mev.hitTestResult())) |
| 942 if (!selection().contains(p)) | |
| 943 return; | 976 return; |
| 944 | 977 |
| 945 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 978 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 946 // needs to be audited. See http://crbug.com/590369 for more details. | 979 // needs to be audited. See http://crbug.com/590369 for more details. |
| 947 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 980 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 948 | 981 |
| 949 const VisiblePositionInFlatTree& visiblePos = | 982 const VisiblePositionInFlatTree& visiblePos = |
| 950 visiblePositionOfHitTestResult(mev.hitTestResult()); | 983 visiblePositionOfHitTestResult(mev.hitTestResult()); |
| 951 if (visiblePos.isNull()) { | 984 if (visiblePos.isNull()) { |
| 952 selection().setSelection(VisibleSelectionInFlatTree()); | 985 selection().setSelection(VisibleSelectionInFlatTree()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 return event.event().altKey() && event.isOverLink(); | 1023 return event.event().altKey() && event.isOverLink(); |
| 991 } | 1024 } |
| 992 | 1025 |
| 993 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { | 1026 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { |
| 994 bool isMouseDownOnLinkOrImage = | 1027 bool isMouseDownOnLinkOrImage = |
| 995 event.isOverLink() || event.hitTestResult().image(); | 1028 event.isOverLink() || event.hitTestResult().image(); |
| 996 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; | 1029 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; |
| 997 } | 1030 } |
| 998 | 1031 |
| 999 } // namespace blink | 1032 } // namespace blink |
| OLD | NEW |