Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: ui/views/controls/textfield/textfield.cc

Issue 2408623002: Views: Extract text selection code from Textfield. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include <utility> 8 #include <utility>
9 9
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 22 matching lines...) Expand all
33 #include "ui/native_theme/native_theme.h" 33 #include "ui/native_theme/native_theme.h"
34 #include "ui/strings/grit/ui_strings.h" 34 #include "ui/strings/grit/ui_strings.h"
35 #include "ui/views/background.h" 35 #include "ui/views/background.h"
36 #include "ui/views/controls/focus_ring.h" 36 #include "ui/views/controls/focus_ring.h"
37 #include "ui/views/controls/focusable_border.h" 37 #include "ui/views/controls/focusable_border.h"
38 #include "ui/views/controls/label.h" 38 #include "ui/views/controls/label.h"
39 #include "ui/views/controls/menu/menu_runner.h" 39 #include "ui/views/controls/menu/menu_runner.h"
40 #include "ui/views/controls/native/native_view_host.h" 40 #include "ui/views/controls/native/native_view_host.h"
41 #include "ui/views/controls/textfield/textfield_controller.h" 41 #include "ui/views/controls/textfield/textfield_controller.h"
42 #include "ui/views/drag_utils.h" 42 #include "ui/views/drag_utils.h"
43 #include "ui/views/metrics.h"
44 #include "ui/views/native_cursor.h" 43 #include "ui/views/native_cursor.h"
45 #include "ui/views/painter.h" 44 #include "ui/views/painter.h"
46 #include "ui/views/style/platform_style.h" 45 #include "ui/views/style/platform_style.h"
47 #include "ui/views/views_delegate.h" 46 #include "ui/views/views_delegate.h"
48 #include "ui/views/widget/widget.h" 47 #include "ui/views/widget/widget.h"
49 48
50 #if defined(OS_WIN) 49 #if defined(OS_WIN)
51 #include "base/win/win_util.h" 50 #include "base/win/win_util.h"
52 #include "ui/base/win/osk_display_manager.h" 51 #include "ui/base/win/osk_display_manager.h"
53 #endif 52 #endif
(...skipping 24 matching lines...) Expand all
78 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; 77 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
79 78
80 void ConvertRectToScreen(const View* src, gfx::Rect* r) { 79 void ConvertRectToScreen(const View* src, gfx::Rect* r) {
81 DCHECK(src); 80 DCHECK(src);
82 81
83 gfx::Point new_origin = r->origin(); 82 gfx::Point new_origin = r->origin();
84 View::ConvertPointToScreen(src, &new_origin); 83 View::ConvertPointToScreen(src, &new_origin);
85 r->set_origin(new_origin); 84 r->set_origin(new_origin);
86 } 85 }
87 86
88 // Get the drag selection timer delay, respecting animation scaling for testing.
89 int GetDragSelectionDelay() {
90 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
91 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100;
92 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25;
93 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400;
94 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: return 1;
95 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0;
96 }
97 return 100;
98 }
99
100 // Get the default command for a given key |event|. 87 // Get the default command for a given key |event|.
101 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { 88 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) {
102 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) 89 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
103 return ui::TextEditCommand::INVALID_COMMAND; 90 return ui::TextEditCommand::INVALID_COMMAND;
104 91
105 const bool shift = event.IsShiftDown(); 92 const bool shift = event.IsShiftDown();
106 const bool control = event.IsControlDown(); 93 const bool control = event.IsControlDown();
107 const bool alt = event.IsAltDown() || event.IsAltGrDown(); 94 const bool alt = event.IsAltDown() || event.IsAltGrDown();
108 switch (event.key_code()) { 95 switch (event.key_code()) {
109 case ui::VKEY_Z: 96 case ui::VKEY_Z:
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 use_default_selection_text_color_(true), 235 use_default_selection_text_color_(true),
249 use_default_selection_background_color_(true), 236 use_default_selection_background_color_(true),
250 text_color_(SK_ColorBLACK), 237 text_color_(SK_ColorBLACK),
251 background_color_(SK_ColorWHITE), 238 background_color_(SK_ColorWHITE),
252 selection_text_color_(SK_ColorWHITE), 239 selection_text_color_(SK_ColorWHITE),
253 selection_background_color_(SK_ColorBLUE), 240 selection_background_color_(SK_ColorBLUE),
254 placeholder_text_color_(kDefaultPlaceholderTextColor), 241 placeholder_text_color_(kDefaultPlaceholderTextColor),
255 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), 242 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
256 text_input_flags_(0), 243 text_input_flags_(0),
257 performing_user_action_(false), 244 performing_user_action_(false),
245 performing_mouse_action_(false),
258 skip_input_method_cancel_composition_(false), 246 skip_input_method_cancel_composition_(false),
259 drop_cursor_visible_(false), 247 drop_cursor_visible_(false),
260 initiating_drag_(false), 248 initiating_drag_(false),
261 aggregated_clicks_(0), 249 selection_controller_(new SelectionController(this)),
262 drag_start_display_offset_(0), 250 drag_start_display_offset_(0),
263 touch_handles_hidden_due_to_scroll_(false), 251 touch_handles_hidden_due_to_scroll_(false),
264 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), 252 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()),
265 weak_ptr_factory_(this) { 253 weak_ptr_factory_(this) {
266 set_context_menu_controller(this); 254 set_context_menu_controller(this);
267 set_drag_controller(this); 255 set_drag_controller(this);
268 GetRenderText()->SetFontList(GetDefaultFontList()); 256 GetRenderText()->SetFontList(GetDefaultFontList());
269 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); 257 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder()));
270 SetFocusBehavior(FocusBehavior::ALWAYS); 258 SetFocusBehavior(FocusBehavior::ALWAYS);
271 259
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 model_->InsertText(new_text); 315 model_->InsertText(new_text);
328 UpdateAfterChange(true, true); 316 UpdateAfterChange(true, true);
329 } 317 }
330 318
331 base::string16 Textfield::GetSelectedText() const { 319 base::string16 Textfield::GetSelectedText() const {
332 return model_->GetSelectedText(); 320 return model_->GetSelectedText();
333 } 321 }
334 322
335 void Textfield::SelectAll(bool reversed) { 323 void Textfield::SelectAll(bool reversed) {
336 model_->SelectAll(reversed); 324 model_->SelectAll(reversed);
337 UpdateSelectionClipboard(); 325 // Todo is this redundant?
msw 2016/10/14 18:54:20 nit: address todo
karandeepb 2016/10/17 07:08:15 Done.
326 if (HasSelection())
327 UpdateSelectionClipboard();
338 UpdateAfterChange(false, true); 328 UpdateAfterChange(false, true);
339 } 329 }
340 330
341 void Textfield::SelectWordAt(const gfx::Point& point) { 331 void Textfield::SelectWordAt(const gfx::Point& point) {
342 model_->MoveCursorTo(point, false); 332 model_->MoveCursorTo(point, false);
343 model_->SelectWord(); 333 model_->SelectWord();
344 UpdateAfterChange(false, true); 334 UpdateAfterChange(false, true);
345 } 335 }
346 336
347 void Textfield::ClearSelection() { 337 void Textfield::ClearSelection() {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 } 514 }
525 515
526 void Textfield::ClearEditHistory() { 516 void Textfield::ClearEditHistory() {
527 model_->ClearEditHistory(); 517 model_->ClearEditHistory();
528 } 518 }
529 519
530 void Textfield::SetAccessibleName(const base::string16& name) { 520 void Textfield::SetAccessibleName(const base::string16& name) {
531 accessible_name_ = name; 521 accessible_name_ = name;
532 } 522 }
533 523
534 bool Textfield::HasTextBeingDragged() {
535 return initiating_drag_;
536 }
537
538 //////////////////////////////////////////////////////////////////////////////// 524 ////////////////////////////////////////////////////////////////////////////////
539 // Textfield, View overrides: 525 // Textfield, View overrides:
540 526
541 gfx::Insets Textfield::GetInsets() const { 527 gfx::Insets Textfield::GetInsets() const {
542 gfx::Insets insets = View::GetInsets(); 528 gfx::Insets insets = View::GetInsets();
543 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); 529 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding);
544 return insets; 530 return insets;
545 } 531 }
546 532
547 int Textfield::GetBaseline() const { 533 int Textfield::GetBaseline() const {
(...skipping 18 matching lines...) Expand all
566 } 552 }
567 553
568 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { 554 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
569 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); 555 bool in_selection = GetRenderText()->IsPointInSelection(event.location());
570 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; 556 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
571 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); 557 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
572 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; 558 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor;
573 } 559 }
574 560
575 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { 561 bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
576 TrackMouseClicks(event); 562 bool handled = controller_ && controller_->HandleMouseEvent(this, event);
577 563 if (!handled &&
578 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { 564 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) {
579 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { 565 RequestFocus();
580 RequestFocus(); 566 ShowImeIfNeeded();
581 ShowImeIfNeeded();
582 }
583
584 if (event.IsOnlyLeftMouseButton()) {
585 OnBeforeUserAction();
586 initiating_drag_ = false;
587 switch (aggregated_clicks_) {
588 case 0:
589 if (GetRenderText()->IsPointInSelection(event.location()))
590 initiating_drag_ = true;
591 else
592 MoveCursorTo(event.location(), event.IsShiftDown());
593 break;
594 case 1:
595 SelectWordAt(event.location());
596 double_click_word_ = GetRenderText()->selection();
597 break;
598 case 2:
599 SelectAll(false);
600 break;
601 default:
602 NOTREACHED();
603 }
604 OnAfterUserAction();
605 }
606
607 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
608 if (event.IsOnlyMiddleMouseButton()) {
609 if (GetRenderText()->IsPointInSelection(event.location())) {
610 OnBeforeUserAction();
611 ClearSelection();
612 ui::ScopedClipboardWriter(
613 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
614 OnAfterUserAction();
615 } else if (!read_only()) {
616 PasteSelectionClipboard(event);
617 }
618 }
619 #endif
620 } 567 }
621 568 return selection_controller_->OnMousePressed(event, handled);
622 return true;
623 } 569 }
624 570
625 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { 571 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
626 last_drag_location_ = event.location(); 572 return selection_controller_->OnMouseDragged(event);
627
628 // Don't adjust the cursor on a potential drag and drop.
629 if (initiating_drag_ || !event.IsOnlyLeftMouseButton())
630 return true;
631
632 // A timer is used to continuously scroll while selecting beyond side edges.
633 const int x = event.location().x();
634 if ((x >= 0 && x <= width()) || GetDragSelectionDelay() == 0) {
635 drag_selection_timer_.Stop();
636 SelectThroughLastDragLocation();
637 } else if (!drag_selection_timer_.IsRunning()) {
638 // Select through the edge of the visible text, then start the scroll timer.
639 last_drag_location_.set_x(std::min(std::max(0, x), width()));
640 SelectThroughLastDragLocation();
641 drag_selection_timer_.Start(
642 FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()),
643 this, &Textfield::SelectThroughLastDragLocation);
644 }
645
646 return true;
647 } 573 }
648 574
649 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { 575 void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
650 OnBeforeUserAction(); 576 selection_controller_->OnMouseReleased(event);
651 drag_selection_timer_.Stop();
652 // Cancel suspected drag initiations, the user was clicking in the selection.
653 if (initiating_drag_)
654 MoveCursorTo(event.location(), false);
655 initiating_drag_ = false;
656 UpdateSelectionClipboard();
657 OnAfterUserAction();
658 } 577 }
659 578
660 WordLookupClient* Textfield::GetWordLookupClient() { 579 WordLookupClient* Textfield::GetWordLookupClient() {
661 return this; 580 return this;
662 } 581 }
663 582
664 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { 583 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
665 ui::TextEditCommand edit_command = scheduled_text_edit_command_; 584 ui::TextEditCommand edit_command = scheduled_text_edit_command_;
666 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; 585 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND;
667 586
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 // Textfield, WordLookupClient overrides: 1031 // Textfield, WordLookupClient overrides:
1113 1032
1114 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, 1033 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point,
1115 gfx::DecoratedText* decorated_word, 1034 gfx::DecoratedText* decorated_word,
1116 gfx::Point* baseline_point) { 1035 gfx::Point* baseline_point) {
1117 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, 1036 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word,
1118 baseline_point); 1037 baseline_point);
1119 } 1038 }
1120 1039
1121 //////////////////////////////////////////////////////////////////////////////// 1040 ////////////////////////////////////////////////////////////////////////////////
1041 // Textfield, SelectionController::Delegate overrides:
1042
1043 bool Textfield::HasTextBeingDragged() const {
1044 return initiating_drag_;
msw 2016/10/14 18:54:20 Should this live in SelectionController?
karandeepb 2016/10/17 07:08:15 initiaiting_drag_ is just a hint that a drag and d
1045 }
1046
1047 ////////////////////////////////////////////////////////////////////////////////
1122 // Textfield, ui::TouchEditable overrides: 1048 // Textfield, ui::TouchEditable overrides:
1123 1049
1124 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { 1050 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
1125 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1051 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1126 return; 1052 return;
1127 1053
1128 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); 1054 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
1129 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); 1055 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
1130 gfx::SelectionModel selection( 1056 gfx::SelectionModel selection(
1131 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), 1057 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
1577 skip_input_method_cancel_composition_ = false; 1503 skip_input_method_cancel_composition_ = false;
1578 1504
1579 UpdateAfterChange(true, true); 1505 UpdateAfterChange(true, true);
1580 OnAfterUserAction(); 1506 OnAfterUserAction();
1581 } 1507 }
1582 1508
1583 gfx::RenderText* Textfield::GetRenderText() const { 1509 gfx::RenderText* Textfield::GetRenderText() const {
1584 return model_->render_text(); 1510 return model_->render_text();
1585 } 1511 }
1586 1512
1513 gfx::Point Textfield::GetLastClickLocation() const {
1514 return selection_controller_->last_click_location();
1515 }
1516
1587 base::string16 Textfield::GetSelectionClipboardText() const { 1517 base::string16 Textfield::GetSelectionClipboardText() const {
1588 base::string16 selection_clipboard_text; 1518 base::string16 selection_clipboard_text;
1589 ui::Clipboard::GetForCurrentThread()->ReadText( 1519 ui::Clipboard::GetForCurrentThread()->ReadText(
1590 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); 1520 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
1591 return selection_clipboard_text; 1521 return selection_clipboard_text;
1592 } 1522 }
1593 1523
1594 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { 1524 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) {
1595 DestroyTouchSelection(); 1525 DestroyTouchSelection();
1596 1526
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 break; 1705 break;
1776 case ui::TextEditCommand::INSERT_TEXT: 1706 case ui::TextEditCommand::INSERT_TEXT:
1777 case ui::TextEditCommand::SET_MARK: 1707 case ui::TextEditCommand::SET_MARK:
1778 case ui::TextEditCommand::UNSELECT: 1708 case ui::TextEditCommand::UNSELECT:
1779 case ui::TextEditCommand::INVALID_COMMAND: 1709 case ui::TextEditCommand::INVALID_COMMAND:
1780 NOTREACHED(); 1710 NOTREACHED();
1781 break; 1711 break;
1782 } 1712 }
1783 1713
1784 cursor_changed |= GetSelectionModel() != selection_model; 1714 cursor_changed |= GetSelectionModel() != selection_model;
1785 if (cursor_changed) 1715 if (cursor_changed && HasSelection())
1786 UpdateSelectionClipboard(); 1716 UpdateSelectionClipboard();
1787 UpdateAfterChange(text_changed, cursor_changed); 1717 UpdateAfterChange(text_changed, cursor_changed);
1788 OnAfterUserAction(); 1718 OnAfterUserAction();
1789 } 1719 }
1790 1720
1791 //////////////////////////////////////////////////////////////////////////////// 1721 ////////////////////////////////////////////////////////////////////////////////
1792 // Textfield, private: 1722 // Textfield, private:
1793 1723
1724 ////////////////////////////////////////////////////////////////////////////////
1725 // Textfield, SelectionController::Delegate overrides:
1726
1727 gfx::RenderText* Textfield::GetRenderTextForSelection() {
1728 return GetRenderText();
1729 }
1730
1731 bool Textfield::IsReadOnly() const {
1732 return false;
msw 2016/10/14 18:54:20 Textfields can be read-only. This should be: retur
karandeepb 2016/10/17 07:08:15 Oh yeah, thanks for catching this.
1733 }
1734
1735 void Textfield::SetTextBeingDragged(bool value) {
1736 initiating_drag_ = value;
1737 }
1738
1739 int Textfield::GetViewHeight() const {
1740 return height();
1741 }
1742
1743 int Textfield::GetViewWidth() const {
1744 return width();
1745 }
1746
1747 int Textfield::GetDragSelectionDelay() const {
1748 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
1749 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION:
1750 return 100;
1751 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION:
1752 return 25;
1753 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION:
1754 return 400;
1755 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION:
1756 return 1;
1757 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION:
1758 return 0;
1759 }
1760 return 100;
1761 }
1762
1763 void Textfield::OnBeforeMouseAction() {
1764 OnBeforeUserAction();
1765 DCHECK(!performing_mouse_action_);
1766 performing_mouse_action_ = true;
1767 }
1768
1769 void Textfield::OnAfterMouseAction(bool text_changed, bool selection_changed) {
1770 OnAfterUserAction();
1771 DCHECK(performing_mouse_action_);
1772 performing_mouse_action_ = false;
1773 UpdateAfterChange(text_changed, selection_changed);
1774 }
1775
1776 void Textfield::OnBeforeSelectionUpdated() {
1777 DCHECK(performing_mouse_action_);
1778 if (model_->HasCompositionText())
1779 model_->ConfirmCompositionText();
1780 }
1781
1782 void Textfield::OnAfterSelectionUpdated() {
1783 DCHECK(performing_mouse_action_);
1784 UpdateAfterChange(false, true);
msw 2016/10/14 18:54:20 It seems like we'll have some redundant calls to U
karandeepb 2016/10/17 07:08:15 During a mouse action, UpdateAfterChange will be a
msw 2016/10/18 23:15:05 Could we avoid adding On[Before|After]MouseAction
karandeepb 2016/10/20 04:12:57 Removed On[Before|After]SelectionUpdated.
1785 }
1786
1787 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
1788 if (!event.IsOnlyMiddleMouseButton() || read_only() ||
1789 !performing_user_action_)
1790 return;
1791 base::string16 selection_clipboard_text = GetSelectionClipboardText();
1792 const gfx::SelectionModel mouse =
1793 GetRenderText()->FindCursorPosition(event.location());
1794 if (!HasFocus())
1795 RequestFocus();
1796 model_->MoveCursorTo(mouse);
1797 if (!selection_clipboard_text.empty()) {
1798 model_->InsertText(selection_clipboard_text);
1799 UpdateAfterChange(true, true);
1800 }
1801 }
1802
1803 void Textfield::UpdateSelectionClipboard() {
1804 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1805 if (performing_user_action_ &&
1806 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
1807 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION)
1808 .WriteText(GetSelectedText());
1809 if (controller_)
1810 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
1811 }
1812 #endif
1813 }
1814
1794 void Textfield::AccessibilitySetValue(const base::string16& new_value) { 1815 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
1795 if (!read_only()) { 1816 if (!read_only()) {
1796 SetText(new_value); 1817 SetText(new_value);
1797 ClearSelection(); 1818 ClearSelection();
1798 } 1819 }
1799 } 1820 }
1800 1821
1801 void Textfield::UpdateBackgroundColor() { 1822 void Textfield::UpdateBackgroundColor() {
1802 const SkColor color = GetBackgroundColor(); 1823 const SkColor color = GetBackgroundColor();
1803 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { 1824 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
1804 set_background(Background::CreateBackgroundPainter( 1825 set_background(Background::CreateBackgroundPainter(
1805 true, Painter::CreateSolidRoundRectPainter( 1826 true, Painter::CreateSolidRoundRectPainter(
1806 color, FocusableBorder::kCornerRadiusDp))); 1827 color, FocusableBorder::kCornerRadiusDp)));
1807 } else { 1828 } else {
1808 set_background(Background::CreateSolidBackground(color)); 1829 set_background(Background::CreateSolidBackground(color));
1809 } 1830 }
1810 // Disable subpixel rendering when the background color is transparent 1831 // Disable subpixel rendering when the background color is transparent
1811 // because it draws incorrect colors around the glyphs in that case. 1832 // because it draws incorrect colors around the glyphs in that case.
1812 // See crbug.com/115198 1833 // See crbug.com/115198
1813 GetRenderText()->set_subpixel_rendering_suppressed( 1834 GetRenderText()->set_subpixel_rendering_suppressed(
1814 SkColorGetA(color) != SK_AlphaOPAQUE); 1835 SkColorGetA(color) != SK_AlphaOPAQUE);
1815 SchedulePaint(); 1836 SchedulePaint();
1816 } 1837 }
1817 1838
1818 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { 1839 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
1840 if (performing_mouse_action_)
1841 return;
1819 if (text_changed) { 1842 if (text_changed) {
1820 if (controller_) 1843 if (controller_)
1821 controller_->ContentsChanged(this, text()); 1844 controller_->ContentsChanged(this, text());
1822 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); 1845 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
1823 } 1846 }
1824 if (cursor_changed) { 1847 if (cursor_changed) {
1825 GetRenderText()->set_cursor_visible(ShouldShowCursor()); 1848 GetRenderText()->set_cursor_visible(ShouldShowCursor());
1826 RepaintCursor(); 1849 RepaintCursor();
1827 if (ShouldBlinkCursor()) 1850 if (ShouldBlinkCursor())
1828 StartBlinkingCursor(); 1851 StartBlinkingCursor();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 render_text->DrawCursor(canvas, drop_cursor_position_); 1890 render_text->DrawCursor(canvas, drop_cursor_position_);
1868 1891
1869 canvas->Restore(); 1892 canvas->Restore();
1870 } 1893 }
1871 1894
1872 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { 1895 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
1873 if (model_->MoveCursorTo(point, select)) 1896 if (model_->MoveCursorTo(point, select))
1874 UpdateAfterChange(false, true); 1897 UpdateAfterChange(false, true);
1875 } 1898 }
1876 1899
1877 void Textfield::SelectThroughLastDragLocation() {
1878 OnBeforeUserAction();
1879
1880 const bool drags_to_end = PlatformStyle::kTextfieldDragVerticallyDragsToEnd;
1881 if (drags_to_end && last_drag_location_.y() < 0) {
1882 model_->MoveCursor(gfx::BreakType::LINE_BREAK,
1883 gfx::VisualCursorDirection::CURSOR_LEFT,
1884 gfx::SELECTION_RETAIN);
1885 } else if (drags_to_end && last_drag_location_.y() > height()) {
1886 model_->MoveCursor(gfx::BreakType::LINE_BREAK,
1887 gfx::VisualCursorDirection::CURSOR_RIGHT,
1888 gfx::SELECTION_RETAIN);
1889 } else {
1890 model_->MoveCursorTo(last_drag_location_, true);
1891 }
1892
1893 if (aggregated_clicks_ == 1) {
1894 model_->SelectWord();
1895 // Expand the selection so the initially selected word remains selected.
1896 gfx::Range selection = GetRenderText()->selection();
1897 const size_t min = std::min(selection.GetMin(),
1898 double_click_word_.GetMin());
1899 const size_t max = std::max(selection.GetMax(),
1900 double_click_word_.GetMax());
1901 const bool reversed = selection.is_reversed();
1902 selection.set_start(reversed ? max : min);
1903 selection.set_end(reversed ? min : max);
1904 model_->SelectRange(selection);
1905 }
1906 UpdateAfterChange(false, true);
1907 OnAfterUserAction();
1908 }
1909
1910 void Textfield::OnCaretBoundsChanged() { 1900 void Textfield::OnCaretBoundsChanged() {
1911 if (GetInputMethod()) 1901 if (GetInputMethod())
1912 GetInputMethod()->OnCaretBoundsChanged(this); 1902 GetInputMethod()->OnCaretBoundsChanged(this);
1913 if (touch_selection_controller_) 1903 if (touch_selection_controller_)
1914 touch_selection_controller_->SelectionChanged(); 1904 touch_selection_controller_->SelectionChanged();
1915 } 1905 }
1916 1906
1917 void Textfield::OnBeforeUserAction() { 1907 void Textfield::OnBeforeUserAction() {
1918 DCHECK(!performing_user_action_); 1908 DCHECK(!performing_user_action_);
1919 performing_user_action_ = true; 1909 performing_user_action_ = true;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1973 // IsCommandIdEnabled() as appropriate, for the commands added. 1963 // IsCommandIdEnabled() as appropriate, for the commands added.
1974 if (controller_) 1964 if (controller_)
1975 controller_->UpdateContextMenu(context_menu_contents_.get()); 1965 controller_->UpdateContextMenu(context_menu_contents_.get());
1976 } 1966 }
1977 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), 1967 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(),
1978 MenuRunner::HAS_MNEMONICS | 1968 MenuRunner::HAS_MNEMONICS |
1979 MenuRunner::CONTEXT_MENU | 1969 MenuRunner::CONTEXT_MENU |
1980 MenuRunner::ASYNC)); 1970 MenuRunner::ASYNC));
1981 } 1971 }
1982 1972
1983 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
1984 if (event.IsOnlyLeftMouseButton()) {
1985 base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
1986 if (!last_click_time_.is_null() &&
1987 time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
1988 !ExceededDragThreshold(event.location() - last_click_location_)) {
1989 // Upon clicking after a triple click, the count should go back to double
1990 // click and alternate between double and triple. This assignment maps
1991 // 0 to 1, 1 to 2, 2 to 1.
1992 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
1993 } else {
1994 aggregated_clicks_ = 0;
1995 }
1996 last_click_time_ = event.time_stamp();
1997 last_click_location_ = event.location();
1998 }
1999 }
2000
2001 bool Textfield::ImeEditingAllowed() const { 1973 bool Textfield::ImeEditingAllowed() const {
2002 // Disallow input method editing of password fields. 1974 // Disallow input method editing of password fields.
2003 ui::TextInputType t = GetTextInputType(); 1975 ui::TextInputType t = GetTextInputType();
2004 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); 1976 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
2005 } 1977 }
2006 1978
2007 void Textfield::RevealPasswordChar(int index) { 1979 void Textfield::RevealPasswordChar(int index) {
2008 GetRenderText()->SetObscuredRevealIndex(index); 1980 GetRenderText()->SetObscuredRevealIndex(index);
2009 SchedulePaint(); 1981 SchedulePaint();
2010 1982
2011 if (index != -1) { 1983 if (index != -1) {
2012 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), 1984 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(),
2013 base::Bind(&Textfield::RevealPasswordChar, 1985 base::Bind(&Textfield::RevealPasswordChar,
2014 weak_ptr_factory_.GetWeakPtr(), -1)); 1986 weak_ptr_factory_.GetWeakPtr(), -1));
2015 } 1987 }
2016 } 1988 }
2017 1989
2018 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { 1990 void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
2019 if (!HasFocus()) 1991 if (!HasFocus())
2020 return; 1992 return;
2021 1993
2022 if (!touch_selection_controller_) { 1994 if (!touch_selection_controller_) {
2023 touch_selection_controller_.reset( 1995 touch_selection_controller_.reset(
2024 ui::TouchEditingControllerDeprecated::Create(this)); 1996 ui::TouchEditingControllerDeprecated::Create(this));
2025 } 1997 }
2026 if (touch_selection_controller_) 1998 if (touch_selection_controller_)
2027 touch_selection_controller_->SelectionChanged(); 1999 touch_selection_controller_->SelectionChanged();
2028 } 2000 }
2029 2001
2030 void Textfield::UpdateSelectionClipboard() const {
2031 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2032 if (performing_user_action_ && HasSelection() &&
2033 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
2034 ui::ScopedClipboardWriter(
2035 ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
2036 if (controller_)
2037 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
2038 }
2039 #endif
2040 }
2041
2042 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
2043 DCHECK(event.IsOnlyMiddleMouseButton());
2044 DCHECK(!read_only());
2045 base::string16 selection_clipboard_text = GetSelectionClipboardText();
2046 OnBeforeUserAction();
2047 const gfx::SelectionModel mouse =
2048 GetRenderText()->FindCursorPosition(event.location());
2049 if (!HasFocus())
2050 RequestFocus();
2051 model_->MoveCursorTo(mouse);
2052 if (!selection_clipboard_text.empty()) {
2053 model_->InsertText(selection_clipboard_text);
2054 UpdateAfterChange(true, true);
2055 }
2056 OnAfterUserAction();
2057 }
2058
2059 void Textfield::OnEditFailed() { 2002 void Textfield::OnEditFailed() {
2060 PlatformStyle::OnTextfieldEditFailed(); 2003 PlatformStyle::OnTextfieldEditFailed();
2061 } 2004 }
2062 2005
2063 bool Textfield::ShouldShowCursor() const { 2006 bool Textfield::ShouldShowCursor() const {
2064 return HasFocus() && !HasSelection() && enabled() && !read_only() && 2007 return HasFocus() && !HasSelection() && enabled() && !read_only() &&
2065 !drop_cursor_visible_; 2008 !drop_cursor_visible_;
2066 } 2009 }
2067 2010
2068 bool Textfield::ShouldBlinkCursor() const { 2011 bool Textfield::ShouldBlinkCursor() const {
(...skipping 12 matching lines...) Expand all
2081 } 2024 }
2082 2025
2083 void Textfield::OnCursorBlinkTimerFired() { 2026 void Textfield::OnCursorBlinkTimerFired() {
2084 DCHECK(ShouldBlinkCursor()); 2027 DCHECK(ShouldBlinkCursor());
2085 gfx::RenderText* render_text = GetRenderText(); 2028 gfx::RenderText* render_text = GetRenderText();
2086 render_text->set_cursor_visible(!render_text->cursor_visible()); 2029 render_text->set_cursor_visible(!render_text->cursor_visible());
2087 RepaintCursor(); 2030 RepaintCursor();
2088 } 2031 }
2089 2032
2090 } // namespace views 2033 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698