123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- // 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/drag_drop/tab_drag_drop_delegate.h"
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "ash/constants/ash_features.h"
- #include "ash/public/cpp/test/test_new_window_delegate.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"
- #include "base/pickle.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/gmock_callback_support.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "base/test/scoped_feature_list.h"
- #include "testing/gmock/include/gmock/gmock.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.h"
- #include "ui/compositor/test/test_utils.h"
- #include "ui/events/test/event_generator.h"
- #include "ui/gfx/geometry/vector2d.h"
- using ::base::test::RunOnceCallback;
- using ::testing::_;
- using ::testing::NiceMock;
- using ::testing::Return;
- namespace ash {
- namespace {
- constexpr int kWebUITabStripHeight = 100;
- class MockShellDelegate : public TestShellDelegate {
- public:
- MockShellDelegate() = default;
- ~MockShellDelegate() override = default;
- MOCK_METHOD(bool, IsTabDrag, (const ui::OSExchangeData&), (override));
- int GetBrowserWebUITabStripHeight() override { return kWebUITabStripHeight; }
- };
- class MockNewWindowDelegate : public TestNewWindowDelegate {
- public:
- MockNewWindowDelegate() = default;
- ~MockNewWindowDelegate() override = default;
- MOCK_METHOD(void,
- NewWindowForDetachingTab,
- (aura::Window*,
- const ui::OSExchangeData&,
- NewWindowForDetachingTabCallback),
- (override));
- };
- } // namespace
- class TabDragDropDelegateTest : public AshTestBase {
- public:
- TabDragDropDelegateTest() {
- ash::features::SetWebUITabStripEnabled(true);
- scoped_feature_list_.InitAndEnableFeature(
- ash::features::kWebUITabStripTabDragIntegration);
- }
- // AshTestBase:
- void SetUp() override {
- auto mock_new_window_delegate =
- std::make_unique<NiceMock<MockNewWindowDelegate>>();
- mock_new_window_delegate_ptr_ = mock_new_window_delegate.get();
- test_new_window_delegate_provider_ =
- std::make_unique<TestNewWindowDelegateProvider>(
- std::move(mock_new_window_delegate));
- auto mock_shell_delegate = std::make_unique<NiceMock<MockShellDelegate>>();
- 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(ExitOverview());
- }
- 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;
- test_new_window_delegate_provider_.reset();
- AshTestBase::TearDown();
- }
- MockShellDelegate* mock_shell_delegate() { return mock_shell_delegate_; }
- MockNewWindowDelegate* mock_new_window_delegate() {
- return static_cast<MockNewWindowDelegate*>(
- NewWindowDelegate::GetInstance());
- }
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
- NiceMock<MockShellDelegate>* mock_shell_delegate_ = nullptr;
- std::unique_ptr<TestNewWindowDelegateProvider>
- test_new_window_delegate_provider_;
- NiceMock<MockNewWindowDelegate>* mock_new_window_delegate_ptr_ = nullptr;
- std::unique_ptr<aura::Window> dummy_window_;
- };
- TEST_F(TabDragDropDelegateTest, ForwardsDragCheckToShellDelegate) {
- ON_CALL(*mock_shell_delegate(), IsTabDrag(_)).WillByDefault(Return(false));
- EXPECT_FALSE(TabDragDropDelegate::IsChromeTabDrag(ui::OSExchangeData()));
- ON_CALL(*mock_shell_delegate(), IsTabDrag(_)).WillByDefault(Return(true));
- EXPECT_TRUE(TabDragDropDelegate::IsChromeTabDrag(ui::OSExchangeData()));
- }
- TEST_F(TabDragDropDelegateTest, DragToExistingTabStrip) {
- // Create a fake source window. Its details don't matter.
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- // A new window shouldn't be created in this case.
- EXPECT_CALL(*mock_new_window_delegate(), NewWindowForDetachingTab(_, _, _))
- .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.get(), gfx::Point(0, 0));
- delegate.DragUpdate(gfx::Point(1, 0));
- delegate.DragUpdate(gfx::Point(2, 0));
- // Let |delegate| be destroyed without a Drop() call.
- }
- TEST_F(TabDragDropDelegateTest, DragToNewWindow) {
- // 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();
- EXPECT_FALSE(
- SplitViewController::Get(source_window.get())->InTabletSplitViewMode());
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- // Emulate a drag session ending in a drop to a new window.
- auto delegate = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate->DragUpdate(drag_start_location);
- delegate->DragUpdate(drag_start_location + gfx::Vector2d(1, 0));
- delegate->DragUpdate(drag_start_location + gfx::Vector2d(2, 0));
- // Check that a new window is requested. Assume the correct drop data
- // is passed. Return the new window.
- std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate.release()->DropAndDeleteSelf(
- drag_start_location + gfx::Vector2d(2, 0), ui::OSExchangeData());
- EXPECT_FALSE(
- SplitViewController::Get(source_window.get())->InTabletSplitViewMode());
- }
- // When a tab is dragged to the left/right side of the Web Contents. It should
- // enter split view.
- TEST_F(TabDragDropDelegateTest, DropOnEdgeEntersSplitView) {
- // 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();
- // 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 =
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
- source_window.get())
- .right_center();
- auto delegate = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate->DragUpdate(drag_start_location);
- delegate->DragUpdate(drag_end_location);
- new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate.release()->DropAndDeleteSelf(drag_end_location,
- ui::OSExchangeData());
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- EXPECT_EQ(new_window.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::RIGHT));
- EXPECT_EQ(source_window.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::LEFT));
- }
- // When a tab is dragged to the left/right edge of the tab strip. It should not
- // enter split view.
- // https://crbug.com/1316070
- TEST_F(TabDragDropDelegateTest, DropOnEdgeShouldNotEnterSplitView) {
- // 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();
- // 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 tab strip. It should not enter
- // split view.
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- const gfx::Point drag_end_location =
- gfx::Point(source_window->bounds().right(), kWebUITabStripHeight * 0.5);
- auto delegate = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate->DragUpdate(drag_start_location);
- delegate->DragUpdate(drag_end_location);
- new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate.release()->DropAndDeleteSelf(drag_end_location,
- ui::OSExchangeData());
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- EXPECT_FALSE(split_view_controller->InTabletSplitViewMode());
- }
- TEST_F(TabDragDropDelegateTest, DropTabInSplitViewMode) {
- // Enter tablet split view mode by snap the source window to the left.
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- split_view_controller->SnapWindow(source_window.get(),
- SplitViewController::SnapPosition::LEFT);
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- // Snap another window to the right to make sure right split screen is not in
- // overview mode.
- std::unique_ptr<aura::Window> right_window = CreateToplevelTestWindow();
- split_view_controller->SnapWindow(right_window.get(),
- SplitViewController::SnapPosition::RIGHT);
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- auto area =
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
- source_window.get());
- // Emulate a drag to the right side of the screen.
- // |new_window1| should snap to the right split view.
- gfx::Point drag_end_location_right(area.width() * 0.8, area.height() * 0.5);
- auto delegate1 = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate1->DragUpdate(drag_start_location);
- delegate1->DragUpdate(drag_end_location_right);
- std::unique_ptr<aura::Window> new_window1 = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window1.get()));
- delegate1.release()->DropAndDeleteSelf(drag_end_location_right,
- ui::OSExchangeData());
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- EXPECT_EQ(new_window1.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::RIGHT));
- EXPECT_EQ(source_window.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::LEFT));
- new_window1.reset(); // Close |new_window1|.
- // Emulate a drag to the left side of the screen.
- // |new_window2| should snap to the left split view.
- // |source_window| should go into overview mode.
- gfx::Point drag_end_location_left(area.width() * 0.2, area.height() * 0.5);
- auto delegate2 = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate2->DragUpdate(drag_start_location);
- delegate2->DragUpdate(drag_end_location_left);
- std::unique_ptr<aura::Window> new_window2 = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window2.get()));
- delegate2.release()->DropAndDeleteSelf(drag_end_location_left,
- ui::OSExchangeData());
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- EXPECT_EQ(nullptr, split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::RIGHT));
- EXPECT_EQ(new_window2.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::LEFT));
- ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
- auto windows_list = Shell::Get()
- ->overview_controller()
- ->GetWindowsListInOverviewGridsForTest();
- EXPECT_NE(
- std::end(windows_list),
- std::find(windows_list.begin(), windows_list.end(), source_window.get()));
- }
- TEST_F(TabDragDropDelegateTest, DropTabToOverviewMode) {
- // Enter tablet split view mode by snap the source window to the left.
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- split_view_controller->SnapWindow(source_window.get(),
- SplitViewController::SnapPosition::LEFT);
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- auto area =
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
- source_window.get());
- // Emulate a drag to the right side of the screen.
- // |new_window1| should snap to overview mode.
- gfx::Point drag_end_location_right(area.width() * 0.8, area.height() * 0.5);
- auto delegate1 = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate1->DragUpdate(drag_start_location);
- delegate1->DragUpdate(drag_end_location_right);
- std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate1.release()->DropAndDeleteSelf(drag_end_location_right,
- ui::OSExchangeData());
- EXPECT_EQ(nullptr, split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::RIGHT));
- auto windows_list = Shell::Get()
- ->overview_controller()
- ->GetWindowsListInOverviewGridsForTest();
- EXPECT_NE(
- std::end(windows_list),
- std::find(windows_list.begin(), windows_list.end(), new_window.get()));
- }
- TEST_F(TabDragDropDelegateTest, WillNotDropTabToOverviewModeInSnappingZone) {
- // Enter tablet split view mode by snap the source window to the left.
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- split_view_controller->SnapWindow(source_window.get(),
- SplitViewController::SnapPosition::LEFT);
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- auto area =
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
- source_window.get());
- // Emulate a drag to the right snapping zone of the screen.
- // |new_window1| should not snap to overview mode.
- gfx::Point drag_end_location_right(area.width() * 0.95, area.height() * 0.5);
- auto delegate1 = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate1->DragUpdate(drag_start_location);
- delegate1->DragUpdate(drag_end_location_right);
- std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate1.release()->DropAndDeleteSelf(drag_end_location_right,
- ui::OSExchangeData());
- EXPECT_EQ(new_window.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::RIGHT));
- ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
- }
- TEST_F(TabDragDropDelegateTest, WillNotDropTabToOverviewMode) {
- // Enter tablet split view mode by snap the source window to the left.
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- SplitViewController* const split_view_controller =
- SplitViewController::Get(source_window.get());
- split_view_controller->SnapWindow(source_window.get(),
- SplitViewController::SnapPosition::LEFT);
- EXPECT_TRUE(split_view_controller->InTabletSplitViewMode());
- ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- auto area =
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
- source_window.get());
- // Emulate a drag to the left side of the screen.
- // |new_window1| should not snap to overview mode.
- gfx::Point drag_end_location_right(area.width() * 0.2, area.height() * 0.5);
- auto delegate1 = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate1->DragUpdate(drag_start_location);
- delegate1->DragUpdate(drag_end_location_right);
- std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate1.release()->DropAndDeleteSelf(drag_end_location_right,
- ui::OSExchangeData());
- EXPECT_EQ(new_window.get(), split_view_controller->GetSnappedWindow(
- SplitViewController::SnapPosition::LEFT));
- auto windows_list = Shell::Get()
- ->overview_controller()
- ->GetWindowsListInOverviewGridsForTest();
- EXPECT_EQ(
- std::end(windows_list),
- std::find(windows_list.begin(), windows_list.end(), new_window.get()));
- }
- 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());
- }
- // Make sure metrics is recorded during tab dragging in tablet mode with
- // webui tab strip enable.
- TEST_F(TabDragDropDelegateTest, TabDraggingHistogram) {
- base::HistogramTester histogram_tester;
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- EXPECT_FALSE(
- SplitViewController::Get(source_window.get())->InTabletSplitViewMode());
- const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
- // Emulate a drag session ending in a drop to a new window. This should
- // generate a histogram.
- auto delegate = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
- delegate->DragUpdate(drag_start_location + gfx::Vector2d(1, 0));
- EXPECT_TRUE(ui::WaitForNextFrameToBePresented(
- source_window->layer()->GetCompositor()));
- // Check that a new window is requested. Assume the correct drop data
- // is passed. Return the new window.
- std::unique_ptr<aura::Window> new_window = CreateToplevelTestWindow();
- EXPECT_CALL(*mock_new_window_delegate(),
- NewWindowForDetachingTab(source_window.get(), _, _))
- .Times(1)
- .WillOnce(RunOnceCallback<2>(new_window.get()));
- delegate.release()->DropAndDeleteSelf(
- drag_start_location + gfx::Vector2d(1, 0), ui::OSExchangeData());
- EXPECT_TRUE(ui::WaitForNextFrameToBePresented(
- source_window->layer()->GetCompositor()));
- EXPECT_FALSE(
- SplitViewController::Get(source_window.get())->InTabletSplitViewMode());
- histogram_tester.ExpectTotalCount("Ash.TabDrag.PresentationTime.TabletMode",
- 1);
- histogram_tester.ExpectTotalCount(
- "Ash.TabDrag.PresentationTime.MaxLatency.TabletMode", 1);
- }
- // There are edge cases where a dragging tab closes itself before being dropped.
- // In these cases new window will be nullptr and it
- // should be handled gracefully. https://crbug.com/1286203
- TEST_F(TabDragDropDelegateTest, DropWithoutNewWindow) {
- std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
- const gfx::Point drag_location = source_window->bounds().CenterPoint();
- auto delegate = std::make_unique<TabDragDropDelegate>(
- Shell::GetPrimaryRootWindow(), source_window.get(), drag_location);
- delegate->OnNewBrowserWindowCreated(drag_location, /*new_window=*/nullptr);
- }
- } // namespace ash
|