Commit 7e9b5103 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

Allow browser dragging on the non-tabstrip caption area.

The dragging behavior is the same with dragging an app window from the
top of the screen. As it shares some same logic with dragging an app
window, these logic are extracted to TabletModeWindowDragDelegate.

See recorded video:
https://drive.google.com/open?id=1d6t7K-ZuxgpT57b-Mx5gMJ49IjMHX-9X

Bug: 823769
Test: SplitViewTabDraggingTest.OnlyAllowDraggingOnCaptionArea

Change-Id: I09d852ef9eefd1059f2be85fee52e1714b1968fd
Reviewed-on: https://chromium-review.googlesource.com/1150860
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580004}
parent b870c2c6
...@@ -262,8 +262,6 @@ void ShelfLayoutManager::UpdateVisibilityState() { ...@@ -262,8 +262,6 @@ void ShelfLayoutManager::UpdateVisibilityState() {
SetState(SHELF_VISIBLE); SetState(SHELF_VISIBLE);
} else if (Shell::Get()->screen_pinning_controller()->IsPinned()) { } else if (Shell::Get()->screen_pinning_controller()->IsPinned()) {
SetState(SHELF_HIDDEN); SetState(SHELF_HIDDEN);
} else if (IsDraggingWindowFromTopOfDisplay()) {
SetState(SHELF_VISIBLE);
} else { } else {
// TODO(zelidrag): Verify shelf drag animation still shows on the device // TODO(zelidrag): Verify shelf drag animation still shows on the device
// when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN. // when we are in SHELF_AUTO_HIDE_ALWAYS_HIDDEN.
...@@ -273,7 +271,9 @@ void ShelfLayoutManager::UpdateVisibilityState() { ...@@ -273,7 +271,9 @@ void ShelfLayoutManager::UpdateVisibilityState() {
switch (window_state) { switch (window_state) {
case wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN: { case wm::WORKSPACE_WINDOW_STATE_FULL_SCREEN: {
if (IsShelfAutoHideForFullscreenMaximized()) { if (IsDraggingWindowFromTopOrCaptionArea()) {
SetState(SHELF_VISIBLE);
} else if (IsShelfAutoHideForFullscreenMaximized()) {
SetState(SHELF_AUTO_HIDE); SetState(SHELF_AUTO_HIDE);
} else if (IsShelfHiddenForFullscreen()) { } else if (IsShelfHiddenForFullscreen()) {
SetState(SHELF_HIDDEN); SetState(SHELF_HIDDEN);
...@@ -285,7 +285,9 @@ void ShelfLayoutManager::UpdateVisibilityState() { ...@@ -285,7 +285,9 @@ void ShelfLayoutManager::UpdateVisibilityState() {
break; break;
} }
case wm::WORKSPACE_WINDOW_STATE_MAXIMIZED: case wm::WORKSPACE_WINDOW_STATE_MAXIMIZED:
if (IsShelfAutoHideForFullscreenMaximized()) { if (IsDraggingWindowFromTopOrCaptionArea()) {
SetState(SHELF_VISIBLE);
} else if (IsShelfAutoHideForFullscreenMaximized()) {
SetState(SHELF_AUTO_HIDE); SetState(SHELF_AUTO_HIDE);
} else { } else {
SetState(CalculateShelfVisibility()); SetState(CalculateShelfVisibility());
...@@ -414,14 +416,21 @@ bool ShelfLayoutManager::ProcessGestureEvent( ...@@ -414,14 +416,21 @@ bool ShelfLayoutManager::ProcessGestureEvent(
return false; return false;
} }
bool ShelfLayoutManager::IsDraggingWindowFromTopOfDisplay() const { bool ShelfLayoutManager::IsDraggingWindowFromTopOrCaptionArea() const {
// Currently dragging maximized or fullscreen window from the top or the
// caption area is only allowed in tablet mode.
if (!IsTabletModeEnabled())
return false;
// TODO(minch): Check active window directly if removed search field // TODO(minch): Check active window directly if removed search field
// in overview mode. http://crbug.com/866679 // in overview mode. http://crbug.com/866679
auto windows = Shell::Get()->mru_window_tracker()->BuildMruWindowList(); auto windows = Shell::Get()->mru_window_tracker()->BuildMruWindowList();
for (auto* window : windows) { for (auto* window : windows) {
wm::WindowState* window_state = wm::GetWindowState(window); wm::WindowState* window_state = wm::GetWindowState(window);
if (window_state && window_state->is_dragged() && if (window_state && window_state->is_dragged() &&
window_state->drag_details()->window_component == HTCLIENT) { (window_state->IsMaximized() || window_state->IsFullscreen()) &&
(window_state->drag_details()->window_component == HTCLIENT ||
window_state->drag_details()->window_component == HTCAPTION)) {
return true; return true;
} }
} }
......
...@@ -138,8 +138,10 @@ class ASH_EXPORT ShelfLayoutManager ...@@ -138,8 +138,10 @@ class ASH_EXPORT ShelfLayoutManager
// be processed any further, false otherwise. // be processed any further, false otherwise.
bool ProcessGestureEvent(const ui::GestureEvent& event_in_screen); bool ProcessGestureEvent(const ui::GestureEvent& event_in_screen);
// Returns true if a window is being dragged from the top of the display. // Returns true if a maximized or fullscreen window is being dragged from the
bool IsDraggingWindowFromTopOfDisplay() const; // top of the display or from the caption area. Note currently for this case
// it's only allowed in tablet mode, not in laptop mode.
bool IsDraggingWindowFromTopOrCaptionArea() const;
// Overridden from wm::WmSnapToPixelLayoutManager: // Overridden from wm::WmSnapToPixelLayoutManager:
void OnWindowResized() override; void OnWindowResized() override;
......
...@@ -141,8 +141,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -141,8 +141,8 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// Ends the split view mode. // Ends the split view mode.
void EndSplitView(); void EndSplitView();
// Called when a window's tab(s) start/end being dragged around or other // Called when a window (either it's browser window or an app window) start/
// non-browser windows start/end being dragged from the top of the display. // end being dragged.
void OnWindowDragStarted(aura::Window* dragged_window); void OnWindowDragStarted(aura::Window* dragged_window);
void OnWindowDragEnded(aura::Window* dragged_window, void OnWindowDragEnded(aura::Window* dragged_window,
SnapPosition desired_snap_position, SnapPosition desired_snap_position,
......
...@@ -1582,27 +1582,35 @@ class SplitViewTabDraggingTest : public SplitViewControllerTest { ...@@ -1582,27 +1582,35 @@ class SplitViewTabDraggingTest : public SplitViewControllerTest {
}; };
// Test that in tablet mode, we only allow dragging that happens on window // Test that in tablet mode, we only allow dragging that happens on window
// caption area and tab-dragging is in process. // caption area.
TEST_F(SplitViewTabDraggingTest, OnlyAllowDraggingOnTabs) { TEST_F(SplitViewTabDraggingTest, OnlyAllowDraggingOnCaptionArea) {
const gfx::Rect bounds(0, 0, 400, 400); const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window(CreateWindow(bounds)); std::unique_ptr<aura::Window> window(CreateWindow(bounds));
std::unique_ptr<WindowResizer> resizer =
CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
EXPECT_FALSE(resizer.get());
SetIsInTabDragging(window.get(), /*is_dragging=*/true);
// Only dragging on HTCAPTION area is allowed. // Only dragging on HTCAPTION area is allowed.
resizer = CreateResizerForTest(window.get(), gfx::Point(), HTLEFT); std::unique_ptr<WindowResizer> resizer =
CreateResizerForTest(window.get(), gfx::Point(), HTLEFT);
EXPECT_FALSE(resizer.get()); EXPECT_FALSE(resizer.get());
resizer = CreateResizerForTest(window.get(), gfx::Point(), HTRIGHT); resizer = CreateResizerForTest(window.get(), gfx::Point(), HTRIGHT);
EXPECT_FALSE(resizer.get()); EXPECT_FALSE(resizer.get());
resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION); resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
EXPECT_TRUE(resizer.get()); EXPECT_TRUE(resizer.get());
resizer->CompleteDrag(); resizer->CompleteDrag();
resizer.reset();
// No matter if we're in tab-dragging process, as long as the drag happens on
// the caption area, it should be able to drag the window.
SetIsInTabDragging(window.get(), /*is_dragging=*/true);
resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
EXPECT_TRUE(resizer.get());
resizer->CompleteDrag();
resizer.reset();
SetIsInTabDragging(window.get(), /*is_dragging=*/false); SetIsInTabDragging(window.get(), /*is_dragging=*/false);
resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION); resizer = CreateResizerForTest(window.get(), gfx::Point(), HTCAPTION);
EXPECT_FALSE(resizer.get()); EXPECT_TRUE(resizer.get());
resizer->CompleteDrag();
resizer.reset();
} }
// Test that in tablet mode, if the dragging is from mouse event, the mouse // Test that in tablet mode, if the dragging is from mouse event, the mouse
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#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/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/overview/window_selector_controller.h"
...@@ -87,72 +85,29 @@ bool TabletModeAppWindowDragController::DragWindowFromTop( ...@@ -87,72 +85,29 @@ bool TabletModeAppWindowDragController::DragWindowFromTop(
void TabletModeAppWindowDragController::StartWindowDrag( void TabletModeAppWindowDragController::StartWindowDrag(
ui::GestureEvent* event) { ui::GestureEvent* event) {
initial_location_in_screen_ = GetEventLocationInScreen(event);
drag_delegate_->StartWindowDrag(static_cast<aura::Window*>(event->target()), drag_delegate_->StartWindowDrag(static_cast<aura::Window*>(event->target()),
initial_location_in_screen_); GetEventLocationInScreen(event));
WindowSelectorController* window_selector_controller =
Shell::Get()->window_selector_controller();
DCHECK(window_selector_controller->IsSelecting());
WindowGrid* window_grid =
window_selector_controller->window_selector()->GetGridWithRootWindow(
drag_delegate_->dragged_window()->GetRootWindow());
const std::vector<std::unique_ptr<WindowSelectorItem>>& selector_items =
window_grid->window_list();
new_selector_item_bounds_ = selector_items.back().get()->target_bounds();
} }
void TabletModeAppWindowDragController::UpdateWindowDrag( void TabletModeAppWindowDragController::UpdateWindowDrag(
ui::GestureEvent* event) { ui::GestureEvent* event) {
const gfx::Point location_in_screen(GetEventLocationInScreen(event)); // Update the dragged window's tranform during dragging.
UpdateDraggedWindow(location_in_screen); drag_delegate_->ContinueWindowDrag(
drag_delegate_->ContinueWindowDrag(location_in_screen); GetEventLocationInScreen(event),
TabletModeWindowDragDelegate::UpdateDraggedWindowType::UPDATE_TRANSFORM);
} }
void TabletModeAppWindowDragController::EndWindowDrag( void TabletModeAppWindowDragController::EndWindowDrag(
ui::GestureEvent* event, ui::GestureEvent* event,
wm::WmToplevelWindowEventHandler::DragResult result) { wm::WmToplevelWindowEventHandler::DragResult result) {
const gfx::Point location_in_screen(GetEventLocationInScreen(event));
drag_delegate_->dragged_window()->SetTransform(gfx::Transform());
if (event->type() == ui::ET_SCROLL_FLING_START && if (event->type() == ui::ET_SCROLL_FLING_START &&
event->details().velocity_y() > kFlingToOverviewThreshold) { event->details().velocity_y() > kFlingToOverviewThreshold) {
DCHECK(Shell::Get()->window_selector_controller()->IsSelecting());
Shell::Get()->window_selector_controller()->window_selector()->AddItem( Shell::Get()->window_selector_controller()->window_selector()->AddItem(
drag_delegate_->dragged_window(), /*reposition=*/true, drag_delegate_->dragged_window(), /*reposition=*/true,
/*animate=*/true); /*animate=*/true);
} }
drag_delegate_->EndWindowDrag(result, location_in_screen); drag_delegate_->EndWindowDrag(result, GetEventLocationInScreen(event));
}
void TabletModeAppWindowDragController::UpdateDraggedWindow(
const gfx::Point& location_in_screen) {
DCHECK(drag_delegate_->dragged_window());
RootWindowController::ForWindow(drag_delegate_->dragged_window())
->GetShelfLayoutManager()
->UpdateVisibilityState();
float scale = CalculateWindowScale(location_in_screen.y());
gfx::Transform transform;
const gfx::Rect window_bounds = drag_delegate_->dragged_window()->bounds();
transform.Translate(
(location_in_screen.x() - window_bounds.x()) -
(initial_location_in_screen_.x() - window_bounds.x()) * scale,
(location_in_screen.y() - window_bounds.y()) -
(initial_location_in_screen_.y() - window_bounds.y()) * scale);
transform.Scale(scale, scale);
drag_delegate_->dragged_window()->SetTransform(transform);
}
float TabletModeAppWindowDragController::CalculateWindowScale(
int y_location_in_screen) const {
float minimum_scale =
static_cast<float>(new_selector_item_bounds_.height()) /
static_cast<float>(drag_delegate_->dragged_window()->bounds().height());
int y_full = new_selector_item_bounds_.y();
int y_diff = y_full - y_location_in_screen;
if (y_diff < 0)
return minimum_scale;
return (1.0f - minimum_scale) * y_diff / y_full + minimum_scale;
} }
} // namespace ash } // namespace ash
...@@ -38,25 +38,8 @@ class ASH_EXPORT TabletModeAppWindowDragController { ...@@ -38,25 +38,8 @@ 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);
// The scale of the window during drag is based on the distance from
// |y_location_in_screen| to the y position of |new_selector_item_bounds_|.
// The dragged window will become smaller when it becomes nearer to the new
// selector item. And then keep the minimum scale if it has been dragged
// further than the new selector item.
float CalculateWindowScale(int y_location_in_screen) const;
std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_; std::unique_ptr<TabletModeWindowDragDelegate> drag_delegate_;
gfx::Point initial_location_in_screen_;
// Overview mode will be triggered if a window is being dragged from the top
// of the display, and a new selector item will be created in the overview
// grid. See |new_selector_item_widget_| in WindowGrid for more info.
gfx::Rect new_selector_item_bounds_;
DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragController); DISALLOW_COPY_AND_ASSIGN(TabletModeAppWindowDragController);
}; };
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
#include "ash/wm/window_util.h"
#include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/cursor_manager.h" #include "ui/wm/core/cursor_manager.h"
...@@ -40,23 +41,29 @@ TabletModeBrowserWindowDragController:: ...@@ -40,23 +41,29 @@ TabletModeBrowserWindowDragController::
void TabletModeBrowserWindowDragController::Drag( void TabletModeBrowserWindowDragController::Drag(
const gfx::Point& location_in_parent, const gfx::Point& location_in_parent,
int event_flags) { int event_flags) {
// Update dragged window's bounds. gfx::Point location_in_screen = location_in_parent;
gfx::Rect bounds = CalculateBoundsForDrag(location_in_parent); ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
if (bounds != GetTarget()->bounds()) { previous_location_in_screen_ = location_in_screen;
// Update the dragged window, the drag indicators, the preview window,
// source window position, blurred background, etc, if necessary.
if (wm::IsDraggingTabs(GetTarget())) {
// Update the dragged window's bounds if it's tab-dragging.
base::WeakPtr<TabletModeBrowserWindowDragController> resizer( base::WeakPtr<TabletModeBrowserWindowDragController> resizer(
weak_ptr_factory_.GetWeakPtr()); weak_ptr_factory_.GetWeakPtr());
GetTarget()->SetBounds(bounds); drag_delegate_->ContinueWindowDrag(
location_in_screen,
TabletModeWindowDragDelegate::UpdateDraggedWindowType::UPDATE_BOUNDS,
CalculateBoundsForDrag(location_in_parent));
// Note, this might have been deleted when reaching here.
if (!resizer) if (!resizer)
return; return;
} else {
// Otherwise, update the dragged window's transform.
drag_delegate_->ContinueWindowDrag(
location_in_screen, TabletModeWindowDragDelegate::
UpdateDraggedWindowType::UPDATE_TRANSFORM);
} }
gfx::Point location_in_screen = location_in_parent;
::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
previous_location_in_screen_ = location_in_screen;
// Update the drag indicators, snap preview window, source window position,
// blurred backgournd, etc, if necessary.
drag_delegate_->ContinueWindowDrag(location_in_screen);
} }
void TabletModeBrowserWindowDragController::CompleteDrag() { void TabletModeBrowserWindowDragController::CompleteDrag() {
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_grid.h"
#include "ash/wm/overview/window_selector.h" #include "ash/wm/overview/window_selector.h"
...@@ -34,12 +36,30 @@ WindowSelector* GetWindowSelector() { ...@@ -34,12 +36,30 @@ WindowSelector* GetWindowSelector() {
: nullptr; : nullptr;
} }
// Gets the new selector item's bounds in overview grid that is displaying in
// the same root window as |dragged_window|.
gfx::Rect GetNewSelectorItemBounds(aura::Window* dragged_window) {
if (!Shell::Get()->window_selector_controller()->IsSelecting())
return gfx::Rect();
WindowGrid* window_grid = GetWindowSelector()->GetGridWithRootWindow(
dragged_window->GetRootWindow());
if (!window_grid || window_grid->empty())
return gfx::Rect();
WindowSelectorItem* last_item = window_grid->window_list().back().get();
if (!window_grid->IsNewSelectorItemWindow(last_item->GetWindow()))
return gfx::Rect();
return last_item->target_bounds();
}
} // namespace } // namespace
TabletModeWindowDragDelegate::TabletModeWindowDragDelegate() TabletModeWindowDragDelegate::TabletModeWindowDragDelegate()
: split_view_controller_(Shell::Get()->split_view_controller()), : split_view_controller_(Shell::Get()->split_view_controller()),
split_view_drag_indicators_(std::make_unique<SplitViewDragIndicators>()) { split_view_drag_indicators_(std::make_unique<SplitViewDragIndicators>()),
} weak_ptr_factory_(this) {}
TabletModeWindowDragDelegate::~TabletModeWindowDragDelegate() = default; TabletModeWindowDragDelegate::~TabletModeWindowDragDelegate() = default;
...@@ -47,9 +67,15 @@ void TabletModeWindowDragDelegate::StartWindowDrag( ...@@ -47,9 +67,15 @@ void TabletModeWindowDragDelegate::StartWindowDrag(
aura::Window* dragged_window, aura::Window* dragged_window,
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen) {
dragged_window_ = dragged_window; dragged_window_ = dragged_window;
initial_location_in_screen_ = location_in_screen;
PrepareForDraggedWindow(location_in_screen); PrepareForDraggedWindow(location_in_screen);
// Update the shelf's visibility.
RootWindowController::ForWindow(dragged_window_)
->GetShelfLayoutManager()
->UpdateVisibilityState();
// 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,
...@@ -72,10 +98,32 @@ void TabletModeWindowDragDelegate::StartWindowDrag( ...@@ -72,10 +98,32 @@ void TabletModeWindowDragDelegate::StartWindowDrag(
GetWindowSelector()->OnWindowDragStarted(dragged_window_, GetWindowSelector()->OnWindowDragStarted(dragged_window_,
/*animate=*/was_overview_open); /*animate=*/was_overview_open);
} }
new_selector_item_bounds_ = GetNewSelectorItemBounds(dragged_window_);
} }
void TabletModeWindowDragDelegate::ContinueWindowDrag( void TabletModeWindowDragDelegate::ContinueWindowDrag(
const gfx::Point& location_in_screen) { const gfx::Point& location_in_screen,
UpdateDraggedWindowType type,
const gfx::Rect& target_bounds) {
if (type == UpdateDraggedWindowType::UPDATE_BOUNDS) {
// UPDATE_BOUNDS is used when dragging tab(s) out of a browser window.
// Changing bounds might delete ourselves as the dragged (browser) window
// tab(s) might merge into another browser window.
base::WeakPtr<TabletModeWindowDragDelegate> delegate(
weak_ptr_factory_.GetWeakPtr());
if (target_bounds != dragged_window_->bounds()) {
dragged_window_->SetBounds(target_bounds);
if (!delegate)
return;
}
} else { // type == UpdateDraggedWindowType::UPDATE_TRANSFORM
// UPDATE_TRANSFORM is used when dragging an entire window around, either
// it's a browser window or an app window.
UpdateDraggedWindowTransform(location_in_screen);
}
// For child classes to do their special handling if any.
UpdateForDraggedWindow(location_in_screen); UpdateForDraggedWindow(location_in_screen);
// Update drag indicators and preview window if necessary. // Update drag indicators and preview window if necessary.
...@@ -109,6 +157,15 @@ void TabletModeWindowDragDelegate::EndWindowDrag( ...@@ -109,6 +157,15 @@ void TabletModeWindowDragDelegate::EndWindowDrag(
location_in_screen); location_in_screen);
split_view_drag_indicators_->SetIndicatorState(IndicatorState::kNone, split_view_drag_indicators_->SetIndicatorState(IndicatorState::kNone,
location_in_screen); location_in_screen);
// If |dragged_window_|'s transform has changed during dragging, and it has
// not been added into overview grid, restore its transform to identity.
if (!dragged_window_->layer()->GetTargetTransform().IsIdentity() &&
(!GetWindowSelector() ||
!GetWindowSelector()->IsWindowInOverview(dragged_window_))) {
dragged_window_->SetTransform(gfx::Transform());
}
dragged_window_ = nullptr; dragged_window_ = nullptr;
} }
...@@ -228,4 +285,31 @@ IndicatorState TabletModeWindowDragDelegate::GetIndicatorState( ...@@ -228,4 +285,31 @@ IndicatorState TabletModeWindowDragDelegate::GetIndicatorState(
return can_snap ? IndicatorState::kDragArea : IndicatorState::kCannotSnap; return can_snap ? IndicatorState::kDragArea : IndicatorState::kCannotSnap;
} }
void TabletModeWindowDragDelegate::UpdateDraggedWindowTransform(
const gfx::Point& location_in_screen) {
DCHECK(Shell::Get()->window_selector_controller()->IsSelecting());
// Calculate the desired scale along the y-axis. The scale of the window
// during drag is based on the distance from |y_location_in_screen| to the y
// position of |new_selector_item_bounds_|. The dragged window will become
// smaller when it becomes nearer to the new selector item. And then keep the
// minimum scale if it has been dragged further than the new selector item.
float scale = static_cast<float>(new_selector_item_bounds_.height()) /
static_cast<float>(dragged_window_->bounds().height());
int y_full = new_selector_item_bounds_.y();
int y_diff = y_full - location_in_screen.y();
if (y_diff >= 0)
scale = (1.0f - scale) * y_diff / y_full + scale;
gfx::Transform transform;
const gfx::Rect window_bounds = dragged_window_->bounds();
transform.Translate(
(location_in_screen.x() - window_bounds.x()) -
(initial_location_in_screen_.x() - window_bounds.x()) * scale,
(location_in_screen.y() - window_bounds.y()) -
(initial_location_in_screen_.y() - window_bounds.y()) * scale);
transform.Scale(scale, scale);
dragged_window_->SetTransform(transform);
}
} // namespace ash } // namespace ash
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#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"
#include "base/memory/weak_ptr.h"
namespace ash { namespace ash {
...@@ -17,19 +18,34 @@ enum class IndicatorState; ...@@ -17,19 +18,34 @@ enum class IndicatorState;
class SplitViewDragIndicators; class SplitViewDragIndicators;
// This class includes the common logic when dragging a window around, either // This class includes the common logic when dragging a window around, either
// it's a browser window, or an app window. It does everything needs to be done // it's a browser window, or an app window. It does almost everything needs to
// other than updating the dragged window (which is done by DragController), // be done, including updating the dragged window's bounds (if it's dragged by
// e.g., it decides when/where to show the drag indicators and preview windows, // tabs) or transform (if it's dragged by entire window). it also decides
// shows/hides the backdrop, interacts with overview and splitview, etc. // when/where to show the drag indicators and preview windows, shows/hides the
// backdrop, interacts with overview and splitview, etc.
class TabletModeWindowDragDelegate { class TabletModeWindowDragDelegate {
public: public:
enum class UpdateDraggedWindowType {
UPDATE_BOUNDS,
UPDATE_TRANSFORM,
};
TabletModeWindowDragDelegate(); TabletModeWindowDragDelegate();
virtual ~TabletModeWindowDragDelegate(); virtual ~TabletModeWindowDragDelegate();
// Called when a window starts/continues/ends being dragged around. // Called when a window starts being dragged.
void StartWindowDrag(aura::Window* window, void StartWindowDrag(aura::Window* window,
const gfx::Point& location_in_screen); const gfx::Point& location_in_screen);
void ContinueWindowDrag(const gfx::Point& location_in_screen);
// Called when a window continues being dragged. |type| specifies how we want
// to update the dragged window during dragging, and |target_bounds| is the
// target window bounds for the dragged window if |type| is UPDATE_BOUNDS.
// Note |target_bounds| has no use if |type| is UPDATE_TRANSFROM.
void ContinueWindowDrag(const gfx::Point& location_in_screen,
UpdateDraggedWindowType type,
const gfx::Rect& target_bounds = gfx::Rect());
// Calls when a window ends dragging with its drag result |result|.
void EndWindowDrag(wm::WmToplevelWindowEventHandler::DragResult result, void EndWindowDrag(wm::WmToplevelWindowEventHandler::DragResult result,
const gfx::Point& location_in_screen); const gfx::Point& location_in_screen);
...@@ -68,6 +84,9 @@ class TabletModeWindowDragDelegate { ...@@ -68,6 +84,9 @@ class TabletModeWindowDragDelegate {
// Returns the IndicatorState according to |location_in_screen|. // Returns the IndicatorState according to |location_in_screen|.
IndicatorState GetIndicatorState(const gfx::Point& location_in_screen) const; IndicatorState GetIndicatorState(const gfx::Point& location_in_screen) const;
// Update the dragged window's transform during dragging.
void UpdateDraggedWindowTransform(const gfx::Point& location_in_screen);
SplitViewController* const split_view_controller_; SplitViewController* const split_view_controller_;
// A widget to display the drag indicators and preview window. // A widget to display the drag indicators and preview window.
...@@ -78,6 +97,16 @@ class TabletModeWindowDragDelegate { ...@@ -78,6 +97,16 @@ class 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;
gfx::Point initial_location_in_screen_;
// Overview mode will be triggered if a window is being dragged, and a new
// selector item will be created in the overview grid. The variable stores
// the new selector item bounds in overview and will be used to calculate
// the desired window tranform during dragging.
gfx::Rect new_selector_item_bounds_;
base::WeakPtrFactory<TabletModeWindowDragDelegate> weak_ptr_factory_;
private: private:
DISALLOW_COPY_AND_ASSIGN(TabletModeWindowDragDelegate); DISALLOW_COPY_AND_ASSIGN(TabletModeWindowDragDelegate);
}; };
......
...@@ -1790,22 +1790,6 @@ TEST_F(TabletModeWindowManagerTest, SetPropertyOnUnmanagedWindow) { ...@@ -1790,22 +1790,6 @@ TEST_F(TabletModeWindowManagerTest, SetPropertyOnUnmanagedWindow) {
window->Show(); window->Show();
} }
// Test that there is no window resizer in tablet mode.
TEST_F(TabletModeWindowManagerTest, NoWindowResizerInTabletMode) {
gfx::Rect rect(10, 10, 200, 200);
std::unique_ptr<aura::Window> window(
CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect));
std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
window.get(), gfx::Point(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE));
EXPECT_TRUE(resizer.get());
resizer.reset();
CreateTabletModeWindowManager();
resizer = CreateWindowResizer(window.get(), gfx::Point(), HTCAPTION,
::wm::WINDOW_MOVE_SOURCE_MOUSE);
EXPECT_FALSE(resizer.get());
}
// Test that the minimized window bounds doesn't change until it's unminimized. // Test that the minimized window bounds doesn't change until it's unminimized.
TEST_F(TabletModeWindowManagerTest, DontChangeBoundsForMinimizedWindow) { TEST_F(TabletModeWindowManagerTest, DontChangeBoundsForMinimizedWindow) {
gfx::Rect rect(10, 10, 200, 50); gfx::Rect rect(10, 10, 200, 50);
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_positioning_utils.h" #include "ash/wm/window_positioning_utils.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h" #include "ash/wm/wm_event.h"
#include "ash/wm/workspace/phantom_window_controller.h" #include "ash/wm/workspace/phantom_window_controller.h"
#include "ash/wm/workspace/two_step_edge_cycler.h" #include "ash/wm/workspace/two_step_edge_cycler.h"
...@@ -69,8 +68,8 @@ std::unique_ptr<WindowResizer> CreateWindowResizer( ...@@ -69,8 +68,8 @@ std::unique_ptr<WindowResizer> CreateWindowResizer(
->tablet_mode_controller() ->tablet_mode_controller()
->IsTabletModeWindowManagerEnabled()) { ->IsTabletModeWindowManagerEnabled()) {
// We still don't allow any dragging or resizing happening on the area other // We still don't allow any dragging or resizing happening on the area other
// then caption area. Only allow dragging that happends on the tab(s). // then caption area.
if (window_component != HTCAPTION || !wm::IsDraggingTabs(window)) if (window_component != HTCAPTION)
return nullptr; return nullptr;
window_state->CreateDragDetails(point_in_parent, window_component, source); window_state->CreateDragDetails(point_in_parent, window_component, source);
......
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