Chromium Code Reviews| 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 #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 Loading... | |
| 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" |
| 45 #include "ui/views/selection_controller.h" | |
| 46 #include "ui/views/style/platform_style.h" | 46 #include "ui/views/style/platform_style.h" |
| 47 #include "ui/views/views_delegate.h" | 47 #include "ui/views/views_delegate.h" |
| 48 #include "ui/views/widget/widget.h" | 48 #include "ui/views/widget/widget.h" |
| 49 | 49 |
| 50 #if defined(OS_WIN) | 50 #if defined(OS_WIN) |
| 51 #include "base/win/win_util.h" | 51 #include "base/win/win_util.h" |
| 52 #include "ui/base/win/osk_display_manager.h" | 52 #include "ui/base/win/osk_display_manager.h" |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 55 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 78 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; | 78 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; |
| 79 | 79 |
| 80 void ConvertRectToScreen(const View* src, gfx::Rect* r) { | 80 void ConvertRectToScreen(const View* src, gfx::Rect* r) { |
| 81 DCHECK(src); | 81 DCHECK(src); |
| 82 | 82 |
| 83 gfx::Point new_origin = r->origin(); | 83 gfx::Point new_origin = r->origin(); |
| 84 View::ConvertPointToScreen(src, &new_origin); | 84 View::ConvertPointToScreen(src, &new_origin); |
| 85 r->set_origin(new_origin); | 85 r->set_origin(new_origin); |
| 86 } | 86 } |
| 87 | 87 |
| 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|. | 88 // Get the default command for a given key |event|. |
| 101 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { | 89 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { |
| 102 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) | 90 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) |
| 103 return ui::TextEditCommand::INVALID_COMMAND; | 91 return ui::TextEditCommand::INVALID_COMMAND; |
| 104 | 92 |
| 105 const bool shift = event.IsShiftDown(); | 93 const bool shift = event.IsShiftDown(); |
| 106 const bool control = event.IsControlDown(); | 94 const bool control = event.IsControlDown(); |
| 107 const bool alt = event.IsAltDown() || event.IsAltGrDown(); | 95 const bool alt = event.IsAltDown() || event.IsAltGrDown(); |
| 108 switch (event.key_code()) { | 96 switch (event.key_code()) { |
| 109 case ui::VKEY_Z: | 97 case ui::VKEY_Z: |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 selection_text_color_(SK_ColorWHITE), | 240 selection_text_color_(SK_ColorWHITE), |
| 253 selection_background_color_(SK_ColorBLUE), | 241 selection_background_color_(SK_ColorBLUE), |
| 254 placeholder_text_color_(kDefaultPlaceholderTextColor), | 242 placeholder_text_color_(kDefaultPlaceholderTextColor), |
| 255 invalid_(false), | 243 invalid_(false), |
| 256 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | 244 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
| 257 text_input_flags_(0), | 245 text_input_flags_(0), |
| 258 performing_user_action_(false), | 246 performing_user_action_(false), |
| 259 skip_input_method_cancel_composition_(false), | 247 skip_input_method_cancel_composition_(false), |
| 260 drop_cursor_visible_(false), | 248 drop_cursor_visible_(false), |
| 261 initiating_drag_(false), | 249 initiating_drag_(false), |
| 262 aggregated_clicks_(0), | 250 selection_controller_(new SelectionController(this)), |
| 263 drag_start_display_offset_(0), | 251 drag_start_display_offset_(0), |
| 264 touch_handles_hidden_due_to_scroll_(false), | 252 touch_handles_hidden_due_to_scroll_(false), |
| 265 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), | 253 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), |
| 266 weak_ptr_factory_(this) { | 254 weak_ptr_factory_(this) { |
| 267 set_context_menu_controller(this); | 255 set_context_menu_controller(this); |
| 268 set_drag_controller(this); | 256 set_drag_controller(this); |
| 269 GetRenderText()->SetFontList(GetDefaultFontList()); | 257 GetRenderText()->SetFontList(GetDefaultFontList()); |
| 270 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 258 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
| 271 SetFocusBehavior(FocusBehavior::ALWAYS); | 259 SetFocusBehavior(FocusBehavior::ALWAYS); |
| 272 | 260 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 model_->InsertText(new_text); | 316 model_->InsertText(new_text); |
| 329 UpdateAfterChange(true, true); | 317 UpdateAfterChange(true, true); |
| 330 } | 318 } |
| 331 | 319 |
| 332 base::string16 Textfield::GetSelectedText() const { | 320 base::string16 Textfield::GetSelectedText() const { |
| 333 return model_->GetSelectedText(); | 321 return model_->GetSelectedText(); |
| 334 } | 322 } |
| 335 | 323 |
| 336 void Textfield::SelectAll(bool reversed) { | 324 void Textfield::SelectAll(bool reversed) { |
| 337 model_->SelectAll(reversed); | 325 model_->SelectAll(reversed); |
| 338 UpdateSelectionClipboard(); | 326 if (HasSelection() && performing_user_action_) |
| 327 UpdateSelectionClipboard(); | |
| 339 UpdateAfterChange(false, true); | 328 UpdateAfterChange(false, true); |
| 340 } | 329 } |
| 341 | 330 |
| 342 void Textfield::SelectWordAt(const gfx::Point& point) { | 331 void Textfield::SelectWordAt(const gfx::Point& point) { |
| 343 model_->MoveCursorTo(point, false); | 332 model_->MoveCursorTo(point, false); |
| 344 model_->SelectWord(); | 333 model_->SelectWord(); |
| 345 UpdateAfterChange(false, true); | 334 UpdateAfterChange(false, true); |
| 346 } | 335 } |
| 347 | 336 |
| 348 void Textfield::ClearSelection() { | 337 void Textfield::ClearSelection() { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 } | 527 } |
| 539 | 528 |
| 540 void Textfield::ClearEditHistory() { | 529 void Textfield::ClearEditHistory() { |
| 541 model_->ClearEditHistory(); | 530 model_->ClearEditHistory(); |
| 542 } | 531 } |
| 543 | 532 |
| 544 void Textfield::SetAccessibleName(const base::string16& name) { | 533 void Textfield::SetAccessibleName(const base::string16& name) { |
| 545 accessible_name_ = name; | 534 accessible_name_ = name; |
| 546 } | 535 } |
| 547 | 536 |
| 548 bool Textfield::HasTextBeingDragged() { | |
| 549 return initiating_drag_; | |
| 550 } | |
| 551 | |
| 552 //////////////////////////////////////////////////////////////////////////////// | 537 //////////////////////////////////////////////////////////////////////////////// |
| 553 // Textfield, View overrides: | 538 // Textfield, View overrides: |
| 554 | 539 |
| 555 gfx::Insets Textfield::GetInsets() const { | 540 gfx::Insets Textfield::GetInsets() const { |
| 556 gfx::Insets insets = View::GetInsets(); | 541 gfx::Insets insets = View::GetInsets(); |
| 557 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); | 542 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); |
| 558 return insets; | 543 return insets; |
| 559 } | 544 } |
| 560 | 545 |
| 561 int Textfield::GetBaseline() const { | 546 int Textfield::GetBaseline() const { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 580 } | 565 } |
| 581 | 566 |
| 582 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { | 567 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { |
| 583 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 568 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); |
| 584 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 569 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
| 585 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 570 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
| 586 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; | 571 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; |
| 587 } | 572 } |
| 588 | 573 |
| 589 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { | 574 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { |
| 590 TrackMouseClicks(event); | 575 bool handled = controller_ && controller_->HandleMouseEvent(this, event); |
| 591 | 576 if (!handled && |
| 592 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { | 577 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) { |
| 593 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { | 578 RequestFocus(); |
| 594 RequestFocus(); | 579 ShowImeIfNeeded(); |
| 595 ShowImeIfNeeded(); | 580 } |
| 596 } | |
| 597 | |
| 598 if (event.IsOnlyLeftMouseButton()) { | |
| 599 OnBeforeUserAction(); | |
| 600 initiating_drag_ = false; | |
| 601 switch (aggregated_clicks_) { | |
| 602 case 0: | |
| 603 if (GetRenderText()->IsPointInSelection(event.location())) | |
| 604 initiating_drag_ = true; | |
| 605 else | |
| 606 MoveCursorTo(event.location(), event.IsShiftDown()); | |
| 607 break; | |
| 608 case 1: | |
| 609 SelectWordAt(event.location()); | |
| 610 double_click_word_ = GetRenderText()->selection(); | |
| 611 break; | |
| 612 case 2: | |
| 613 SelectAll(false); | |
| 614 break; | |
| 615 default: | |
| 616 NOTREACHED(); | |
| 617 } | |
| 618 OnAfterUserAction(); | |
| 619 } | |
| 620 | 581 |
| 621 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 582 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 622 if (event.IsOnlyMiddleMouseButton()) { | 583 if (!handled && !HasFocus() && event.IsOnlyMiddleMouseButton()) |
|
karandeepb
2016/10/20 04:12:57
This causes a behavior change (for the better IMO)
msw
2016/10/21 02:14:15
I hugely appreciate your attention to detail and e
karandeepb
2016/10/21 05:04:32
Yeah I think it's still better than the current be
| |
| 623 if (GetRenderText()->IsPointInSelection(event.location())) { | 584 RequestFocus(); |
| 624 OnBeforeUserAction(); | |
| 625 ClearSelection(); | |
| 626 ui::ScopedClipboardWriter( | |
| 627 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16()); | |
| 628 OnAfterUserAction(); | |
| 629 } else if (!read_only()) { | |
| 630 PasteSelectionClipboard(event); | |
| 631 } | |
| 632 } | |
| 633 #endif | 585 #endif |
| 634 } | |
| 635 | 586 |
| 636 return true; | 587 return selection_controller_->OnMousePressed(event, handled); |
| 637 } | 588 } |
| 638 | 589 |
| 639 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 590 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 640 last_drag_location_ = event.location(); | 591 return selection_controller_->OnMouseDragged(event); |
| 641 | |
| 642 // Don't adjust the cursor on a potential drag and drop. | |
| 643 if (initiating_drag_ || !event.IsOnlyLeftMouseButton()) | |
| 644 return true; | |
| 645 | |
| 646 // A timer is used to continuously scroll while selecting beyond side edges. | |
| 647 const int x = event.location().x(); | |
| 648 if ((x >= 0 && x <= width()) || GetDragSelectionDelay() == 0) { | |
| 649 drag_selection_timer_.Stop(); | |
| 650 SelectThroughLastDragLocation(); | |
| 651 } else if (!drag_selection_timer_.IsRunning()) { | |
| 652 // Select through the edge of the visible text, then start the scroll timer. | |
| 653 last_drag_location_.set_x(std::min(std::max(0, x), width())); | |
| 654 SelectThroughLastDragLocation(); | |
| 655 drag_selection_timer_.Start( | |
| 656 FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()), | |
| 657 this, &Textfield::SelectThroughLastDragLocation); | |
| 658 } | |
| 659 | |
| 660 return true; | |
| 661 } | 592 } |
| 662 | 593 |
| 663 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 594 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 664 OnBeforeUserAction(); | 595 selection_controller_->OnMouseReleased(event); |
| 665 drag_selection_timer_.Stop(); | |
| 666 // Cancel suspected drag initiations, the user was clicking in the selection. | |
| 667 if (initiating_drag_) | |
| 668 MoveCursorTo(event.location(), false); | |
| 669 initiating_drag_ = false; | |
| 670 UpdateSelectionClipboard(); | |
| 671 OnAfterUserAction(); | |
| 672 } | 596 } |
| 673 | 597 |
| 674 WordLookupClient* Textfield::GetWordLookupClient() { | 598 WordLookupClient* Textfield::GetWordLookupClient() { |
| 675 return this; | 599 return this; |
| 676 } | 600 } |
| 677 | 601 |
| 678 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 602 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 679 ui::TextEditCommand edit_command = scheduled_text_edit_command_; | 603 ui::TextEditCommand edit_command = scheduled_text_edit_command_; |
| 680 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; | 604 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; |
| 681 | 605 |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1129 // Textfield, WordLookupClient overrides: | 1053 // Textfield, WordLookupClient overrides: |
| 1130 | 1054 |
| 1131 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, | 1055 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, |
| 1132 gfx::DecoratedText* decorated_word, | 1056 gfx::DecoratedText* decorated_word, |
| 1133 gfx::Point* baseline_point) { | 1057 gfx::Point* baseline_point) { |
| 1134 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, | 1058 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, |
| 1135 baseline_point); | 1059 baseline_point); |
| 1136 } | 1060 } |
| 1137 | 1061 |
| 1138 //////////////////////////////////////////////////////////////////////////////// | 1062 //////////////////////////////////////////////////////////////////////////////// |
| 1063 // Textfield, SelectionControllerDelegate overrides: | |
| 1064 | |
| 1065 bool Textfield::HasTextBeingDragged() const { | |
| 1066 return initiating_drag_; | |
| 1067 } | |
| 1068 | |
| 1069 //////////////////////////////////////////////////////////////////////////////// | |
| 1139 // Textfield, ui::TouchEditable overrides: | 1070 // Textfield, ui::TouchEditable overrides: |
| 1140 | 1071 |
| 1141 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { | 1072 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { |
| 1142 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) | 1073 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) |
| 1143 return; | 1074 return; |
| 1144 | 1075 |
| 1145 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); | 1076 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); |
| 1146 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); | 1077 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); |
| 1147 gfx::SelectionModel selection( | 1078 gfx::SelectionModel selection( |
| 1148 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), | 1079 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1594 skip_input_method_cancel_composition_ = false; | 1525 skip_input_method_cancel_composition_ = false; |
| 1595 | 1526 |
| 1596 UpdateAfterChange(true, true); | 1527 UpdateAfterChange(true, true); |
| 1597 OnAfterUserAction(); | 1528 OnAfterUserAction(); |
| 1598 } | 1529 } |
| 1599 | 1530 |
| 1600 gfx::RenderText* Textfield::GetRenderText() const { | 1531 gfx::RenderText* Textfield::GetRenderText() const { |
| 1601 return model_->render_text(); | 1532 return model_->render_text(); |
| 1602 } | 1533 } |
| 1603 | 1534 |
| 1535 gfx::Point Textfield::GetLastClickLocation() const { | |
| 1536 return selection_controller_->last_click_location(); | |
| 1537 } | |
| 1538 | |
| 1604 base::string16 Textfield::GetSelectionClipboardText() const { | 1539 base::string16 Textfield::GetSelectionClipboardText() const { |
| 1605 base::string16 selection_clipboard_text; | 1540 base::string16 selection_clipboard_text; |
| 1606 ui::Clipboard::GetForCurrentThread()->ReadText( | 1541 ui::Clipboard::GetForCurrentThread()->ReadText( |
| 1607 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); | 1542 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); |
| 1608 return selection_clipboard_text; | 1543 return selection_clipboard_text; |
| 1609 } | 1544 } |
| 1610 | 1545 |
| 1611 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { | 1546 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { |
| 1612 DestroyTouchSelection(); | 1547 DestroyTouchSelection(); |
| 1613 | 1548 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1792 break; | 1727 break; |
| 1793 case ui::TextEditCommand::INSERT_TEXT: | 1728 case ui::TextEditCommand::INSERT_TEXT: |
| 1794 case ui::TextEditCommand::SET_MARK: | 1729 case ui::TextEditCommand::SET_MARK: |
| 1795 case ui::TextEditCommand::UNSELECT: | 1730 case ui::TextEditCommand::UNSELECT: |
| 1796 case ui::TextEditCommand::INVALID_COMMAND: | 1731 case ui::TextEditCommand::INVALID_COMMAND: |
| 1797 NOTREACHED(); | 1732 NOTREACHED(); |
| 1798 break; | 1733 break; |
| 1799 } | 1734 } |
| 1800 | 1735 |
| 1801 cursor_changed |= GetSelectionModel() != selection_model; | 1736 cursor_changed |= GetSelectionModel() != selection_model; |
| 1802 if (cursor_changed) | 1737 if (cursor_changed && HasSelection()) |
| 1803 UpdateSelectionClipboard(); | 1738 UpdateSelectionClipboard(); |
| 1804 UpdateAfterChange(text_changed, cursor_changed); | 1739 UpdateAfterChange(text_changed, cursor_changed); |
| 1805 OnAfterUserAction(); | 1740 OnAfterUserAction(); |
| 1806 } | 1741 } |
| 1807 | 1742 |
| 1808 //////////////////////////////////////////////////////////////////////////////// | 1743 //////////////////////////////////////////////////////////////////////////////// |
| 1809 // Textfield, private: | 1744 // Textfield, private: |
| 1810 | 1745 |
| 1746 //////////////////////////////////////////////////////////////////////////////// | |
| 1747 // Textfield, SelectionControllerDelegate overrides: | |
| 1748 | |
| 1749 gfx::RenderText* Textfield::GetRenderTextForSelectionController() { | |
| 1750 return GetRenderText(); | |
| 1751 } | |
| 1752 | |
| 1753 bool Textfield::IsReadOnly() const { | |
| 1754 return read_only(); | |
| 1755 } | |
| 1756 | |
| 1757 void Textfield::SetTextBeingDragged(bool value) { | |
| 1758 initiating_drag_ = value; | |
| 1759 } | |
| 1760 | |
| 1761 int Textfield::GetViewHeight() const { | |
| 1762 return height(); | |
| 1763 } | |
| 1764 | |
| 1765 int Textfield::GetViewWidth() const { | |
| 1766 return width(); | |
| 1767 } | |
| 1768 | |
| 1769 int Textfield::GetDragSelectionDelay() const { | |
| 1770 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { | |
| 1771 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: | |
| 1772 return 100; | |
| 1773 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: | |
| 1774 return 25; | |
| 1775 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: | |
| 1776 return 400; | |
| 1777 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: | |
| 1778 return 1; | |
| 1779 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: | |
| 1780 return 0; | |
| 1781 } | |
| 1782 return 100; | |
| 1783 } | |
| 1784 | |
| 1785 void Textfield::OnBeforeMouseAction() { | |
| 1786 OnBeforeUserAction(); | |
| 1787 if (model_->HasCompositionText()) | |
| 1788 model_->ConfirmCompositionText(); | |
| 1789 } | |
| 1790 | |
| 1791 void Textfield::OnAfterMouseAction(bool text_changed, bool selection_changed) { | |
| 1792 OnAfterUserAction(); | |
| 1793 UpdateAfterChange(text_changed, selection_changed); | |
| 1794 } | |
| 1795 | |
| 1796 bool Textfield::PasteSelectionClipboard() { | |
| 1797 DCHECK(performing_user_action_); | |
| 1798 DCHECK(!read_only()); | |
| 1799 const base::string16 selection_clipboard_text = GetSelectionClipboardText(); | |
| 1800 if (selection_clipboard_text.empty()) | |
| 1801 return false; | |
| 1802 | |
| 1803 model_->InsertText(selection_clipboard_text); | |
|
karandeepb
2016/10/20 04:12:57
Also, removed the UpdateAfterChange here.
msw
2016/10/21 02:14:16
That might be worth a comment, ie. "Callers should
karandeepb
2016/10/21 05:04:32
There are currently no callers within Textfield. A
| |
| 1804 return true; | |
| 1805 } | |
| 1806 | |
| 1807 void Textfield::UpdateSelectionClipboard() { | |
| 1808 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1809 if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 1810 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) | |
| 1811 .WriteText(GetSelectedText()); | |
| 1812 if (controller_) | |
| 1813 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); | |
| 1814 } | |
| 1815 #endif | |
| 1816 } | |
| 1817 | |
| 1811 void Textfield::AccessibilitySetValue(const base::string16& new_value) { | 1818 void Textfield::AccessibilitySetValue(const base::string16& new_value) { |
| 1812 if (!read_only()) { | 1819 if (!read_only()) { |
| 1813 SetText(new_value); | 1820 SetText(new_value); |
| 1814 ClearSelection(); | 1821 ClearSelection(); |
| 1815 } | 1822 } |
| 1816 } | 1823 } |
| 1817 | 1824 |
| 1818 void Textfield::UpdateBackgroundColor() { | 1825 void Textfield::UpdateBackgroundColor() { |
| 1819 const SkColor color = GetBackgroundColor(); | 1826 const SkColor color = GetBackgroundColor(); |
| 1820 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { | 1827 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1891 render_text->DrawCursor(canvas, drop_cursor_position_); | 1898 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1892 | 1899 |
| 1893 canvas->Restore(); | 1900 canvas->Restore(); |
| 1894 } | 1901 } |
| 1895 | 1902 |
| 1896 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | 1903 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { |
| 1897 if (model_->MoveCursorTo(point, select)) | 1904 if (model_->MoveCursorTo(point, select)) |
| 1898 UpdateAfterChange(false, true); | 1905 UpdateAfterChange(false, true); |
| 1899 } | 1906 } |
| 1900 | 1907 |
| 1901 void Textfield::SelectThroughLastDragLocation() { | |
| 1902 OnBeforeUserAction(); | |
| 1903 | |
| 1904 const bool drags_to_end = PlatformStyle::kTextfieldDragVerticallyDragsToEnd; | |
| 1905 if (drags_to_end && last_drag_location_.y() < 0) { | |
| 1906 model_->MoveCursor(gfx::BreakType::LINE_BREAK, | |
| 1907 gfx::VisualCursorDirection::CURSOR_LEFT, | |
| 1908 gfx::SELECTION_RETAIN); | |
| 1909 } else if (drags_to_end && last_drag_location_.y() > height()) { | |
| 1910 model_->MoveCursor(gfx::BreakType::LINE_BREAK, | |
| 1911 gfx::VisualCursorDirection::CURSOR_RIGHT, | |
| 1912 gfx::SELECTION_RETAIN); | |
| 1913 } else { | |
| 1914 model_->MoveCursorTo(last_drag_location_, true); | |
| 1915 } | |
| 1916 | |
| 1917 if (aggregated_clicks_ == 1) { | |
| 1918 model_->SelectWord(); | |
| 1919 // Expand the selection so the initially selected word remains selected. | |
| 1920 gfx::Range selection = GetRenderText()->selection(); | |
| 1921 const size_t min = std::min(selection.GetMin(), | |
| 1922 double_click_word_.GetMin()); | |
| 1923 const size_t max = std::max(selection.GetMax(), | |
| 1924 double_click_word_.GetMax()); | |
| 1925 const bool reversed = selection.is_reversed(); | |
| 1926 selection.set_start(reversed ? max : min); | |
| 1927 selection.set_end(reversed ? min : max); | |
| 1928 model_->SelectRange(selection); | |
| 1929 } | |
| 1930 UpdateAfterChange(false, true); | |
| 1931 OnAfterUserAction(); | |
| 1932 } | |
| 1933 | |
| 1934 void Textfield::OnCaretBoundsChanged() { | 1908 void Textfield::OnCaretBoundsChanged() { |
| 1935 if (GetInputMethod()) | 1909 if (GetInputMethod()) |
| 1936 GetInputMethod()->OnCaretBoundsChanged(this); | 1910 GetInputMethod()->OnCaretBoundsChanged(this); |
| 1937 if (touch_selection_controller_) | 1911 if (touch_selection_controller_) |
| 1938 touch_selection_controller_->SelectionChanged(); | 1912 touch_selection_controller_->SelectionChanged(); |
| 1939 } | 1913 } |
| 1940 | 1914 |
| 1941 void Textfield::OnBeforeUserAction() { | 1915 void Textfield::OnBeforeUserAction() { |
| 1942 DCHECK(!performing_user_action_); | 1916 DCHECK(!performing_user_action_); |
| 1943 performing_user_action_ = true; | 1917 performing_user_action_ = true; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1997 // IsCommandIdEnabled() as appropriate, for the commands added. | 1971 // IsCommandIdEnabled() as appropriate, for the commands added. |
| 1998 if (controller_) | 1972 if (controller_) |
| 1999 controller_->UpdateContextMenu(context_menu_contents_.get()); | 1973 controller_->UpdateContextMenu(context_menu_contents_.get()); |
| 2000 } | 1974 } |
| 2001 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), | 1975 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), |
| 2002 MenuRunner::HAS_MNEMONICS | | 1976 MenuRunner::HAS_MNEMONICS | |
| 2003 MenuRunner::CONTEXT_MENU | | 1977 MenuRunner::CONTEXT_MENU | |
| 2004 MenuRunner::ASYNC)); | 1978 MenuRunner::ASYNC)); |
| 2005 } | 1979 } |
| 2006 | 1980 |
| 2007 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { | |
| 2008 if (event.IsOnlyLeftMouseButton()) { | |
| 2009 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; | |
| 2010 if (!last_click_time_.is_null() && | |
| 2011 time_delta.InMilliseconds() <= GetDoubleClickInterval() && | |
| 2012 !ExceededDragThreshold(event.location() - last_click_location_)) { | |
| 2013 // Upon clicking after a triple click, the count should go back to double | |
| 2014 // click and alternate between double and triple. This assignment maps | |
| 2015 // 0 to 1, 1 to 2, 2 to 1. | |
| 2016 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1; | |
| 2017 } else { | |
| 2018 aggregated_clicks_ = 0; | |
| 2019 } | |
| 2020 last_click_time_ = event.time_stamp(); | |
| 2021 last_click_location_ = event.location(); | |
| 2022 } | |
| 2023 } | |
| 2024 | |
| 2025 bool Textfield::ImeEditingAllowed() const { | 1981 bool Textfield::ImeEditingAllowed() const { |
| 2026 // Disallow input method editing of password fields. | 1982 // Disallow input method editing of password fields. |
| 2027 ui::TextInputType t = GetTextInputType(); | 1983 ui::TextInputType t = GetTextInputType(); |
| 2028 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 1984 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 2029 } | 1985 } |
| 2030 | 1986 |
| 2031 void Textfield::RevealPasswordChar(int index) { | 1987 void Textfield::RevealPasswordChar(int index) { |
| 2032 GetRenderText()->SetObscuredRevealIndex(index); | 1988 GetRenderText()->SetObscuredRevealIndex(index); |
| 2033 SchedulePaint(); | 1989 SchedulePaint(); |
| 2034 | 1990 |
| 2035 if (index != -1) { | 1991 if (index != -1) { |
| 2036 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), | 1992 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), |
| 2037 base::Bind(&Textfield::RevealPasswordChar, | 1993 base::Bind(&Textfield::RevealPasswordChar, |
| 2038 weak_ptr_factory_.GetWeakPtr(), -1)); | 1994 weak_ptr_factory_.GetWeakPtr(), -1)); |
| 2039 } | 1995 } |
| 2040 } | 1996 } |
| 2041 | 1997 |
| 2042 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { | 1998 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { |
| 2043 if (!HasFocus()) | 1999 if (!HasFocus()) |
| 2044 return; | 2000 return; |
| 2045 | 2001 |
| 2046 if (!touch_selection_controller_) { | 2002 if (!touch_selection_controller_) { |
| 2047 touch_selection_controller_.reset( | 2003 touch_selection_controller_.reset( |
| 2048 ui::TouchEditingControllerDeprecated::Create(this)); | 2004 ui::TouchEditingControllerDeprecated::Create(this)); |
| 2049 } | 2005 } |
| 2050 if (touch_selection_controller_) | 2006 if (touch_selection_controller_) |
| 2051 touch_selection_controller_->SelectionChanged(); | 2007 touch_selection_controller_->SelectionChanged(); |
| 2052 } | 2008 } |
| 2053 | 2009 |
| 2054 void Textfield::UpdateSelectionClipboard() const { | |
| 2055 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 2056 if (performing_user_action_ && HasSelection() && | |
| 2057 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 2058 ui::ScopedClipboardWriter( | |
| 2059 ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText()); | |
| 2060 if (controller_) | |
| 2061 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); | |
| 2062 } | |
| 2063 #endif | |
| 2064 } | |
| 2065 | |
| 2066 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) { | |
| 2067 DCHECK(event.IsOnlyMiddleMouseButton()); | |
| 2068 DCHECK(!read_only()); | |
| 2069 base::string16 selection_clipboard_text = GetSelectionClipboardText(); | |
| 2070 OnBeforeUserAction(); | |
| 2071 const gfx::SelectionModel mouse = | |
| 2072 GetRenderText()->FindCursorPosition(event.location()); | |
| 2073 if (!HasFocus()) | |
| 2074 RequestFocus(); | |
| 2075 model_->MoveCursorTo(mouse); | |
|
karandeepb
2016/10/20 04:12:58
Do you know if using TextfieldModel::MoveCursorTo(
msw
2016/10/21 02:14:15
I also doubt that it's deliberate. It seems like w
karandeepb
2016/10/21 05:04:32
Already doing it.
| |
| 2076 if (!selection_clipboard_text.empty()) { | |
| 2077 model_->InsertText(selection_clipboard_text); | |
| 2078 UpdateAfterChange(true, true); | |
| 2079 } | |
| 2080 OnAfterUserAction(); | |
| 2081 } | |
| 2082 | |
| 2083 void Textfield::OnEditFailed() { | 2010 void Textfield::OnEditFailed() { |
| 2084 PlatformStyle::OnTextfieldEditFailed(); | 2011 PlatformStyle::OnTextfieldEditFailed(); |
| 2085 } | 2012 } |
| 2086 | 2013 |
| 2087 bool Textfield::ShouldShowCursor() const { | 2014 bool Textfield::ShouldShowCursor() const { |
| 2088 return HasFocus() && !HasSelection() && enabled() && !read_only() && | 2015 return HasFocus() && !HasSelection() && enabled() && !read_only() && |
| 2089 !drop_cursor_visible_; | 2016 !drop_cursor_visible_; |
| 2090 } | 2017 } |
| 2091 | 2018 |
| 2092 bool Textfield::ShouldBlinkCursor() const { | 2019 bool Textfield::ShouldBlinkCursor() const { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2105 } | 2032 } |
| 2106 | 2033 |
| 2107 void Textfield::OnCursorBlinkTimerFired() { | 2034 void Textfield::OnCursorBlinkTimerFired() { |
| 2108 DCHECK(ShouldBlinkCursor()); | 2035 DCHECK(ShouldBlinkCursor()); |
| 2109 gfx::RenderText* render_text = GetRenderText(); | 2036 gfx::RenderText* render_text = GetRenderText(); |
| 2110 render_text->set_cursor_visible(!render_text->cursor_visible()); | 2037 render_text->set_cursor_visible(!render_text->cursor_visible()); |
| 2111 RepaintCursor(); | 2038 RepaintCursor(); |
| 2112 } | 2039 } |
| 2113 | 2040 |
| 2114 } // namespace views | 2041 } // namespace views |
| OLD | NEW |