Index: trunk/src/ash/wm/workspace/phantom_window_controller.cc |
=================================================================== |
--- trunk/src/ash/wm/workspace/phantom_window_controller.cc (revision 244088) |
+++ trunk/src/ash/wm/workspace/phantom_window_controller.cc (working copy) |
@@ -12,6 +12,7 @@ |
#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" |
@@ -22,30 +23,10 @@ |
namespace ash { |
namespace internal { |
+// EdgePainter ---------------------------------------------------------------- |
+ |
namespace { |
-// The duration of the show animation. |
-const int kAnimationDurationMs = 200; |
- |
-// 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::ScopedLayerAnimationSettings scoped_setter( |
- widget->GetNativeWindow()->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(kAnimationDurationMs)); |
- widget->SetBounds(new_bounds_in_screen); |
-} |
- |
-// EdgePainter ---------------------------------------------------------------- |
- |
// Paints the background of the phantom window for window snapping. |
class EdgePainter : public views::Painter { |
public: |
@@ -60,6 +41,9 @@ |
DISALLOW_COPY_AND_ASSIGN(EdgePainter); |
}; |
+} // namespace |
+ |
+ |
EdgePainter::EdgePainter() { |
} |
@@ -102,75 +86,95 @@ |
SkIntToScalar(kRoundRectSize), paint); |
} |
-} // namespace |
// PhantomWindowController ---------------------------------------------------- |
PhantomWindowController::PhantomWindowController(aura::Window* window) |
: window_(window), |
- phantom_below_window_(NULL) { |
+ phantom_below_window_(NULL), |
+ phantom_widget_(NULL), |
+ phantom_widget_start_(NULL) { |
} |
PhantomWindowController::~PhantomWindowController() { |
+ Hide(); |
} |
void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { |
- if (bounds_in_screen == target_bounds_in_screen_) |
+ if (bounds_in_screen == bounds_in_screen_) |
return; |
- target_bounds_in_screen_ = bounds_in_screen; |
- |
- gfx::Rect start_bounds_in_screen; |
- if (!phantom_widget_in_target_root_) { |
- start_bounds_in_screen = window_->GetBoundsInScreen(); |
- } else { |
- start_bounds_in_screen = |
- phantom_widget_in_target_root_->GetWindowBoundsInScreen(); |
+ 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(); |
+ else |
+ start_bounds_ = phantom_widget_->GetWindowBoundsInScreen(); |
+ if (phantom_widget_ && |
+ phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) { |
+ phantom_widget_->Close(); |
+ phantom_widget_ = NULL; |
} |
+ if (!phantom_widget_) |
+ phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_); |
- aura::Window* target_root = |
- wm::GetRootWindowMatching(target_bounds_in_screen_); |
- if (!phantom_widget_in_target_root_ || |
- phantom_widget_in_target_root_->GetNativeWindow()->GetRootWindow() != |
- target_root) { |
- phantom_widget_in_target_root_ = |
- CreatePhantomWidget(target_root, start_bounds_in_screen); |
- } |
- AnimateToBounds(phantom_widget_in_target_root_.get(), |
- target_bounds_in_screen_); |
- |
- // Create a secondary widget in a second screen if |start_bounds_in_screen| |
- // 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_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_); |
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_in_screen)) { |
+ root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) { |
start_root = root_windows[i]; |
break; |
} |
} |
} |
- if (start_root == target_root) { |
- phantom_widget_in_start_root_.reset(); |
- } else { |
- if (!phantom_widget_in_start_root_ || |
- phantom_widget_in_start_root_->GetNativeWindow()->GetRootWindow() != |
- start_root) { |
- phantom_widget_in_start_root_ = |
- CreatePhantomWidget(start_root, start_bounds_in_screen); |
- } |
- AnimateToBounds(phantom_widget_in_start_root_.get(), |
- target_bounds_in_screen_); |
+ if (phantom_widget_start_ && |
+ (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root |
+ || start_root == target_root)) { |
+ phantom_widget_start_->Close(); |
+ phantom_widget_start_ = NULL; |
} |
+ 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(); |
} |
-scoped_ptr<views::Widget> PhantomWindowController::CreatePhantomWidget( |
+void PhantomWindowController::Hide() { |
+ if (phantom_widget_) |
+ phantom_widget_->Close(); |
+ phantom_widget_ = NULL; |
+ if (phantom_widget_start_) |
+ phantom_widget_start_->Close(); |
+ phantom_widget_start_ = NULL; |
+} |
+ |
+bool PhantomWindowController::IsShowing() const { |
+ return phantom_widget_ != NULL; |
+} |
+ |
+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); |
+} |
+ |
+views::Widget* PhantomWindowController::CreatePhantomWidget( |
aura::Window* root_window, |
const gfx::Rect& bounds_in_screen) { |
- scoped_ptr<views::Widget> phantom_widget(new views::Widget); |
+ views::Widget* phantom_widget = new views::Widget; |
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
// PhantomWindowController is used by FrameMaximizeButton to highlight the |
@@ -180,7 +184,6 @@ |
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); |
@@ -203,11 +206,8 @@ |
ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer(); |
widget_layer->SetOpacity(0); |
ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator()); |
- scoped_setter.SetTransitionDuration( |
- base::TimeDelta::FromMilliseconds(kAnimationDurationMs)); |
widget_layer->SetOpacity(1); |
- |
- return phantom_widget.Pass(); |
+ return phantom_widget; |
} |
} // namespace internal |