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(
// |item_| will be deleted after RemoveWindowSelectorItem().
aura::Window* window = item_->GetWindow();
const gfx::Rect item_bounds = item_->target_bounds();
window_selector_->RemoveWindowSelectorItem(item_);
split_view_controller_->SnapWindow(window, snap_position);
split_view_controller_->SnapWindow(window, snap_position, item_bounds);
item_ = nullptr;
}
......
......@@ -231,8 +231,10 @@ void WindowSelectorController::OnOverviewButtonTrayLongPressed(
// The transform will be reset later after the window is snapped.
item_to_snap->RestoreWindow(/*reset_transform=*/false);
aura::Window* window = item_to_snap->GetWindow();
const gfx::Rect item_bounds = item_to_snap->target_bounds();
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(
split_view_controller->GetSnappedWindowBoundsInScreen(
window, SplitViewController::RIGHT));
......
......@@ -17,11 +17,11 @@
#include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.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_selector_controller.h"
#include "ash/wm/overview/window_selector_item.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/window_state.h"
#include "ash/wm/window_transient_descendant_iterator.h"
......@@ -204,7 +204,8 @@ bool SplitViewController::IsCurrentScreenOrientationPrimary() const {
}
void SplitViewController::SnapWindow(aura::Window* window,
SnapPosition snap_position) {
SnapPosition snap_position,
const gfx::Rect& window_item_bounds) {
DCHECK(window && CanSnap(window));
DCHECK_NE(snap_position, NONE);
......@@ -237,6 +238,9 @@ void SplitViewController::SnapWindow(aura::Window* 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.
// Since the minimum size of |window| maybe larger than currently bounds in
// |snap_position|.
......@@ -474,6 +478,7 @@ void SplitViewController::EndSplitView() {
black_scrim_layer_.reset();
default_snap_position_ = NONE;
divider_position_ = -1;
overview_window_item_bounds_map_.clear();
UpdateSplitViewStateAndNotifyObservers();
base::RecordAction(base::UserMetricsAction("SplitView_EndSplitView"));
......@@ -500,6 +505,9 @@ void SplitViewController::OnWindowDestroying(aura::Window* window) {
DCHECK(window == left_window_ || window == right_window_);
if (smooth_resize_window_ == window)
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);
}
......@@ -555,12 +563,28 @@ void SplitViewController::OnWindowActivated(ActivationReason reason,
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
// is active.
if (default_snap_position_ == LEFT)
SnapWindow(gained_active, SplitViewController::RIGHT);
else if (default_snap_position_ == RIGHT)
SnapWindow(gained_active, SplitViewController::LEFT);
SnapWindow(gained_active, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
window_item_bounds);
}
void SplitViewController::OnOverviewModeStarting() {
......@@ -602,11 +626,10 @@ void SplitViewController::OnOverviewModeEnding() {
for (const auto& window_selector_item : windows) {
aura::Window* window = window_selector_item->GetWindow();
if (CanSnap(window) && window != GetDefaultSnappedWindow()) {
const gfx::Rect item_bounds = window_selector_item->target_bounds();
window_selector->RemoveWindowSelectorItem(window_selector_item.get());
if (default_snap_position_ == LEFT)
SnapWindow(window, SplitViewController::RIGHT);
else if (default_snap_position_ == RIGHT)
SnapWindow(window, SplitViewController::LEFT);
SnapWindow(window, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
item_bounds);
return;
}
}
......@@ -1136,14 +1159,30 @@ void SplitViewController::RestoreAndActivateSnappedWindow(
aura::Window* window) {
DCHECK(window == left_window_ || window == right_window_);
// Restore the window's transform first if its transform is not identity. In
// this case the window must come from the overview window grid.
// If the snapped window comes from the overview window grid, calculate a good
// 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()) {
for (auto* window_iter : wm::GetTransientTreeIterator(window)) {
ScopedOverviewAnimationSettings animation_settings(
ash::OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW,
window_iter);
window_iter->SetTransform(gfx::Transform());
if (!starting_transform.IsIdentity())
window_iter->SetTransform(starting_transform);
DoSplitviewTransformAnimation(window_iter->layer(),
SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW,
gfx::Transform(), nullptr);
}
}
wm::ActivateWindow(window);
......
......@@ -11,6 +11,7 @@
#include "ash/shell_observer.h"
#include "ash/wm/tablet_mode/tablet_mode_observer.h"
#include "ash/wm/window_state_observer.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/time/time.h"
......@@ -90,8 +91,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// primary orientation.
bool IsCurrentScreenOrientationPrimary() const;
// Snaps window to left/right.
void SnapWindow(aura::Window* window, SnapPosition snap_position);
// Snaps window to left/right. |window_item_bounds| is the bounds of the
// 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
// windows is not snapped.
......@@ -350,6 +355,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// details.
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_;
mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_;
......
......@@ -29,15 +29,21 @@ constexpr base::TimeDelta kLabelAnimationMs =
// The delay before the indicator labels start animating.
constexpr base::TimeDelta kLabelAnimationDelayMs =
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 kPreviewAreaHighlightOpacity = 0.18f;
// Gets the duration, tween type and delay before animation based on |type|.
void GetAnimationValuesForType(SplitviewAnimationType type,
base::TimeDelta* out_duration,
gfx::Tween::Type* out_tween_type,
base::TimeDelta* out_delay) {
void GetAnimationValuesForType(
SplitviewAnimationType type,
base::TimeDelta* out_duration,
gfx::Tween::Type* out_tween_type,
ui::LayerAnimator::PreemptionStrategy* out_preemption_strategy,
base::TimeDelta* out_delay) {
*out_preemption_strategy = ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET;
switch (type) {
case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN:
case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT:
......@@ -71,20 +77,29 @@ void GetAnimationValuesForType(SplitviewAnimationType type,
*out_duration = kOtherFadeInOutMs;
*out_tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
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();
}
// Helper function to apply animation values to |settings|.
void ApplyAnimationSettings(ui::ScopedLayerAnimationSettings* settings,
ui::LayerAnimator* animator,
base::TimeDelta duration,
gfx::Tween::Type tween,
base::TimeDelta delay) {
void ApplyAnimationSettings(
ui::ScopedLayerAnimationSettings* settings,
ui::LayerAnimator* animator,
base::TimeDelta duration,
gfx::Tween::Type tween,
ui::LayerAnimator::PreemptionStrategy preemption_strategy,
base::TimeDelta delay) {
DCHECK_EQ(settings->GetAnimator(), animator);
settings->SetTransitionDuration(duration);
settings->SetTweenType(tween);
settings->SetPreemptionStrategy(preemption_strategy);
if (!delay.is_zero()) {
settings->SetPreemptionStrategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
......@@ -130,12 +145,15 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer,
base::TimeDelta duration;
gfx::Tween::Type tween;
ui::LayerAnimator::PreemptionStrategy preemption_strategy;
base::TimeDelta delay;
GetAnimationValuesForType(type, &duration, &tween, &delay);
GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
&delay);
ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator);
ApplyAnimationSettings(&settings, animator, duration, tween, delay);
ApplyAnimationSettings(&settings, animator, duration, tween,
preemption_strategy, delay);
layer->SetOpacity(target_opacity);
}
......@@ -150,6 +168,7 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN:
case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_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_OUT:
break;
......@@ -160,12 +179,15 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
base::TimeDelta duration;
gfx::Tween::Type tween;
ui::LayerAnimator::PreemptionStrategy preemption_strategy;
base::TimeDelta delay;
GetAnimationValuesForType(type, &duration, &tween, &delay);
GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
&delay);
ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator);
ApplyAnimationSettings(&settings, animator, duration, tween, delay);
ApplyAnimationSettings(&settings, animator, duration, tween,
preemption_strategy, delay);
if (observer)
settings.AddObserver(observer);
layer->SetTransform(target_transform);
......
......@@ -55,6 +55,8 @@ enum SplitviewAnimationType {
// Used to slide in the text labels.
SPLITVIEW_ANIMATION_TEXT_SLIDE_IN,
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|.
......
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