ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / app_list / views / app_list_view.cc
blob216abf4d4505b16a46ee4977aada5e6bc56ef716
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
3 // found in the LICENSE file.
5 #include "ui/app_list/views/app_list_view.h"
7 #include <algorithm>
9 #include "base/command_line.h"
10 #include "base/metrics/histogram.h"
11 #include "base/profiler/scoped_tracker.h"
12 #include "base/strings/string_util.h"
13 #include "base/win/windows_version.h"
14 #include "ui/app_list/app_list_constants.h"
15 #include "ui/app_list/app_list_model.h"
16 #include "ui/app_list/app_list_switches.h"
17 #include "ui/app_list/app_list_view_delegate.h"
18 #include "ui/app_list/speech_ui_model.h"
19 #include "ui/app_list/views/app_list_background.h"
20 #include "ui/app_list/views/app_list_folder_view.h"
21 #include "ui/app_list/views/app_list_main_view.h"
22 #include "ui/app_list/views/app_list_view_observer.h"
23 #include "ui/app_list/views/apps_container_view.h"
24 #include "ui/app_list/views/contents_view.h"
25 #include "ui/app_list/views/search_box_view.h"
26 #include "ui/app_list/views/speech_view.h"
27 #include "ui/app_list/views/start_page_view.h"
28 #include "ui/base/ui_base_switches.h"
29 #include "ui/compositor/layer.h"
30 #include "ui/compositor/layer_animation_observer.h"
31 #include "ui/compositor/scoped_layer_animation_settings.h"
32 #include "ui/gfx/canvas.h"
33 #include "ui/gfx/geometry/insets.h"
34 #include "ui/gfx/image/image_skia.h"
35 #include "ui/gfx/path.h"
36 #include "ui/gfx/skia_util.h"
37 #include "ui/resources/grit/ui_resources.h"
38 #include "ui/views/bubble/bubble_frame_view.h"
39 #include "ui/views/controls/image_view.h"
40 #include "ui/views/controls/textfield/textfield.h"
41 #include "ui/views/layout/fill_layout.h"
42 #include "ui/views/widget/widget.h"
44 #if defined(USE_AURA)
45 #include "ui/aura/window.h"
46 #include "ui/aura/window_tree_host.h"
47 #include "ui/views/bubble/bubble_window_targeter.h"
48 #include "ui/wm/core/masked_window_targeter.h"
49 #if defined(OS_WIN)
50 #include "ui/base/win/shell.h"
51 #endif
52 #if !defined(OS_CHROMEOS)
53 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
54 #endif
55 #endif // defined(USE_AURA)
57 namespace app_list {
59 namespace {
61 // The margin from the edge to the speech UI.
62 const int kSpeechUIMargin = 12;
64 // The vertical position for the appearing animation of the speech UI.
65 const float kSpeechUIAppearingPosition = 12;
67 // The distance between the arrow tip and edge of the anchor view.
68 const int kArrowOffset = 10;
70 // Determines whether the current environment supports shadows bubble borders.
71 bool SupportsShadow() {
72 #if defined(OS_WIN)
73 // Shadows are not supported on Windows without Aero Glass.
74 if (!ui::win::IsAeroGlassEnabled() ||
75 base::CommandLine::ForCurrentProcess()->HasSwitch(
76 ::switches::kDisableDwmComposition)) {
77 return false;
79 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
80 // Shadows are not supported on (non-ChromeOS) Linux.
81 return false;
82 #endif
83 return true;
86 // This view forwards the focus to the search box widget by providing it as a
87 // FocusTraversable when a focus search is provided.
88 class SearchBoxFocusHost : public views::View {
89 public:
90 explicit SearchBoxFocusHost(views::Widget* search_box_widget)
91 : search_box_widget_(search_box_widget) {}
93 ~SearchBoxFocusHost() override {}
95 views::FocusTraversable* GetFocusTraversable() override {
96 return search_box_widget_;
99 private:
100 views::Widget* search_box_widget_;
102 DISALLOW_COPY_AND_ASSIGN(SearchBoxFocusHost);
105 // The view for the App List overlay, which appears as a white rounded
106 // rectangle with the given radius.
107 class AppListOverlayView : public views::View {
108 public:
109 explicit AppListOverlayView(int corner_radius)
110 : corner_radius_(corner_radius) {
111 SetPaintToLayer(true);
112 SetVisible(false);
113 layer()->SetOpacity(0.0f);
116 ~AppListOverlayView() override {}
118 // Overridden from views::View:
119 void OnPaint(gfx::Canvas* canvas) override {
120 SkPaint paint;
121 paint.setStyle(SkPaint::kFill_Style);
122 paint.setColor(SK_ColorWHITE);
123 canvas->DrawRoundRect(GetContentsBounds(), corner_radius_, paint);
126 private:
127 const int corner_radius_;
129 DISALLOW_COPY_AND_ASSIGN(AppListOverlayView);
132 #if defined(USE_AURA)
133 // An event targeter for the search box widget which will ignore events that
134 // are on the search box's shadow.
135 class SearchBoxWindowTargeter : public wm::MaskedWindowTargeter {
136 public:
137 explicit SearchBoxWindowTargeter(views::View* search_box)
138 : wm::MaskedWindowTargeter(search_box->GetWidget()->GetNativeWindow()),
139 search_box_(search_box) {}
140 ~SearchBoxWindowTargeter() override {}
142 private:
143 // wm::MaskedWindowTargeter:
144 bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override {
145 mask->addRect(gfx::RectToSkRect(search_box_->GetContentsBounds()));
146 return true;
149 views::View* search_box_;
151 DISALLOW_COPY_AND_ASSIGN(SearchBoxWindowTargeter);
153 #endif
155 } // namespace
157 // An animation observer to hide the view at the end of the animation.
158 class HideViewAnimationObserver : public ui::ImplicitAnimationObserver {
159 public:
160 HideViewAnimationObserver()
161 : frame_(NULL),
162 target_(NULL) {
165 ~HideViewAnimationObserver() override {
166 if (target_)
167 StopObservingImplicitAnimations();
170 void SetTarget(views::View* target) {
171 if (target_)
172 StopObservingImplicitAnimations();
173 target_ = target;
176 void set_frame(views::BubbleFrameView* frame) { frame_ = frame; }
178 private:
179 // Overridden from ui::ImplicitAnimationObserver:
180 void OnImplicitAnimationsCompleted() override {
181 if (target_) {
182 target_->SetVisible(false);
183 target_ = NULL;
185 // Should update the background by invoking SchedulePaint().
186 if (frame_)
187 frame_->SchedulePaint();
191 views::BubbleFrameView* frame_;
192 views::View* target_;
194 DISALLOW_COPY_AND_ASSIGN(HideViewAnimationObserver);
197 ////////////////////////////////////////////////////////////////////////////////
198 // AppListView:
200 AppListView::AppListView(AppListViewDelegate* delegate)
201 : delegate_(delegate),
202 app_list_main_view_(nullptr),
203 speech_view_(nullptr),
204 search_box_focus_host_(nullptr),
205 search_box_widget_(nullptr),
206 search_box_view_(nullptr),
207 overlay_view_(nullptr),
208 animation_observer_(new HideViewAnimationObserver()) {
209 CHECK(delegate);
211 delegate_->AddObserver(this);
212 delegate_->GetSpeechUI()->AddObserver(this);
215 AppListView::~AppListView() {
216 delegate_->GetSpeechUI()->RemoveObserver(this);
217 delegate_->RemoveObserver(this);
218 animation_observer_.reset();
219 // Remove child views first to ensure no remaining dependencies on delegate_.
220 RemoveAllChildViews(true);
223 void AppListView::InitAsBubbleAttachedToAnchor(
224 gfx::NativeView parent,
225 int initial_apps_page,
226 views::View* anchor,
227 const gfx::Vector2d& anchor_offset,
228 views::BubbleBorder::Arrow arrow,
229 bool border_accepts_events) {
230 SetAnchorView(anchor);
231 InitAsBubbleInternal(
232 parent, initial_apps_page, arrow, border_accepts_events, anchor_offset);
235 void AppListView::InitAsBubbleAtFixedLocation(
236 gfx::NativeView parent,
237 int initial_apps_page,
238 const gfx::Point& anchor_point_in_screen,
239 views::BubbleBorder::Arrow arrow,
240 bool border_accepts_events) {
241 SetAnchorView(NULL);
242 SetAnchorRect(gfx::Rect(anchor_point_in_screen, gfx::Size()));
243 InitAsBubbleInternal(
244 parent, initial_apps_page, arrow, border_accepts_events, gfx::Vector2d());
247 void AppListView::InitAsFramelessWindow(gfx::NativeView parent,
248 int initial_apps_page,
249 gfx::Rect bounds) {
250 InitContents(parent, initial_apps_page);
251 overlay_view_ = new AppListOverlayView(0 /* no corners */);
252 AddChildView(overlay_view_);
254 views::Widget* widget = new views::Widget();
255 views::Widget::InitParams params(
256 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
257 params.parent = parent;
258 params.delegate = this;
259 widget->Init(params);
260 widget->SetBounds(bounds);
261 // This needs to be set *after* Widget::Init() because BubbleDelegateView sets
262 // its own background at OnNativeThemeChanged(), which is called in
263 // View::AddChildView() which is called at Widget::SetContentsView() to build
264 // the views hierarchy in the widget.
265 set_background(new AppListBackground(0));
267 InitChildWidgets();
270 void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) {
271 GetBubbleFrameView()->bubble_border()->set_arrow(arrow);
272 SizeToContents(); // Recalcuates with new border.
273 GetBubbleFrameView()->SchedulePaint();
276 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
277 SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
280 void AppListView::SetDragAndDropHostOfCurrentAppList(
281 ApplicationDragAndDropHost* drag_and_drop_host) {
282 app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
285 void AppListView::ShowWhenReady() {
286 app_list_main_view_->ShowAppListWhenReady();
289 void AppListView::Close() {
290 app_list_main_view_->Close();
291 delegate_->Dismiss();
294 void AppListView::UpdateBounds() {
295 SizeToContents();
298 void AppListView::SetAppListOverlayVisible(bool visible) {
299 DCHECK(overlay_view_);
301 // Display the overlay immediately so we can begin the animation.
302 overlay_view_->SetVisible(true);
304 ui::ScopedLayerAnimationSettings settings(
305 overlay_view_->layer()->GetAnimator());
306 settings.SetTweenType(gfx::Tween::LINEAR);
308 // If we're dismissing the overlay, hide the view at the end of the animation.
309 if (!visible) {
310 // Since only one animation is visible at a time, it's safe to re-use
311 // animation_observer_ here.
312 animation_observer_->set_frame(NULL);
313 animation_observer_->SetTarget(overlay_view_);
314 settings.AddObserver(animation_observer_.get());
317 const float kOverlayFadeInMilliseconds = 125;
318 settings.SetTransitionDuration(
319 base::TimeDelta::FromMilliseconds(kOverlayFadeInMilliseconds));
321 const float kOverlayOpacity = 0.75f;
322 overlay_view_->layer()->SetOpacity(visible ? kOverlayOpacity : 0.0f);
323 // Create the illusion that the search box is hidden behind the app list
324 // overlay mask by setting its opacity to the same value, and disabling it.
326 ui::ScopedLayerAnimationSettings settings(
327 search_box_widget_->GetLayer()->GetAnimator());
328 const float kSearchBoxWidgetOpacity = 0.5f;
329 search_box_widget_->GetLayer()->SetOpacity(visible ? kSearchBoxWidgetOpacity
330 : 1.0f);
331 search_box_view_->SetEnabled(!visible);
332 if (!visible)
333 search_box_view_->search_box()->RequestFocus();
337 bool AppListView::ShouldCenterWindow() const {
338 return delegate_->ShouldCenterWindow();
341 gfx::Size AppListView::GetPreferredSize() const {
342 return app_list_main_view_->GetPreferredSize();
345 void AppListView::Paint(gfx::Canvas* canvas, const views::CullSet& cull_set) {
346 views::BubbleDelegateView::Paint(canvas, cull_set);
347 if (!next_paint_callback_.is_null()) {
348 next_paint_callback_.Run();
349 next_paint_callback_.Reset();
353 void AppListView::OnThemeChanged() {
354 #if defined(OS_WIN)
355 GetWidget()->Close();
356 #endif
359 bool AppListView::ShouldHandleSystemCommands() const {
360 return true;
363 bool AppListView::ShouldDescendIntoChildForEventHandling(
364 gfx::NativeView child,
365 const gfx::Point& location) {
366 // While on the start page, don't descend into the custom launcher page. Since
367 // the only valid action is to open it.
368 ContentsView* contents_view = app_list_main_view_->contents_view();
369 if (contents_view->GetActiveState() == AppListModel::STATE_START)
370 return !contents_view->GetCustomPageCollapsedBounds().Contains(location);
372 return views::BubbleDelegateView::ShouldDescendIntoChildForEventHandling(
373 child, location);
376 void AppListView::Prerender() {
377 app_list_main_view_->Prerender();
380 void AppListView::OnProfilesChanged() {
381 app_list_main_view_->search_box_view()->InvalidateMenu();
384 void AppListView::OnShutdown() {
385 // Nothing to do on views - the widget will soon be closed, which will tear
386 // everything down.
389 void AppListView::SetProfileByPath(const base::FilePath& profile_path) {
390 delegate_->SetProfileByPath(profile_path);
391 app_list_main_view_->ModelChanged();
394 void AppListView::AddObserver(AppListViewObserver* observer) {
395 observers_.AddObserver(observer);
398 void AppListView::RemoveObserver(AppListViewObserver* observer) {
399 observers_.RemoveObserver(observer);
402 // static
403 void AppListView::SetNextPaintCallback(const base::Closure& callback) {
404 next_paint_callback_ = callback;
407 #if defined(OS_WIN)
408 HWND AppListView::GetHWND() const {
409 gfx::NativeWindow window =
410 GetWidget()->GetTopLevelWidget()->GetNativeWindow();
411 return window->GetHost()->GetAcceleratedWidget();
413 #endif
415 PaginationModel* AppListView::GetAppsPaginationModel() {
416 return app_list_main_view_->contents_view()
417 ->apps_container_view()
418 ->apps_grid_view()
419 ->pagination_model();
422 void AppListView::InitContents(gfx::NativeView parent, int initial_apps_page) {
423 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
424 // crbug.com/441028 are fixed.
425 tracked_objects::ScopedTracker tracking_profile(
426 FROM_HERE_WITH_EXPLICIT_FUNCTION(
427 "440224, 441028 AppListView::InitContents"));
429 app_list_main_view_ = new AppListMainView(delegate_);
430 AddChildView(app_list_main_view_);
431 app_list_main_view_->SetPaintToLayer(true);
432 app_list_main_view_->SetFillsBoundsOpaquely(false);
433 app_list_main_view_->layer()->SetMasksToBounds(true);
435 // This will be added to the |search_box_widget_| after the app list widget is
436 // initialized.
437 search_box_view_ = new SearchBoxView(app_list_main_view_, delegate_);
438 search_box_view_->SetPaintToLayer(true);
439 search_box_view_->SetFillsBoundsOpaquely(false);
440 search_box_view_->layer()->SetMasksToBounds(true);
442 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
443 // crbug.com/441028 are fixed.
444 tracked_objects::ScopedTracker tracking_profile1(
445 FROM_HERE_WITH_EXPLICIT_FUNCTION(
446 "440224, 441028 AppListView::InitContents1"));
448 app_list_main_view_->Init(parent, initial_apps_page, search_box_view_);
450 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
451 // crbug.com/441028 are fixed.
452 tracked_objects::ScopedTracker tracking_profile2(
453 FROM_HERE_WITH_EXPLICIT_FUNCTION(
454 "440224, 441028 AppListView::InitContents2"));
456 // Speech recognition is available only when the start page exists.
457 if (delegate_ && delegate_->IsSpeechRecognitionEnabled()) {
458 speech_view_ = new SpeechView(delegate_);
459 speech_view_->SetVisible(false);
460 speech_view_->SetPaintToLayer(true);
461 speech_view_->SetFillsBoundsOpaquely(false);
462 speech_view_->layer()->SetOpacity(0.0f);
463 AddChildView(speech_view_);
466 OnProfilesChanged();
469 void AppListView::InitChildWidgets() {
470 DCHECK(search_box_view_);
472 // Create the search box widget.
473 views::Widget::InitParams search_box_widget_params(
474 views::Widget::InitParams::TYPE_CONTROL);
475 search_box_widget_params.parent = GetWidget()->GetNativeView();
476 search_box_widget_params.opacity =
477 views::Widget::InitParams::TRANSLUCENT_WINDOW;
479 // Create a widget for the SearchBoxView to live in. This allows the
480 // SearchBoxView to be on top of the custom launcher page's WebContents
481 // (otherwise the search box events will be captured by the WebContents).
482 search_box_widget_ = new views::Widget;
483 search_box_widget_->Init(search_box_widget_params);
484 search_box_widget_->SetContentsView(search_box_view_);
486 // The search box will not naturally receive focus by itself (because it is in
487 // a separate widget). Create this SearchBoxFocusHost in the main widget to
488 // forward the focus search into to the search box.
489 search_box_focus_host_ = new SearchBoxFocusHost(search_box_widget_);
490 AddChildView(search_box_focus_host_);
491 search_box_widget_->SetFocusTraversableParentView(search_box_focus_host_);
492 search_box_widget_->SetFocusTraversableParent(
493 GetWidget()->GetFocusTraversable());
495 #if defined(USE_AURA)
496 // Mouse events on the search box shadow should not be captured.
497 aura::Window* window = search_box_widget_->GetNativeWindow();
498 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
499 new SearchBoxWindowTargeter(search_box_view_)));
500 #endif
502 app_list_main_view_->contents_view()->Layout();
505 void AppListView::InitAsBubbleInternal(gfx::NativeView parent,
506 int initial_apps_page,
507 views::BubbleBorder::Arrow arrow,
508 bool border_accepts_events,
509 const gfx::Vector2d& anchor_offset) {
510 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
511 tracked_objects::ScopedTracker tracking_profile1(
512 FROM_HERE_WITH_EXPLICIT_FUNCTION(
513 "431326 AppListView::InitAsBubbleInternal1"));
515 base::Time start_time = base::Time::Now();
517 InitContents(parent, initial_apps_page);
519 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
520 tracked_objects::ScopedTracker tracking_profile2(
521 FROM_HERE_WITH_EXPLICIT_FUNCTION(
522 "431326 AppListView::InitAsBubbleInternal2"));
524 set_color(kContentsBackgroundColor);
525 set_margins(gfx::Insets());
526 set_parent_window(parent);
527 set_close_on_deactivate(false);
528 set_close_on_esc(false);
529 set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(),
530 kArrowOffset + anchor_offset.x(),
531 kArrowOffset - anchor_offset.y(),
532 kArrowOffset - anchor_offset.x()));
533 set_border_accepts_events(border_accepts_events);
534 set_shadow(SupportsShadow() ? views::BubbleBorder::BIG_SHADOW
535 : views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER);
537 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
538 tracked_objects::ScopedTracker tracking_profile2_1(
539 FROM_HERE_WITH_EXPLICIT_FUNCTION(
540 "431326 AppListView::InitAsBubbleInternal2_1"));
542 // This creates the app list widget. (Before this, child widgets cannot be
543 // created.)
544 views::BubbleDelegateView::CreateBubble(this);
546 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
547 tracked_objects::ScopedTracker tracking_profile2_11(
548 FROM_HERE_WITH_EXPLICIT_FUNCTION(
549 "431326 AppListView::InitAsBubbleInternal2_11"));
551 SetBubbleArrow(arrow);
553 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
554 tracked_objects::ScopedTracker tracking_profile2_2(
555 FROM_HERE_WITH_EXPLICIT_FUNCTION(
556 "431326 AppListView::InitAsBubbleInternal2_2"));
558 // We can now create the internal widgets.
559 InitChildWidgets();
561 #if defined(USE_AURA)
562 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
563 tracked_objects::ScopedTracker tracking_profile3(
564 FROM_HERE_WITH_EXPLICIT_FUNCTION(
565 "431326 AppListView::InitAsBubbleInternal3"));
567 aura::Window* window = GetWidget()->GetNativeWindow();
568 window->layer()->SetMasksToBounds(true);
569 GetBubbleFrameView()->set_background(new AppListBackground(
570 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius()));
571 set_background(NULL);
572 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
573 new views::BubbleWindowTargeter(this)));
574 #else
575 set_background(new AppListBackground(
576 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius()));
578 // On non-aura the bubble has two widgets, and it's possible for the border
579 // to be shown independently in odd situations. Explicitly hide the bubble
580 // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the
581 // window manager do not have the SWP_SHOWWINDOW flag set which would cause
582 // the border to be shown. See http://crbug.com/231687 .
583 GetWidget()->Hide();
584 #endif
586 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
587 tracked_objects::ScopedTracker tracking_profile4(
588 FROM_HERE_WITH_EXPLICIT_FUNCTION(
589 "431326 AppListView::InitAsBubbleInternal4"));
591 // On platforms that don't support a shadow, the rounded border of the app
592 // list is constructed _inside_ the view, so a rectangular background goes
593 // over the border in the rounded corners. To fix this, give the background a
594 // corner radius 1px smaller than the outer border, so it just reaches but
595 // doesn't cover it.
596 const int kOverlayCornerRadius =
597 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
598 overlay_view_ =
599 new AppListOverlayView(kOverlayCornerRadius - (SupportsShadow() ? 0 : 1));
600 overlay_view_->SetBoundsRect(GetContentsBounds());
601 AddChildView(overlay_view_);
603 if (delegate_)
604 delegate_->ViewInitialized();
606 UMA_HISTOGRAM_TIMES("Apps.AppListCreationTime",
607 base::Time::Now() - start_time);
610 void AppListView::OnBeforeBubbleWidgetInit(
611 views::Widget::InitParams* params,
612 views::Widget* widget) const {
613 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
614 if (delegate_ && delegate_->ForceNativeDesktop())
615 params->native_widget = new views::DesktopNativeWidgetAura(widget);
616 #endif
617 #if defined(OS_WIN)
618 // Windows 7 and higher offer pinning to the taskbar, but we need presence
619 // on the taskbar for the user to be able to pin us. So, show the window on
620 // the taskbar for these versions of Windows.
621 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
622 params->force_show_in_taskbar = true;
623 #elif defined(OS_LINUX)
624 // Set up a custom WM_CLASS for the app launcher window. This allows task
625 // switchers in X11 environments to distinguish it from main browser windows.
626 params->wm_class_name = kAppListWMClass;
627 // Show the window in the taskbar, even though it is a bubble, which would not
628 // normally be shown.
629 params->force_show_in_taskbar = true;
630 #endif
633 views::View* AppListView::GetInitiallyFocusedView() {
634 return app_list_main_view_->search_box_view()->search_box();
637 gfx::ImageSkia AppListView::GetWindowIcon() {
638 if (delegate_)
639 return delegate_->GetWindowIcon();
641 return gfx::ImageSkia();
644 bool AppListView::WidgetHasHitTestMask() const {
645 return GetBubbleFrameView() != nullptr;
648 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const {
649 DCHECK(mask);
650 DCHECK(GetBubbleFrameView());
652 mask->addRect(gfx::RectToSkRect(
653 GetBubbleFrameView()->GetContentsBounds()));
656 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
657 // The accelerator is added by BubbleDelegateView.
658 if (accelerator.key_code() == ui::VKEY_ESCAPE) {
659 if (switches::IsExperimentalAppListEnabled()) {
660 // If the ContentsView does not handle the back action, then this is the
661 // top level, so we close the app list.
662 if (!app_list_main_view_->contents_view()->Back()) {
663 GetWidget()->Deactivate();
664 Close();
666 return true;
669 if (app_list_main_view_->search_box_view()->HasSearch()) {
670 app_list_main_view_->search_box_view()->ClearSearch();
671 } else if (app_list_main_view_->contents_view()
672 ->apps_container_view()
673 ->IsInFolderView()) {
674 app_list_main_view_->contents_view()
675 ->apps_container_view()
676 ->app_list_folder_view()
677 ->CloseFolderPage();
678 return true;
679 } else {
680 GetWidget()->Deactivate();
681 Close();
683 return true;
686 return false;
689 void AppListView::Layout() {
690 const gfx::Rect contents_bounds = GetContentsBounds();
692 // Make sure to layout |app_list_main_view_| and |speech_view_| at the center
693 // of the widget.
694 gfx::Rect centered_bounds = contents_bounds;
695 centered_bounds.ClampToCenteredSize(gfx::Size(
696 app_list_main_view_->contents_view()->GetDefaultContentsBounds().width(),
697 contents_bounds.height()));
699 app_list_main_view_->SetBoundsRect(centered_bounds);
701 if (speech_view_) {
702 gfx::Rect speech_bounds = centered_bounds;
703 int preferred_height = speech_view_->GetPreferredSize().height();
704 speech_bounds.Inset(kSpeechUIMargin, kSpeechUIMargin);
705 speech_bounds.set_height(std::min(speech_bounds.height(),
706 preferred_height));
707 speech_bounds.Inset(-speech_view_->GetInsets());
708 speech_view_->SetBoundsRect(speech_bounds);
712 void AppListView::SchedulePaintInRect(const gfx::Rect& rect) {
713 BubbleDelegateView::SchedulePaintInRect(rect);
714 if (GetBubbleFrameView())
715 GetBubbleFrameView()->SchedulePaint();
718 void AppListView::OnWidgetDestroying(views::Widget* widget) {
719 BubbleDelegateView::OnWidgetDestroying(widget);
720 if (delegate_ && widget == GetWidget())
721 delegate_->ViewClosing();
724 void AppListView::OnWidgetActivationChanged(views::Widget* widget,
725 bool active) {
726 // Do not called inherited function as the bubble delegate auto close
727 // functionality is not used.
728 if (widget == GetWidget())
729 FOR_EACH_OBSERVER(AppListViewObserver, observers_,
730 OnActivationChanged(widget, active));
733 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
734 bool visible) {
735 BubbleDelegateView::OnWidgetVisibilityChanged(widget, visible);
737 if (widget != GetWidget())
738 return;
740 if (!visible)
741 app_list_main_view_->ResetForShow();
744 void AppListView::OnSpeechRecognitionStateChanged(
745 SpeechRecognitionState new_state) {
746 if (!speech_view_)
747 return;
749 bool will_appear = (new_state == SPEECH_RECOGNITION_RECOGNIZING ||
750 new_state == SPEECH_RECOGNITION_IN_SPEECH ||
751 new_state == SPEECH_RECOGNITION_NETWORK_ERROR);
752 // No change for this class.
753 if (speech_view_->visible() == will_appear)
754 return;
756 if (will_appear)
757 speech_view_->Reset();
759 animation_observer_->set_frame(GetBubbleFrameView());
760 gfx::Transform speech_transform;
761 speech_transform.Translate(
762 0, SkFloatToMScalar(kSpeechUIAppearingPosition));
763 if (will_appear)
764 speech_view_->layer()->SetTransform(speech_transform);
767 ui::ScopedLayerAnimationSettings main_settings(
768 app_list_main_view_->layer()->GetAnimator());
769 if (will_appear) {
770 animation_observer_->SetTarget(app_list_main_view_);
771 main_settings.AddObserver(animation_observer_.get());
773 app_list_main_view_->layer()->SetOpacity(will_appear ? 0.0f : 1.0f);
777 ui::ScopedLayerAnimationSettings search_box_settings(
778 search_box_widget_->GetLayer()->GetAnimator());
779 search_box_widget_->GetLayer()->SetOpacity(will_appear ? 0.0f : 1.0f);
783 ui::ScopedLayerAnimationSettings speech_settings(
784 speech_view_->layer()->GetAnimator());
785 if (!will_appear) {
786 animation_observer_->SetTarget(speech_view_);
787 speech_settings.AddObserver(animation_observer_.get());
790 speech_view_->layer()->SetOpacity(will_appear ? 1.0f : 0.0f);
791 if (will_appear)
792 speech_view_->layer()->SetTransform(gfx::Transform());
793 else
794 speech_view_->layer()->SetTransform(speech_transform);
797 // Prevent the search box from receiving events when hidden.
798 search_box_view_->SetEnabled(!will_appear);
800 if (will_appear) {
801 speech_view_->SetVisible(true);
802 } else {
803 app_list_main_view_->SetVisible(true);
804 search_box_view_->search_box()->RequestFocus();
808 } // namespace app_list