Commit ca9a3f3e authored by Min Chen's avatar Min Chen Committed by Commit Bot

Update split view divider position on work area bounds.

Work area is not always starts from the top of the display, e.g, docked
magnifier will put a view port window at the top area of the display.
This will cause that in portrait screen orientation, the height of the
work area is not always larger than the width of the work area. This cl
tried to fix this by updating the divider position on
|divider_closest_ratio_| instead on relying on the longer side of the
work area.
This cl also fixed the wrong bounds of the preview area, which was set
in its own view coordinate. So should special consider the case that
work area is not from the top of the display too.

Bug: 866680, 897900
Change-Id: I86a98aee52ecbd706385cda0a639e5182997914b
Reviewed-on: https://chromium-review.googlesource.com/c/1292833
Commit-Queue: Min Chen <minch@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602364}
parent 1af52b71
...@@ -594,6 +594,7 @@ void SplitViewController::EndSplitView(EndReason end_reason) { ...@@ -594,6 +594,7 @@ void SplitViewController::EndSplitView(EndReason end_reason) {
black_scrim_layer_.reset(); black_scrim_layer_.reset();
default_snap_position_ = NONE; default_snap_position_ = NONE;
divider_position_ = -1; divider_position_ = -1;
divider_closest_ratio_ = 0.f;
snapping_window_transformed_bounds_map_.clear(); snapping_window_transformed_bounds_map_.clear();
UpdateSplitViewStateAndNotifyObservers(); UpdateSplitViewStateAndNotifyObservers();
...@@ -830,18 +831,24 @@ void SplitViewController::OnDisplayMetricsChanged( ...@@ -830,18 +831,24 @@ void SplitViewController::OnDisplayMetricsChanged(
return; return;
} }
// Update |divider_position_| if the top/left window changes. if ((metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION) ||
if ((metrics & (display::DisplayObserver::DISPLAY_METRIC_ROTATION)) && (metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) {
(IsPrimaryOrientation(previous_screen_orientation) !=
IsCurrentScreenOrientationPrimary())) {
const int work_area_long_length = GetDividerEndPosition();
const gfx::Size divider_size = SplitViewDivider::GetDividerSize( const gfx::Size divider_size = SplitViewDivider::GetDividerSize(
display.work_area(), GetCurrentScreenOrientation(), display.work_area(), GetCurrentScreenOrientation(), false);
false /* is_dragging */); const int divider_thickness =
const int divider_short_length =
std::min(divider_size.width(), divider_size.height()); std::min(divider_size.width(), divider_size.height());
// Set default |divider_closest_ratio_| to kFixedPositionRatios[1].
if (!divider_closest_ratio_)
divider_closest_ratio_ = kFixedPositionRatios[1];
// Reverse the position ratio if top/left window changes.
if (IsPrimaryOrientation(previous_screen_orientation) !=
IsCurrentScreenOrientationPrimary()) {
divider_closest_ratio_ = 1.f - divider_closest_ratio_;
}
divider_position_ = divider_position_ =
work_area_long_length - divider_short_length - divider_position_; std::floor(divider_closest_ratio_ * GetDividerEndPosition()) -
std::floor(divider_thickness / 2.f);
} }
// For other display configuration changes, we only move the divider to the // For other display configuration changes, we only move the divider to the
...@@ -996,7 +1003,7 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition( ...@@ -996,7 +1003,7 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition(
right_window_min_size = right_window_->delegate()->GetMinimumSize(); right_window_min_size = right_window_->delegate()->GetMinimumSize();
bool is_primary = IsCurrentScreenOrientationPrimary(); bool is_primary = IsCurrentScreenOrientationPrimary();
int long_length = GetDividerEndPosition(); int divider_end_position = GetDividerEndPosition();
// The distance from the current resizing position to the left or right side // The distance from the current resizing position to the left or right side
// of the screen. Note: left or right side here means the side of the // of the screen. Note: left or right side here means the side of the
// |left_window_| or |right_window_|. // |left_window_| or |right_window_|.
...@@ -1021,11 +1028,11 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition( ...@@ -1021,11 +1028,11 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition(
min_right_length = right_window_min_size.height(); min_right_length = right_window_min_size.height();
} }
if (left_window_distance < long_length * kOneThirdPositionRatio || if (left_window_distance < divider_end_position * kOneThirdPositionRatio ||
left_window_distance < min_left_length) { left_window_distance < min_left_length) {
return LEFT; return LEFT;
} }
if (right_window_distance < long_length * kOneThirdPositionRatio || if (right_window_distance < divider_end_position * kOneThirdPositionRatio ||
right_window_distance < min_right_length) { right_window_distance < min_right_length) {
return RIGHT; return RIGHT;
} }
...@@ -1105,12 +1112,12 @@ void SplitViewController::MoveDividerToClosestFixedPosition() { ...@@ -1105,12 +1112,12 @@ void SplitViewController::MoveDividerToClosestFixedPosition() {
// extract the center from |divider_position_|. The result will also be the // extract the center from |divider_position_|. The result will also be the
// center of the divider, so extract the origin, unless the result is on of // center of the divider, so extract the origin, unless the result is on of
// the endpoints. // the endpoints.
int work_area_long_length = GetDividerEndPosition(); int divider_end_position = GetDividerEndPosition();
float closest_ratio = FindClosestPositionRatio( divider_closest_ratio_ = FindClosestPositionRatio(
divider_position_ + std::floor(divider_thickness / 2.f), divider_position_ + std::floor(divider_thickness / 2.f),
work_area_long_length); divider_end_position);
divider_position_ = std::floor(work_area_long_length * closest_ratio); divider_position_ = std::floor(divider_end_position * divider_closest_ratio_);
if (closest_ratio > 0.f && closest_ratio < 1.f) if (divider_closest_ratio_ > 0.f && divider_closest_ratio_ < 1.f)
divider_position_ -= std::floor(divider_thickness / 2.f); divider_position_ -= std::floor(divider_thickness / 2.f);
} }
...@@ -1136,7 +1143,8 @@ aura::Window* SplitViewController::GetActiveWindowAfterResizingUponExit() { ...@@ -1136,7 +1143,8 @@ aura::Window* SplitViewController::GetActiveWindowAfterResizingUponExit() {
int SplitViewController::GetDividerEndPosition() { int SplitViewController::GetDividerEndPosition() {
const gfx::Rect work_area_bounds = const gfx::Rect work_area_bounds =
GetDisplayWorkAreaBoundsInScreen(GetDefaultSnappedWindow()); GetDisplayWorkAreaBoundsInScreen(GetDefaultSnappedWindow());
return std::max(work_area_bounds.width(), work_area_bounds.height()); return IsCurrentScreenOrientationLandscape() ? work_area_bounds.width()
: work_area_bounds.height();
} }
void SplitViewController::OnWindowSnapped(aura::Window* window) { void SplitViewController::OnWindowSnapped(aura::Window* window) {
...@@ -1235,7 +1243,6 @@ void SplitViewController::GetDividerOptionalPositionRatios( ...@@ -1235,7 +1243,6 @@ void SplitViewController::GetDividerOptionalPositionRatios(
is_left_or_top ? right_window_ : left_window_; is_left_or_top ? right_window_ : left_window_;
bool is_landscape = IsCurrentScreenOrientationLandscape(); bool is_landscape = IsCurrentScreenOrientationLandscape();
int long_length = GetDividerEndPosition();
float min_size_left_ratio = 0.f, min_size_right_ratio = 0.f; float min_size_left_ratio = 0.f, min_size_right_ratio = 0.f;
int min_left_size = 0, min_right_size = 0; int min_left_size = 0, min_right_size = 0;
if (left_or_top_window && left_or_top_window->delegate()) { if (left_or_top_window && left_or_top_window->delegate()) {
...@@ -1247,8 +1254,11 @@ void SplitViewController::GetDividerOptionalPositionRatios( ...@@ -1247,8 +1254,11 @@ void SplitViewController::GetDividerOptionalPositionRatios(
min_right_size = is_landscape ? min_size.width() : min_size.height(); min_right_size = is_landscape ? min_size.width() : min_size.height();
} }
min_size_left_ratio = static_cast<float>(min_left_size) / long_length; int divider_end_position = GetDividerEndPosition();
min_size_right_ratio = static_cast<float>(min_right_size) / long_length; min_size_left_ratio =
static_cast<float>(min_left_size) / divider_end_position;
min_size_right_ratio =
static_cast<float>(min_right_size) / divider_end_position;
if (min_size_left_ratio <= kOneThirdPositionRatio) if (min_size_left_ratio <= kOneThirdPositionRatio)
position_ratios->push_back(kOneThirdPositionRatio); position_ratios->push_back(kOneThirdPositionRatio);
......
...@@ -264,8 +264,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -264,8 +264,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// needs to be activated. Returns nullptr if there is no such window. // needs to be activated. Returns nullptr if there is no such window.
aura::Window* GetActiveWindowAfterResizingUponExit(); aura::Window* GetActiveWindowAfterResizingUponExit();
// Returns the maximum value of the |divider_position_|. It should always be // Returns the maximum value of the |divider_position_|. It is the width of
// the length of the longer side of the current display's work area bounds. // the current display's work area bounds in landscape orientation, or height
// of the current display's work area bounds in portrait orientation.
int GetDividerEndPosition(); int GetDividerEndPosition();
// Called after a to-be-snapped window |window| got snapped. It updates the // Called after a to-be-snapped window |window| got snapped. It updates the
...@@ -384,8 +385,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -384,8 +385,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// The window observer that obseves the tab-dragged window. // The window observer that obseves the tab-dragged window.
std::unique_ptr<TabDraggedWindowObserver> dragged_window_observer_; std::unique_ptr<TabDraggedWindowObserver> dragged_window_observer_;
// The distance between the origin of the divider and the origin of the screen // The distance between the origin of the divider and the origin of the
// in screen coordinates. // current display's work area in screen coordinates.
// |<--- divider_position_ --->| // |<--- divider_position_ --->|
// ---------------------------------------------------------- // ----------------------------------------------------------
// | | | | // | | | |
...@@ -394,6 +395,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -394,6 +395,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// ---------------------------------------------------------- // ----------------------------------------------------------
int divider_position_ = -1; int divider_position_ = -1;
// The closest position ratio of divider among kFixedPositionRatios,
// kOneThirdPositionRatio and kTwoThirdPositionRatio based on current
// |divider_position_|. Used to update |divider_position_| on work area
// changes.
float divider_closest_ratio_ = 0.f;
// The location of the previous mouse/gesture event in screen coordinates. // The location of the previous mouse/gesture event in screen coordinates.
gfx::Point previous_event_location_; gfx::Point previous_event_location_;
......
...@@ -167,6 +167,10 @@ class SplitViewControllerTest : public AshTestBase { ...@@ -167,6 +167,10 @@ class SplitViewControllerTest : public AshTestBase {
int divider_position() { return split_view_controller()->divider_position(); } int divider_position() { return split_view_controller()->divider_position(); }
float divider_closest_ratio() {
return split_view_controller()->divider_closest_ratio_;
}
protected: protected:
class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate { class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate {
public: public:
...@@ -1656,6 +1660,65 @@ TEST_F(SplitViewControllerTest, AdjustTransientChildBounds) { ...@@ -1656,6 +1660,65 @@ TEST_F(SplitViewControllerTest, AdjustTransientChildBounds) {
EndSplitView(); EndSplitView();
} }
// Tests the divider closest position ratio if work area is not starts from the
// top of the display.
TEST_F(SplitViewControllerTest, DividerClosestRatioOnWorkArea) {
UpdateDisplay("1200x800");
// Docked magnifier will put a view port window on the top of the display.
Shell::Get()->docked_magnifier_controller()->SetEnabled(true);
int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
display::DisplayManager* display_manager = Shell::Get()->display_manager();
display::test::ScopedSetInternalDisplayId set_internal(display_manager,
display_id);
ScreenOrientationControllerTestApi test_api(
Shell::Get()->screen_orientation_controller());
ui::test::EventGenerator* generator = GetEventGenerator();
ASSERT_EQ(OrientationLockType::kLandscapePrimary,
test_api.GetCurrentOrientation());
const gfx::Rect bounds(0, 0, 200, 200);
std::unique_ptr<aura::Window> window(CreateWindow(bounds));
split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
test_api.SetDisplayRotation(display::Display::ROTATE_90,
display::Display::RotationSource::ACTIVE);
EXPECT_EQ(OrientationLockType::kPortraitSecondary,
test_api.GetCurrentOrientation());
EXPECT_EQ(divider_closest_ratio(), 0.5f);
test_api.SetDisplayRotation(display::Display::ROTATE_0,
display::Display::RotationSource::ACTIVE);
EXPECT_EQ(OrientationLockType::kLandscapePrimary,
test_api.GetCurrentOrientation());
EXPECT_EQ(divider_closest_ratio(), 0.5f);
gfx::Rect divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false);
gfx::Rect workarea_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window.get());
generator->set_current_location(divider_bounds.CenterPoint());
// Drag the divider to one third position of the work area's width.
generator->DragMouseTo(
gfx::Point(workarea_bounds.width() * 0.33f, workarea_bounds.y()));
EXPECT_EQ(divider_closest_ratio(), 0.33f);
// Divider closest position ratio changed from one third to two thirds if
// left/top window changes.
test_api.SetDisplayRotation(display::Display::ROTATE_90,
display::Display::RotationSource::ACTIVE);
EXPECT_EQ(OrientationLockType::kPortraitSecondary,
test_api.GetCurrentOrientation());
EXPECT_EQ(divider_closest_ratio(), 0.67f);
// Divider closest position ratio is kept as one third if left/top window
// doesn't changes.
test_api.SetDisplayRotation(display::Display::ROTATE_270,
display::Display::RotationSource::ACTIVE);
EXPECT_EQ(OrientationLockType::kPortraitPrimary,
test_api.GetCurrentOrientation());
EXPECT_EQ(divider_closest_ratio(), 0.33f);
}
// Test the tab-dragging related functionalities in tablet mode. Tab(s) can be // Test the tab-dragging related functionalities in tablet mode. Tab(s) can be
// dragged out of a window and then put in split view mode or merge into another // dragged out of a window and then put in split view mode or merge into another
// window. // window.
......
...@@ -356,6 +356,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -356,6 +356,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
GetWidget()->GetNativeWindow(), preview_left GetWidget()->GetNativeWindow(), preview_left
? SplitViewController::LEFT ? SplitViewController::LEFT
: SplitViewController::RIGHT); : SplitViewController::RIGHT);
gfx::Rect work_area_bounds = Shell::Get()
->split_view_controller()
->GetDisplayWorkAreaBoundsInScreen(
GetWidget()->GetNativeWindow());
preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y());
preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp); kHighlightScreenEdgePaddingDp);
......
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