Commit 33508671 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

overview gesture: Go home if overview is invisible when drag ends.

Bug: 1027353, 997885
Change-Id: Ia72d214f3a96f55e15128bb4b4155df5ddfe250e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1931544
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721192}
parent 36ff5692
......@@ -1754,6 +1754,8 @@ test("ash_unittests") {
"frame/non_client_frame_view_ash_unittest.cc",
"highlighter/highlighter_controller_unittest.cc",
"highlighter/highlighter_gesture_util_unittest.cc",
"home_screen/drag_window_from_shelf_controller_test_api.cc",
"home_screen/drag_window_from_shelf_controller_test_api.h",
"home_screen/drag_window_from_shelf_controller_unittest.cc",
"home_screen/home_launcher_gesture_handler_unittest.cc",
"home_screen/home_screen_controller_unittest.cc",
......
......@@ -13,6 +13,7 @@
#include "ash/root_window_controller.h"
#include "ash/scoped_animation_disabler.h"
#include "ash/screen_util.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_view.h"
#include "ash/wallpaper/wallpaper_widget_controller.h"
......@@ -185,8 +186,7 @@ void DragWindowFromShelfController::Drag(const gfx::Point& location_in_screen,
std::abs(scroll_y) > kShowOverviewThreshold) {
// If the dragging velocity is large enough, hide overview windows.
show_overview_timer_.Stop();
overview_session->SetVisibleDuringWindowDragging(/*visible=*/false,
/*animate=*/false);
HideOverviewDuringDrag();
} else {
// Otherwise start the |show_overview_timer_| to show and update overview
// when the dragging slows down or stops.
......@@ -275,6 +275,16 @@ void DragWindowFromShelfController::OnWindowDestroying(aura::Window* window) {
window_ = nullptr;
}
void DragWindowFromShelfController::AddObserver(
DragWindowFromShelfController::Observer* observer) {
observers_.AddObserver(observer);
}
void DragWindowFromShelfController::RemoveObserver(
DragWindowFromShelfController::Observer* observer) {
observers_.RemoveObserver(observer);
}
void DragWindowFromShelfController::OnDragStarted(
const gfx::Point& location_in_screen) {
drag_started_ = true;
......@@ -483,6 +493,14 @@ bool DragWindowFromShelfController::ShouldRestoreToOriginalBounds(
bool DragWindowFromShelfController::ShouldGoToHomeScreen(
const gfx::Point& location_in_screen,
base::Optional<float> velocity_y) const {
// If the drag ends below the shelf, do not go to home screen (theoratically
// it may happen in kExtended hotseat case when drag can start and end below
// the shelf).
if (location_in_screen.y() >=
Shelf::ForWindow(window_)->GetIdealBoundsForWorkAreaCalculation().y()) {
return false;
}
// For a hidden hotseat, if the event end position does not exceed
// GetReturnToMaximizedThreshold(), it should restore back to the maximized
// bounds even though the velocity might be large.
......@@ -491,10 +509,22 @@ bool DragWindowFromShelfController::ShouldGoToHomeScreen(
return false;
}
// Do not go home if we're in split screen.
if (SplitViewController::Get(Shell::GetPrimaryRootWindow())
->InSplitViewMode()) {
return false;
}
// If overview is invisible when the drag ends, no matter what the velocity
// is, we should go to home screen.
if (Shell::Get()->overview_controller()->InOverviewSession() &&
!show_overview_windows_) {
return true;
}
// Otherwise go home if the velocity is large enough.
return velocity_y.has_value() && *velocity_y < 0 &&
std::abs(*velocity_y) >= kVelocityToHomeScreenThreshold &&
!SplitViewController::Get(Shell::GetPrimaryRootWindow())
->InSplitViewMode();
std::abs(*velocity_y) >= kVelocityToHomeScreenThreshold;
}
SplitViewController::SnapPosition
......@@ -548,8 +578,24 @@ void DragWindowFromShelfController::ShowOverviewDuringOrAfterDrag() {
if (!overview_controller->InOverviewSession())
return;
show_overview_windows_ = true;
overview_controller->overview_session()->SetVisibleDuringWindowDragging(
/*visible=*/true, /*animate=*/true);
for (Observer& observer : observers_)
observer.OnOverviewVisibilityChanged(true);
}
void DragWindowFromShelfController::HideOverviewDuringDrag() {
show_overview_windows_ = false;
OverviewController* overview_controller = Shell::Get()->overview_controller();
if (!overview_controller->InOverviewSession())
return;
overview_controller->overview_session()->SetVisibleDuringWindowDragging(
/*visible=*/false,
/*animate=*/false);
for (Observer& observer : observers_)
observer.OnOverviewVisibilityChanged(false);
}
void DragWindowFromShelfController::ScaleDownWindowAfterDrag() {
......@@ -599,8 +645,7 @@ void DragWindowFromShelfController::OnWindowDragStartedInOverview() {
overview_session->SetSplitViewDragIndicatorsDraggedWindow(window_);
// Hide overview windows first and fade in the windows after delaying
// kShowOverviewTimeWhenDragSuspend.
overview_session->SetVisibleDuringWindowDragging(/*visible=*/false,
/*animate=*/false);
HideOverviewDuringDrag();
}
} // namespace ash
......@@ -13,6 +13,7 @@
#include "ash/wm/splitview/split_view_controller.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
......@@ -74,6 +75,13 @@ class ASH_EXPORT DragWindowFromShelfController : public aura::WindowObserver {
kGoToOverviewMode
};
class Observer : public base::CheckedObserver {
public:
// Called when overview visibility is changed during or after window
// dragging.
virtual void OnOverviewVisibilityChanged(bool visible) {}
};
DragWindowFromShelfController(aura::Window* window,
const gfx::Point& location_in_screen,
HotseatState hotseat_state);
......@@ -93,8 +101,12 @@ class ASH_EXPORT DragWindowFromShelfController : public aura::WindowObserver {
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
aura::Window* dragged_window() const { return window_; }
bool drag_started() const { return drag_started_; }
bool show_overview_windows() const { return show_overview_windows_; }
private:
class WindowsHider;
......@@ -140,6 +152,9 @@ class ASH_EXPORT DragWindowFromShelfController : public aura::WindowObserver {
// Calls when the user resumes or ends window dragging. Overview should show
// up and split view indicators should be updated.
void ShowOverviewDuringOrAfterDrag();
// Overview should be hidden when the user drags the window quickly up or
// around.
void HideOverviewDuringDrag();
// Called when the dragged window should scale down and fade out to home
// screen after drag ends.
......@@ -173,6 +188,11 @@ class ASH_EXPORT DragWindowFromShelfController : public aura::WindowObserver {
// The hotseat state when drag starts.
const HotseatState hotseat_state_;
// True if overview is active and its windows are showing.
bool show_overview_windows_ = false;
base::ObserverList<Observer> observers_;
base::WeakPtrFactory<DragWindowFromShelfController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DragWindowFromShelfController);
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/home_screen/drag_window_from_shelf_controller_test_api.h"
#include "ash/shell.h"
#include "ash/wm/overview/overview_controller.h"
namespace ash {
DragWindowFromShelfControllerTestApi::DragWindowFromShelfControllerTestApi(
DragWindowFromShelfController* window_drag_controller)
: window_drag_controller_(window_drag_controller) {
DCHECK(window_drag_controller_);
window_drag_controller_->AddObserver(this);
}
DragWindowFromShelfControllerTestApi::~DragWindowFromShelfControllerTestApi() {
window_drag_controller_->RemoveObserver(this);
}
void DragWindowFromShelfControllerTestApi::WaitUntilOverviewIsShown() {
if (!Shell::Get()->overview_controller()->InOverviewSession() ||
window_drag_controller_->show_overview_windows()) {
return;
}
show_overview_waiter_ = std::make_unique<base::RunLoop>();
show_overview_waiter_->Run();
}
void DragWindowFromShelfControllerTestApi::OnOverviewVisibilityChanged(
bool visible) {
if (visible && show_overview_waiter_)
show_overview_waiter_->Quit();
}
} // namespace ash
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_HOME_SCREEN_DRAG_WINDOW_FROM_SHELF_CONTROLLER_TEST_API_H_
#define ASH_HOME_SCREEN_DRAG_WINDOW_FROM_SHELF_CONTROLLER_TEST_API_H_
#include "ash/ash_export.h"
#include "ash/home_screen/drag_window_from_shelf_controller.h"
#include "base/run_loop.h"
namespace ash {
class ASH_EXPORT DragWindowFromShelfControllerTestApi
: public DragWindowFromShelfController::Observer {
public:
explicit DragWindowFromShelfControllerTestApi(
DragWindowFromShelfController* window_drag_controller);
~DragWindowFromShelfControllerTestApi() override;
void WaitUntilOverviewIsShown();
// DragWindowFromShelfController::Observer:
void OnOverviewVisibilityChanged(bool visible) override;
private:
DragWindowFromShelfController* const
window_drag_controller_; // const pointer
std::unique_ptr<base::RunLoop> show_overview_waiter_;
DragWindowFromShelfControllerTestApi(
const DragWindowFromShelfControllerTestApi&) = delete;
DragWindowFromShelfControllerTestApi& operator=(
const DragWindowFromShelfControllerTestApi&) = delete;
};
} // namespace ash
#endif // ASH_HOME_SCREEN_DRAG_WINDOW_FROM_SHELF_CONTROLLER_TEST_API_H_
......@@ -4,6 +4,7 @@
#include "ash/home_screen/drag_window_from_shelf_controller.h"
#include "ash/home_screen/drag_window_from_shelf_controller_test_api.h"
#include "ash/home_screen/home_screen_controller.h"
#include "ash/home_screen/home_screen_delegate.h"
#include "ash/root_window_controller.h"
......@@ -21,6 +22,7 @@
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "ash/wm/window_state.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/wm/core/window_util.h"
namespace ash {
......@@ -176,6 +178,8 @@ TEST_F(DragWindowFromShelfControllerTest, MayOrMayNotReShowHiddenWindows) {
EXPECT_FALSE(window2->IsVisible());
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
DragWindowFromShelfControllerTestApi test_api(window_drag_controller());
test_api.WaitUntilOverviewIsShown();
EndDrag(gfx::Point(200, 200), base::nullopt);
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_TRUE(overview_controller->overview_session()->IsWindowInOverview(
......@@ -211,6 +215,8 @@ TEST_F(DragWindowFromShelfControllerTest, MinimizedWindowsShowInOverview) {
StartDrag(window1.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
// Drag it far enough so overview should be open behind the dragged window.
Drag(gfx::Point(200, 200), 0.f, 1.f);
DragWindowFromShelfControllerTestApi test_api(window_drag_controller());
test_api.WaitUntilOverviewIsShown();
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_TRUE(window1->IsVisible());
......@@ -276,6 +282,8 @@ TEST_F(DragWindowFromShelfControllerTest, RestoreWindowToOriginalBounds) {
Drag(gfx::Point(200, 200), 0.f, 1.f);
EXPECT_FALSE(window->layer()->GetTargetTransform().IsIdentity());
EXPECT_TRUE(overview_controller->InOverviewSession());
DragWindowFromShelfControllerTestApi test_api(window_drag_controller());
test_api.WaitUntilOverviewIsShown();
EndDrag(
gfx::Point(
200,
......@@ -442,6 +450,8 @@ TEST_F(DragWindowFromShelfControllerTest, HideOverviewDuringDragging) {
StartDrag(window1.get(), shelf_bounds.CenterPoint(), HotseatState::kExtended);
Drag(gfx::Point(200, 200), 0.5f, 0.5f);
DragWindowFromShelfControllerTestApi test_api(window_drag_controller());
test_api.WaitUntilOverviewIsShown();
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
// We test the visibility of overview by testing the drop target widget's
......@@ -459,6 +469,9 @@ TEST_F(DragWindowFromShelfControllerTest, HideOverviewDuringDragging) {
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(drop_target_item->GetWindow()->layer()->GetTargetOpacity(), 0.f);
Drag(gfx::Point(200, 200), 0.5f, 0.5f);
DragWindowFromShelfControllerTestApi test_api2(window_drag_controller());
test_api2.WaitUntilOverviewIsShown();
EndDrag(gfx::Point(200, 200),
/*velocity_y=*/base::nullopt);
EXPECT_TRUE(overview_controller->InOverviewSession());
......@@ -521,7 +534,7 @@ TEST_F(DragWindowFromShelfControllerTest, NoBackdropDuringWindowScaleDown) {
StartDrag(window.get(), shelf_bounds.left_center(), HotseatState::kExtended);
Drag(gfx::Point(0, 200), 0.f, 10.f);
EndDrag(shelf_bounds.CenterPoint(),
EndDrag(gfx::Point(0, 200),
base::make_optional(
-DragWindowFromShelfController::kVelocityToHomeScreenThreshold));
EXPECT_FALSE(window->layer()->GetTargetTransform().IsIdentity());
......@@ -668,4 +681,33 @@ TEST_F(DragWindowFromShelfControllerTest, DragToSnapMinDistance) {
EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window1.get()));
}
// Test that if overview is invisible when drag ends, the window will be taken
// to the home screen.
TEST_F(DragWindowFromShelfControllerTest, GoHomeIfOverviewInvisible) {
UpdateDisplay("400x400");
const gfx::Rect shelf_bounds =
Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
auto window = CreateTestWindow();
StartDrag(window.get(), shelf_bounds.left_center(), HotseatState::kExtended);
Drag(gfx::Point(200, 200), 0.f, 10.f);
DragWindowFromShelfControllerTestApi test_api(window_drag_controller());
test_api.WaitUntilOverviewIsShown();
// End drag without any fling, the window should be added to overview.
EndDrag(gfx::Point(200, 200), base::nullopt);
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_TRUE(overview_controller->overview_session()->IsWindowInOverview(
window.get()));
wm::ActivateWindow(window.get());
StartDrag(window.get(), shelf_bounds.left_center(), HotseatState::kExtended);
Drag(gfx::Point(200, 200), 0.f, 10.f);
// At this moment overview should be invisible. End the drag without any
// fling, the window should be taken to home screen.
EndDrag(gfx::Point(200, 200), base::nullopt);
EXPECT_TRUE(WindowState::Get(window.get())->IsMinimized());
}
} // namespace ash
......@@ -16,6 +16,7 @@
#include "ash/app_list/views/app_list_view.h"
#include "ash/focus_cycler.h"
#include "ash/home_screen/drag_window_from_shelf_controller.h"
#include "ash/home_screen/drag_window_from_shelf_controller_test_api.h"
#include "ash/home_screen/home_launcher_gesture_handler.h"
#include "ash/home_screen/home_screen_controller.h"
#include "ash/keyboard/ui/keyboard_ui.h"
......@@ -3930,6 +3931,11 @@ TEST_P(HotseatShelfLayoutManagerTest, ExitingOvervieHidesHotseat) {
bottom_shelf_bounds.CenterPoint().y());
// Small scroll update, to simulate the user holding the pointer.
UpdateScroll(2);
DragWindowFromShelfController* window_drag_controller =
GetShelfLayoutManager()->window_drag_controller_for_testing();
ASSERT_TRUE(window_drag_controller);
DragWindowFromShelfControllerTestApi test_api(window_drag_controller);
test_api.WaitUntilOverviewIsShown();
EndScroll(/*is_fling=*/false, 0.f);
OverviewController* overview_controller = Shell::Get()->overview_controller();
......
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