Commit 4acdf65b authored by Ahmed Fakhry's avatar Ahmed Fakhry Committed by Commit Bot

Desks: Fix portrait mode splitview indicators conflict with desks bar

This CL fixes the overlap between the desks bar, and the splitview
drag indicators when in portrait tablet mode. The desks bar is now
shifted down when necessary to make room for the indicators.

BUG=998239
TEST=Manually, Added new tests.

Change-Id: Ic890a8d344a93551c617cb3f2212f19f869ab611
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1787158
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#693888}
parent 91338692
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_utils.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_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_divider.h" #include "ash/wm/splitview/split_view_divider.h"
#include "ash/wm/splitview/split_view_drag_indicators.h" #include "ash/wm/splitview/split_view_drag_indicators.h"
...@@ -266,13 +267,37 @@ gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) { ...@@ -266,13 +267,37 @@ gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) {
// Returns the desks widget bounds in root, given the screen bounds of the // Returns the desks widget bounds in root, given the screen bounds of the
// overview grid. // overview grid.
gfx::Rect GetDesksWidgetBounds(aura::Window* root, gfx::Rect GetDesksWidgetBounds(aura::Window* root,
OverviewSession* overview_session,
const gfx::Rect& overview_grid_screen_bounds) { const gfx::Rect& overview_grid_screen_bounds) {
gfx::Rect desks_widget_root_bounds = overview_grid_screen_bounds; gfx::Rect desks_widget_root_bounds = overview_grid_screen_bounds;
::wm::ConvertRectFromScreen(root, &desks_widget_root_bounds); ::wm::ConvertRectFromScreen(root, &desks_widget_root_bounds);
desks_widget_root_bounds.set_height(DesksBarView::GetBarHeight()); desks_widget_root_bounds.set_height(DesksBarView::GetBarHeight());
// Shift the widget down to make room for the splitview indicator guidance
// when it's shown at the top of the screen when in portrait mode and no other
// windows are snapped.
auto* split_view_drag_indicators =
overview_session->split_view_drag_indicators();
if (split_view_drag_indicators &&
split_view_drag_indicators->current_indicator_state() ==
IndicatorState::kDragArea &&
!IsCurrentScreenOrientationLandscape() &&
!Shell::Get()->split_view_controller()->InSplitViewMode()) {
desks_widget_root_bounds.Offset(0,
overview_grid_screen_bounds.height() *
kHighlightScreenPrimaryAxisRatio +
2 * kHighlightScreenEdgePaddingDp);
}
return screen_util::SnapBoundsToDisplayEdge(desks_widget_root_bounds, root); return screen_util::SnapBoundsToDisplayEdge(desks_widget_root_bounds, root);
} }
// Returns the given |widget|'s bounds in its native window's root coordinates.
gfx::Rect GetWidgetBoundsInRoot(views::Widget* widget) {
auto* window = widget->GetNativeWindow();
return window->GetBoundsInRootWindow();
}
} // namespace } // namespace
// The class to observe the overview window that the dragged tabs will merge // The class to observe the overview window that the dragged tabs will merge
...@@ -599,8 +624,7 @@ void OverviewGrid::SetBoundsAndUpdatePositions( ...@@ -599,8 +624,7 @@ void OverviewGrid::SetBoundsAndUpdatePositions(
const gfx::Rect& bounds_in_screen, const gfx::Rect& bounds_in_screen,
const base::flat_set<OverviewItem*>& ignored_items) { const base::flat_set<OverviewItem*>& ignored_items) {
bounds_ = bounds_in_screen; bounds_ = bounds_in_screen;
if (desks_widget_) MaybeUpdateDesksWidgetBounds();
desks_widget_->SetBounds(GetDesksWidgetBounds(root_window_, bounds_));
PositionWindows(/*animate=*/true, ignored_items); PositionWindows(/*animate=*/true, ignored_items);
} }
...@@ -634,6 +658,16 @@ void OverviewGrid::RearrangeDuringDrag(aura::Window* dragged_window, ...@@ -634,6 +658,16 @@ void OverviewGrid::RearrangeDuringDrag(aura::Window* dragged_window,
} }
} }
void OverviewGrid::MaybeUpdateDesksWidgetBounds() {
if (!desks_widget_)
return;
const gfx::Rect desks_widget_bounds =
GetDesksWidgetBounds(root_window_, overview_session_, bounds_);
if (desks_widget_bounds != GetWidgetBoundsInRoot(desks_widget_.get()))
desks_widget_->SetBounds(desks_widget_bounds);
}
void OverviewGrid::UpdateDropTargetBackgroundVisibility( void OverviewGrid::UpdateDropTargetBackgroundVisibility(
OverviewItem* dragged_item, OverviewItem* dragged_item,
const gfx::PointF& location_in_screen) { const gfx::PointF& location_in_screen) {
...@@ -1354,7 +1388,8 @@ void OverviewGrid::MaybeInitDesksWidget() { ...@@ -1354,7 +1388,8 @@ void OverviewGrid::MaybeInitDesksWidget() {
return; return;
desks_widget_ = DesksBarView::CreateDesksWidget( desks_widget_ = DesksBarView::CreateDesksWidget(
root_window_, GetDesksWidgetBounds(root_window_, bounds_)); root_window_,
GetDesksWidgetBounds(root_window_, overview_session_, bounds_));
desks_bar_view_ = new DesksBarView; desks_bar_view_ = new DesksBarView;
// The following order of function calls is significant: SetContentsView() // The following order of function calls is significant: SetContentsView()
......
...@@ -133,6 +133,9 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver, ...@@ -133,6 +133,9 @@ class ASH_EXPORT OverviewGrid : public aura::WindowObserver,
void RearrangeDuringDrag(aura::Window* dragged_window, void RearrangeDuringDrag(aura::Window* dragged_window,
IndicatorState indicator_state); IndicatorState indicator_state);
// Updates the desks bar widget bounds if necessary.
void MaybeUpdateDesksWidgetBounds();
// Updates the appearance of the drop target to visually indicate when the // Updates the appearance of the drop target to visually indicate when the
// dragged window is being dragged over it. For dragging from the top, pass // dragged window is being dragged over it. For dragging from the top, pass
// null for |dragged_item|. // null for |dragged_item|.
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
#include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/overview_window_drag_controller.h"
#include <algorithm>
#include <memory> #include <memory>
#include <utility>
#include "ash/display/mouse_cursor_event_filter.h" #include "ash/display/mouse_cursor_event_filter.h"
#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_features.h"
...@@ -97,6 +99,22 @@ bool GetVirtualDesksBarEnabled(OverviewItem* item) { ...@@ -97,6 +99,22 @@ bool GetVirtualDesksBarEnabled(OverviewItem* item) {
item->overview_grid()->IsDesksBarViewActive(); item->overview_grid()->IsDesksBarViewActive();
} }
// Runs the given |callback| when this object goes out of scope.
class AtScopeExitRunner {
public:
explicit AtScopeExitRunner(base::OnceClosure callback)
: callback_(std::move(callback)) {
DCHECK(!callback_.is_null());
}
~AtScopeExitRunner() { std::move(callback_).Run(); }
private:
base::OnceClosure callback_;
DISALLOW_COPY_AND_ASSIGN(AtScopeExitRunner);
};
} // namespace } // namespace
OverviewWindowDragController::OverviewWindowDragController( OverviewWindowDragController::OverviewWindowDragController(
...@@ -204,7 +222,8 @@ void OverviewWindowDragController::StartNormalDragMode( ...@@ -204,7 +222,8 @@ void OverviewWindowDragController::StartNormalDragMode(
item_->ScaleUpSelectedItem( item_->ScaleUpSelectedItem(
OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW); OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW);
original_scaled_size_ = item_->target_bounds().size(); original_scaled_size_ = item_->target_bounds().size();
item_->overview_grid()->AddDropTargetForDraggingFromOverview(item_); auto* overview_grid = item_->overview_grid();
overview_grid->AddDropTargetForDraggingFromOverview(item_);
if (should_allow_split_view_) { if (should_allow_split_view_) {
overview_session_->SetSplitViewDragIndicatorsIndicatorState( overview_session_->SetSplitViewDragIndicatorsIndicatorState(
...@@ -228,9 +247,13 @@ void OverviewWindowDragController::StartNormalDragMode( ...@@ -228,9 +247,13 @@ void OverviewWindowDragController::StartNormalDragMode(
item_no_header_size.Enlarge(float{-kWindowMargin * 2}, item_no_header_size.Enlarge(float{-kWindowMargin * 2},
float{-kWindowMargin * 2 - kHeaderHeightDp}); float{-kWindowMargin * 2 - kHeaderHeightDp});
// We must update the desks bar widget bounds before we cache its bounds
// below, in case it needs to be pushed down due to splitview indicators.
overview_grid->MaybeUpdateDesksWidgetBounds();
// Calculate cached values for usage during drag. // Calculate cached values for usage during drag.
desks_bar_bounds_ = gfx::RectF( desks_bar_bounds_ =
item_->overview_grid()->desks_bar_view()->GetBoundsInScreen()); gfx::RectF(overview_grid->desks_bar_view()->GetBoundsInScreen());
shrink_bounds_ = desks_bar_bounds_; shrink_bounds_ = desks_bar_bounds_;
shrink_bounds_.Inset(-item_no_header_size.width() / 2, shrink_bounds_.Inset(-item_no_header_size.width() / 2,
-item_no_header_size.height() / 2); -item_no_header_size.height() / 2);
...@@ -391,6 +414,7 @@ void OverviewWindowDragController::ContinueNormalDrag( ...@@ -391,6 +414,7 @@ void OverviewWindowDragController::ContinueNormalDrag(
// If virtual desks is enabled, we want to gradually shrink the dragged item // If virtual desks is enabled, we want to gradually shrink the dragged item
// as it gets closer to get dropped into a desk mini view. // as it gets closer to get dropped into a desk mini view.
auto* overview_grid = item_->overview_grid();
if (virtual_desks_bar_enabled_) { if (virtual_desks_bar_enabled_) {
// TODO(sammiequon): There is a slight jump especially if we drag from the // TODO(sammiequon): There is a slight jump especially if we drag from the
// corner of a larger overview item, but this is necessary for the time // corner of a larger overview item, but this is necessary for the time
...@@ -407,7 +431,7 @@ void OverviewWindowDragController::ContinueNormalDrag( ...@@ -407,7 +431,7 @@ void OverviewWindowDragController::ContinueNormalDrag(
if (shrink_bounds_.Contains(location_in_screen)) { if (shrink_bounds_.Contains(location_in_screen)) {
// Update the mini views borders by checking if |location_in_screen| // Update the mini views borders by checking if |location_in_screen|
// intersects. // intersects.
item_->overview_grid()->IntersectsWithDesksBar( overview_grid->IntersectsWithDesksBar(
gfx::ToRoundedPoint(location_in_screen), gfx::ToRoundedPoint(location_in_screen),
/*update_desks_bar_drag_details=*/true, /*for_drop=*/false); /*update_desks_bar_drag_details=*/true, /*for_drop=*/false);
...@@ -436,10 +460,15 @@ void OverviewWindowDragController::ContinueNormalDrag( ...@@ -436,10 +460,15 @@ void OverviewWindowDragController::ContinueNormalDrag(
} }
} }
if (should_allow_split_view_) if (should_allow_split_view_) {
UpdateDragIndicatorsAndOverviewGrid(location_in_screen); UpdateDragIndicatorsAndOverviewGrid(location_in_screen);
item_->overview_grid()->UpdateDropTargetBackgroundVisibility( // The newly updated indicator state may cause the desks widget to be pushed
item_, location_in_screen); // down to make room for the top splitview guidance indicator when in
// portrait mode.
overview_grid->MaybeUpdateDesksWidgetBounds();
}
overview_grid->UpdateDropTargetBackgroundVisibility(item_,
location_in_screen);
bounds.set_x(centerpoint.x() - bounds.width() / 2.f); bounds.set_x(centerpoint.x() - bounds.width() / 2.f);
bounds.set_y(centerpoint.y() - bounds.height() / 2.f); bounds.set_y(centerpoint.y() - bounds.height() / 2.f);
...@@ -452,12 +481,13 @@ OverviewWindowDragController::DragResult ...@@ -452,12 +481,13 @@ OverviewWindowDragController::DragResult
OverviewWindowDragController::CompleteNormalDrag( OverviewWindowDragController::CompleteNormalDrag(
const gfx::PointF& location_in_screen) { const gfx::PointF& location_in_screen) {
DCHECK_EQ(current_drag_behavior_, DragBehavior::kNormalDrag); DCHECK_EQ(current_drag_behavior_, DragBehavior::kNormalDrag);
DCHECK(item_->overview_grid()->drop_target_widget()); auto* overview_grid = item_->overview_grid();
DCHECK(overview_grid->drop_target_widget());
if (AreMultiDisplayOverviewAndSplitViewEnabled()) { if (AreMultiDisplayOverviewAndSplitViewEnabled()) {
Shell::Get()->mouse_cursor_filter()->HideSharedEdgeIndicator(); Shell::Get()->mouse_cursor_filter()->HideSharedEdgeIndicator();
item_->DestroyPhantomsForDragging(); item_->DestroyPhantomsForDragging();
} }
item_->overview_grid()->RemoveDropTarget(); overview_grid->RemoveDropTarget();
const gfx::Point rounded_screen_point = const gfx::Point rounded_screen_point =
gfx::ToRoundedPoint(location_in_screen); gfx::ToRoundedPoint(location_in_screen);
...@@ -473,15 +503,28 @@ OverviewWindowDragController::CompleteNormalDrag( ...@@ -473,15 +503,28 @@ OverviewWindowDragController::CompleteNormalDrag(
// orientation was changed. // orientation was changed.
UpdateDragIndicatorsAndOverviewGrid(location_in_screen); UpdateDragIndicatorsAndOverviewGrid(location_in_screen);
overview_session_->SetSplitViewDragIndicatorsIndicatorState( overview_session_->SetSplitViewDragIndicatorsIndicatorState(
IndicatorState::kNone, gfx::Point()); IndicatorState::kNone, rounded_screen_point);
} }
// This function has multiple exit positions, at each we must update the desks
// bar widget bounds. We can't do this before we attempt dropping the window
// on a desk mini_view, since this will change where it is relative to the
// current |location_in_screen|.
AtScopeExitRunner at_exit_runner{base::BindOnce(
[](OverviewGrid* grid) {
DCHECK(grid);
// Overview might have exited if we snapped windows on both sides.
if (Shell::Get()->overview_controller()->InOverviewSession())
grid->MaybeUpdateDesksWidgetBounds();
},
overview_grid)};
// Attempt to move a window to a different desk. // Attempt to move a window to a different desk.
if (virtual_desks_bar_enabled_) { if (virtual_desks_bar_enabled_) {
item_->SetOpacity(original_opacity_); item_->SetOpacity(original_opacity_);
if (item_->overview_grid()->MaybeDropItemOnDeskMiniView( if (overview_grid->MaybeDropItemOnDeskMiniView(rounded_screen_point,
rounded_screen_point, item_)) { item_)) {
// Window was successfully moved to another desk, and |item_| was // Window was successfully moved to another desk, and |item_| was
// removed from the grid. It may never be accessed after this. // removed from the grid. It may never be accessed after this.
item_ = nullptr; item_ = nullptr;
...@@ -537,8 +580,8 @@ void OverviewWindowDragController::UpdateDragIndicatorsAndOverviewGrid( ...@@ -537,8 +580,8 @@ void OverviewWindowDragController::UpdateDragIndicatorsAndOverviewGrid(
} }
item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(), item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(),
indicator_state); indicator_state);
overview_session_->SetSplitViewDragIndicatorsIndicatorState(indicator_state, overview_session_->SetSplitViewDragIndicatorsIndicatorState(
gfx::Point()); indicator_state, gfx::ToRoundedPoint(location_in_screen));
} }
gfx::Rect OverviewWindowDragController::GetWorkAreaOfDisplayBeingDraggedIn() gfx::Rect OverviewWindowDragController::GetWorkAreaOfDisplayBeingDraggedIn()
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "ash/wm/splitview/split_view_drag_indicators.h" #include "ash/wm/splitview/split_view_drag_indicators.h"
#include <utility>
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_animation_types.h" #include "ash/public/cpp/window_animation_types.h"
#include "ash/screen_util.h" #include "ash/screen_util.h"
...@@ -276,6 +278,8 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -276,6 +278,8 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
~SplitViewDragIndicatorsView() override {} ~SplitViewDragIndicatorsView() override {}
SplitViewHighlightView* left_highlight_view() { return left_highlight_view_; }
// Called by parent widget when the state machine changes. Handles setting the // Called by parent widget when the state machine changes. Handles setting the
// opacity and bounds of the highlights and labels. // opacity and bounds of the highlights and labels.
void OnIndicatorTypeChanged(IndicatorState indicator_state) { void OnIndicatorTypeChanged(IndicatorState indicator_state) {
...@@ -321,6 +325,7 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -321,6 +325,7 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
// animate when changing states, but not when bounds or orientation is // animate when changing states, but not when bounds or orientation is
// changed. // changed.
void Layout(bool animate) { void Layout(bool animate) {
// TODO(xdai|afakhry): Attempt to simplify this logic.
const bool landscape = IsCurrentScreenOrientationLandscape(); const bool landscape = IsCurrentScreenOrientationLandscape();
const int display_width = landscape ? width() : height(); const int display_width = landscape ? width() : height();
const int display_height = landscape ? height() : width(); const int display_height = landscape ? height() : width();
...@@ -380,12 +385,15 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -380,12 +385,15 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
aura::Window* root_window = aura::Window* root_window =
GetWidget()->GetNativeWindow()->GetRootWindow(); GetWidget()->GetNativeWindow()->GetRootWindow();
wm::ConvertRectFromScreen(root_window, &preview_area_bounds);
// Preview area should have no overlap with the shelf. // Preview area should have no overlap with the shelf.
preview_area_bounds.Subtract( preview_area_bounds.Subtract(
Shelf::ForWindow(root_window)->GetIdealBounds()); Shelf::ForWindow(root_window)->GetIdealBounds());
const gfx::Rect work_area_bounds = gfx::Rect work_area_bounds =
GetWorkAreaBoundsNoOverlapWithShelf(root_window); GetWorkAreaBoundsNoOverlapWithShelf(root_window);
wm::ConvertRectFromScreen(root_window, &work_area_bounds);
preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y()); preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y());
if (!nix_preview_inset) { if (!nix_preview_inset) {
preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp,
...@@ -641,4 +649,9 @@ bool SplitViewDragIndicators::GetIndicatorTypeVisibilityForTesting( ...@@ -641,4 +649,9 @@ bool SplitViewDragIndicators::GetIndicatorTypeVisibilityForTesting(
0.f; 0.f;
} }
gfx::Rect SplitViewDragIndicators::GetLeftHighlightViewBoundsForTesting()
const {
return indicators_view_->left_highlight_view()->bounds();
}
} // namespace ash } // namespace ash
...@@ -88,6 +88,8 @@ class ASH_EXPORT SplitViewDragIndicators { ...@@ -88,6 +88,8 @@ class ASH_EXPORT SplitViewDragIndicators {
bool GetIndicatorTypeVisibilityForTesting(IndicatorType type) const; bool GetIndicatorTypeVisibilityForTesting(IndicatorType type) const;
gfx::Rect GetLeftHighlightViewBoundsForTesting() const;
IndicatorState current_indicator_state() const { IndicatorState current_indicator_state() const {
return current_indicator_state_; return current_indicator_state_;
} }
......
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