diff options
author | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 22:52:44 +0000 |
---|---|---|
committer | xiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 22:52:44 +0000 |
commit | ae4987d641566c6036fc10e9a284df687d8db4ab (patch) | |
tree | bc7f62e7bcf10b23102bd8a4e53fcc57b6d8462b /ui | |
parent | 8e937860d73f45a2fde92a736fd5f43a9e35e185 (diff) | |
download | chromium_src-ae4987d641566c6036fc10e9a284df687d8db4ab.zip chromium_src-ae4987d641566c6036fc10e9a284df687d8db4ab.tar.gz chromium_src-ae4987d641566c6036fc10e9a284df687d8db4ab.tar.bz2 |
[Aura] Refactor and update app list window.
- Move showing, dimissing, animation observer, click monitoring code tha into an AppList controller in aura_shell;
- Change ShellDelegate::ShowApps to an inteface to request app list widget and having a callback to notify app list controller when the widget is ready;
- Click outside to dismiss the window.
- Hide default container when app list is visible;
BUG=98308
TEST=Verify click outside applist window to dismiss it. Browser windows should be hidden when app list window is shown and should be visible when app list is gone.
Review URL: http://codereview.chromium.org/8558031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111021 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura_shell/app_list.cc | 175 | ||||
-rw-r--r-- | ui/aura_shell/app_list.h | 83 | ||||
-rw-r--r-- | ui/aura_shell/aura_shell.gyp | 2 | ||||
-rw-r--r-- | ui/aura_shell/examples/aura_shell_main.cc | 35 | ||||
-rw-r--r-- | ui/aura_shell/launcher/launcher_view.cc | 2 | ||||
-rw-r--r-- | ui/aura_shell/shell.cc | 7 | ||||
-rw-r--r-- | ui/aura_shell/shell.h | 6 | ||||
-rw-r--r-- | ui/aura_shell/shell_delegate.h | 9 |
8 files changed, 314 insertions, 5 deletions
diff --git a/ui/aura_shell/app_list.cc b/ui/aura_shell/app_list.cc new file mode 100644 index 0000000..0218713 --- /dev/null +++ b/ui/aura_shell/app_list.cc @@ -0,0 +1,175 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura_shell/app_list.h" + +#include "base/bind.h" +#include "ui/aura/event.h" +#include "ui/aura/window.h" +#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/shell_delegate.h" +#include "ui/aura_shell/shell_window_ids.h" +#include "ui/gfx/screen.h" + +namespace aura_shell { +namespace internal { + +namespace { + +// Gets preferred bounds of app list window in show/hide state. +gfx::Rect GetPreferredBounds(bool show) { + // The y-axis offset used at the beginning of showing animation. + static const int kMoveUpAnimationOffset = 50; + + gfx::Point cursor = gfx::Screen::GetCursorScreenPoint(); + gfx::Rect work_area = gfx::Screen::GetMonitorWorkAreaNearestPoint(cursor); + gfx::Rect widget_bounds(work_area); + widget_bounds.Inset(150, 100); + if (!show) + widget_bounds.Offset(0, kMoveUpAnimationOffset); + + return widget_bounds; +} + +ui::Layer* GetLayer(views::Widget* widget) { + return widget->GetNativeView()->layer(); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// AppList, public: + +AppList::AppList() + : aura::EventFilter(NULL), + is_visible_(false), + widget_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST(set_widget_factory_(this)) { +} + +AppList::~AppList() { + ResetWidget(); +} + +void AppList::SetVisible(bool visible) { + if (visible == is_visible_) + return; + + is_visible_ = visible; + + if (widget_) { + ScheduleAnimation(); + } else if (is_visible_ && !set_widget_factory_.HasWeakPtrs()) { + Shell::GetInstance()->delegate()->RequestAppListWidget( + base::Bind(&AppList::SetWidget, set_widget_factory_.GetWeakPtr())); + } +} + +bool AppList::IsVisible() { + return widget_ && widget_->IsVisible(); +} + +//////////////////////////////////////////////////////////////////////////////// +// AppList, private: + +void AppList::SetWidget(views::Widget* widget) { + DCHECK(widget_ == NULL); + set_widget_factory_.InvalidateWeakPtrs(); + + if (is_visible_) { + widget_ = widget; + widget_->AddObserver(this); + GetLayer(widget_)->GetAnimator()->AddObserver(this); + Shell::GetInstance()->AddDesktopEventFilter(this); + + widget_->SetBounds(GetPreferredBounds(false)); + widget_->SetOpacity(0); + ScheduleAnimation(); + + widget_->Show(); + widget_->Activate(); + } else { + widget->Close(); + } +} + +void AppList::ResetWidget() { + if (!widget_) + return; + + widget_->RemoveObserver(this); + GetLayer(widget_)->GetAnimator()->RemoveObserver(this); + Shell::GetInstance()->RemoveDesktopEventFilter(this); + widget_ = NULL; +} + +void AppList::ScheduleAnimation() { + ui::Layer* layer = GetLayer(widget_); + ui::LayerAnimator::ScopedSettings app_list_animation(layer->GetAnimator()); + layer->SetBounds(GetPreferredBounds(is_visible_)); + layer->SetOpacity(is_visible_ ? 1.0 : 0.0); + + ui::Layer* default_container_layer = Shell::GetInstance()->GetContainer( + internal::kShellWindowId_DefaultContainer)->layer(); + ui::LayerAnimator::ScopedSettings default_container_animation( + default_container_layer->GetAnimator()); + default_container_layer->SetOpacity(is_visible_ ? 0.0 : 1.0); +} + +//////////////////////////////////////////////////////////////////////////////// +// AppList, aura::EventFilter implementation: + +bool AppList::PreHandleKeyEvent(aura::Window* target, + aura::KeyEvent* event) { + return false; +} + +bool AppList::PreHandleMouseEvent(aura::Window* target, + aura::MouseEvent* event) { + if (widget_ && is_visible_ && event->type() == ui::ET_MOUSE_PRESSED) { + aura::MouseEvent translated(*event, target, widget_->GetNativeView()); + if (!widget_->GetNativeView()->ContainsPoint(translated.location())) + SetVisible(false); + } + return false; +} + +ui::TouchStatus AppList::PreHandleTouchEvent(aura::Window* target, + aura::TouchEvent* event) { + return ui::TOUCH_STATUS_UNKNOWN; +} + +//////////////////////////////////////////////////////////////////////////////// +// AppList, ui::LayerAnimationObserver implementation: + +void AppList::OnLayerAnimationEnded( + const ui::LayerAnimationSequence* sequence) { + if (!is_visible_ ) + widget_->Close(); +} + +void AppList::OnLayerAnimationAborted( + const ui::LayerAnimationSequence* sequence) { +} + +void AppList::OnLayerAnimationScheduled( + const ui::LayerAnimationSequence* sequence) { +} + +//////////////////////////////////////////////////////////////////////////////// +// AppList, views::Widget::Observer implementation: + +void AppList::OnWidgetClosing(views::Widget* widget) { + DCHECK(widget_ == widget); + ResetWidget(); +} + +void AppList::OnWidgetActivationChanged(views::Widget* widget, bool active) { + DCHECK(widget_ == widget); + if (widget_ && is_visible_ && !active) + SetVisible(false); +} + +} // namespace internal +} // namespace aura_shell diff --git a/ui/aura_shell/app_list.h b/ui/aura_shell/app_list.h new file mode 100644 index 0000000..eb2b886 --- /dev/null +++ b/ui/aura_shell/app_list.h @@ -0,0 +1,83 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_AURA_SHELL_APP_LIST_H_ +#define UI_AURA_SHELL_APP_LIST_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/weak_ptr.h" +#include "ui/aura/event_filter.h" +#include "ui/gfx/compositor/layer_animation_observer.h" +#include "views/widget/widget.h" + +namespace aura_shell { +namespace internal { + +// AppList is a controller that manages app list UI for shell. To show the UI, +// it requests app list widget from ShellDelegate and shows it when ready. +// While the UI is visible, it monitors things such as app list widget's +// activation state and desktop mouse click to auto dismiss the UI. +class AppList : public aura::EventFilter, + public ui::LayerAnimationObserver, + public views::Widget::Observer { + public: + AppList(); + virtual ~AppList(); + + // Show/hide app list window. + void SetVisible(bool visible); + + // Whether app list window is visible (shown or being shown). + bool IsVisible(); + + private: + // Sets app list widget. If we are in visible mode, start showing animation. + // Otherwise, we just close the widget. + void SetWidget(views::Widget* widget); + + // Forgets the widget. + void ResetWidget(); + + // Starts show/hide animation. + void ScheduleAnimation(); + + // aura::EventFilter overrides: + virtual bool PreHandleKeyEvent(aura::Window* target, + aura::KeyEvent* event) OVERRIDE; + virtual bool PreHandleMouseEvent(aura::Window* target, + aura::MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, + aura::TouchEvent* event) OVERRIDE; + + // ui::LayerAnimationObserver overrides: + virtual void OnLayerAnimationEnded( + const ui::LayerAnimationSequence* sequence) OVERRIDE; + virtual void OnLayerAnimationAborted( + const ui::LayerAnimationSequence* sequence) OVERRIDE; + virtual void OnLayerAnimationScheduled( + const ui::LayerAnimationSequence* sequence) OVERRIDE; + + // views::Widget::Observer overrides: + virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; + virtual void OnWidgetActivationChanged(views::Widget* widget, + bool active) OVERRIDE; + + // Whether we should show or hide app list widget. + bool is_visible_; + + // App list widget we get from ShellDelegate. + views::Widget* widget_; + + // A weak ptr factory for callbacks that ShellDelegate used to set widget. + base::WeakPtrFactory<AppList> set_widget_factory_; + + DISALLOW_COPY_AND_ASSIGN(AppList); +}; + +} // namespace internal +} // namespace aura_shell + +#endif // UI_AURA_SHELL_APP_LIST_H_ diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp index 345b999..dd42888 100644 --- a/ui/aura_shell/aura_shell.gyp +++ b/ui/aura_shell/aura_shell.gyp @@ -35,6 +35,8 @@ # All .cc, .h under views, except unittests 'always_on_top_controller.cc', 'always_on_top_controller.h', + 'app_list.cc', + 'app_list.h', 'default_container_event_filter.cc', 'default_container_event_filter.h', 'default_container_layout_manager.cc', diff --git a/ui/aura_shell/examples/aura_shell_main.cc b/ui/aura_shell/examples/aura_shell_main.cc index 9cacb3b..17e3923 100644 --- a/ui/aura_shell/examples/aura_shell_main.cc +++ b/ui/aura_shell/examples/aura_shell_main.cc @@ -15,10 +15,40 @@ #include "ui/aura_shell/shell_factory.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" +#include "ui/gfx/canvas.h" #include "ui/gfx/compositor/test/compositor_test_support.h" +#include "views/widget/widget_delegate.h" +#include "views/widget/widget.h" namespace { +class AppListWindow : public views::WidgetDelegateView { + public: + AppListWindow() { + } + + // static + static views::Widget* Create() { + AppListWindow* app_list = new AppListWindow; + + views::Widget::InitParams widget_params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + widget_params.delegate = app_list; + widget_params.keep_on_top = true; + widget_params.transparent = true; + + views::Widget* widget = new views::Widget; + widget->Init(widget_params); + widget->SetContentsView(app_list); + return widget; + } + + // Overridden from views::View: + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { + canvas->FillRect(SkColorSetARGB(0x4F, 0xFF, 0, 0), bounds()); + } +}; + class ShellDelegateImpl : public aura_shell::ShellDelegate { public: ShellDelegateImpl() { @@ -35,8 +65,9 @@ class ShellDelegateImpl : public aura_shell::ShellDelegate { return aura_shell::internal::CreateStatusArea(); } - virtual void ShowApps() OVERRIDE { - NOTIMPLEMENTED(); + virtual void RequestAppListWidget( + const SetWidgetCallback& callback) OVERRIDE { + callback.Run(AppListWindow::Create()); } virtual void LauncherItemClicked( diff --git a/ui/aura_shell/launcher/launcher_view.cc b/ui/aura_shell/launcher/launcher_view.cc index b6fb445..46a0b07 100644 --- a/ui/aura_shell/launcher/launcher_view.cc +++ b/ui/aura_shell/launcher/launcher_view.cc @@ -598,7 +598,7 @@ void LauncherView::ButtonPressed(views::Button* sender, if (sender == new_browser_button_) { delegate->CreateNewWindow(); } else if (sender == show_apps_button_) { - delegate->ShowApps(); + Shell::GetInstance()->ToggleAppList(); } else if (sender == overflow_button_) { ShowOverflowMenu(); } else { diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc index 8a63f21..ddd08b5 100644 --- a/ui/aura_shell/shell.cc +++ b/ui/aura_shell/shell.cc @@ -12,6 +12,7 @@ #include "ui/aura/desktop.h" #include "ui/aura/window.h" #include "ui/aura/window_types.h" +#include "ui/aura_shell/app_list.h" #include "ui/aura_shell/default_container_event_filter.h" #include "ui/aura_shell/default_container_layout_manager.h" #include "ui/aura_shell/desktop_event_filter.h" @@ -219,6 +220,12 @@ void Shell::ToggleOverview() { workspace_controller_->ToggleOverview(); } +void Shell::ToggleAppList() { + if (!app_list_.get()) + app_list_.reset(new internal::AppList); + app_list_->SetVisible(!app_list_->IsVisible()); +} + //////////////////////////////////////////////////////////////////////////////// // Shell, private: diff --git a/ui/aura_shell/shell.h b/ui/aura_shell/shell.h index 3f4e3ac..0ab72bc 100644 --- a/ui/aura_shell/shell.h +++ b/ui/aura_shell/shell.h @@ -30,6 +30,7 @@ class Launcher; class ShellDelegate; namespace internal { +class AppList; class DragDropController; class ShadowController; class ShelfLayoutController; @@ -62,6 +63,9 @@ class AURA_SHELL_EXPORT Shell { // Toggles between overview mode and normal mode. void ToggleOverview(); + // Toggles app list. + void ToggleAppList(); + ShellDelegate* delegate() { return delegate_.get(); } Launcher* launcher() { return launcher_.get(); } @@ -91,6 +95,8 @@ class AURA_SHELL_EXPORT Shell { scoped_ptr<Launcher> launcher_; + scoped_ptr<internal::AppList> app_list_; + scoped_ptr<internal::DragDropController> drag_drop_controller_; scoped_ptr<internal::WorkspaceController> workspace_controller_; scoped_ptr<internal::ShelfLayoutController> shelf_layout_controller_; diff --git a/ui/aura_shell/shell_delegate.h b/ui/aura_shell/shell_delegate.h index b316669..28eb602 100644 --- a/ui/aura_shell/shell_delegate.h +++ b/ui/aura_shell/shell_delegate.h @@ -6,6 +6,7 @@ #define UI_AURA_SHELL_SHELL_DELEGATE_H_ #pragma once +#include "base/callback.h" #include "ui/aura_shell/aura_shell_export.h" namespace views { @@ -19,6 +20,9 @@ struct LauncherItem; // Delegate of the Shell. class AURA_SHELL_EXPORT ShellDelegate { public: + // Callback to pass back a widget used by RequestAppListWidget. + typedef base::Callback<void(views::Widget*)> SetWidgetCallback; + // The Shell owns the delegate. virtual ~ShellDelegate() {} @@ -29,8 +33,9 @@ class AURA_SHELL_EXPORT ShellDelegate { // Invoked to create a new status area. Can return NULL. virtual views::Widget* CreateStatusArea() = 0; - // Invoked when the user clicks the app list button on the launcher. - virtual void ShowApps() = 0; + // Invoked to create app list widget. The Delegate calls the callback + // when the widget is ready to show. + virtual void RequestAppListWidget(const SetWidgetCallback& callback) = 0; // Invoked when the user clicks on a window entry in the launcher. virtual void LauncherItemClicked(const LauncherItem& item) = 0; |