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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 use_default_selection_background_color_(true), | 237 use_default_selection_background_color_(true), |
| 250 text_color_(SK_ColorBLACK), | 238 text_color_(SK_ColorBLACK), |
| 251 background_color_(SK_ColorWHITE), | 239 background_color_(SK_ColorWHITE), |
| 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), |
| 247 performing_mouse_action_(false), | |
| 259 skip_input_method_cancel_composition_(false), | 248 skip_input_method_cancel_composition_(false), |
| 260 drop_cursor_visible_(false), | 249 drop_cursor_visible_(false), |
| 261 initiating_drag_(false), | 250 initiating_drag_(false), |
| 262 aggregated_clicks_(0), | 251 selection_controller_(new SelectionController(this)), |
| 263 drag_start_display_offset_(0), | 252 drag_start_display_offset_(0), |
| 264 touch_handles_hidden_due_to_scroll_(false), | 253 touch_handles_hidden_due_to_scroll_(false), |
| 265 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), | 254 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), |
| 266 weak_ptr_factory_(this) { | 255 weak_ptr_factory_(this) { |
| 267 set_context_menu_controller(this); | 256 set_context_menu_controller(this); |
| 268 set_drag_controller(this); | 257 set_drag_controller(this); |
| 269 GetRenderText()->SetFontList(GetDefaultFontList()); | 258 GetRenderText()->SetFontList(GetDefaultFontList()); |
| 270 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 259 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
| 271 SetFocusBehavior(FocusBehavior::ALWAYS); | 260 SetFocusBehavior(FocusBehavior::ALWAYS); |
| 272 | 261 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 model_->InsertText(new_text); | 317 model_->InsertText(new_text); |
| 329 UpdateAfterChange(true, true); | 318 UpdateAfterChange(true, true); |
| 330 } | 319 } |
| 331 | 320 |
| 332 base::string16 Textfield::GetSelectedText() const { | 321 base::string16 Textfield::GetSelectedText() const { |
| 333 return model_->GetSelectedText(); | 322 return model_->GetSelectedText(); |
| 334 } | 323 } |
| 335 | 324 |
| 336 void Textfield::SelectAll(bool reversed) { | 325 void Textfield::SelectAll(bool reversed) { |
| 337 model_->SelectAll(reversed); | 326 model_->SelectAll(reversed); |
| 338 UpdateSelectionClipboard(); | 327 if (HasSelection()) |
| 328 UpdateSelectionClipboard(); | |
| 339 UpdateAfterChange(false, true); | 329 UpdateAfterChange(false, true); |
| 340 } | 330 } |
| 341 | 331 |
| 342 void Textfield::SelectWordAt(const gfx::Point& point) { | 332 void Textfield::SelectWordAt(const gfx::Point& point) { |
| 343 model_->MoveCursorTo(point, false); | 333 model_->MoveCursorTo(point, false); |
| 344 model_->SelectWord(); | 334 model_->SelectWord(); |
| 345 UpdateAfterChange(false, true); | 335 UpdateAfterChange(false, true); |
| 346 } | 336 } |
| 347 | 337 |
| 348 void Textfield::ClearSelection() { | 338 void Textfield::ClearSelection() { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 } | 528 } |
| 539 | 529 |
| 540 void Textfield::ClearEditHistory() { | 530 void Textfield::ClearEditHistory() { |
| 541 model_->ClearEditHistory(); | 531 model_->ClearEditHistory(); |
| 542 } | 532 } |
| 543 | 533 |
| 544 void Textfield::SetAccessibleName(const base::string16& name) { | 534 void Textfield::SetAccessibleName(const base::string16& name) { |
| 545 accessible_name_ = name; | 535 accessible_name_ = name; |
| 546 } | 536 } |
| 547 | 537 |
| 548 bool Textfield::HasTextBeingDragged() { | |
| 549 return initiating_drag_; | |
| 550 } | |
| 551 | |
| 552 //////////////////////////////////////////////////////////////////////////////// | 538 //////////////////////////////////////////////////////////////////////////////// |
| 553 // Textfield, View overrides: | 539 // Textfield, View overrides: |
| 554 | 540 |
| 555 gfx::Insets Textfield::GetInsets() const { | 541 gfx::Insets Textfield::GetInsets() const { |
| 556 gfx::Insets insets = View::GetInsets(); | 542 gfx::Insets insets = View::GetInsets(); |
| 557 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); | 543 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); |
| 558 return insets; | 544 return insets; |
| 559 } | 545 } |
| 560 | 546 |
| 561 int Textfield::GetBaseline() const { | 547 int Textfield::GetBaseline() const { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 580 } | 566 } |
| 581 | 567 |
| 582 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { | 568 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { |
| 583 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 569 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); |
| 584 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 570 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
| 585 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 571 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
| 586 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; | 572 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; |
| 587 } | 573 } |
| 588 | 574 |
| 589 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { | 575 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { |
| 590 TrackMouseClicks(event); | 576 bool handled = controller_ && controller_->HandleMouseEvent(this, event); |
| 591 | 577 if (!handled && |
| 592 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { | 578 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) { |
| 593 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { | 579 RequestFocus(); |
| 594 RequestFocus(); | 580 ShowImeIfNeeded(); |
| 595 ShowImeIfNeeded(); | |
| 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 | |
| 621 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 622 if (event.IsOnlyMiddleMouseButton()) { | |
| 623 if (GetRenderText()->IsPointInSelection(event.location())) { | |
| 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 | |
| 634 } | 581 } |
| 635 | 582 return selection_controller_->OnMousePressed(event, handled); |
| 636 return true; | |
| 637 } | 583 } |
| 638 | 584 |
| 639 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 585 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 640 last_drag_location_ = event.location(); | 586 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 } | 587 } |
| 662 | 588 |
| 663 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 589 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 664 OnBeforeUserAction(); | 590 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 } | 591 } |
| 673 | 592 |
| 674 WordLookupClient* Textfield::GetWordLookupClient() { | 593 WordLookupClient* Textfield::GetWordLookupClient() { |
| 675 return this; | 594 return this; |
| 676 } | 595 } |
| 677 | 596 |
| 678 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 597 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 679 ui::TextEditCommand edit_command = scheduled_text_edit_command_; | 598 ui::TextEditCommand edit_command = scheduled_text_edit_command_; |
| 680 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; | 599 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; |
| 681 | 600 |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1129 // Textfield, WordLookupClient overrides: | 1048 // Textfield, WordLookupClient overrides: |
| 1130 | 1049 |
| 1131 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, | 1050 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, |
| 1132 gfx::DecoratedText* decorated_word, | 1051 gfx::DecoratedText* decorated_word, |
| 1133 gfx::Point* baseline_point) { | 1052 gfx::Point* baseline_point) { |
| 1134 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, | 1053 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, |
| 1135 baseline_point); | 1054 baseline_point); |
| 1136 } | 1055 } |
| 1137 | 1056 |
| 1138 //////////////////////////////////////////////////////////////////////////////// | 1057 //////////////////////////////////////////////////////////////////////////////// |
| 1058 // Textfield, SelectionControllerDelegate overrides: | |
| 1059 | |
| 1060 bool Textfield::HasTextBeingDragged() const { | |
| 1061 return initiating_drag_; | |
| 1062 } | |
| 1063 | |
| 1064 //////////////////////////////////////////////////////////////////////////////// | |
| 1139 // Textfield, ui::TouchEditable overrides: | 1065 // Textfield, ui::TouchEditable overrides: |
| 1140 | 1066 |
| 1141 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { | 1067 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { |
| 1142 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) | 1068 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) |
| 1143 return; | 1069 return; |
| 1144 | 1070 |
| 1145 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); | 1071 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); |
| 1146 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); | 1072 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); |
| 1147 gfx::SelectionModel selection( | 1073 gfx::SelectionModel selection( |
| 1148 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), | 1074 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; | 1520 skip_input_method_cancel_composition_ = false; |
| 1595 | 1521 |
| 1596 UpdateAfterChange(true, true); | 1522 UpdateAfterChange(true, true); |
| 1597 OnAfterUserAction(); | 1523 OnAfterUserAction(); |
| 1598 } | 1524 } |
| 1599 | 1525 |
| 1600 gfx::RenderText* Textfield::GetRenderText() const { | 1526 gfx::RenderText* Textfield::GetRenderText() const { |
| 1601 return model_->render_text(); | 1527 return model_->render_text(); |
| 1602 } | 1528 } |
| 1603 | 1529 |
| 1530 gfx::Point Textfield::GetLastClickLocation() const { | |
| 1531 return selection_controller_->last_click_location(); | |
| 1532 } | |
| 1533 | |
| 1604 base::string16 Textfield::GetSelectionClipboardText() const { | 1534 base::string16 Textfield::GetSelectionClipboardText() const { |
| 1605 base::string16 selection_clipboard_text; | 1535 base::string16 selection_clipboard_text; |
| 1606 ui::Clipboard::GetForCurrentThread()->ReadText( | 1536 ui::Clipboard::GetForCurrentThread()->ReadText( |
| 1607 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); | 1537 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); |
| 1608 return selection_clipboard_text; | 1538 return selection_clipboard_text; |
| 1609 } | 1539 } |
| 1610 | 1540 |
| 1611 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { | 1541 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { |
| 1612 DestroyTouchSelection(); | 1542 DestroyTouchSelection(); |
| 1613 | 1543 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1792 break; | 1722 break; |
| 1793 case ui::TextEditCommand::INSERT_TEXT: | 1723 case ui::TextEditCommand::INSERT_TEXT: |
| 1794 case ui::TextEditCommand::SET_MARK: | 1724 case ui::TextEditCommand::SET_MARK: |
| 1795 case ui::TextEditCommand::UNSELECT: | 1725 case ui::TextEditCommand::UNSELECT: |
| 1796 case ui::TextEditCommand::INVALID_COMMAND: | 1726 case ui::TextEditCommand::INVALID_COMMAND: |
| 1797 NOTREACHED(); | 1727 NOTREACHED(); |
| 1798 break; | 1728 break; |
| 1799 } | 1729 } |
| 1800 | 1730 |
| 1801 cursor_changed |= GetSelectionModel() != selection_model; | 1731 cursor_changed |= GetSelectionModel() != selection_model; |
| 1802 if (cursor_changed) | 1732 if (cursor_changed && HasSelection()) |
| 1803 UpdateSelectionClipboard(); | 1733 UpdateSelectionClipboard(); |
| 1804 UpdateAfterChange(text_changed, cursor_changed); | 1734 UpdateAfterChange(text_changed, cursor_changed); |
| 1805 OnAfterUserAction(); | 1735 OnAfterUserAction(); |
| 1806 } | 1736 } |
| 1807 | 1737 |
| 1808 //////////////////////////////////////////////////////////////////////////////// | 1738 //////////////////////////////////////////////////////////////////////////////// |
| 1809 // Textfield, private: | 1739 // Textfield, private: |
| 1810 | 1740 |
| 1741 //////////////////////////////////////////////////////////////////////////////// | |
| 1742 // Textfield, SelectionControllerDelegate overrides: | |
| 1743 | |
| 1744 gfx::RenderText* Textfield::GetRenderTextForSelectionController() { | |
| 1745 return GetRenderText(); | |
| 1746 } | |
| 1747 | |
| 1748 bool Textfield::IsReadOnly() const { | |
| 1749 return read_only(); | |
| 1750 } | |
| 1751 | |
| 1752 void Textfield::SetTextBeingDragged(bool value) { | |
| 1753 initiating_drag_ = value; | |
| 1754 } | |
| 1755 | |
| 1756 int Textfield::GetViewHeight() const { | |
| 1757 return height(); | |
| 1758 } | |
| 1759 | |
| 1760 int Textfield::GetViewWidth() const { | |
| 1761 return width(); | |
| 1762 } | |
| 1763 | |
| 1764 int Textfield::GetDragSelectionDelay() const { | |
| 1765 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { | |
| 1766 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: | |
| 1767 return 100; | |
| 1768 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: | |
| 1769 return 25; | |
| 1770 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: | |
| 1771 return 400; | |
| 1772 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: | |
| 1773 return 1; | |
| 1774 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: | |
| 1775 return 0; | |
| 1776 } | |
| 1777 return 100; | |
| 1778 } | |
| 1779 | |
| 1780 void Textfield::OnBeforeMouseAction() { | |
| 1781 OnBeforeUserAction(); | |
| 1782 DCHECK(!performing_mouse_action_); | |
| 1783 performing_mouse_action_ = true; | |
| 1784 } | |
| 1785 | |
| 1786 void Textfield::OnAfterMouseAction(bool text_changed, bool selection_changed) { | |
| 1787 OnAfterUserAction(); | |
| 1788 DCHECK(performing_mouse_action_); | |
| 1789 performing_mouse_action_ = false; | |
| 1790 UpdateAfterChange(text_changed, selection_changed); | |
| 1791 } | |
| 1792 | |
| 1793 void Textfield::OnBeforeSelectionUpdated() { | |
|
msw
2016/10/18 23:15:05
nit: rename these to OnBeforeSelectionUpdate and O
karandeepb
2016/10/20 04:12:57
Done. (Obsolete)
| |
| 1794 DCHECK(performing_mouse_action_); | |
| 1795 if (model_->HasCompositionText()) | |
| 1796 model_->ConfirmCompositionText(); | |
| 1797 } | |
| 1798 | |
| 1799 void Textfield::OnAfterSelectionUpdated() { | |
| 1800 DCHECK(performing_mouse_action_); | |
| 1801 UpdateAfterChange(false, true); | |
| 1802 } | |
| 1803 | |
| 1804 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) { | |
| 1805 if (!event.IsOnlyMiddleMouseButton() || read_only() || | |
| 1806 !performing_user_action_) | |
| 1807 return; | |
| 1808 base::string16 selection_clipboard_text = GetSelectionClipboardText(); | |
| 1809 const gfx::SelectionModel mouse = | |
| 1810 GetRenderText()->FindCursorPosition(event.location()); | |
| 1811 if (!HasFocus()) | |
| 1812 RequestFocus(); | |
| 1813 model_->MoveCursorTo(mouse); | |
| 1814 if (!selection_clipboard_text.empty()) { | |
| 1815 model_->InsertText(selection_clipboard_text); | |
| 1816 UpdateAfterChange(true, true); | |
| 1817 } | |
| 1818 } | |
| 1819 | |
| 1820 void Textfield::UpdateSelectionClipboard() { | |
| 1821 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1822 if (performing_user_action_ && | |
| 1823 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 1824 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) | |
| 1825 .WriteText(GetSelectedText()); | |
| 1826 if (controller_) | |
| 1827 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); | |
| 1828 } | |
| 1829 #endif | |
| 1830 } | |
| 1831 | |
| 1811 void Textfield::AccessibilitySetValue(const base::string16& new_value) { | 1832 void Textfield::AccessibilitySetValue(const base::string16& new_value) { |
| 1812 if (!read_only()) { | 1833 if (!read_only()) { |
| 1813 SetText(new_value); | 1834 SetText(new_value); |
| 1814 ClearSelection(); | 1835 ClearSelection(); |
| 1815 } | 1836 } |
| 1816 } | 1837 } |
| 1817 | 1838 |
| 1818 void Textfield::UpdateBackgroundColor() { | 1839 void Textfield::UpdateBackgroundColor() { |
| 1819 const SkColor color = GetBackgroundColor(); | 1840 const SkColor color = GetBackgroundColor(); |
| 1820 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { | 1841 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1833 } | 1854 } |
| 1834 | 1855 |
| 1835 void Textfield::UpdateBorder() { | 1856 void Textfield::UpdateBorder() { |
| 1836 auto border = base::MakeUnique<views::FocusableBorder>(); | 1857 auto border = base::MakeUnique<views::FocusableBorder>(); |
| 1837 if (invalid_) | 1858 if (invalid_) |
| 1838 border->SetColorId(ui::NativeTheme::kColorId_AlertSeverityHigh); | 1859 border->SetColorId(ui::NativeTheme::kColorId_AlertSeverityHigh); |
| 1839 View::SetBorder(std::move(border)); | 1860 View::SetBorder(std::move(border)); |
| 1840 } | 1861 } |
| 1841 | 1862 |
| 1842 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { | 1863 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { |
| 1864 if (performing_mouse_action_) | |
| 1865 return; | |
| 1843 if (text_changed) { | 1866 if (text_changed) { |
| 1844 if (controller_) | 1867 if (controller_) |
| 1845 controller_->ContentsChanged(this, text()); | 1868 controller_->ContentsChanged(this, text()); |
| 1846 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); | 1869 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); |
| 1847 } | 1870 } |
| 1848 if (cursor_changed) { | 1871 if (cursor_changed) { |
| 1849 GetRenderText()->set_cursor_visible(ShouldShowCursor()); | 1872 GetRenderText()->set_cursor_visible(ShouldShowCursor()); |
| 1850 RepaintCursor(); | 1873 RepaintCursor(); |
| 1851 if (ShouldBlinkCursor()) | 1874 if (ShouldBlinkCursor()) |
| 1852 StartBlinkingCursor(); | 1875 StartBlinkingCursor(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1891 render_text->DrawCursor(canvas, drop_cursor_position_); | 1914 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1892 | 1915 |
| 1893 canvas->Restore(); | 1916 canvas->Restore(); |
| 1894 } | 1917 } |
| 1895 | 1918 |
| 1896 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | 1919 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { |
| 1897 if (model_->MoveCursorTo(point, select)) | 1920 if (model_->MoveCursorTo(point, select)) |
| 1898 UpdateAfterChange(false, true); | 1921 UpdateAfterChange(false, true); |
| 1899 } | 1922 } |
| 1900 | 1923 |
| 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() { | 1924 void Textfield::OnCaretBoundsChanged() { |
| 1935 if (GetInputMethod()) | 1925 if (GetInputMethod()) |
| 1936 GetInputMethod()->OnCaretBoundsChanged(this); | 1926 GetInputMethod()->OnCaretBoundsChanged(this); |
| 1937 if (touch_selection_controller_) | 1927 if (touch_selection_controller_) |
| 1938 touch_selection_controller_->SelectionChanged(); | 1928 touch_selection_controller_->SelectionChanged(); |
| 1939 } | 1929 } |
| 1940 | 1930 |
| 1941 void Textfield::OnBeforeUserAction() { | 1931 void Textfield::OnBeforeUserAction() { |
| 1942 DCHECK(!performing_user_action_); | 1932 DCHECK(!performing_user_action_); |
| 1943 performing_user_action_ = true; | 1933 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. | 1987 // IsCommandIdEnabled() as appropriate, for the commands added. |
| 1998 if (controller_) | 1988 if (controller_) |
| 1999 controller_->UpdateContextMenu(context_menu_contents_.get()); | 1989 controller_->UpdateContextMenu(context_menu_contents_.get()); |
| 2000 } | 1990 } |
| 2001 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), | 1991 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), |
| 2002 MenuRunner::HAS_MNEMONICS | | 1992 MenuRunner::HAS_MNEMONICS | |
| 2003 MenuRunner::CONTEXT_MENU | | 1993 MenuRunner::CONTEXT_MENU | |
| 2004 MenuRunner::ASYNC)); | 1994 MenuRunner::ASYNC)); |
| 2005 } | 1995 } |
| 2006 | 1996 |
| 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 { | 1997 bool Textfield::ImeEditingAllowed() const { |
| 2026 // Disallow input method editing of password fields. | 1998 // Disallow input method editing of password fields. |
| 2027 ui::TextInputType t = GetTextInputType(); | 1999 ui::TextInputType t = GetTextInputType(); |
| 2028 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 2000 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 2029 } | 2001 } |
| 2030 | 2002 |
| 2031 void Textfield::RevealPasswordChar(int index) { | 2003 void Textfield::RevealPasswordChar(int index) { |
| 2032 GetRenderText()->SetObscuredRevealIndex(index); | 2004 GetRenderText()->SetObscuredRevealIndex(index); |
| 2033 SchedulePaint(); | 2005 SchedulePaint(); |
| 2034 | 2006 |
| 2035 if (index != -1) { | 2007 if (index != -1) { |
| 2036 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), | 2008 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), |
| 2037 base::Bind(&Textfield::RevealPasswordChar, | 2009 base::Bind(&Textfield::RevealPasswordChar, |
| 2038 weak_ptr_factory_.GetWeakPtr(), -1)); | 2010 weak_ptr_factory_.GetWeakPtr(), -1)); |
| 2039 } | 2011 } |
| 2040 } | 2012 } |
| 2041 | 2013 |
| 2042 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { | 2014 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { |
| 2043 if (!HasFocus()) | 2015 if (!HasFocus()) |
| 2044 return; | 2016 return; |
| 2045 | 2017 |
| 2046 if (!touch_selection_controller_) { | 2018 if (!touch_selection_controller_) { |
| 2047 touch_selection_controller_.reset( | 2019 touch_selection_controller_.reset( |
| 2048 ui::TouchEditingControllerDeprecated::Create(this)); | 2020 ui::TouchEditingControllerDeprecated::Create(this)); |
| 2049 } | 2021 } |
| 2050 if (touch_selection_controller_) | 2022 if (touch_selection_controller_) |
| 2051 touch_selection_controller_->SelectionChanged(); | 2023 touch_selection_controller_->SelectionChanged(); |
| 2052 } | 2024 } |
| 2053 | 2025 |
| 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); | |
| 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() { | 2026 void Textfield::OnEditFailed() { |
| 2084 PlatformStyle::OnTextfieldEditFailed(); | 2027 PlatformStyle::OnTextfieldEditFailed(); |
| 2085 } | 2028 } |
| 2086 | 2029 |
| 2087 bool Textfield::ShouldShowCursor() const { | 2030 bool Textfield::ShouldShowCursor() const { |
| 2088 return HasFocus() && !HasSelection() && enabled() && !read_only() && | 2031 return HasFocus() && !HasSelection() && enabled() && !read_only() && |
| 2089 !drop_cursor_visible_; | 2032 !drop_cursor_visible_; |
| 2090 } | 2033 } |
| 2091 | 2034 |
| 2092 bool Textfield::ShouldBlinkCursor() const { | 2035 bool Textfield::ShouldBlinkCursor() const { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2105 } | 2048 } |
| 2106 | 2049 |
| 2107 void Textfield::OnCursorBlinkTimerFired() { | 2050 void Textfield::OnCursorBlinkTimerFired() { |
| 2108 DCHECK(ShouldBlinkCursor()); | 2051 DCHECK(ShouldBlinkCursor()); |
| 2109 gfx::RenderText* render_text = GetRenderText(); | 2052 gfx::RenderText* render_text = GetRenderText(); |
| 2110 render_text->set_cursor_visible(!render_text->cursor_visible()); | 2053 render_text->set_cursor_visible(!render_text->cursor_visible()); |
| 2111 RepaintCursor(); | 2054 RepaintCursor(); |
| 2112 } | 2055 } |
| 2113 | 2056 |
| 2114 } // namespace views | 2057 } // namespace views |
| OLD | NEW |