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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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), | 258 editing_cursor_visible_(false), |
|
Peter Kasting
2016/09/16 18:52:27
I still don't really know what "editing cursor vis
| |
| 259 drop_cursor_visible_(false), | 259 drop_cursor_visible_(false), |
| 260 initiating_drag_(false), | 260 initiating_drag_(false), |
| 261 aggregated_clicks_(0), | 261 aggregated_clicks_(0), |
| 262 drag_start_display_offset_(0), | 262 drag_start_display_offset_(0), |
| 263 touch_handles_hidden_due_to_scroll_(false), | 263 touch_handles_hidden_due_to_scroll_(false), |
| 264 weak_ptr_factory_(this) { | 264 weak_ptr_factory_(this) { |
| 265 set_context_menu_controller(this); | 265 set_context_menu_controller(this); |
| 266 set_drag_controller(this); | 266 set_drag_controller(this); |
| 267 GetRenderText()->SetFontList(GetDefaultFontList()); | 267 GetRenderText()->SetFontList(GetDefaultFontList()); |
| 268 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); | 268 SetBorder(std::unique_ptr<Border>(new FocusableBorder())); |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 967 } | 967 } |
| 968 | 968 |
| 969 void Textfield::OnPaint(gfx::Canvas* canvas) { | 969 void Textfield::OnPaint(gfx::Canvas* canvas) { |
| 970 OnPaintBackground(canvas); | 970 OnPaintBackground(canvas); |
| 971 PaintTextAndCursor(canvas); | 971 PaintTextAndCursor(canvas); |
| 972 OnPaintBorder(canvas); | 972 OnPaintBorder(canvas); |
| 973 } | 973 } |
| 974 | 974 |
| 975 void Textfield::OnFocus() { | 975 void Textfield::OnFocus() { |
| 976 GetRenderText()->set_focused(true); | 976 GetRenderText()->set_focused(true); |
| 977 cursor_visible_ = true; | 977 editing_cursor_visible_ = true; |
|
Peter Kasting
2016/09/16 18:52:27
Why not make this mutually exclusive with HasSelec
| |
| 978 SchedulePaint(); | 978 SchedulePaint(); |
| 979 if (GetInputMethod()) | 979 if (GetInputMethod()) |
| 980 GetInputMethod()->SetFocusedTextInputClient(this); | 980 GetInputMethod()->SetFocusedTextInputClient(this); |
| 981 OnCaretBoundsChanged(); | 981 OnCaretBoundsChanged(); |
| 982 | 982 |
| 983 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); | 983 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); |
| 984 if (caret_blink_ms != 0) { | 984 if (caret_blink_ms != 0 && !HasSelection()) { |
| 985 cursor_repaint_timer_.Start(FROM_HERE, | 985 cursor_repaint_timer_.Start(FROM_HERE, |
| 986 base::TimeDelta::FromMilliseconds(caret_blink_ms), this, | 986 base::TimeDelta::FromMilliseconds(caret_blink_ms), this, |
| 987 &Textfield::UpdateCursor); | 987 &Textfield::UpdateCursor); |
| 988 } | 988 } |
| 989 | 989 |
| 990 View::OnFocus(); | 990 View::OnFocus(); |
| 991 SchedulePaint(); | 991 SchedulePaint(); |
| 992 } | 992 } |
| 993 | 993 |
| 994 void Textfield::OnBlur() { | 994 void Textfield::OnBlur() { |
| 995 GetRenderText()->set_focused(false); | 995 GetRenderText()->set_focused(false); |
| 996 if (GetInputMethod()) | 996 if (GetInputMethod()) |
| 997 GetInputMethod()->DetachTextInputClient(this); | 997 GetInputMethod()->DetachTextInputClient(this); |
| 998 cursor_repaint_timer_.Stop(); | 998 cursor_repaint_timer_.Stop(); |
| 999 if (cursor_visible_) { | 999 if (editing_cursor_visible_) { |
| 1000 cursor_visible_ = false; | 1000 editing_cursor_visible_ = false; |
| 1001 RepaintCursor(); | 1001 RepaintCursor(); |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 DestroyTouchSelection(); | 1004 DestroyTouchSelection(); |
| 1005 | 1005 |
| 1006 // Border typically draws focus indicator. | 1006 // Border typically draws focus indicator. |
| 1007 SchedulePaint(); | 1007 SchedulePaint(); |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 gfx::Point Textfield::GetKeyboardContextMenuLocation() { | 1010 gfx::Point Textfield::GetKeyboardContextMenuLocation() { |
| (...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1780 } | 1780 } |
| 1781 // Disable subpixel rendering when the background color is transparent | 1781 // Disable subpixel rendering when the background color is transparent |
| 1782 // because it draws incorrect colors around the glyphs in that case. | 1782 // because it draws incorrect colors around the glyphs in that case. |
| 1783 // See crbug.com/115198 | 1783 // See crbug.com/115198 |
| 1784 GetRenderText()->set_subpixel_rendering_suppressed( | 1784 GetRenderText()->set_subpixel_rendering_suppressed( |
| 1785 SkColorGetA(color) != SK_AlphaOPAQUE); | 1785 SkColorGetA(color) != SK_AlphaOPAQUE); |
| 1786 SchedulePaint(); | 1786 SchedulePaint(); |
| 1787 } | 1787 } |
| 1788 | 1788 |
| 1789 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { | 1789 void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) { |
| 1790 DCHECK(HasFocus()); | |
| 1790 if (text_changed) { | 1791 if (text_changed) { |
| 1791 if (controller_) | 1792 if (controller_) |
| 1792 controller_->ContentsChanged(this, text()); | 1793 controller_->ContentsChanged(this, text()); |
| 1793 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); | 1794 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true); |
| 1794 } | 1795 } |
| 1795 if (cursor_changed) { | 1796 if (cursor_changed) { |
| 1796 cursor_visible_ = true; | 1797 editing_cursor_visible_ = false; |
| 1797 RepaintCursor(); | 1798 RepaintCursor(); |
|
Peter Kasting
2016/09/16 18:52:27
Nit: Since RepaintCursor() merely schedules a pain
| |
| 1798 if (cursor_repaint_timer_.IsRunning()) | 1799 |
| 1800 // If this textfield is not focused, the timer must have been stopped in | |
| 1801 // |Textfield::OnBlur|, and this method needs to avoid accidentally | |
| 1802 // restarting it. | |
| 1803 if (!HasFocus()) | |
| 1804 DCHECK(!cursor_repaint_timer_.IsRunning()); | |
|
Peter Kasting
2016/09/16 18:52:27
Nit: Just:
DCHECK(HasFocus() || !cursor_repai
| |
| 1805 | |
| 1806 // Cursor repaints are suppressed whenever there is a selection or this view | |
| 1807 // does not have focus. When the selection changes, the cursor moves, or | |
| 1808 // this view gains/loses focus, this method will get called with | |
| 1809 // |cursor_changed| set to true, and the timer will be restarted here. | |
| 1810 if (HasSelection()) { | |
|
Peter Kasting
2016/09/16 18:52:27
Nit: Inspired by my suggestion above to move the R
| |
| 1811 cursor_repaint_timer_.Stop(); | |
| 1812 } else if (HasFocus() && enabled() && !read_only()) { | |
| 1813 editing_cursor_visible_ = true; | |
| 1799 cursor_repaint_timer_.Reset(); | 1814 cursor_repaint_timer_.Reset(); |
| 1815 } | |
| 1816 | |
| 1800 if (!text_changed) { | 1817 if (!text_changed) { |
| 1801 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire | 1818 // TEXT_CHANGED implies TEXT_SELECTION_CHANGED, so we only need to fire |
| 1802 // this if only the selection changed. | 1819 // this if only the selection changed. |
| 1803 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); | 1820 NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_SELECTION_CHANGED, true); |
| 1804 } | 1821 } |
| 1805 } | 1822 } |
| 1806 if (text_changed || cursor_changed) { | 1823 if (text_changed || cursor_changed) { |
| 1807 OnCaretBoundsChanged(); | 1824 OnCaretBoundsChanged(); |
| 1808 SchedulePaint(); | 1825 SchedulePaint(); |
| 1809 } | 1826 } |
| 1810 } | 1827 } |
| 1811 | 1828 |
| 1812 void Textfield::UpdateCursor() { | 1829 void Textfield::UpdateCursor() { |
| 1813 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); | 1830 const size_t caret_blink_ms = Textfield::GetCaretBlinkMs(); |
| 1814 cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0); | 1831 editing_cursor_visible_ = !editing_cursor_visible_ || (caret_blink_ms == 0); |
| 1815 RepaintCursor(); | 1832 RepaintCursor(); |
| 1816 } | 1833 } |
| 1817 | 1834 |
| 1818 void Textfield::RepaintCursor() { | 1835 void Textfield::RepaintCursor() { |
| 1819 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); | 1836 gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds()); |
| 1820 r.Inset(-1, -1, -1, -1); | 1837 r.Inset(-1, -1, -1, -1); |
| 1821 SchedulePaintInRect(r); | 1838 SchedulePaintInRect(r); |
| 1822 } | 1839 } |
| 1823 | 1840 |
| 1824 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { | 1841 void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) { |
| 1825 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); | 1842 TRACE_EVENT0("views", "Textfield::PaintTextAndCursor"); |
| 1826 canvas->Save(); | 1843 canvas->Save(); |
| 1827 | 1844 |
| 1828 // Draw placeholder text if needed. | 1845 // Draw placeholder text if needed. |
| 1829 gfx::RenderText* render_text = GetRenderText(); | 1846 gfx::RenderText* render_text = GetRenderText(); |
| 1830 if (text().empty() && !GetPlaceholderText().empty()) { | 1847 if (text().empty() && !GetPlaceholderText().empty()) { |
| 1831 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), | 1848 canvas->DrawStringRect(GetPlaceholderText(), GetFontList(), |
| 1832 ui::MaterialDesignController::IsSecondaryUiMaterial() | 1849 ui::MaterialDesignController::IsSecondaryUiMaterial() |
| 1833 ? SkColorSetA(GetTextColor(), 0x83) | 1850 ? SkColorSetA(GetTextColor(), 0x83) |
| 1834 : placeholder_text_color_, | 1851 : placeholder_text_color_, |
| 1835 render_text->display_rect()); | 1852 render_text->display_rect()); |
| 1836 } | 1853 } |
| 1837 | 1854 |
| 1838 // Draw the text, cursor, and selection. | 1855 // Draw the text, cursor, and selection. |
| 1839 render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ && | 1856 render_text->set_cursor_visible(editing_cursor_visible_ && |
| 1857 !drop_cursor_visible_ && | |
| 1840 !HasSelection()); | 1858 !HasSelection()); |
| 1841 render_text->Draw(canvas); | 1859 render_text->Draw(canvas); |
| 1842 | 1860 |
| 1843 // Draw the detached drop cursor that marks where the text will be dropped. | 1861 // Draw the detached drop cursor that marks where the text will be dropped. |
| 1844 if (drop_cursor_visible_) | 1862 if (drop_cursor_visible_) |
| 1845 render_text->DrawCursor(canvas, drop_cursor_position_); | 1863 render_text->DrawCursor(canvas, drop_cursor_position_); |
| 1846 | 1864 |
| 1847 canvas->Restore(); | 1865 canvas->Restore(); |
| 1848 } | 1866 } |
| 1849 | 1867 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2027 RequestFocus(); | 2045 RequestFocus(); |
| 2028 model_->MoveCursorTo(mouse); | 2046 model_->MoveCursorTo(mouse); |
| 2029 if (!selection_clipboard_text.empty()) { | 2047 if (!selection_clipboard_text.empty()) { |
| 2030 model_->InsertText(selection_clipboard_text); | 2048 model_->InsertText(selection_clipboard_text); |
| 2031 UpdateAfterChange(true, true); | 2049 UpdateAfterChange(true, true); |
| 2032 } | 2050 } |
| 2033 OnAfterUserAction(); | 2051 OnAfterUserAction(); |
| 2034 } | 2052 } |
| 2035 | 2053 |
| 2036 } // namespace views | 2054 } // namespace views |
| OLD | NEW |