Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: ui/views/controls/textfield/textfield.cc

Issue 2322303002: Textfield: suppress cursor repaints when there's a selection (Closed)
Patch Set: remove spurious DCHECK Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 use_default_selection_background_color_(true), 248 use_default_selection_background_color_(true),
249 text_color_(SK_ColorBLACK), 249 text_color_(SK_ColorBLACK),
250 background_color_(SK_ColorWHITE), 250 background_color_(SK_ColorWHITE),
251 selection_text_color_(SK_ColorWHITE), 251 selection_text_color_(SK_ColorWHITE),
252 selection_background_color_(SK_ColorBLUE), 252 selection_background_color_(SK_ColorBLUE),
253 placeholder_text_color_(kDefaultPlaceholderTextColor), 253 placeholder_text_color_(kDefaultPlaceholderTextColor),
254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), 254 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
255 text_input_flags_(0), 255 text_input_flags_(0),
256 performing_user_action_(false), 256 performing_user_action_(false),
257 skip_input_method_cancel_composition_(false), 257 skip_input_method_cancel_composition_(false),
258 cursor_visible_(false),
259 drop_cursor_visible_(false), 258 drop_cursor_visible_(false),
260 initiating_drag_(false), 259 initiating_drag_(false),
261 aggregated_clicks_(0), 260 aggregated_clicks_(0),
262 drag_start_display_offset_(0), 261 drag_start_display_offset_(0),
263 touch_handles_hidden_due_to_scroll_(false), 262 touch_handles_hidden_due_to_scroll_(false),
264 weak_ptr_factory_(this) { 263 weak_ptr_factory_(this) {
265 set_context_menu_controller(this); 264 set_context_menu_controller(this);
266 set_drag_controller(this); 265 set_drag_controller(this);
267 GetRenderText()->SetFontList(GetDefaultFontList()); 266 GetRenderText()->SetFontList(GetDefaultFontList());
268 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); 267 SetBorder(std::unique_ptr<Border>(new FocusableBorder()));
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 gfx::RenderText* render_text = GetRenderText(); 847 gfx::RenderText* render_text = GetRenderText();
849 const gfx::Range& selection = render_text->selection(); 848 const gfx::Range& selection = render_text->selection();
850 drop_cursor_position_ = render_text->FindCursorPosition(event.location()); 849 drop_cursor_position_ = render_text->FindCursorPosition(event.location());
851 bool in_selection = !selection.is_empty() && 850 bool in_selection = !selection.is_empty() &&
852 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); 851 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
853 drop_cursor_visible_ = !in_selection; 852 drop_cursor_visible_ = !in_selection;
854 // TODO(msw): Pan over text when the user drags to the visible text edge. 853 // TODO(msw): Pan over text when the user drags to the visible text edge.
855 OnCaretBoundsChanged(); 854 OnCaretBoundsChanged();
856 SchedulePaint(); 855 SchedulePaint();
857 856
857 StopBlinkingCursor();
858
858 if (initiating_drag_) { 859 if (initiating_drag_) {
859 if (in_selection) 860 if (in_selection)
860 return ui::DragDropTypes::DRAG_NONE; 861 return ui::DragDropTypes::DRAG_NONE;
861 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY : 862 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
862 ui::DragDropTypes::DRAG_MOVE; 863 ui::DragDropTypes::DRAG_MOVE;
863 } 864 }
864 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE; 865 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
865 } 866 }
866 867
867 void Textfield::OnDragExited() { 868 void Textfield::OnDragExited() {
868 drop_cursor_visible_ = false; 869 drop_cursor_visible_ = false;
870 if (ShouldBlinkCursor())
871 StartBlinkingCursor();
869 SchedulePaint(); 872 SchedulePaint();
870 } 873 }
871 874
872 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) { 875 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) {
873 DCHECK(CanDrop(event.data())); 876 DCHECK(CanDrop(event.data()));
874 drop_cursor_visible_ = false; 877 drop_cursor_visible_ = false;
875 878
876 if (controller_) { 879 if (controller_) {
877 int drag_operation = controller_->OnDrop(event.data()); 880 int drag_operation = controller_->OnDrop(event.data());
878 if (drag_operation != ui::DragDropTypes::DRAG_NONE) 881 if (drag_operation != ui::DragDropTypes::DRAG_NONE)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 } 973 }
971 974
972 void Textfield::OnPaint(gfx::Canvas* canvas) { 975 void Textfield::OnPaint(gfx::Canvas* canvas) {
973 OnPaintBackground(canvas); 976 OnPaintBackground(canvas);
974 PaintTextAndCursor(canvas); 977 PaintTextAndCursor(canvas);
975 OnPaintBorder(canvas); 978 OnPaintBorder(canvas);
976 } 979 }
977 980
978 void Textfield::OnFocus() { 981 void Textfield::OnFocus() {
979 GetRenderText()->set_focused(true); 982 GetRenderText()->set_focused(true);
980 cursor_visible_ = true; 983 if (ShouldShowCursor())
984 GetRenderText()->set_cursor_visible(true);
981 SchedulePaint(); 985 SchedulePaint();
982 if (GetInputMethod()) 986 if (GetInputMethod())
983 GetInputMethod()->SetFocusedTextInputClient(this); 987 GetInputMethod()->SetFocusedTextInputClient(this);
984 OnCaretBoundsChanged(); 988 OnCaretBoundsChanged();
985 989 if (ShouldBlinkCursor())
986 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); 990 StartBlinkingCursor();
987 if (caret_blink_ms != 0) {
988 cursor_repaint_timer_.Start(FROM_HERE,
989 base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
990 &Textfield::UpdateCursor);
991 }
992
993 View::OnFocus(); 991 View::OnFocus();
994 SchedulePaint(); 992 SchedulePaint();
995 } 993 }
996 994
997 void Textfield::OnBlur() { 995 void Textfield::OnBlur() {
998 GetRenderText()->set_focused(false); 996 gfx::RenderText* render_text = GetRenderText();
997 render_text->set_focused(false);
999 if (GetInputMethod()) 998 if (GetInputMethod())
1000 GetInputMethod()->DetachTextInputClient(this); 999 GetInputMethod()->DetachTextInputClient(this);
1001 cursor_repaint_timer_.Stop(); 1000 StopBlinkingCursor();
1002 if (cursor_visible_) { 1001 if (render_text->cursor_visible()) {
1003 cursor_visible_ = false; 1002 render_text->set_cursor_visible(false);
1004 RepaintCursor(); 1003 RepaintCursor();
1005 } 1004 }
1006 1005
1007 DestroyTouchSelection(); 1006 DestroyTouchSelection();
1008 1007
1009 // Border typically draws focus indicator. 1008 // Border typically draws focus indicator.
1010 SchedulePaint(); 1009 SchedulePaint();
1011 } 1010 }
1012 1011
1013 gfx::Point Textfield::GetKeyboardContextMenuLocation() { 1012 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
1794 SchedulePaint(); 1793 SchedulePaint();
1795 } 1794 }
1796 1795
1797 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { 1796 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
1798 if (text_changed) { 1797 if (text_changed) {
1799 if (controller_) 1798 if (controller_)
1800 controller_->ContentsChanged(this, text()); 1799 controller_->ContentsChanged(this, text());
1801 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); 1800 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
1802 } 1801 }
1803 if (cursor_changed) { 1802 if (cursor_changed) {
1804 cursor_visible_ = true; 1803 GetRenderText()->set_cursor_visible(ShouldShowCursor());
1805 RepaintCursor(); 1804 RepaintCursor();
1806 if (cursor_repaint_timer_.IsRunning()) 1805 if (ShouldBlinkCursor())
1807 cursor_repaint_timer_.Reset(); 1806 StartBlinkingCursor();
1807 else
1808 StopBlinkingCursor();
1808 if (!text_changed) { 1809 if (!text_changed) {
1809 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire 1810 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire
1810 // this if only the selection changed. 1811 // this if only the selection changed.
1811 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); 1812 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true);
1812 } 1813 }
1813 } 1814 }
1814 if (text_changed || cursor_changed) { 1815 if (text_changed || cursor_changed) {
1815 OnCaretBoundsChanged(); 1816 OnCaretBoundsChanged();
1816 SchedulePaint(); 1817 SchedulePaint();
1817 } 1818 }
1818 } 1819 }
1819 1820
1820 void Textfield::UpdateCursor() {
1821 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
1822 cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0);
1823 RepaintCursor();
1824 }
1825
1826 void Textfield::RepaintCursor() { 1821 void Textfield::RepaintCursor() {
1827 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); 1822 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
1828 r.Inset(-1, -1, -1, -1); 1823 r.Inset(-1, -1, -1, -1);
1829 SchedulePaintInRect(r); 1824 SchedulePaintInRect(r);
1830 } 1825 }
1831 1826
1832 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { 1827 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
1833 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); 1828 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor");
1834 canvas->Save(); 1829 canvas->Save();
1835 1830
1836 // Draw placeholder text if needed. 1831 // Draw placeholder text if needed.
1837 gfx::RenderText* render_text = GetRenderText(); 1832 gfx::RenderText* render_text = GetRenderText();
1838 if (text().empty() && !GetPlaceholderText().empty()) { 1833 if (text().empty() && !GetPlaceholderText().empty()) {
1839 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), 1834 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(),
1840 ui::MaterialDesignController::IsSecondaryUiMaterial() 1835 ui::MaterialDesignController::IsSecondaryUiMaterial()
1841 ? SkColorSetA(GetTextColor(), 0x83) 1836 ? SkColorSetA(GetTextColor(), 0x83)
1842 : placeholder_text_color_, 1837 : placeholder_text_color_,
1843 render_text->display_rect()); 1838 render_text->display_rect());
1844 } 1839 }
1845 1840
1846 // Draw the text, cursor, and selection.
1847 render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ &&
1848 !HasSelection());
1849 render_text->Draw(canvas); 1841 render_text->Draw(canvas);
1850 1842
1851 // Draw the detached drop cursor that marks where the text will be dropped. 1843 // Draw the detached drop cursor that marks where the text will be dropped.
1852 if (drop_cursor_visible_) 1844 if (drop_cursor_visible_)
1853 render_text->DrawCursor(canvas, drop_cursor_position_); 1845 render_text->DrawCursor(canvas, drop_cursor_position_);
1854 1846
1855 canvas->Restore(); 1847 canvas->Restore();
1856 } 1848 }
1857 1849
1858 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { 1850 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
2039 model_->InsertText(selection_clipboard_text); 2031 model_->InsertText(selection_clipboard_text);
2040 UpdateAfterChange(true, true); 2032 UpdateAfterChange(true, true);
2041 } 2033 }
2042 OnAfterUserAction(); 2034 OnAfterUserAction();
2043 } 2035 }
2044 2036
2045 void Textfield::OnKeypressUnhandled() { 2037 void Textfield::OnKeypressUnhandled() {
2046 PlatformStyle::OnTextfieldKeypressUnhandled(); 2038 PlatformStyle::OnTextfieldKeypressUnhandled();
2047 } 2039 }
2048 2040
2041 bool Textfield::ShouldShowCursor() const {
2042 return HasFocus() && !HasSelection() && enabled() && !read_only() &&
2043 !drop_cursor_visible_;
2044 }
2045
2046 bool Textfield::ShouldBlinkCursor() const {
2047 return ShouldShowCursor() && Textfield::GetCaretBlinkMs() != 0;
2048 }
2049
2050 void Textfield::StartBlinkingCursor() {
2051 DCHECK(ShouldBlinkCursor());
2052 cursor_blink_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
2053 Textfield::GetCaretBlinkMs()),
2054 this, &Textfield::OnCursorBlinkTimerFired);
2055 }
2056
2057 void Textfield::StopBlinkingCursor() {
2058 cursor_blink_timer_.Stop();
2059 }
2060
2061 void Textfield::OnCursorBlinkTimerFired() {
2062 DCHECK(ShouldBlinkCursor());
2063 gfx::RenderText* render_text = GetRenderText();
2064 render_text->set_cursor_visible(!render_text->cursor_visible());
2065 RepaintCursor();
2066 }
2067
2049 } // namespace views 2068 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698