Commit 832c793a authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Reland "Scale source window during tab drag-and-drop"

This is a reland of 2a23cb68

The build failure was due to an ash header being included in a
non-ChromeOS build. This managed to build correctly until my CL.
The reland makes the include conditional on building for ChromeOS.

TBR=oshima@chromium.org

Original change's description:
> Scale source window during tab drag-and-drop
>
> This behavior is very similar to tablet mode tab drags from the native
> tab strip. Some of this code is copied, and some is shared (through
> TabletModeBrowserWindowDragSessionWindowsHider).
>
> Bug: 1069869
> Change-Id: If5c6f163f7d8af9918be3bc97ca8a91b1df063c1
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2202507
> Commit-Queue: Collin Baker <collinbaker@chromium.org>
> Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
> Reviewed-by: Xiaoqian Dai <xdai@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#770272}

Bug: 1069869
Change-Id: I02f6becf72fac663a744d2033e16e2fd14dce843
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2209384Reviewed-by: default avatarCollin Baker <collinbaker@chromium.org>
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#770322}
parent da8b32d5
......@@ -82,6 +82,7 @@ component("ash") {
"wm/overview/overview_controller.h",
"wm/splitview/split_view_controller.h",
"wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h",
"wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h",
"wm/tablet_mode/tablet_mode_controller.h",
"wm/tablet_mode/tablet_mode_window_drag_delegate.h",
"wm/tablet_mode/tablet_mode_window_resizer.h",
......@@ -1401,6 +1402,7 @@ component("ash") {
"wm/tablet_mode/scoped_skip_user_session_blocked_check.cc",
"wm/tablet_mode/scoped_skip_user_session_blocked_check.h",
"wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc",
"wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.cc",
"wm/tablet_mode/tablet_mode_controller.cc",
"wm/tablet_mode/tablet_mode_toggle_fullscreen_event_handler.cc",
"wm/tablet_mode/tablet_mode_toggle_fullscreen_event_handler.h",
......
......@@ -5,6 +5,7 @@
#include "ash/drag_drop/tab_drag_drop_delegate.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
......@@ -12,13 +13,17 @@
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_drag_indicators.h"
#include "ash/wm/splitview/split_view_utils.h"
#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h"
#include "base/no_destructor.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/clipboard/clipboard_format_type.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
......@@ -34,6 +39,14 @@ constexpr float kDistanceFromEdgeDp = 16.f;
// prevents accidental snaps.
constexpr float kMinimumDragToSnapDistanceDp = 96.f;
// 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;
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsSourceWindowForDrag, false)
} // namespace
// static
......@@ -44,25 +57,40 @@ bool TabDragDropDelegate::IsChromeTabDrag(const ui::OSExchangeData& drag_data) {
return Shell::Get()->shell_delegate()->IsTabDrag(drag_data);
}
// static
bool TabDragDropDelegate::IsSourceWindowForDrag(const aura::Window* window) {
return window->GetProperty(kIsSourceWindowForDrag);
}
TabDragDropDelegate::TabDragDropDelegate(
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& start_location_in_screen)
: root_window_(root_window),
source_window_(source_window),
source_window_(source_window->GetToplevelWindow()),
start_location_in_screen_(start_location_in_screen) {
DCHECK(root_window_);
DCHECK(source_window_);
source_window_->SetProperty(kIsSourceWindowForDrag, true);
split_view_drag_indicators_ =
std::make_unique<SplitViewDragIndicators>(root_window_);
}
TabDragDropDelegate::~TabDragDropDelegate() = default;
TabDragDropDelegate::~TabDragDropDelegate() {
if (!source_window_->GetProperty(kIsSourceWindowForDrag))
return;
// If we didn't drop to a new window, we must restore the original window.
RestoreSourceWindowBounds();
source_window_->ClearProperty(kIsSourceWindowForDrag);
}
void TabDragDropDelegate::DragUpdate(const gfx::Point& location_in_screen) {
const gfx::Rect area =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
root_window_);
SplitViewController::SnapPosition snap_position =
const SplitViewController::SnapPosition snap_position =
::ash::GetSnapPositionForLocation(
Shell::GetPrimaryRootWindow(), location_in_screen,
start_location_in_screen_,
......@@ -79,8 +107,7 @@ void TabDragDropDelegate::DragUpdate(const gfx::Point& location_in_screen) {
true, SplitViewDragIndicators::WindowDraggingState::kFromTop,
snap_position));
// TODO(https://crbug.com/1069869): scale source window up/down similar to
// |TabletModeBrowserWindowDragDelegate::UpdateSourceWindow()|.
UpdateSourceWindowBoundsIfNecessary(snap_position);
}
void TabDragDropDelegate::Drop(const gfx::Point& location_in_screen,
......@@ -88,6 +115,7 @@ void TabDragDropDelegate::Drop(const gfx::Point& location_in_screen,
aura::Window* const new_window =
Shell::Get()->shell_delegate()->CreateBrowserForTabDrop(source_window_,
drop_data);
DCHECK(new_window);
const gfx::Rect area =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
......@@ -103,6 +131,13 @@ void TabDragDropDelegate::Drop(const gfx::Point& location_in_screen,
/*vertical_edge_inset=*/area.height() * kHighlightScreenPrimaryAxisRatio +
kHighlightScreenEdgePaddingDp);
if (snap_position == SplitViewController::SnapPosition::NONE)
RestoreSourceWindowBounds();
// This must be done after restoring the source window's bounds since
// otherwise the SetBounds() call may have no effect.
source_window_->ClearProperty(kIsSourceWindowForDrag);
if (snap_position == SplitViewController::SnapPosition::NONE)
return;
......@@ -121,8 +156,62 @@ void TabDragDropDelegate::Drop(const gfx::Point& location_in_screen,
// |source_window_| is itself a child window of the browser since it
// hosts web content (specifically, the tab strip WebUI). Snap its
// toplevel window which is the browser window.
split_view_controller->SnapWindow(source_window_->GetToplevelWindow(),
opposite_position);
split_view_controller->SnapWindow(source_window_, opposite_position);
}
void TabDragDropDelegate::UpdateSourceWindowBoundsIfNecessary(
SplitViewController::SnapPosition candidate_snap_position) {
SplitViewController* const split_view_controller =
SplitViewController::Get(source_window_);
if (split_view_controller->IsWindowInSplitView(source_window_))
return;
if (!windows_hider_) {
windows_hider_ =
std::make_unique<TabletModeBrowserWindowDragSessionWindowsHider>(
source_window_, nullptr);
}
gfx::Rect new_source_window_bounds;
if (candidate_snap_position == SplitViewController::SnapPosition::NONE) {
const gfx::Rect area =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
root_window_);
new_source_window_bounds = area;
new_source_window_bounds.ClampToCenteredSize(gfx::Size(
area.width() * kSourceWindowScale, area.height() * kSourceWindowScale));
} else {
const SplitViewController::SnapPosition opposite_position =
(candidate_snap_position == SplitViewController::SnapPosition::LEFT)
? SplitViewController::SnapPosition::RIGHT
: SplitViewController::SnapPosition::LEFT;
new_source_window_bounds =
SplitViewController::Get(source_window_)
->GetSnappedWindowBoundsInScreen(opposite_position, source_window_);
}
wm::ConvertRectFromScreen(source_window_->parent(),
&new_source_window_bounds);
if (new_source_window_bounds != source_window_->GetTargetBounds()) {
ui::ScopedLayerAnimationSettings settings(
source_window_->layer()->GetAnimator());
settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
source_window_->SetBounds(new_source_window_bounds);
}
}
void TabDragDropDelegate::RestoreSourceWindowBounds() {
if (SplitViewController::Get(source_window_)
->IsWindowInSplitView(source_window_))
return;
const gfx::Rect area =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
root_window_);
source_window_->SetBounds(area);
}
} // namespace ash
......@@ -8,6 +8,7 @@
#include <memory>
#include "ash/ash_export.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ui/gfx/geometry/point.h"
namespace aura {
......@@ -21,6 +22,7 @@ class OSExchangeData;
namespace ash {
class SplitViewDragIndicators;
class TabletModeBrowserWindowDragSessionWindowsHider;
// Provides special handling for Chrome tab drags on behalf of
// DragDropController. This must be created at the beginning of a tab drag and
......@@ -31,6 +33,9 @@ class ASH_EXPORT TabDragDropDelegate {
// (or simply returns false if the integration is disabled).
static bool IsChromeTabDrag(const ui::OSExchangeData& drag_data);
// Returns whether a tab from |window| is actively being dragged.
static bool IsSourceWindowForDrag(const aura::Window* window);
// |root_window| is the root window from which the drag originated. The drag
// is expected to stay in |root_window|. |source_window| is the Chrome window
// the tab was dragged from. |start_location_in_screen| is the location of
......@@ -54,11 +59,22 @@ class ASH_EXPORT TabDragDropDelegate {
const ui::OSExchangeData& drop_data);
private:
// Scales or transforms the source window if appropriate for this drag.
// |candidate_snap_position| is where the dragged tab will be snapped
// if dropped immediately.
void UpdateSourceWindowBoundsIfNecessary(
SplitViewController::SnapPosition candidate_snap_position);
// Puts the source window back into its original position.
void RestoreSourceWindowBounds();
aura::Window* const root_window_;
aura::Window* const source_window_;
const gfx::Point start_location_in_screen_;
std::unique_ptr<SplitViewDragIndicators> split_view_drag_indicators_;
std::unique_ptr<TabletModeBrowserWindowDragSessionWindowsHider>
windows_hider_;
};
} // namespace ash
......
......@@ -9,10 +9,12 @@
#include <vector>
#include "ash/public/cpp/ash_features.h"
#include "ash/scoped_animation_disabler.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test_shell_delegate.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "base/containers/flat_map.h"
......@@ -66,9 +68,17 @@ class TabDragDropDelegateTest : public AshTestBase {
mock_shell_delegate_ = mock_shell_delegate.get();
AshTestBase::SetUp(std::move(mock_shell_delegate));
ash::TabletModeControllerTestApi().EnterTabletMode();
// Create a dummy window and exit overview mode since drags can't be
// initiated from overview mode.
dummy_window_ = CreateToplevelTestWindow();
ASSERT_TRUE(Shell::Get()->overview_controller()->EndOverview());
}
void TearDown() override {
// Must be deleted before AshTestBase's tear down.
dummy_window_.reset();
// Clear our pointer before the object is destroyed.
mock_shell_delegate_ = nullptr;
AshTestBase::TearDown();
......@@ -79,6 +89,8 @@ class TabDragDropDelegateTest : public AshTestBase {
private:
base::test::ScopedFeatureList scoped_feature_list_;
NiceMock<MockShellDelegate>* mock_shell_delegate_ = nullptr;
std::unique_ptr<aura::Window> dummy_window_;
};
TEST_F(TabDragDropDelegateTest, ForwardsDragCheckToShellDelegate) {
......@@ -91,16 +103,15 @@ TEST_F(TabDragDropDelegateTest, ForwardsDragCheckToShellDelegate) {
TEST_F(TabDragDropDelegateTest, DragToExistingTabStrip) {
// Create a fake source window. Its details don't matter.
aura::Window* const source_window =
CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 1, 1));
std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
// A new window shouldn't be created in this case.
EXPECT_CALL(*mock_shell_delegate(), CreateBrowserForTabDrop(_, _)).Times(0);
// Emulate a drag session whose drop target accepts the drop. In this
// case, TabDragDropDelegate::Drop() is not called.
TabDragDropDelegate delegate(Shell::GetPrimaryRootWindow(), source_window,
gfx::Point(0, 0));
TabDragDropDelegate delegate(Shell::GetPrimaryRootWindow(),
source_window.get(), gfx::Point(0, 0));
delegate.DragUpdate(gfx::Point(1, 0));
delegate.DragUpdate(gfx::Point(2, 0));
......@@ -143,6 +154,11 @@ TEST_F(TabDragDropDelegateTest, DropOnEdgeEntersSplitView) {
// since we're in tablet mode.
std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
// We want to avoid entering overview mode between the delegate.Drop()
// call and |new_window|'s destruction. So we define it here before
// creating it.
std::unique_ptr<aura::Window> new_window;
// Emulate a drag to the right edge of the screen.
const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
const gfx::Point drag_end_location =
......@@ -155,7 +171,7 @@ TEST_F(TabDragDropDelegateTest, DropOnEdgeEntersSplitView) {
delegate.DragUpdate(drag_start_location);
delegate.DragUpdate(drag_end_location);
std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
new_window = CreateToplevelTestWindow();
EXPECT_CALL(*mock_shell_delegate(),
CreateBrowserForTabDrop(source_window.get(), _))
.Times(1)
......@@ -172,4 +188,83 @@ TEST_F(TabDragDropDelegateTest, DropOnEdgeEntersSplitView) {
SplitViewController::SnapPosition::LEFT));
}
TEST_F(TabDragDropDelegateTest, SourceWindowBoundsUpdatedWhileDragging) {
// Create the source window. This should automatically fill the work area
// since we're in tablet mode.
std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
const gfx::Rect original_bounds = source_window->bounds();
// Drag a few pixels away to trigger window scaling, then to the
// screen edge to visually snap the source window.
const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
const gfx::Point drag_mid_location =
drag_start_location + gfx::Vector2d(10, 0);
const gfx::Point drag_end_location =
screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
source_window.get())
.left_center();
{
TabDragDropDelegate delegate(Shell::GetPrimaryRootWindow(),
source_window.get(), drag_start_location);
delegate.DragUpdate(drag_start_location);
delegate.DragUpdate(drag_mid_location);
// |source_window| should be shrunk in all directions
EXPECT_GT(source_window->bounds().x(), original_bounds.x());
EXPECT_GT(source_window->bounds().y(), original_bounds.y());
EXPECT_LT(source_window->bounds().right(), original_bounds.right());
EXPECT_LT(source_window->bounds().bottom(), original_bounds.bottom());
delegate.DragUpdate(drag_end_location);
// |source_window| should appear in the snapped position, but not
// actually be snapped.
SplitViewController* const split_view_controller =
SplitViewController::Get(source_window.get());
EXPECT_EQ(
source_window->bounds(),
split_view_controller->GetSnappedWindowBoundsInParent(
SplitViewController::SnapPosition::RIGHT, source_window.get()));
EXPECT_FALSE(split_view_controller->InSplitViewMode());
}
// The original bounds should be restored.
EXPECT_EQ(source_window->bounds(), original_bounds);
}
TEST_F(TabDragDropDelegateTest, SnappedSourceWindowNotMoved) {
// Create the source window. This should automatically fill the work area
// since we're in tablet mode.
std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
SplitViewController* const split_view_controller =
SplitViewController::Get(source_window.get());
SplitViewController::SnapPosition const snap_position =
SplitViewController::SnapPosition::LEFT;
split_view_controller->SnapWindow(source_window.get(), snap_position);
const gfx::Rect original_bounds = source_window->bounds();
const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
const gfx::Point drag_end_location =
drag_start_location + gfx::Vector2d(10, 0);
{
TabDragDropDelegate delegate(Shell::GetPrimaryRootWindow(),
source_window.get(), drag_start_location);
delegate.DragUpdate(drag_start_location);
delegate.DragUpdate(drag_end_location);
// |source_window| should remain snapped and it's bounds should not change.
EXPECT_EQ(source_window.get(),
split_view_controller->GetSnappedWindow(snap_position));
EXPECT_EQ(original_bounds, source_window->bounds());
}
// Everything should still be the same after the drag ends.
EXPECT_EQ(source_window.get(),
split_view_controller->GetSnappedWindow(snap_position));
EXPECT_EQ(original_bounds, source_window->bounds());
}
} // namespace ash
......@@ -7,19 +7,9 @@
#include <vector>
#include "ash/display/screen_orientation_controller.h"
#include "ash/home_screen/home_screen_controller.h"
#include "ash/public/cpp/wallpaper_types.h"
#include "ash/public/cpp/window_backdrop.h"
#include "ash/root_window_controller.h"
#include "ash/scoped_animation_disabler.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_view.h"
#include "ash/wallpaper/wallpaper_widget_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_constants.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/splitview/split_view_constants.h"
#include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_session_windows_hider.h"
#include "ash/wm/tablet_mode/tablet_mode_window_state.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
......@@ -109,112 +99,6 @@ class SourceWindowAnimationObserver : public ui::ImplicitAnimationObserver,
} // namespace
// WindowsHider hides all visible windows except the currently dragged window
// and the dragged window's source window upon its creation, and restores the
// windows' visibility upon its destruction. It also blurs and darkens the
// background, hides the home launcher if home launcher is enabled. Only need to
// do so if we need to scale up and down the source window when dragging a tab
// window out of it.
class TabletModeBrowserWindowDragDelegate::WindowsHider
: public aura::WindowObserver {
public:
explicit WindowsHider(aura::Window* dragged_window)
: dragged_window_(dragged_window) {
DCHECK(dragged_window);
aura::Window* source_window =
dragged_window->GetProperty(kTabDraggingSourceWindowKey);
DCHECK(source_window);
// Disable the backdrop for |source_window| during dragging.
WindowBackdrop::Get(source_window)->DisableBackdrop();
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
aura::Window* root_window = dragged_window->GetRootWindow();
std::vector<aura::Window*> windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
for (aura::Window* window : windows) {
if (window == dragged_window || window == source_window ||
window->GetRootWindow() != root_window) {
continue;
}
window_visibility_map_.emplace(window, window->IsVisible());
if (window->IsVisible()) {
ScopedAnimationDisabler disabler(window);
window->Hide();
}
window->AddObserver(this);
}
// Hide the home launcher if it's enabled during dragging.
Shell::Get()->home_screen_controller()->OnWindowDragStarted();
// Blurs the wallpaper background.
RootWindowController::ForWindow(root_window)
->wallpaper_widget_controller()
->SetWallpaperProperty(wallpaper_constants::kOverviewState);
}
~WindowsHider() override {
// It might be possible that |source_window| is destroyed during dragging.
aura::Window* source_window =
dragged_window_->GetProperty(kTabDraggingSourceWindowKey);
if (source_window)
WindowBackdrop::Get(source_window)->RestoreBackdrop();
for (auto iter = window_visibility_map_.begin();
iter != window_visibility_map_.end(); ++iter) {
iter->first->RemoveObserver(this);
if (iter->second) {
ScopedAnimationDisabler disabler(iter->first);
iter->first->Show();
}
}
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
// May reshow the home launcher after dragging.
Shell::Get()->home_screen_controller()->OnWindowDragEnded(
/*animate=*/false);
// Clears the background wallpaper blur.
RootWindowController::ForWindow(dragged_window_->GetRootWindow())
->wallpaper_widget_controller()
->SetWallpaperProperty(wallpaper_constants::kClear);
}
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override {
window->RemoveObserver(this);
window_visibility_map_.erase(window);
}
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
if (visible) {
// Do not let |window| change to visible during the lifetime of |this|.
// Also update |window_visibility_map_| so that we can restore the window
// visibility correctly.
window->Hide();
window_visibility_map_[window] = visible;
}
// else do nothing. It must come from Hide() function above thus should be
// ignored.
}
private:
// The currently dragged window. Guaranteed to be non-nullptr during the
// lifetime of |this|.
aura::Window* dragged_window_;
// Maintains the map between windows and their visibilities. All windows
// except the dragged window and the source window should stay hidden during
// dragging.
std::map<aura::Window*, bool> window_visibility_map_;
DISALLOW_COPY_AND_ASSIGN(WindowsHider);
};
TabletModeBrowserWindowDragDelegate::TabletModeBrowserWindowDragDelegate() =
default;
......@@ -279,7 +163,9 @@ void TabletModeBrowserWindowDragDelegate::UpdateSourceWindow(
// Only create WindowHider if we need to scale up/down the source window.
if (!windows_hider_)
windows_hider_ = std::make_unique<WindowsHider>(dragged_window_);
windows_hider_ =
std::make_unique<TabletModeBrowserWindowDragSessionWindowsHider>(
source_window, dragged_window_);
const gfx::Rect work_area_bounds =
display::Screen::GetScreen()
......
......@@ -11,6 +11,8 @@
namespace ash {
class TabletModeBrowserWindowDragSessionWindowsHider;
// 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 other windows below the
......@@ -22,8 +24,6 @@ class ASH_EXPORT TabletModeBrowserWindowDragDelegate
~TabletModeBrowserWindowDragDelegate() override;
private:
class WindowsHider;
// TabletModeWindowDragDelegate:
void PrepareWindowDrag(const gfx::PointF& location_in_screen) override;
void UpdateWindowDrag(const gfx::PointF& location_in_screen) override;
......@@ -52,7 +52,8 @@ class ASH_EXPORT TabletModeBrowserWindowDragDelegate
// hides the home launcher if home launcher is enabled, blurs and darkens the
// background upon its creation. All of these will be restored upon its
// destruction.
std::unique_ptr<WindowsHider> windows_hider_;
std::unique_ptr<TabletModeBrowserWindowDragSessionWindowsHider>
windows_hider_;
// The observer to observe the source window's bounds change animation during
// dragging. It's used to prevent the dragged window to merge back into the
......
// Copyright 2020 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_session_windows_hider.h"
#include <vector>
#include "ash/home_screen/home_screen_controller.h"
#include "ash/public/cpp/window_backdrop.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/scoped_animation_disabler.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_view.h"
#include "ash/wallpaper/wallpaper_widget_controller.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_controller.h"
#include "ui/aura/window.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
namespace ash {
TabletModeBrowserWindowDragSessionWindowsHider::
TabletModeBrowserWindowDragSessionWindowsHider(aura::Window* source_window,
aura::Window* dragged_window)
: source_window_(source_window), dragged_window_(dragged_window) {
DCHECK(source_window_);
if (dragged_window_) {
DCHECK_EQ(source_window_,
dragged_window_->GetProperty(kTabDraggingSourceWindowKey));
}
root_window_ = source_window_->GetRootWindow();
// Disable the backdrop for |source_window_| during dragging.
WindowBackdrop::Get(source_window_)->DisableBackdrop();
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
std::vector<aura::Window*> windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
for (aura::Window* window : windows) {
if (window == dragged_window_ || window == source_window_ ||
window->GetRootWindow() != root_window_) {
continue;
}
window_visibility_map_.emplace(window, window->IsVisible());
if (window->IsVisible()) {
ScopedAnimationDisabler disabler(window);
window->Hide();
}
window->AddObserver(this);
}
// Hide the home launcher if it's enabled during dragging.
Shell::Get()->home_screen_controller()->OnWindowDragStarted();
// Blurs the wallpaper background.
RootWindowController::ForWindow(root_window_)
->wallpaper_widget_controller()
->SetWallpaperProperty(wallpaper_constants::kOverviewState);
}
TabletModeBrowserWindowDragSessionWindowsHider::
~TabletModeBrowserWindowDragSessionWindowsHider() {
// It might be possible that |source_window_| is destroyed during dragging.
if (source_window_)
WindowBackdrop::Get(source_window_)->RestoreBackdrop();
for (auto iter = window_visibility_map_.begin();
iter != window_visibility_map_.end(); ++iter) {
iter->first->RemoveObserver(this);
if (iter->second) {
ScopedAnimationDisabler disabler(iter->first);
iter->first->Show();
}
}
DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
// May reshow the home launcher after dragging.
Shell::Get()->home_screen_controller()->OnWindowDragEnded(
/*animate=*/false);
// Clears the background wallpaper blur.
RootWindowController::ForWindow(root_window_)
->wallpaper_widget_controller()
->SetWallpaperProperty(wallpaper_constants::kClear);
}
void TabletModeBrowserWindowDragSessionWindowsHider::OnWindowDestroying(
aura::Window* window) {
if (window == source_window_) {
source_window_ = nullptr;
return;
}
window->RemoveObserver(this);
window_visibility_map_.erase(window);
}
void TabletModeBrowserWindowDragSessionWindowsHider::OnWindowVisibilityChanged(
aura::Window* window,
bool visible) {
if (window == source_window_)
return;
if (visible) {
// Do not let |window| change to visible during the lifetime of |this|.
// Also update |window_visibility_map_| so that we can restore the window
// visibility correctly.
window->Hide();
window_visibility_map_[window] = visible;
}
// else do nothing. It must come from Hide() function above thus should be
// ignored.
}
} // namespace ash
// Copyright 2020 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_SESSION_WINDOWS_HIDER_H_
#define ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_SESSION_WINDOWS_HIDER_H_
#include <map>
#include "base/macros.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
namespace ash {
// Hides all visible windows except the source window and the dragged
// window (if applicable), and restores the windows' visibility upon its
// destruction. It also blurs and darkens the background, hides the home
// launcher if home launcher is enabled. Only need to do so if we need
// to scale up and down the source window when dragging a tab window out
// of it.
class TabletModeBrowserWindowDragSessionWindowsHider
: public aura::WindowObserver {
public:
TabletModeBrowserWindowDragSessionWindowsHider(aura::Window* source_window,
aura::Window* dragged_window);
~TabletModeBrowserWindowDragSessionWindowsHider() override;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
private:
// The window from which the drag originated.
aura::Window* source_window_;
// The currently dragged window, if applicable.
aura::Window* dragged_window_;
// The root window the drag is taking place within. Guaranteed to be
// non-null during the lifetime of |this|.
aura::Window* root_window_;
// Maintains the map between windows and their visibilities. All windows
// except the dragged window and the source window should stay hidden during
// dragging.
std::map<aura::Window*, bool> window_visibility_map_;
DISALLOW_COPY_AND_ASSIGN(TabletModeBrowserWindowDragSessionWindowsHider);
};
} // namespace ash
#endif // ASH_WM_TABLET_MODE_TABLET_MODE_BROWSER_WINDOW_DRAG_SESSION_WINDOWS_HIDER_H_
......@@ -6,6 +6,7 @@
#include <utility>
#include "ash/drag_drop/tab_drag_drop_delegate.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_animation_types.h"
......@@ -327,7 +328,8 @@ void TabletModeWindowState::OnWMEvent(WindowState* window_state,
return;
if (window_util::IsDraggingTabs(window_state->window()) ||
IsTabDraggingSourceWindow(window_state->window())) {
IsTabDraggingSourceWindow(window_state->window()) ||
TabDragDropDelegate::IsSourceWindowForDrag(window_state->window())) {
// If the window is the current tab-dragged window or the current tab-
// dragged window's source window, we may need to update its bounds
// during dragging.
......
......@@ -4,7 +4,6 @@
#include "components/exo/drag_drop_operation.h"
#include "ash/drag_drop/drag_drop_controller.h"
#include "base/barrier_closure.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/exo/data_offer.h"
......@@ -19,6 +18,10 @@
#include "ui/display/screen.h"
#include "ui/gfx/transform_util.h"
#if defined(OS_CHROMEOS)
#include "ash/drag_drop/drag_drop_controller.h"
#endif // defined(OS_CHROMEOS)
namespace exo {
namespace {
......
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