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

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

Issue 2322303002: Textfield: suppress cursor repaints when there's a selection (Closed)
Patch Set: refactor all the stuff Created 4 years, 3 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
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 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 gfx::RenderText* render_text = GetRenderText(); 844 gfx::RenderText* render_text = GetRenderText();
846 const gfx::Range& selection = render_text->selection(); 845 const gfx::Range& selection = render_text->selection();
847 drop_cursor_position_ = render_text->FindCursorPosition(event.location()); 846 drop_cursor_position_ = render_text->FindCursorPosition(event.location());
848 bool in_selection = !selection.is_empty() && 847 bool in_selection = !selection.is_empty() &&
849 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos())); 848 selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
850 drop_cursor_visible_ = !in_selection; 849 drop_cursor_visible_ = !in_selection;
851 // TODO(msw): Pan over text when the user drags to the visible text edge. 850 // TODO(msw): Pan over text when the user drags to the visible text edge.
852 OnCaretBoundsChanged(); 851 OnCaretBoundsChanged();
853 SchedulePaint(); 852 SchedulePaint();
854 853
854 StopBlinkingCursor();
855
855 if (initiating_drag_) { 856 if (initiating_drag_) {
856 if (in_selection) 857 if (in_selection)
857 return ui::DragDropTypes::DRAG_NONE; 858 return ui::DragDropTypes::DRAG_NONE;
858 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY : 859 return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
859 ui::DragDropTypes::DRAG_MOVE; 860 ui::DragDropTypes::DRAG_MOVE;
860 } 861 }
861 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE; 862 return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
862 } 863 }
863 864
864 void Textfield::OnDragExited() { 865 void Textfield::OnDragExited() {
865 drop_cursor_visible_ = false; 866 drop_cursor_visible_ = false;
867 if (ShouldBlinkCursor())
868 StartBlinkingCursor();
866 SchedulePaint(); 869 SchedulePaint();
867 } 870 }
868 871
869 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) { 872 int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) {
870 DCHECK(CanDrop(event.data())); 873 DCHECK(CanDrop(event.data()));
871 drop_cursor_visible_ = false; 874 drop_cursor_visible_ = false;
872 875
873 if (controller_) { 876 if (controller_) {
874 int drag_operation = controller_->OnDrop(event.data()); 877 int drag_operation = controller_->OnDrop(event.data());
875 if (drag_operation != ui::DragDropTypes::DRAG_NONE) 878 if (drag_operation != ui::DragDropTypes::DRAG_NONE)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 } 970 }
968 971
969 void Textfield::OnPaint(gfx::Canvas* canvas) { 972 void Textfield::OnPaint(gfx::Canvas* canvas) {
970 OnPaintBackground(canvas); 973 OnPaintBackground(canvas);
971 PaintTextAndCursor(canvas); 974 PaintTextAndCursor(canvas);
972 OnPaintBorder(canvas); 975 OnPaintBorder(canvas);
973 } 976 }
974 977
975 void Textfield::OnFocus() { 978 void Textfield::OnFocus() {
976 GetRenderText()->set_focused(true); 979 GetRenderText()->set_focused(true);
977 cursor_visible_ = true; 980 if (ShouldShowCursor())
981 GetRenderText()->set_cursor_visible(true);
978 SchedulePaint(); 982 SchedulePaint();
979 if (GetInputMethod()) 983 if (GetInputMethod())
980 GetInputMethod()->SetFocusedTextInputClient(this); 984 GetInputMethod()->SetFocusedTextInputClient(this);
981 OnCaretBoundsChanged(); 985 OnCaretBoundsChanged();
982 986 if (ShouldBlinkCursor())
983 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); 987 StartBlinkingCursor();
984 if (caret_blink_ms != 0) {
985 cursor_repaint_timer_.Start(FROM_HERE,
986 base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
987 &Textfield::UpdateCursor);
988 }
989
990 View::OnFocus(); 988 View::OnFocus();
991 SchedulePaint(); 989 SchedulePaint();
992 } 990 }
993 991
994 void Textfield::OnBlur() { 992 void Textfield::OnBlur() {
995 GetRenderText()->set_focused(false); 993 gfx::RenderText* render_text = GetRenderText();
994 render_text->set_focused(false);
996 if (GetInputMethod()) 995 if (GetInputMethod())
997 GetInputMethod()->DetachTextInputClient(this); 996 GetInputMethod()->DetachTextInputClient(this);
998 cursor_repaint_timer_.Stop(); 997 StopBlinkingCursor();
999 if (cursor_visible_) { 998 if (render_text->cursor_visible()) {
1000 cursor_visible_ = false; 999 render_text->set_cursor_visible(false);
1001 RepaintCursor(); 1000 RepaintCursor();
1002 } 1001 }
1003 1002
1004 DestroyTouchSelection(); 1003 DestroyTouchSelection();
1005 1004
1006 // Border typically draws focus indicator. 1005 // Border typically draws focus indicator.
1007 SchedulePaint(); 1006 SchedulePaint();
1008 } 1007 }
1009 1008
1010 gfx::Point Textfield::GetKeyboardContextMenuLocation() { 1009 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 } 1779 }
1781 // Disable subpixel rendering when the background color is transparent 1780 // Disable subpixel rendering when the background color is transparent
1782 // because it draws incorrect colors around the glyphs in that case. 1781 // because it draws incorrect colors around the glyphs in that case.
1783 // See crbug.com/115198 1782 // See crbug.com/115198
1784 GetRenderText()->set_subpixel_rendering_suppressed( 1783 GetRenderText()->set_subpixel_rendering_suppressed(
1785 SkColorGetA(color) != SK_AlphaOPAQUE); 1784 SkColorGetA(color) != SK_AlphaOPAQUE);
1786 SchedulePaint(); 1785 SchedulePaint();
1787 } 1786 }
1788 1787
1789 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { 1788 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
1789 DCHECK(HasFocus());
1790 if (text_changed) { 1790 if (text_changed) {
1791 if (controller_) 1791 if (controller_)
1792 controller_->ContentsChanged(this, text()); 1792 controller_->ContentsChanged(this, text());
1793 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); 1793 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
1794 } 1794 }
1795 if (cursor_changed) { 1795 if (cursor_changed) {
1796 cursor_visible_ = true; 1796 GetRenderText()->set_cursor_visible(ShouldShowCursor());
1797 RepaintCursor(); 1797 RepaintCursor();
1798 if (cursor_repaint_timer_.IsRunning()) 1798 if (ShouldBlinkCursor())
1799 cursor_repaint_timer_.Reset(); 1799 StartBlinkingCursor();
1800 else
1801 StopBlinkingCursor();
1800 if (!text_changed) { 1802 if (!text_changed) {
1801 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire 1803 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire
1802 // this if only the selection changed. 1804 // this if only the selection changed.
1803 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); 1805 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true);
1804 } 1806 }
1805 } 1807 }
1806 if (text_changed || cursor_changed) { 1808 if (text_changed || cursor_changed) {
1807 OnCaretBoundsChanged(); 1809 OnCaretBoundsChanged();
1808 SchedulePaint(); 1810 SchedulePaint();
1809 } 1811 }
1810 } 1812 }
1811 1813
1812 void Textfield::UpdateCursor() {
1813 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
1814 cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0);
1815 RepaintCursor();
1816 }
1817
1818 void Textfield::RepaintCursor() { 1814 void Textfield::RepaintCursor() {
1819 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); 1815 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
1820 r.Inset(-1, -1, -1, -1); 1816 r.Inset(-1, -1, -1, -1);
1821 SchedulePaintInRect(r); 1817 SchedulePaintInRect(r);
1822 } 1818 }
1823 1819
1824 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { 1820 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
1825 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); 1821 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor");
1826 canvas->Save(); 1822 canvas->Save();
1827 1823
1828 // Draw placeholder text if needed. 1824 // Draw placeholder text if needed.
1829 gfx::RenderText* render_text = GetRenderText(); 1825 gfx::RenderText* render_text = GetRenderText();
1830 if (text().empty() && !GetPlaceholderText().empty()) { 1826 if (text().empty() && !GetPlaceholderText().empty()) {
1831 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), 1827 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(),
1832 ui::MaterialDesignController::IsSecondaryUiMaterial() 1828 ui::MaterialDesignController::IsSecondaryUiMaterial()
1833 ? SkColorSetA(GetTextColor(), 0x83) 1829 ? SkColorSetA(GetTextColor(), 0x83)
1834 : placeholder_text_color_, 1830 : placeholder_text_color_,
1835 render_text->display_rect()); 1831 render_text->display_rect());
1836 } 1832 }
1837 1833
1838 // Draw the text, cursor, and selection.
1839 render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ &&
1840 !HasSelection());
1841 render_text->Draw(canvas); 1834 render_text->Draw(canvas);
1842 1835
1843 // Draw the detached drop cursor that marks where the text will be dropped. 1836 // Draw the detached drop cursor that marks where the text will be dropped.
1844 if (drop_cursor_visible_) 1837 if (drop_cursor_visible_)
1845 render_text->DrawCursor(canvas, drop_cursor_position_); 1838 render_text->DrawCursor(canvas, drop_cursor_position_);
1846 1839
1847 canvas->Restore(); 1840 canvas->Restore();
1848 } 1841 }
1849 1842
1850 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) { 1843 void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2026 if (!HasFocus()) 2019 if (!HasFocus())
2027 RequestFocus(); 2020 RequestFocus();
2028 model_->MoveCursorTo(mouse); 2021 model_->MoveCursorTo(mouse);
2029 if (!selection_clipboard_text.empty()) { 2022 if (!selection_clipboard_text.empty()) {
2030 model_->InsertText(selection_clipboard_text); 2023 model_->InsertText(selection_clipboard_text);
2031 UpdateAfterChange(true, true); 2024 UpdateAfterChange(true, true);
2032 } 2025 }
2033 OnAfterUserAction(); 2026 OnAfterUserAction();
2034 } 2027 }
2035 2028
2029 bool Textfield::ShouldShowCursor() const {
2030 return HasFocus() && !HasSelection() && enabled() && !read_only() &&
2031 !drop_cursor_visible_;
2032 }
2033
2034 bool Textfield::ShouldBlinkCursor() const {
2035 return ShouldShowCursor() && Textfield::GetCaretBlinkMs() != 0;
2036 }
2037
2038 void Textfield::StartBlinkingCursor() {
2039 DCHECK(ShouldBlinkCursor());
2040 cursor_blink_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(
2041 Textfield::GetCaretBlinkMs()),
2042 this, &Textfield::BlinkCursor);
2043 }
2044
2045 void Textfield::StopBlinkingCursor() {
2046 cursor_blink_timer_.Stop();
2047 }
2048
2049 void Textfield::BlinkCursor() {
2050 DCHECK(ShouldBlinkCursor());
2051 gfx::RenderText* render_text = GetRenderText();
2052 render_text->set_cursor_visible(!render_text->cursor_visible());
2053 RepaintCursor();
2054 }
2055
2036 } // namespace views 2056 } // namespace views
OLDNEW
« ui/views/controls/textfield/textfield.h ('K') | « ui/views/controls/textfield/textfield.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698