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

Side by Side Diff: ui/app_list/views/search_box_view.cc

Issue 2952763002: SearchBoxView now enables/disables cursor based on user interaction. (Closed)
Patch Set: Addressed Comments, refactored. Created 3 years, 5 months 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/app_list/views/search_box_view.h" 5 #include "ui/app_list/views/search_box_view.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "build/build_config.h" 11 #include "build/build_config.h"
12 #include "ui/app_list/app_list_constants.h" 12 #include "ui/app_list/app_list_constants.h"
13 #include "ui/app_list/app_list_features.h" 13 #include "ui/app_list/app_list_features.h"
14 #include "ui/app_list/app_list_model.h" 14 #include "ui/app_list/app_list_model.h"
15 #include "ui/app_list/app_list_switches.h" 15 #include "ui/app_list/app_list_switches.h"
16 #include "ui/app_list/app_list_view_delegate.h" 16 #include "ui/app_list/app_list_view_delegate.h"
17 #include "ui/app_list/resources/grit/app_list_resources.h" 17 #include "ui/app_list/resources/grit/app_list_resources.h"
18 #include "ui/app_list/search_box_model.h" 18 #include "ui/app_list/search_box_model.h"
19 #include "ui/app_list/speech_ui_model.h" 19 #include "ui/app_list/speech_ui_model.h"
20 #include "ui/app_list/vector_icons.h" 20 #include "ui/app_list/vector_icons.h"
21 #include "ui/app_list/views/app_list_main_view.h"
21 #include "ui/app_list/views/app_list_view.h" 22 #include "ui/app_list/views/app_list_view.h"
22 #include "ui/app_list/views/contents_view.h" 23 #include "ui/app_list/views/contents_view.h"
23 #include "ui/app_list/views/search_box_view_delegate.h" 24 #include "ui/app_list/views/search_box_view_delegate.h"
25 #include "ui/app_list/views/search_result_container_view.h"
26 #include "ui/app_list/views/search_result_page_view.h"
24 #include "ui/base/ime/text_input_flags.h" 27 #include "ui/base/ime/text_input_flags.h"
25 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
26 #include "ui/base/resource/resource_bundle.h" 29 #include "ui/base/resource/resource_bundle.h"
27 #include "ui/events/event.h" 30 #include "ui/events/event.h"
28 #include "ui/gfx/canvas.h" 31 #include "ui/gfx/canvas.h"
29 #include "ui/gfx/geometry/insets.h" 32 #include "ui/gfx/geometry/insets.h"
30 #include "ui/gfx/paint_vector_icon.h" 33 #include "ui/gfx/paint_vector_icon.h"
31 #include "ui/gfx/shadow_value.h" 34 #include "ui/gfx/shadow_value.h"
32 #include "ui/strings/grit/ui_strings.h" 35 #include "ui/strings/grit/ui_strings.h"
33 #include "ui/views/background.h" 36 #include "ui/views/background.h"
(...skipping 21 matching lines...) Expand all
55 constexpr int kBackgroundBorderCornerRadius = 2; 58 constexpr int kBackgroundBorderCornerRadius = 2;
56 constexpr int kBackgroundBorderCornerRadiusFullscreen = 24; 59 constexpr int kBackgroundBorderCornerRadiusFullscreen = 24;
57 constexpr int kGoogleIconSize = 24; 60 constexpr int kGoogleIconSize = 24;
58 constexpr int kMicIconSize = 24; 61 constexpr int kMicIconSize = 24;
59 62
60 // Default color used when wallpaper customized color is not available for 63 // Default color used when wallpaper customized color is not available for
61 // searchbox, #000 at 87% opacity. 64 // searchbox, #000 at 87% opacity.
62 constexpr SkColor kDefaultSearchboxColor = 65 constexpr SkColor kDefaultSearchboxColor =
63 SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00); 66 SkColorSetARGBMacro(0xDE, 0x00, 0x00, 0x00);
64 67
68 // Color of placeholder text in zero query state.
69 constexpr SkColor kZeroQuerySearchboxColor =
70 SkColorSetARGBMacro(0x8A, 0x00, 0x00, 0x00);
71
65 // A background that paints a solid white rounded rect with a thin grey border. 72 // A background that paints a solid white rounded rect with a thin grey border.
66 class SearchBoxBackground : public views::Background { 73 class SearchBoxBackground : public views::Background {
67 public: 74 public:
68 SearchBoxBackground() 75 SearchBoxBackground()
69 : background_border_corner_radius_( 76 : background_border_corner_radius_(
70 features::IsFullscreenAppListEnabled() 77 features::IsFullscreenAppListEnabled()
71 ? kBackgroundBorderCornerRadiusFullscreen 78 ? kBackgroundBorderCornerRadiusFullscreen
72 : kBackgroundBorderCornerRadius) {} 79 : kBackgroundBorderCornerRadius) {}
73 ~SearchBoxBackground() override {} 80 ~SearchBoxBackground() override {}
74 81
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); 173 views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
167 layout->set_minimum_cross_axis_size(kPreferredHeight); 174 layout->set_minimum_cross_axis_size(kPreferredHeight);
168 175
169 search_box_->SetBorder(views::NullBorder()); 176 search_box_->SetBorder(views::NullBorder());
170 search_box_->SetTextColor(kSearchTextColor); 177 search_box_->SetTextColor(kSearchTextColor);
171 search_box_->SetBackgroundColor(kSearchBoxBackgroundDefault); 178 search_box_->SetBackgroundColor(kSearchBoxBackgroundDefault);
172 search_box_->set_controller(this); 179 search_box_->set_controller(this);
173 search_box_->SetTextInputType(ui::TEXT_INPUT_TYPE_SEARCH); 180 search_box_->SetTextInputType(ui::TEXT_INPUT_TYPE_SEARCH);
174 search_box_->SetTextInputFlags(ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF); 181 search_box_->SetTextInputFlags(ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF);
175 if (is_fullscreen_app_list_enabled_) { 182 if (is_fullscreen_app_list_enabled_) {
183 app_list_view_->PrependPreTargetHandler(this);
oshima 2017/06/29 16:58:50 just curious. Why you need to use target handler?
newcomer 2017/06/30 21:47:23 This has been removed. There were some issues tha
184
176 google_icon_ = new views::ImageView(); 185 google_icon_ = new views::ImageView();
177 google_icon_->SetImage(gfx::CreateVectorIcon( 186 google_icon_->SetImage(gfx::CreateVectorIcon(
178 kIcGoogleBlackIcon, kGoogleIconSize, kDefaultSearchboxColor)); 187 kIcGoogleBlackIcon, kGoogleIconSize, kDefaultSearchboxColor));
179 content_container_->AddChildView(google_icon_); 188 content_container_->AddChildView(google_icon_);
180 189
181 search_box_->set_placeholder_text_color(kDefaultSearchboxColor); 190 search_box_->set_placeholder_text_color(kDefaultSearchboxColor);
182 search_box_->set_placeholder_text_draw_flags( 191 search_box_->set_placeholder_text_draw_flags(
183 gfx::Canvas::TEXT_ALIGN_CENTER); 192 gfx::Canvas::TEXT_ALIGN_CENTER);
184 search_box_->SetFontList(search_box_->GetFontList().DeriveWithSizeDelta(2)); 193 search_box_->SetFontList(search_box_->GetFontList().DeriveWithSizeDelta(2));
194 search_box_->SetCursorEnabled(is_search_box_active_);
185 } else { 195 } else {
186 back_button_ = new SearchBoxImageButton(this); 196 back_button_ = new SearchBoxImageButton(this);
187 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 197 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
188 back_button_->SetImage( 198 back_button_->SetImage(
189 views::ImageButton::STATE_NORMAL, 199 views::ImageButton::STATE_NORMAL,
190 rb.GetImageSkiaNamed(IDR_APP_LIST_FOLDER_BACK_NORMAL)); 200 rb.GetImageSkiaNamed(IDR_APP_LIST_FOLDER_BACK_NORMAL));
191 back_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER, 201 back_button_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
192 views::ImageButton::ALIGN_MIDDLE); 202 views::ImageButton::ALIGN_MIDDLE);
193 SetBackButtonLabel(false); 203 SetBackButtonLabel(false);
194 content_container_->AddChildView(back_button_); 204 content_container_->AddChildView(back_button_);
195 205
196 search_box_->set_placeholder_text_color(kHintTextColor); 206 search_box_->set_placeholder_text_color(kHintTextColor);
197 } 207 }
198 content_container_->AddChildView(search_box_); 208 content_container_->AddChildView(search_box_);
199 layout->SetFlexForView(search_box_, 1); 209 layout->SetFlexForView(search_box_, 1);
200 210
201 view_delegate_->GetSpeechUI()->AddObserver(this); 211 view_delegate_->GetSpeechUI()->AddObserver(this);
202 ModelChanged(); 212 ModelChanged();
203 } 213 }
204 214
205 SearchBoxView::~SearchBoxView() { 215 SearchBoxView::~SearchBoxView() {
206 view_delegate_->GetSpeechUI()->RemoveObserver(this); 216 view_delegate_->GetSpeechUI()->RemoveObserver(this);
207 model_->search_box()->RemoveObserver(this); 217 model_->search_box()->RemoveObserver(this);
218 if (is_fullscreen_app_list_enabled_)
219 app_list_view_->RemovePreTargetHandler(this);
208 } 220 }
209 221
210 void SearchBoxView::ModelChanged() { 222 void SearchBoxView::ModelChanged() {
211 if (model_) 223 if (model_)
212 model_->search_box()->RemoveObserver(this); 224 model_->search_box()->RemoveObserver(this);
213 225
214 model_ = view_delegate_->GetModel(); 226 model_ = view_delegate_->GetModel();
215 DCHECK(model_); 227 DCHECK(model_);
216 model_->search_box()->AddObserver(this); 228 model_->search_box()->AddObserver(this);
217 SpeechRecognitionButtonPropChanged(); 229 SpeechRecognitionButtonPropChanged();
218 HintTextChanged(); 230 HintTextChanged();
219 } 231 }
220 232
221 bool SearchBoxView::HasSearch() const { 233 bool SearchBoxView::HasSearch() const {
222 return !search_box_->text().empty(); 234 return !search_box_->text().empty();
223 } 235 }
224 236
225 void SearchBoxView::ClearSearch() { 237 void SearchBoxView::ClearSearch() {
226 search_box_->SetText(base::string16()); 238 search_box_->SetText(base::string16());
227 view_delegate_->AutoLaunchCanceled(); 239 view_delegate_->AutoLaunchCanceled();
228 // Updates model and fires query changed manually because SetText() above 240 // Updates model and fires query changed manually because SetText() above
229 // does not generate ContentsChanged() notification. 241 // does not generate ContentsChanged() notification.
230 UpdateModel(); 242 UpdateModel();
231 NotifyQueryChanged(); 243 NotifyQueryChanged();
244 if (is_fullscreen_app_list_enabled_) {
245 SetSearchBoxActive(false);
246 app_list_view_->SetStateFromSearchBoxView(true);
247 }
232 } 248 }
233 249
234 void SearchBoxView::SetShadow(const gfx::ShadowValue& shadow) { 250 void SearchBoxView::SetShadow(const gfx::ShadowValue& shadow) {
235 if (is_fullscreen_app_list_enabled_) 251 if (is_fullscreen_app_list_enabled_)
236 return; 252 return;
237 253
238 SetBorder(base::MakeUnique<views::ShadowBorder>(shadow)); 254 SetBorder(base::MakeUnique<views::ShadowBorder>(shadow));
239 Layout(); 255 Layout();
240 } 256 }
241 257
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 if (!back_button_) 341 if (!back_button_)
326 return; 342 return;
327 343
328 base::string16 back_button_label(l10n_util::GetStringUTF16( 344 base::string16 back_button_label(l10n_util::GetStringUTF16(
329 folder ? IDS_APP_LIST_FOLDER_CLOSE_FOLDER_ACCESSIBILE_NAME 345 folder ? IDS_APP_LIST_FOLDER_CLOSE_FOLDER_ACCESSIBILE_NAME
330 : IDS_APP_LIST_BACK)); 346 : IDS_APP_LIST_BACK));
331 back_button_->SetAccessibleName(back_button_label); 347 back_button_->SetAccessibleName(back_button_label);
332 back_button_->SetTooltipText(back_button_label); 348 back_button_->SetTooltipText(back_button_label);
333 } 349 }
334 350
351 void SearchBoxView::SetSearchBoxActive(bool active) {
352 if (active == is_search_box_active_)
353 return;
354
355 is_search_box_active_ = active;
356 search_box_->set_placeholder_text_draw_flags(
357 active ? gfx::Canvas::TEXT_ALIGN_LEFT : gfx::Canvas::TEXT_ALIGN_CENTER);
358 search_box_->set_placeholder_text_color(active ? kZeroQuerySearchboxColor
359 : kDefaultSearchboxColor);
360 search_box_->SetCursorEnabled(active);
361 search_box_->SchedulePaint();
362 }
363
364 void SearchBoxView::HandleSearchBoxEvent(ui::LocatedEvent* located_event,
365 ui::EventType type) {
366 if (!is_fullscreen_app_list_enabled_)
367 return;
368 if (type != ui::ET_MOUSE_PRESSED && type != ui::ET_GESTURE_TAP)
369 return;
370
371 bool event_is_in_searchbox_bounds =
372 GetWidget()->GetWindowBoundsInScreen().Contains(
373 located_event->root_location());
374
375 bool event_is_in_search_result_bounds = false;
376 ContentsView* main_contents_view =
377 app_list_view_->app_list_main_view()->contents_view();
378
379 // If a search result is visible check if the event was within its bounds.
380 if (main_contents_view->IsShowingSearchResults()) {
381 View* search_result_contents_view =
382 main_contents_view->search_results_page_view()->contents_view();
383
384 const gfx::Rect search_result_bounds =
385 search_result_contents_view->GetBoundsInScreen();
386 event_is_in_search_result_bounds =
387 search_result_bounds.Contains(located_event->root_location());
388 }
389
390 if (is_search_box_active_ && !event_is_in_searchbox_bounds &&
391 !event_is_in_search_result_bounds) {
392 // If the event was not within searchbox bounds or search result bounds and
393 // the search box is active, close the app list.
394 located_event->SetHandled();
395 app_list_view_->SetState(AppListView::CLOSED);
xiyuan 2017/06/27 23:11:10 It seems we want to dismiss app list when there is
newcomer 2017/06/30 21:47:23 Handled offline. We found the problems in the leaf
396 } else if (!is_search_box_active_ && event_is_in_searchbox_bounds &&
397 search_box_->text().empty()) {
398 // If the event was within the searchbox bounds and in an inactive empty
399 // search box, enable the search box.
400 SetSearchBoxActive(true);
xiyuan 2017/06/27 23:11:10 This branch is probably not necessary since the ev
newcomer 2017/06/30 21:47:23 It is necessary because there are two regions of t
401 located_event->SetHandled();
402 }
403 }
404
405 bool SearchBoxView::OnTextfieldEvent() {
406 if (!is_search_box_active_) {
407 SetSearchBoxActive(true);
408 return true;
409 } else {
410 return false;
411 }
412 }
413
335 bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) { 414 bool SearchBoxView::OnMouseWheel(const ui::MouseWheelEvent& event) {
336 if (contents_view_) 415 if (contents_view_)
337 return contents_view_->OnMouseWheel(event); 416 return contents_view_->OnMouseWheel(event);
338 417
339 return false; 418 return false;
340 } 419 }
341 420
342 void SearchBoxView::OnEnabledChanged() { 421 void SearchBoxView::OnEnabledChanged() {
343 search_box_->SetEnabled(enabled()); 422 search_box_->SetEnabled(enabled());
344 if (speech_button_) 423 if (speech_button_)
345 speech_button_->SetEnabled(enabled()); 424 speech_button_->SetEnabled(enabled());
346 } 425 }
347 426
348 const char* SearchBoxView::GetClassName() const { 427 const char* SearchBoxView::GetClassName() const {
349 return "SearchBoxView"; 428 return "SearchBoxView";
350 } 429 }
351 430
431 void SearchBoxView::OnGestureEvent(ui::GestureEvent* event) {
432 HandleSearchBoxEvent(event->AsLocatedEvent(), event->type());
oshima 2017/06/29 16:58:50 AsLocatedEvent is a utility method to downcast fro
newcomer 2017/06/30 21:47:23 Done.
433 }
434
435 void SearchBoxView::OnMouseEvent(ui::MouseEvent* event) {
436 HandleSearchBoxEvent(event->AsLocatedEvent(), event->type());
437 }
438
352 void SearchBoxView::UpdateModel() { 439 void SearchBoxView::UpdateModel() {
353 // Temporarily remove from observer to ignore notifications caused by us. 440 // Temporarily remove from observer to ignore notifications caused by us.
354 model_->search_box()->RemoveObserver(this); 441 model_->search_box()->RemoveObserver(this);
355 model_->search_box()->Update(search_box_->text(), false); 442 model_->search_box()->Update(search_box_->text(), false);
356 model_->search_box()->SetSelectionModel(search_box_->GetSelectionModel()); 443 model_->search_box()->SetSelectionModel(search_box_->GetSelectionModel());
357 model_->search_box()->AddObserver(this); 444 model_->search_box()->AddObserver(this);
358 } 445 }
359 446
360 void SearchBoxView::NotifyQueryChanged() { 447 void SearchBoxView::NotifyQueryChanged() {
361 DCHECK(delegate_); 448 DCHECK(delegate_);
362 delegate_->QueryChanged(this); 449 delegate_->QueryChanged(this);
363 } 450 }
364 451
365 void SearchBoxView::ContentsChanged(views::Textfield* sender, 452 void SearchBoxView::ContentsChanged(views::Textfield* sender,
366 const base::string16& new_contents) { 453 const base::string16& new_contents) {
367 UpdateModel(); 454 UpdateModel();
368 view_delegate_->AutoLaunchCanceled(); 455 view_delegate_->AutoLaunchCanceled();
369 NotifyQueryChanged(); 456 NotifyQueryChanged();
370 if (is_fullscreen_app_list_enabled_) 457 if (is_fullscreen_app_list_enabled_) {
371 app_list_view_->SetStateFromSearchBoxView(search_box_->text().empty()); 458 if (is_search_box_active_ == search_box_->text().empty()) {
459 SetSearchBoxActive(!search_box_->text().empty());
460 app_list_view_->SetStateFromSearchBoxView(search_box_->text().empty());
461 }
462 }
372 } 463 }
373 464
374 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, 465 bool SearchBoxView::HandleKeyEvent(views::Textfield* sender,
375 const ui::KeyEvent& key_event) { 466 const ui::KeyEvent& key_event) {
376 if (key_event.type() == ui::ET_KEY_PRESSED) { 467 if (key_event.type() == ui::ET_KEY_PRESSED) {
377 if (key_event.key_code() == ui::VKEY_TAB && 468 if (key_event.key_code() == ui::VKEY_TAB &&
378 focused_view_ != FOCUS_CONTENTS_VIEW && 469 focused_view_ != FOCUS_CONTENTS_VIEW &&
379 MoveTabFocus(key_event.IsShiftDown())) 470 MoveTabFocus(key_event.IsShiftDown()))
380 return true; 471 return true;
381 472
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 speech_button_->OnKeyReleased(key_event)) 506 speech_button_->OnKeyReleased(key_event))
416 return true; 507 return true;
417 508
418 return contents_view_ && contents_view_->visible() && 509 return contents_view_ && contents_view_->visible() &&
419 contents_view_->OnKeyReleased(key_event); 510 contents_view_->OnKeyReleased(key_event);
420 } 511 }
421 512
422 return false; 513 return false;
423 } 514 }
424 515
516 bool SearchBoxView::HandleMouseEvent(views::Textfield* sender,
517 const ui::MouseEvent& mouse_event) {
518 if (!is_fullscreen_app_list_enabled_)
519 return false;
520
521 return OnTextfieldEvent();
522 }
523
524 bool SearchBoxView::HandleGestureEvent(views::Textfield* sender,
525 const ui::GestureEvent& gesture_event) {
526 if (!is_fullscreen_app_list_enabled_)
527 return false;
528
529 return OnTextfieldEvent();
530 }
531
425 void SearchBoxView::ButtonPressed(views::Button* sender, 532 void SearchBoxView::ButtonPressed(views::Button* sender,
426 const ui::Event& event) { 533 const ui::Event& event) {
427 if (back_button_ && sender == back_button_) 534 if (back_button_ && sender == back_button_)
428 delegate_->BackButtonPressed(); 535 delegate_->BackButtonPressed();
429 else if (speech_button_ && sender == speech_button_) 536 else if (speech_button_ && sender == speech_button_)
430 view_delegate_->StartSpeechRecognition(); 537 view_delegate_->StartSpeechRecognition();
431 else 538 else
432 NOTREACHED(); 539 NOTREACHED();
433 } 540 }
434 541
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 NotifyQueryChanged(); 596 NotifyQueryChanged();
490 } 597 }
491 598
492 void SearchBoxView::OnSpeechRecognitionStateChanged( 599 void SearchBoxView::OnSpeechRecognitionStateChanged(
493 SpeechRecognitionState new_state) { 600 SpeechRecognitionState new_state) {
494 SpeechRecognitionButtonPropChanged(); 601 SpeechRecognitionButtonPropChanged();
495 SchedulePaint(); 602 SchedulePaint();
496 } 603 }
497 604
498 } // namespace app_list 605 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698