Performance histograms for extension content verification
[chromium-blink-merge.git] / ui / app_list / views / app_list_view.cc
blobedbe25259cc54a48d43f32eadb879a927cf01761
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/strings/string_util.h"
11 #include "base/win/windows_version.h"
12 #include "ui/app_list/app_list_constants.h"
13 #include "ui/app_list/app_list_model.h"
14 #include "ui/app_list/app_list_view_delegate.h"
15 #include "ui/app_list/speech_ui_model.h"
16 #include "ui/app_list/views/app_list_background.h"
17 #include "ui/app_list/views/app_list_folder_view.h"
18 #include "ui/app_list/views/app_list_main_view.h"
19 #include "ui/app_list/views/app_list_view_observer.h"
20 #include "ui/app_list/views/apps_container_view.h"
21 #include "ui/app_list/views/contents_view.h"
22 #include "ui/app_list/views/search_box_view.h"
23 #include "ui/app_list/views/speech_view.h"
24 #include "ui/base/ui_base_switches.h"
25 #include "ui/compositor/layer.h"
26 #include "ui/compositor/layer_animation_observer.h"
27 #include "ui/compositor/scoped_layer_animation_settings.h"
28 #include "ui/gfx/image/image_skia.h"
29 #include "ui/gfx/insets.h"
30 #include "ui/gfx/path.h"
31 #include "ui/gfx/skia_util.h"
32 #include "ui/views/bubble/bubble_frame_view.h"
33 #include "ui/views/controls/textfield/textfield.h"
34 #include "ui/views/layout/fill_layout.h"
35 #include "ui/views/widget/widget.h"
37 #if defined(USE_AURA)
38 #include "ui/aura/window.h"
39 #include "ui/aura/window_tree_host.h"
40 #include "ui/views/bubble/bubble_window_targeter.h"
41 #if defined(OS_WIN)
42 #include "ui/base/win/shell.h"
43 #endif
44 #if !defined(OS_CHROMEOS)
45 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
46 #endif
47 #endif // defined(USE_AURA)
49 namespace app_list {
51 namespace {
53 // The margin from the edge to the speech UI.
54 const int kSpeechUIMargin = 12;
56 // The vertical position for the appearing animation of the speech UI.
57 const float kSpeechUIAppearingPosition = 12;
59 // The distance between the arrow tip and edge of the anchor view.
60 const int kArrowOffset = 10;
62 // Determines whether the current environment supports shadows bubble borders.
63 bool SupportsShadow() {
64 #if defined(OS_WIN)
65 // Shadows are not supported on Windows without Aero Glass.
66 if (!ui::win::IsAeroGlassEnabled() ||
67 CommandLine::ForCurrentProcess()->HasSwitch(
68 switches::kDisableDwmComposition)) {
69 return false;
71 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
72 // Shadows are not supported on (non-ChromeOS) Linux.
73 return false;
74 #endif
75 return true;
78 } // namespace
80 // An animation observer to hide the view at the end of the animation.
81 class HideViewAnimationObserver : public ui::ImplicitAnimationObserver {
82 public:
83 HideViewAnimationObserver()
84 : frame_(NULL),
85 target_(NULL) {
88 virtual ~HideViewAnimationObserver() {
89 if (target_)
90 StopObservingImplicitAnimations();
93 void SetTarget(views::View* target) {
94 if (!target_)
95 StopObservingImplicitAnimations();
96 target_ = target;
99 void set_frame(views::BubbleFrameView* frame) { frame_ = frame; }
101 private:
102 // Overridden from ui::ImplicitAnimationObserver:
103 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
104 if (target_) {
105 target_->SetVisible(false);
106 target_ = NULL;
108 // Should update the background by invoking SchedulePaint().
109 frame_->SchedulePaint();
113 views::BubbleFrameView* frame_;
114 views::View* target_;
116 DISALLOW_COPY_AND_ASSIGN(HideViewAnimationObserver);
119 ////////////////////////////////////////////////////////////////////////////////
120 // AppListView:
122 AppListView::AppListView(AppListViewDelegate* delegate)
123 : delegate_(delegate),
124 app_list_main_view_(NULL),
125 speech_view_(NULL),
126 animation_observer_(new HideViewAnimationObserver()) {
127 CHECK(delegate);
129 delegate_->AddObserver(this);
130 delegate_->GetSpeechUI()->AddObserver(this);
133 AppListView::~AppListView() {
134 delegate_->GetSpeechUI()->RemoveObserver(this);
135 delegate_->RemoveObserver(this);
136 animation_observer_.reset();
137 // Remove child views first to ensure no remaining dependencies on delegate_.
138 RemoveAllChildViews(true);
141 void AppListView::InitAsBubbleAttachedToAnchor(
142 gfx::NativeView parent,
143 int initial_apps_page,
144 views::View* anchor,
145 const gfx::Vector2d& anchor_offset,
146 views::BubbleBorder::Arrow arrow,
147 bool border_accepts_events) {
148 SetAnchorView(anchor);
149 InitAsBubbleInternal(
150 parent, initial_apps_page, arrow, border_accepts_events, anchor_offset);
153 void AppListView::InitAsBubbleAtFixedLocation(
154 gfx::NativeView parent,
155 int initial_apps_page,
156 const gfx::Point& anchor_point_in_screen,
157 views::BubbleBorder::Arrow arrow,
158 bool border_accepts_events) {
159 SetAnchorView(NULL);
160 SetAnchorRect(gfx::Rect(anchor_point_in_screen, gfx::Size()));
161 InitAsBubbleInternal(
162 parent, initial_apps_page, arrow, border_accepts_events, gfx::Vector2d());
165 void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) {
166 GetBubbleFrameView()->bubble_border()->set_arrow(arrow);
167 SizeToContents(); // Recalcuates with new border.
168 GetBubbleFrameView()->SchedulePaint();
171 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
172 SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
175 void AppListView::SetDragAndDropHostOfCurrentAppList(
176 ApplicationDragAndDropHost* drag_and_drop_host) {
177 app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
180 void AppListView::ShowWhenReady() {
181 app_list_main_view_->ShowAppListWhenReady();
184 void AppListView::Close() {
185 app_list_main_view_->Close();
186 delegate_->Dismiss();
189 void AppListView::UpdateBounds() {
190 SizeToContents();
193 bool AppListView::ShouldCenterWindow() const {
194 return delegate_->ShouldCenterWindow();
197 gfx::Size AppListView::GetPreferredSize() const {
198 return app_list_main_view_->GetPreferredSize();
201 void AppListView::Paint(gfx::Canvas* canvas, const views::CullSet& cull_set) {
202 views::BubbleDelegateView::Paint(canvas, cull_set);
203 if (!next_paint_callback_.is_null()) {
204 next_paint_callback_.Run();
205 next_paint_callback_.Reset();
209 void AppListView::OnThemeChanged() {
210 #if defined(OS_WIN)
211 GetWidget()->Close();
212 #endif
215 bool AppListView::ShouldHandleSystemCommands() const {
216 return true;
219 void AppListView::Prerender() {
220 app_list_main_view_->Prerender();
223 void AppListView::OnProfilesChanged() {
224 app_list_main_view_->search_box_view()->InvalidateMenu();
227 void AppListView::SetProfileByPath(const base::FilePath& profile_path) {
228 delegate_->SetProfileByPath(profile_path);
229 app_list_main_view_->ModelChanged();
232 void AppListView::AddObserver(AppListViewObserver* observer) {
233 observers_.AddObserver(observer);
236 void AppListView::RemoveObserver(AppListViewObserver* observer) {
237 observers_.RemoveObserver(observer);
240 // static
241 void AppListView::SetNextPaintCallback(const base::Closure& callback) {
242 next_paint_callback_ = callback;
245 #if defined(OS_WIN)
246 HWND AppListView::GetHWND() const {
247 gfx::NativeWindow window =
248 GetWidget()->GetTopLevelWidget()->GetNativeWindow();
249 return window->GetHost()->GetAcceleratedWidget();
251 #endif
253 PaginationModel* AppListView::GetAppsPaginationModel() {
254 return app_list_main_view_->contents_view()
255 ->apps_container_view()
256 ->apps_grid_view()
257 ->pagination_model();
260 void AppListView::InitAsBubbleInternal(gfx::NativeView parent,
261 int initial_apps_page,
262 views::BubbleBorder::Arrow arrow,
263 bool border_accepts_events,
264 const gfx::Vector2d& anchor_offset) {
265 app_list_main_view_ =
266 new AppListMainView(delegate_.get(), initial_apps_page, parent);
267 AddChildView(app_list_main_view_);
268 app_list_main_view_->SetPaintToLayer(true);
269 app_list_main_view_->SetFillsBoundsOpaquely(false);
270 app_list_main_view_->layer()->SetMasksToBounds(true);
272 // Speech recognition is available only when the start page exists.
273 if (delegate_ && delegate_->IsSpeechRecognitionEnabled()) {
274 speech_view_ = new SpeechView(delegate_.get());
275 speech_view_->SetVisible(false);
276 speech_view_->SetPaintToLayer(true);
277 speech_view_->SetFillsBoundsOpaquely(false);
278 speech_view_->layer()->SetOpacity(0.0f);
279 AddChildView(speech_view_);
282 OnProfilesChanged();
283 set_color(kContentsBackgroundColor);
284 set_margins(gfx::Insets());
285 set_parent_window(parent);
286 set_close_on_deactivate(false);
287 set_close_on_esc(false);
288 set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(),
289 kArrowOffset + anchor_offset.x(),
290 kArrowOffset - anchor_offset.y(),
291 kArrowOffset - anchor_offset.x()));
292 set_border_accepts_events(border_accepts_events);
293 set_shadow(SupportsShadow() ? views::BubbleBorder::BIG_SHADOW
294 : views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER);
295 views::BubbleDelegateView::CreateBubble(this);
296 SetBubbleArrow(arrow);
298 #if defined(USE_AURA)
299 aura::Window* window = GetWidget()->GetNativeWindow();
300 window->layer()->SetMasksToBounds(true);
301 GetBubbleFrameView()->set_background(new AppListBackground(
302 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
303 app_list_main_view_));
304 set_background(NULL);
305 window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
306 new views::BubbleWindowTargeter(this)));
307 #else
308 set_background(new AppListBackground(
309 GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
310 app_list_main_view_));
312 // On non-aura the bubble has two widgets, and it's possible for the border
313 // to be shown independently in odd situations. Explicitly hide the bubble
314 // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the
315 // window manager do not have the SWP_SHOWWINDOW flag set which would cause
316 // the border to be shown. See http://crbug.com/231687 .
317 GetWidget()->Hide();
318 #endif
320 if (delegate_)
321 delegate_->ViewInitialized();
324 void AppListView::OnBeforeBubbleWidgetInit(
325 views::Widget::InitParams* params,
326 views::Widget* widget) const {
327 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
328 if (delegate_ && delegate_->ForceNativeDesktop())
329 params->native_widget = new views::DesktopNativeWidgetAura(widget);
330 #endif
331 #if defined(OS_WIN)
332 // Windows 7 and higher offer pinning to the taskbar, but we need presence
333 // on the taskbar for the user to be able to pin us. So, show the window on
334 // the taskbar for these versions of Windows.
335 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
336 params->force_show_in_taskbar = true;
337 #elif defined(OS_LINUX)
338 // Set up a custom WM_CLASS for the app launcher window. This allows task
339 // switchers in X11 environments to distinguish it from main browser windows.
340 params->wm_class_name = kAppListWMClass;
341 // Show the window in the taskbar, even though it is a bubble, which would not
342 // normally be shown.
343 params->force_show_in_taskbar = true;
344 #endif
347 views::View* AppListView::GetInitiallyFocusedView() {
348 return app_list_main_view_->search_box_view()->search_box();
351 gfx::ImageSkia AppListView::GetWindowIcon() {
352 if (delegate_)
353 return delegate_->GetWindowIcon();
355 return gfx::ImageSkia();
358 bool AppListView::WidgetHasHitTestMask() const {
359 return true;
362 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const {
363 DCHECK(mask);
364 mask->addRect(gfx::RectToSkRect(
365 GetBubbleFrameView()->GetContentsBounds()));
368 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
369 // The accelerator is added by BubbleDelegateView.
370 if (accelerator.key_code() == ui::VKEY_ESCAPE) {
371 if (app_list_main_view_->search_box_view()->HasSearch()) {
372 app_list_main_view_->search_box_view()->ClearSearch();
373 } else if (app_list_main_view_->contents_view()
374 ->apps_container_view()
375 ->IsInFolderView()) {
376 app_list_main_view_->contents_view()
377 ->apps_container_view()
378 ->app_list_folder_view()
379 ->CloseFolderPage();
380 return true;
381 } else {
382 GetWidget()->Deactivate();
383 Close();
385 return true;
388 return false;
391 void AppListView::Layout() {
392 const gfx::Rect contents_bounds = GetContentsBounds();
393 app_list_main_view_->SetBoundsRect(contents_bounds);
395 if (speech_view_) {
396 gfx::Rect speech_bounds = contents_bounds;
397 int preferred_height = speech_view_->GetPreferredSize().height();
398 speech_bounds.Inset(kSpeechUIMargin, kSpeechUIMargin);
399 speech_bounds.set_height(std::min(speech_bounds.height(),
400 preferred_height));
401 speech_bounds.Inset(-speech_view_->GetInsets());
402 speech_view_->SetBoundsRect(speech_bounds);
406 void AppListView::SchedulePaintInRect(const gfx::Rect& rect) {
407 BubbleDelegateView::SchedulePaintInRect(rect);
408 if (GetBubbleFrameView())
409 GetBubbleFrameView()->SchedulePaint();
412 void AppListView::OnWidgetDestroying(views::Widget* widget) {
413 BubbleDelegateView::OnWidgetDestroying(widget);
414 if (delegate_ && widget == GetWidget())
415 delegate_->ViewClosing();
418 void AppListView::OnWidgetActivationChanged(views::Widget* widget,
419 bool active) {
420 // Do not called inherited function as the bubble delegate auto close
421 // functionality is not used.
422 if (widget == GetWidget())
423 FOR_EACH_OBSERVER(AppListViewObserver, observers_,
424 OnActivationChanged(widget, active));
427 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
428 bool visible) {
429 BubbleDelegateView::OnWidgetVisibilityChanged(widget, visible);
431 if (widget != GetWidget())
432 return;
434 if (!visible)
435 app_list_main_view_->ResetForShow();
438 void AppListView::OnSpeechRecognitionStateChanged(
439 SpeechRecognitionState new_state) {
440 if (!speech_view_)
441 return;
443 bool will_appear = (new_state == SPEECH_RECOGNITION_RECOGNIZING ||
444 new_state == SPEECH_RECOGNITION_IN_SPEECH ||
445 new_state == SPEECH_RECOGNITION_NETWORK_ERROR);
446 // No change for this class.
447 if (speech_view_->visible() == will_appear)
448 return;
450 if (will_appear)
451 speech_view_->Reset();
453 animation_observer_->set_frame(GetBubbleFrameView());
454 gfx::Transform speech_transform;
455 speech_transform.Translate(
456 0, SkFloatToMScalar(kSpeechUIAppearingPosition));
457 if (will_appear)
458 speech_view_->layer()->SetTransform(speech_transform);
461 ui::ScopedLayerAnimationSettings main_settings(
462 app_list_main_view_->layer()->GetAnimator());
463 if (will_appear) {
464 animation_observer_->SetTarget(app_list_main_view_);
465 main_settings.AddObserver(animation_observer_.get());
467 app_list_main_view_->layer()->SetOpacity(will_appear ? 0.0f : 1.0f);
471 ui::ScopedLayerAnimationSettings speech_settings(
472 speech_view_->layer()->GetAnimator());
473 if (!will_appear) {
474 animation_observer_->SetTarget(speech_view_);
475 speech_settings.AddObserver(animation_observer_.get());
478 speech_view_->layer()->SetOpacity(will_appear ? 1.0f : 0.0f);
479 if (will_appear)
480 speech_view_->layer()->SetTransform(gfx::Transform());
481 else
482 speech_view_->layer()->SetTransform(speech_transform);
485 if (will_appear)
486 speech_view_->SetVisible(true);
487 else
488 app_list_main_view_->SetVisible(true);
491 } // namespace app_list