Commit 047b6d71 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

overview gesture: Swipe up from shelf to drag the active window around.

See https://docs.google.com/document/d/1rskVuhK9wAqgntcq9WYPSknMEc_jsAp3zrqb4YSMAqE/edit#
for the mock and expected behaviors.

See crbug.com/997885#c5 for demo. For now with this CL in place, we can
only drag the window around. More will be done in follow up Cls.

Bug: 997885
Change-Id: Iecea3a8cb4a6fe3c6a64ddddea08bc010cfb72dc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1817105
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700306}
parent f589d580
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ASH_HOME_SCREEN_HOME_LAUNCHER_GESTURE_HANDLER_H_ #define ASH_HOME_SCREEN_HOME_LAUNCHER_GESTURE_HANDLER_H_
#include <map> #include <map>
#include <memory>
#include <vector> #include <vector>
#include "ash/ash_export.h" #include "ash/ash_export.h"
...@@ -42,6 +43,11 @@ class ASH_EXPORT HomeLauncherGestureHandler ...@@ -42,6 +43,11 @@ class ASH_EXPORT HomeLauncherGestureHandler
// Sliding up the MRU window to display launcher. If in overview mode, // Sliding up the MRU window to display launcher. If in overview mode,
// slides up overview mode as well. // slides up overview mode as well.
kSlideUpToShow, kSlideUpToShow,
// Sliding up from the shelf to drag the MRU window (or one of the snapped
// window in splitview) around to enter either home launcher screen or to
// overview screen. If in overview mode, this mode is a no-op. Note: This
// mode is behind the feature flag kDragFromShelfToHomeOrOverview.
kDragWindowToHomeOrOverview,
// Sliding down the MRU window to hide launcher. // Sliding down the MRU window to hide launcher.
kSlideDownToHide, kSlideDownToHide,
}; };
...@@ -95,6 +101,8 @@ class ASH_EXPORT HomeLauncherGestureHandler ...@@ -95,6 +101,8 @@ class ASH_EXPORT HomeLauncherGestureHandler
private: private:
class ScopedWindowModifier; class ScopedWindowModifier;
class DragWindowFromShelfController;
FRIEND_TEST_ALL_PREFIXES(HomeLauncherModeGestureHandlerTest, FRIEND_TEST_ALL_PREFIXES(HomeLauncherModeGestureHandlerTest,
AnimatingToEndResetsState); AnimatingToEndResetsState);
...@@ -119,8 +127,9 @@ class ASH_EXPORT HomeLauncherGestureHandler ...@@ -119,8 +127,9 @@ class ASH_EXPORT HomeLauncherGestureHandler
// on the values in |window_values_| and |transient_descendants_values_|. // on the values in |window_values_| and |transient_descendants_values_|.
// |progress| is between 0.0 and 1.0, where 0.0 means the window will have its // |progress| is between 0.0 and 1.0, where 0.0 means the window will have its
// original opacity and transform, and 1.0 means the window will be faded out // original opacity and transform, and 1.0 means the window will be faded out
// and transformed offscreen. // and transformed offscreen. This function is used by kSlideUpToShow and
void UpdateWindows(double progress, bool animate); // kSlideDownToHide mode.
void UpdateWindowsForSlideUpOrDown(double progress, bool animate);
// Stop observing all windows and remove their local pointers. // Stop observing all windows and remove their local pointers.
void RemoveObserversAndStopTracking(); void RemoveObserversAndStopTracking();
...@@ -137,9 +146,19 @@ class ASH_EXPORT HomeLauncherGestureHandler ...@@ -137,9 +146,19 @@ class ASH_EXPORT HomeLauncherGestureHandler
// Sets up windows that will be used in dragging and animation. If |window| is // Sets up windows that will be used in dragging and animation. If |window| is
// not null for kSlideDownToHide mode, it will be set as the window to run // not null for kSlideDownToHide mode, it will be set as the window to run
// slide down animation. |window| is not used for kSlideUpToShow mode. Returns // slide down animation. |window| is not used for kSlideUpToShow or
// true if windows are successfully set up. // kDragWindowToHomeOrOverview mode. |location_in_screen| is only used for
bool SetUpWindows(Mode mode, aura::Window* window); // kDragWindowToHomeOrOverview mode to find the eligible widnow to drag.
// Returns true if windows are successfully set up.
bool SetUpWindows(Mode mode,
aura::Window* window,
base::Optional<gfx::Point> location_in_screen);
// Called by OnPress/Scroll/ReleaseEvent() when the drag from the shelf or
// from the top starts/continues/ends. |location| is in screen coordinate.
void OnDragStarted(const gfx::Point& location);
void OnDragContinued(const gfx::Point& location);
bool OnDragEnded(const gfx::Point& location);
Mode mode_ = Mode::kNone; Mode mode_ = Mode::kNone;
...@@ -187,6 +206,10 @@ class ASH_EXPORT HomeLauncherGestureHandler ...@@ -187,6 +206,10 @@ class ASH_EXPORT HomeLauncherGestureHandler
// The display where the windows are being processed. // The display where the windows are being processed.
display::Display display_; display::Display display_;
// The window drag controller that will be used in kDragWindowToHomeOrOverview
// mode. Will not be created in other modes.
std::unique_ptr<DragWindowFromShelfController> window_drag_controller_;
base::ObserverList<HomeLauncherGestureHandlerObserver> observers_; base::ObserverList<HomeLauncherGestureHandlerObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(HomeLauncherGestureHandler); DISALLOW_COPY_AND_ASSIGN(HomeLauncherGestureHandler);
......
...@@ -426,6 +426,117 @@ TEST_F(HomeLauncherGestureHandlerTest, TransparentShelfWileDragging) { ...@@ -426,6 +426,117 @@ TEST_F(HomeLauncherGestureHandlerTest, TransparentShelfWileDragging) {
->GetShelfBackgroundType()); ->GetShelfBackgroundType());
} }
// Tests that in kDragWindowToHomeOrOverview mode, the dragged active window
// might be different in different scenarios.
TEST_F(HomeLauncherGestureHandlerTest, DraggedActiveWindow) {
const gfx::Rect shelf_bounds =
Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
// We need at least one window to work with.
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.CenterPoint());
EXPECT_FALSE(GetGestureHandler()->GetActiveWindow());
auto window1 = CreateWindowForTesting();
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.CenterPoint());
EXPECT_EQ(GetGestureHandler()->GetActiveWindow(), window1.get());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.CenterPoint());
EXPECT_FALSE(GetGestureHandler()->GetActiveWindow());
// Test in splitview, depends on the drag position, the active dragged window
// might be different.
auto window2 = CreateWindowForTesting();
SplitViewController* split_view_controller =
Shell::Get()->split_view_controller();
split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.bottom_left());
EXPECT_EQ(GetGestureHandler()->GetActiveWindow(), window1.get());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.bottom_left());
EXPECT_FALSE(GetGestureHandler()->GetActiveWindow());
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.bottom_right());
EXPECT_EQ(GetGestureHandler()->GetActiveWindow(), window2.get());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.bottom_right());
EXPECT_FALSE(GetGestureHandler()->GetActiveWindow());
split_view_controller->EndSplitView();
// In overview, drag from shelf is a no-op.
Shell::Get()->overview_controller()->StartOverview();
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.CenterPoint());
EXPECT_FALSE(GetGestureHandler()->GetActiveWindow());
}
// Tests that in kDragWindowToHomeOrOverview mode, we may hide different sets
// of windows in different scenarios.
TEST_F(HomeLauncherGestureHandlerTest, HideWindowDuringWindowDragging) {
const gfx::Rect shelf_bounds =
Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
auto window3 = CreateWindowForTesting();
auto window2 = CreateWindowForTesting();
auto window1 = CreateWindowForTesting();
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_TRUE(window3->IsVisible());
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.CenterPoint());
EXPECT_TRUE(window1->IsVisible());
EXPECT_FALSE(window2->IsVisible());
EXPECT_FALSE(window3->IsVisible());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.CenterPoint());
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_TRUE(window3->IsVisible());
// In splitview mode, the snapped windows will stay visible during dragging.
SplitViewController* split_view_controller =
Shell::Get()->split_view_controller();
split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.bottom_left());
EXPECT_EQ(GetGestureHandler()->GetActiveWindow(), window1.get());
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_FALSE(window3->IsVisible());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.bottom_left());
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_TRUE(window3->IsVisible());
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.bottom_right());
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_FALSE(window3->IsVisible());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.bottom_right());
EXPECT_TRUE(window1->IsVisible());
EXPECT_TRUE(window2->IsVisible());
EXPECT_TRUE(window3->IsVisible());
}
TEST_F(HomeLauncherGestureHandlerTest, HideHomeLauncherDuringDraggingTest) {
UpdateDisplay("400x400");
const gfx::Rect shelf_bounds =
Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
auto window = CreateWindowForTesting();
GetGestureHandler()->OnPressEvent(Mode::kDragWindowToHomeOrOverview,
shelf_bounds.CenterPoint());
GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), 1.f);
aura::Window* home_screen_window =
Shell::Get()->home_screen_controller()->delegate()->GetHomeScreenWindow();
EXPECT_TRUE(home_screen_window);
EXPECT_FALSE(home_screen_window->IsVisible());
GetGestureHandler()->OnReleaseEvent(shelf_bounds.CenterPoint());
EXPECT_TRUE(home_screen_window->IsVisible());
}
class HomeLauncherModeGestureHandlerTest class HomeLauncherModeGestureHandlerTest
: public HomeLauncherGestureHandlerTest, : public HomeLauncherGestureHandlerTest,
public testing::WithParamInterface<Mode> { public testing::WithParamInterface<Mode> {
......
...@@ -96,6 +96,9 @@ const base::Feature kEnableBackgroundBlur{"EnableBackgroundBlur", ...@@ -96,6 +96,9 @@ const base::Feature kEnableBackgroundBlur{"EnableBackgroundBlur",
const base::Feature kSwipingFromLeftEdgeToGoBack{ const base::Feature kSwipingFromLeftEdgeToGoBack{
"SwipingFromLeftEdgeToGoBack", base::FEATURE_DISABLED_BY_DEFAULT}; "SwipingFromLeftEdgeToGoBack", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kDragFromShelfToHomeOrOverview{
"DragFromShelfToHomeOrOverview", base::FEATURE_DISABLED_BY_DEFAULT};
bool IsHideArcMediaNotificationsEnabled() { bool IsHideArcMediaNotificationsEnabled() {
return base::FeatureList::IsEnabled(kMediaSessionNotification) && return base::FeatureList::IsEnabled(kMediaSessionNotification) &&
base::FeatureList::IsEnabled(kHideArcMediaNotifications); base::FeatureList::IsEnabled(kHideArcMediaNotifications);
...@@ -181,5 +184,9 @@ bool IsSwipingFromLeftEdgeToGoBackEnabled() { ...@@ -181,5 +184,9 @@ bool IsSwipingFromLeftEdgeToGoBackEnabled() {
return base::FeatureList::IsEnabled(kSwipingFromLeftEdgeToGoBack); return base::FeatureList::IsEnabled(kSwipingFromLeftEdgeToGoBack);
} }
bool IsDragFromShelfToHomeOrOverviewEnabled() {
return base::FeatureList::IsEnabled(kDragFromShelfToHomeOrOverview);
}
} // namespace features } // namespace features
} // namespace ash } // namespace ash
...@@ -125,6 +125,12 @@ ASH_PUBLIC_EXPORT extern const base::Feature kUnifiedMessageCenterRefactor; ...@@ -125,6 +125,12 @@ ASH_PUBLIC_EXPORT extern const base::Feature kUnifiedMessageCenterRefactor;
// display. Only for tablet mode. // display. Only for tablet mode.
ASH_PUBLIC_EXPORT extern const base::Feature kSwipingFromLeftEdgeToGoBack; ASH_PUBLIC_EXPORT extern const base::Feature kSwipingFromLeftEdgeToGoBack;
// Enables dragging from shelf to enter home screen or overview feature.
// Only for tablet mode.
// TODO(https://crbug.com/992642): Remove this after this feature is fully
// launched.
ASH_PUBLIC_EXPORT extern const base::Feature kDragFromShelfToHomeOrOverview;
ASH_PUBLIC_EXPORT bool IsHideArcMediaNotificationsEnabled(); ASH_PUBLIC_EXPORT bool IsHideArcMediaNotificationsEnabled();
ASH_PUBLIC_EXPORT bool IsKeyboardShortcutViewerAppEnabled(); ASH_PUBLIC_EXPORT bool IsKeyboardShortcutViewerAppEnabled();
...@@ -165,6 +171,8 @@ ASH_PUBLIC_EXPORT bool IsBackgroundBlurEnabled(); ...@@ -165,6 +171,8 @@ ASH_PUBLIC_EXPORT bool IsBackgroundBlurEnabled();
ASH_PUBLIC_EXPORT bool IsSwipingFromLeftEdgeToGoBackEnabled(); ASH_PUBLIC_EXPORT bool IsSwipingFromLeftEdgeToGoBackEnabled();
ASH_PUBLIC_EXPORT bool IsDragFromShelfToHomeOrOverviewEnabled();
} // namespace features } // namespace features
} // namespace ash } // namespace ash
......
...@@ -166,7 +166,7 @@ class HideAnimationObserver : public ui::ImplicitAnimationObserver { ...@@ -166,7 +166,7 @@ class HideAnimationObserver : public ui::ImplicitAnimationObserver {
class HotseatEventHandler : public ui::EventHandler, class HotseatEventHandler : public ui::EventHandler,
public ShelfLayoutManagerObserver { public ShelfLayoutManagerObserver {
public: public:
HotseatEventHandler(ShelfLayoutManager* shelf_layout_manager) explicit HotseatEventHandler(ShelfLayoutManager* shelf_layout_manager)
: shelf_layout_manager_(shelf_layout_manager) { : shelf_layout_manager_(shelf_layout_manager) {
shelf_layout_manager_->AddObserver(this); shelf_layout_manager_->AddObserver(this);
Shell::Get()->AddPreTargetHandler(this); Shell::Get()->AddPreTargetHandler(this);
...@@ -1829,9 +1829,12 @@ bool ShelfLayoutManager::StartGestureDrag( ...@@ -1829,9 +1829,12 @@ bool ShelfLayoutManager::StartGestureDrag(
drag_status_ = kDragAppListInProgress; drag_status_ = kDragAppListInProgress;
HomeLauncherGestureHandler* home_launcher_handler = HomeLauncherGestureHandler* home_launcher_handler =
Shell::Get()->home_screen_controller()->home_launcher_gesture_handler(); Shell::Get()->home_screen_controller()->home_launcher_gesture_handler();
if (home_launcher_handler->OnPressEvent( HomeLauncherGestureHandler::Mode slide_mode =
HomeLauncherGestureHandler::Mode::kSlideUpToShow, features::IsDragFromShelfToHomeOrOverviewEnabled()
gesture_in_screen.location())) { ? HomeLauncherGestureHandler::Mode::kDragWindowToHomeOrOverview
: HomeLauncherGestureHandler::Mode::kSlideUpToShow;
if (home_launcher_handler->OnPressEvent(slide_mode,
gesture_in_screen.location())) {
return true; return true;
} }
drag_status_ = previous_drag_status; drag_status_ = previous_drag_status;
...@@ -1889,7 +1892,7 @@ void ShelfLayoutManager::UpdateMouseDrag( ...@@ -1889,7 +1892,7 @@ void ShelfLayoutManager::UpdateMouseDrag(
if (drag_status_ == kDragAttempt) { if (drag_status_ == kDragAttempt) {
// Do not start drag for the small offset. // Do not start drag for the small offset.
if (abs(mouse_in_screen.location().y() - last_mouse_drag_position_.y()) < if (abs(mouse_in_screen.location().y() - last_mouse_drag_position_.y()) <
kMouseDragThreshold) { kMouseDragThreshold) {
return; return;
} }
......
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