Commit 8cf3df27 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

Reland "overview: Fixed aspect ratio for overview items in splitview."

This is a reland of fac39a19

Original change's description:
> overview: Fixed aspect ratio for overview items in splitview.
> 
> Overview items now match the aspect ratio of the window bounds if they
> get snapped. This will happen if splitview is active on either side, or
> if the window is getting dragged close enough to an edge. A videos of
> before and after this patch is in the bug.
> 
> Follow up:
> Make this work for tablet mode with 6 or more windows. In that case
> the positioning logic follows a different path.
> Match the exact dimensions in the spec, this patch only does rough
> clipping.
> 
> Test: added tests, manual
> Bug: 1011973
> Change-Id: I3d9d341c54b58d0e86440045ad1408ca3a0fd27d
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1849175
> Commit-Queue: Sammie Quon <sammiequon@chromium.org>
> Reviewed-by: Xiaoqian Dai <xdai@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#707426}

Bug: 1011973
Change-Id: I6ff9ce5c4ecebf2a2006abd26821c5c12b82e5e3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1872453Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707876}
parent 30508e5a
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "ash/wm/overview/overview_item.h" #include "ash/wm/overview/overview_item.h"
#include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_session.h"
#include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/overview_window_drag_controller.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/resize_shadow_controller.h" #include "ash/wm/resize_shadow_controller.h"
#include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_constants.h"
...@@ -304,36 +305,6 @@ gfx::Rect GetGridBoundsInScreen(aura::Window* root_window, ...@@ -304,36 +305,6 @@ gfx::Rect GetGridBoundsInScreen(aura::Window* root_window,
return bounds; return bounds;
} }
// Get the grid bounds if a window is snapped in splitview, or what they will be
// when snapped based on |indicator_state|.
gfx::Rect GetGridBoundsInScreenForSplitview(
aura::Window* window,
base::Optional<IndicatorState> indicator_state = base::nullopt) {
SplitViewController* split_view_controller = SplitViewController::Get(window);
auto state = split_view_controller->state();
// If we are in splitview mode already just use the given state, otherwise
// convert |indicator_state| to a splitview state.
if (!split_view_controller->InSplitViewMode() && indicator_state) {
if (*indicator_state == IndicatorState::kPreviewAreaLeft)
state = SplitViewController::State::kLeftSnapped;
else if (*indicator_state == IndicatorState::kPreviewAreaRight)
state = SplitViewController::State::kRightSnapped;
}
switch (state) {
case SplitViewController::State::kLeftSnapped:
return split_view_controller->GetSnappedWindowBoundsInScreen(
SplitViewController::RIGHT);
case SplitViewController::State::kRightSnapped:
return split_view_controller->GetSnappedWindowBoundsInScreen(
SplitViewController::LEFT);
default:
return screen_util::
GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(window);
}
}
gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) { gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) {
const int horizontal_inset = const int horizontal_inset =
gfx::ToFlooredInt(std::min(kOverviewInsetRatio * grid_bounds.width(), gfx::ToFlooredInt(std::min(kOverviewInsetRatio * grid_bounds.width(),
...@@ -811,6 +782,7 @@ void OverviewGrid::OnWindowDragStarted(aura::Window* dragged_window, ...@@ -811,6 +782,7 @@ void OverviewGrid::OnWindowDragStarted(aura::Window* dragged_window,
bool animate) { bool animate) {
DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); DCHECK_EQ(dragged_window->GetRootWindow(), root_window_);
DCHECK(!drop_target_widget_); DCHECK(!drop_target_widget_);
dragged_window_ = dragged_window;
drop_target_widget_ = CreateDropTargetWidget(dragged_window, animate); drop_target_widget_ = CreateDropTargetWidget(dragged_window, animate);
overview_session_->AddItem(drop_target_widget_->GetNativeWindow(), overview_session_->AddItem(drop_target_widget_->GetNativeWindow(),
/*reposition=*/true, animate); /*reposition=*/true, animate);
...@@ -825,6 +797,7 @@ void OverviewGrid::OnWindowDragStarted(aura::Window* dragged_window, ...@@ -825,6 +797,7 @@ void OverviewGrid::OnWindowDragStarted(aura::Window* dragged_window,
void OverviewGrid::OnWindowDragContinued(aura::Window* dragged_window, void OverviewGrid::OnWindowDragContinued(aura::Window* dragged_window,
const gfx::PointF& location_in_screen, const gfx::PointF& location_in_screen,
IndicatorState indicator_state) { IndicatorState indicator_state) {
DCHECK_EQ(dragged_window_, dragged_window);
DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); DCHECK_EQ(dragged_window->GetRootWindow(), root_window_);
RearrangeDuringDrag(dragged_window, indicator_state); RearrangeDuringDrag(dragged_window, indicator_state);
...@@ -869,8 +842,10 @@ void OverviewGrid::OnWindowDragEnded(aura::Window* dragged_window, ...@@ -869,8 +842,10 @@ void OverviewGrid::OnWindowDragEnded(aura::Window* dragged_window,
const gfx::PointF& location_in_screen, const gfx::PointF& location_in_screen,
bool should_drop_window_into_overview, bool should_drop_window_into_overview,
bool snap) { bool snap) {
DCHECK_EQ(dragged_window_, dragged_window);
DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); DCHECK_EQ(dragged_window->GetRootWindow(), root_window_);
DCHECK(drop_target_widget_.get()); DCHECK(drop_target_widget_.get());
dragged_window_ = nullptr;
// Add the dragged window into drop target in overview if // Add the dragged window into drop target in overview if
// |should_drop_window_into_overview| is true. Only consider add the dragged // |should_drop_window_into_overview| is true. Only consider add the dragged
...@@ -1511,7 +1486,8 @@ void OverviewGrid::EndScroll() { ...@@ -1511,7 +1486,8 @@ void OverviewGrid::EndScroll() {
items_scrolling_bounds_.clear(); items_scrolling_bounds_.clear();
presentation_time_recorder_.reset(); presentation_time_recorder_.reset();
PositionWindows(/*animate=*/false); if (!overview_session_->is_shutting_down())
PositionWindows(/*animate=*/false);
} }
void OverviewGrid::MaybeInitDesksWidget() { void OverviewGrid::MaybeInitDesksWidget() {
...@@ -1742,11 +1718,36 @@ bool OverviewGrid::FitWindowRectsInBounds( ...@@ -1742,11 +1718,36 @@ bool OverviewGrid::FitWindowRectsInBounds(
continue; continue;
} }
const gfx::RectF target_bounds = window_list_[i]->GetTargetBoundsInScreen(); gfx::RectF target_bounds = window_list_[i]->GetTargetBoundsInScreen();
int width = std::max( float scale = window_list_[i]->GetItemScale(item_size);
1, gfx::ToFlooredInt(target_bounds.width() *
window_list_[i]->GetItemScale(item_size)) + // The drop target, unlike the other windows has its bounds set directly, so
2 * kWindowMargin); // |GetTargetBoundsInScreen()| won't return the value we want. Instead, get
// the scale from the window it was meant to be a placeholder for.
if (IsDropTargetWindow(window_list_[i]->GetWindow())) {
aura::Window* dragged_window = nullptr;
OverviewItem* item =
overview_session_->window_drag_controller()
? overview_session_->window_drag_controller()->item()
: nullptr;
if (item)
dragged_window = item->GetWindow();
else if (dragged_window_)
dragged_window = dragged_window_;
if (dragged_window && dragged_window->parent()) {
target_bounds = ::ash::GetTargetBoundsInScreen(dragged_window);
const gfx::SizeF inset_size(item_size.width(),
item_size.height() - 2 * kWindowMargin);
scale = ScopedOverviewTransformWindow::GetItemScale(
target_bounds.size(), inset_size,
dragged_window->GetProperty(aura::client::kTopViewInset),
kHeaderHeightDp);
}
}
int width = std::max(1, gfx::ToFlooredInt(target_bounds.width() * scale) +
2 * kWindowMargin);
switch (window_list_[i]->GetWindowDimensionsType()) { switch (window_list_[i]->GetWindowDimensionsType()) {
case ScopedOverviewTransformWindow::GridWindowFillMode::kLetterBoxed: case ScopedOverviewTransformWindow::GridWindowFillMode::kLetterBoxed:
width = ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold * width = ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold *
...@@ -1760,6 +1761,36 @@ bool OverviewGrid::FitWindowRectsInBounds( ...@@ -1760,6 +1761,36 @@ bool OverviewGrid::FitWindowRectsInBounds(
break; break;
} }
const bool is_landscape = IsCurrentScreenOrientationLandscape();
// Get the bounds of the window if there is a snapped window or a window
// about to be snapped.
base::Optional<gfx::RectF> split_view_bounds =
GetSplitviewBoundsMaintainingAspectRatio(window_list_[i]->GetWindow());
gfx::Size unclipped_size;
if (split_view_bounds) {
if (is_landscape) {
unclipped_size.set_width(width - 2 * kWindowMargin);
unclipped_size.set_height(height - 2 * kWindowMargin);
// For landscape mode, shrink |width| so that the aspect ratio matches
// that of |split_view_bounds|.
width =
std::max(1, gfx::ToFlooredInt(split_view_bounds->width() * scale) +
2 * kWindowMargin);
} else {
// For portrait mode, we want |height| to stay the same, so calculate
// what the unclipped height would be based on |split_view_bounds|.
width =
split_view_bounds->width() * height / split_view_bounds->height();
int unclipped_height =
(target_bounds.height() * width) / target_bounds.width();
unclipped_size.set_width(width);
unclipped_size.set_height(unclipped_height);
}
}
window_list_[i]->set_unclipped_size(
unclipped_size.IsEmpty() ? base::nullopt
: base::make_optional(unclipped_size));
if (left + width > bounds.right()) { if (left + width > bounds.right()) {
// Move to the next row if possible. // Move to the next row if possible.
if (*out_min_right > left) if (*out_min_right > left)
...@@ -1778,10 +1809,10 @@ bool OverviewGrid::FitWindowRectsInBounds( ...@@ -1778,10 +1809,10 @@ bool OverviewGrid::FitWindowRectsInBounds(
} }
// Position the current rect. // Position the current rect.
(*out_rects)[i] = gfx::RectF(gfx::Rect(left, top, width, height)); (*out_rects)[i] = gfx::RectF(left, top, width, height);
// Increment horizontal position using sanitized positive |width()|. // Increment horizontal position using sanitized positive |width|.
left += gfx::ToRoundedInt((*out_rects)[i].width()); left += width;
*out_max_bottom = top + height; *out_max_bottom = top + height;
} }
......
...@@ -465,6 +465,10 @@ class ASH_EXPORT OverviewGrid : public SplitViewObserver, ...@@ -465,6 +465,10 @@ class ASH_EXPORT OverviewGrid : public SplitViewObserver,
// Records the presentation time of scrolling the grid in overview mode. // Records the presentation time of scrolling the grid in overview mode.
std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_; std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_;
// Weak pointer to the window that is being dragged from the top, if there is
// one.
aura::Window* dragged_window_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(OverviewGrid); DISALLOW_COPY_AND_ASSIGN(OverviewGrid);
}; };
......
...@@ -1019,6 +1019,8 @@ void OverviewItem::OnWindowDestroying(aura::Window* window) { ...@@ -1019,6 +1019,8 @@ void OverviewItem::OnWindowDestroying(aura::Window* window) {
return; return;
if (is_being_dragged_) { if (is_being_dragged_) {
DCHECK_EQ(this, overview_session_->window_drag_controller()->item());
overview_session_->window_drag_controller()->ResetGesture();
Shell::Get()->overview_controller()->UnpauseOcclusionTracker( Shell::Get()->overview_controller()->UnpauseOcclusionTracker(
kOcclusionPauseDurationForDrag); kOcclusionPauseDurationForDrag);
} }
...@@ -1173,9 +1175,15 @@ void OverviewItem::SetItemBounds(const gfx::RectF& target_bounds, ...@@ -1173,9 +1175,15 @@ void OverviewItem::SetItemBounds(const gfx::RectF& target_bounds,
screen_rect.set_size(screen_size); screen_rect.set_size(screen_size);
const int top_view_inset = transform_window_.GetTopInset(); const int top_view_inset = transform_window_.GetTopInset();
gfx::RectF transformed_bounds = target_bounds;
// Update |transformed_bounds| to match the unclipped size of the window, so
// we transform the window to the correct size.
if (unclipped_size_)
transformed_bounds.set_size(gfx::SizeF(*unclipped_size_));
gfx::RectF overview_item_bounds = gfx::RectF overview_item_bounds =
transform_window_.ShrinkRectToFitPreservingAspectRatio( transform_window_.ShrinkRectToFitPreservingAspectRatio(
screen_rect, target_bounds, top_view_inset, kHeaderHeightDp); screen_rect, transformed_bounds, top_view_inset, kHeaderHeightDp);
const gfx::Transform transform = const gfx::Transform transform =
gfx::TransformBetweenRects(screen_rect, overview_item_bounds); gfx::TransformBetweenRects(screen_rect, overview_item_bounds);
...@@ -1186,17 +1194,24 @@ void OverviewItem::SetItemBounds(const gfx::RectF& target_bounds, ...@@ -1186,17 +1194,24 @@ void OverviewItem::SetItemBounds(const gfx::RectF& target_bounds,
return; return;
} }
ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings; {
transform_window_.BeginScopedAnimation(animation_type, &animation_settings); ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings;
if (animation_type == OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW && transform_window_.BeginScopedAnimation(animation_type, &animation_settings);
!animation_settings.empty()) { if (animation_type ==
animation_settings.front()->AddObserver(new AnimationObserver{ OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW &&
base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted, !animation_settings.empty()) {
weak_ptr_factory_.GetWeakPtr()), animation_settings.front()->AddObserver(new AnimationObserver{
base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded, base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted,
weak_ptr_factory_.GetWeakPtr())}); weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded,
weak_ptr_factory_.GetWeakPtr())});
}
SetTransform(window, transform);
} }
SetTransform(window, transform);
transform_window_.SetClipping(unclipped_size_
? GetWindowTargetBoundsWithInsets().size()
: gfx::SizeF());
} }
void OverviewItem::CreateWindowLabel() { void OverviewItem::CreateWindowLabel() {
......
...@@ -259,6 +259,10 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate, ...@@ -259,6 +259,10 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate,
void set_disable_mask(bool disable) { disable_mask_ = disable; } void set_disable_mask(bool disable) { disable_mask_ = disable; }
void set_unclipped_size(base::Optional<gfx::Size> unclipped_size) {
unclipped_size_ = unclipped_size;
}
views::ImageButton* GetCloseButtonForTesting(); views::ImageButton* GetCloseButtonForTesting();
float GetCloseButtonVisibilityForTesting() const; float GetCloseButtonVisibilityForTesting() const;
float GetTitlebarOpacityForTesting() const; float GetTitlebarOpacityForTesting() const;
...@@ -347,7 +351,9 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate, ...@@ -347,7 +351,9 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate,
// The contained Window's wrapper. // The contained Window's wrapper.
ScopedOverviewTransformWindow transform_window_; ScopedOverviewTransformWindow transform_window_;
// The target bounds this overview item is fit within. // The target bounds this overview item is fit within. When in splitview,
// |item_widget_| is fit within these bounds, but the window itself is
// transformed to |unclipped_size_|, and then clipped.
gfx::RectF target_bounds_; gfx::RectF target_bounds_;
// True if running SetItemBounds. This prevents recursive calls resulting from // True if running SetItemBounds. This prevents recursive calls resulting from
...@@ -411,9 +417,18 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate, ...@@ -411,9 +417,18 @@ class ASH_EXPORT OverviewItem : public CaptionContainerView::EventDelegate,
bool prepared_for_overview_ = false; bool prepared_for_overview_ = false;
// Stores the last translations of the windows affected by SetBounds. Used for // This has a value when there is a snapped window, or a window about to be
// ease of calculations when swiping away overview mode using home launcher // snapped (triggering a splitview preview area). This will be set when items
// gesture. // are positioned in OverviewGrid. The bounds delivered in |SetBounds| are the
// true bounds of this item, but we want to maintain the aspect ratio of the
// window, who's bounds are not set to split view size. So in |SetItemBounds|,
// we transform the window not to |target_bounds_| but to this value, and then
// apply clipping on the window to |target_bounds_|.
base::Optional<gfx::Size> unclipped_size_ = base::nullopt;
// Stores the last translations of the windows affected by |SetBounds|. Used
// for ease of calculations when swiping away overview mode using home
// launcher gesture.
base::flat_map<aura::Window*, int> translation_y_map_; base::flat_map<aura::Window*, int> translation_y_map_;
// The shadow around the overview window. Shadows the original window, not // The shadow around the overview window. Shadows the original window, not
......
...@@ -3820,6 +3820,92 @@ TEST_P(SplitViewOverviewSessionTest, DraggingUnsnappableAppWithSplitView) { ...@@ -3820,6 +3820,92 @@ TEST_P(SplitViewOverviewSessionTest, DraggingUnsnappableAppWithSplitView) {
EXPECT_EQ(expected_grid_bounds, GetGridBounds()); EXPECT_EQ(expected_grid_bounds, GetGridBounds());
} }
TEST_P(SplitViewOverviewSessionTest, Clipping) {
// Helper to check if two rectangles have roughly the same aspect ratio. They
// may be off by a bit due to insets and overview headers, but should have
// roughly the same shape.
auto aspect_ratio_near = [](const gfx::Rect& rect1, const gfx::Rect& rect2) {
DCHECK_GT(rect1.height(), 0);
DCHECK_GT(rect2.height(), 0);
constexpr float kEpsilon = 0.1f;
const float rect1_aspect_ratio =
float{rect1.width()} / float{rect1.height()};
const float rect2_aspect_ratio =
float{rect2.width()} / float{rect2.height()};
return std::abs(rect2_aspect_ratio - rect1_aspect_ratio) < kEpsilon;
};
std::unique_ptr<aura::Window> window1 = CreateTestWindow();
std::unique_ptr<aura::Window> window2 = CreateTestWindow();
for (bool portrait : {false, true}) {
SCOPED_TRACE(portrait ? "Portrait" : "Landscape");
if (portrait) {
ScreenOrientationControllerTestApi test_api(
Shell::Get()->screen_orientation_controller());
test_api.SetDisplayRotation(display::Display::ROTATE_90,
display::Display::RotationSource::ACTIVE);
}
const gfx::Rect clipping1 = window1->layer()->clip_rect();
const gfx::Rect clipping2 = window2->layer()->clip_rect();
const gfx::Rect maximized_bounds =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
window1.get());
const gfx::Rect split_view_bounds_right =
split_view_controller()->GetSnappedWindowBoundsInScreen(
SplitViewController::SnapPosition::RIGHT);
ToggleOverview();
// Tests that in regular overview, the clipping is unchanged.
ASSERT_TRUE(overview_controller()->InOverviewSession());
EXPECT_EQ(clipping1, window1->layer()->clip_rect());
EXPECT_EQ(clipping2, window2->layer()->clip_rect());
OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
overview_session()->InitiateDrag(item1,
item1->target_bounds().CenterPoint(),
/*is_touch_dragging=*/false);
// Tests that after we drag to a preview area, the items target bounds have
// a matching aspect ratio to what the window would have if it were to be
// snapped in splitview. The window clipping should match this, but the
// windows regular bounds remain unchanged (maximized).
overview_session()->Drag(item1, gfx::PointF());
EXPECT_EQ(IndicatorState::kPreviewAreaLeft,
overview_session()
->split_view_drag_indicators()
->current_indicator_state());
EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty());
EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(),
split_view_bounds_right));
EXPECT_TRUE(aspect_ratio_near(gfx::ToEnclosedRect(item2->target_bounds()),
split_view_bounds_right));
EXPECT_TRUE(
aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds));
// Tests that after snapping, the aspect ratios should be the same as being
// in the preview area.
overview_session()->CompleteDrag(item1, gfx::PointF());
ASSERT_EQ(SplitViewController::State::kLeftSnapped,
split_view_controller()->state());
EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty());
EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(),
split_view_bounds_right));
EXPECT_TRUE(aspect_ratio_near(gfx::ToEnclosedRect(item2->target_bounds()),
split_view_bounds_right));
EXPECT_TRUE(
aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds));
// Tests that the clipping is reset after exiting overview.
EndSplitView();
ToggleOverview();
EXPECT_EQ(clipping1, window1->layer()->clip_rect());
EXPECT_EQ(clipping2, window1->layer()->clip_rect());
}
}
// Tests that if there is only one window in the MRU window list in the overview // Tests that if there is only one window in the MRU window list in the overview
// mode, snapping the window to one side of the screen will not end the overview // mode, snapping the window to one side of the screen will not end the overview
// mode even if there is no more window left in the overview window grid. // mode even if there is no more window left in the overview window grid.
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/scoped_animation_disabler.h" #include "ash/scoped_animation_disabler.h"
#include "ash/screen_util.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/overview/cleanup_animation_observer.h" #include "ash/wm/overview/cleanup_animation_observer.h"
#include "ash/wm/overview/delayed_animation_observer_impl.h" #include "ash/wm/overview/delayed_animation_observer_impl.h"
...@@ -218,6 +219,58 @@ void MaximizeIfSnapped(aura::Window* window) { ...@@ -218,6 +219,58 @@ void MaximizeIfSnapped(aura::Window* window) {
} }
} }
// Get the grid bounds if a window is snapped in splitview, or what they will be
// when snapped based on |indicator_state|.
gfx::Rect GetGridBoundsInScreenForSplitview(
aura::Window* window,
base::Optional<IndicatorState> indicator_state) {
auto* split_view_controller =
SplitViewController::Get(Shell::GetPrimaryRootWindow());
auto state = split_view_controller->state();
// If we are in splitview mode already just use the given state, otherwise
// convert |indicator_state| to a splitview state.
if (!split_view_controller->InSplitViewMode() && indicator_state) {
if (*indicator_state == IndicatorState::kPreviewAreaLeft)
state = SplitViewController::State::kLeftSnapped;
else if (*indicator_state == IndicatorState::kPreviewAreaRight)
state = SplitViewController::State::kRightSnapped;
}
switch (state) {
case SplitViewController::State::kLeftSnapped:
return split_view_controller->GetSnappedWindowBoundsInScreen(
SplitViewController::RIGHT);
case SplitViewController::State::kRightSnapped:
return split_view_controller->GetSnappedWindowBoundsInScreen(
SplitViewController::LEFT);
default:
return screen_util::
GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(window);
}
}
base::Optional<gfx::RectF> GetSplitviewBoundsMaintainingAspectRatio(
aura::Window* window) {
if (!Shell::Get()->tablet_mode_controller()->InTabletMode())
return base::nullopt;
auto* overview_session =
Shell::Get()->overview_controller()->overview_session();
DCHECK(overview_session);
// TODO(sammiequon): This does not work for drag from top as they have
// different drag indicators object as regular overview.
auto indicator_state =
overview_session->split_view_drag_indicators()->current_indicator_state();
if (!SplitViewController::Get(Shell::GetPrimaryRootWindow())
->InSplitViewMode() &&
!SplitViewDragIndicators::IsPreviewAreaState(indicator_state)) {
return base::nullopt;
}
return base::make_optional(gfx::RectF(GetGridBoundsInScreenForSplitview(
window, base::make_optional(indicator_state))));
}
bool ShouldUseTabletModeGridLayout() { bool ShouldUseTabletModeGridLayout() {
return base::FeatureList::IsEnabled(features::kNewOverviewLayout) && return base::FeatureList::IsEnabled(features::kNewOverviewLayout) &&
Shell::Get()->tablet_mode_controller()->InTabletMode(); Shell::Get()->tablet_mode_controller()->InTabletMode();
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/wm/overview/overview_animation_type.h" #include "ash/wm/overview/overview_animation_type.h"
#include "ash/wm/splitview/split_view_drag_indicators.h"
#include "ash/wm/window_transient_descendant_iterator.h" #include "ash/wm/window_transient_descendant_iterator.h"
#include "base/optional.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/layer_type.h" #include "ui/compositor/layer_type.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -76,6 +78,18 @@ bool IsSlidingOutOverviewFromShelf(); ...@@ -76,6 +78,18 @@ bool IsSlidingOutOverviewFromShelf();
// Maximize the window if it is snapped without animation. // Maximize the window if it is snapped without animation.
void MaximizeIfSnapped(aura::Window* window); void MaximizeIfSnapped(aura::Window* window);
// Get the grid bounds if a window is snapped in splitview, or what they will be
// when snapped based on |indicator_state|.
gfx::Rect GetGridBoundsInScreenForSplitview(
aura::Window* window,
base::Optional<IndicatorState> indicator_state = base::nullopt);
// Gets the bounds of a window if it were to be snapped or about to be snapped
// in splitview. Returns nothing if we are not in tablet mode, or if we aren't
// in splitview, or if we aren't showing a splitview preview.
base::Optional<gfx::RectF> GetSplitviewBoundsMaintainingAspectRatio(
aura::Window* window);
// Check if kNewOverviewLayout is enabled for tablet mode. // Check if kNewOverviewLayout is enabled for tablet mode.
bool ShouldUseTabletModeGridLayout(); bool ShouldUseTabletModeGridLayout();
......
...@@ -580,10 +580,10 @@ void OverviewWindowDragController::UpdateDragIndicatorsAndOverviewGrid( ...@@ -580,10 +580,10 @@ void OverviewWindowDragController::UpdateDragIndicatorsAndOverviewGrid(
snap_position_ = GetSnapPosition(location_in_screen); snap_position_ = GetSnapPosition(location_in_screen);
IndicatorState indicator_state = IndicatorState indicator_state =
GetIndicatorState(item_->GetWindow(), snap_position_); GetIndicatorState(item_->GetWindow(), snap_position_);
item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(),
indicator_state);
overview_session_->SetSplitViewDragIndicatorsIndicatorState( overview_session_->SetSplitViewDragIndicatorsIndicatorState(
indicator_state, gfx::ToRoundedPoint(location_in_screen)); indicator_state, gfx::ToRoundedPoint(location_in_screen));
item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(),
indicator_state);
} }
gfx::Rect OverviewWindowDragController::GetWorkAreaOfDisplayBeingDraggedIn() gfx::Rect OverviewWindowDragController::GetWorkAreaOfDisplayBeingDraggedIn()
......
...@@ -285,6 +285,22 @@ void ScopedOverviewTransformWindow::SetOpacity(float opacity) { ...@@ -285,6 +285,22 @@ void ScopedOverviewTransformWindow::SetOpacity(float opacity) {
window->layer()->SetOpacity(opacity); window->layer()->SetOpacity(opacity);
} }
void ScopedOverviewTransformWindow::SetClipping(const gfx::SizeF& size) {
// If width or height are 0, restore the overview clipping.
if (size.IsEmpty()) {
window_->layer()->SetClipRect(overview_clip_rect_);
return;
}
// Compute the clip rect. Transform affects the clip rect, so take that into
// account.
gfx::Rect clip_rect;
const gfx::Vector2dF scale = window_->layer()->GetTargetTransform().Scale2d();
clip_rect.set_width(size.width() / scale.x());
clip_rect.set_height(size.height() / scale.y());
window_->layer()->SetClipRect(clip_rect);
}
gfx::RectF ScopedOverviewTransformWindow::ShrinkRectToFitPreservingAspectRatio( gfx::RectF ScopedOverviewTransformWindow::ShrinkRectToFitPreservingAspectRatio(
const gfx::RectF& rect, const gfx::RectF& rect,
const gfx::RectF& bounds, const gfx::RectF& bounds,
...@@ -417,6 +433,7 @@ void ScopedOverviewTransformWindow::UpdateRoundedCorners(bool show, ...@@ -417,6 +433,7 @@ void ScopedOverviewTransformWindow::UpdateRoundedCorners(bool show,
ScopedOverviewAnimationSettings settings( ScopedOverviewAnimationSettings settings(
OVERVIEW_ANIMATION_FRAME_HEADER_CLIP, window_); OVERVIEW_ANIMATION_FRAME_HEADER_CLIP, window_);
layer->SetClipRect(clip_rect); layer->SetClipRect(clip_rect);
overview_clip_rect_ = clip_rect;
} }
} }
......
...@@ -112,6 +112,10 @@ class ASH_EXPORT ScopedOverviewTransformWindow ...@@ -112,6 +112,10 @@ class ASH_EXPORT ScopedOverviewTransformWindow
// Sets the opacity of the managed windows. // Sets the opacity of the managed windows.
void SetOpacity(float opacity); void SetOpacity(float opacity);
// Apply clipping on the managed windows. If |size| is empty, then restore
// |overview_clip_rect_|.
void SetClipping(const gfx::SizeF& size);
// Returns |rect| having been shrunk to fit within |bounds| (preserving the // Returns |rect| having been shrunk to fit within |bounds| (preserving the
// aspect ratio). Takes into account a window header that is |top_view_inset| // aspect ratio). Takes into account a window header that is |top_view_inset|
// tall in the original window getting replaced by a window caption that is // tall in the original window getting replaced by a window caption that is
...@@ -211,6 +215,11 @@ class ASH_EXPORT ScopedOverviewTransformWindow ...@@ -211,6 +215,11 @@ class ASH_EXPORT ScopedOverviewTransformWindow
// mode. // mode.
gfx::Rect original_clip_rect_; gfx::Rect original_clip_rect_;
// The clippng on the layer of |window_| after entering overview mode.
// Additional clipping may be added, and when that additional clipping is
// removed, we should go back to this clipping.
gfx::Rect overview_clip_rect_;
std::unique_ptr<ScopedOverviewHideWindows> hidden_transient_children_; std::unique_ptr<ScopedOverviewHideWindows> hidden_transient_children_;
base::WeakPtrFactory<ScopedOverviewTransformWindow> weak_ptr_factory_{this}; base::WeakPtrFactory<ScopedOverviewTransformWindow> weak_ptr_factory_{this};
......
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