Workaround for xkbcommon dead keys.
[chromium-blink-merge.git] / ui / app_list / views / app_list_view.cc
blob01058c612bb0a23a21cc4d318c34b1bca386d7cc
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/image/image_skia.h"
34 #include "ui/gfx/insets.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 #if defined(OS_WIN)
49 #include "ui/base/win/shell.h"
50 #endif
51 #if !defined(OS_CHROMEOS)
52 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
53 #endif
54 #endif // defined(USE_AURA)
56 namespace app_list {
58 namespace {
60 // The margin from the edge to the speech UI.
61 const int kSpeechUIMargin = 12;
63 // The vertical position for the appearing animation of the speech UI.
64 const float kSpeechUIAppearingPosition = 12;
66 // The distance between the arrow tip and edge of the anchor view.
67 const int kArrowOffset = 10;
69 // Determines whether the current environment supports shadows bubble borders.
70 bool SupportsShadow() {
71 #if defined(OS_WIN)
72 // Shadows are not supported on Windows without Aero Glass.
73 if (!ui::win::IsAeroGlassEnabled() ||
74 CommandLine::ForCurrentProcess()->HasSwitch(
75 ::switches::kDisableDwmComposition)) {
76 return false;
78 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
79 // Shadows are not supported on (non-ChromeOS) Linux.
80 return false;
81 #endif
82 return true;
85 // The view for the App List overlay, which appears as a white rounded
86 // rectangle with the given radius.
87 class AppListOverlayView : public views::View {
88 public:
89 explicit AppListOverlayView(int corner_radius)
90 : corner_radius_(corner_radius) {
91 SetPaintToLayer(true);
92 SetVisible(false);
93 layer()->SetOpacity(0.0f);
96 ~AppListOverlayView() override {}
98 // Overridden from views::View:
99 void OnPaint(gfx::Canvas* canvas) override {
100 SkPaint paint;
101 paint.setStyle(SkPaint::kFill_Style);
102 paint.setColor(SK_ColorWHITE);
103 canvas->DrawRoundRect(GetContentsBounds(), corner_radius_, paint);
106 private:
107 const int corner_radius_;
109 DISALLOW_COPY_AND_ASSIGN(AppListOverlayView);
112 } // namespace
114 // An animation observer to hide the view at the end of the animation.
115 class HideViewAnimationObserver : public ui::ImplicitAnimationObserver {
116 public:
117 HideViewAnimationObserver()
118 : frame_(NULL),
119 target_(NULL) {
122 ~HideViewAnimationObserver() override {
123 if (target_)
124 StopObservingImplicitAnimations();
127 void SetTarget(views::View* target) {
128 if (target_)
129 StopObservingImplicitAnimations();
130 target_ = target;
133 void set_frame(views::BubbleFrameView* frame) { frame_ = frame; }
135 private:
136 // Overridden from ui::ImplicitAnimationObserver:
137 void OnImplicitAnimationsCompleted() override {
138 if (target_) {
139 target_->SetVisible(false);
140 target_ = NULL;
142 // Should update the background by invoking SchedulePaint().
143 if (frame_)
144 frame_->SchedulePaint();
148 views::BubbleFrameView* frame_;
149 views::View* target_;
151 DISALLOW_COPY_AND_ASSIGN(HideViewAnimationObserver);
154 ////////////////////////////////////////////////////////////////////////////////
155 // AppListView:
157 AppListView::AppListView(AppListViewDelegate* delegate)
158 : delegate_(delegate),
159 app_list_main_view_(nullptr),
160 speech_view_(nullptr),
161 search_box_widget_(nullptr),
162 search_box_view_(nullptr),
163 overlay_view_(nullptr),
164 animation_observer_(new HideViewAnimationObserver()) {
165 CHECK(delegate);
167 delegate_->AddObserver(this);
168 delegate_->GetSpeechUI()->AddObserver(this);
171 AppListView::~AppListView() {
172 delegate_->GetSpeechUI()->RemoveObserver(this);
173 delegate_->RemoveObserver(this);
174 animation_observer_.reset();
175 // Remove child views first to ensure no remaining dependencies on delegate_.
176 RemoveAllChildViews(true);
179 void AppListView::InitAsBubbleAttachedToAnchor(
180 gfx::NativeView parent,
181 int initial_apps_page,
182 views::View* anchor,
183 const gfx::Vector2d& anchor_offset,
184 views::BubbleBorder::Arrow arrow,
185 bool border_accepts_events) {
186 SetAnchorView(anchor);
187 InitAsBubbleInternal(
188 parent, initial_apps_page, arrow, border_accepts_events, anchor_offset);
191 void AppListView::InitAsBubbleAtFixedLocation(
192 gfx::NativeView parent,
193 int initial_apps_page,
194 const gfx::Point& anchor_point_in_screen,
195 views::BubbleBorder::Arrow arrow,
196 bool border_accepts_events) {
197 SetAnchorView(NULL);
198 SetAnchorRect(gfx::Rect(anchor_point_in_screen, gfx::Size()));
199 InitAsBubbleInternal(
200 parent, initial_apps_page, arrow, border_accepts_events, gfx::Vector2d());
203 void AppListView::InitAsFramelessWindow(gfx::NativeView parent,
204 int initial_apps_page,
205 gfx::Rect bounds) {
206 InitContents(parent, initial_apps_page);
207 overlay_view_ = new AppListOverlayView(0 /* no corners */);
208 AddChildView(overlay_view_);
210 views::Widget* widget = new views::Widget();
211 views::Widget::InitParams params(
212 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
213 params.parent = parent;
214 params.delegate = this;
215 widget->Init(params);
216 widget->SetBounds(bounds);
217 // This needs to be set *after* Widget::Init() because BubbleDelegateView sets
218 // its own background at OnNativeThemeChanged(), which is called in
219 // View::AddChildView() which is called at Widget::SetContentsView() to build
220 // the views hierarchy in the widget.
221 set_background(new AppListBackground(0, app_list_main_view_));
223 InitChildWidgets();
226 void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) {
227 GetBubbleFrameView()->bubble_border()->set_arrow(arrow);
228 SizeToContents(); // Recalcuates with new border.
229 GetBubbleFrameView()->SchedulePaint();
232 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
233 SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
236 void AppListView::SetDragAndDropHostOfCurrentAppList(
237 ApplicationDragAndDropHost* drag_and_drop_host) {
238 app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
241 void AppListView::ShowWhenReady() {
242 app_list_main_view_->ShowAppListWhenReady();
245 void AppListView::Close() {
246 app_list_main_view_->Close();
247 delegate_->Dismiss();
250 void AppListView::UpdateBounds() {
251 SizeToContents();
254 void AppListView::SetAppListOverlayVisible(bool visible) {
255 DCHECK(overlay_view_);
257 // Display the overlay immediately so we can begin the animation.
258 overlay_view_->SetVisible(true);
260 ui::ScopedLayerAnimationSettings settings(
261 overlay_view_->layer()->GetAnimator());
262 settings.SetTweenType(gfx::Tween::LINEAR);
264 // If we're dismissing the overlay, hide the view at the end of the animation.
265 if (!visible) {
266 // Since only one animation is visible at a time, it's safe to re-use
267 // animation_observer_ here.
268 animation_observer_->set_frame(NULL);
269 animation_observer_->SetTarget(overlay_view_);
270 settings.AddObserver(animation_observer_.get());
273 const float kOverlayFadeInMilliseconds = 125;
274 settings.SetTransitionDuration(
275 base::TimeDelta::FromMilliseconds(kOverlayFadeInMilliseconds));
277 const float kOverlayOpacity = 0.75f;
278 overlay_view_->layer()->SetOpacity(visible ? kOverlayOpacity : 0.0f);
279 // Create the illusion that the search box is hidden behind the app list
280 // overlay mask by setting its opacity to the same value, and disabling it.
282 ui::ScopedLayerAnimationSettings settings(
283 search_box_widget_->GetLayer()->GetAnimator());
284 const float kSearchBoxWidgetOpacity = 0.5f;
285 search_box_widget_->GetLayer()->SetOpacity(visible ? kSearchBoxWidgetOpacity
286 : 1.0f);
287 search_box_view_->SetEnabled(!visible);
291 bool AppListView::ShouldCenterWindow() const {
292 return delegate_->ShouldCenterWindow();
295 gfx::Size AppListView::GetPreferredSize() const {
296 return app_list_main_view_->GetPreferredSize();
299 void AppListView::Paint(gfx::Canvas* canvas, const views::CullSet& cull_set) {
300 views::BubbleDelegateView::Paint(canvas, cull_set);
301 if (!next_paint_callback_.is_null()) {
302 next_paint_callback_.Run();
303 next_paint_callback_.Reset();
307 void AppListView::OnThemeChanged() {
308 #if defined(OS_WIN)
309 GetWidget()->Close();
310 #endif
313 bool AppListView::ShouldHandleSystemCommands() const {
314 return true;
317 void AppListView::Prerender() {
318 app_list_main_view_->Prerender();
321 void AppListView::OnProfilesChanged() {
322 app_list_main_view_->search_box_view()->InvalidateMenu();
325 void AppListView::OnShutdown() {
326 // Nothing to do on views - the widget will soon be closed, which will tear
327 // everything down.
330 void AppListView::SetProfileByPath(const base::FilePath& profile_path) {
331 delegate_->SetProfileByPath(profile_path);
332 app_list_main_view_->ModelChanged();
335 void AppListView::AddObserver(AppListViewObserver* observer) {
336 observers_.AddObserver(observer);
339 void AppListView::RemoveObserver(AppListViewObserver* observer) {
340 observers_.RemoveObserver(observer);
343 // static
344 void AppListView::SetNextPaintCallback(const base::Closure& callback) {
345 next_paint_callback_ = callback;
348 #if defined(OS_WIN)
349 HWND AppListView::GetHWND() const {
350 gfx::NativeWindow window =
351 GetWidget()->GetTopLevelWidget()->GetNativeWindow();
352 return window->GetHost()->GetAcceleratedWidget();
354 #endif
356 PaginationModel* AppListView::GetAppsPaginationModel() {
357 return app_list_main_view_->contents_view()
358 ->apps_container_view()
359 ->apps_grid_view()
360 ->pagination_model();
363 void AppListView::InitContents(gfx::NativeView parent, int initial_apps_page) {
364 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
365 // crbug.com/441028 are fixed.
366 tracked_objects::ScopedTracker tracking_profile(
367 FROM_HERE_WITH_EXPLICIT_FUNCTION(
368 "440224, 441028 AppListView::InitContents"));
370 app_list_main_view_ = new AppListMainView(delegate_);
371 AddChildView(app_list_main_view_);
372 app_list_main_view_->SetPaintToLayer(true);
373 app_list_main_view_->SetFillsBoundsOpaquely(false);
374 app_list_main_view_->layer()->SetMasksToBounds(true);
376 // This will be added to the |search_box_widget_| after the app list widget is
377 // initialized.
378 search_box_view_ = new SearchBoxView(app_list_main_view_, delegate_);
379 search_box_view_->SetPaintToLayer(true);
380 search_box_view_->SetFillsBoundsOpaquely(false);
381 search_box_view_->layer()->SetMasksToBounds(true);
383 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
384 // crbug.com/441028 are fixed.
385 tracked_objects::ScopedTracker tracking_profile1(
386 FROM_HERE_WITH_EXPLICIT_FUNCTION(
387 "440224, 441028 AppListView::InitContents1"));
389 app_list_main_view_->Init(parent, initial_apps_page, search_box_view_);
391 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440224 and
392 // crbug.com/441028 are fixed.
393 tracked_objects::ScopedTracker tracking_profile2(
394 FROM_HERE_WITH_EXPLICIT_FUNCTION(
395 "440224, 441028 AppListView::InitContents2"));
397 // Speech recognition is available only when the start page exists.
398 if (delegate_ && delegate_->IsSpeechRecognitionEnabled()) {
399 speech_view_ = new SpeechView(delegate_);
400 speech_view_->SetVisible(false);
401 speech_view_->SetPaintToLayer(true);
402 speech_view_->SetFillsBoundsOpaquely(false);
403 speech_view_->layer()->SetOpacity(0.0f);
404 AddChildView(speech_view_);
407 OnProfilesChanged();
410 void AppListView::InitChildWidgets() {
411 DCHECK(search_box_view_);
413 app_list_main_view_->InitWidgets();
415 // Create the search box widget.
416 views::Widget::InitParams search_box_widget_params(
417 views::Widget::InitParams::TYPE_CONTROL);
418 search_box_widget_params.parent = GetWidget()->GetNativeView();
419 search_box_widget_params.opacity =
420 views::Widget::InitParams::TRANSLUCENT_WINDOW;
422 // Create a widget for the SearchBoxView to live in. This allows the
423 // SearchBoxView to be on top of the custom launcher page's WebContents
424 // (otherwise the search box events will be captured by the WebContents).
425 search_box_widget_ = new views::Widget;
426 search_box_widget_->Init(search_box_widget_params);
427 search_box_widget_->SetContentsView(search_box_view_);
429 app_list_main_view_->contents_view()->Layout();
432 void AppListView::InitAsBubbleInternal(gfx::NativeView parent,
433 int initial_apps_page,
434 views::BubbleBorder::Arrow arrow,
435 bool border_accepts_events,
436 const gfx::Vector2d& anchor_offset) {
437 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
438 tracked_objects::ScopedTracker tracking_profile1(
439 FROM_HERE_WITH_EXPLICIT_FUNCTION(
440 "431326 AppListView::InitAsBubbleInternal1"));
442 base::Time start_time = base::Time::Now();
444 InitContents(parent, initial_apps_page);
446 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
447 tracked_objects::ScopedTracker tracking_profile2(
448 FROM_HERE_WITH_EXPLICIT_FUNCTION(
449 "431326 AppListView::InitAsBubbleInternal2"));
451 set_color(kContentsBackgroundColor);
452 set_margins(gfx::Insets());
453 set_parent_window(parent);
454 set_close_on_deactivate(false);
455 set_close_on_esc(false);
456 set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(),
457 kArrowOffset + anchor_offset.x(),
458 kArrowOffset - anchor_offset.y(),
459 kArrowOffset - anchor_offset.x()));
460 set_border_accepts_events(border_accepts_events);
461 set_shadow(SupportsShadow() ? views::BubbleBorder::BIG_SHADOW
462 : views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER);
464 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
465 tracked_objects::ScopedTracker tracking_profile2_1(
466 FROM_HERE_WITH_EXPLICIT_FUNCTION(
467 "431326 AppListView::InitAsBubbleInternal2_1"));
469 // This creates the app list widget. (Before this, child widgets cannot be
470 // created.)
471 views::BubbleDelegateView::CreateBubble(this);
473 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
474 tracked_objects::ScopedTracker tracking_profile2_11(
475 FROM_HERE_WITH_EXPLICIT_FUNCTION(
476 "431326 AppListView::InitAsBubbleInternal2_11"));
478 SetBubbleArrow(arrow);
480 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
481 tracked_objects::ScopedTracker tracking_profile2_2(
482 FROM_HERE_WITH_EXPLICIT_FUNCTION(
483 "431326 AppListView::InitAsBubbleInternal2_2"));
485 // We can now create the internal widgets.
486 InitChildWidgets();
488 #if defined(USE_AURA)
489 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
490 tracked_objects::ScopedTracker tracking_profile3(
491 FROM_HERE_WITH_EXPLICIT_FUNCTION(
492 "431326 AppListView::InitAsBubbleInternal3"));
494 aura::Window* window = GetWidget()->GetNativeWindow();
495 window->layer()->SetMasksToBounds(true);
496 GetBubbleFrameView()->set_background(new AppListBackground(
497 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
498 app_list_main_view_));
499 set_background(NULL);
500 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
501 new views::BubbleWindowTargeter(this)));
502 #else
503 set_background(new AppListBackground(
504 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
505 app_list_main_view_));
507 // On non-aura the bubble has two widgets, and it's possible for the border
508 // to be shown independently in odd situations. Explicitly hide the bubble
509 // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the
510 // window manager do not have the SWP_SHOWWINDOW flag set which would cause
511 // the border to be shown. See http://crbug.com/231687 .
512 GetWidget()->Hide();
513 #endif
515 // TODO(vadimt): Remove ScopedTracker below once crbug.com/431326 is fixed.
516 tracked_objects::ScopedTracker tracking_profile4(
517 FROM_HERE_WITH_EXPLICIT_FUNCTION(
518 "431326 AppListView::InitAsBubbleInternal4"));
520 // On platforms that don't support a shadow, the rounded border of the app
521 // list is constructed _inside_ the view, so a rectangular background goes
522 // over the border in the rounded corners. To fix this, give the background a
523 // corner radius 1px smaller than the outer border, so it just reaches but
524 // doesn't cover it.
525 const int kOverlayCornerRadius =
526 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius();
527 overlay_view_ =
528 new AppListOverlayView(kOverlayCornerRadius - (SupportsShadow() ? 0 : 1));
529 overlay_view_->SetBoundsRect(GetContentsBounds());
530 AddChildView(overlay_view_);
532 if (delegate_)
533 delegate_->ViewInitialized();
535 UMA_HISTOGRAM_TIMES("Apps.AppListCreationTime",
536 base::Time::Now() - start_time);
539 void AppListView::OnBeforeBubbleWidgetInit(
540 views::Widget::InitParams* params,
541 views::Widget* widget) const {
542 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
543 if (delegate_ && delegate_->ForceNativeDesktop())
544 params->native_widget = new views::DesktopNativeWidgetAura(widget);
545 #endif
546 #if defined(OS_WIN)
547 // Windows 7 and higher offer pinning to the taskbar, but we need presence
548 // on the taskbar for the user to be able to pin us. So, show the window on
549 // the taskbar for these versions of Windows.
550 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
551 params->force_show_in_taskbar = true;
552 #elif defined(OS_LINUX)
553 // Set up a custom WM_CLASS for the app launcher window. This allows task
554 // switchers in X11 environments to distinguish it from main browser windows.
555 params->wm_class_name = kAppListWMClass;
556 // Show the window in the taskbar, even though it is a bubble, which would not
557 // normally be shown.
558 params->force_show_in_taskbar = true;
559 #endif
562 views::View* AppListView::GetInitiallyFocusedView() {
563 return app_list_main_view_->search_box_view()->search_box();
566 gfx::ImageSkia AppListView::GetWindowIcon() {
567 if (delegate_)
568 return delegate_->GetWindowIcon();
570 return gfx::ImageSkia();
573 bool AppListView::WidgetHasHitTestMask() const {
574 return GetBubbleFrameView() != nullptr;
577 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const {
578 DCHECK(mask);
579 DCHECK(GetBubbleFrameView());
581 mask->addRect(gfx::RectToSkRect(
582 GetBubbleFrameView()->GetContentsBounds()));
585 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
586 // The accelerator is added by BubbleDelegateView.
587 if (accelerator.key_code() == ui::VKEY_ESCAPE) {
588 if (switches::IsExperimentalAppListEnabled()) {
589 // If the ContentsView does not handle the back action, then this is the
590 // top level, so we close the app list.
591 if (!app_list_main_view_->contents_view()->Back()) {
592 GetWidget()->Deactivate();
593 Close();
595 return true;
598 if (app_list_main_view_->search_box_view()->HasSearch()) {
599 app_list_main_view_->search_box_view()->ClearSearch();
600 } else if (app_list_main_view_->contents_view()
601 ->apps_container_view()
602 ->IsInFolderView()) {
603 app_list_main_view_->contents_view()
604 ->apps_container_view()
605 ->app_list_folder_view()
606 ->CloseFolderPage();
607 return true;
608 } else {
609 GetWidget()->Deactivate();
610 Close();
612 return true;
615 return false;
618 void AppListView::Layout() {
619 const gfx::Rect contents_bounds = GetContentsBounds();
621 // Make sure to layout |app_list_main_view_| and |speech_view_| at the center
622 // of the widget.
623 gfx::Rect centered_bounds = contents_bounds;
624 centered_bounds.ClampToCenteredSize(gfx::Size(
625 app_list_main_view_->contents_view()->GetDefaultContentsBounds().width(),
626 contents_bounds.height()));
628 app_list_main_view_->SetBoundsRect(centered_bounds);
630 if (speech_view_) {
631 gfx::Rect speech_bounds = centered_bounds;
632 int preferred_height = speech_view_->GetPreferredSize().height();
633 speech_bounds.Inset(kSpeechUIMargin, kSpeechUIMargin);
634 speech_bounds.set_height(std::min(speech_bounds.height(),
635 preferred_height));
636 speech_bounds.Inset(-speech_view_->GetInsets());
637 speech_view_->SetBoundsRect(speech_bounds);
641 void AppListView::SchedulePaintInRect(const gfx::Rect& rect) {
642 BubbleDelegateView::SchedulePaintInRect(rect);
643 if (GetBubbleFrameView())
644 GetBubbleFrameView()->SchedulePaint();
647 void AppListView::OnWidgetDestroying(views::Widget* widget) {
648 BubbleDelegateView::OnWidgetDestroying(widget);
649 if (delegate_ && widget == GetWidget())
650 delegate_->ViewClosing();
653 void AppListView::OnWidgetActivationChanged(views::Widget* widget,
654 bool active) {
655 // Do not called inherited function as the bubble delegate auto close
656 // functionality is not used.
657 if (widget == GetWidget())
658 FOR_EACH_OBSERVER(AppListViewObserver, observers_,
659 OnActivationChanged(widget, active));
662 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
663 bool visible) {
664 BubbleDelegateView::OnWidgetVisibilityChanged(widget, visible);
666 if (widget != GetWidget())
667 return;
669 if (!visible)
670 app_list_main_view_->ResetForShow();
673 void AppListView::OnSpeechRecognitionStateChanged(
674 SpeechRecognitionState new_state) {
675 if (!speech_view_)
676 return;
678 bool will_appear = (new_state == SPEECH_RECOGNITION_RECOGNIZING ||
679 new_state == SPEECH_RECOGNITION_IN_SPEECH ||
680 new_state == SPEECH_RECOGNITION_NETWORK_ERROR);
681 // No change for this class.
682 if (speech_view_->visible() == will_appear)
683 return;
685 if (will_appear)
686 speech_view_->Reset();
688 animation_observer_->set_frame(GetBubbleFrameView());
689 gfx::Transform speech_transform;
690 speech_transform.Translate(
691 0, SkFloatToMScalar(kSpeechUIAppearingPosition));
692 if (will_appear)
693 speech_view_->layer()->SetTransform(speech_transform);
696 ui::ScopedLayerAnimationSettings main_settings(
697 app_list_main_view_->layer()->GetAnimator());
698 if (will_appear) {
699 animation_observer_->SetTarget(app_list_main_view_);
700 main_settings.AddObserver(animation_observer_.get());
702 app_list_main_view_->layer()->SetOpacity(will_appear ? 0.0f : 1.0f);
706 ui::ScopedLayerAnimationSettings search_box_settings(
707 search_box_widget_->GetLayer()->GetAnimator());
708 search_box_widget_->GetLayer()->SetOpacity(will_appear ? 0.0f : 1.0f);
712 ui::ScopedLayerAnimationSettings speech_settings(
713 speech_view_->layer()->GetAnimator());
714 if (!will_appear) {
715 animation_observer_->SetTarget(speech_view_);
716 speech_settings.AddObserver(animation_observer_.get());
719 speech_view_->layer()->SetOpacity(will_appear ? 1.0f : 0.0f);
720 if (will_appear)
721 speech_view_->layer()->SetTransform(gfx::Transform());
722 else
723 speech_view_->layer()->SetTransform(speech_transform);
726 // Prevent the search box from receiving events when hidden.
727 search_box_view_->SetEnabled(!will_appear);
729 if (will_appear) {
730 speech_view_->SetVisible(true);
731 } else {
732 app_list_main_view_->SetVisible(true);
733 search_box_view_->search_box()->RequestFocus();
737 } // namespace app_list