| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/textfield/textfield.h" | 5 #include "ui/views/controls/textfield/textfield.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "grit/ui_strings.h" | 10 #include "grit/ui_strings.h" |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 const gfx::Insets& insets = GetInsets(); | 485 const gfx::Insets& insets = GetInsets(); |
| 486 return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) + | 486 return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) + |
| 487 insets.width(), GetFontList().GetHeight() + insets.height()); | 487 insets.width(), GetFontList().GetHeight() + insets.height()); |
| 488 } | 488 } |
| 489 | 489 |
| 490 const char* Textfield::GetClassName() const { | 490 const char* Textfield::GetClassName() const { |
| 491 return kViewClassName; | 491 return kViewClassName; |
| 492 } | 492 } |
| 493 | 493 |
| 494 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { | 494 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { |
| 495 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 495 bool in_selection = GetRenderText()->IsPointInSelection( |
| 496 gfx::ToFlooredPoint(event.location())); |
| 496 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 497 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
| 497 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 498 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
| 498 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; | 499 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; |
| 499 } | 500 } |
| 500 | 501 |
| 501 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { | 502 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { |
| 502 TrackMouseClicks(event); | 503 TrackMouseClicks(event); |
| 503 | 504 |
| 504 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { | 505 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { |
| 505 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { | 506 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { |
| 506 RequestFocus(); | 507 RequestFocus(); |
| 507 ShowImeIfNeeded(); | 508 ShowImeIfNeeded(); |
| 508 } | 509 } |
| 509 | 510 |
| 510 if (event.IsOnlyLeftMouseButton()) { | 511 if (event.IsOnlyLeftMouseButton()) { |
| 511 OnBeforeUserAction(); | 512 OnBeforeUserAction(); |
| 512 initiating_drag_ = false; | 513 initiating_drag_ = false; |
| 513 switch (aggregated_clicks_) { | 514 switch (aggregated_clicks_) { |
| 514 case 0: | 515 case 0: |
| 515 if (GetRenderText()->IsPointInSelection(event.location())) | 516 if (GetRenderText()->IsPointInSelection( |
| 517 gfx::ToFlooredPoint(event.location()))) |
| 516 initiating_drag_ = true; | 518 initiating_drag_ = true; |
| 517 else | 519 else |
| 518 MoveCursorTo(event.location(), event.IsShiftDown()); | 520 MoveCursorTo(gfx::ToFlooredPoint(event.location()), |
| 521 event.IsShiftDown()); |
| 519 break; | 522 break; |
| 520 case 1: | 523 case 1: |
| 521 model_->MoveCursorTo(event.location(), false); | 524 model_->MoveCursorTo(gfx::ToFlooredPoint(event.location()), false); |
| 522 model_->SelectWord(); | 525 model_->SelectWord(); |
| 523 UpdateAfterChange(false, true); | 526 UpdateAfterChange(false, true); |
| 524 double_click_word_ = GetRenderText()->selection(); | 527 double_click_word_ = GetRenderText()->selection(); |
| 525 break; | 528 break; |
| 526 case 2: | 529 case 2: |
| 527 SelectAll(false); | 530 SelectAll(false); |
| 528 break; | 531 break; |
| 529 default: | 532 default: |
| 530 NOTREACHED(); | 533 NOTREACHED(); |
| 531 } | 534 } |
| 532 OnAfterUserAction(); | 535 OnAfterUserAction(); |
| 533 } | 536 } |
| 534 | 537 |
| 535 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 538 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 536 if (event.IsOnlyMiddleMouseButton()) { | 539 if (event.IsOnlyMiddleMouseButton()) { |
| 537 if (GetRenderText()->IsPointInSelection(event.location())) { | 540 if (GetRenderText()->IsPointInSelection( |
| 541 gfx::ToFlooredPoint(event.location()))) { |
| 538 OnBeforeUserAction(); | 542 OnBeforeUserAction(); |
| 539 ClearSelection(); | 543 ClearSelection(); |
| 540 ui::ScopedClipboardWriter( | 544 ui::ScopedClipboardWriter( |
| 541 ui::Clipboard::GetForCurrentThread(), | 545 ui::Clipboard::GetForCurrentThread(), |
| 542 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16()); | 546 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16()); |
| 543 OnAfterUserAction(); | 547 OnAfterUserAction(); |
| 544 } else if(!read_only()) { | 548 } else if(!read_only()) { |
| 545 PasteSelectionClipboard(event); | 549 PasteSelectionClipboard(event); |
| 546 } | 550 } |
| 547 } | 551 } |
| 548 #endif | 552 #endif |
| 549 } | 553 } |
| 550 | 554 |
| 551 touch_selection_controller_.reset(); | 555 touch_selection_controller_.reset(); |
| 552 return true; | 556 return true; |
| 553 } | 557 } |
| 554 | 558 |
| 555 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 559 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 556 // Don't adjust the cursor on a potential drag and drop, or if the mouse | 560 // Don't adjust the cursor on a potential drag and drop, or if the mouse |
| 557 // movement from the last mouse click does not exceed the drag threshold. | 561 // movement from the last mouse click does not exceed the drag threshold. |
| 558 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() || | 562 if (initiating_drag_ || !event.IsOnlyLeftMouseButton() || |
| 559 !ExceededDragThreshold(event.location() - last_click_location_)) { | 563 !ExceededDragThreshold(gfx::ToFlooredPoint(event.location()) - |
| 564 last_click_location_)) { |
| 560 return true; | 565 return true; |
| 561 } | 566 } |
| 562 | 567 |
| 563 OnBeforeUserAction(); | 568 OnBeforeUserAction(); |
| 564 model_->MoveCursorTo(event.location(), true); | 569 model_->MoveCursorTo(gfx::ToFlooredPoint(event.location()), true); |
| 565 if (aggregated_clicks_ == 1) { | 570 if (aggregated_clicks_ == 1) { |
| 566 model_->SelectWord(); | 571 model_->SelectWord(); |
| 567 // Expand the selection so the initially selected word remains selected. | 572 // Expand the selection so the initially selected word remains selected. |
| 568 gfx::Range selection = GetRenderText()->selection(); | 573 gfx::Range selection = GetRenderText()->selection(); |
| 569 const size_t min = std::min(selection.GetMin(), | 574 const size_t min = std::min(selection.GetMin(), |
| 570 double_click_word_.GetMin()); | 575 double_click_word_.GetMin()); |
| 571 const size_t max = std::max(selection.GetMax(), | 576 const size_t max = std::max(selection.GetMax(), |
| 572 double_click_word_.GetMax()); | 577 double_click_word_.GetMax()); |
| 573 const bool reversed = selection.is_reversed(); | 578 const bool reversed = selection.is_reversed(); |
| 574 selection.set_start(reversed ? max : min); | 579 selection.set_start(reversed ? max : min); |
| 575 selection.set_end(reversed ? min : max); | 580 selection.set_end(reversed ? min : max); |
| 576 model_->SelectRange(selection); | 581 model_->SelectRange(selection); |
| 577 } | 582 } |
| 578 UpdateAfterChange(false, true); | 583 UpdateAfterChange(false, true); |
| 579 OnAfterUserAction(); | 584 OnAfterUserAction(); |
| 580 return true; | 585 return true; |
| 581 } | 586 } |
| 582 | 587 |
| 583 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 588 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 584 OnBeforeUserAction(); | 589 OnBeforeUserAction(); |
| 585 // Cancel suspected drag initiations, the user was clicking in the selection. | 590 // Cancel suspected drag initiations, the user was clicking in the selection. |
| 586 if (initiating_drag_) | 591 if (initiating_drag_) |
| 587 MoveCursorTo(event.location(), false); | 592 MoveCursorTo(gfx::ToFlooredPoint(event.location()), false); |
| 588 initiating_drag_ = false; | 593 initiating_drag_ = false; |
| 589 UpdateSelectionClipboard(); | 594 UpdateSelectionClipboard(); |
| 590 OnAfterUserAction(); | 595 OnAfterUserAction(); |
| 591 } | 596 } |
| 592 | 597 |
| 593 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 598 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 594 bool handled = controller_ && controller_->HandleKeyEvent(this, event); | 599 bool handled = controller_ && controller_->HandleKeyEvent(this, event); |
| 595 touch_selection_controller_.reset(); | 600 touch_selection_controller_.reset(); |
| 596 if (handled) | 601 if (handled) |
| 597 return true; | 602 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 | 634 |
| 630 void Textfield::OnGestureEvent(ui::GestureEvent* event) { | 635 void Textfield::OnGestureEvent(ui::GestureEvent* event) { |
| 631 switch (event->type()) { | 636 switch (event->type()) { |
| 632 case ui::ET_GESTURE_TAP_DOWN: | 637 case ui::ET_GESTURE_TAP_DOWN: |
| 633 OnBeforeUserAction(); | 638 OnBeforeUserAction(); |
| 634 RequestFocus(); | 639 RequestFocus(); |
| 635 ShowImeIfNeeded(); | 640 ShowImeIfNeeded(); |
| 636 | 641 |
| 637 // We don't deselect if the point is in the selection | 642 // We don't deselect if the point is in the selection |
| 638 // because TAP_DOWN may turn into a LONG_PRESS. | 643 // because TAP_DOWN may turn into a LONG_PRESS. |
| 639 if (!GetRenderText()->IsPointInSelection(event->location())) | 644 if (!GetRenderText()->IsPointInSelection( |
| 640 MoveCursorTo(event->location(), false); | 645 gfx::ToFlooredPoint(event->location()))) |
| 646 MoveCursorTo(gfx::ToFlooredPoint(event->location()), false); |
| 641 OnAfterUserAction(); | 647 OnAfterUserAction(); |
| 642 event->SetHandled(); | 648 event->SetHandled(); |
| 643 break; | 649 break; |
| 644 case ui::ET_GESTURE_SCROLL_UPDATE: | 650 case ui::ET_GESTURE_SCROLL_UPDATE: |
| 645 OnBeforeUserAction(); | 651 OnBeforeUserAction(); |
| 646 MoveCursorTo(event->location(), true); | 652 MoveCursorTo(gfx::ToFlooredPoint(event->location()), true); |
| 647 OnAfterUserAction(); | 653 OnAfterUserAction(); |
| 648 event->SetHandled(); | 654 event->SetHandled(); |
| 649 break; | 655 break; |
| 650 case ui::ET_GESTURE_SCROLL_END: | 656 case ui::ET_GESTURE_SCROLL_END: |
| 651 case ui::ET_SCROLL_FLING_START: | 657 case ui::ET_SCROLL_FLING_START: |
| 652 CreateTouchSelectionControllerAndNotifyIt(); | 658 CreateTouchSelectionControllerAndNotifyIt(); |
| 653 event->SetHandled(); | 659 event->SetHandled(); |
| 654 break; | 660 break; |
| 655 case ui::ET_GESTURE_TAP: | 661 case ui::ET_GESTURE_TAP: |
| 656 if (event->details().tap_count() == 1) { | 662 if (event->details().tap_count() == 1) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 667 #endif | 673 #endif |
| 668 break; | 674 break; |
| 669 case ui::ET_GESTURE_LONG_PRESS: | 675 case ui::ET_GESTURE_LONG_PRESS: |
| 670 // If long press happens outside selection, select word and show context | 676 // If long press happens outside selection, select word and show context |
| 671 // menu (If touch selection is enabled, context menu is shown by the | 677 // menu (If touch selection is enabled, context menu is shown by the |
| 672 // |touch_selection_controller_|, hence we mark the event handled. | 678 // |touch_selection_controller_|, hence we mark the event handled. |
| 673 // Otherwise, the regular context menu will be shown by views). | 679 // Otherwise, the regular context menu will be shown by views). |
| 674 // If long press happens in selected text and touch drag drop is enabled, | 680 // If long press happens in selected text and touch drag drop is enabled, |
| 675 // we will turn off touch selection (if one exists) and let views do drag | 681 // we will turn off touch selection (if one exists) and let views do drag |
| 676 // drop. | 682 // drop. |
| 677 if (!GetRenderText()->IsPointInSelection(event->location())) { | 683 if (!GetRenderText()->IsPointInSelection( |
| 684 gfx::ToFlooredPoint(event->location()))) { |
| 678 OnBeforeUserAction(); | 685 OnBeforeUserAction(); |
| 679 model_->SelectWord(); | 686 model_->SelectWord(); |
| 680 touch_selection_controller_.reset( | 687 touch_selection_controller_.reset( |
| 681 ui::TouchSelectionController::create(this)); | 688 ui::TouchSelectionController::create(this)); |
| 682 UpdateAfterChange(false, true); | 689 UpdateAfterChange(false, true); |
| 683 OnAfterUserAction(); | 690 OnAfterUserAction(); |
| 684 if (touch_selection_controller_) | 691 if (touch_selection_controller_) |
| 685 event->SetHandled(); | 692 event->SetHandled(); |
| 686 } else if (switches::IsTouchDragDropEnabled()) { | 693 } else if (switches::IsTouchDragDropEnabled()) { |
| 687 initiating_drag_ = true; | 694 initiating_drag_ = true; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 std::set<OSExchangeData::CustomFormat> custom_formats; | 755 std::set<OSExchangeData::CustomFormat> custom_formats; |
| 749 GetDropFormats(&formats, &custom_formats); | 756 GetDropFormats(&formats, &custom_formats); |
| 750 return enabled() && !read_only() && | 757 return enabled() && !read_only() && |
| 751 data.HasAnyFormat(formats, custom_formats); | 758 data.HasAnyFormat(formats, custom_formats); |
| 752 } | 759 } |
| 753 | 760 |
| 754 int Textfield::OnDragUpdated(const ui::DropTargetEvent& event) { | 761 int Textfield::OnDragUpdated(const ui::DropTargetEvent& event) { |
| 755 DCHECK(CanDrop(event.data())); | 762 DCHECK(CanDrop(event.data())); |
| 756 gfx::RenderText* render_text = GetRenderText(); | 763 gfx::RenderText* render_text = GetRenderText(); |
| 757 const gfx::Range& selection = render_text->selection(); | 764 const gfx::Range& selection = render_text->selection(); |
| 758 drop_cursor_position_ = render_text->FindCursorPosition(event.location()); | 765 drop_cursor_position_ = |
| 766 render_text->FindCursorPosition(gfx::ToFlooredPoint(event.location())); |
| 759 bool in_selection = !selection.is_empty() && | 767 bool in_selection = !selection.is_empty() && |
| 760 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); | 768 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); |
| 761 drop_cursor_visible_ = !in_selection; | 769 drop_cursor_visible_ = !in_selection; |
| 762 // TODO(msw): Pan over text when the user drags to the visible text edge. | 770 // TODO(msw): Pan over text when the user drags to the visible text edge. |
| 763 OnCaretBoundsChanged(); | 771 OnCaretBoundsChanged(); |
| 764 SchedulePaint(); | 772 SchedulePaint(); |
| 765 | 773 |
| 766 if (initiating_drag_) { | 774 if (initiating_drag_) { |
| 767 if (in_selection) | 775 if (in_selection) |
| 768 return ui::DragDropTypes::DRAG_NONE; | 776 return ui::DragDropTypes::DRAG_NONE; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 781 DCHECK(CanDrop(event.data())); | 789 DCHECK(CanDrop(event.data())); |
| 782 drop_cursor_visible_ = false; | 790 drop_cursor_visible_ = false; |
| 783 | 791 |
| 784 if (controller_) { | 792 if (controller_) { |
| 785 int drag_operation = controller_->OnDrop(event.data()); | 793 int drag_operation = controller_->OnDrop(event.data()); |
| 786 if (drag_operation != ui::DragDropTypes::DRAG_NONE) | 794 if (drag_operation != ui::DragDropTypes::DRAG_NONE) |
| 787 return drag_operation; | 795 return drag_operation; |
| 788 } | 796 } |
| 789 | 797 |
| 790 gfx::RenderText* render_text = GetRenderText(); | 798 gfx::RenderText* render_text = GetRenderText(); |
| 791 DCHECK(!initiating_drag_ || | 799 DCHECK( |
| 792 !render_text->IsPointInSelection(event.location())); | 800 !initiating_drag_ || |
| 801 !render_text->IsPointInSelection(gfx::ToFlooredPoint(event.location()))); |
| 793 OnBeforeUserAction(); | 802 OnBeforeUserAction(); |
| 794 skip_input_method_cancel_composition_ = true; | 803 skip_input_method_cancel_composition_ = true; |
| 795 | 804 |
| 796 gfx::SelectionModel drop_destination_model = | 805 gfx::SelectionModel drop_destination_model = |
| 797 render_text->FindCursorPosition(event.location()); | 806 render_text->FindCursorPosition(gfx::ToFlooredPoint(event.location())); |
| 798 base::string16 new_text; | 807 base::string16 new_text; |
| 799 event.data().GetString(&new_text); | 808 event.data().GetString(&new_text); |
| 800 | 809 |
| 801 // Delete the current selection for a drag and drop within this view. | 810 // Delete the current selection for a drag and drop within this view. |
| 802 const bool move = initiating_drag_ && !event.IsControlDown() && | 811 const bool move = initiating_drag_ && !event.IsControlDown() && |
| 803 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; | 812 event.source_operations() & ui::DragDropTypes::DRAG_MOVE; |
| 804 if (move) { | 813 if (move) { |
| 805 // Adjust the drop destination if it is on or after the current selection. | 814 // Adjust the drop destination if it is on or after the current selection. |
| 806 size_t pos = drop_destination_model.caret_pos(); | 815 size_t pos = drop_destination_model.caret_pos(); |
| 807 pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length(); | 816 pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length(); |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1603 if (controller_) | 1612 if (controller_) |
| 1604 controller_->UpdateContextMenu(context_menu_contents_.get()); | 1613 controller_->UpdateContextMenu(context_menu_contents_.get()); |
| 1605 } | 1614 } |
| 1606 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get())); | 1615 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get())); |
| 1607 } | 1616 } |
| 1608 | 1617 |
| 1609 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { | 1618 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { |
| 1610 if (event.IsOnlyLeftMouseButton()) { | 1619 if (event.IsOnlyLeftMouseButton()) { |
| 1611 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; | 1620 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; |
| 1612 if (time_delta.InMilliseconds() <= GetDoubleClickInterval() && | 1621 if (time_delta.InMilliseconds() <= GetDoubleClickInterval() && |
| 1613 !ExceededDragThreshold(event.location() - last_click_location_)) { | 1622 !ExceededDragThreshold(gfx::ToFlooredPoint(event.location()) - |
| 1623 last_click_location_)) { |
| 1614 // Upon clicking after a triple click, the count should go back to double | 1624 // Upon clicking after a triple click, the count should go back to double |
| 1615 // click and alternate between double and triple. This assignment maps | 1625 // click and alternate between double and triple. This assignment maps |
| 1616 // 0 to 1, 1 to 2, 2 to 1. | 1626 // 0 to 1, 1 to 2, 2 to 1. |
| 1617 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1; | 1627 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1; |
| 1618 } else { | 1628 } else { |
| 1619 aggregated_clicks_ = 0; | 1629 aggregated_clicks_ = 0; |
| 1620 } | 1630 } |
| 1621 last_click_time_ = event.time_stamp(); | 1631 last_click_time_ = event.time_stamp(); |
| 1622 last_click_location_ = event.location(); | 1632 last_click_location_ = gfx::ToFlooredPoint(event.location()); |
| 1623 } | 1633 } |
| 1624 } | 1634 } |
| 1625 | 1635 |
| 1626 bool Textfield::ImeEditingAllowed() const { | 1636 bool Textfield::ImeEditingAllowed() const { |
| 1627 // Disallow input method editing of password fields. | 1637 // Disallow input method editing of password fields. |
| 1628 ui::TextInputType t = GetTextInputType(); | 1638 ui::TextInputType t = GetTextInputType(); |
| 1629 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 1639 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 1630 } | 1640 } |
| 1631 | 1641 |
| 1632 void Textfield::RevealPasswordChar(int index) { | 1642 void Textfield::RevealPasswordChar(int index) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1662 } | 1672 } |
| 1663 | 1673 |
| 1664 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) { | 1674 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) { |
| 1665 DCHECK(event.IsOnlyMiddleMouseButton()); | 1675 DCHECK(event.IsOnlyMiddleMouseButton()); |
| 1666 DCHECK(!read_only()); | 1676 DCHECK(!read_only()); |
| 1667 base::string16 selection_clipboard_text = GetSelectionClipboardText(); | 1677 base::string16 selection_clipboard_text = GetSelectionClipboardText(); |
| 1668 if (!selection_clipboard_text.empty()) { | 1678 if (!selection_clipboard_text.empty()) { |
| 1669 OnBeforeUserAction(); | 1679 OnBeforeUserAction(); |
| 1670 gfx::Range range = GetSelectionModel().selection(); | 1680 gfx::Range range = GetSelectionModel().selection(); |
| 1671 gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity(); | 1681 gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity(); |
| 1672 const gfx::SelectionModel mouse = | 1682 const gfx::SelectionModel mouse = GetRenderText()->FindCursorPosition( |
| 1673 GetRenderText()->FindCursorPosition(event.location()); | 1683 gfx::ToFlooredPoint(event.location())); |
| 1674 model_->MoveCursorTo(mouse); | 1684 model_->MoveCursorTo(mouse); |
| 1675 model_->InsertText(selection_clipboard_text); | 1685 model_->InsertText(selection_clipboard_text); |
| 1676 // Update the new selection range as needed. | 1686 // Update the new selection range as needed. |
| 1677 if (range.GetMin() >= mouse.caret_pos()) { | 1687 if (range.GetMin() >= mouse.caret_pos()) { |
| 1678 const size_t length = selection_clipboard_text.length(); | 1688 const size_t length = selection_clipboard_text.length(); |
| 1679 range = gfx::Range(range.start() + length, range.end() + length); | 1689 range = gfx::Range(range.start() + length, range.end() + length); |
| 1680 } | 1690 } |
| 1681 model_->MoveCursorTo(gfx::SelectionModel(range, affinity)); | 1691 model_->MoveCursorTo(gfx::SelectionModel(range, affinity)); |
| 1682 UpdateAfterChange(true, true); | 1692 UpdateAfterChange(true, true); |
| 1683 OnAfterUserAction(); | 1693 OnAfterUserAction(); |
| 1684 } | 1694 } |
| 1685 } | 1695 } |
| 1686 | 1696 |
| 1687 } // namespace views | 1697 } // namespace views |
| OLD | NEW |