| 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 | 160 |
| 161 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); | 161 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); |
| 162 Node* innerNode = event.innerNode(); | 162 Node* innerNode = event.innerNode(); |
| 163 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) | 163 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect)) |
| 164 return false; | 164 return false; |
| 165 | 165 |
| 166 // Extend the selection if the Shift key is down, unless the click is in a | 166 // Extend the selection if the Shift key is down, unless the click is in a |
| 167 // link or image. | 167 // link or image. |
| 168 bool extendSelection = isExtendingSelection(event); | 168 bool extendSelection = isExtendingSelection(event); |
| 169 | 169 |
| 170 // Don't restart the selection when the mouse is pressed on an | |
| 171 // existing selection so we can allow for text dragging. | |
| 172 if (FrameView* view = m_frame->view()) { | |
| 173 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()); | |
| 174 if (!extendSelection && selection().contains(vPoint)) { | |
| 175 m_mouseDownWasSingleClickInSelection = true; | |
| 176 return false; | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 const VisiblePositionInFlatTree& visibleHitPos = | 170 const VisiblePositionInFlatTree& visibleHitPos = |
| 181 visiblePositionOfHitTestResult(event.hitTestResult()); | 171 visiblePositionOfHitTestResult(event.hitTestResult()); |
| 182 const VisiblePositionInFlatTree& visiblePos = | 172 const VisiblePositionInFlatTree& visiblePos = |
| 183 visibleHitPos.isNull() | 173 visibleHitPos.isNull() |
| 184 ? createVisiblePosition( | 174 ? createVisiblePosition( |
| 185 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) | 175 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) |
| 186 : visibleHitPos; | 176 : visibleHitPos; |
| 187 const VisibleSelectionInFlatTree& selection = | 177 const VisibleSelectionInFlatTree& selection = |
| 188 this->selection().visibleSelection<EditingInFlatTreeStrategy>(); | 178 this->selection().visibleSelection<EditingInFlatTreeStrategy>(); |
| 189 | 179 |
| 180 // Don't restart the selection when the mouse is pressed on an |
| 181 // existing selection so we can allow for text dragging. |
| 182 if (!extendSelection && this->selection().contains(event.hitTestResult())) { |
| 183 m_mouseDownWasSingleClickInSelection = true; |
| 184 if (!event.event().fromTouch()) |
| 185 return false; |
| 186 |
| 187 if (!this->selection().isHandleVisible()) { |
| 188 updateSelectionForMouseDownDispatchingSelectStart( |
| 189 innerNode, selection, CharacterGranularity, |
| 190 HandleVisibility::Visible); |
| 191 return false; |
| 192 } |
| 193 } |
| 194 |
| 190 if (extendSelection && !selection.isNone()) { | 195 if (extendSelection && !selection.isNone()) { |
| 191 // Note: "fast/events/shift-click-user-select-none.html" makes | 196 // Note: "fast/events/shift-click-user-select-none.html" makes |
| 192 // |pos.isNull()| true. | 197 // |pos.isNull()| true. |
| 193 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll( | 198 const PositionInFlatTree& pos = adjustPositionRespectUserSelectAll( |
| 194 innerNode, selection.start(), selection.end(), | 199 innerNode, selection.start(), selection.end(), |
| 195 visiblePos.deepEquivalent()); | 200 visiblePos.deepEquivalent()); |
| 196 SelectionInFlatTree::Builder builder; | 201 SelectionInFlatTree::Builder builder; |
| 197 builder.setGranularity(this->selection().granularity()); | 202 builder.setGranularity(this->selection().granularity()); |
| 198 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) { | 203 if (m_frame->editor().behavior().shouldConsiderSelectionAsDirectional()) { |
| 199 builder.setBaseAndExtent(selection.base(), pos); | 204 builder.setBaseAndExtent(selection.base(), pos); |
| 200 } else if (pos.isNull()) { | 205 } else if (pos.isNull()) { |
| 201 builder.setBaseAndExtent(selection.base(), selection.extent()); | 206 builder.setBaseAndExtent(selection.base(), selection.extent()); |
| 202 } else { | 207 } else { |
| 203 // Shift+Click deselects when selection was created right-to-left | 208 // Shift+Click deselects when selection was created right-to-left |
| 204 const PositionInFlatTree& start = selection.start(); | 209 const PositionInFlatTree& start = selection.start(); |
| 205 const PositionInFlatTree& end = selection.end(); | 210 const PositionInFlatTree& end = selection.end(); |
| 206 const int distanceToStart = textDistance(start, pos); | 211 const int distanceToStart = textDistance(start, pos); |
| 207 const int distanceToEnd = textDistance(pos, end); | 212 const int distanceToEnd = textDistance(pos, end); |
| 208 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start, | 213 builder.setBaseAndExtent(distanceToStart <= distanceToEnd ? end : start, |
| 209 pos); | 214 pos); |
| 210 } | 215 } |
| 211 | 216 |
| 212 updateSelectionForMouseDownDispatchingSelectStart( | 217 updateSelectionForMouseDownDispatchingSelectStart( |
| 213 innerNode, createVisibleSelection(builder.build()), | 218 innerNode, createVisibleSelection(builder.build()), |
| 214 this->selection().granularity()); | 219 this->selection().granularity(), HandleVisibility::NotVisible); |
| 215 return false; | 220 return false; |
| 216 } | 221 } |
| 217 | 222 |
| 218 if (m_selectionState == SelectionState::ExtendedSelection) { | 223 if (m_selectionState == SelectionState::ExtendedSelection) { |
| 219 updateSelectionForMouseDownDispatchingSelectStart(innerNode, selection, | 224 updateSelectionForMouseDownDispatchingSelectStart( |
| 220 CharacterGranularity); | 225 innerNode, selection, CharacterGranularity, |
| 226 HandleVisibility::NotVisible); |
| 221 return false; | 227 return false; |
| 222 } | 228 } |
| 223 | 229 |
| 224 if (visiblePos.isNull()) { | 230 if (visiblePos.isNull()) { |
| 225 updateSelectionForMouseDownDispatchingSelectStart( | 231 updateSelectionForMouseDownDispatchingSelectStart( |
| 226 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity); | 232 innerNode, VisibleSelectionInFlatTree(), CharacterGranularity, |
| 233 HandleVisibility::NotVisible); |
| 227 return false; | 234 return false; |
| 228 } | 235 } |
| 229 | 236 |
| 237 bool isHandleVisible = false; |
| 238 if (hasEditableStyle(*innerNode)) { |
| 239 const bool isTextBoxEmpty = |
| 240 createVisibleSelection(SelectionInFlatTree::Builder() |
| 241 .selectAllChildren(*innerNode) |
| 242 .build()) |
| 243 .isCaret(); |
| 244 const bool notLeftClick = event.event().pointerProperties().button != |
| 245 WebPointerProperties::Button::Left; |
| 246 if (!isTextBoxEmpty || notLeftClick) |
| 247 isHandleVisible = event.event().fromTouch(); |
| 248 } |
| 249 |
| 230 updateSelectionForMouseDownDispatchingSelectStart( | 250 updateSelectionForMouseDownDispatchingSelectStart( |
| 231 innerNode, | 251 innerNode, |
| 232 expandSelectionToRespectUserSelectAll( | 252 expandSelectionToRespectUserSelectAll( |
| 233 innerNode, createVisibleSelection( | 253 innerNode, createVisibleSelection( |
| 234 SelectionInFlatTree::Builder() | 254 SelectionInFlatTree::Builder() |
| 235 .collapse(visiblePos.toPositionWithAffinity()) | 255 .collapse(visiblePos.toPositionWithAffinity()) |
| 236 .build())), | 256 .build())), |
| 237 CharacterGranularity); | 257 CharacterGranularity, isHandleVisible ? HandleVisibility::Visible |
| 258 : HandleVisibility::NotVisible); |
| 238 return false; | 259 return false; |
| 239 } | 260 } |
| 240 | 261 |
| 241 void SelectionController::updateSelectionForMouseDrag( | 262 void SelectionController::updateSelectionForMouseDrag( |
| 242 const HitTestResult& hitTestResult, | 263 const HitTestResult& hitTestResult, |
| 243 Node* mousePressNode, | 264 Node* mousePressNode, |
| 244 const LayoutPoint& dragStartPos, | 265 const LayoutPoint& dragStartPos, |
| 245 const IntPoint& lastKnownMousePosition) { | 266 const IntPoint& lastKnownMousePosition) { |
| 246 if (!m_mouseDownMayStartSelect) | 267 if (!m_mouseDownMayStartSelect) |
| 247 return; | 268 return; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 // |newSelection|. | 378 // |newSelection|. |
| 358 if (selection().granularity() != CharacterGranularity) { | 379 if (selection().granularity() != CharacterGranularity) { |
| 359 newSelection = createVisibleSelection( | 380 newSelection = createVisibleSelection( |
| 360 SelectionInFlatTree::Builder() | 381 SelectionInFlatTree::Builder() |
| 361 .setBaseAndExtent(newSelection.base(), newSelection.extent()) | 382 .setBaseAndExtent(newSelection.base(), newSelection.extent()) |
| 362 .setGranularity(selection().granularity()) | 383 .setGranularity(selection().granularity()) |
| 363 .build()); | 384 .build()); |
| 364 } | 385 } |
| 365 | 386 |
| 366 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), | 387 setNonDirectionalSelectionIfNeeded(newSelection, selection().granularity(), |
| 367 AdjustEndpointsAtBidiBoundary); | 388 AdjustEndpointsAtBidiBoundary, |
| 389 HandleVisibility::NotVisible); |
| 368 } | 390 } |
| 369 | 391 |
| 370 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( | 392 bool SelectionController::updateSelectionForMouseDownDispatchingSelectStart( |
| 371 Node* targetNode, | 393 Node* targetNode, |
| 372 const VisibleSelectionInFlatTree& selection, | 394 const VisibleSelectionInFlatTree& selection, |
| 373 TextGranularity granularity) { | 395 TextGranularity granularity, |
| 396 HandleVisibility handleVisibility) { |
| 374 if (targetNode && targetNode->layoutObject() && | 397 if (targetNode && targetNode->layoutObject() && |
| 375 !targetNode->layoutObject()->isSelectable()) | 398 !targetNode->layoutObject()->isSelectable()) |
| 376 return false; | 399 return false; |
| 377 | 400 |
| 378 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) | 401 if (dispatchSelectStart(targetNode) != DispatchEventResult::NotCanceled) |
| 379 return false; | 402 return false; |
| 380 | 403 |
| 381 // |dispatchSelectStart()| can change document hosted by |m_frame|. | 404 // |dispatchSelectStart()| can change document hosted by |m_frame|. |
| 382 if (!this->selection().isAvailable()) | 405 if (!this->selection().isAvailable()) |
| 383 return false; | 406 return false; |
| 384 | 407 |
| 385 if (!selection.isValidFor(this->selection().document())) | 408 if (!selection.isValidFor(this->selection().document())) |
| 386 return false; | 409 return false; |
| 387 | 410 |
| 388 if (selection.isRange()) { | 411 if (selection.isRange()) { |
| 389 m_selectionState = SelectionState::ExtendedSelection; | 412 m_selectionState = SelectionState::ExtendedSelection; |
| 390 } else { | 413 } else { |
| 391 granularity = CharacterGranularity; | 414 granularity = CharacterGranularity; |
| 392 m_selectionState = SelectionState::PlacedCaret; | 415 m_selectionState = SelectionState::PlacedCaret; |
| 393 } | 416 } |
| 394 | 417 |
| 395 setNonDirectionalSelectionIfNeeded(selection, granularity, | 418 setNonDirectionalSelectionIfNeeded(selection, granularity, |
| 396 DoNotAdjustEndpoints); | 419 DoNotAdjustEndpoints, handleVisibility); |
| 397 | 420 |
| 398 return true; | 421 return true; |
| 399 } | 422 } |
| 400 | 423 |
| 401 bool SelectionController::selectClosestWordFromHitTestResult( | 424 bool SelectionController::selectClosestWordFromHitTestResult( |
| 402 const HitTestResult& result, | 425 const HitTestResult& result, |
| 403 AppendTrailingWhitespace appendTrailingWhitespace, | 426 AppendTrailingWhitespace appendTrailingWhitespace, |
| 404 SelectInputEventType selectInputEventType) { | 427 SelectInputEventType selectInputEventType) { |
| 405 Node* innerNode = result.innerNode(); | 428 Node* innerNode = result.innerNode(); |
| 406 VisibleSelectionInFlatTree newSelection; | 429 VisibleSelectionInFlatTree newSelection; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 420 const VisiblePositionInFlatTree& pos = | 443 const VisiblePositionInFlatTree& pos = |
| 421 visiblePositionOfHitTestResult(adjustedHitTestResult); | 444 visiblePositionOfHitTestResult(adjustedHitTestResult); |
| 422 if (pos.isNotNull()) { | 445 if (pos.isNotNull()) { |
| 423 newSelection = | 446 newSelection = |
| 424 createVisibleSelection(SelectionInFlatTree::Builder() | 447 createVisibleSelection(SelectionInFlatTree::Builder() |
| 425 .collapse(pos.toPositionWithAffinity()) | 448 .collapse(pos.toPositionWithAffinity()) |
| 426 .setGranularity(WordGranularity) | 449 .setGranularity(WordGranularity) |
| 427 .build()); | 450 .build()); |
| 428 } | 451 } |
| 429 | 452 |
| 453 HandleVisibility visibility = HandleVisibility::NotVisible; |
| 430 if (selectInputEventType == SelectInputEventType::Touch) { | 454 if (selectInputEventType == SelectInputEventType::Touch) { |
| 431 // If node doesn't have text except space, tab or line break, do not | 455 // If node doesn't have text except space, tab or line break, do not |
| 432 // select that 'empty' area. | 456 // select that 'empty' area. |
| 433 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end()); | 457 EphemeralRangeInFlatTree range(newSelection.start(), newSelection.end()); |
| 434 const String& str = | 458 const String& str = |
| 435 plainText(range, hasEditableStyle(*innerNode) | 459 plainText(range, hasEditableStyle(*innerNode) |
| 436 ? TextIteratorEmitsObjectReplacementCharacter | 460 ? TextIteratorEmitsObjectReplacementCharacter |
| 437 : TextIteratorDefaultBehavior); | 461 : TextIteratorDefaultBehavior); |
| 438 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) | 462 if (str.isEmpty() || str.simplifyWhiteSpace().containsOnlyWhitespace()) |
| 439 return false; | 463 return false; |
| 440 | 464 |
| 441 if (newSelection.rootEditableElement() && | 465 if (newSelection.rootEditableElement() && |
| 442 pos.deepEquivalent() == | 466 pos.deepEquivalent() == |
| 443 VisiblePositionInFlatTree::lastPositionInNode( | 467 VisiblePositionInFlatTree::lastPositionInNode( |
| 444 newSelection.rootEditableElement()) | 468 newSelection.rootEditableElement()) |
| 445 .deepEquivalent()) | 469 .deepEquivalent()) |
| 446 return false; | 470 return false; |
| 471 |
| 472 visibility = HandleVisibility::Visible; |
| 447 } | 473 } |
| 448 | 474 |
| 449 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) | 475 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) |
| 450 newSelection.appendTrailingWhitespace(); | 476 newSelection.appendTrailingWhitespace(); |
| 451 | 477 |
| 452 return updateSelectionForMouseDownDispatchingSelectStart( | 478 return updateSelectionForMouseDownDispatchingSelectStart( |
| 453 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 479 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 454 WordGranularity); | 480 WordGranularity, visibility); |
| 455 } | 481 } |
| 456 | 482 |
| 457 void SelectionController::selectClosestMisspellingFromHitTestResult( | 483 void SelectionController::selectClosestMisspellingFromHitTestResult( |
| 458 const HitTestResult& result, | 484 const HitTestResult& result, |
| 459 AppendTrailingWhitespace appendTrailingWhitespace) { | 485 AppendTrailingWhitespace appendTrailingWhitespace) { |
| 460 Node* innerNode = result.innerNode(); | 486 Node* innerNode = result.innerNode(); |
| 461 VisibleSelectionInFlatTree newSelection; | 487 VisibleSelectionInFlatTree newSelection; |
| 462 | 488 |
| 463 if (!innerNode || !innerNode->layoutObject()) | 489 if (!innerNode || !innerNode->layoutObject()) |
| 464 return; | 490 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 478 newSelection = createVisibleSelection( | 504 newSelection = createVisibleSelection( |
| 479 SelectionInFlatTree::Builder().collapse(start).extend(end).build()); | 505 SelectionInFlatTree::Builder().collapse(start).extend(end).build()); |
| 480 } | 506 } |
| 481 } | 507 } |
| 482 | 508 |
| 483 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) | 509 if (appendTrailingWhitespace == AppendTrailingWhitespace::ShouldAppend) |
| 484 newSelection.appendTrailingWhitespace(); | 510 newSelection.appendTrailingWhitespace(); |
| 485 | 511 |
| 486 updateSelectionForMouseDownDispatchingSelectStart( | 512 updateSelectionForMouseDownDispatchingSelectStart( |
| 487 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 513 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 488 WordGranularity); | 514 WordGranularity, HandleVisibility::NotVisible); |
| 489 } | 515 } |
| 490 | 516 |
| 491 void SelectionController::selectClosestWordFromMouseEvent( | 517 void SelectionController::selectClosestWordFromMouseEvent( |
| 492 const MouseEventWithHitTestResults& result) { | 518 const MouseEventWithHitTestResults& result) { |
| 493 if (!m_mouseDownMayStartSelect) | 519 if (!m_mouseDownMayStartSelect) |
| 494 return; | 520 return; |
| 495 | 521 |
| 496 AppendTrailingWhitespace appendTrailingWhitespace = | 522 AppendTrailingWhitespace appendTrailingWhitespace = |
| 497 (result.event().clickCount() == 2 && | 523 (result.event().clickCount() == 2 && |
| 498 m_frame->editor().isSelectTrailingWhitespaceEnabled()) | 524 m_frame->editor().isSelectTrailingWhitespaceEnabled()) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 const VisiblePositionInFlatTree pos = | 561 const VisiblePositionInFlatTree pos = |
| 536 visiblePositionOfHitTestResult(result.hitTestResult()); | 562 visiblePositionOfHitTestResult(result.hitTestResult()); |
| 537 if (pos.isNotNull() && | 563 if (pos.isNotNull() && |
| 538 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) { | 564 pos.deepEquivalent().anchorNode()->isDescendantOf(URLElement)) { |
| 539 newSelection = createVisibleSelection( | 565 newSelection = createVisibleSelection( |
| 540 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build()); | 566 SelectionInFlatTree::Builder().selectAllChildren(*URLElement).build()); |
| 541 } | 567 } |
| 542 | 568 |
| 543 updateSelectionForMouseDownDispatchingSelectStart( | 569 updateSelectionForMouseDownDispatchingSelectStart( |
| 544 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 570 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 545 WordGranularity); | 571 WordGranularity, HandleVisibility::NotVisible); |
| 546 } | 572 } |
| 547 | 573 |
| 548 // TODO(xiaochengh): We should not use reference to return value. | 574 // TODO(xiaochengh): We should not use reference to return value. |
| 549 static void adjustEndpointsAtBidiBoundary( | 575 static void adjustEndpointsAtBidiBoundary( |
| 550 VisiblePositionInFlatTree& visibleBase, | 576 VisiblePositionInFlatTree& visibleBase, |
| 551 VisiblePositionInFlatTree& visibleExtent) { | 577 VisiblePositionInFlatTree& visibleExtent) { |
| 552 DCHECK(visibleBase.isValid()); | 578 DCHECK(visibleBase.isValid()); |
| 553 DCHECK(visibleExtent.isValid()); | 579 DCHECK(visibleExtent.isValid()); |
| 554 | 580 |
| 555 RenderedPosition base(visibleBase); | 581 RenderedPosition base(visibleBase); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { | 619 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { |
| 594 visibleExtent = createVisiblePosition( | 620 visibleExtent = createVisiblePosition( |
| 595 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun())); | 621 toPositionInFlatTree(extent.positionAtRightBoundaryOfBiDiRun())); |
| 596 return; | 622 return; |
| 597 } | 623 } |
| 598 } | 624 } |
| 599 | 625 |
| 600 void SelectionController::setNonDirectionalSelectionIfNeeded( | 626 void SelectionController::setNonDirectionalSelectionIfNeeded( |
| 601 const VisibleSelectionInFlatTree& passedNewSelection, | 627 const VisibleSelectionInFlatTree& passedNewSelection, |
| 602 TextGranularity granularity, | 628 TextGranularity granularity, |
| 603 EndPointsAdjustmentMode endpointsAdjustmentMode) { | 629 EndPointsAdjustmentMode endpointsAdjustmentMode, |
| 630 HandleVisibility handleVisibility) { |
| 604 VisibleSelectionInFlatTree newSelection = passedNewSelection; | 631 VisibleSelectionInFlatTree newSelection = passedNewSelection; |
| 605 bool isDirectional = | 632 bool isDirectional = |
| 606 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || | 633 m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() || |
| 607 newSelection.isDirectional(); | 634 newSelection.isDirectional(); |
| 608 | 635 |
| 609 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 636 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 610 // needs to be audited. See http://crbug.com/590369 for more details. | 637 // needs to be audited. See http://crbug.com/590369 for more details. |
| 611 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 638 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 612 | 639 |
| 613 const PositionInFlatTree& basePosition = | 640 const PositionInFlatTree& basePosition = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 633 newSelection.setExtent(newExtent); | 660 newSelection.setExtent(newExtent); |
| 634 } else if (originalBase.isNotNull()) { | 661 } else if (originalBase.isNotNull()) { |
| 635 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() == | 662 if (selection().visibleSelection<EditingInFlatTreeStrategy>().base() == |
| 636 newSelection.base()) | 663 newSelection.base()) |
| 637 newSelection.setBase(originalBase); | 664 newSelection.setBase(originalBase); |
| 638 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); | 665 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); |
| 639 } | 666 } |
| 640 | 667 |
| 641 // Adjusting base and extent will make newSelection always directional | 668 // Adjusting base and extent will make newSelection always directional |
| 642 newSelection.setIsDirectional(isDirectional); | 669 newSelection.setIsDirectional(isDirectional); |
| 643 if (selection().visibleSelection<EditingInFlatTreeStrategy>() == newSelection) | 670 const bool isHandleVisible = handleVisibility == HandleVisibility::Visible; |
| 671 if (selection().visibleSelection<EditingInFlatTreeStrategy>() == |
| 672 newSelection && |
| 673 selection().isHandleVisible() == isHandleVisible) |
| 644 return; | 674 return; |
| 645 | 675 |
| 646 const FrameSelection::SetSelectionOptions options = | 676 FrameSelection::SetSelectionOptions options = |
| 647 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; | 677 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle; |
| 678 if (isHandleVisible) |
| 679 options |= FrameSelection::HandleVisible; |
| 648 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, | 680 selection().setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, |
| 649 granularity); | 681 granularity); |
| 650 } | 682 } |
| 651 | 683 |
| 652 bool SelectionController::setCaretAtHitTestResult( | 684 bool SelectionController::setCaretAtHitTestResult( |
| 653 const HitTestResult& hitTestResult) { | 685 const HitTestResult& hitTestResult) { |
| 654 Node* innerNode = hitTestResult.innerNode(); | 686 Node* innerNode = hitTestResult.innerNode(); |
| 655 if (!innerNode) | 687 if (!innerNode) |
| 656 return false; | 688 return false; |
| 657 | 689 |
| 658 const VisiblePositionInFlatTree& visibleHitPos = | 690 const VisiblePositionInFlatTree& visibleHitPos = |
| 659 visiblePositionOfHitTestResult(hitTestResult); | 691 visiblePositionOfHitTestResult(hitTestResult); |
| 660 const VisiblePositionInFlatTree& visiblePos = | 692 const VisiblePositionInFlatTree& visiblePos = |
| 661 visibleHitPos.isNull() | 693 visibleHitPos.isNull() |
| 662 ? createVisiblePosition( | 694 ? createVisiblePosition( |
| 663 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) | 695 PositionInFlatTree::firstPositionInOrBeforeNode(innerNode)) |
| 664 : visibleHitPos; | 696 : visibleHitPos; |
| 665 | 697 |
| 666 return updateSelectionForMouseDownDispatchingSelectStart( | 698 return updateSelectionForMouseDownDispatchingSelectStart( |
| 667 innerNode, | 699 innerNode, |
| 668 expandSelectionToRespectUserSelectAll( | 700 expandSelectionToRespectUserSelectAll( |
| 669 innerNode, createVisibleSelection( | 701 innerNode, createVisibleSelection( |
| 670 SelectionInFlatTree::Builder() | 702 SelectionInFlatTree::Builder() |
| 671 .collapse(visiblePos.toPositionWithAffinity()) | 703 .collapse(visiblePos.toPositionWithAffinity()) |
| 672 .build())), | 704 .build())), |
| 673 CharacterGranularity); | 705 CharacterGranularity, HandleVisibility::Visible); |
| 674 } | 706 } |
| 675 | 707 |
| 676 bool SelectionController::handleMousePressEventDoubleClick( | 708 bool SelectionController::handleMousePressEventDoubleClick( |
| 677 const MouseEventWithHitTestResults& event) { | 709 const MouseEventWithHitTestResults& event) { |
| 678 TRACE_EVENT0("blink", | 710 TRACE_EVENT0("blink", |
| 679 "SelectionController::handleMousePressEventDoubleClick"); | 711 "SelectionController::handleMousePressEventDoubleClick"); |
| 680 | 712 |
| 681 if (!selection().isAvailable()) | 713 if (!selection().isAvailable()) |
| 682 return false; | 714 return false; |
| 683 | 715 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 const VisiblePositionInFlatTree& pos = | 758 const VisiblePositionInFlatTree& pos = |
| 727 visiblePositionOfHitTestResult(event.hitTestResult()); | 759 visiblePositionOfHitTestResult(event.hitTestResult()); |
| 728 if (pos.isNotNull()) { | 760 if (pos.isNotNull()) { |
| 729 newSelection = | 761 newSelection = |
| 730 createVisibleSelection(SelectionInFlatTree::Builder() | 762 createVisibleSelection(SelectionInFlatTree::Builder() |
| 731 .collapse(pos.toPositionWithAffinity()) | 763 .collapse(pos.toPositionWithAffinity()) |
| 732 .setGranularity(ParagraphGranularity) | 764 .setGranularity(ParagraphGranularity) |
| 733 .build()); | 765 .build()); |
| 734 } | 766 } |
| 735 | 767 |
| 768 bool isHandleVisible = event.event().fromTouch() && newSelection.isRange(); |
| 769 |
| 736 return updateSelectionForMouseDownDispatchingSelectStart( | 770 return updateSelectionForMouseDownDispatchingSelectStart( |
| 737 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), | 771 innerNode, expandSelectionToRespectUserSelectAll(innerNode, newSelection), |
| 738 ParagraphGranularity); | 772 ParagraphGranularity, isHandleVisible ? HandleVisibility::Visible |
| 773 : HandleVisibility::NotVisible); |
| 739 } | 774 } |
| 740 | 775 |
| 741 void SelectionController::handleMousePressEvent( | 776 void SelectionController::handleMousePressEvent( |
| 742 const MouseEventWithHitTestResults& event) { | 777 const MouseEventWithHitTestResults& event) { |
| 743 // If we got the event back, that must mean it wasn't prevented, | 778 // If we got the event back, that must mean it wasn't prevented, |
| 744 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. | 779 // so it's allowed to start a drag or selection if it wasn't in a scrollbar. |
| 745 m_mouseDownMayStartSelect = | 780 m_mouseDownMayStartSelect = |
| 746 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) && | 781 (canMouseDownStartSelect(event.innerNode()) || isLinkSelection(event)) && |
| 747 !event.scrollbar(); | 782 !event.scrollbar(); |
| 748 m_mouseDownWasSingleClickInSelection = false; | 783 m_mouseDownWasSingleClickInSelection = false; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 pos.deepEquivalent().parentAnchoredEquivalent()), | 973 pos.deepEquivalent().parentAnchoredEquivalent()), |
| 939 DocumentMarker::MisspellingMarkers()) | 974 DocumentMarker::MisspellingMarkers()) |
| 940 .size() > 0; | 975 .size() > 0; |
| 941 } | 976 } |
| 942 | 977 |
| 943 void SelectionController::sendContextMenuEvent( | 978 void SelectionController::sendContextMenuEvent( |
| 944 const MouseEventWithHitTestResults& mev, | 979 const MouseEventWithHitTestResults& mev, |
| 945 const LayoutPoint& position) { | 980 const LayoutPoint& position) { |
| 946 if (!selection().isAvailable()) | 981 if (!selection().isAvailable()) |
| 947 return; | 982 return; |
| 948 if (selection().contains(position) || mev.scrollbar() || | 983 if (selection().contains(mev.hitTestResult()) || mev.scrollbar() || |
| 949 // FIXME: In the editable case, word selection sometimes selects content | 984 // FIXME: In the editable case, word selection sometimes selects content |
| 950 // that isn't underneath the mouse. | 985 // that isn't underneath the mouse. |
| 951 // If the selection is non-editable, we do word selection to make it | 986 // If the selection is non-editable, we do word selection to make it |
| 952 // easier to use the contextual menu items available for text selections. | 987 // easier to use the contextual menu items available for text selections. |
| 953 // But only if we're above text. | 988 // But only if we're above text. |
| 954 !(selection().isContentEditable() || | 989 !(selection().isContentEditable() || |
| 955 (mev.innerNode() && mev.innerNode()->isTextNode()))) | 990 (mev.innerNode() && mev.innerNode()->isTextNode()))) |
| 956 return; | 991 return; |
| 957 | 992 |
| 958 // Context menu events are always allowed to perform a selection. | 993 // Context menu events are always allowed to perform a selection. |
| 959 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, | 994 AutoReset<bool> mouseDownMayStartSelectChange(&m_mouseDownMayStartSelect, |
| 960 true); | 995 true); |
| 961 | 996 |
| 962 if (hitTestResultIsMisspelled(mev.hitTestResult())) | 997 if (hitTestResultIsMisspelled(mev.hitTestResult())) |
| 963 return selectClosestMisspellingFromMouseEvent(mev); | 998 return selectClosestMisspellingFromMouseEvent(mev); |
| 964 | 999 |
| 965 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) | 1000 if (!m_frame->editor().behavior().shouldSelectOnContextualMenuClick()) |
| 966 return; | 1001 return; |
| 967 | 1002 |
| 968 selectClosestWordOrLinkFromMouseEvent(mev); | 1003 selectClosestWordOrLinkFromMouseEvent(mev); |
| 969 } | 1004 } |
| 970 | 1005 |
| 971 void SelectionController::passMousePressEventToSubframe( | 1006 void SelectionController::passMousePressEventToSubframe( |
| 972 const MouseEventWithHitTestResults& mev) { | 1007 const MouseEventWithHitTestResults& mev) { |
| 973 // If we're clicking into a frame that is selected, the frame will appear | 1008 // If we're clicking into a frame that is selected, the frame will appear |
| 974 // greyed out even though we're clicking on the selection. This looks | 1009 // greyed out even though we're clicking on the selection. This looks |
| 975 // really strange (having the whole frame be greyed out), so we deselect the | 1010 // really strange (having the whole frame be greyed out), so we deselect the |
| 976 // selection. | 1011 // selection. |
| 977 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); | 1012 if (!selection().contains(mev.hitTestResult())) |
| 978 if (!selection().contains(p)) | |
| 979 return; | 1013 return; |
| 980 | 1014 |
| 981 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 1015 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 982 // needs to be audited. See http://crbug.com/590369 for more details. | 1016 // needs to be audited. See http://crbug.com/590369 for more details. |
| 983 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 1017 m_frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 984 | 1018 |
| 985 const VisiblePositionInFlatTree& visiblePos = | 1019 const VisiblePositionInFlatTree& visiblePos = |
| 986 visiblePositionOfHitTestResult(mev.hitTestResult()); | 1020 visiblePositionOfHitTestResult(mev.hitTestResult()); |
| 987 if (visiblePos.isNull()) { | 1021 if (visiblePos.isNull()) { |
| 988 selection().setSelection(VisibleSelectionInFlatTree()); | 1022 selection().setSelection(VisibleSelectionInFlatTree()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 return event.event().altKey() && event.isOverLink(); | 1060 return event.event().altKey() && event.isOverLink(); |
| 1027 } | 1061 } |
| 1028 | 1062 |
| 1029 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { | 1063 bool isExtendingSelection(const MouseEventWithHitTestResults& event) { |
| 1030 bool isMouseDownOnLinkOrImage = | 1064 bool isMouseDownOnLinkOrImage = |
| 1031 event.isOverLink() || event.hitTestResult().image(); | 1065 event.isOverLink() || event.hitTestResult().image(); |
| 1032 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; | 1066 return event.event().shiftKey() && !isMouseDownOnLinkOrImage; |
| 1033 } | 1067 } |
| 1034 | 1068 |
| 1035 } // namespace blink | 1069 } // namespace blink |
| OLD | NEW |