| 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 |