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