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) {
black_scrim_layer_.reset();
default_snap_position_ = NONE;
divider_position_ = -1;
divider_closest_ratio_ = 0.f;
snapping_window_transformed_bounds_map_.clear();
UpdateSplitViewStateAndNotifyObservers();
......@@ -830,18 +831,24 @@ void SplitViewController::OnDisplayMetricsChanged(
return;
}
// Update |divider_position_| if the top/left window changes.
if ((metrics & (display::DisplayObserver::DISPLAY_METRIC_ROTATION)) &&
(IsPrimaryOrientation(previous_screen_orientation) !=
IsCurrentScreenOrientationPrimary())) {
const int work_area_long_length = GetDividerEndPosition();
if ((metrics & display::DisplayObserver::DISPLAY_METRIC_ROTATION) ||
(metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) {
const gfx::Size divider_size = SplitViewDivider::GetDividerSize(
display.work_area(), GetCurrentScreenOrientation(),
false /* is_dragging */);
const int divider_short_length =
display.work_area(), GetCurrentScreenOrientation(), false);
const int divider_thickness =
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_ =
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
......@@ -996,7 +1003,7 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition(
right_window_min_size = right_window_->delegate()->GetMinimumSize();
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
// of the screen. Note: left or right side here means the side of the
// |left_window_| or |right_window_|.
......@@ -1021,11 +1028,11 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition(
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) {
return LEFT;
}
if (right_window_distance < long_length * kOneThirdPositionRatio ||
if (right_window_distance < divider_end_position * kOneThirdPositionRatio ||
right_window_distance < min_right_length) {
return RIGHT;
}
......@@ -1105,12 +1112,12 @@ void SplitViewController::MoveDividerToClosestFixedPosition() {
// 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
// the endpoints.
int work_area_long_length = GetDividerEndPosition();
float closest_ratio = FindClosestPositionRatio(
int divider_end_position = GetDividerEndPosition();
divider_closest_ratio_ = FindClosestPositionRatio(
divider_position_ + std::floor(divider_thickness / 2.f),
work_area_long_length);
divider_position_ = std::floor(work_area_long_length * closest_ratio);
if (closest_ratio > 0.f && closest_ratio < 1.f)
divider_end_position);
divider_position_ = std::floor(divider_end_position * divider_closest_ratio_);
if (divider_closest_ratio_ > 0.f && divider_closest_ratio_ < 1.f)
divider_position_ -= std::floor(divider_thickness / 2.f);
}
......@@ -1136,7 +1143,8 @@ aura::Window* SplitViewController::GetActiveWindowAfterResizingUponExit() {
int SplitViewController::GetDividerEndPosition() {
const gfx::Rect work_area_bounds =
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) {
......@@ -1235,7 +1243,6 @@ void SplitViewController::GetDividerOptionalPositionRatios(
is_left_or_top ? right_window_ : left_window_;
bool is_landscape = IsCurrentScreenOrientationLandscape();
int long_length = GetDividerEndPosition();
float min_size_left_ratio = 0.f, min_size_right_ratio = 0.f;
int min_left_size = 0, min_right_size = 0;
if (left_or_top_window && left_or_top_window->delegate()) {
......@@ -1247,8 +1254,11 @@ void SplitViewController::GetDividerOptionalPositionRatios(
min_right_size = is_landscape ? min_size.width() : min_size.height();
}
min_size_left_ratio = static_cast<float>(min_left_size) / long_length;
min_size_right_ratio = static_cast<float>(min_right_size) / long_length;
int divider_end_position = GetDividerEndPosition();
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)
position_ratios->push_back(kOneThirdPositionRatio);
......
......@@ -264,8 +264,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// needs to be activated. Returns nullptr if there is no such window.
aura::Window* GetActiveWindowAfterResizingUponExit();
// Returns the maximum value of the |divider_position_|. It should always be
// the length of the longer side of the current display's work area bounds.
// Returns the maximum value of the |divider_position_|. It is the width of
// 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();
// Called after a to-be-snapped window |window| got snapped. It updates the
......@@ -384,8 +385,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// The window observer that obseves the tab-dragged window.
std::unique_ptr<TabDraggedWindowObserver> dragged_window_observer_;
// The distance between the origin of the divider and the origin of the screen
// in screen coordinates.
// The distance between the origin of the divider and the origin of the
// current display's work area in screen coordinates.
// |<--- divider_position_ --->|
// ----------------------------------------------------------
// | | | |
......@@ -394,6 +395,12 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// ----------------------------------------------------------
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.
gfx::Point previous_event_location_;
......
......@@ -167,6 +167,10 @@ class SplitViewControllerTest : public AshTestBase {
int divider_position() { return split_view_controller()->divider_position(); }
float divider_closest_ratio() {
return split_view_controller()->divider_closest_ratio_;
}
protected:
class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate {
public:
......@@ -1656,6 +1660,65 @@ TEST_F(SplitViewControllerTest, AdjustTransientChildBounds) {
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
// dragged out of a window and then put in split view mode or merge into another
// window.
......
......@@ -356,6 +356,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
GetWidget()->GetNativeWindow(), preview_left
? SplitViewController::LEFT
: 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,
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