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"
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/custom_launcher_page_view.h"
26 #include "ui/app_list/views/search_box_view.h"
27 #include "ui/app_list/views/speech_view.h"
28 #include "ui/app_list/views/start_page_view.h"
29 #include "ui/base/ui_base_switches.h"
30 #include "ui/compositor/layer.h"
31 #include "ui/compositor/layer_animation_observer.h"
32 #include "ui/compositor/scoped_layer_animation_settings.h"
33 #include "ui/gfx/canvas.h"
34 #include "ui/gfx/geometry/insets.h"
35 #include "ui/gfx/image/image_skia.h"
36 #include "ui/gfx/path.h"
37 #include "ui/gfx/skia_util.h"
38 #include "ui/resources/grit/ui_resources.h"
39 #include "ui/views/bubble/bubble_frame_view.h"
40 #include "ui/views/controls/image_view.h"
41 #include "ui/views/controls/textfield/textfield.h"
42 #include "ui/views/layout/fill_layout.h"
43 #include "ui/views/widget/widget.h"
46 #include "ui/aura/window.h"
47 #include "ui/aura/window_tree_host.h"
48 #include "ui/views/bubble/bubble_window_targeter.h"
49 #include "ui/wm/core/masked_window_targeter.h"
51 #include "ui/base/win/shell.h"
53 #if !defined(OS_CHROMEOS)
54 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
56 #endif // defined(USE_AURA)
62 // The margin from the edge to the speech UI.
63 const int kSpeechUIMargin
= 12;
65 // The vertical position for the appearing animation of the speech UI.
66 const float kSpeechUIAppearingPosition
= 12;
68 // The distance between the arrow tip and edge of the anchor view.
69 const int kArrowOffset
= 10;
71 // Determines whether the current environment supports shadows bubble borders.
72 bool SupportsShadow() {
74 // Shadows are not supported on Windows without Aero Glass.
75 if (!ui::win::IsAeroGlassEnabled() ||
76 base::CommandLine::ForCurrentProcess()->HasSwitch(
77 ::switches::kDisableDwmComposition
)) {
80 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
81 // Shadows are not supported on (non-ChromeOS) Linux.
87 // This view forwards the focus to the search box widget by providing it as a
88 // FocusTraversable when a focus search is provided.
89 class SearchBoxFocusHost
: public views::View
{
91 explicit SearchBoxFocusHost(views::Widget
* search_box_widget
)
92 : search_box_widget_(search_box_widget
) {}
94 ~SearchBoxFocusHost() override
{}
96 views::FocusTraversable
* GetFocusTraversable() override
{
97 return search_box_widget_
;
101 views::Widget
* search_box_widget_
;
103 DISALLOW_COPY_AND_ASSIGN(SearchBoxFocusHost
);
106 // The view for the App List overlay, which appears as a white rounded
107 // rectangle with the given radius.
108 class AppListOverlayView
: public views::View
{
110 explicit AppListOverlayView(int corner_radius
)
111 : corner_radius_(corner_radius
) {
112 SetPaintToLayer(true);
114 layer()->SetOpacity(0.0f
);
117 ~AppListOverlayView() override
{}
119 // Overridden from views::View:
120 void OnPaint(gfx::Canvas
* canvas
) override
{
122 paint
.setStyle(SkPaint::kFill_Style
);
123 paint
.setColor(SK_ColorWHITE
);
124 canvas
->DrawRoundRect(GetContentsBounds(), corner_radius_
, paint
);
128 const int corner_radius_
;
130 DISALLOW_COPY_AND_ASSIGN(AppListOverlayView
);
133 #if defined(USE_AURA)
134 // An event targeter for the search box widget which will ignore events that
135 // are on the search box's shadow.
136 class SearchBoxWindowTargeter
: public wm::MaskedWindowTargeter
{
138 explicit SearchBoxWindowTargeter(views::View
* search_box
)
139 : wm::MaskedWindowTargeter(search_box
->GetWidget()->GetNativeWindow()),
140 search_box_(search_box
) {}
141 ~SearchBoxWindowTargeter() override
{}
144 // wm::MaskedWindowTargeter:
145 bool GetHitTestMask(aura::Window
* window
, gfx::Path
* mask
) const override
{
146 mask
->addRect(gfx::RectToSkRect(search_box_
->GetContentsBounds()));
150 views::View
* search_box_
;
152 DISALLOW_COPY_AND_ASSIGN(SearchBoxWindowTargeter
);
158 // An animation observer to hide the view at the end of the animation.
159 class HideViewAnimationObserver
: public ui::ImplicitAnimationObserver
{
161 HideViewAnimationObserver()
166 ~HideViewAnimationObserver() override
{
168 StopObservingImplicitAnimations();
171 void SetTarget(views::View
* target
) {
173 StopObservingImplicitAnimations();
177 void set_frame(views::BubbleFrameView
* frame
) { frame_
= frame
; }
180 // Overridden from ui::ImplicitAnimationObserver:
181 void OnImplicitAnimationsCompleted() override
{
183 target_
->SetVisible(false);
186 // Should update the background by invoking SchedulePaint().
188 frame_
->SchedulePaint();
192 views::BubbleFrameView
* frame_
;
193 views::View
* target_
;
195 DISALLOW_COPY_AND_ASSIGN(HideViewAnimationObserver
);
198 ////////////////////////////////////////////////////////////////////////////////
201 AppListView::AppListView(AppListViewDelegate
* delegate
)
202 : delegate_(delegate
),
203 app_list_main_view_(nullptr),
204 speech_view_(nullptr),
205 search_box_focus_host_(nullptr),
206 search_box_widget_(nullptr),
207 search_box_view_(nullptr),
208 overlay_view_(nullptr),
209 animation_observer_(new HideViewAnimationObserver()) {
212 delegate_
->AddObserver(this);
213 delegate_
->GetSpeechUI()->AddObserver(this);
216 AppListView::~AppListView() {
217 delegate_
->GetSpeechUI()->RemoveObserver(this);
218 delegate_
->RemoveObserver(this);
219 animation_observer_
.reset();
220 // Remove child views first to ensure no remaining dependencies on delegate_.
221 RemoveAllChildViews(true);
224 void AppListView::InitAsBubbleAttachedToAnchor(
225 gfx::NativeView parent
,
226 int initial_apps_page
,
228 const gfx::Vector2d
& anchor_offset
,
229 views::BubbleBorder::Arrow arrow
,
230 bool border_accepts_events
) {
231 SetAnchorView(anchor
);
232 InitAsBubbleInternal(
233 parent
, initial_apps_page
, arrow
, border_accepts_events
, anchor_offset
);
236 void AppListView::InitAsBubbleAtFixedLocation(
237 gfx::NativeView parent
,
238 int initial_apps_page
,
239 const gfx::Point
& anchor_point_in_screen
,
240 views::BubbleBorder::Arrow arrow
,
241 bool border_accepts_events
) {
243 SetAnchorRect(gfx::Rect(anchor_point_in_screen
, gfx::Size()));
244 InitAsBubbleInternal(
245 parent
, initial_apps_page
, arrow
, border_accepts_events
, gfx::Vector2d());
248 void AppListView::InitAsFramelessWindow(gfx::NativeView parent
,
249 int initial_apps_page
,
251 InitContents(parent
, initial_apps_page
);
252 overlay_view_
= new AppListOverlayView(0 /* no corners */);
253 AddChildView(overlay_view_
);
255 views::Widget
* widget
= new views::Widget();
256 views::Widget::InitParams
params(
257 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
258 params
.parent
= parent
;
259 params
.delegate
= this;
260 widget
->Init(params
);
261 widget
->SetBounds(bounds
);
262 // This needs to be set *after* Widget::Init() because BubbleDelegateView sets
263 // its own background at OnNativeThemeChanged(), which is called in
264 // View::AddChildView() which is called at Widget::SetContentsView() to build
265 // the views hierarchy in the widget.
266 set_background(new AppListBackground(0));
271 void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow
) {
272 GetBubbleFrameView()->bubble_border()->set_arrow(arrow
);
273 SizeToContents(); // Recalcuates with new border.
274 GetBubbleFrameView()->SchedulePaint();
277 void AppListView::SetAnchorPoint(const gfx::Point
& anchor_point
) {
278 SetAnchorRect(gfx::Rect(anchor_point
, gfx::Size()));
281 void AppListView::SetDragAndDropHostOfCurrentAppList(
282 ApplicationDragAndDropHost
* drag_and_drop_host
) {
283 app_list_main_view_
->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host
);
286 void AppListView::ShowWhenReady() {
287 app_list_main_view_
->ShowAppListWhenReady();
290 void AppListView::Close() {
291 app_list_main_view_
->Close();
292 delegate_
->Dismiss();
295 void AppListView::UpdateBounds() {
299 void AppListView::SetAppListOverlayVisible(bool visible
) {
300 DCHECK(overlay_view_
);
302 // Display the overlay immediately so we can begin the animation.
303 overlay_view_
->SetVisible(true);
305 ui::ScopedLayerAnimationSettings
settings(
306 overlay_view_
->layer()->GetAnimator());
307 settings
.SetTweenType(gfx::Tween::LINEAR
);
309 // If we're dismissing the overlay, hide the view at the end of the animation.
311 // Since only one animation is visible at a time, it's safe to re-use
312 // animation_observer_ here.
313 animation_observer_
->set_frame(NULL
);
314 animation_observer_
->SetTarget(overlay_view_
);
315 settings
.AddObserver(animation_observer_
.get());
318 const float kOverlayFadeInMilliseconds
= 125;
319 settings
.SetTransitionDuration(
320 base::TimeDelta::FromMilliseconds(kOverlayFadeInMilliseconds
));
322 const float kOverlayOpacity
= 0.75f
;
323 overlay_view_
->layer()->SetOpacity(visible
? kOverlayOpacity
: 0.0f
);
324 // Create the illusion that the search box is hidden behind the app list
325 // overlay mask by setting its opacity to the same value, and disabling it.
327 ui::ScopedLayerAnimationSettings
settings(
328 search_box_widget_
->GetLayer()->GetAnimator());
329 const float kSearchBoxWidgetOpacity
= 0.5f
;
330 search_box_widget_
->GetLayer()->SetOpacity(visible
? kSearchBoxWidgetOpacity
332 search_box_view_
->SetEnabled(!visible
);
334 search_box_view_
->search_box()->RequestFocus();
338 bool AppListView::ShouldCenterWindow() const {
339 return delegate_
->ShouldCenterWindow();
342 gfx::Size
AppListView::GetPreferredSize() const {
343 return app_list_main_view_
->GetPreferredSize();
346 void AppListView::OnPaint(gfx::Canvas
* canvas
) {
347 views::BubbleDelegateView::OnPaint(canvas
);
348 if (!next_paint_callback_
.is_null()) {
349 next_paint_callback_
.Run();
350 next_paint_callback_
.Reset();
354 void AppListView::OnThemeChanged() {
356 GetWidget()->Close();
360 bool AppListView::ShouldHandleSystemCommands() const {
364 bool AppListView::ShouldDescendIntoChildForEventHandling(
365 gfx::NativeView child
,
366 const gfx::Point
& location
) {
367 // While on the start page, don't descend into the custom launcher page. Since
368 // the only valid action is to open it.
369 ContentsView
* contents_view
= app_list_main_view_
->contents_view();
370 if (contents_view
->custom_page_view() &&
371 contents_view
->GetActiveState() == AppListModel::STATE_START
)
372 return !contents_view
->custom_page_view()
373 ->GetCollapsedLauncherPageBounds()
376 return views::BubbleDelegateView::ShouldDescendIntoChildForEventHandling(
380 void AppListView::Prerender() {
381 app_list_main_view_
->Prerender();
384 void AppListView::OnProfilesChanged() {
385 app_list_main_view_
->search_box_view()->InvalidateMenu();
388 void AppListView::OnShutdown() {
389 // Nothing to do on views - the widget will soon be closed, which will tear
393 void AppListView::SetProfileByPath(const base::FilePath
& profile_path
) {
394 delegate_
->SetProfileByPath(profile_path
);
395 app_list_main_view_
->ModelChanged();
398 void AppListView::AddObserver(AppListViewObserver
* observer
) {
399 observers_
.AddObserver(observer
);
402 void AppListView::RemoveObserver(AppListViewObserver
* observer
) {
403 observers_
.RemoveObserver(observer
);
407 void AppListView::SetNextPaintCallback(const base::Closure
& callback
) {
408 next_paint_callback_
= callback
;
412 HWND
AppListView::GetHWND() const {
413 gfx::NativeWindow window
=
414 GetWidget()->GetTopLevelWidget()->GetNativeWindow();
415 return window
->GetHost()->GetAcceleratedWidget();
419 PaginationModel
* AppListView::GetAppsPaginationModel() {
420 return app_list_main_view_
->contents_view()
421 ->apps_container_view()
423 ->pagination_model();
426 void AppListView::InitContents(gfx::NativeView parent
, int initial_apps_page
) {
427 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
428 // crbug.com/441028 are fixed.
429 tracked_objects::ScopedTracker
tracking_profile(
430 FROM_HERE_WITH_EXPLICIT_FUNCTION(
431 "440224, 441028 AppListView::InitContents"));
433 app_list_main_view_
= new AppListMainView(delegate_
);
434 AddChildView(app_list_main_view_
);
435 app_list_main_view_
->SetPaintToLayer(true);
436 app_list_main_view_
->SetFillsBoundsOpaquely(false);
437 app_list_main_view_
->layer()->SetMasksToBounds(true);
439 // This will be added to the |search_box_widget_| after the app list widget is
441 search_box_view_
= new SearchBoxView(app_list_main_view_
, delegate_
);
442 search_box_view_
->SetPaintToLayer(true);
443 search_box_view_
->SetFillsBoundsOpaquely(false);
444 search_box_view_
->layer()->SetMasksToBounds(true);
446 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
447 // crbug.com/441028 are fixed.
448 tracked_objects::ScopedTracker
tracking_profile1(
449 FROM_HERE_WITH_EXPLICIT_FUNCTION(
450 "440224, 441028 AppListView::InitContents1"));
452 app_list_main_view_
->Init(parent
, initial_apps_page
, search_box_view_
);
454 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
455 // crbug.com/441028 are fixed.
456 tracked_objects::ScopedTracker
tracking_profile2(
457 FROM_HERE_WITH_EXPLICIT_FUNCTION(
458 "440224, 441028 AppListView::InitContents2"));
460 // Speech recognition is available only when the start page exists.
461 if (delegate_
&& delegate_
->IsSpeechRecognitionEnabled()) {
462 speech_view_
= new SpeechView(delegate_
);
463 speech_view_
->SetVisible(false);
464 speech_view_
->SetPaintToLayer(true);
465 speech_view_
->SetFillsBoundsOpaquely(false);
466 speech_view_
->layer()->SetOpacity(0.0f
);
467 AddChildView(speech_view_
);
473 void AppListView::InitChildWidgets() {
474 DCHECK(search_box_view_
);
476 // Create the search box widget.
477 views::Widget::InitParams
search_box_widget_params(
478 views::Widget::InitParams::TYPE_CONTROL
);
479 search_box_widget_params
.parent
= GetWidget()->GetNativeView();
480 search_box_widget_params
.opacity
=
481 views::Widget::InitParams::TRANSLUCENT_WINDOW
;
483 // Create a widget for the SearchBoxView to live in. This allows the
484 // SearchBoxView to be on top of the custom launcher page's WebContents
485 // (otherwise the search box events will be captured by the WebContents).
486 search_box_widget_
= new views::Widget
;
487 search_box_widget_
->Init(search_box_widget_params
);
488 search_box_widget_
->SetContentsView(search_box_view_
);
490 // The search box will not naturally receive focus by itself (because it is in
491 // a separate widget). Create this SearchBoxFocusHost in the main widget to
492 // forward the focus search into to the search box.
493 search_box_focus_host_
= new SearchBoxFocusHost(search_box_widget_
);
494 AddChildView(search_box_focus_host_
);
495 search_box_widget_
->SetFocusTraversableParentView(search_box_focus_host_
);
496 search_box_widget_
->SetFocusTraversableParent(
497 GetWidget()->GetFocusTraversable());
499 #if defined(USE_AURA)
500 // Mouse events on the search box shadow should not be captured.
501 aura::Window
* window
= search_box_widget_
->GetNativeWindow();
502 window
->SetEventTargeter(scoped_ptr
<ui::EventTargeter
>(
503 new SearchBoxWindowTargeter(search_box_view_
)));
506 app_list_main_view_
->contents_view()->Layout();
509 void AppListView::InitAsBubbleInternal(gfx::NativeView parent
,
510 int initial_apps_page
,
511 views::BubbleBorder::Arrow arrow
,
512 bool border_accepts_events
,
513 const gfx::Vector2d
& anchor_offset
) {
514 base::Time start_time
= base::Time::Now();
516 InitContents(parent
, initial_apps_page
);
518 set_color(kContentsBackgroundColor
);
519 set_margins(gfx::Insets());
520 set_parent_window(parent
);
521 set_close_on_deactivate(false);
522 set_close_on_esc(false);
523 set_anchor_view_insets(gfx::Insets(kArrowOffset
+ anchor_offset
.y(),
524 kArrowOffset
+ anchor_offset
.x(),
525 kArrowOffset
- anchor_offset
.y(),
526 kArrowOffset
- anchor_offset
.x()));
527 set_border_accepts_events(border_accepts_events
);
528 set_shadow(SupportsShadow() ? views::BubbleBorder::BIG_SHADOW
529 : views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER
);
532 // TODO(tapted): Remove ScopedTracker below once crbug.com/431326 is fixed.
533 tracked_objects::ScopedTracker
tracking_profile(
534 FROM_HERE_WITH_EXPLICIT_FUNCTION(
535 "431326 views::BubbleDelegateView::CreateBubble()"));
537 // This creates the app list widget. (Before this, child widgets cannot be
539 views::BubbleDelegateView::CreateBubble(this);
542 SetBubbleArrow(arrow
);
544 // We can now create the internal widgets.
547 #if defined(USE_AURA)
548 aura::Window
* window
= GetWidget()->GetNativeWindow();
549 window
->layer()->SetMasksToBounds(true);
550 GetBubbleFrameView()->set_background(new AppListBackground(
551 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius()));
552 set_background(NULL
);
553 window
->SetEventTargeter(scoped_ptr
<ui::EventTargeter
>(
554 new views::BubbleWindowTargeter(this)));
556 set_background(new AppListBackground(
557 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius()));
559 // On non-aura the bubble has two widgets, and it's possible for the border
560 // to be shown independently in odd situations. Explicitly hide the bubble
561 // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the
562 // window manager do not have the SWP_SHOWWINDOW flag set which would cause
563 // the border to be shown. See http://crbug.com/231687 .
567 // On platforms that don't support a shadow, the rounded border of the app
568 // list is constructed _inside_ the view, so a rectangular background goes
569 // over the border in the rounded corners. To fix this, give the background a
570 // corner radius 1px smaller than the outer border, so it just reaches but
572 const int kOverlayCornerRadius
=
573 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
575 new AppListOverlayView(kOverlayCornerRadius
- (SupportsShadow() ? 0 : 1));
576 overlay_view_
->SetBoundsRect(GetContentsBounds());
577 AddChildView(overlay_view_
);
580 delegate_
->ViewInitialized();
582 UMA_HISTOGRAM_TIMES("Apps.AppListCreationTime",
583 base::Time::Now() - start_time
);
586 void AppListView::OnBeforeBubbleWidgetInit(
587 views::Widget::InitParams
* params
,
588 views::Widget
* widget
) const {
589 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
590 if (delegate_
&& delegate_
->ForceNativeDesktop())
591 params
->native_widget
= new views::DesktopNativeWidgetAura(widget
);
594 // Windows 7 and higher offer pinning to the taskbar, but we need presence
595 // on the taskbar for the user to be able to pin us. So, show the window on
596 // the taskbar for these versions of Windows.
597 if (base::win::GetVersion() >= base::win::VERSION_WIN7
)
598 params
->force_show_in_taskbar
= true;
599 #elif defined(OS_LINUX)
600 // Set up a custom WM_CLASS for the app launcher window. This allows task
601 // switchers in X11 environments to distinguish it from main browser windows.
602 params
->wm_class_name
= kAppListWMClass
;
603 // Show the window in the taskbar, even though it is a bubble, which would not
604 // normally be shown.
605 params
->force_show_in_taskbar
= true;
609 views::View
* AppListView::GetInitiallyFocusedView() {
610 return app_list_main_view_
->search_box_view()->search_box();
613 gfx::ImageSkia
AppListView::GetWindowIcon() {
615 return delegate_
->GetWindowIcon();
617 return gfx::ImageSkia();
620 bool AppListView::WidgetHasHitTestMask() const {
621 return GetBubbleFrameView() != nullptr;
624 void AppListView::GetWidgetHitTestMask(gfx::Path
* mask
) const {
626 DCHECK(GetBubbleFrameView());
628 mask
->addRect(gfx::RectToSkRect(
629 GetBubbleFrameView()->GetContentsBounds()));
632 bool AppListView::AcceleratorPressed(const ui::Accelerator
& accelerator
) {
633 // The accelerator is added by BubbleDelegateView.
634 if (accelerator
.key_code() == ui::VKEY_ESCAPE
) {
635 if (switches::IsExperimentalAppListEnabled()) {
636 // If the ContentsView does not handle the back action, then this is the
637 // top level, so we close the app list.
638 if (!app_list_main_view_
->contents_view()->Back()) {
639 GetWidget()->Deactivate();
645 if (app_list_main_view_
->search_box_view()->HasSearch()) {
646 app_list_main_view_
->search_box_view()->ClearSearch();
647 } else if (app_list_main_view_
->contents_view()
648 ->apps_container_view()
649 ->IsInFolderView()) {
650 app_list_main_view_
->contents_view()
651 ->apps_container_view()
652 ->app_list_folder_view()
656 GetWidget()->Deactivate();
665 void AppListView::Layout() {
666 const gfx::Rect contents_bounds
= GetContentsBounds();
668 // Make sure to layout |app_list_main_view_| and |speech_view_| at the center
670 gfx::Rect centered_bounds
= contents_bounds
;
671 centered_bounds
.ClampToCenteredSize(gfx::Size(
672 app_list_main_view_
->contents_view()->GetDefaultContentsBounds().width(),
673 contents_bounds
.height()));
675 app_list_main_view_
->SetBoundsRect(centered_bounds
);
678 gfx::Rect speech_bounds
= centered_bounds
;
679 int preferred_height
= speech_view_
->GetPreferredSize().height();
680 speech_bounds
.Inset(kSpeechUIMargin
, kSpeechUIMargin
);
681 speech_bounds
.set_height(std::min(speech_bounds
.height(),
683 speech_bounds
.Inset(-speech_view_
->GetInsets());
684 speech_view_
->SetBoundsRect(speech_bounds
);
688 void AppListView::SchedulePaintInRect(const gfx::Rect
& rect
) {
689 BubbleDelegateView::SchedulePaintInRect(rect
);
690 if (GetBubbleFrameView())
691 GetBubbleFrameView()->SchedulePaint();
694 void AppListView::OnWidgetDestroying(views::Widget
* widget
) {
695 BubbleDelegateView::OnWidgetDestroying(widget
);
696 if (delegate_
&& widget
== GetWidget())
697 delegate_
->ViewClosing();
700 void AppListView::OnWidgetActivationChanged(views::Widget
* widget
,
702 // Do not called inherited function as the bubble delegate auto close
703 // functionality is not used.
704 if (widget
== GetWidget())
705 FOR_EACH_OBSERVER(AppListViewObserver
, observers_
,
706 OnActivationChanged(widget
, active
));
709 void AppListView::OnWidgetVisibilityChanged(views::Widget
* widget
,
711 BubbleDelegateView::OnWidgetVisibilityChanged(widget
, visible
);
713 if (widget
!= GetWidget())
717 app_list_main_view_
->ResetForShow();
720 void AppListView::OnSpeechRecognitionStateChanged(
721 SpeechRecognitionState new_state
) {
725 bool will_appear
= (new_state
== SPEECH_RECOGNITION_RECOGNIZING
||
726 new_state
== SPEECH_RECOGNITION_IN_SPEECH
||
727 new_state
== SPEECH_RECOGNITION_NETWORK_ERROR
);
728 // No change for this class.
729 if (speech_view_
->visible() == will_appear
)
733 speech_view_
->Reset();
735 animation_observer_
->set_frame(GetBubbleFrameView());
736 gfx::Transform speech_transform
;
737 speech_transform
.Translate(
738 0, SkFloatToMScalar(kSpeechUIAppearingPosition
));
740 speech_view_
->layer()->SetTransform(speech_transform
);
743 ui::ScopedLayerAnimationSettings
main_settings(
744 app_list_main_view_
->layer()->GetAnimator());
746 animation_observer_
->SetTarget(app_list_main_view_
);
747 main_settings
.AddObserver(animation_observer_
.get());
749 app_list_main_view_
->layer()->SetOpacity(will_appear
? 0.0f
: 1.0f
);
753 ui::ScopedLayerAnimationSettings
search_box_settings(
754 search_box_widget_
->GetLayer()->GetAnimator());
755 search_box_widget_
->GetLayer()->SetOpacity(will_appear
? 0.0f
: 1.0f
);
759 ui::ScopedLayerAnimationSettings
speech_settings(
760 speech_view_
->layer()->GetAnimator());
762 animation_observer_
->SetTarget(speech_view_
);
763 speech_settings
.AddObserver(animation_observer_
.get());
766 speech_view_
->layer()->SetOpacity(will_appear
? 1.0f
: 0.0f
);
768 speech_view_
->layer()->SetTransform(gfx::Transform());
770 speech_view_
->layer()->SetTransform(speech_transform
);
773 // Prevent the search box from receiving events when hidden.
774 search_box_view_
->SetEnabled(!will_appear
);
777 speech_view_
->SetVisible(true);
779 app_list_main_view_
->SetVisible(true);
780 // Refocus the search box. However, if the app list widget does not have
781 // focus, it means another window has already taken focus, and we *must not*
782 // focus the search box (or we would steal focus back into the app list).
783 if (GetWidget()->IsActive())
784 search_box_view_
->search_box()->RequestFocus();
788 } // namespace app_list