| Index: ash/wm/workspace/phantom_window_controller.cc
|
| diff --git a/ash/wm/workspace/phantom_window_controller.cc b/ash/wm/workspace/phantom_window_controller.cc
|
| index 83a0e3fdcb05e2d019654abcc9aad6f89192c78d..2ecd2e1e3367330673ad8091a5f49cd802def66b 100644
|
| --- a/ash/wm/workspace/phantom_window_controller.cc
|
| +++ b/ash/wm/workspace/phantom_window_controller.cc
|
| @@ -4,15 +4,16 @@
|
|
|
| #include "ash/wm/workspace/phantom_window_controller.h"
|
|
|
| +#include "ash/ash_switches.h"
|
| #include "ash/shell.h"
|
| #include "ash/shell_window_ids.h"
|
| #include "ash/wm/coordinate_conversion.h"
|
| +#include "grit/ash_resources.h"
|
| #include "third_party/skia/include/core/SkCanvas.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/aura/window.h"
|
| #include "ui/compositor/layer.h"
|
| #include "ui/compositor/scoped_layer_animation_settings.h"
|
| -#include "ui/gfx/animation/slide_animation.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/skia_util.h"
|
| #include "ui/views/background.h"
|
| @@ -23,10 +24,73 @@
|
| namespace ash {
|
| namespace internal {
|
|
|
| -// EdgePainter ----------------------------------------------------------------
|
| -
|
| namespace {
|
|
|
| +// The duration of the bounds change animation.
|
| +const int kBoundsChangeAnimationDurationMs = 200;
|
| +
|
| +// The duration of the fade in animation to show the phantom window.
|
| +const int kShowAnimationDurationMs = 200;
|
| +
|
| +// The duration of the fade out animation to hide the phantom window.
|
| +const int kHideAnimationDurationMs = 100;
|
| +
|
| +// The amount of pixels that the shadow should extend past the window bounds
|
| +// when using the alternate caption button style.
|
| +const int kShadowThickness = 52;
|
| +
|
| +// Converts the bounds of a phantom window without a shadow to those of a
|
| +// phantom window with a shadow.
|
| +gfx::Rect GetBoundsWithShadow(const gfx::Rect& bounds) {
|
| + gfx::Rect bounds_with_shadow(bounds);
|
| + // Phantom windows have a shadow solely when using the alternate caption
|
| + // button style.
|
| + if (switches::UseAlternateFrameCaptionButtonStyle())
|
| + bounds_with_shadow.Inset(-kShadowThickness, -kShadowThickness);
|
| + return bounds_with_shadow;
|
| +}
|
| +
|
| +// Starts an animation of |widget| to |new_bounds|. No-op if |widget| is NULL.
|
| +void AnimateToBounds(views::Widget* widget, const gfx::Rect& new_bounds) {
|
| + if (!widget)
|
| + return;
|
| +
|
| + aura::Window* window = widget->GetNativeWindow();
|
| + ui::ScopedLayerAnimationSettings scoped_setter(
|
| + window->layer()->GetAnimator());
|
| + scoped_setter.SetTweenType(gfx::Tween::EASE_IN);
|
| + scoped_setter.SetPreemptionStrategy(
|
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| + scoped_setter.SetTransitionDuration(
|
| + base::TimeDelta::FromMilliseconds(kBoundsChangeAnimationDurationMs));
|
| + window->SetBounds(GetBoundsWithShadow(new_bounds));
|
| +}
|
| +
|
| +// Starts a fade in or fade out animation of |widget|. No-op if |widget| is
|
| +// NULL.
|
| +void AnimateToVisibility(views::Widget* widget, bool new_visibility) {
|
| + if (!widget)
|
| + return;
|
| +
|
| + if (new_visibility)
|
| + widget->Show();
|
| +
|
| + int animation_duration_ms = new_visibility ?
|
| + kShowAnimationDurationMs : kHideAnimationDurationMs;
|
| +
|
| + ui::Layer* layer = widget->GetNativeWindow()->layer();
|
| + ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator());
|
| + scoped_setter.SetPreemptionStrategy(
|
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
|
| + scoped_setter.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
|
| + animation_duration_ms));
|
| + layer->SetOpacity(new_visibility ? 1.0f : 0.0f);
|
| + if (!new_visibility)
|
| + widget->Hide();
|
| +}
|
| +
|
| +// EdgePainter ----------------------------------------------------------------
|
| +
|
| // Paints the background of the phantom window for window snapping.
|
| class EdgePainter : public views::Painter {
|
| public:
|
| @@ -41,9 +105,6 @@ class EdgePainter : public views::Painter {
|
| DISALLOW_COPY_AND_ASSIGN(EdgePainter);
|
| };
|
|
|
| -} // namespace
|
| -
|
| -
|
| EdgePainter::EdgePainter() {
|
| }
|
|
|
| @@ -86,89 +147,79 @@ void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
|
| SkIntToScalar(kRoundRectSize), paint);
|
| }
|
|
|
| +} // namespace
|
|
|
| // PhantomWindowController ----------------------------------------------------
|
|
|
| PhantomWindowController::PhantomWindowController(aura::Window* window)
|
| : window_(window),
|
| phantom_below_window_(NULL),
|
| - phantom_widget_(NULL),
|
| - phantom_widget_start_(NULL) {
|
| + target_visibility_(false) {
|
| }
|
|
|
| PhantomWindowController::~PhantomWindowController() {
|
| - Hide();
|
| }
|
|
|
| void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) {
|
| - if (bounds_in_screen == bounds_in_screen_)
|
| + StartFade(true);
|
| +
|
| + if (bounds_in_screen == target_bounds_in_screen_)
|
| return;
|
| - bounds_in_screen_ = bounds_in_screen;
|
| - aura::Window* target_root = wm::GetRootWindowMatching(bounds_in_screen);
|
| - // Show the phantom at the current bounds of the window. We'll animate to the
|
| - // target bounds. If phantom exists, update the start bounds.
|
| +
|
| + target_bounds_in_screen_ = bounds_in_screen;
|
| + gfx::Rect start_bounds;
|
| if (!phantom_widget_)
|
| - start_bounds_ = window_->GetBoundsInScreen();
|
| + start_bounds = window_->GetBoundsInScreen();
|
| else
|
| - start_bounds_ = phantom_widget_->GetWindowBoundsInScreen();
|
| - if (phantom_widget_ &&
|
| + start_bounds = phantom_widget_->GetWindowBoundsInScreen();
|
| +
|
| + aura::Window* target_root =
|
| + wm::GetRootWindowMatching(target_bounds_in_screen_);
|
| + if (!phantom_widget_ ||
|
| phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) {
|
| - phantom_widget_->Close();
|
| - phantom_widget_ = NULL;
|
| + phantom_widget_.reset(CreatePhantomWidget(target_root, start_bounds));
|
| }
|
| - if (!phantom_widget_)
|
| - phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_);
|
| + AnimateToBounds(phantom_widget_.get(), target_bounds_in_screen_);
|
|
|
| - // Create a secondary widget in a second screen if start_bounds_ lie at least
|
| - // partially in that other screen. This allows animations to start or restart
|
| - // in one root window and progress into another root.
|
| - aura::Window* start_root = wm::GetRootWindowMatching(start_bounds_);
|
| + // Create a secondary widget in a second screen if |start_bounds| lies at
|
| + // least partially in another screen. This allows animations to start or
|
| + // restart in one root window and progress to another root.
|
| + aura::Window* start_root = wm::GetRootWindowMatching(start_bounds);
|
| if (start_root == target_root) {
|
| aura::Window::Windows root_windows = Shell::GetAllRootWindows();
|
| for (size_t i = 0; i < root_windows.size(); ++i) {
|
| if (root_windows[i] != target_root &&
|
| - root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) {
|
| + root_windows[i]->GetBoundsInScreen().Intersects(start_bounds)) {
|
| start_root = root_windows[i];
|
| break;
|
| }
|
| }
|
| }
|
| - if (phantom_widget_start_ &&
|
| - (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root
|
| - || start_root == target_root)) {
|
| - phantom_widget_start_->Close();
|
| - phantom_widget_start_ = NULL;
|
| + if (start_root == target_root) {
|
| + phantom_widget_start_.reset();
|
| + } else {
|
| + if (!phantom_widget_start_ ||
|
| + phantom_widget_start_->GetNativeWindow()->GetRootWindow() !=
|
| + start_root) {
|
| + phantom_widget_start_.reset(
|
| + CreatePhantomWidget(start_root, start_bounds));
|
| + }
|
| + AnimateToBounds(phantom_widget_start_.get(), target_bounds_in_screen_);
|
| }
|
| - if (!phantom_widget_start_ && start_root != target_root)
|
| - phantom_widget_start_ = CreatePhantomWidget(start_root, start_bounds_);
|
| -
|
| - animation_.reset(new gfx::SlideAnimation(this));
|
| - animation_->SetTweenType(gfx::Tween::EASE_IN);
|
| - const int kAnimationDurationMS = 200;
|
| - animation_->SetSlideDuration(kAnimationDurationMS);
|
| - animation_->Show();
|
| }
|
|
|
| -void PhantomWindowController::Hide() {
|
| - if (phantom_widget_)
|
| - phantom_widget_->Close();
|
| - phantom_widget_ = NULL;
|
| - if (phantom_widget_start_)
|
| - phantom_widget_start_->Close();
|
| - phantom_widget_start_ = NULL;
|
| +void PhantomWindowController::StartFadeOut() {
|
| + StartFade(false);
|
| }
|
|
|
| -bool PhantomWindowController::IsShowing() const {
|
| - return phantom_widget_ != NULL;
|
| +void PhantomWindowController::Hide() {
|
| + target_visibility_ = false;
|
| + phantom_widget_.reset();
|
| + phantom_widget_start_.reset();
|
| }
|
|
|
| -void PhantomWindowController::AnimationProgressed(
|
| - const gfx::Animation* animation) {
|
| - const gfx::Rect current_bounds =
|
| - animation->CurrentValueBetween(start_bounds_, bounds_in_screen_);
|
| - if (phantom_widget_start_)
|
| - phantom_widget_start_->SetBounds(current_bounds);
|
| - phantom_widget_->SetBounds(current_bounds);
|
| +bool PhantomWindowController::IsShowing() const {
|
| + return target_visibility_;
|
| }
|
|
|
| views::Widget* PhantomWindowController::CreatePhantomWidget(
|
| @@ -184,31 +235,44 @@ views::Widget* PhantomWindowController::CreatePhantomWidget(
|
| kShellWindowId_ShelfContainer);
|
| params.can_activate = false;
|
| params.keep_on_top = true;
|
| + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| phantom_widget->set_focus_on_creation(false);
|
| phantom_widget->Init(params);
|
| phantom_widget->SetVisibilityChangedAnimationsEnabled(false);
|
| phantom_widget->GetNativeWindow()->SetName("PhantomWindow");
|
| phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow);
|
| - views::View* content_view = new views::View;
|
| - content_view->set_background(
|
| - views::Background::CreateBackgroundPainter(true, new EdgePainter));
|
| - phantom_widget->SetContentsView(content_view);
|
| - phantom_widget->SetBounds(bounds_in_screen);
|
| + phantom_widget->SetBounds(GetBoundsWithShadow(bounds_in_screen));
|
| if (phantom_below_window_)
|
| phantom_widget->StackBelow(phantom_below_window_);
|
| else
|
| phantom_widget->StackAbove(window_);
|
|
|
| - // Show the widget after all the setups.
|
| - phantom_widget->Show();
|
| + views::Painter* background_painter;
|
| + if (switches::UseAlternateFrameCaptionButtonStyle()) {
|
| + const int kImages[] = IMAGE_GRID(IDR_AURA_PHANTOM_WINDOW);
|
| + background_painter = views::Painter::CreateImageGridPainter(kImages);
|
| + } else {
|
| + background_painter = new EdgePainter;
|
| + }
|
| + views::View* content_view = new views::View;
|
| + content_view->set_background(
|
| + views::Background::CreateBackgroundPainter(true, background_painter));
|
| + phantom_widget->SetContentsView(content_view);
|
|
|
| // Fade the window in.
|
| ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer();
|
| widget_layer->SetOpacity(0);
|
| - ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator());
|
| - widget_layer->SetOpacity(1);
|
| + AnimateToVisibility(phantom_widget, true);
|
| return phantom_widget;
|
| }
|
|
|
| +void PhantomWindowController::StartFade(bool fade_in) {
|
| + if (target_visibility_ != fade_in) {
|
| + target_visibility_ = fade_in;
|
| + AnimateToVisibility(phantom_widget_.get(), target_visibility_);
|
| + AnimateToVisibility(phantom_widget_start_.get(), target_visibility_);
|
| + }
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace ash
|
|
|