| 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" |
| 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 Loading... |
| 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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 invalid_(false), | 242 invalid_(false), |
| 256 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | 243 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
| 257 text_input_flags_(0), | 244 text_input_flags_(0), |
| 258 performing_user_action_(false), | 245 performing_user_action_(false), |
| 259 skip_input_method_cancel_composition_(false), | 246 skip_input_method_cancel_composition_(false), |
| 260 drop_cursor_visible_(false), | 247 drop_cursor_visible_(false), |
| 261 initiating_drag_(false), | 248 initiating_drag_(false), |
| 262 aggregated_clicks_(0), | 249 selection_controller_(this), |
| 263 drag_start_display_offset_(0), | 250 drag_start_display_offset_(0), |
| 264 touch_handles_hidden_due_to_scroll_(false), | 251 touch_handles_hidden_due_to_scroll_(false), |
| 265 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), | 252 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), |
| 266 weak_ptr_factory_(this) { | 253 weak_ptr_factory_(this) { |
| 267 set_context_menu_controller(this); | 254 set_context_menu_controller(this); |
| 268 set_drag_controller(this); | 255 set_drag_controller(this); |
| 269 GetRenderText()->SetFontList(GetDefaultFontList()); | 256 GetRenderText()->SetFontList(GetDefaultFontList()); |
| 270 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 257 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
| 271 SetFocusBehavior(FocusBehavior::ALWAYS); | 258 SetFocusBehavior(FocusBehavior::ALWAYS); |
| 272 | 259 |
| 260 // On Linux, middle click should update or paste the selection clipboard. |
| 261 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 262 selection_controller_.set_handles_selection_clipboard(true); |
| 263 #endif |
| 264 |
| 273 // These allow BrowserView to pass edit commands from the Chrome menu to us | 265 // These allow BrowserView to pass edit commands from the Chrome menu to us |
| 274 // when we're focused by simply asking the FocusManager to | 266 // when we're focused by simply asking the FocusManager to |
| 275 // ProcessAccelerator() with the relevant accelerators. | 267 // ProcessAccelerator() with the relevant accelerators. |
| 276 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN)); | 268 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN)); |
| 277 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN)); | 269 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN)); |
| 278 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN)); | 270 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN)); |
| 279 } | 271 } |
| 280 | 272 |
| 281 Textfield::~Textfield() { | 273 Textfield::~Textfield() { |
| 282 if (GetInputMethod()) { | 274 if (GetInputMethod()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 model_->InsertText(new_text); | 320 model_->InsertText(new_text); |
| 329 UpdateAfterChange(true, true); | 321 UpdateAfterChange(true, true); |
| 330 } | 322 } |
| 331 | 323 |
| 332 base::string16 Textfield::GetSelectedText() const { | 324 base::string16 Textfield::GetSelectedText() const { |
| 333 return model_->GetSelectedText(); | 325 return model_->GetSelectedText(); |
| 334 } | 326 } |
| 335 | 327 |
| 336 void Textfield::SelectAll(bool reversed) { | 328 void Textfield::SelectAll(bool reversed) { |
| 337 model_->SelectAll(reversed); | 329 model_->SelectAll(reversed); |
| 338 UpdateSelectionClipboard(); | 330 if (HasSelection() && performing_user_action_) |
| 331 UpdateSelectionClipboard(); |
| 339 UpdateAfterChange(false, true); | 332 UpdateAfterChange(false, true); |
| 340 } | 333 } |
| 341 | 334 |
| 342 void Textfield::SelectWordAt(const gfx::Point& point) { | 335 void Textfield::SelectWordAt(const gfx::Point& point) { |
| 343 model_->MoveCursorTo(point, false); | 336 model_->MoveCursorTo(point, false); |
| 344 model_->SelectWord(); | 337 model_->SelectWord(); |
| 345 UpdateAfterChange(false, true); | 338 UpdateAfterChange(false, true); |
| 346 } | 339 } |
| 347 | 340 |
| 348 void Textfield::ClearSelection() { | 341 void Textfield::ClearSelection() { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 } | 531 } |
| 539 | 532 |
| 540 void Textfield::ClearEditHistory() { | 533 void Textfield::ClearEditHistory() { |
| 541 model_->ClearEditHistory(); | 534 model_->ClearEditHistory(); |
| 542 } | 535 } |
| 543 | 536 |
| 544 void Textfield::SetAccessibleName(const base::string16& name) { | 537 void Textfield::SetAccessibleName(const base::string16& name) { |
| 545 accessible_name_ = name; | 538 accessible_name_ = name; |
| 546 } | 539 } |
| 547 | 540 |
| 548 bool Textfield::HasTextBeingDragged() { | |
| 549 return initiating_drag_; | |
| 550 } | |
| 551 | |
| 552 //////////////////////////////////////////////////////////////////////////////// | 541 //////////////////////////////////////////////////////////////////////////////// |
| 553 // Textfield, View overrides: | 542 // Textfield, View overrides: |
| 554 | 543 |
| 555 gfx::Insets Textfield::GetInsets() const { | 544 gfx::Insets Textfield::GetInsets() const { |
| 556 gfx::Insets insets = View::GetInsets(); | 545 gfx::Insets insets = View::GetInsets(); |
| 557 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); | 546 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); |
| 558 return insets; | 547 return insets; |
| 559 } | 548 } |
| 560 | 549 |
| 561 int Textfield::GetBaseline() const { | 550 int Textfield::GetBaseline() const { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 580 } | 569 } |
| 581 | 570 |
| 582 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { | 571 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { |
| 583 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 572 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); |
| 584 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 573 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
| 585 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 574 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
| 586 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; | 575 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; |
| 587 } | 576 } |
| 588 | 577 |
| 589 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { | 578 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { |
| 590 TrackMouseClicks(event); | 579 bool handled = controller_ && controller_->HandleMouseEvent(this, event); |
| 591 | 580 if (!handled && |
| 592 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { | 581 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) { |
| 593 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { | 582 RequestFocus(); |
| 594 RequestFocus(); | 583 ShowImeIfNeeded(); |
| 595 ShowImeIfNeeded(); | 584 } |
| 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 | 585 |
| 621 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 586 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 622 if (event.IsOnlyMiddleMouseButton()) { | 587 if (!handled && !HasFocus() && event.IsOnlyMiddleMouseButton()) |
| 623 if (GetRenderText()->IsPointInSelection(event.location())) { | 588 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 | 589 #endif |
| 634 } | |
| 635 | 590 |
| 636 return true; | 591 return selection_controller_.OnMousePressed(event, handled); |
| 637 } | 592 } |
| 638 | 593 |
| 639 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 594 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 640 last_drag_location_ = event.location(); | 595 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 } | 596 } |
| 662 | 597 |
| 663 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 598 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 664 OnBeforeUserAction(); | 599 selection_controller_.OnMouseReleased(event); |
| 665 drag_selection_timer_.Stop(); | 600 } |
| 666 // Cancel suspected drag initiations, the user was clicking in the selection. | 601 |
| 667 if (initiating_drag_) | 602 void Textfield::OnMouseCaptureLost() { |
| 668 MoveCursorTo(event.location(), false); | 603 selection_controller_.OnMouseCaptureLost(); |
| 669 initiating_drag_ = false; | |
| 670 UpdateSelectionClipboard(); | |
| 671 OnAfterUserAction(); | |
| 672 } | 604 } |
| 673 | 605 |
| 674 WordLookupClient* Textfield::GetWordLookupClient() { | 606 WordLookupClient* Textfield::GetWordLookupClient() { |
| 675 return this; | 607 return this; |
| 676 } | 608 } |
| 677 | 609 |
| 678 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 610 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 679 ui::TextEditCommand edit_command = scheduled_text_edit_command_; | 611 ui::TextEditCommand edit_command = scheduled_text_edit_command_; |
| 680 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; | 612 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; |
| 681 | 613 |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 // Textfield, WordLookupClient overrides: | 1061 // Textfield, WordLookupClient overrides: |
| 1130 | 1062 |
| 1131 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, | 1063 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, |
| 1132 gfx::DecoratedText* decorated_word, | 1064 gfx::DecoratedText* decorated_word, |
| 1133 gfx::Point* baseline_point) { | 1065 gfx::Point* baseline_point) { |
| 1134 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, | 1066 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, |
| 1135 baseline_point); | 1067 baseline_point); |
| 1136 } | 1068 } |
| 1137 | 1069 |
| 1138 //////////////////////////////////////////////////////////////////////////////// | 1070 //////////////////////////////////////////////////////////////////////////////// |
| 1071 // Textfield, SelectionControllerDelegate overrides: |
| 1072 |
| 1073 bool Textfield::HasTextBeingDragged() const { |
| 1074 return initiating_drag_; |
| 1075 } |
| 1076 |
| 1077 //////////////////////////////////////////////////////////////////////////////// |
| 1139 // Textfield, ui::TouchEditable overrides: | 1078 // Textfield, ui::TouchEditable overrides: |
| 1140 | 1079 |
| 1141 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { | 1080 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { |
| 1142 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) | 1081 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) |
| 1143 return; | 1082 return; |
| 1144 | 1083 |
| 1145 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); | 1084 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); |
| 1146 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); | 1085 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); |
| 1147 gfx::SelectionModel selection( | 1086 gfx::SelectionModel selection( |
| 1148 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), | 1087 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; | 1533 skip_input_method_cancel_composition_ = false; |
| 1595 | 1534 |
| 1596 UpdateAfterChange(true, true); | 1535 UpdateAfterChange(true, true); |
| 1597 OnAfterUserAction(); | 1536 OnAfterUserAction(); |
| 1598 } | 1537 } |
| 1599 | 1538 |
| 1600 gfx::RenderText* Textfield::GetRenderText() const { | 1539 gfx::RenderText* Textfield::GetRenderText() const { |
| 1601 return model_->render_text(); | 1540 return model_->render_text(); |
| 1602 } | 1541 } |
| 1603 | 1542 |
| 1543 gfx::Point Textfield::GetLastClickLocation() const { |
| 1544 return selection_controller_.last_click_location(); |
| 1545 } |
| 1546 |
| 1604 base::string16 Textfield::GetSelectionClipboardText() const { | 1547 base::string16 Textfield::GetSelectionClipboardText() const { |
| 1605 base::string16 selection_clipboard_text; | 1548 base::string16 selection_clipboard_text; |
| 1606 ui::Clipboard::GetForCurrentThread()->ReadText( | 1549 ui::Clipboard::GetForCurrentThread()->ReadText( |
| 1607 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); | 1550 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); |
| 1608 return selection_clipboard_text; | 1551 return selection_clipboard_text; |
| 1609 } | 1552 } |
| 1610 | 1553 |
| 1611 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { | 1554 void Textfield::ExecuteTextEditCommand(ui::TextEditCommand command) { |
| 1612 DestroyTouchSelection(); | 1555 DestroyTouchSelection(); |
| 1613 | 1556 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 break; | 1735 break; |
| 1793 case ui::TextEditCommand::INSERT_TEXT: | 1736 case ui::TextEditCommand::INSERT_TEXT: |
| 1794 case ui::TextEditCommand::SET_MARK: | 1737 case ui::TextEditCommand::SET_MARK: |
| 1795 case ui::TextEditCommand::UNSELECT: | 1738 case ui::TextEditCommand::UNSELECT: |
| 1796 case ui::TextEditCommand::INVALID_COMMAND: | 1739 case ui::TextEditCommand::INVALID_COMMAND: |
| 1797 NOTREACHED(); | 1740 NOTREACHED(); |
| 1798 break; | 1741 break; |
| 1799 } | 1742 } |
| 1800 | 1743 |
| 1801 cursor_changed |= GetSelectionModel() != selection_model; | 1744 cursor_changed |= GetSelectionModel() != selection_model; |
| 1802 if (cursor_changed) | 1745 if (cursor_changed && HasSelection()) |
| 1803 UpdateSelectionClipboard(); | 1746 UpdateSelectionClipboard(); |
| 1804 UpdateAfterChange(text_changed, cursor_changed); | 1747 UpdateAfterChange(text_changed, cursor_changed); |
| 1805 OnAfterUserAction(); | 1748 OnAfterUserAction(); |
| 1806 } | 1749 } |
| 1807 | 1750 |
| 1808 //////////////////////////////////////////////////////////////////////////////// | 1751 //////////////////////////////////////////////////////////////////////////////// |
| 1809 // Textfield, private: | 1752 // Textfield, private: |
| 1810 | 1753 |
| 1754 //////////////////////////////////////////////////////////////////////////////// |
| 1755 // Textfield, SelectionControllerDelegate overrides: |
| 1756 |
| 1757 gfx::RenderText* Textfield::GetRenderTextForSelectionController() { |
| 1758 return GetRenderText(); |
| 1759 } |
| 1760 |
| 1761 bool Textfield::IsReadOnly() const { |
| 1762 return read_only(); |
| 1763 } |
| 1764 |
| 1765 void Textfield::SetTextBeingDragged(bool value) { |
| 1766 initiating_drag_ = value; |
| 1767 } |
| 1768 |
| 1769 int Textfield::GetViewHeight() const { |
| 1770 return height(); |
| 1771 } |
| 1772 |
| 1773 int Textfield::GetViewWidth() const { |
| 1774 return width(); |
| 1775 } |
| 1776 |
| 1777 int Textfield::GetDragSelectionDelay() const { |
| 1778 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { |
| 1779 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: |
| 1780 return 100; |
| 1781 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: |
| 1782 return 25; |
| 1783 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: |
| 1784 return 400; |
| 1785 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: |
| 1786 return 1; |
| 1787 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: |
| 1788 return 0; |
| 1789 } |
| 1790 return 100; |
| 1791 } |
| 1792 |
| 1793 void Textfield::OnBeforePointerAction() { |
| 1794 OnBeforeUserAction(); |
| 1795 if (model_->HasCompositionText()) |
| 1796 model_->ConfirmCompositionText(); |
| 1797 } |
| 1798 |
| 1799 void Textfield::OnAfterPointerAction(bool text_changed, |
| 1800 bool selection_changed) { |
| 1801 OnAfterUserAction(); |
| 1802 UpdateAfterChange(text_changed, selection_changed); |
| 1803 } |
| 1804 |
| 1805 bool Textfield::PasteSelectionClipboard() { |
| 1806 DCHECK(performing_user_action_); |
| 1807 DCHECK(!read_only()); |
| 1808 const base::string16 selection_clipboard_text = GetSelectionClipboardText(); |
| 1809 if (selection_clipboard_text.empty()) |
| 1810 return false; |
| 1811 |
| 1812 model_->InsertText(selection_clipboard_text); |
| 1813 return true; |
| 1814 } |
| 1815 |
| 1816 void Textfield::UpdateSelectionClipboard() { |
| 1817 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 1818 if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { |
| 1819 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) |
| 1820 .WriteText(GetSelectedText()); |
| 1821 if (controller_) |
| 1822 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); |
| 1823 } |
| 1824 #endif |
| 1825 } |
| 1826 |
| 1811 void Textfield::AccessibilitySetValue(const base::string16& new_value) { | 1827 void Textfield::AccessibilitySetValue(const base::string16& new_value) { |
| 1812 if (!read_only()) { | 1828 if (!read_only()) { |
| 1813 SetText(new_value); | 1829 SetText(new_value); |
| 1814 ClearSelection(); | 1830 ClearSelection(); |
| 1815 } | 1831 } |
| 1816 } | 1832 } |
| 1817 | 1833 |
| 1818 void Textfield::UpdateBackgroundColor() { | 1834 void Textfield::UpdateBackgroundColor() { |
| 1819 const SkColor color = GetBackgroundColor(); | 1835 const SkColor color = GetBackgroundColor(); |
| 1820 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { | 1836 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_); | 1907 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1892 | 1908 |
| 1893 canvas->Restore(); | 1909 canvas->Restore(); |
| 1894 } | 1910 } |
| 1895 | 1911 |
| 1896 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | 1912 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { |
| 1897 if (model_->MoveCursorTo(point, select)) | 1913 if (model_->MoveCursorTo(point, select)) |
| 1898 UpdateAfterChange(false, true); | 1914 UpdateAfterChange(false, true); |
| 1899 } | 1915 } |
| 1900 | 1916 |
| 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() { | 1917 void Textfield::OnCaretBoundsChanged() { |
| 1935 if (GetInputMethod()) | 1918 if (GetInputMethod()) |
| 1936 GetInputMethod()->OnCaretBoundsChanged(this); | 1919 GetInputMethod()->OnCaretBoundsChanged(this); |
| 1937 if (touch_selection_controller_) | 1920 if (touch_selection_controller_) |
| 1938 touch_selection_controller_->SelectionChanged(); | 1921 touch_selection_controller_->SelectionChanged(); |
| 1939 } | 1922 } |
| 1940 | 1923 |
| 1941 void Textfield::OnBeforeUserAction() { | 1924 void Textfield::OnBeforeUserAction() { |
| 1942 DCHECK(!performing_user_action_); | 1925 DCHECK(!performing_user_action_); |
| 1943 performing_user_action_ = true; | 1926 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. | 1980 // IsCommandIdEnabled() as appropriate, for the commands added. |
| 1998 if (controller_) | 1981 if (controller_) |
| 1999 controller_->UpdateContextMenu(context_menu_contents_.get()); | 1982 controller_->UpdateContextMenu(context_menu_contents_.get()); |
| 2000 } | 1983 } |
| 2001 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), | 1984 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), |
| 2002 MenuRunner::HAS_MNEMONICS | | 1985 MenuRunner::HAS_MNEMONICS | |
| 2003 MenuRunner::CONTEXT_MENU | | 1986 MenuRunner::CONTEXT_MENU | |
| 2004 MenuRunner::ASYNC)); | 1987 MenuRunner::ASYNC)); |
| 2005 } | 1988 } |
| 2006 | 1989 |
| 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 { | 1990 bool Textfield::ImeEditingAllowed() const { |
| 2026 // Disallow input method editing of password fields. | 1991 // Disallow input method editing of password fields. |
| 2027 ui::TextInputType t = GetTextInputType(); | 1992 ui::TextInputType t = GetTextInputType(); |
| 2028 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 1993 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 2029 } | 1994 } |
| 2030 | 1995 |
| 2031 void Textfield::RevealPasswordChar(int index) { | 1996 void Textfield::RevealPasswordChar(int index) { |
| 2032 GetRenderText()->SetObscuredRevealIndex(index); | 1997 GetRenderText()->SetObscuredRevealIndex(index); |
| 2033 SchedulePaint(); | 1998 SchedulePaint(); |
| 2034 | 1999 |
| 2035 if (index != -1) { | 2000 if (index != -1) { |
| 2036 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), | 2001 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), |
| 2037 base::Bind(&Textfield::RevealPasswordChar, | 2002 base::Bind(&Textfield::RevealPasswordChar, |
| 2038 weak_ptr_factory_.GetWeakPtr(), -1)); | 2003 weak_ptr_factory_.GetWeakPtr(), -1)); |
| 2039 } | 2004 } |
| 2040 } | 2005 } |
| 2041 | 2006 |
| 2042 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { | 2007 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { |
| 2043 if (!HasFocus()) | 2008 if (!HasFocus()) |
| 2044 return; | 2009 return; |
| 2045 | 2010 |
| 2046 if (!touch_selection_controller_) { | 2011 if (!touch_selection_controller_) { |
| 2047 touch_selection_controller_.reset( | 2012 touch_selection_controller_.reset( |
| 2048 ui::TouchEditingControllerDeprecated::Create(this)); | 2013 ui::TouchEditingControllerDeprecated::Create(this)); |
| 2049 } | 2014 } |
| 2050 if (touch_selection_controller_) | 2015 if (touch_selection_controller_) |
| 2051 touch_selection_controller_->SelectionChanged(); | 2016 touch_selection_controller_->SelectionChanged(); |
| 2052 } | 2017 } |
| 2053 | 2018 |
| 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() { | 2019 void Textfield::OnEditFailed() { |
| 2084 PlatformStyle::OnTextfieldEditFailed(); | 2020 PlatformStyle::OnTextfieldEditFailed(); |
| 2085 } | 2021 } |
| 2086 | 2022 |
| 2087 bool Textfield::ShouldShowCursor() const { | 2023 bool Textfield::ShouldShowCursor() const { |
| 2088 return HasFocus() && !HasSelection() && enabled() && !read_only() && | 2024 return HasFocus() && !HasSelection() && enabled() && !read_only() && |
| 2089 !drop_cursor_visible_; | 2025 !drop_cursor_visible_; |
| 2090 } | 2026 } |
| 2091 | 2027 |
| 2092 bool Textfield::ShouldBlinkCursor() const { | 2028 bool Textfield::ShouldBlinkCursor() const { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2105 } | 2041 } |
| 2106 | 2042 |
| 2107 void Textfield::OnCursorBlinkTimerFired() { | 2043 void Textfield::OnCursorBlinkTimerFired() { |
| 2108 DCHECK(ShouldBlinkCursor()); | 2044 DCHECK(ShouldBlinkCursor()); |
| 2109 gfx::RenderText* render_text = GetRenderText(); | 2045 gfx::RenderText* render_text = GetRenderText(); |
| 2110 render_text->set_cursor_visible(!render_text->cursor_visible()); | 2046 render_text->set_cursor_visible(!render_text->cursor_visible()); |
| 2111 RepaintCursor(); | 2047 RepaintCursor(); |
| 2112 } | 2048 } |
| 2113 | 2049 |
| 2114 } // namespace views | 2050 } // namespace views |
| OLD | NEW |