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

Tab dragging: Refactoring.

Put the common logic in TabletModeWindowDragDelegate and create
TabletModeBrowserWindowDragDelegate and TabletModeAppWindowDragDelegate
to do special handling for browser windows and app windows.

*DragDelegate does almost everything other than updating the dragged
window (which is done by *DragController by either changing the dragged
window's bounds or transform).

Bug: 823769
Change-Id: Idc9e788f7e273a92fc783af347f62cd862be54bd
Reviewed-on: https://chromium-review.googlesource.com/1134503
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575766}
parent c0e6d51a
...@@ -1215,6 +1215,8 @@ component("ash") { ...@@ -1215,6 +1215,8 @@ component("ash") {
"wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h", "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h",
"wm/tablet_mode/tablet_mode_browser_window_drag_controller.cc", "wm/tablet_mode/tablet_mode_browser_window_drag_controller.cc",
"wm/tablet_mode/tablet_mode_browser_window_drag_controller.h", "wm/tablet_mode/tablet_mode_browser_window_drag_controller.h",
"wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc",
"wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h",
"wm/tablet_mode/tablet_mode_controller.cc", "wm/tablet_mode/tablet_mode_controller.cc",
"wm/tablet_mode/tablet_mode_controller.h", "wm/tablet_mode/tablet_mode_controller.h",
"wm/tablet_mode/tablet_mode_event_handler.cc", "wm/tablet_mode/tablet_mode_event_handler.cc",
......
...@@ -37,15 +37,6 @@ constexpr SkColor kSplitviewLabelBackgroundColor = ...@@ -37,15 +37,6 @@ constexpr SkColor kSplitviewLabelBackgroundColor =
constexpr int kSplitviewAnimationDurationMs = 250; constexpr int kSplitviewAnimationDurationMs = 250;
// The threshold to compute the minimum vertical distance to start showing the
// drag indicators and preview window when dragging a window into splitscreen in
// tablet mode.
constexpr float kIndicatorsThresholdRatio = 0.1;
// The threshold to compute the vertical distance to hide the drag indicators
// and maximize the dragged window after the drag ends.
constexpr float kMaximizeThresholdRatio = 0.4;
} // namespace ash } // namespace ash
#endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_CONSTANTS_H_ #endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_CONSTANTS_H_
...@@ -4,13 +4,10 @@ ...@@ -4,13 +4,10 @@
#include "ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h" #include "ash/wm/tablet_mode/tablet_mode_app_window_drag_controller.h"
#include "ash/shell.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/splitview/split_view_drag_indicators.h" #include "ash/wm/splitview/split_view_drag_indicators.h"
#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/display/screen.h"
#include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/coordinate_conversion.h"
namespace ash { namespace ash {
...@@ -25,10 +22,34 @@ gfx::Point GetEventLocationInScreen(const ui::GestureEvent* event) { ...@@ -25,10 +22,34 @@ gfx::Point GetEventLocationInScreen(const ui::GestureEvent* event) {
return location_in_screen; return location_in_screen;
} }
// The drag delegate for app windows. It not only includes the logic in
// TabletModeWindowDragDelegate, but also has special logic for app windows.
class TabletModeAppWindowDragDelegate : public TabletModeWindowDragDelegate {
public:
TabletModeAppWindowDragDelegate() = default;
~TabletModeAppWindowDragDelegate() override = default;
private:
// TabletModeWindowDragDelegate:
void PrepareForDraggedWindow(const gfx::Point& location_in_screen) override {
wm::GetWindowState(dragged_window_)
->CreateDragDetails(location_in_screen, HTCLIENT,
::wm::WINDOW_MOVE_SOURCE_TOUCH);
}
void UpdateForDraggedWindow(const gfx::Point& location_in_screen) override {}
void EndingForDraggedWindow(
wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) override {
wm::GetWindowState(dragged_window_)->DeleteDragDetails();
}
DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragDelegate);
};
} // namespace } // namespace
TabletModeAppWindowDragController::TabletModeAppWindowDragController() TabletModeAppWindowDragController::TabletModeAppWindowDragController()
: drag_delegate_(std::make_unique<TabletModeWindowDragDelegate>()) {} : drag_delegate_(std::make_unique<TabletModeAppWindowDragDelegate>()) {}
TabletModeAppWindowDragController::~TabletModeAppWindowDragController() = TabletModeAppWindowDragController::~TabletModeAppWindowDragController() =
default; default;
...@@ -60,34 +81,37 @@ bool TabletModeAppWindowDragController::DragWindowFromTop( ...@@ -60,34 +81,37 @@ bool TabletModeAppWindowDragController::DragWindowFromTop(
void TabletModeAppWindowDragController::StartWindowDrag( void TabletModeAppWindowDragController::StartWindowDrag(
ui::GestureEvent* event) { ui::GestureEvent* event) {
drag_delegate_->OnWindowDragStarted(
static_cast<aura::Window*>(event->target()));
initial_location_in_screen_ = GetEventLocationInScreen(event); initial_location_in_screen_ = GetEventLocationInScreen(event);
drag_delegate_->StartWindowDrag(static_cast<aura::Window*>(event->target()),
wm::GetWindowState(drag_delegate_->dragged_window()) initial_location_in_screen_);
->CreateDragDetails(initial_location_in_screen_, HTCLIENT,
::wm::WINDOW_MOVE_SOURCE_TOUCH);
if (!Shell::Get()->window_selector_controller()->IsSelecting())
Shell::Get()->window_selector_controller()->ToggleOverview();
gesture_drag_amount_.SetPoint(0.f, 0.f);
} }
void TabletModeAppWindowDragController::UpdateWindowDrag( void TabletModeAppWindowDragController::UpdateWindowDrag(
ui::GestureEvent* event) { ui::GestureEvent* event) {
const gfx::Point location_in_screen(GetEventLocationInScreen(event)); const gfx::Point location_in_screen(GetEventLocationInScreen(event));
drag_delegate_->UpdateIndicatorState(location_in_screen); UpdateDraggedWindow(location_in_screen);
drag_delegate_->ContinueWindowDrag(location_in_screen);
gesture_drag_amount_ += }
gfx::Vector2dF(event->details().scroll_x(), event->details().scroll_y());
const gfx::Rect display_bounds = void TabletModeAppWindowDragController::EndWindowDrag(
display::Screen::GetScreen() ui::GestureEvent* event,
->GetDisplayNearestWindow(drag_delegate_->dragged_window()) wm::WmToplevelWindowEventHandler::DragResult result) {
.bounds(); const gfx::Point location_in_screen(GetEventLocationInScreen(event));
drag_delegate_->dragged_window()->SetTransform(gfx::Transform());
drag_delegate_->EndWindowDrag(result, location_in_screen);
}
void TabletModeAppWindowDragController::UpdateDraggedWindow(
const gfx::Point& location_in_screen) {
gfx::PointF gesture_drag_amount =
gfx::PointF(location_in_screen.x() - initial_location_in_screen_.x(),
location_in_screen.y() - initial_location_in_screen_.y());
const gfx::Size display_size =
drag_delegate_->dragged_window()->GetRootWindow()->bounds().size();
const float x_scale = const float x_scale =
1.0f - fabsf(gesture_drag_amount_.x()) / display_bounds.width(); 1.0f - fabsf(gesture_drag_amount.x()) / display_size.width();
const float y_scale = const float y_scale =
1.0f - fabsf(gesture_drag_amount_.y()) / display_bounds.height(); 1.0f - fabsf(gesture_drag_amount.y()) / display_size.height();
const float scale = std::min(x_scale, y_scale); const float scale = std::min(x_scale, y_scale);
gfx::Transform transform; gfx::Transform transform;
transform.Translate( transform.Translate(
...@@ -97,14 +121,4 @@ void TabletModeAppWindowDragController::UpdateWindowDrag( ...@@ -97,14 +121,4 @@ void TabletModeAppWindowDragController::UpdateWindowDrag(
drag_delegate_->dragged_window()->SetTransform(transform); drag_delegate_->dragged_window()->SetTransform(transform);
} }
void TabletModeAppWindowDragController::EndWindowDrag(
ui::GestureEvent* event,
wm::WmToplevelWindowEventHandler::DragResult result) {
const gfx::Point location_in_screen(GetEventLocationInScreen(event));
drag_delegate_->dragged_window()->SetTransform(gfx::Transform());
wm::GetWindowState(drag_delegate_->dragged_window())->DeleteDragDetails();
drag_delegate_->OnWindowDragEnded(result, location_in_screen);
gesture_drag_amount_.SetPoint(0.f, 0.f);
}
} // namespace ash } // namespace ash
...@@ -35,13 +35,13 @@ class ASH_EXPORT TabletModeAppWindowDragController { ...@@ -35,13 +35,13 @@ class ASH_EXPORT TabletModeAppWindowDragController {
void EndWindowDrag(ui::GestureEvent* event, void EndWindowDrag(ui::GestureEvent* event,
wm::WmToplevelWindowEventHandler::DragResult result); wm::WmToplevelWindowEventHandler::DragResult result);
// Apply transform to the dragged window during dragging.
void UpdateDraggedWindow(const gfx::Point& location_in_screen);
std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_; std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_;
gfx::Point initial_location_in_screen_; gfx::Point initial_location_in_screen_;
// Tracks the amount of the drag. Only valid if window is being dragged.
gfx::PointF gesture_drag_amount_;
DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragController); DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragController);
}; };
......
...@@ -12,10 +12,6 @@ ...@@ -12,10 +12,6 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
namespace views {
class Widget;
} // namespace views
namespace ash { namespace ash {
class TabletModeWindowDragDelegate; class TabletModeWindowDragDelegate;
...@@ -44,32 +40,14 @@ class TabletModeBrowserWindowDragController : public WindowResizer { ...@@ -44,32 +40,14 @@ class TabletModeBrowserWindowDragController : public WindowResizer {
} }
private: private:
void EndDragImpl(wm::WmToplevelWindowEventHandler::DragResult result); // The drag delegate that does the real work: shows/hides the drag indicators,
// preview windows, blurred background, etc, during dragging.
// Scales down the source window if the dragged window is dragged past the std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_;
// |kIndicatorThresholdRatio| threshold and restores it if the dragged window
// is dragged back toward the top of the screen. |location_in_screen| is the
// current drag location for the dragged window.
void UpdateSourceWindow(const gfx::Point& location_in_screen);
// Shows/Hides/Destroies the scrim widget |scrim_| based on the current
// location |location_in_screen|.
void UpdateScrim(const gfx::Point& location_in_screen);
// Shows the scrim with the specified opacity, blur and expected bounds.
void ShowScrim(float opacity, float blur, const gfx::Rect& bounds_in_screen);
// A widget placed below the current dragged window to show the blurred or
// transparent background and to prevent the dragged window merge into any
// browser window beneath it during dragging.
std::unique_ptr<views::Widget> scrim_;
gfx::Point previous_location_in_parent_; gfx::Point previous_location_in_screen_;
bool did_lock_cursor_ = false; bool did_lock_cursor_ = false;
std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_;
// Used to determine if this has been deleted during a drag such as when a tab // Used to determine if this has been deleted during a drag such as when a tab
// gets dragged into another browser window. // gets dragged into another browser window.
base::WeakPtrFactory<TabletModeBrowserWindowDragController> weak_ptr_factory_; base::WeakPtrFactory<TabletModeBrowserWindowDragController> weak_ptr_factory_;
......
// Copyright 2018 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/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
#include "ash/shell.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/splitview/split_view_constants.h"
#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_window_state.h"
#include "ui/aura/window.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
namespace {
// The scale factor that the source window should scale if the source window is
// not the dragged window && is not in splitscreen when drag starts && the user
// has dragged the window to pass the |kIndicatorThresholdRatio| vertical
// threshold.
constexpr float kSourceWindowScale = 0.85;
// Values of the blurred scrim.
constexpr SkColor kScrimBackgroundColor = SK_ColorGRAY;
constexpr float kScrimOpacity = 0.8;
constexpr float kScrimBlur = 5.f;
constexpr int kScrimTransitionInMs = 250;
constexpr int kScrimRoundRectRadiusDp = 4;
// The threshold to compute the vertical distance to create/reset the scrim. The
// scrim is placed below the current dragged window. This value is smaller than
// kIndicatorsThreshouldRatio to prevent the dragged window to merge back to
// its source window during its source window's animation.
constexpr float kScrimResetThresholdRatio = 0.05;
// Returns the window selector if overview mode is active, otherwise returns
// nullptr.
WindowSelector* GetWindowSelector() {
return Shell::Get()->window_selector_controller()->IsSelecting()
? Shell::Get()->window_selector_controller()->window_selector()
: nullptr;
}
// Creates a transparent scrim which is placed below |dragged_window|.
std::unique_ptr<views::Widget> CreateScrim(aura::Window* dragged_window,
const gfx::Rect& bounds) {
std::unique_ptr<views::Widget> widget = CreateBackgroundWidget(
/*root_window=*/dragged_window->GetRootWindow(),
/*layer_type=*/ui::LAYER_TEXTURED,
/*background_color=*/kScrimBackgroundColor,
/*border_thickness=*/0,
/*border_radius=*/kScrimRoundRectRadiusDp,
/*border_color=*/SK_ColorTRANSPARENT,
/*initial_opacity=*/0.f,
/*parent=*/dragged_window->parent(),
/*stack_on_top=*/false);
widget->SetBounds(bounds);
return widget;
}
// When the dragged window is dragged past this value, a transparent scrim will
// be created to place below the current dragged window to prevent the dragged
// window to merge into any browser window beneath it and when it's dragged back
// toward the top of the screen, the scrim will be destroyed.
int GetScrimVerticalThreshold(const gfx::Rect& work_area_bounds) {
return work_area_bounds.y() +
work_area_bounds.height() * kScrimResetThresholdRatio;
}
} // namespace
TabletModeBrowserWindowDragDelegate::TabletModeBrowserWindowDragDelegate() =
default;
TabletModeBrowserWindowDragDelegate::~TabletModeBrowserWindowDragDelegate() =
default;
void TabletModeBrowserWindowDragDelegate::PrepareForDraggedWindow(
const gfx::Point& location_in_screen) {
DCHECK(dragged_window_);
wm::WindowState* window_state = wm::GetWindowState(dragged_window_);
window_state->OnDragStarted(window_state->drag_details()->window_component);
}
void TabletModeBrowserWindowDragDelegate::UpdateForDraggedWindow(
const gfx::Point& location_in_screen) {
DCHECK(dragged_window_);
// Update the source window if necessary.
UpdateSourceWindow(location_in_screen);
// Update the scrim that beneath the dragged window if necessary.
UpdateScrim(location_in_screen);
}
void TabletModeBrowserWindowDragDelegate::EndingForDraggedWindow(
wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) {
if (result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS)
wm::GetWindowState(dragged_window_)->OnCompleteDrag(location_in_screen);
else
wm::GetWindowState(dragged_window_)->OnRevertDrag(location_in_screen);
// The source window might have been scaled during dragging, update its bounds
// to ensure it has the right bounds after the drag ends.
aura::Window* source_window =
dragged_window_->GetProperty(ash::kTabDraggingSourceWindowKey);
if (source_window && !wm::GetWindowState(source_window)->IsSnapped()) {
TabletModeWindowState::UpdateWindowPosition(
wm::GetWindowState(source_window));
}
scrim_.reset();
}
bool TabletModeBrowserWindowDragDelegate::ShouldOpenOverviewWhenDragStarts() {
DCHECK(dragged_window_);
aura::Window* source_window =
dragged_window_->GetProperty(ash::kTabDraggingSourceWindowKey);
return !source_window;
}
void TabletModeBrowserWindowDragDelegate::UpdateSourceWindow(
const gfx::Point& location_in_screen) {
// Only do the scale if the source window is not the dragged window && the
// source window is not in splitscreen && the source window is not in
// overview.
aura::Window* source_window =
dragged_window_->GetProperty(ash::kTabDraggingSourceWindowKey);
if (!source_window || source_window == dragged_window_ ||
source_window == split_view_controller_->left_window() ||
source_window == split_view_controller_->right_window() ||
(GetWindowSelector() &&
GetWindowSelector()->IsWindowInOverview(source_window))) {
return;
}
const gfx::Rect work_area_bounds =
display::Screen::GetScreen()
->GetDisplayNearestWindow(dragged_window_)
.work_area();
gfx::Rect expected_bounds(work_area_bounds);
if (location_in_screen.y() >=
GetIndicatorsVerticalThreshold(work_area_bounds)) {
SplitViewController::SnapPosition snap_position =
GetSnapPosition(location_in_screen);
if (snap_position == SplitViewController::NONE) {
// Scale down the source window if the event location passes the vertical
// |kIndicatorThresholdRatio| threshold.
expected_bounds.ClampToCenteredSize(
gfx::Size(work_area_bounds.width() * kSourceWindowScale,
work_area_bounds.height() * kSourceWindowScale));
} else {
// Put the source window on the other side of the split screen.
expected_bounds = split_view_controller_->GetSnappedWindowBoundsInScreen(
source_window, snap_position == SplitViewController::LEFT
? SplitViewController::RIGHT
: SplitViewController::LEFT);
}
}
source_window->SetBoundsInScreen(
expected_bounds,
display::Screen::GetScreen()->GetDisplayNearestWindow(source_window));
}
void TabletModeBrowserWindowDragDelegate::UpdateScrim(
const gfx::Point& location_in_screen) {
// If overview mode is active, do not show the scrim on the overview side of
// the screen.
if (Shell::Get()->window_selector_controller()->IsSelecting()) {
WindowGrid* window_grid = GetWindowSelector()->GetGridWithRootWindow(
dragged_window_->GetRootWindow());
if (window_grid && window_grid->bounds().Contains(location_in_screen)) {
scrim_.reset();
return;
}
}
const gfx::Rect work_area_bounds =
display::Screen::GetScreen()
->GetDisplayNearestWindow(dragged_window_)
.work_area();
if (location_in_screen.y() < GetScrimVerticalThreshold(work_area_bounds)) {
// Remove |scrim_| entirely so that the dragged window can be merged back
// to the source window when the dragged window is dragged back toward the
// top area of the screen.
scrim_.reset();
return;
}
SplitViewController::SnapPosition snap_position =
GetSnapPosition(location_in_screen);
bool should_show_blurred_scrim = false;
if (location_in_screen.y() >=
GetMaximizeVerticalThreshold(work_area_bounds)) {
if (split_view_controller_->IsSplitViewModeActive() !=
(snap_position == SplitViewController::NONE)) {
should_show_blurred_scrim = true;
}
}
if (!should_show_blurred_scrim) {
scrim_.reset();
return;
}
gfx::Rect expected_bounds(work_area_bounds);
if (split_view_controller_->IsSplitViewModeActive()) {
expected_bounds = split_view_controller_->GetSnappedWindowBoundsInScreen(
dragged_window_, snap_position);
} else {
expected_bounds.Inset(kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp);
}
ShowScrim(kScrimOpacity, kScrimBlur, expected_bounds);
}
void TabletModeBrowserWindowDragDelegate::ShowScrim(
float opacity,
float blur,
const gfx::Rect& bounds_in_screen) {
gfx::Rect bounds(bounds_in_screen);
::wm::ConvertRectFromScreen(dragged_window_->parent(), &bounds);
if (scrim_ && scrim_->GetLayer()->GetTargetOpacity() == opacity &&
scrim_->GetNativeWindow()->bounds() == bounds) {
return;
}
if (!scrim_)
scrim_ = CreateScrim(dragged_window_, bounds);
dragged_window_->parent()->StackChildBelow(scrim_->GetNativeWindow(),
dragged_window_);
scrim_->GetLayer()->SetBackgroundBlur(blur);
if (scrim_->GetNativeWindow()->bounds() != bounds) {
scrim_->SetOpacity(0.f);
scrim_->SetBounds(bounds);
}
ui::ScopedLayerAnimationSettings animation(scrim_->GetLayer()->GetAnimator());
animation.SetTweenType(gfx::Tween::EASE_IN_OUT);
animation.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kScrimTransitionInMs));
animation.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
scrim_->SetOpacity(opacity);
}
} // namespace ash
// Copyright 2018 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_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
#define ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
#include "base/macros.h"
namespace views {
class Widget;
} // namespace views
namespace ash {
// The drag delegate for browser windows. It not only includes the logic in
// TabletModeWindowDragDelegate, but also has special logic for browser windows,
// e.g., scales the source window, shows/hides the blurred background, etc.
class TabletModeBrowserWindowDragDelegate
: public TabletModeWindowDragDelegate {
public:
TabletModeBrowserWindowDragDelegate();
~TabletModeBrowserWindowDragDelegate() override;
private:
// TabletModeWindowDragDelegate:
void PrepareForDraggedWindow(const gfx::Point& location_in_screen) override;
void UpdateForDraggedWindow(const gfx::Point& location_in_screen) override;
void EndingForDraggedWindow(
wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) override;
bool ShouldOpenOverviewWhenDragStarts() override;
// Scales down the source window if the dragged window is dragged past the
// |kIndicatorThresholdRatio| threshold and restores it if the dragged window
// is dragged back toward the top of the screen. |location_in_screen| is the
// current drag location for the dragged window.
void UpdateSourceWindow(const gfx::Point& location_in_screen);
// Shows/Hides/Destroies the scrim widget |scrim_| based on the current
// location |location_in_screen|.
void UpdateScrim(const gfx::Point& location_in_screen);
// Shows the scrim with the specified opacity, blur and expected bounds.
void ShowScrim(float opacity, float blur, const gfx::Rect& bounds_in_screen);
// A widget placed below the current dragged window to show the blurred or
// transparent background and to prevent the dragged window merge into any
// browser window beneath it during dragging.
std::unique_ptr<views::Widget> scrim_;
DISALLOW_COPY_AND_ASSIGN(TabletModeBrowserWindowDragDelegate);
};
} // namespace ash
#endif // ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_DELEGATE_H_
...@@ -17,6 +17,15 @@ namespace ash { ...@@ -17,6 +17,15 @@ namespace ash {
namespace { namespace {
// The threshold to compute the minimum vertical distance to start showing the
// drag indicators and preview window when dragging a window into splitscreen in
// tablet mode.
constexpr float kIndicatorsThresholdRatio = 0.1;
// The threshold to compute the vertical distance to hide the drag indicators
// and maximize the dragged window after the drag ends.
constexpr float kMaximizeThresholdRatio = 0.4;
// Returns the window selector if overview mode is active, otherwise returns // Returns the window selector if overview mode is active, otherwise returns
// nullptr. // nullptr.
WindowSelector* GetWindowSelector() { WindowSelector* GetWindowSelector() {
...@@ -54,38 +63,59 @@ TabletModeWindowDragDelegate::TabletModeWindowDragDelegate() ...@@ -54,38 +63,59 @@ TabletModeWindowDragDelegate::TabletModeWindowDragDelegate()
TabletModeWindowDragDelegate::~TabletModeWindowDragDelegate() = default; TabletModeWindowDragDelegate::~TabletModeWindowDragDelegate() = default;
// static void TabletModeWindowDragDelegate::StartWindowDrag(
int TabletModeWindowDragDelegate::GetIndicatorsVerticalThreshold( aura::Window* dragged_window,
const gfx::Rect& work_area_bounds) { const gfx::Point& location_in_screen) {
return work_area_bounds.y() + dragged_window_ = dragged_window;
work_area_bounds.height() * kIndicatorsThresholdRatio;
}
// static PrepareForDraggedWindow(location_in_screen);
int TabletModeWindowDragDelegate::GetMaximizeVerticalThreshold(
const gfx::Rect& work_area_bounds) {
return work_area_bounds.y() +
work_area_bounds.height() * kMaximizeThresholdRatio;
}
void TabletModeWindowDragDelegate::OnWindowDragStarted(
aura::Window* dragged_window) {
dragged_window_ = dragged_window;
// Disable the backdrop on the dragged window. // Disable the backdrop on the dragged window.
original_backdrop_mode_ = dragged_window_->GetProperty(kBackdropWindowMode); original_backdrop_mode_ = dragged_window_->GetProperty(kBackdropWindowMode);
dragged_window_->SetProperty(kBackdropWindowMode, dragged_window_->SetProperty(kBackdropWindowMode,
BackdropWindowMode::kDisabled); BackdropWindowMode::kDisabled);
split_view_controller_->OnWindowDragStarted(dragged_window_); split_view_controller_->OnWindowDragStarted(dragged_window_);
if (ShouldOpenOverviewWhenDragStarts()) {
WindowSelectorController* controller =
Shell::Get()->window_selector_controller();
if (!controller->IsSelecting())
controller->ToggleOverview();
}
if (GetWindowSelector())
GetWindowSelector()->OnWindowDragStarted(dragged_window_);
} }
void TabletModeWindowDragDelegate::OnWindowDragEnded( void TabletModeWindowDragDelegate::ContinueWindowDrag(
const gfx::Point& location_in_screen) {
UpdateForDraggedWindow(location_in_screen);
// Update drag indicators and preview window if necessary.
split_view_drag_indicators_->SetIndicatorState(
GetIndicatorState(location_in_screen), location_in_screen);
if (GetWindowSelector()) {
GetWindowSelector()->OnWindowDragContinued(dragged_window_,
location_in_screen);
}
}
void TabletModeWindowDragDelegate::EndWindowDrag(
wm::WmToplevelWindowEventHandler::DragResult result, wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen) {
EndingForDraggedWindow(result, location_in_screen);
dragged_window_->SetProperty(kBackdropWindowMode, original_backdrop_mode_); dragged_window_->SetProperty(kBackdropWindowMode, original_backdrop_mode_);
SplitViewController::SnapPosition snap_position = SplitViewController::NONE; SplitViewController::SnapPosition snap_position = SplitViewController::NONE;
if (result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS && if (result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS &&
split_view_controller_->CanSnap(dragged_window_)) split_view_controller_->CanSnap(dragged_window_)) {
snap_position = GetSnapPosition(location_in_screen); snap_position = GetSnapPosition(location_in_screen);
}
// The window might merge into an overview window or become a new window item
// in overview mode.
if (GetWindowSelector())
GetWindowSelector()->OnWindowDragEnded(dragged_window_, location_in_screen);
split_view_controller_->OnWindowDragEnded(dragged_window_, snap_position, split_view_controller_->OnWindowDragEnded(dragged_window_, snap_position,
location_in_screen); location_in_screen);
split_view_drag_indicators_->SetIndicatorState(IndicatorState::kNone, split_view_drag_indicators_->SetIndicatorState(IndicatorState::kNone,
...@@ -93,10 +123,21 @@ void TabletModeWindowDragDelegate::OnWindowDragEnded( ...@@ -93,10 +123,21 @@ void TabletModeWindowDragDelegate::OnWindowDragEnded(
dragged_window_ = nullptr; dragged_window_ = nullptr;
} }
void TabletModeWindowDragDelegate::UpdateIndicatorState( bool TabletModeWindowDragDelegate::ShouldOpenOverviewWhenDragStarts() {
const gfx::Point& location_in_screen) { DCHECK(dragged_window_);
split_view_drag_indicators_->SetIndicatorState( return true;
GetIndicatorState(location_in_screen), location_in_screen); }
int TabletModeWindowDragDelegate::GetIndicatorsVerticalThreshold(
const gfx::Rect& work_area_bounds) const {
return work_area_bounds.y() +
work_area_bounds.height() * kIndicatorsThresholdRatio;
}
int TabletModeWindowDragDelegate::GetMaximizeVerticalThreshold(
const gfx::Rect& work_area_bounds) const {
return work_area_bounds.y() +
work_area_bounds.height() * kMaximizeThresholdRatio;
} }
SplitViewController::SnapPosition TabletModeWindowDragDelegate::GetSnapPosition( SplitViewController::SnapPosition TabletModeWindowDragDelegate::GetSnapPosition(
...@@ -162,12 +203,12 @@ SplitViewController::SnapPosition TabletModeWindowDragDelegate::GetSnapPosition( ...@@ -162,12 +203,12 @@ SplitViewController::SnapPosition TabletModeWindowDragDelegate::GetSnapPosition(
} }
IndicatorState TabletModeWindowDragDelegate::GetIndicatorState( IndicatorState TabletModeWindowDragDelegate::GetIndicatorState(
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen) const {
SplitViewController::SnapPosition snap_position = SplitViewController::SnapPosition snap_position =
GetSnapPosition(location_in_screen); GetSnapPosition(location_in_screen);
const bool can_snap = split_view_controller_->CanSnap(dragged_window_); const bool can_snap = split_view_controller_->CanSnap(dragged_window_);
if (snap_position != SplitViewController::NONE && if (snap_position != SplitViewController::NONE &&
!split_view_controller()->IsSplitViewModeActive() && can_snap) { !split_view_controller_->IsSplitViewModeActive() && can_snap) {
// Show the preview window if |location_in_screen| is not contained by an // Show the preview window if |location_in_screen| is not contained by an
// eligible target window item to merge the dragged window. // eligible target window item to merge the dragged window.
WindowSelectorItem* item = WindowSelectorItem* item =
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <memory> #include <memory>
#include "ash/ash_export.h"
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/wm_toplevel_window_event_handler.h" #include "ash/wm/wm_toplevel_window_event_handler.h"
...@@ -17,45 +16,57 @@ namespace ash { ...@@ -17,45 +16,57 @@ namespace ash {
enum class IndicatorState; enum class IndicatorState;
class SplitViewDragIndicators; class SplitViewDragIndicators;
// This class includes the common logic that can be used by both // This class includes the common logic when dragging a window around, either
// TabletModeBrowserWindowDragController and TabletModeAppWindowDragController. // it's a browser window, or an app window. It does everything needs to be done
class ASH_EXPORT TabletModeWindowDragDelegate { // other than updating the dragged window (which is done by DragController),
// e.g., it decides when/where to show the drag indicators and preview windows,
// shows/hides the backdrop, interacts with overview and splitview, etc.
class TabletModeWindowDragDelegate {
public: public:
TabletModeWindowDragDelegate(); TabletModeWindowDragDelegate();
virtual ~TabletModeWindowDragDelegate(); virtual ~TabletModeWindowDragDelegate();
// Called when a window starts/continues/ends being dragged around.
void StartWindowDrag(aura::Window* window,
const gfx::Point& location_in_screen);
void ContinueWindowDrag(const gfx::Point& location_in_screen);
void EndWindowDrag(wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen);
aura::Window* dragged_window() { return dragged_window_; }
SplitViewDragIndicators* split_view_drag_indicators_for_testing() { SplitViewDragIndicators* split_view_drag_indicators_for_testing() {
return split_view_drag_indicators_.get(); return split_view_drag_indicators_.get();
} }
protected:
// These three methods are used by its child class to do its special handling
// before/during/after dragging.
virtual void PrepareForDraggedWindow(
const gfx::Point& location_in_screen) = 0;
virtual void UpdateForDraggedWindow(const gfx::Point& location_in_screen) = 0;
virtual void EndingForDraggedWindow(
wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen) = 0;
// Returns true if we should open overview behind the dragged window when drag
// starts.
virtual bool ShouldOpenOverviewWhenDragStarts();
// When the dragged window is dragged past this value, the drag indicators // When the dragged window is dragged past this value, the drag indicators
// will show up. // will show up.
static int GetIndicatorsVerticalThreshold(const gfx::Rect& work_area_bounds); int GetIndicatorsVerticalThreshold(const gfx::Rect& work_area_bounds) const;
// When the dragged window is dragged past this value, a blured scrim will // When the dragged window is dragged past this value, a blured scrim will
// show up, indicating the dragged window will be maximized after releasing. // show up, indicating the dragged window will be maximized after releasing.
static int GetMaximizeVerticalThreshold(const gfx::Rect& work_area_bounds); int GetMaximizeVerticalThreshold(const gfx::Rect& work_area_bounds) const;
// Called when a browser/app window start/end being dragging around.
void OnWindowDragStarted(aura::Window* window);
void OnWindowDragEnded(wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen);
// Updates the split view drag indicators according to |location_in_screen|.
void UpdateIndicatorState(const gfx::Point& location_in_screen);
// Gets the desired snap position for |location_in_screen|. // Gets the desired snap position for |location_in_screen|.
SplitViewController::SnapPosition GetSnapPosition( SplitViewController::SnapPosition GetSnapPosition(
const gfx::Point& location_in_screen) const; const gfx::Point& location_in_screen) const;
SplitViewController* split_view_controller() {
return split_view_controller_;
}
aura::Window* dragged_window() { return dragged_window_; }
private:
// Returns the IndicatorState according to |location_in_screen|. // Returns the IndicatorState according to |location_in_screen|.
IndicatorState GetIndicatorState(const gfx::Point& location_in_screen); IndicatorState GetIndicatorState(const gfx::Point& location_in_screen) const;
SplitViewController* const split_view_controller_; SplitViewController* const split_view_controller_;
...@@ -67,6 +78,7 @@ class ASH_EXPORT TabletModeWindowDragDelegate { ...@@ -67,6 +78,7 @@ class ASH_EXPORT TabletModeWindowDragDelegate {
// The backdrop should be disabled during dragging and resumed after dragging. // The backdrop should be disabled during dragging and resumed after dragging.
BackdropWindowMode original_backdrop_mode_ = BackdropWindowMode::kAuto; BackdropWindowMode original_backdrop_mode_ = BackdropWindowMode::kAuto;
private:
DISALLOW_COPY_AND_ASSIGN(TabletModeWindowDragDelegate); DISALLOW_COPY_AND_ASSIGN(TabletModeWindowDragDelegate);
}; };
......
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