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 21 matching lines...) Expand all Loading... | |
| 32 #include "ui/gfx/selection_bound.h" | 32 #include "ui/gfx/selection_bound.h" |
| 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/focusable_border.h" | 36 #include "ui/views/controls/focusable_border.h" |
| 37 #include "ui/views/controls/label.h" | 37 #include "ui/views/controls/label.h" |
| 38 #include "ui/views/controls/menu/menu_runner.h" | 38 #include "ui/views/controls/menu/menu_runner.h" |
| 39 #include "ui/views/controls/native/native_view_host.h" | 39 #include "ui/views/controls/native/native_view_host.h" |
| 40 #include "ui/views/controls/textfield/textfield_controller.h" | 40 #include "ui/views/controls/textfield/textfield_controller.h" |
| 41 #include "ui/views/drag_utils.h" | 41 #include "ui/views/drag_utils.h" |
| 42 #include "ui/views/metrics.h" | |
| 43 #include "ui/views/native_cursor.h" | 42 #include "ui/views/native_cursor.h" |
| 44 #include "ui/views/painter.h" | 43 #include "ui/views/painter.h" |
| 44 #include "ui/views/selection_controller.h" | |
| 45 #include "ui/views/style/platform_style.h" | 45 #include "ui/views/style/platform_style.h" |
| 46 #include "ui/views/views_delegate.h" | 46 #include "ui/views/views_delegate.h" |
| 47 #include "ui/views/widget/widget.h" | 47 #include "ui/views/widget/widget.h" |
| 48 | 48 |
| 49 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
| 50 #include "base/win/win_util.h" | 50 #include "base/win/win_util.h" |
| 51 #include "ui/base/win/osk_display_manager.h" | 51 #include "ui/base/win/osk_display_manager.h" |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | 54 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 77 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; | 77 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY; |
| 78 | 78 |
| 79 void ConvertRectToScreen(const View* src, gfx::Rect* r) { | 79 void ConvertRectToScreen(const View* src, gfx::Rect* r) { |
| 80 DCHECK(src); | 80 DCHECK(src); |
| 81 | 81 |
| 82 gfx::Point new_origin = r->origin(); | 82 gfx::Point new_origin = r->origin(); |
| 83 View::ConvertPointToScreen(src, &new_origin); | 83 View::ConvertPointToScreen(src, &new_origin); |
| 84 r->set_origin(new_origin); | 84 r->set_origin(new_origin); |
| 85 } | 85 } |
| 86 | 86 |
| 87 // Get the drag selection timer delay, respecting animation scaling for testing. | |
| 88 int GetDragSelectionDelay() { | |
| 89 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { | |
| 90 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100; | |
| 91 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25; | |
| 92 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400; | |
| 93 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: return 1; | |
| 94 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0; | |
| 95 } | |
| 96 return 100; | |
| 97 } | |
| 98 | |
| 99 // Get the default command for a given key |event|. | 87 // Get the default command for a given key |event|. |
| 100 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { | 88 ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) { |
| 101 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) | 89 if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode()) |
| 102 return ui::TextEditCommand::INVALID_COMMAND; | 90 return ui::TextEditCommand::INVALID_COMMAND; |
| 103 | 91 |
| 104 const bool shift = event.IsShiftDown(); | 92 const bool shift = event.IsShiftDown(); |
| 105 const bool control = event.IsControlDown(); | 93 const bool control = event.IsControlDown(); |
| 106 const bool alt = event.IsAltDown() || event.IsAltGrDown(); | 94 const bool alt = event.IsAltDown() || event.IsAltGrDown(); |
| 107 switch (event.key_code()) { | 95 switch (event.key_code()) { |
| 108 case ui::VKEY_Z: | 96 case ui::VKEY_Z: |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 use_default_selection_text_color_(true), | 235 use_default_selection_text_color_(true), |
| 248 use_default_selection_background_color_(true), | 236 use_default_selection_background_color_(true), |
| 249 text_color_(SK_ColorBLACK), | 237 text_color_(SK_ColorBLACK), |
| 250 background_color_(SK_ColorWHITE), | 238 background_color_(SK_ColorWHITE), |
| 251 selection_text_color_(SK_ColorWHITE), | 239 selection_text_color_(SK_ColorWHITE), |
| 252 selection_background_color_(SK_ColorBLUE), | 240 selection_background_color_(SK_ColorBLUE), |
| 253 placeholder_text_color_(kDefaultPlaceholderTextColor), | 241 placeholder_text_color_(kDefaultPlaceholderTextColor), |
| 254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), | 242 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
| 255 text_input_flags_(0), | 243 text_input_flags_(0), |
| 256 performing_user_action_(false), | 244 performing_user_action_(false), |
| 245 performing_mouse_action_(false), | |
| 257 skip_input_method_cancel_composition_(false), | 246 skip_input_method_cancel_composition_(false), |
| 258 drop_cursor_visible_(false), | 247 drop_cursor_visible_(false), |
| 259 initiating_drag_(false), | 248 initiating_drag_(false), |
| 260 aggregated_clicks_(0), | 249 selection_controller_(new SelectionController(this)), |
| 261 drag_start_display_offset_(0), | 250 drag_start_display_offset_(0), |
| 262 touch_handles_hidden_due_to_scroll_(false), | 251 touch_handles_hidden_due_to_scroll_(false), |
| 263 weak_ptr_factory_(this) { | 252 weak_ptr_factory_(this) { |
| 264 set_context_menu_controller(this); | 253 set_context_menu_controller(this); |
| 265 set_drag_controller(this); | 254 set_drag_controller(this); |
| 266 GetRenderText()->SetFontList(GetDefaultFontList()); | 255 GetRenderText()->SetFontList(GetDefaultFontList()); |
| 267 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 256 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
| 268 SetFocusBehavior(FocusBehavior::ALWAYS); | 257 SetFocusBehavior(FocusBehavior::ALWAYS); |
| 269 | 258 |
| 270 // These allow BrowserView to pass edit commands from the Chrome menu to us | 259 // These allow BrowserView to pass edit commands from the Chrome menu to us |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 return; | 313 return; |
| 325 model_->InsertText(new_text); | 314 model_->InsertText(new_text); |
| 326 OnCaretBoundsChanged(); | 315 OnCaretBoundsChanged(); |
| 327 SchedulePaint(); | 316 SchedulePaint(); |
| 328 } | 317 } |
| 329 | 318 |
| 330 base::string16 Textfield::GetSelectedText() const { | 319 base::string16 Textfield::GetSelectedText() const { |
| 331 return model_->GetSelectedText(); | 320 return model_->GetSelectedText(); |
| 332 } | 321 } |
| 333 | 322 |
| 334 void Textfield::SelectAll(bool reversed) { | |
| 335 model_->SelectAll(reversed); | |
| 336 UpdateSelectionClipboard(); | |
| 337 UpdateAfterChange(false, true); | |
| 338 } | |
| 339 | |
| 340 void Textfield::SelectWordAt(const gfx::Point& point) { | |
| 341 model_->MoveCursorTo(point, false); | |
| 342 model_->SelectWord(); | |
| 343 UpdateAfterChange(false, true); | |
| 344 } | |
| 345 | |
| 346 void Textfield::ClearSelection() { | |
| 347 model_->ClearSelection(); | |
| 348 UpdateAfterChange(false, true); | |
| 349 } | |
| 350 | |
| 351 bool Textfield::HasSelection() const { | 323 bool Textfield::HasSelection() const { |
| 352 return !GetSelectedRange().is_empty(); | 324 return !GetSelectedRange().is_empty(); |
| 353 } | 325 } |
| 354 | 326 |
| 355 SkColor Textfield::GetTextColor() const { | 327 SkColor Textfield::GetTextColor() const { |
| 356 if (!use_default_text_color_) | 328 if (!use_default_text_color_) |
| 357 return text_color_; | 329 return text_color_; |
| 358 | 330 |
| 359 return GetNativeTheme()->GetSystemColor(read_only() || !enabled() ? | 331 return GetNativeTheme()->GetSystemColor(read_only() || !enabled() ? |
| 360 ui::NativeTheme::kColorId_TextfieldReadOnlyColor : | 332 ui::NativeTheme::kColorId_TextfieldReadOnlyColor : |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 } | 447 } |
| 476 | 448 |
| 477 bool Textfield::IsIMEComposing() const { | 449 bool Textfield::IsIMEComposing() const { |
| 478 return model_->HasCompositionText(); | 450 return model_->HasCompositionText(); |
| 479 } | 451 } |
| 480 | 452 |
| 481 const gfx::Range& Textfield::GetSelectedRange() const { | 453 const gfx::Range& Textfield::GetSelectedRange() const { |
| 482 return GetRenderText()->selection(); | 454 return GetRenderText()->selection(); |
| 483 } | 455 } |
| 484 | 456 |
| 485 void Textfield::SelectRange(const gfx::Range& range) { | |
| 486 model_->SelectRange(range); | |
| 487 UpdateAfterChange(false, true); | |
| 488 } | |
| 489 | |
| 490 const gfx::SelectionModel& Textfield::GetSelectionModel() const { | 457 const gfx::SelectionModel& Textfield::GetSelectionModel() const { |
| 491 return GetRenderText()->selection_model(); | 458 return GetRenderText()->selection_model(); |
| 492 } | 459 } |
| 493 | 460 |
| 494 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) { | 461 void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) { |
| 495 model_->SelectSelectionModel(sel); | 462 model_->SelectSelectionModel(sel); |
| 496 UpdateAfterChange(false, true); | 463 UpdateAfterChange(false, true); |
| 497 } | 464 } |
| 498 | 465 |
| 499 size_t Textfield::GetCursorPosition() const { | 466 size_t Textfield::GetCursorPosition() const { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 523 } | 490 } |
| 524 | 491 |
| 525 void Textfield::ClearEditHistory() { | 492 void Textfield::ClearEditHistory() { |
| 526 model_->ClearEditHistory(); | 493 model_->ClearEditHistory(); |
| 527 } | 494 } |
| 528 | 495 |
| 529 void Textfield::SetAccessibleName(const base::string16& name) { | 496 void Textfield::SetAccessibleName(const base::string16& name) { |
| 530 accessible_name_ = name; | 497 accessible_name_ = name; |
| 531 } | 498 } |
| 532 | 499 |
| 533 bool Textfield::HasTextBeingDragged() { | |
| 534 return initiating_drag_; | |
| 535 } | |
| 536 | |
| 537 //////////////////////////////////////////////////////////////////////////////// | 500 //////////////////////////////////////////////////////////////////////////////// |
| 538 // Textfield, View overrides: | 501 // Textfield, View overrides: |
| 539 | 502 |
| 540 gfx::Insets Textfield::GetInsets() const { | 503 gfx::Insets Textfield::GetInsets() const { |
| 541 gfx::Insets insets = View::GetInsets(); | 504 gfx::Insets insets = View::GetInsets(); |
| 542 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); | 505 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); |
| 543 return insets; | 506 return insets; |
| 544 } | 507 } |
| 545 | 508 |
| 546 int Textfield::GetBaseline() const { | 509 int Textfield::GetBaseline() const { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 558 } | 521 } |
| 559 | 522 |
| 560 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { | 523 gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) { |
| 561 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); | 524 bool in_selection = GetRenderText()->IsPointInSelection(event.location()); |
| 562 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; | 525 bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED; |
| 563 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); | 526 bool text_cursor = !initiating_drag_ && (drag_event || !in_selection); |
| 564 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; | 527 return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor; |
| 565 } | 528 } |
| 566 | 529 |
| 567 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { | 530 bool Textfield::OnMousePressed(const ui::MouseEvent& event) { |
| 568 TrackMouseClicks(event); | 531 bool handled = controller_ && controller_->HandleMouseEvent(this, event); |
| 569 | 532 if (!handled && |
| 570 if (!controller_ || !controller_->HandleMouseEvent(this, event)) { | 533 (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())) { |
| 571 if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) { | 534 RequestFocus(); |
| 572 RequestFocus(); | 535 ShowImeIfNeeded(); |
| 573 ShowImeIfNeeded(); | |
| 574 } | |
| 575 | |
| 576 if (event.IsOnlyLeftMouseButton()) { | |
| 577 OnBeforeUserAction(); | |
| 578 initiating_drag_ = false; | |
| 579 switch (aggregated_clicks_) { | |
| 580 case 0: | |
| 581 if (GetRenderText()->IsPointInSelection(event.location())) | |
| 582 initiating_drag_ = true; | |
| 583 else | |
| 584 MoveCursorTo(event.location(), event.IsShiftDown()); | |
| 585 break; | |
| 586 case 1: | |
| 587 SelectWordAt(event.location()); | |
| 588 double_click_word_ = GetRenderText()->selection(); | |
| 589 break; | |
| 590 case 2: | |
| 591 SelectAll(false); | |
| 592 break; | |
| 593 default: | |
| 594 NOTREACHED(); | |
| 595 } | |
| 596 OnAfterUserAction(); | |
| 597 } | |
| 598 | |
| 599 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 600 if (event.IsOnlyMiddleMouseButton()) { | |
| 601 if (GetRenderText()->IsPointInSelection(event.location())) { | |
| 602 OnBeforeUserAction(); | |
| 603 ClearSelection(); | |
| 604 ui::ScopedClipboardWriter( | |
| 605 ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16()); | |
| 606 OnAfterUserAction(); | |
| 607 } else if (!read_only()) { | |
| 608 PasteSelectionClipboard(event); | |
| 609 } | |
| 610 } | |
| 611 #endif | |
| 612 } | 536 } |
| 613 | 537 |
| 614 return true; | 538 return handled | selection_controller_->OnMousePressed(event, handled); |
| 615 } | 539 } |
| 616 | 540 |
| 617 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { | 541 bool Textfield::OnMouseDragged(const ui::MouseEvent& event) { |
| 618 last_drag_location_ = event.location(); | 542 return selection_controller_->OnMouseDragged(event); |
| 619 | |
| 620 // Don't adjust the cursor on a potential drag and drop. | |
| 621 if (initiating_drag_ || !event.IsOnlyLeftMouseButton()) | |
| 622 return true; | |
| 623 | |
| 624 // A timer is used to continuously scroll while selecting beyond side edges. | |
| 625 const int x = event.location().x(); | |
| 626 if ((x >= 0 && x <= width()) || GetDragSelectionDelay() == 0) { | |
| 627 drag_selection_timer_.Stop(); | |
| 628 SelectThroughLastDragLocation(); | |
| 629 } else if (!drag_selection_timer_.IsRunning()) { | |
| 630 // Select through the edge of the visible text, then start the scroll timer. | |
| 631 last_drag_location_.set_x(std::min(std::max(0, x), width())); | |
| 632 SelectThroughLastDragLocation(); | |
| 633 drag_selection_timer_.Start( | |
| 634 FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()), | |
| 635 this, &Textfield::SelectThroughLastDragLocation); | |
| 636 } | |
| 637 | |
| 638 return true; | |
| 639 } | 543 } |
| 640 | 544 |
| 641 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { | 545 void Textfield::OnMouseReleased(const ui::MouseEvent& event) { |
| 642 OnBeforeUserAction(); | 546 selection_controller_->OnMouseReleased(event); |
| 643 drag_selection_timer_.Stop(); | |
| 644 // Cancel suspected drag initiations, the user was clicking in the selection. | |
| 645 if (initiating_drag_) | |
| 646 MoveCursorTo(event.location(), false); | |
| 647 initiating_drag_ = false; | |
| 648 UpdateSelectionClipboard(); | |
| 649 OnAfterUserAction(); | |
| 650 } | 547 } |
| 651 | 548 |
| 652 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { | 549 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) { |
| 653 ui::TextEditCommand edit_command = scheduled_text_edit_command_; | 550 ui::TextEditCommand edit_command = scheduled_text_edit_command_; |
| 654 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; | 551 scheduled_text_edit_command_ = ui::TextEditCommand::INVALID_COMMAND; |
| 655 | 552 |
| 656 // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify | 553 // Since HandleKeyEvent() might destroy |this|, get a weak pointer and verify |
| 657 // it isn't null before proceeding. | 554 // it isn't null before proceeding. |
| 658 base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr()); | 555 base::WeakPtr<Textfield> textfield(weak_ptr_factory_.GetWeakPtr()); |
| 659 | 556 |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1090 return drag_operations; | 987 return drag_operations; |
| 1091 } | 988 } |
| 1092 | 989 |
| 1093 bool Textfield::CanStartDragForView(View* sender, | 990 bool Textfield::CanStartDragForView(View* sender, |
| 1094 const gfx::Point& press_pt, | 991 const gfx::Point& press_pt, |
| 1095 const gfx::Point& p) { | 992 const gfx::Point& p) { |
| 1096 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); | 993 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); |
| 1097 } | 994 } |
| 1098 | 995 |
| 1099 //////////////////////////////////////////////////////////////////////////////// | 996 //////////////////////////////////////////////////////////////////////////////// |
| 997 // Textfield, SelectionControllerHost overrides: | |
| 998 | |
| 999 bool Textfield::HasTextBeingDragged() const { | |
| 1000 return initiating_drag_; | |
| 1001 } | |
| 1002 | |
| 1003 void Textfield::SelectAll(bool reversed) { | |
| 1004 model_->SelectAll(reversed); | |
| 1005 if (HasSelection()) | |
| 1006 UpdateSelectionClipboard(); | |
|
tapted
2016/10/11 04:42:09
this feels like something the SelectionController
karandeepb
2016/10/14 09:27:34
Not sure if this is still relevant. Also, it seems
| |
| 1007 UpdateAfterChange(false, true); | |
| 1008 } | |
| 1009 | |
| 1010 void Textfield::SelectRange(const gfx::Range& range) { | |
| 1011 model_->SelectRange(range); | |
| 1012 UpdateAfterChange(false, true); | |
| 1013 } | |
| 1014 | |
| 1015 void Textfield::ClearSelection() { | |
| 1016 model_->ClearSelection(); | |
| 1017 UpdateAfterChange(false, true); | |
| 1018 } | |
| 1019 | |
| 1020 //////////////////////////////////////////////////////////////////////////////// | |
| 1100 // Textfield, ui::TouchEditable overrides: | 1021 // Textfield, ui::TouchEditable overrides: |
| 1101 | 1022 |
| 1102 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { | 1023 void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) { |
| 1103 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) | 1024 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) |
| 1104 return; | 1025 return; |
| 1105 | 1026 |
| 1106 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); | 1027 gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start); |
| 1107 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); | 1028 gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end); |
| 1108 gfx::SelectionModel selection( | 1029 gfx::SelectionModel selection( |
| 1109 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), | 1030 gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()), |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1753 break; | 1674 break; |
| 1754 case ui::TextEditCommand::INSERT_TEXT: | 1675 case ui::TextEditCommand::INSERT_TEXT: |
| 1755 case ui::TextEditCommand::SET_MARK: | 1676 case ui::TextEditCommand::SET_MARK: |
| 1756 case ui::TextEditCommand::UNSELECT: | 1677 case ui::TextEditCommand::UNSELECT: |
| 1757 case ui::TextEditCommand::INVALID_COMMAND: | 1678 case ui::TextEditCommand::INVALID_COMMAND: |
| 1758 NOTREACHED(); | 1679 NOTREACHED(); |
| 1759 break; | 1680 break; |
| 1760 } | 1681 } |
| 1761 | 1682 |
| 1762 cursor_changed |= GetSelectionModel() != selection_model; | 1683 cursor_changed |= GetSelectionModel() != selection_model; |
| 1763 if (cursor_changed) | 1684 if (cursor_changed && HasSelection()) |
| 1764 UpdateSelectionClipboard(); | 1685 UpdateSelectionClipboard(); |
| 1765 UpdateAfterChange(text_changed, cursor_changed); | 1686 UpdateAfterChange(text_changed, cursor_changed); |
| 1766 OnAfterUserAction(); | 1687 OnAfterUserAction(); |
| 1767 } | 1688 } |
| 1768 | 1689 |
| 1769 //////////////////////////////////////////////////////////////////////////////// | 1690 //////////////////////////////////////////////////////////////////////////////// |
| 1770 // Textfield, private: | 1691 // Textfield, private: |
| 1771 | 1692 |
| 1693 //////////////////////////////////////////////////////////////////////////////// | |
| 1694 // Textfield, SelectionControllerHost overrides: | |
| 1695 | |
| 1696 gfx::RenderText* Textfield::GetRenderTextForSelection() { | |
| 1697 return GetRenderText(); | |
| 1698 } | |
| 1699 | |
| 1700 bool Textfield::IsReadOnly() const { | |
| 1701 return false; | |
| 1702 } | |
| 1703 | |
| 1704 void Textfield::SetTextBeingDragged(bool value) { | |
| 1705 initiating_drag_ = value; | |
| 1706 } | |
| 1707 | |
| 1708 int Textfield::GetViewHeight() const { | |
| 1709 return height(); | |
| 1710 } | |
| 1711 | |
| 1712 int Textfield::GetViewWidth() const { | |
| 1713 return width(); | |
| 1714 } | |
| 1715 | |
| 1716 int Textfield::GetDragSelectionDelay() const { | |
| 1717 switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) { | |
| 1718 case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: | |
| 1719 return 100; | |
| 1720 case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: | |
| 1721 return 25; | |
| 1722 case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: | |
| 1723 return 400; | |
| 1724 case ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION: | |
| 1725 return 1; | |
| 1726 case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: | |
| 1727 return 0; | |
| 1728 } | |
| 1729 return 100; | |
| 1730 } | |
| 1731 | |
| 1732 void Textfield::OnBeforeMouseAction() { | |
| 1733 OnBeforeUserAction(); | |
| 1734 DCHECK(!performing_mouse_action_); | |
| 1735 performing_mouse_action_ = true; | |
| 1736 } | |
| 1737 | |
| 1738 void Textfield::OnAfterMouseAction(bool text_changed, bool selection_changed) { | |
| 1739 OnAfterUserAction(); | |
| 1740 DCHECK(performing_mouse_action_); | |
| 1741 performing_mouse_action_ = false; | |
| 1742 UpdateAfterChange(text_changed, selection_changed); | |
| 1743 } | |
| 1744 | |
| 1745 void Textfield::SelectWordAt(const gfx::Point& point) { | |
| 1746 model_->MoveCursorTo(point, false); | |
| 1747 SelectWord(); | |
| 1748 } | |
| 1749 | |
| 1750 void Textfield::SelectWord() { | |
| 1751 model_->SelectWord(); | |
| 1752 UpdateAfterChange(false, true); | |
|
tapted
2016/10/11 04:42:09
yeah if these can move into TextfieldModel (or som
karandeepb
2016/10/14 09:27:34
Have updated SelectionController and narrowed down
| |
| 1753 } | |
| 1754 | |
| 1755 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | |
| 1756 if (model_->MoveCursorTo(point, select)) | |
| 1757 UpdateAfterChange(false, true); | |
| 1758 } | |
| 1759 | |
| 1760 void Textfield::SelectTillEdge(gfx::VisualCursorDirection direction) { | |
| 1761 GetRenderText()->MoveCursor(gfx::LINE_BREAK, direction, | |
| 1762 gfx::SELECTION_RETAIN); | |
| 1763 UpdateAfterChange(false, true); | |
| 1764 } | |
| 1765 | |
| 1766 void Textfield::PasteSelectionClipboard() { | |
| 1767 if (read_only()) | |
| 1768 return; | |
| 1769 const base::string16 selection_clipboard_text = GetSelectionClipboardText(); | |
| 1770 if (!HasFocus()) | |
| 1771 RequestFocus(); | |
| 1772 if (!selection_clipboard_text.empty()) { | |
| 1773 model_->InsertText(selection_clipboard_text); | |
| 1774 UpdateAfterChange(true, true); | |
| 1775 } | |
| 1776 } | |
| 1777 | |
| 1778 void Textfield::UpdateSelectionClipboard() { | |
| 1779 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 1780 if (performing_user_action_ && | |
| 1781 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 1782 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) | |
| 1783 .WriteText(GetSelectedText()); | |
| 1784 if (controller_) | |
| 1785 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); | |
| 1786 } | |
| 1787 #endif | |
| 1788 } | |
| 1789 | |
| 1772 void Textfield::AccessibilitySetValue(const base::string16& new_value) { | 1790 void Textfield::AccessibilitySetValue(const base::string16& new_value) { |
| 1773 if (!read_only()) { | 1791 if (!read_only()) { |
| 1774 SetText(new_value); | 1792 SetText(new_value); |
| 1775 ClearSelection(); | 1793 ClearSelection(); |
| 1776 } | 1794 } |
| 1777 } | 1795 } |
| 1778 | 1796 |
| 1779 void Textfield::UpdateBackgroundColor() { | 1797 void Textfield::UpdateBackgroundColor() { |
| 1780 const SkColor color = GetBackgroundColor(); | 1798 const SkColor color = GetBackgroundColor(); |
| 1781 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { | 1799 if (ui::MaterialDesignController::IsSecondaryUiMaterial()) { |
| 1782 set_background(Background::CreateBackgroundPainter( | 1800 set_background(Background::CreateBackgroundPainter( |
| 1783 true, Painter::CreateSolidRoundRectPainter( | 1801 true, Painter::CreateSolidRoundRectPainter( |
| 1784 color, FocusableBorder::kCornerRadiusDp))); | 1802 color, FocusableBorder::kCornerRadiusDp))); |
| 1785 } else { | 1803 } else { |
| 1786 set_background(Background::CreateSolidBackground(color)); | 1804 set_background(Background::CreateSolidBackground(color)); |
| 1787 } | 1805 } |
| 1788 // Disable subpixel rendering when the background color is transparent | 1806 // Disable subpixel rendering when the background color is transparent |
| 1789 // because it draws incorrect colors around the glyphs in that case. | 1807 // because it draws incorrect colors around the glyphs in that case. |
| 1790 // See crbug.com/115198 | 1808 // See crbug.com/115198 |
| 1791 GetRenderText()->set_subpixel_rendering_suppressed( | 1809 GetRenderText()->set_subpixel_rendering_suppressed( |
| 1792 SkColorGetA(color) != SK_AlphaOPAQUE); | 1810 SkColorGetA(color) != SK_AlphaOPAQUE); |
| 1793 SchedulePaint(); | 1811 SchedulePaint(); |
| 1794 } | 1812 } |
| 1795 | 1813 |
| 1796 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { | 1814 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { |
| 1815 if (performing_mouse_action_) | |
| 1816 return; | |
| 1797 if (text_changed) { | 1817 if (text_changed) { |
| 1798 if (controller_) | 1818 if (controller_) |
| 1799 controller_->ContentsChanged(this, text()); | 1819 controller_->ContentsChanged(this, text()); |
| 1800 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); | 1820 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); |
| 1801 } | 1821 } |
| 1802 if (cursor_changed) { | 1822 if (cursor_changed) { |
| 1803 GetRenderText()->set_cursor_visible(ShouldShowCursor()); | 1823 GetRenderText()->set_cursor_visible(ShouldShowCursor()); |
| 1804 RepaintCursor(); | 1824 RepaintCursor(); |
| 1805 if (ShouldBlinkCursor()) | 1825 if (ShouldBlinkCursor()) |
| 1806 StartBlinkingCursor(); | 1826 StartBlinkingCursor(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1840 | 1860 |
| 1841 render_text->Draw(canvas); | 1861 render_text->Draw(canvas); |
| 1842 | 1862 |
| 1843 // Draw the detached drop cursor that marks where the text will be dropped. | 1863 // Draw the detached drop cursor that marks where the text will be dropped. |
| 1844 if (drop_cursor_visible_) | 1864 if (drop_cursor_visible_) |
| 1845 render_text->DrawCursor(canvas, drop_cursor_position_); | 1865 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1846 | 1866 |
| 1847 canvas->Restore(); | 1867 canvas->Restore(); |
| 1848 } | 1868 } |
| 1849 | 1869 |
| 1850 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { | |
| 1851 if (model_->MoveCursorTo(point, select)) | |
| 1852 UpdateAfterChange(false, true); | |
| 1853 } | |
| 1854 | |
| 1855 void Textfield::SelectThroughLastDragLocation() { | |
| 1856 OnBeforeUserAction(); | |
| 1857 | |
| 1858 const bool drags_to_end = PlatformStyle::kTextfieldDragVerticallyDragsToEnd; | |
| 1859 if (drags_to_end && last_drag_location_.y() < 0) { | |
| 1860 model_->MoveCursor(gfx::BreakType::LINE_BREAK, | |
| 1861 gfx::VisualCursorDirection::CURSOR_LEFT, | |
| 1862 gfx::SELECTION_RETAIN); | |
| 1863 } else if (drags_to_end && last_drag_location_.y() > height()) { | |
| 1864 model_->MoveCursor(gfx::BreakType::LINE_BREAK, | |
| 1865 gfx::VisualCursorDirection::CURSOR_RIGHT, | |
| 1866 gfx::SELECTION_RETAIN); | |
| 1867 } else { | |
| 1868 model_->MoveCursorTo(last_drag_location_, true); | |
| 1869 } | |
| 1870 | |
| 1871 if (aggregated_clicks_ == 1) { | |
| 1872 model_->SelectWord(); | |
| 1873 // Expand the selection so the initially selected word remains selected. | |
| 1874 gfx::Range selection = GetRenderText()->selection(); | |
| 1875 const size_t min = std::min(selection.GetMin(), | |
| 1876 double_click_word_.GetMin()); | |
| 1877 const size_t max = std::max(selection.GetMax(), | |
| 1878 double_click_word_.GetMax()); | |
| 1879 const bool reversed = selection.is_reversed(); | |
| 1880 selection.set_start(reversed ? max : min); | |
| 1881 selection.set_end(reversed ? min : max); | |
| 1882 model_->SelectRange(selection); | |
| 1883 } | |
| 1884 UpdateAfterChange(false, true); | |
| 1885 OnAfterUserAction(); | |
| 1886 } | |
| 1887 | |
| 1888 void Textfield::OnCaretBoundsChanged() { | 1870 void Textfield::OnCaretBoundsChanged() { |
| 1889 if (GetInputMethod()) | 1871 if (GetInputMethod()) |
| 1890 GetInputMethod()->OnCaretBoundsChanged(this); | 1872 GetInputMethod()->OnCaretBoundsChanged(this); |
| 1891 if (touch_selection_controller_) | 1873 if (touch_selection_controller_) |
| 1892 touch_selection_controller_->SelectionChanged(); | 1874 touch_selection_controller_->SelectionChanged(); |
| 1893 } | 1875 } |
| 1894 | 1876 |
| 1895 void Textfield::OnBeforeUserAction() { | 1877 void Textfield::OnBeforeUserAction() { |
| 1896 DCHECK(!performing_user_action_); | 1878 DCHECK(!performing_user_action_); |
| 1897 performing_user_action_ = true; | 1879 performing_user_action_ = true; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1951 // IsCommandIdEnabled() as appropriate, for the commands added. | 1933 // IsCommandIdEnabled() as appropriate, for the commands added. |
| 1952 if (controller_) | 1934 if (controller_) |
| 1953 controller_->UpdateContextMenu(context_menu_contents_.get()); | 1935 controller_->UpdateContextMenu(context_menu_contents_.get()); |
| 1954 } | 1936 } |
| 1955 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), | 1937 context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get(), |
| 1956 MenuRunner::HAS_MNEMONICS | | 1938 MenuRunner::HAS_MNEMONICS | |
| 1957 MenuRunner::CONTEXT_MENU | | 1939 MenuRunner::CONTEXT_MENU | |
| 1958 MenuRunner::ASYNC)); | 1940 MenuRunner::ASYNC)); |
| 1959 } | 1941 } |
| 1960 | 1942 |
| 1961 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { | |
| 1962 if (event.IsOnlyLeftMouseButton()) { | |
| 1963 base::TimeDelta time_delta = event.time_stamp() - last_click_time_; | |
| 1964 if (!last_click_time_.is_null() && | |
| 1965 time_delta.InMilliseconds() <= GetDoubleClickInterval() && | |
| 1966 !ExceededDragThreshold(event.location() - last_click_location_)) { | |
| 1967 // Upon clicking after a triple click, the count should go back to double | |
| 1968 // click and alternate between double and triple. This assignment maps | |
| 1969 // 0 to 1, 1 to 2, 2 to 1. | |
| 1970 aggregated_clicks_ = (aggregated_clicks_ % 2) + 1; | |
| 1971 } else { | |
| 1972 aggregated_clicks_ = 0; | |
| 1973 } | |
| 1974 last_click_time_ = event.time_stamp(); | |
| 1975 last_click_location_ = event.location(); | |
| 1976 } | |
| 1977 } | |
| 1978 | |
| 1979 bool Textfield::ImeEditingAllowed() const { | 1943 bool Textfield::ImeEditingAllowed() const { |
| 1980 // Disallow input method editing of password fields. | 1944 // Disallow input method editing of password fields. |
| 1981 ui::TextInputType t = GetTextInputType(); | 1945 ui::TextInputType t = GetTextInputType(); |
| 1982 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); | 1946 return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD); |
| 1983 } | 1947 } |
| 1984 | 1948 |
| 1985 void Textfield::RevealPasswordChar(int index) { | 1949 void Textfield::RevealPasswordChar(int index) { |
| 1986 GetRenderText()->SetObscuredRevealIndex(index); | 1950 GetRenderText()->SetObscuredRevealIndex(index); |
| 1987 SchedulePaint(); | 1951 SchedulePaint(); |
| 1988 | 1952 |
| 1989 if (index != -1) { | 1953 if (index != -1) { |
| 1990 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), | 1954 password_reveal_timer_.Start(FROM_HERE, GetPasswordRevealDuration(), |
| 1991 base::Bind(&Textfield::RevealPasswordChar, | 1955 base::Bind(&Textfield::RevealPasswordChar, |
| 1992 weak_ptr_factory_.GetWeakPtr(), -1)); | 1956 weak_ptr_factory_.GetWeakPtr(), -1)); |
| 1993 } | 1957 } |
| 1994 } | 1958 } |
| 1995 | 1959 |
| 1996 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { | 1960 void Textfield::CreateTouchSelectionControllerAndNotifyIt() { |
| 1997 if (!HasFocus()) | 1961 if (!HasFocus()) |
| 1998 return; | 1962 return; |
| 1999 | 1963 |
| 2000 if (!touch_selection_controller_) { | 1964 if (!touch_selection_controller_) { |
| 2001 touch_selection_controller_.reset( | 1965 touch_selection_controller_.reset( |
| 2002 ui::TouchEditingControllerDeprecated::Create(this)); | 1966 ui::TouchEditingControllerDeprecated::Create(this)); |
| 2003 } | 1967 } |
| 2004 if (touch_selection_controller_) | 1968 if (touch_selection_controller_) |
| 2005 touch_selection_controller_->SelectionChanged(); | 1969 touch_selection_controller_->SelectionChanged(); |
| 2006 } | 1970 } |
| 2007 | 1971 |
| 2008 void Textfield::UpdateSelectionClipboard() const { | |
| 2009 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 2010 if (performing_user_action_ && HasSelection() && | |
| 2011 text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { | |
| 2012 ui::ScopedClipboardWriter( | |
| 2013 ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText()); | |
| 2014 if (controller_) | |
| 2015 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); | |
| 2016 } | |
| 2017 #endif | |
| 2018 } | |
| 2019 | |
| 2020 void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) { | |
| 2021 DCHECK(event.IsOnlyMiddleMouseButton()); | |
| 2022 DCHECK(!read_only()); | |
| 2023 base::string16 selection_clipboard_text = GetSelectionClipboardText(); | |
| 2024 OnBeforeUserAction(); | |
| 2025 const gfx::SelectionModel mouse = | |
| 2026 GetRenderText()->FindCursorPosition(event.location()); | |
| 2027 if (!HasFocus()) | |
| 2028 RequestFocus(); | |
| 2029 model_->MoveCursorTo(mouse); | |
| 2030 if (!selection_clipboard_text.empty()) { | |
| 2031 model_->InsertText(selection_clipboard_text); | |
| 2032 UpdateAfterChange(true, true); | |
| 2033 } | |
| 2034 OnAfterUserAction(); | |
| 2035 } | |
| 2036 | |
| 2037 void Textfield::OnKeypressUnhandled() { | 1972 void Textfield::OnKeypressUnhandled() { |
| 2038 PlatformStyle::OnTextfieldKeypressUnhandled(); | 1973 PlatformStyle::OnTextfieldKeypressUnhandled(); |
| 2039 } | 1974 } |
| 2040 | 1975 |
| 2041 bool Textfield::ShouldShowCursor() const { | 1976 bool Textfield::ShouldShowCursor() const { |
| 2042 return HasFocus() && !HasSelection() && enabled() && !read_only() && | 1977 return HasFocus() && !HasSelection() && enabled() && !read_only() && |
| 2043 !drop_cursor_visible_; | 1978 !drop_cursor_visible_; |
| 2044 } | 1979 } |
| 2045 | 1980 |
| 2046 bool Textfield::ShouldBlinkCursor() const { | 1981 bool Textfield::ShouldBlinkCursor() const { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2058 cursor_blink_timer_.Stop(); | 1993 cursor_blink_timer_.Stop(); |
| 2059 } | 1994 } |
| 2060 | 1995 |
| 2061 void Textfield::OnCursorBlinkTimerFired() { | 1996 void Textfield::OnCursorBlinkTimerFired() { |
| 2062 DCHECK(ShouldBlinkCursor()); | 1997 DCHECK(ShouldBlinkCursor()); |
| 2063 gfx::RenderText* render_text = GetRenderText(); | 1998 gfx::RenderText* render_text = GetRenderText(); |
| 2064 render_text->set_cursor_visible(!render_text->cursor_visible()); | 1999 render_text->set_cursor_visible(!render_text->cursor_visible()); |
| 2065 RepaintCursor(); | 2000 RepaintCursor(); |
| 2066 } | 2001 } |
| 2067 | 2002 |
| 2003 gfx::Point Textfield::last_click_location() const { | |
| 2004 return selection_controller_->last_click_location(); | |
| 2005 } | |
| 2006 | |
| 2068 } // namespace views | 2007 } // namespace views |
| OLD | NEW |