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

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 up colors for Linux. 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 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 read_only_(false), 244 read_only_(false),
245 default_width_in_chars_(0), 245 default_width_in_chars_(0),
246 use_default_text_color_(true), 246 use_default_text_color_(true),
247 use_default_background_color_(true), 247 use_default_background_color_(true),
248 use_default_selection_text_color_(true), 248 use_default_selection_text_color_(true),
249 use_default_selection_background_color_(true), 249 use_default_selection_background_color_(true),
250 text_color_(SK_ColorBLACK), 250 text_color_(SK_ColorBLACK),
251 background_color_(SK_ColorWHITE), 251 background_color_(SK_ColorWHITE),
252 selection_text_color_(SK_ColorWHITE), 252 selection_text_color_(SK_ColorWHITE),
253 selection_background_color_(SK_ColorBLUE), 253 selection_background_color_(SK_ColorBLUE),
254 focus_manager_(nullptr),
254 placeholder_text_color_(kDefaultPlaceholderTextColor), 255 placeholder_text_color_(kDefaultPlaceholderTextColor),
255 invalid_(false), 256 invalid_(false),
256 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), 257 text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
257 text_input_flags_(0), 258 text_input_flags_(0),
258 performing_user_action_(false), 259 performing_user_action_(false),
259 skip_input_method_cancel_composition_(false), 260 skip_input_method_cancel_composition_(false),
260 drop_cursor_visible_(false), 261 drop_cursor_visible_(false),
261 initiating_drag_(false), 262 initiating_drag_(false),
262 aggregated_clicks_(0), 263 aggregated_clicks_(0),
263 drag_start_display_offset_(0), 264 drag_start_display_offset_(0),
264 touch_handles_hidden_due_to_scroll_(false), 265 touch_handles_hidden_due_to_scroll_(false),
265 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()), 266 use_focus_ring_(ui::MaterialDesignController::IsSecondaryUiMaterial()),
266 weak_ptr_factory_(this) { 267 weak_ptr_factory_(this) {
267 set_context_menu_controller(this); 268 set_context_menu_controller(this);
268 set_drag_controller(this); 269 set_drag_controller(this);
269 GetRenderText()->SetFontList(GetDefaultFontList()); 270 GetRenderText()->SetFontList(GetDefaultFontList());
270 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder())); 271 View::SetBorder(std::unique_ptr<Border>(new FocusableBorder()));
271 SetFocusBehavior(FocusBehavior::ALWAYS); 272 SetFocusBehavior(FocusBehavior::ALWAYS);
272 273
273 // These allow BrowserView to pass edit commands from the Chrome menu to us 274 // These allow BrowserView to pass edit commands from the Chrome menu to us
274 // when we're focused by simply asking the FocusManager to 275 // when we're focused by simply asking the FocusManager to
275 // ProcessAccelerator() with the relevant accelerators. 276 // ProcessAccelerator() with the relevant accelerators.
276 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN)); 277 AddAccelerator(ui::Accelerator(ui::VKEY_X, ui::EF_CONTROL_DOWN));
277 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN)); 278 AddAccelerator(ui::Accelerator(ui::VKEY_C, ui::EF_CONTROL_DOWN));
278 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN)); 279 AddAccelerator(ui::Accelerator(ui::VKEY_V, ui::EF_CONTROL_DOWN));
279 } 280 }
280 281
281 Textfield::~Textfield() { 282 Textfield::~Textfield() {
283 // If not currently attached to a Widget, |focus_manager_| would be null.
284 if (focus_manager_) {
285 // The Textfield may still be listening to focus changes if the Textfield is
286 // destroyed by its controller from OnKey events.
287 focus_manager_->RemoveFocusChangeListener(this);
288 focus_manager_ = nullptr;
289 }
282 if (GetInputMethod()) { 290 if (GetInputMethod()) {
283 // The textfield should have been blurred before destroy. 291 // The textfield should have been blurred before destroy.
284 DCHECK(this != GetInputMethod()->GetTextInputClient()); 292 DCHECK(this != GetInputMethod()->GetTextInputClient());
285 } 293 }
286 } 294 }
287 295
288 void Textfield::SetReadOnly(bool read_only) { 296 void Textfield::SetReadOnly(bool read_only) {
289 // Update read-only without changing the focusable state (or active, etc.). 297 // Update read-only without changing the focusable state (or active, etc.).
290 read_only_ = read_only; 298 read_only_ = read_only;
291 if (GetInputMethod()) 299 if (GetInputMethod())
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 SkColor Textfield::GetSelectionBackgroundColor() const { 430 SkColor Textfield::GetSelectionBackgroundColor() const {
423 return use_default_selection_background_color_ ? 431 return use_default_selection_background_color_ ?
424 GetNativeTheme()->GetSystemColor( 432 GetNativeTheme()->GetSystemColor(
425 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) : 433 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) :
426 selection_background_color_; 434 selection_background_color_;
427 } 435 }
428 436
429 void Textfield::SetSelectionBackgroundColor(SkColor color) { 437 void Textfield::SetSelectionBackgroundColor(SkColor color) {
430 selection_background_color_ = color; 438 selection_background_color_ = color;
431 use_default_selection_background_color_ = false; 439 use_default_selection_background_color_ = false;
432 GetRenderText()->set_selection_background_focused_color( 440 GetRenderText()->set_selection_background_color(
433 GetSelectionBackgroundColor()); 441 GetSelectionBackgroundColor());
434 SchedulePaint(); 442 SchedulePaint();
435 } 443 }
436 444
437 void Textfield::UseDefaultSelectionBackgroundColor() { 445 void Textfield::UseDefaultSelectionBackgroundColor() {
438 use_default_selection_background_color_ = true; 446 use_default_selection_background_color_ = true;
439 GetRenderText()->set_selection_background_focused_color( 447 GetRenderText()->set_selection_background_color(
440 GetSelectionBackgroundColor()); 448 GetSelectionBackgroundColor());
441 SchedulePaint(); 449 SchedulePaint();
442 } 450 }
443 451
452 SkColor Textfield::GetUnfocusedSelectionBackgroundColor() const {
453 return GetNativeTheme()->GetSystemColor(
454 ui::NativeTheme::kColorId_TextfieldSelectionBackgroundUnfocused);
455 }
456
444 bool Textfield::GetCursorEnabled() const { 457 bool Textfield::GetCursorEnabled() const {
445 return GetRenderText()->cursor_enabled(); 458 return GetRenderText()->cursor_enabled();
446 } 459 }
447 460
448 void Textfield::SetCursorEnabled(bool enabled) { 461 void Textfield::SetCursorEnabled(bool enabled) {
449 GetRenderText()->SetCursorEnabled(enabled); 462 GetRenderText()->SetCursorEnabled(enabled);
450 } 463 }
451 464
452 const gfx::FontList& Textfield::GetFontList() const { 465 const gfx::FontList& Textfield::GetFontList() const {
453 return GetRenderText()->font_list(); 466 return GetRenderText()->font_list();
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 touch_selection_controller_->SelectionChanged(); 1001 touch_selection_controller_->SelectionChanged();
989 } 1002 }
990 1003
991 void Textfield::OnEnabledChanged() { 1004 void Textfield::OnEnabledChanged() {
992 View::OnEnabledChanged(); 1005 View::OnEnabledChanged();
993 if (GetInputMethod()) 1006 if (GetInputMethod())
994 GetInputMethod()->OnTextInputTypeChanged(this); 1007 GetInputMethod()->OnTextInputTypeChanged(this);
995 SchedulePaint(); 1008 SchedulePaint();
996 } 1009 }
997 1010
1011 void Textfield::ViewHierarchyChanged(
1012 const ViewHierarchyChangedDetails& details) {
1013 // Textfields only care about focus changes if the entire Widget has lost
1014 // focus, so don't bother listening if there is no Widget.
1015 if (!GetWidget())
1016 return;
1017
1018 if (details.parent->Contains(this) && details.move_view == nullptr) {
1019 if (details.is_add) {
1020 FocusManager* focus_manager = GetFocusManager();
1021 // There should never be two different FocusManagers for the same Widget
1022 // at the same time.
1023 DCHECK(!focus_manager_ && focus_manager);
1024 focus_manager_ = focus_manager;
1025 focus_manager_->AddFocusChangeListener(this);
1026 } else {
1027 DCHECK(focus_manager_);
1028 focus_manager_->RemoveFocusChangeListener(this);
1029 focus_manager_ = nullptr;
1030 }
1031 }
1032 }
1033
998 void Textfield::OnPaint(gfx::Canvas* canvas) { 1034 void Textfield::OnPaint(gfx::Canvas* canvas) {
999 OnPaintBackground(canvas); 1035 OnPaintBackground(canvas);
1000 PaintTextAndCursor(canvas); 1036 PaintTextAndCursor(canvas);
1001 OnPaintBorder(canvas); 1037 OnPaintBorder(canvas);
1002 } 1038 }
1003 1039
1004 void Textfield::OnFocus() { 1040 void Textfield::OnFocus() {
1005 GetRenderText()->set_focused(true); 1041 GetRenderText()->set_focused(true);
1042 GetRenderText()->set_selection_background_color(
1043 GetSelectionBackgroundColor());
tapted 2016/10/24 06:04:16 Can this move to OnWillChangeFocus? Just to keep t
Patti Lor 2016/10/27 00:17:27 Done.
1006 if (ShouldShowCursor()) 1044 if (ShouldShowCursor())
1007 GetRenderText()->set_cursor_visible(true); 1045 GetRenderText()->set_cursor_visible(true);
1008 if (GetInputMethod()) 1046 if (GetInputMethod())
1009 GetInputMethod()->SetFocusedTextInputClient(this); 1047 GetInputMethod()->SetFocusedTextInputClient(this);
1010 OnCaretBoundsChanged(); 1048 OnCaretBoundsChanged();
1011 if (ShouldBlinkCursor()) 1049 if (ShouldBlinkCursor())
1012 StartBlinkingCursor(); 1050 StartBlinkingCursor();
1013 if (use_focus_ring_) { 1051 if (use_focus_ring_) {
1014 FocusRing::Install(this, invalid_ 1052 FocusRing::Install(this, invalid_
1015 ? ui::NativeTheme::kColorId_AlertSeverityHigh 1053 ? ui::NativeTheme::kColorId_AlertSeverityHigh
(...skipping 25 matching lines...) Expand all
1041 gfx::Point Textfield::GetKeyboardContextMenuLocation() { 1079 gfx::Point Textfield::GetKeyboardContextMenuLocation() {
1042 return GetCaretBounds().bottom_right(); 1080 return GetCaretBounds().bottom_right();
1043 } 1081 }
1044 1082
1045 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) { 1083 void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
1046 gfx::RenderText* render_text = GetRenderText(); 1084 gfx::RenderText* render_text = GetRenderText();
1047 render_text->SetColor(GetTextColor()); 1085 render_text->SetColor(GetTextColor());
1048 UpdateBackgroundColor(); 1086 UpdateBackgroundColor();
1049 render_text->set_cursor_color(GetTextColor()); 1087 render_text->set_cursor_color(GetTextColor());
1050 render_text->set_selection_color(GetSelectionTextColor()); 1088 render_text->set_selection_color(GetSelectionTextColor());
1051 render_text->set_selection_background_focused_color( 1089 if (HasFocus()) {
1052 GetSelectionBackgroundColor()); 1090 render_text->set_selection_background_color(GetSelectionBackgroundColor());
1091 } else {
1092 render_text->set_selection_background_color(
1093 GetUnfocusedSelectionBackgroundColor());
1094 }
1053 } 1095 }
1054 1096
1055 //////////////////////////////////////////////////////////////////////////////// 1097 ////////////////////////////////////////////////////////////////////////////////
1056 // Textfield, TextfieldModel::Delegate overrides: 1098 // Textfield, TextfieldModel::Delegate overrides:
1057 1099
1058 void Textfield::OnCompositionTextConfirmedOrCleared() { 1100 void Textfield::OnCompositionTextConfirmedOrCleared() {
1059 if (!skip_input_method_cancel_composition_) 1101 if (!skip_input_method_cancel_composition_)
1060 GetInputMethod()->CancelComposition(this); 1102 GetInputMethod()->CancelComposition(this);
1061 } 1103 }
1062 1104
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 return drag_operations; 1161 return drag_operations;
1120 } 1162 }
1121 1163
1122 bool Textfield::CanStartDragForView(View* sender, 1164 bool Textfield::CanStartDragForView(View* sender,
1123 const gfx::Point& press_pt, 1165 const gfx::Point& press_pt,
1124 const gfx::Point& p) { 1166 const gfx::Point& p) {
1125 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt); 1167 return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
1126 } 1168 }
1127 1169
1128 //////////////////////////////////////////////////////////////////////////////// 1170 ////////////////////////////////////////////////////////////////////////////////
1171 // Textfield, FocusChangeListener overrides:
1172
1173 void Textfield::OnWillChangeFocus(View* focus_before, View* focus_after) {
1174 // If this was the last focused View before switching Widgets, draw the text
1175 // selection grayed out.
1176 if (focus_before == this && focus_after == nullptr) {
1177 GetRenderText()->set_selection_background_color(
1178 GetUnfocusedSelectionBackgroundColor());
1179 GetRenderText()->set_draw_text_selection(true);
1180 } // If another View in the same Widget is focused, don't draw the selection.
1181 else if (focus_before == this && focus_after != nullptr) {
tapted 2016/10/24 06:04:16 nit: we usually have the `else` on the same line a
Patti Lor 2016/10/27 00:17:27 Done, thanks!
1182 GetRenderText()->set_draw_text_selection(false);
1183 } // This is focused now, draw the text selection.
1184 else if (focus_after == this) {
1185 GetRenderText()->set_draw_text_selection(true);
1186 }
1187 }
1188
1189 void Textfield::OnDidChangeFocus(View* focused_before, View* focused_now) {}
1190
1191 // On Windows and Linux, on Widget destruction, Textfields inside a TYPE_CONTROL
1192 // Widget will be destroyed after the FocusManager. Make sure to remove this
tapted 2016/10/24 03:11:19 It might be a bug that Mac is different here, or w
Patti Lor 2016/10/27 00:17:27 Yes - OnViewHierarchyChanged will get called befor
1193 // Textfield as an observer before the FocusManager is destroyed.
1194 #if !defined(OS_MACOSX)
1195 void Textfield::OnFocusManagerDestroying() {
1196 if (!focus_manager_)
1197 return;
1198
1199 focus_manager_->RemoveFocusChangeListener(this);
1200 focus_manager_ = nullptr;
1201 }
1202 #endif
1203
1204 ////////////////////////////////////////////////////////////////////////////////
1129 // Textfield, WordLookupClient overrides: 1205 // Textfield, WordLookupClient overrides:
1130 1206
1131 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point, 1207 bool Textfield::GetDecoratedWordAtPoint(const gfx::Point& point,
1132 gfx::DecoratedText* decorated_word, 1208 gfx::DecoratedText* decorated_word,
1133 gfx::Point* baseline_point) { 1209 gfx::Point* baseline_point) {
1134 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word, 1210 return GetRenderText()->GetDecoratedWordAtPoint(point, decorated_word,
1135 baseline_point); 1211 baseline_point);
1136 } 1212 }
1137 1213
1138 //////////////////////////////////////////////////////////////////////////////// 1214 ////////////////////////////////////////////////////////////////////////////////
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after
2105 } 2181 }
2106 2182
2107 void Textfield::OnCursorBlinkTimerFired() { 2183 void Textfield::OnCursorBlinkTimerFired() {
2108 DCHECK(ShouldBlinkCursor()); 2184 DCHECK(ShouldBlinkCursor());
2109 gfx::RenderText* render_text = GetRenderText(); 2185 gfx::RenderText* render_text = GetRenderText();
2110 render_text->set_cursor_visible(!render_text->cursor_visible()); 2186 render_text->set_cursor_visible(!render_text->cursor_visible());
2111 RepaintCursor(); 2187 RepaintCursor();
2112 } 2188 }
2113 2189
2114 } // namespace views 2190 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698