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), | |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |