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