Chromium Code Reviews| 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..12f2aa43ccfb4e62fb226ca6c9fbb41c9963f65b 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,75 @@ |
| 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 = 55; |
| + |
| +// 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_in_screen|. No-op if |widget| |
| +// is NULL. |
| +void AnimateToBounds(views::Widget* widget, |
| + const gfx::Rect& new_bounds_in_screen) { |
| + if (!widget) |
| + return; |
| + |
| + ui::Layer* layer = widget->GetNativeWindow()->layer(); |
| + ui::ScopedLayerAnimationSettings scoped_setter( |
| + layer->GetAnimator()); |
| + scoped_setter.SetTweenType(gfx::Tween::EASE_IN); |
| + scoped_setter.SetPreemptionStrategy( |
| + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
|
sky
2013/12/19 21:25:43
Why do you want strategy?
pkotwicz
2013/12/20 01:57:20
I think that IMMEDIATELY_ANIMATE_TO_NEW_TARGET sho
|
| + scoped_setter.SetTransitionDuration( |
| + base::TimeDelta::FromMilliseconds(kBoundsChangeAnimationDurationMs)); |
| + widget->SetBounds(new_bounds_in_screen); |
| +} |
| + |
| +// Starts a fade in or fade out animation of |widget|. No-op if |widget| is |
| +// NULL. |
| +void AnimateToVisibility(views::Widget* widget, bool new_visibility) { |
|
sky
2013/12/19 21:25:43
Seems like this is the same as an AnimationType of
pkotwicz
2013/12/20 01:57:20
kChildWindowVisibilityChangesAnimatedKey is false
sky
2014/01/06 17:30:05
Can't you temporarily enable animations when you c
|
| + 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)); |
| + if (!new_visibility) |
| + widget->Hide(); |
|
pkotwicz
2013/12/18 19:16:47
Changed so that Hide() gets called before setting
Mr4D (OOO till 08-26)
2013/12/19 17:56:55
I just checked with sky and all you would need to
pkotwicz
2013/12/19 18:18:22
I am unsure if I understand. I need to call both u
|
| + layer->SetOpacity(new_visibility ? 1.0f : 0.0f); |
| +} |
| + |
| +// EdgePainter ---------------------------------------------------------------- |
| + |
| // Paints the background of the phantom window for window snapping. |
| class EdgePainter : public views::Painter { |
| public: |
| @@ -41,9 +107,6 @@ class EdgePainter : public views::Painter { |
| DISALLOW_COPY_AND_ASSIGN(EdgePainter); |
| }; |
| -} // namespace |
| - |
| - |
| EdgePainter::EdgePainter() { |
| } |
| @@ -86,89 +149,87 @@ 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_) |
| + if (GetBoundsWithShadow(bounds_in_screen) == target_bounds_in_screen_ && |
| + target_visibility_) { |
| 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. |
| - if (!phantom_widget_) |
| - start_bounds_ = window_->GetBoundsInScreen(); |
| + } |
| + if (target_phantom_widget_ && |
| + !target_phantom_widget_->GetNativeView()->layer()->IsDrawn()) { |
|
pkotwicz
2013/12/18 19:16:47
I made the phantom window start animating from |wi
|
| + target_phantom_widget_.reset(); |
| + start_phantom_widget_.reset(); |
| + } |
| + StartFade(true); |
| + |
| + target_bounds_in_screen_ = GetBoundsWithShadow(bounds_in_screen); |
| + gfx::Rect start_bounds; |
| + if (!target_phantom_widget_) |
| + start_bounds = GetBoundsWithShadow(window_->GetBoundsInScreen()); |
|
pkotwicz
2013/12/18 19:16:47
Fixed when GetBoundsWithShadow() is called. In the
|
| else |
| - start_bounds_ = phantom_widget_->GetWindowBoundsInScreen(); |
| - if (phantom_widget_ && |
| - phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) { |
| - phantom_widget_->Close(); |
| - phantom_widget_ = NULL; |
| + start_bounds = target_phantom_widget_->GetWindowBoundsInScreen(); |
| + |
| + aura::Window* target_root = |
| + wm::GetRootWindowMatching(target_bounds_in_screen_); |
| + if (!target_phantom_widget_ || |
| + target_phantom_widget_->GetNativeWindow()->GetRootWindow() != |
| + target_root) { |
| + target_phantom_widget_.reset( |
| + CreatePhantomWidget(target_root, start_bounds)); |
| } |
| - if (!phantom_widget_) |
| - phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_); |
| + AnimateToBounds(target_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) { |
| + start_phantom_widget_.reset(); |
| + } else { |
| + if (!start_phantom_widget_ || |
| + start_phantom_widget_->GetNativeWindow()->GetRootWindow() != |
| + start_root) { |
| + start_phantom_widget_.reset( |
| + CreatePhantomWidget(start_root, start_bounds)); |
| + } |
| + AnimateToBounds(start_phantom_widget_.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; |
| + target_phantom_widget_.reset(); |
| + start_phantom_widget_.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 +245,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); |
| 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(target_phantom_widget_.get(), target_visibility_); |
| + AnimateToVisibility(start_phantom_widget_.get(), target_visibility_); |
| + } |
| +} |
| + |
| } // namespace internal |
| } // namespace ash |