Commit fd4c46a1 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

Cros splitscreen: Animate the overview window to its snapped position.

Define SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW. And also animate the
overview window from its position in overview grid to its snapped postion.

Bug: 822486
Change-Id: I64a48b33012c428a5529dfea58f048f30c043e73
Reviewed-on: https://chromium-review.googlesource.com/972562Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545580}
parent 3748dde9
...@@ -303,8 +303,9 @@ void OverviewWindowDragController::SnapWindow( ...@@ -303,8 +303,9 @@ void OverviewWindowDragController::SnapWindow(
// |item_| will be deleted after RemoveWindowSelectorItem(). // |item_| will be deleted after RemoveWindowSelectorItem().
aura::Window* window = item_->GetWindow(); aura::Window* window = item_->GetWindow();
const gfx::Rect item_bounds = item_->target_bounds();
window_selector_->RemoveWindowSelectorItem(item_); window_selector_->RemoveWindowSelectorItem(item_);
split_view_controller_->SnapWindow(window, snap_position); split_view_controller_->SnapWindow(window, snap_position, item_bounds);
item_ = nullptr; item_ = nullptr;
} }
......
...@@ -231,8 +231,10 @@ void WindowSelectorController::OnOverviewButtonTrayLongPressed( ...@@ -231,8 +231,10 @@ void WindowSelectorController::OnOverviewButtonTrayLongPressed(
// The transform will be reset later after the window is snapped. // The transform will be reset later after the window is snapped.
item_to_snap->RestoreWindow(/*reset_transform=*/false); item_to_snap->RestoreWindow(/*reset_transform=*/false);
aura::Window* window = item_to_snap->GetWindow(); aura::Window* window = item_to_snap->GetWindow();
const gfx::Rect item_bounds = item_to_snap->target_bounds();
window_selector_->RemoveWindowSelectorItem(item_to_snap); window_selector_->RemoveWindowSelectorItem(item_to_snap);
split_view_controller->SnapWindow(window, SplitViewController::LEFT); split_view_controller->SnapWindow(window, SplitViewController::LEFT,
item_bounds);
window_selector_->SetBoundsForWindowGridsInScreen( window_selector_->SetBoundsForWindowGridsInScreen(
split_view_controller->GetSnappedWindowBoundsInScreen( split_view_controller->GetSnappedWindowBoundsInScreen(
window, SplitViewController::RIGHT)); window, SplitViewController::RIGHT));
......
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
#include "ash/system/toast/toast_data.h" #include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h" #include "ash/system/toast/toast_manager.h"
#include "ash/wm/mru_window_tracker.h" #include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/overview/window_selector_item.h" #include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/splitview/split_view_divider.h" #include "ash/wm/splitview/split_view_divider.h"
#include "ash/wm/splitview/split_view_utils.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ash/wm/window_transient_descendant_iterator.h" #include "ash/wm/window_transient_descendant_iterator.h"
...@@ -204,7 +204,8 @@ bool SplitViewController::IsCurrentScreenOrientationPrimary() const { ...@@ -204,7 +204,8 @@ bool SplitViewController::IsCurrentScreenOrientationPrimary() const {
} }
void SplitViewController::SnapWindow(aura::Window* window, void SplitViewController::SnapWindow(aura::Window* window,
SnapPosition snap_position) { SnapPosition snap_position,
const gfx::Rect& window_item_bounds) {
DCHECK(window && CanSnap(window)); DCHECK(window && CanSnap(window));
DCHECK_NE(snap_position, NONE); DCHECK_NE(snap_position, NONE);
...@@ -237,6 +238,9 @@ void SplitViewController::SnapWindow(aura::Window* window, ...@@ -237,6 +238,9 @@ void SplitViewController::SnapWindow(aura::Window* window,
} }
StartObserving(window); StartObserving(window);
if (!window_item_bounds.IsEmpty())
overview_window_item_bounds_map_[window] = window_item_bounds;
// Update the divider position and window bounds before snapping a new window. // Update the divider position and window bounds before snapping a new window.
// Since the minimum size of |window| maybe larger than currently bounds in // Since the minimum size of |window| maybe larger than currently bounds in
// |snap_position|. // |snap_position|.
...@@ -474,6 +478,7 @@ void SplitViewController::EndSplitView() { ...@@ -474,6 +478,7 @@ void SplitViewController::EndSplitView() {
black_scrim_layer_.reset(); black_scrim_layer_.reset();
default_snap_position_ = NONE; default_snap_position_ = NONE;
divider_position_ = -1; divider_position_ = -1;
overview_window_item_bounds_map_.clear();
UpdateSplitViewStateAndNotifyObservers(); UpdateSplitViewStateAndNotifyObservers();
base::RecordAction(base::UserMetricsAction("SplitView_EndSplitView")); base::RecordAction(base::UserMetricsAction("SplitView_EndSplitView"));
...@@ -500,6 +505,9 @@ void SplitViewController::OnWindowDestroying(aura::Window* window) { ...@@ -500,6 +505,9 @@ void SplitViewController::OnWindowDestroying(aura::Window* window) {
DCHECK(window == left_window_ || window == right_window_); DCHECK(window == left_window_ || window == right_window_);
if (smooth_resize_window_ == window) if (smooth_resize_window_ == window)
smooth_resize_window_ = nullptr; smooth_resize_window_ = nullptr;
auto iter = overview_window_item_bounds_map_.find(window);
if (iter != overview_window_item_bounds_map_.end())
overview_window_item_bounds_map_.erase(iter);
OnSnappedWindowMinimizedOrDestroyed(window); OnSnappedWindowMinimizedOrDestroyed(window);
} }
...@@ -555,12 +563,28 @@ void SplitViewController::OnWindowActivated(ActivationReason reason, ...@@ -555,12 +563,28 @@ void SplitViewController::OnWindowActivated(ActivationReason reason,
return; return;
} }
// If the to-be-snapped window comes from the overview grid, get its overview
// window item bounds before trying to snap it.
gfx::Rect window_item_bounds;
if (Shell::Get()->window_selector_controller()->IsSelecting()) {
WindowSelector* window_selector =
Shell::Get()->window_selector_controller()->window_selector();
WindowGrid* current_grid = window_selector->GetGridWithRootWindow(
GetDefaultSnappedWindow()->GetRootWindow());
if (current_grid) {
WindowSelectorItem* item =
current_grid->GetWindowSelectorItemContaining(gained_active);
if (item) {
window_item_bounds = item->target_bounds();
window_selector->RemoveWindowSelectorItem(item);
}
}
}
// Snap the window on the non-default side of the screen if split view mode // Snap the window on the non-default side of the screen if split view mode
// is active. // is active.
if (default_snap_position_ == LEFT) SnapWindow(gained_active, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
SnapWindow(gained_active, SplitViewController::RIGHT); window_item_bounds);
else if (default_snap_position_ == RIGHT)
SnapWindow(gained_active, SplitViewController::LEFT);
} }
void SplitViewController::OnOverviewModeStarting() { void SplitViewController::OnOverviewModeStarting() {
...@@ -602,11 +626,10 @@ void SplitViewController::OnOverviewModeEnding() { ...@@ -602,11 +626,10 @@ void SplitViewController::OnOverviewModeEnding() {
for (const auto& window_selector_item : windows) { for (const auto& window_selector_item : windows) {
aura::Window* window = window_selector_item->GetWindow(); aura::Window* window = window_selector_item->GetWindow();
if (CanSnap(window) && window != GetDefaultSnappedWindow()) { if (CanSnap(window) && window != GetDefaultSnappedWindow()) {
const gfx::Rect item_bounds = window_selector_item->target_bounds();
window_selector->RemoveWindowSelectorItem(window_selector_item.get()); window_selector->RemoveWindowSelectorItem(window_selector_item.get());
if (default_snap_position_ == LEFT) SnapWindow(window, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
SnapWindow(window, SplitViewController::RIGHT); item_bounds);
else if (default_snap_position_ == RIGHT)
SnapWindow(window, SplitViewController::LEFT);
return; return;
} }
} }
...@@ -1136,14 +1159,30 @@ void SplitViewController::RestoreAndActivateSnappedWindow( ...@@ -1136,14 +1159,30 @@ void SplitViewController::RestoreAndActivateSnappedWindow(
aura::Window* window) { aura::Window* window) {
DCHECK(window == left_window_ || window == right_window_); DCHECK(window == left_window_ || window == right_window_);
// Restore the window's transform first if its transform is not identity. In // If the snapped window comes from the overview window grid, calculate a good
// this case the window must come from the overview window grid. // starting transform based on the overview window item's bounds.
gfx::Transform starting_transform;
auto iter = overview_window_item_bounds_map_.find(window);
if (iter != overview_window_item_bounds_map_.end()) {
const gfx::Rect item_bounds = iter->second;
overview_window_item_bounds_map_.erase(iter);
// Calculate the starting transform based on the window's expected snapped
// bounds and its window item bounds in overview.
const gfx::Rect snapped_bounds = GetSnappedWindowBoundsInScreen(
window, (window == left_window_) ? LEFT : RIGHT);
starting_transform = ScopedTransformOverviewWindow::GetTransformForRect(
snapped_bounds, item_bounds);
}
// Restore the window's transform first if it's not identity.
if (!window->layer()->GetTargetTransform().IsIdentity()) { if (!window->layer()->GetTargetTransform().IsIdentity()) {
for (auto* window_iter : wm::GetTransientTreeIterator(window)) { for (auto* window_iter : wm::GetTransientTreeIterator(window)) {
ScopedOverviewAnimationSettings animation_settings( if (!starting_transform.IsIdentity())
ash::OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW, window_iter->SetTransform(starting_transform);
window_iter); DoSplitviewTransformAnimation(window_iter->layer(),
window_iter->SetTransform(gfx::Transform()); SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW,
gfx::Transform(), nullptr);
} }
} }
wm::ActivateWindow(window); wm::ActivateWindow(window);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "ash/shell_observer.h" #include "ash/shell_observer.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "ash/wm/window_state_observer.h" #include "ash/wm/window_state_observer.h"
#include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -90,8 +91,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -90,8 +91,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// primary orientation. // primary orientation.
bool IsCurrentScreenOrientationPrimary() const; bool IsCurrentScreenOrientationPrimary() const;
// Snaps window to left/right. // Snaps window to left/right. |window_item_bounds| is the bounds of the
void SnapWindow(aura::Window* window, SnapPosition snap_position); // overview window item in overview. It's empty if the snapped window doesn't
// come from overview grid.
void SnapWindow(aura::Window* window,
SnapPosition snap_position,
const gfx::Rect& window_item_bounds = gfx::Rect());
// Swaps the left and right windows. This will do nothing if one of the // Swaps the left and right windows. This will do nothing if one of the
// windows is not snapped. // windows is not snapped.
...@@ -350,6 +355,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -350,6 +355,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// details. // details.
aura::Window* smooth_resize_window_ = nullptr; aura::Window* smooth_resize_window_ = nullptr;
// The map from a to-be-snapped window to its overview item's bounds if the
// window comes from the overview.
base::flat_map<aura::Window*, gfx::Rect> overview_window_item_bounds_map_;
base::ObserverList<Observer> observers_; base::ObserverList<Observer> observers_;
mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_; mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_;
......
...@@ -29,15 +29,21 @@ constexpr base::TimeDelta kLabelAnimationMs = ...@@ -29,15 +29,21 @@ constexpr base::TimeDelta kLabelAnimationMs =
// The delay before the indicator labels start animating. // The delay before the indicator labels start animating.
constexpr base::TimeDelta kLabelAnimationDelayMs = constexpr base::TimeDelta kLabelAnimationDelayMs =
base::TimeDelta::FromMilliseconds(167); base::TimeDelta::FromMilliseconds(167);
// The time duration for the window transformation animations.
constexpr base::TimeDelta kWindowTransformMs =
base::TimeDelta::FromMilliseconds(300);
constexpr float kHighlightOpacity = 0.3f; constexpr float kHighlightOpacity = 0.3f;
constexpr float kPreviewAreaHighlightOpacity = 0.18f; constexpr float kPreviewAreaHighlightOpacity = 0.18f;
// Gets the duration, tween type and delay before animation based on |type|. // Gets the duration, tween type and delay before animation based on |type|.
void GetAnimationValuesForType(SplitviewAnimationType type, void GetAnimationValuesForType(
SplitviewAnimationType type,
base::TimeDelta* out_duration, base::TimeDelta* out_duration,
gfx::Tween::Type* out_tween_type, gfx::Tween::Type* out_tween_type,
ui::LayerAnimator::PreemptionStrategy* out_preemption_strategy,
base::TimeDelta* out_delay) { base::TimeDelta* out_delay) {
*out_preemption_strategy = ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET;
switch (type) { switch (type) {
case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN: case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN:
case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT: case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT:
...@@ -71,20 +77,29 @@ void GetAnimationValuesForType(SplitviewAnimationType type, ...@@ -71,20 +77,29 @@ void GetAnimationValuesForType(SplitviewAnimationType type,
*out_duration = kOtherFadeInOutMs; *out_duration = kOtherFadeInOutMs;
*out_tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN; *out_tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
return; return;
case SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW:
*out_duration = kWindowTransformMs;
*out_tween_type = gfx::Tween::EASE_OUT;
*out_preemption_strategy =
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET;
return;
} }
NOTREACHED(); NOTREACHED();
} }
// Helper function to apply animation values to |settings|. // Helper function to apply animation values to |settings|.
void ApplyAnimationSettings(ui::ScopedLayerAnimationSettings* settings, void ApplyAnimationSettings(
ui::ScopedLayerAnimationSettings* settings,
ui::LayerAnimator* animator, ui::LayerAnimator* animator,
base::TimeDelta duration, base::TimeDelta duration,
gfx::Tween::Type tween, gfx::Tween::Type tween,
ui::LayerAnimator::PreemptionStrategy preemption_strategy,
base::TimeDelta delay) { base::TimeDelta delay) {
DCHECK_EQ(settings->GetAnimator(), animator); DCHECK_EQ(settings->GetAnimator(), animator);
settings->SetTransitionDuration(duration); settings->SetTransitionDuration(duration);
settings->SetTweenType(tween); settings->SetTweenType(tween);
settings->SetPreemptionStrategy(preemption_strategy);
if (!delay.is_zero()) { if (!delay.is_zero()) {
settings->SetPreemptionStrategy( settings->SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
...@@ -130,12 +145,15 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer, ...@@ -130,12 +145,15 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer,
base::TimeDelta duration; base::TimeDelta duration;
gfx::Tween::Type tween; gfx::Tween::Type tween;
ui::LayerAnimator::PreemptionStrategy preemption_strategy;
base::TimeDelta delay; base::TimeDelta delay;
GetAnimationValuesForType(type, &duration, &tween, &delay); GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
&delay);
ui::LayerAnimator* animator = layer->GetAnimator(); ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator); ui::ScopedLayerAnimationSettings settings(animator);
ApplyAnimationSettings(&settings, animator, duration, tween, delay); ApplyAnimationSettings(&settings, animator, duration, tween,
preemption_strategy, delay);
layer->SetOpacity(target_opacity); layer->SetOpacity(target_opacity);
} }
...@@ -150,6 +168,7 @@ void DoSplitviewTransformAnimation(ui::Layer* layer, ...@@ -150,6 +168,7 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN: case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN:
case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT: case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT:
case SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT: case SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT:
case SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW:
case SPLITVIEW_ANIMATION_TEXT_SLIDE_IN: case SPLITVIEW_ANIMATION_TEXT_SLIDE_IN:
case SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT: case SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT:
break; break;
...@@ -160,12 +179,15 @@ void DoSplitviewTransformAnimation(ui::Layer* layer, ...@@ -160,12 +179,15 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
base::TimeDelta duration; base::TimeDelta duration;
gfx::Tween::Type tween; gfx::Tween::Type tween;
ui::LayerAnimator::PreemptionStrategy preemption_strategy;
base::TimeDelta delay; base::TimeDelta delay;
GetAnimationValuesForType(type, &duration, &tween, &delay); GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
&delay);
ui::LayerAnimator* animator = layer->GetAnimator(); ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator); ui::ScopedLayerAnimationSettings settings(animator);
ApplyAnimationSettings(&settings, animator, duration, tween, delay); ApplyAnimationSettings(&settings, animator, duration, tween,
preemption_strategy, delay);
if (observer) if (observer)
settings.AddObserver(observer); settings.AddObserver(observer);
layer->SetTransform(target_transform); layer->SetTransform(target_transform);
......
...@@ -55,6 +55,8 @@ enum SplitviewAnimationType { ...@@ -55,6 +55,8 @@ enum SplitviewAnimationType {
// Used to slide in the text labels. // Used to slide in the text labels.
SPLITVIEW_ANIMATION_TEXT_SLIDE_IN, SPLITVIEW_ANIMATION_TEXT_SLIDE_IN,
SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT, SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT,
// Used to apply window transform on the selector item after it gets snapped.
SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW,
}; };
// Animates |layer|'s opacity based on |type|. // Animates |layer|'s opacity based on |type|.
......
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