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

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

Issue 2345183002: Views: Draw Textfield selected text in gray when top-level Widget loses focus.
Patch Set: Fix DCHECKs. Created 4 years, 1 month 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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 read_only_(false), 231 read_only_(false),
232 default_width_in_chars_(0), 232 default_width_in_chars_(0),
233 use_default_text_color_(true), 233 use_default_text_color_(true),
234 use_default_background_color_(true), 234 use_default_background_color_(true),
235 use_default_selection_text_color_(true), 235 use_default_selection_text_color_(true),
236 use_default_selection_background_color_(true), 236 use_default_selection_background_color_(true),
237 text_color_(SK_ColorBLACK), 237 text_color_(SK_ColorBLACK),
238 background_color_(SK_ColorWHITE), 238 background_color_(SK_ColorWHITE),
239 selection_text_color_(SK_ColorWHITE), 239 selection_text_color_(SK_ColorWHITE),
240 selection_background_color_(SK_ColorBLUE), 240 selection_background_color_(SK_ColorBLUE),
241 focus_manager_(nullptr),
241 placeholder_text_color_(kDefaultPlaceholderTextColor), 242 placeholder_text_color_(kDefaultPlaceholderTextColor),
242 invalid_(false), 243 invalid_(false),
243 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), 244 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
244 text_input_flags_(0), 245 text_input_flags_(0),
245 performing_user_action_(false), 246 performing_user_action_(false),
246 skip_input_method_cancel_composition_(false), 247 skip_input_method_cancel_composition_(false),
247 drop_cursor_visible_(false), 248 drop_cursor_visible_(false),
248 initiating_drag_(false), 249 initiating_drag_(false),
249 selection_controller_(this), 250 selection_controller_(this),
250 drag_start_display_offset_(0), 251 drag_start_display_offset_(0),
(...skipping 17 matching lines...) Expand all
268 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN)); 269 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN));
269 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN)); 270 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN));
270 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN)); 271 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN));
271 } 272 }
272 273
273 Textfield::~Textfield() { 274 Textfield::~Textfield() {
274 if (GetInputMethod()) { 275 if (GetInputMethod()) {
275 // The textfield should have been blurred before destroy. 276 // The textfield should have been blurred before destroy.
276 DCHECK(this != GetInputMethod()->GetTextInputClient()); 277 DCHECK(this != GetInputMethod()->GetTextInputClient());
277 } 278 }
279 DCHECK(!focus_manager_);
278 } 280 }
279 281
280 void Textfield::SetReadOnly(bool read_only) { 282 void Textfield::SetReadOnly(bool read_only) {
281 // Update read-only without changing the focusable state (or active, etc.). 283 // Update read-only without changing the focusable state (or active, etc.).
282 read_only_ = read_only; 284 read_only_ = read_only;
283 if (GetInputMethod()) 285 if (GetInputMethod())
284 GetInputMethod()->OnTextInputTypeChanged(this); 286 GetInputMethod()->OnTextInputTypeChanged(this);
285 SetColor(GetTextColor()); 287 SetColor(GetTextColor());
286 UpdateBackgroundColor(); 288 UpdateBackgroundColor();
287 } 289 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 SkColor Textfield::GetSelectionBackgroundColor() const { 417 SkColor Textfield::GetSelectionBackgroundColor() const {
416 return use_default_selection_background_color_ ? 418 return use_default_selection_background_color_ ?
417 GetNativeTheme()->GetSystemColor( 419 GetNativeTheme()->GetSystemColor(
418 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) : 420 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) :
419 selection_background_color_; 421 selection_background_color_;
420 } 422 }
421 423
422 void Textfield::SetSelectionBackgroundColor(SkColor color) { 424 void Textfield::SetSelectionBackgroundColor(SkColor color) {
423 selection_background_color_ = color; 425 selection_background_color_ = color;
424 use_default_selection_background_color_ = false; 426 use_default_selection_background_color_ = false;
425 GetRenderText()->set_selection_background_focused_color( 427 GetRenderText()->set_selection_background_color(
426 GetSelectionBackgroundColor()); 428 GetSelectionBackgroundColor());
427 SchedulePaint(); 429 SchedulePaint();
428 } 430 }
429 431
430 void Textfield::UseDefaultSelectionBackgroundColor() { 432 void Textfield::UseDefaultSelectionBackgroundColor() {
431 use_default_selection_background_color_ = true; 433 use_default_selection_background_color_ = true;
432 GetRenderText()->set_selection_background_focused_color( 434 GetRenderText()->set_selection_background_color(
433 GetSelectionBackgroundColor()); 435 GetSelectionBackgroundColor());
434 SchedulePaint(); 436 SchedulePaint();
435 } 437 }
436 438
439 SkColor Textfield::GetUnfocusedSelectionBackgroundColor() const {
440 return GetNativeTheme()->GetSystemColor(
441 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundUnfocused);
442 }
443
437 bool Textfield::GetCursorEnabled() const { 444 bool Textfield::GetCursorEnabled() const {
438 return GetRenderText()->cursor_enabled(); 445 return GetRenderText()->cursor_enabled();
439 } 446 }
440 447
441 void Textfield::SetCursorEnabled(bool enabled) { 448 void Textfield::SetCursorEnabled(bool enabled) {
442 GetRenderText()->SetCursorEnabled(enabled); 449 GetRenderText()->SetCursorEnabled(enabled);
443 } 450 }
444 451
445 const gfx::FontList& Textfield::GetFontList() const { 452 const gfx::FontList& Textfield::GetFontList() const {
446 return GetRenderText()->font_list(); 453 return GetRenderText()->font_list();
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
920 touch_selection_controller_->SelectionChanged(); 927 touch_selection_controller_->SelectionChanged();
921 } 928 }
922 929
923 void Textfield::OnEnabledChanged() { 930 void Textfield::OnEnabledChanged() {
924 View::OnEnabledChanged(); 931 View::OnEnabledChanged();
925 if (GetInputMethod()) 932 if (GetInputMethod())
926 GetInputMethod()->OnTextInputTypeChanged(this); 933 GetInputMethod()->OnTextInputTypeChanged(this);
927 SchedulePaint(); 934 SchedulePaint();
928 } 935 }
929 936
937 void Textfield::ViewHierarchyChanged(
938 const ViewHierarchyChangedDetails& details) {
939 // Textfields only care about focus changes if the entire Widget has lost
940 // focus, so don't bother listening if there is no Widget.
941 if (!GetWidget())
tapted 2016/11/02 03:59:14 actually I think this `if` can be omitted. -- we c
Patti Lor 2016/11/07 05:34:26 Done.
tapted 2016/11/07 06:14:50 ping? (this should be redundant with the changes i
Patti Lor 2016/11/08 01:47:31 Oops, thank you - forgot to reapply the latest pat
942 return;
943
944 if (details.parent->Contains(this) && details.move_view == nullptr)
945 AddOrRemoveAsFocusChangeListener(details.is_add);
946 }
947
948 void Textfield::NativeViewHierarchyChanged() {
949 if (!GetWidget()) {
tapted 2016/11/02 03:59:14 same here. In fact I think we can just make this e
Patti Lor 2016/11/07 05:34:26 Done.
950 focus_manager_ = nullptr;
951 return;
952 }
953
954 // Update the focus manager if it's changed.
955 if (focus_manager_ != GetFocusManager()) {
956 AddOrRemoveAsFocusChangeListener(false);
957 AddOrRemoveAsFocusChangeListener(true);
tapted 2016/11/02 03:45:06 I think calling with `true` should always behave a
Patti Lor 2016/11/07 05:34:26 Done.
958 }
959 }
960
930 void Textfield::OnPaint(gfx::Canvas* canvas) { 961 void Textfield::OnPaint(gfx::Canvas* canvas) {
931 OnPaintBackground(canvas); 962 OnPaintBackground(canvas);
932 PaintTextAndCursor(canvas); 963 PaintTextAndCursor(canvas);
933 OnPaintBorder(canvas); 964 OnPaintBorder(canvas);
934 } 965 }
935 966
936 void Textfield::OnFocus() { 967 void Textfield::OnFocus() {
937 GetRenderText()->set_focused(true); 968 GetRenderText()->set_focused(true);
938 if (ShouldShowCursor()) 969 if (ShouldShowCursor())
939 GetRenderText()->set_cursor_visible(true); 970 GetRenderText()->set_cursor_visible(true);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 gfx::Point Textfield::GetKeyboardContextMenuLocation() { 1004 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
974 return GetCaretBounds().bottom_right(); 1005 return GetCaretBounds().bottom_right();
975 } 1006 }
976 1007
977 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) { 1008 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
978 gfx::RenderText* render_text = GetRenderText(); 1009 gfx::RenderText* render_text = GetRenderText();
979 render_text->SetColor(GetTextColor()); 1010 render_text->SetColor(GetTextColor());
980 UpdateBackgroundColor(); 1011 UpdateBackgroundColor();
981 render_text->set_cursor_color(GetTextColor()); 1012 render_text->set_cursor_color(GetTextColor());
982 render_text->set_selection_color(GetSelectionTextColor()); 1013 render_text->set_selection_color(GetSelectionTextColor());
983 render_text->set_selection_background_focused_color( 1014 if (HasFocus()) {
984 GetSelectionBackgroundColor()); 1015 render_text->set_selection_background_color(GetSelectionBackgroundColor());
1016 } else {
1017 render_text->set_selection_background_color(
1018 GetUnfocusedSelectionBackgroundColor());
1019 }
985 } 1020 }
986 1021
987 //////////////////////////////////////////////////////////////////////////////// 1022 ////////////////////////////////////////////////////////////////////////////////
988 // Textfield, TextfieldModel::Delegate overrides: 1023 // Textfield, TextfieldModel::Delegate overrides:
989 1024
990 void Textfield::OnCompositionTextConfirmedOrCleared() { 1025 void Textfield::OnCompositionTextConfirmedOrCleared() {
991 if (!skip_input_method_cancel_composition_) 1026 if (!skip_input_method_cancel_composition_)
992 GetInputMethod()->CancelComposition(this); 1027 GetInputMethod()->CancelComposition(this);
993 } 1028 }
994 1029
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 return drag_operations; 1086 return drag_operations;
1052 } 1087 }
1053 1088
1054 bool Textfield::CanStartDragForView(View* sender, 1089 bool Textfield::CanStartDragForView(View* sender,
1055 const gfx::Point& press_pt, 1090 const gfx::Point& press_pt,
1056 const gfx::Point& p) { 1091 const gfx::Point& p) {
1057 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); 1092 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
1058 } 1093 }
1059 1094
1060 //////////////////////////////////////////////////////////////////////////////// 1095 ////////////////////////////////////////////////////////////////////////////////
1096 // Textfield, FocusChangeListener overrides:
1097
1098 void Textfield::OnWillChangeFocus(View* focus_before, View* focus_after) {
1099 if (focus_before != this && focus_after != this)
1100 return;
1101
1102 SkColor selection_bg_color = focus_after
1103 ? GetSelectionBackgroundColor()
1104 : GetUnfocusedSelectionBackgroundColor();
1105
1106 // Selection is drawn if |this| has focus, or the Widget loses activation, but
1107 // not if another View in this Widget is gaining focus.
1108 GetRenderText()->set_draw_text_selection(focus_after == this || !focus_after);
1109 GetRenderText()->set_selection_background_color(selection_bg_color);
1110 }
1111
1112 void Textfield::OnDidChangeFocus(View* focused_before, View* focused_now) {}
1113
1114 ////////////////////////////////////////////////////////////////////////////////
1061 // Textfield, WordLookupClient overrides: 1115 // Textfield, WordLookupClient overrides:
1062 1116
1063 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, 1117 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point,
1064 gfx::DecoratedText* decorated_word, 1118 gfx::DecoratedText* decorated_word,
1065 gfx::Point* baseline_point) { 1119 gfx::Point* baseline_point) {
1066 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, 1120 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word,
1067 baseline_point); 1121 baseline_point);
1068 } 1122 }
1069 1123
1070 //////////////////////////////////////////////////////////////////////////////// 1124 ////////////////////////////////////////////////////////////////////////////////
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 1871 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1818 if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) { 1872 if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
1819 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION) 1873 ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION)
1820 .WriteText(GetSelectedText()); 1874 .WriteText(GetSelectedText());
1821 if (controller_) 1875 if (controller_)
1822 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION); 1876 controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
1823 } 1877 }
1824 #endif 1878 #endif
1825 } 1879 }
1826 1880
1881 void Textfield::AddOrRemoveAsFocusChangeListener(bool add_as_listener) {
1882 if (add_as_listener) {
1883 FocusManager* focus_manager = GetFocusManager();
1884 if (!focus_manager)
1885 return;
tapted 2016/11/02 03:45:06 Comment when this can occur?
tapted 2016/11/02 03:59:14 (btw, I'm guessing this can occur only when Widget
Patti Lor 2016/11/07 05:34:26 Yeah, this happens when there's a TYPE_CONTROL Wid
1886 focus_manager_ = focus_manager;
1887 focus_manager_->AddFocusChangeListener(this);
1888 } else if (focus_manager_) {
tapted 2016/11/02 03:45:06 I think this block can just go at the start of the
Patti Lor 2016/11/07 05:34:26 Done.
1889 focus_manager_->RemoveFocusChangeListener(this);
1890 focus_manager_ = nullptr;
1891 }
1892 }
1893
1827 void Textfield::AccessibilitySetValue(const base::string16& new_value, 1894 void Textfield::AccessibilitySetValue(const base::string16& new_value,
1828 bool clear_first) { 1895 bool clear_first) {
1829 if (read_only()) 1896 if (read_only())
1830 return; 1897 return;
1831 if (!clear_first) 1898 if (!clear_first)
1832 InsertOrReplaceText(new_value); 1899 InsertOrReplaceText(new_value);
1833 else 1900 else
1834 SetText(new_value); 1901 SetText(new_value);
1835 ClearSelection(); 1902 ClearSelection();
1836 } 1903 }
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 } 2112 }
2046 2113
2047 void Textfield::OnCursorBlinkTimerFired() { 2114 void Textfield::OnCursorBlinkTimerFired() {
2048 DCHECK(ShouldBlinkCursor()); 2115 DCHECK(ShouldBlinkCursor());
2049 gfx::RenderText* render_text = GetRenderText(); 2116 gfx::RenderText* render_text = GetRenderText();
2050 render_text->set_cursor_visible(!render_text->cursor_visible()); 2117 render_text->set_cursor_visible(!render_text->cursor_visible());
2051 RepaintCursor(); 2118 RepaintCursor();
2052 } 2119 }
2053 2120
2054 } // namespace views 2121 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698