Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Unified Diff: chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc

Issue 1877043003: [EXPERIMENT] MacViews: Implement Tab Dragging Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git cl format Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index d4fc18e80b3eac8c62d1b5ee9b9f17abc9f7f52e..8dd8c709df56a3d987398c19c0ad049dfd63c789 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
@@ -172,6 +173,12 @@ void TabDragControllerTest::AddTabAndResetBrowser(Browser* browser) {
AddBlankTabAndShow(browser);
StopAnimating(GetTabStripForBrowser(browser));
ResetIDs(browser->tab_strip_model(), 0);
+#if defined(OS_MACOSX)
+ // Currently MacViews' browser windows are shown in the background anc could
+ // be obscured by other windows if there are any. This should be fixed in
+ // order to be consistent with other platforms.
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser));
+#endif // OS_MACOSX
}
Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
@@ -182,7 +189,8 @@ Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
// Resize the two windows so they're right next to each other.
gfx::Rect work_area =
gfx::Screen::GetScreen()
- ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow())
+ ->GetDisplayNearestWindow(platform_util::GetViewForWindow(
+ browser()->window()->GetNativeWindow()))
.work_area();
gfx::Size half_size =
gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10);
@@ -250,7 +258,7 @@ class ScreenEventGeneratorDelegate
#endif
-#if !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS) && defined(USE_AURA)
// Following classes verify a crash scenario. Specifically on Windows when focus
// changes it can trigger capture being lost. This was causing a crash in tab
@@ -373,6 +381,9 @@ class DetachToBrowserTabDragControllerTest
event_generator_.reset(
new ui::test::EventGenerator(ash::Shell::GetPrimaryRootWindow()));
#endif
+#if defined(OS_MACOSX)
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+#endif
}
InputSource input_source() const {
@@ -863,7 +874,8 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
// Resize the browser window so that it is as big as the work area.
gfx::Rect work_area =
gfx::Screen::GetScreen()
- ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow())
+ ->GetDisplayNearestWindow(platform_util::GetViewForWindow(
+ browser()->window()->GetNativeWindow()))
.work_area();
browser()->window()->SetBounds(work_area);
const gfx::Rect initial_bounds(browser()->window()->GetBounds());
@@ -1223,6 +1235,7 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) {
TabStrip* tab_strip = GetTabStripForBrowser(browser());
browser()->tab_strip_model()->AddTabAtToSelection(0);
browser()->tab_strip_model()->AddTabAtToSelection(1);
+ const gfx::Rect initial_bounds = browser()->window()->GetBounds();
// Move to the first tab and drag it enough so that it would normally
// detach.
@@ -1246,8 +1259,193 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) {
// Remaining browser window should not be maximized
EXPECT_FALSE(browser()->window()->IsMaximized());
+
+ const gfx::Rect final_bounds = browser()->window()->GetBounds();
+ EXPECT_EQ(initial_bounds.size(), final_bounds.size());
+ EXPECT_EQ(initial_bounds.origin().x(), final_bounds.origin().x());
+ EXPECT_EQ(initial_bounds.origin().y() + GetDetachY(tab_strip),
+ final_bounds.origin().y());
+}
+
+#if defined(OS_MACOSX)
+// Makes sure we can drag the window using WindowServer by dragging on a tab.
+//
+// All other tests move the windows without relying on the WindowServer, because
+// BridgedNativeWidget::RunMoveLoop() immediately offsets the window on first
+// mouse drag. If we generate more mouse move events after that, it's presumed
+// that the WindowServer will move the window. In order for that to work we need
+// to generate global CGEvents instead of app-specific NSEvents, that's what
+// ui_test_utils::DragAndDrop() is for.
+//
+// If the WindowServer fails to move the window, the final window bounds won't
+// match the expected ones.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+ MacDragsWindowUsingCocoaMoveLoop) {
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+ browser()->tab_strip_model()->AddTabAtToSelection(0);
+ browser()->tab_strip_model()->AddTabAtToSelection(1);
+ const gfx::Rect initial_bounds = browser()->window()->GetBounds();
+
+ // Move to the first tab and drag it enough so that it would normally
+ // detach.
+ gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+
+ // If we don't make the interactive_ui_tests the active application, we won't
+ // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
+ // will deadlock.
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+
+ // We need to move the window using multiple intermediate events in order
+ // to verify that CocoaWindowMoveLoop is working correctly.
+ const int steps = 10;
+ ui_test_utils::DragAndDrop(
+ tab_0_center,
+ gfx::Point(tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip)),
+ steps);
+
+ // Should not be dragging.
+ EXPECT_FALSE(tab_strip->IsDragSessionActive());
+ EXPECT_FALSE(TabDragController::IsActive());
+ EXPECT_FALSE(GetIsDragged(browser()));
+
+ // And there should only be one window.
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+
+ // Remaining browser window should not be maximized
+ EXPECT_FALSE(browser()->window()->IsMaximized());
+
+ const gfx::Rect final_bounds = browser()->window()->GetBounds();
+ EXPECT_EQ(initial_bounds.size(), final_bounds.size());
+ EXPECT_EQ(initial_bounds.origin().x(), final_bounds.origin().x());
+ EXPECT_EQ(initial_bounds.origin().y() + GetDetachY(tab_strip),
+ final_bounds.origin().y());
}
+// Tests that when the first mouse event that starts RunMoveLoop does not
+// overlap the Mac menu bar. BridgedNativeWidget::RunMoveLoop() shifts both the
+// mouse position and the expected window frame after detachment.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+ MacDetachesWindowOnTopOfMacMenuBar) {
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+
+ // Make sure there's enough space to trigger detachment.
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+ browser()->window()->SetBounds(gfx::Rect(100, 100, 400, 200));
+ DCHECK_GT(browser()->window()->GetBounds().y(), GetDetachY(tab_strip));
+
+ // If we don't make the interactive_ui_tests the active application, we won't
+ // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
+ // will deadlock.
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+
+ gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+ gfx::Point on_top_of_menu_bar(tab_0_center.x(), 0);
+ ui_test_utils::DragAndDrop(tab_0_center, on_top_of_menu_bar);
+
+ // Should not be dragging.
+ EXPECT_FALSE(tab_strip->IsDragSessionActive());
+ EXPECT_FALSE(TabDragController::IsActive());
+ EXPECT_FALSE(GetIsDragged(browser()));
+
+ // Second tab should successfully detach.
+ EXPECT_EQ(2u, browser_list->size());
+ EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
+}
+
+// Detaches and reattaches second tab. Will fail if detached window is not moved
+// synchronously at the start of BridgedNativeWidget::RunMoveLoop(): the check
+// for expected WindowServerFrame() will fail.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+ MacDetachesAndReattachesSecondTab) {
+ using ui_test_utils::DragAndDropOperation;
+
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+ browser()->window()->SetBounds(gfx::Rect(100, 100, 400, 200));
+ const gfx::Rect initial_bounds = browser()->window()->GetBounds();
+
+ gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1)));
+ gfx::Point tab_1_shake(tab_1_center.x(),
+ tab_1_center.y() + GetDetachY(tab_strip) * 2);
+
+ // If we don't make the interactive_ui_tests the active application, we won't
+ // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
+ // will deadlock.
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+
+ std::list<DragAndDropOperation> operations;
+ operations.emplace_back(DragAndDropOperation::Move(tab_1_center));
+ operations.emplace_back(DragAndDropOperation::MouseDown());
+ operations.emplace_back(DragAndDropOperation::Move(tab_1_shake));
+ operations.emplace_back(DragAndDropOperation::Move(tab_1_center));
+ operations.emplace_back(DragAndDropOperation::MouseUp());
+
+ ui_test_utils::DragAndDrop(operations);
+
+ // Should not be dragging.
+ EXPECT_FALSE(tab_strip->IsDragSessionActive());
+ EXPECT_FALSE(TabDragController::IsActive());
+ EXPECT_FALSE(GetIsDragged(browser()));
+
+ // And there should only be one window.
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+
+ // The window should remain in its original place.
+ const gfx::Rect final_bounds = browser()->window()->GetBounds();
+ EXPECT_EQ(initial_bounds, final_bounds);
+}
+
+// Tests that when the first mouse event that starts RunMoveLoop does not
+// overlap the Mac menu bar. BridgedNativeWidget::RunMoveLoop() shifts both the
+// mouse position and the expected window frame after detachment.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+ MacDetachesWindowAtTopOfScreen) {
+ using ui_test_utils::DragAndDropOperation;
+
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+
+ // Make sure there's enough space to trigger detachment.
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+ browser()->window()->SetBounds(gfx::Rect(2500, 200, 400, 200));
+ DCHECK_GT(browser()->window()->GetBounds().y(), GetDetachY(tab_strip));
+
+ gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+ gfx::Point at_top_of_screen(tab_0_center.x(), 0);
+ gfx::Point below_top_of_screen(tab_0_center.x(), 100);
+
+ std::list<DragAndDropOperation> operations;
+ operations.push_back(DragAndDropOperation::Move(tab_0_center));
+ operations.push_back(DragAndDropOperation::MouseDown());
+ operations.push_back(DragAndDropOperation::Move(at_top_of_screen));
+ operations.push_back(DragAndDropOperation::Move(below_top_of_screen));
+ operations.push_back(DragAndDropOperation::MouseUp());
+ ui_test_utils::DragAndDrop(operations);
+
+ // Should not be dragging.
+ EXPECT_FALSE(tab_strip->IsDragSessionActive());
+ EXPECT_FALSE(TabDragController::IsActive());
+ EXPECT_FALSE(GetIsDragged(browser()));
+
+ // Second tab should successfully detach.
+ EXPECT_EQ(2u, browser_list->size());
+ EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
+
+ Browser* browser2 = browser_list->get(1);
+ EXPECT_EQ(browser2->window()->GetBounds().size(),
+ browser()->window()->GetBounds().size());
+}
+
+#endif // OS_MACOSX
+
namespace {
// Invoked from the nested message loop.
@@ -1476,6 +1674,8 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
const gfx::Rect initial_bounds(browser2->window()->GetBounds());
+ EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+
// Move to the first tab and drag it enough so that it detaches, but not
// enough that it attaches to browser2.
gfx::Point tab_0_center(
@@ -1523,12 +1723,8 @@ void CancelOnNewTabWhenDraggingStep2(
// Add another tab. This should trigger exiting the nested loop. Add at the
// to exercise past crash when model/tabstrip got out of sync (474082).
- content::WindowedNotificationObserver observer(
- content::NOTIFICATION_LOAD_STOP,
- content::NotificationService::AllSources());
chrome::AddTabAt(browser_list->GetLastActive(), GURL(url::kAboutBlankURL),
0, false);
- observer.Wait();
}
} // namespace
@@ -1553,10 +1749,18 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
gfx::Point tab_0_center(
GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
ASSERT_TRUE(PressInput(tab_0_center));
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
ASSERT_TRUE(DragInputToNotifyWhenDone(
tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
base::Bind(&CancelOnNewTabWhenDraggingStep2, this, browser_list)));
- QuitWhenNotDragging();
+ observer.Wait();
+
+ // On MacViews the Drag ends while waiting for NOTIFICATION_LOAD_STOP.
+ if (TabDragController::IsActive()) {
+ QuitWhenNotDragging();
+ }
// Should be two windows and not dragging.
ASSERT_FALSE(TabDragController::IsActive());
@@ -2142,6 +2346,7 @@ class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
}
void QuitWhenNotDragging() {
+ DCHECK(TabDragController::IsActive());
test::QuitWhenNotDraggingImpl();
base::MessageLoop::current()->Run();
}
« no previous file with comments | « chrome/browser/ui/views/tabs/tab_drag_controller.cc ('k') | chrome/browser/ui/views/tabs/window_finder_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698