Commit 46972105 authored by xiyuan@chromium.org's avatar xiyuan@chromium.org

[Aura] Update app list window.

- Defer showing animation until web contents is rendered;
- Properly close widget after hiding animation is finished;
- Create app list window with always-on-top and transparent flags;

BUG=98308
TEST=Verify showing animation could be seen.


Review URL: http://codereview.chromium.org/8469019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109785 0039d316-1c4b-4281-b951-d872f2087c98
parent 2f451516
...@@ -32,6 +32,10 @@ gfx::Rect GetPreferredBounds(bool show) { ...@@ -32,6 +32,10 @@ gfx::Rect GetPreferredBounds(bool show) {
return widget_bounds; return widget_bounds;
} }
ui::Layer* GetWidgetLayer(views::Widget* widget) {
return widget->GetNativeView()->layer();
}
} // namespace } // namespace
// static // static
...@@ -40,22 +44,23 @@ AppListWindow* AppListWindow::instance_ = NULL; ...@@ -40,22 +44,23 @@ AppListWindow* AppListWindow::instance_ = NULL;
// static // static
void AppListWindow::SetVisible(bool visible) { void AppListWindow::SetVisible(bool visible) {
if (!instance_) { if (!instance_) {
// TODO(xiyuan): Fix first time animation jankiness.
instance_ = new AppListWindow; instance_ = new AppListWindow;
instance_->Init(); instance_->Init();
} }
instance_->SetVisible(visible, true); instance_->DoSetVisible(visible);
} }
// static
bool AppListWindow::IsVisible() { bool AppListWindow::IsVisible() {
return instance_ && instance_->is_visible(); return instance_ && instance_->is_visible_;
} }
AppListWindow::AppListWindow() AppListWindow::AppListWindow()
: widget_(NULL), : widget_(NULL),
contents_(NULL), contents_(NULL),
is_visible_(false) { is_visible_(false),
content_rendered_(false) {
} }
AppListWindow::~AppListWindow() { AppListWindow::~AppListWindow() {
...@@ -84,7 +89,37 @@ const views::Widget* AppListWindow::GetWidget() const { ...@@ -84,7 +89,37 @@ const views::Widget* AppListWindow::GetWidget() const {
void AppListWindow::OnActiveWindowChanged(aura::Window* active) { void AppListWindow::OnActiveWindowChanged(aura::Window* active) {
if (widget_ && !widget_->IsActive() && is_visible_) if (widget_ && !widget_->IsActive() && is_visible_)
SetVisible(false, true); DoSetVisible(false);
}
void AppListWindow::OnLayerAnimationEnded(
const ui::LayerAnimationSequence* sequence) {
if (!is_visible_ )
widget_->Close();
}
void AppListWindow::OnLayerAnimationAborted(
const ui::LayerAnimationSequence* sequence) {
}
void AppListWindow::OnLayerAnimationScheduled(
const ui::LayerAnimationSequence* sequence) {
}
void AppListWindow::OnRenderHostCreated(RenderViewHost* host) {
}
void AppListWindow::OnTabMainFrameLoaded() {
}
void AppListWindow::OnTabMainFrameFirstRender() {
content_rendered_ = true;
// Do deferred show animation if necessary.
if (is_visible_ && GetWidgetLayer(widget_)->opacity() == 0) {
is_visible_ = false;
DoSetVisible(true);
}
} }
void AppListWindow::Init() { void AppListWindow::Init() {
...@@ -92,6 +127,11 @@ void AppListWindow::Init() { ...@@ -92,6 +127,11 @@ void AppListWindow::Init() {
contents_ = new DOMView(); contents_ = new DOMView();
contents_->Init(ProfileManager::GetDefaultProfile(), NULL); contents_->Init(ProfileManager::GetDefaultProfile(), NULL);
TabContents* tab = contents_->dom_contents()->tab_contents();
tab_watcher_.reset(new TabFirstRenderWatcher(tab, this));
content_rendered_ = false;
contents_->LoadURL(GURL(chrome::kChromeUIAppListURL)); contents_->LoadURL(GURL(chrome::kChromeUIAppListURL));
// Use a background with transparency to trigger transparent webkit. // Use a background with transparency to trigger transparent webkit.
...@@ -100,7 +140,6 @@ void AppListWindow::Init() { ...@@ -100,7 +140,6 @@ void AppListWindow::Init() {
background.allocPixels(); background.allocPixels();
background.eraseARGB(0x00, 0x00, 0x00, 0x00); background.eraseARGB(0x00, 0x00, 0x00, 0x00);
TabContents* tab = contents_->dom_contents()->tab_contents();
RenderViewHost* host = tab->render_view_host(); RenderViewHost* host = tab->render_view_host();
host->view()->SetBackground(background); host->view()->SetBackground(background);
...@@ -108,45 +147,38 @@ void AppListWindow::Init() { ...@@ -108,45 +147,38 @@ void AppListWindow::Init() {
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
widget_params.bounds = GetPreferredBounds(false); widget_params.bounds = GetPreferredBounds(false);
widget_params.delegate = this; widget_params.delegate = this;
widget_params.keep_on_top = true;
widget_params.transparent = true;
widget_ = new views::Widget; widget_ = new views::Widget;
widget_->Init(widget_params); widget_->Init(widget_params);
widget_->SetContentsView(contents_); widget_->SetContentsView(contents_);
widget_->SetOpacity(0); widget_->SetOpacity(0);
GetWidgetLayer(widget_)->GetAnimator()->AddObserver(this);
aura::Desktop::GetInstance()->AddObserver(this); aura::Desktop::GetInstance()->AddObserver(this);
} }
void AppListWindow::SetVisible(bool visible, bool animate) { void AppListWindow::DoSetVisible(bool visible) {
if (visible == is_visible_) if (visible == is_visible_)
return; return;
is_visible_ = visible; is_visible_ = visible;
if (animate) { // Skip show animation if contents is not rendered.
gfx::Point dummy; // TODO(xiyuan): Should we show a loading UI if it takes too long?
ui::Layer* layer; if (visible && !content_rendered_)
widget_->CalculateOffsetToAncestorWithLayer(&dummy, &layer); return;
ui::LayerAnimator::ScopedSettings settings(layer->GetAnimator()); ui::Layer* layer = GetWidgetLayer(widget_);
layer->SetBounds(GetPreferredBounds(visible)); ui::LayerAnimator::ScopedSettings settings(layer->GetAnimator());
layer->SetOpacity(visible ? 1.0 : 0.0); layer->SetBounds(GetPreferredBounds(visible));
} layer->SetOpacity(visible ? 1.0 : 0.0);
if (visible) { if (visible) {
widget_->Activate();
widget_->Show(); widget_->Show();
widget_->Activate();
} else { } else {
instance_ = NULL; // Closing and don't reuse this instance_. instance_ = NULL; // Closing and don't reuse this instance_.
if (animate) {
// TODO(xiyuan): Properly close widget after animation finishes.
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&views::Widget::Close, base::Unretained(widget_)),
1000);
} else {
widget_->Close();
}
} }
} }
...@@ -6,7 +6,10 @@ ...@@ -6,7 +6,10 @@
#define CHROME_BROWSER_UI_VIEWS_AURA_APP_LIST_WINDOW_H_ #define CHROME_BROWSER_UI_VIEWS_AURA_APP_LIST_WINDOW_H_
#pragma once #pragma once
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/tab_first_render_watcher.h"
#include "ui/aura/desktop_observer.h" #include "ui/aura/desktop_observer.h"
#include "ui/gfx/compositor/layer_animation_observer.h"
#include "views/widget/widget_delegate.h" #include "views/widget/widget_delegate.h"
class DOMView; class DOMView;
...@@ -16,7 +19,9 @@ class Widget; ...@@ -16,7 +19,9 @@ class Widget;
} }
class AppListWindow : public views::WidgetDelegate, class AppListWindow : public views::WidgetDelegate,
public aura::DesktopObserver { public aura::DesktopObserver,
public ui::LayerAnimationObserver,
public TabFirstRenderWatcher::Delegate {
public: public:
// Show/hide app list window. // Show/hide app list window.
static void SetVisible(bool visible); static void SetVisible(bool visible);
...@@ -28,7 +33,7 @@ class AppListWindow : public views::WidgetDelegate, ...@@ -28,7 +33,7 @@ class AppListWindow : public views::WidgetDelegate,
AppListWindow(); AppListWindow();
virtual ~AppListWindow(); virtual ~AppListWindow();
// Overridden from views::WidgetDelegate: // views::WidgetDelegate overrides:
virtual void DeleteDelegate() OVERRIDE; virtual void DeleteDelegate() OVERRIDE;
virtual views::View* GetContentsView() OVERRIDE; virtual views::View* GetContentsView() OVERRIDE;
virtual void WindowClosing() OVERRIDE; virtual void WindowClosing() OVERRIDE;
...@@ -38,15 +43,24 @@ class AppListWindow : public views::WidgetDelegate, ...@@ -38,15 +43,24 @@ class AppListWindow : public views::WidgetDelegate,
// aura::DesktopObserver overrides: // aura::DesktopObserver overrides:
virtual void OnActiveWindowChanged(aura::Window* active) OVERRIDE; virtual void OnActiveWindowChanged(aura::Window* active) 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;
// TabFirstRenderWatcher::Delegate implementation:
virtual void OnRenderHostCreated(RenderViewHost* host) OVERRIDE;
virtual void OnTabMainFrameLoaded() OVERRIDE;
virtual void OnTabMainFrameFirstRender() OVERRIDE;
// Initializes the window. // Initializes the window.
void Init(); void Init();
// Shows/hides the window. // Shows/hides the window.
void SetVisible(bool visible, bool animate); void DoSetVisible(bool visible);
bool is_visible() const {
return is_visible_;
}
// Current visible app list window. // Current visible app list window.
static AppListWindow* instance_; static AppListWindow* instance_;
...@@ -55,6 +69,13 @@ class AppListWindow : public views::WidgetDelegate, ...@@ -55,6 +69,13 @@ class AppListWindow : public views::WidgetDelegate,
DOMView* contents_; DOMView* contents_;
bool is_visible_; bool is_visible_;
// Monitors TabContents and set |content_rendered_| flag when it's rendered.
scoped_ptr<TabFirstRenderWatcher> tab_watcher_;
// Flag of whether the web contents is rendered. Showing animation is
// deferred until this flag is set to true.
bool content_rendered_;
DISALLOW_COPY_AND_ASSIGN(AppListWindow); DISALLOW_COPY_AND_ASSIGN(AppListWindow);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment