1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h"
9 #include "ash/wm/window_state.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_commands.h"
18 #include "chrome/browser/ui/browser_iterator.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/browser/ui/host_desktop.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/browser/ui/views/frame/browser_view.h"
23 #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h"
24 #include "chrome/browser/ui/views/tabs/tab.h"
25 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
26 #include "chrome/browser/ui/views/tabs/tab_strip.h"
27 #include "chrome/test/base/in_process_browser_test.h"
28 #include "chrome/test/base/interactive_test_utils.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "content/public/browser/notification_details.h"
31 #include "content/public/browser/notification_observer.h"
32 #include "content/public/browser/notification_service.h"
33 #include "content/public/browser/notification_source.h"
34 #include "content/public/browser/web_contents.h"
35 #include "ui/base/test/ui_controls.h"
36 #include "ui/gfx/screen.h"
37 #include "ui/views/view.h"
38 #include "ui/views/widget/widget.h"
40 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
41 #include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h"
42 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
46 #include "ash/display/display_controller.h"
47 #include "ash/display/display_manager.h"
48 #include "ash/shell.h"
49 #include "ash/test/cursor_manager_test_api.h"
50 #include "ash/wm/coordinate_conversion.h"
51 #include "ash/wm/window_util.h"
52 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
53 #include "ui/aura/client/screen_position_client.h"
54 #include "ui/aura/test/event_generator_delegate_aura.h"
55 #include "ui/aura/window_event_dispatcher.h"
56 #include "ui/events/test/event_generator.h"
59 using content::WebContents
;
65 const char kTabDragControllerInteractiveUITestUserDataKey
[] =
66 "TabDragControllerInteractiveUITestUserData";
68 class TabDragControllerInteractiveUITestUserData
69 : public base::SupportsUserData::Data
{
71 explicit TabDragControllerInteractiveUITestUserData(int id
) : id_(id
) {}
72 ~TabDragControllerInteractiveUITestUserData() override
{}
73 int id() { return id_
; }
81 class QuitDraggingObserver
: public content::NotificationObserver
{
83 QuitDraggingObserver() {
84 registrar_
.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE
,
85 content::NotificationService::AllSources());
88 void Observe(int type
,
89 const content::NotificationSource
& source
,
90 const content::NotificationDetails
& details
) override
{
91 DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE
, type
);
92 base::MessageLoopForUI::current()->Quit();
97 ~QuitDraggingObserver() override
{}
99 content::NotificationRegistrar registrar_
;
101 DISALLOW_COPY_AND_ASSIGN(QuitDraggingObserver
);
104 gfx::Point
GetCenterInScreenCoordinates(const views::View
* view
) {
105 gfx::Point
center(view
->width() / 2, view
->height() / 2);
106 views::View::ConvertPointToScreen(view
, ¢er
);
110 void SetID(WebContents
* web_contents
, int id
) {
111 web_contents
->SetUserData(&kTabDragControllerInteractiveUITestUserDataKey
,
112 new TabDragControllerInteractiveUITestUserData(id
));
115 void ResetIDs(TabStripModel
* model
, int start
) {
116 for (int i
= 0; i
< model
->count(); ++i
)
117 SetID(model
->GetWebContentsAt(i
), start
+ i
);
120 std::string
IDString(TabStripModel
* model
) {
122 for (int i
= 0; i
< model
->count(); ++i
) {
125 WebContents
* contents
= model
->GetWebContentsAt(i
);
126 TabDragControllerInteractiveUITestUserData
* user_data
=
127 static_cast<TabDragControllerInteractiveUITestUserData
*>(
128 contents
->GetUserData(
129 &kTabDragControllerInteractiveUITestUserDataKey
));
131 result
+= base::IntToString(user_data
->id());
138 // Creates a listener that quits the message loop when no longer dragging.
139 void QuitWhenNotDraggingImpl() {
140 new QuitDraggingObserver(); // QuitDraggingObserver deletes itself.
143 TabStrip
* GetTabStripForBrowser(Browser
* browser
) {
144 BrowserView
* browser_view
= BrowserView::GetBrowserViewForBrowser(browser
);
145 return static_cast<TabStrip
*>(browser_view
->tabstrip());
150 using test::GetCenterInScreenCoordinates
;
152 using test::ResetIDs
;
153 using test::IDString
;
154 using test::GetTabStripForBrowser
;
156 TabDragControllerTest::TabDragControllerTest()
157 : native_browser_list(BrowserList::GetInstance(
158 chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
161 TabDragControllerTest::~TabDragControllerTest() {
164 void TabDragControllerTest::StopAnimating(TabStrip
* tab_strip
) {
165 tab_strip
->StopAnimating(true);
168 void TabDragControllerTest::AddTabAndResetBrowser(Browser
* browser
) {
169 AddBlankTabAndShow(browser
);
170 StopAnimating(GetTabStripForBrowser(browser
));
171 ResetIDs(browser
->tab_strip_model(), 0);
174 Browser
* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
175 // Create another browser.
176 Browser
* browser2
= CreateBrowser(browser()->profile());
177 ResetIDs(browser2
->tab_strip_model(), 100);
179 // Resize the two windows so they're right next to each other.
180 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
181 browser()->window()->GetNativeWindow()).work_area();
182 gfx::Size half_size
=
183 gfx::Size(work_area
.width() / 3 - 10, work_area
.height() / 2 - 10);
184 browser()->window()->SetBounds(gfx::Rect(work_area
.origin(), half_size
));
185 browser2
->window()->SetBounds(gfx::Rect(
186 work_area
.x() + half_size
.width(), work_area
.y(),
187 half_size
.width(), half_size
.height()));
194 INPUT_SOURCE_MOUSE
= 0,
195 INPUT_SOURCE_TOUCH
= 1
198 int GetDetachY(TabStrip
* tab_strip
) {
199 return std::max(TabDragController::kTouchVerticalDetachMagnetism
,
200 TabDragController::kVerticalDetachMagnetism
) +
201 tab_strip
->height() + 1;
204 bool GetIsDragged(Browser
* browser
) {
205 #if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash)
208 return ash::wm::GetWindowState(browser
->window()->GetNativeWindow())->
215 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
216 class ScreenEventGeneratorDelegate
217 : public aura::test::EventGeneratorDelegateAura
{
219 explicit ScreenEventGeneratorDelegate(aura::Window
* root_window
)
220 : root_window_(root_window
) {}
221 ~ScreenEventGeneratorDelegate() override
{}
223 // EventGeneratorDelegateAura overrides:
224 aura::WindowTreeHost
* GetHostAt(const gfx::Point
& point
) const override
{
225 return root_window_
->GetHost();
228 aura::client::ScreenPositionClient
* GetScreenPositionClient(
229 const aura::Window
* window
) const override
{
230 return aura::client::GetScreenPositionClient(root_window_
);
234 aura::Window
* root_window_
;
236 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate
);
241 #if !defined(OS_CHROMEOS)
243 // Following classes verify a crash scenario. Specifically on Windows when focus
244 // changes it can trigger capture being lost. This was causing a crash in tab
245 // dragging as it wasn't set up to handle this scenario. These classes
246 // synthesize this scenario.
248 // Allows making ClearNativeFocus() invoke ReleaseCapture().
249 class TestDesktopBrowserFrameAura
: public DesktopBrowserFrameAura
{
251 TestDesktopBrowserFrameAura(
252 BrowserFrame
* browser_frame
,
253 BrowserView
* browser_view
)
254 : DesktopBrowserFrameAura(browser_frame
, browser_view
),
255 release_capture_(false) {}
256 ~TestDesktopBrowserFrameAura() override
{}
258 void ReleaseCaptureOnNextClear() {
259 release_capture_
= true;
262 void ClearNativeFocus() override
{
263 views::DesktopNativeWidgetAura::ClearNativeFocus();
264 if (release_capture_
) {
265 release_capture_
= false;
266 GetWidget()->ReleaseCapture();
271 // If true ReleaseCapture() is invoked in ClearNativeFocus().
272 bool release_capture_
;
274 DISALLOW_COPY_AND_ASSIGN(TestDesktopBrowserFrameAura
);
277 // Factory for creating a TestDesktopBrowserFrameAura.
278 class TestNativeBrowserFrameFactory
: public NativeBrowserFrameFactory
{
280 TestNativeBrowserFrameFactory() {}
281 ~TestNativeBrowserFrameFactory() override
{}
283 NativeBrowserFrame
* Create(BrowserFrame
* browser_frame
,
284 BrowserView
* browser_view
) override
{
285 return new TestDesktopBrowserFrameAura(browser_frame
, browser_view
);
289 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory
);
292 class TabDragCaptureLostTest
: public TabDragControllerTest
{
294 TabDragCaptureLostTest() {
295 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory
);
299 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest
);
302 // See description above for details.
303 IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest
, ReleaseCaptureOnDrag
) {
304 AddTabAndResetBrowser(browser());
306 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
307 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
308 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center
) &&
309 ui_test_utils::SendMouseEventsSync(
310 ui_controls::LEFT
, ui_controls::DOWN
));
311 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
312 TestDesktopBrowserFrameAura
* frame
=
313 static_cast<TestDesktopBrowserFrameAura
*>(
314 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()->
315 native_widget_private());
316 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus
317 // changes capture is released and the drag cancels.
318 frame
->ReleaseCaptureOnNextClear();
319 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center
));
320 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
323 IN_PROC_BROWSER_TEST_F(TabDragControllerTest
, GestureEndShouldEndDragTest
) {
324 AddTabAndResetBrowser(browser());
326 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
328 Tab
* tab1
= tab_strip
->tab_at(1);
329 gfx::Point
tab_1_center(tab1
->width() / 2, tab1
->height() / 2);
331 ui::GestureEvent
gesture_tap_down(
336 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
337 tab_strip
->MaybeStartDrag(tab1
, gesture_tap_down
,
338 tab_strip
->GetSelectionModel());
339 EXPECT_TRUE(TabDragController::IsActive());
341 ui::GestureEvent
gesture_end(tab_1_center
.x(),
345 ui::GestureEventDetails(ui::ET_GESTURE_END
));
346 tab_strip
->OnGestureEvent(&gesture_end
);
347 EXPECT_FALSE(TabDragController::IsActive());
348 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
353 class DetachToBrowserTabDragControllerTest
354 : public TabDragControllerTest
,
355 public ::testing::WithParamInterface
<const char*> {
357 DetachToBrowserTabDragControllerTest() {}
359 void SetUpOnMainThread() override
{
360 #if defined(OS_CHROMEOS)
361 event_generator_
.reset(
362 new ui::test::EventGenerator(ash::Shell::GetPrimaryRootWindow()));
366 InputSource
input_source() const {
367 return strstr(GetParam(), "mouse") ?
368 INPUT_SOURCE_MOUSE
: INPUT_SOURCE_TOUCH
;
371 // Set root window from a point in screen coordinates
372 void SetEventGeneratorRootWindow(const gfx::Point
& point
) {
373 if (input_source() == INPUT_SOURCE_MOUSE
)
375 #if defined(OS_CHROMEOS)
376 event_generator_
.reset(new ui::test::EventGenerator(
377 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point
))));
381 // The following methods update one of the mouse or touch input depending upon
383 bool PressInput(const gfx::Point
& location
) {
384 if (input_source() == INPUT_SOURCE_MOUSE
) {
385 return ui_test_utils::SendMouseMoveSync(location
) &&
386 ui_test_utils::SendMouseEventsSync(
387 ui_controls::LEFT
, ui_controls::DOWN
);
389 #if defined(OS_CHROMEOS)
390 event_generator_
->set_current_location(location
);
391 event_generator_
->PressTouch();
399 // Second touch input is only used for touch sequence tests.
400 EXPECT_EQ(INPUT_SOURCE_TOUCH
, input_source());
401 #if defined(OS_CHROMEOS)
402 event_generator_
->set_current_location(
403 event_generator_
->current_location());
404 event_generator_
->PressTouchId(1);
411 bool DragInputTo(const gfx::Point
& location
) {
412 if (input_source() == INPUT_SOURCE_MOUSE
)
413 return ui_test_utils::SendMouseMoveSync(location
);
414 #if defined(OS_CHROMEOS)
415 event_generator_
->MoveTouch(location
);
422 bool DragInputToAsync(const gfx::Point
& location
) {
423 if (input_source() == INPUT_SOURCE_MOUSE
)
424 return ui_controls::SendMouseMove(location
.x(), location
.y());
425 #if defined(OS_CHROMEOS)
426 event_generator_
->MoveTouch(location
);
433 bool DragInputToNotifyWhenDone(int x
,
435 const base::Closure
& task
) {
436 if (input_source() == INPUT_SOURCE_MOUSE
)
437 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
438 #if defined(OS_CHROMEOS)
439 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
440 event_generator_
->MoveTouch(gfx::Point(x
, y
));
447 bool DragInputToDelayedNotifyWhenDone(int x
,
449 const base::Closure
& task
,
450 base::TimeDelta delay
) {
451 if (input_source() == INPUT_SOURCE_MOUSE
)
452 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
453 #if defined(OS_CHROMEOS)
454 base::MessageLoop::current()->PostDelayedTask(FROM_HERE
, task
, delay
);
455 event_generator_
->MoveTouch(gfx::Point(x
, y
));
462 bool DragInput2ToNotifyWhenDone(int x
,
464 const base::Closure
& task
) {
465 if (input_source() == INPUT_SOURCE_MOUSE
)
466 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
467 #if defined(OS_CHROMEOS)
468 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
469 event_generator_
->MoveTouchId(gfx::Point(x
, y
), 1);
476 bool ReleaseInput() {
477 if (input_source() == INPUT_SOURCE_MOUSE
) {
478 return ui_test_utils::SendMouseEventsSync(
479 ui_controls::LEFT
, ui_controls::UP
);
481 #if defined(OS_CHROMEOS)
482 event_generator_
->ReleaseTouch();
489 bool ReleaseInput2() {
490 if (input_source() == INPUT_SOURCE_MOUSE
) {
491 return ui_test_utils::SendMouseEventsSync(
492 ui_controls::LEFT
, ui_controls::UP
);
494 #if defined(OS_CHROMEOS)
495 event_generator_
->ReleaseTouchId(1);
502 bool ReleaseMouseAsync() {
503 return input_source() == INPUT_SOURCE_MOUSE
&&
504 ui_controls::SendMouseEvents(ui_controls::LEFT
, ui_controls::UP
);
507 void QuitWhenNotDragging() {
508 if (input_source() == INPUT_SOURCE_MOUSE
) {
509 // Schedule observer to quit message loop when done dragging. This has to
510 // be async so the message loop can run.
511 test::QuitWhenNotDraggingImpl();
512 base::MessageLoop::current()->Run();
514 // Touch events are sync, so we know we're not in a drag session. But some
515 // tests rely on the browser fully closing, which is async. So, run all
517 base::RunLoop run_loop
;
518 run_loop
.RunUntilIdle();
522 void AddBlankTabAndShow(Browser
* browser
) {
523 InProcessBrowserTest::AddBlankTabAndShow(browser
);
526 Browser
* browser() const { return InProcessBrowserTest::browser(); }
529 #if defined(OS_CHROMEOS)
530 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
533 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest
);
536 // Creates a browser with two tabs, drags the second to the first.
537 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, DragInSameWindow
) {
538 // TODO(sky): this won't work with touch as it requires a long press.
539 if (input_source() == INPUT_SOURCE_TOUCH
) {
540 VLOG(1) << "Test is DISABLED for touch input.";
544 AddTabAndResetBrowser(browser());
546 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
547 TabStripModel
* model
= browser()->tab_strip_model();
549 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
550 ASSERT_TRUE(PressInput(tab_1_center
));
551 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
552 ASSERT_TRUE(DragInputTo(tab_0_center
));
553 ASSERT_TRUE(ReleaseInput());
554 EXPECT_EQ("1 0", IDString(model
));
555 EXPECT_FALSE(TabDragController::IsActive());
556 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
558 // The tab strip should no longer have capture because the drag was ended and
559 // mouse/touch was released.
560 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
565 // Invoked from the nested message loop.
566 void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
567 TabStrip
* not_attached_tab_strip
,
568 TabStrip
* target_tab_strip
) {
569 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
570 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
571 ASSERT_TRUE(TabDragController::IsActive());
573 // Drag to target_tab_strip. This should stop the nested loop from dragging
575 gfx::Point
target_point(target_tab_strip
->width() -1,
576 target_tab_strip
->height() / 2);
577 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
578 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
583 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
584 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
585 // compositor. crbug.com/331924
586 #define MAYBE_DragToSeparateWindow DISABLED_DragToSeparateWindow
588 #define MAYBE_DragToSeparateWindow DragToSeparateWindow
590 // Creates two browsers, drags from first into second.
591 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
592 MAYBE_DragToSeparateWindow
) {
593 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
595 // Add another tab to browser().
596 AddTabAndResetBrowser(browser());
598 // Create another browser.
599 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
600 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
602 // Move to the first tab and drag it enough so that it detaches, but not
603 // enough that it attaches to browser2.
604 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
605 ASSERT_TRUE(PressInput(tab_0_center
));
606 ASSERT_TRUE(DragInputToNotifyWhenDone(
607 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
608 base::Bind(&DragToSeparateWindowStep2
,
609 this, tab_strip
, tab_strip2
)));
610 QuitWhenNotDragging();
612 // Should now be attached to tab_strip2.
613 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
614 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
615 ASSERT_TRUE(TabDragController::IsActive());
616 EXPECT_FALSE(GetIsDragged(browser()));
618 // Release mouse or touch, stopping the drag session.
619 ASSERT_TRUE(ReleaseInput());
620 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
621 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
622 ASSERT_FALSE(TabDragController::IsActive());
623 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
624 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
625 EXPECT_FALSE(GetIsDragged(browser2
));
627 // Both windows should not be maximized
628 EXPECT_FALSE(browser()->window()->IsMaximized());
629 EXPECT_FALSE(browser2
->window()->IsMaximized());
631 // The tab strip should no longer have capture because the drag was ended and
632 // mouse/touch was released.
633 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
634 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
639 void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest
* test
) {
640 if (test
->input_source() == INPUT_SOURCE_TOUCH
)
641 ASSERT_TRUE(test
->ReleaseInput());
644 #if defined(OS_CHROMEOS)
645 bool IsWindowPositionManaged(aura::Window
* window
) {
646 return ash::wm::GetWindowState(window
)->window_position_managed();
648 bool HasUserChangedWindowPositionOrSize(aura::Window
* window
) {
649 return ash::wm::GetWindowState(window
)->bounds_changed_by_user();
652 bool IsWindowPositionManaged(gfx::NativeWindow window
) {
655 bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window
) {
662 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
663 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
664 // compositor. crbug.com/331924
665 #define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow
667 #define MAYBE_DetachToOwnWindow DetachToOwnWindow
669 // Drags from browser to separate window and releases mouse.
670 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
671 MAYBE_DetachToOwnWindow
) {
672 const gfx::Rect
initial_bounds(browser()->window()->GetBounds());
674 AddTabAndResetBrowser(browser());
675 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
677 // Move to the first tab and drag it enough so that it detaches.
678 gfx::Point
tab_0_center(
679 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
680 ASSERT_TRUE(PressInput(tab_0_center
));
681 ASSERT_TRUE(DragInputToNotifyWhenDone(
682 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
683 base::Bind(&DetachToOwnWindowStep2
, this)));
684 if (input_source() == INPUT_SOURCE_MOUSE
) {
685 ASSERT_TRUE(ReleaseMouseAsync());
686 QuitWhenNotDragging();
689 // Should no longer be dragging.
690 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
691 ASSERT_FALSE(TabDragController::IsActive());
693 // There should now be another browser.
694 ASSERT_EQ(2u, native_browser_list
->size());
695 Browser
* new_browser
= native_browser_list
->get(1);
696 ASSERT_TRUE(new_browser
->window()->IsActive());
697 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
698 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
700 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
701 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
703 // The bounds of the initial window should not have changed.
704 EXPECT_EQ(initial_bounds
.ToString(),
705 browser()->window()->GetBounds().ToString());
707 EXPECT_FALSE(GetIsDragged(browser()));
708 EXPECT_FALSE(GetIsDragged(new_browser
));
709 // After this both windows should still be manageable.
710 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
711 EXPECT_TRUE(IsWindowPositionManaged(
712 new_browser
->window()->GetNativeWindow()));
714 // Both windows should not be maximized
715 EXPECT_FALSE(browser()->window()->IsMaximized());
716 EXPECT_FALSE(new_browser
->window()->IsMaximized());
718 // The tab strip should no longer have capture because the drag was ended and
719 // mouse/touch was released.
720 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
721 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
724 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
725 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
726 // compositor. crbug.com/331924
727 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
728 DISABLED_DetachToOwnWindowFromMaximizedWindow
730 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
731 DetachToOwnWindowFromMaximizedWindow
733 // Drags from browser to a separate window and releases mouse.
734 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
735 MAYBE_DetachToOwnWindowFromMaximizedWindow
) {
736 // Maximize the initial browser window.
737 browser()->window()->Maximize();
738 ASSERT_TRUE(browser()->window()->IsMaximized());
741 AddTabAndResetBrowser(browser());
742 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
744 // Move to the first tab and drag it enough so that it detaches.
745 gfx::Point
tab_0_center(
746 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
747 ASSERT_TRUE(PressInput(tab_0_center
));
748 ASSERT_TRUE(DragInputToNotifyWhenDone(
749 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
750 base::Bind(&DetachToOwnWindowStep2
, this)));
751 if (input_source() == INPUT_SOURCE_MOUSE
) {
752 ASSERT_TRUE(ReleaseMouseAsync());
753 QuitWhenNotDragging();
756 // Should no longer be dragging.
757 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
758 ASSERT_FALSE(TabDragController::IsActive());
760 // There should now be another browser.
761 ASSERT_EQ(2u, native_browser_list
->size());
762 Browser
* new_browser
= native_browser_list
->get(1);
763 ASSERT_TRUE(new_browser
->window()->IsActive());
764 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
765 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
767 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
768 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
770 // The bounds of the initial window should not have changed.
771 EXPECT_TRUE(browser()->window()->IsMaximized());
773 EXPECT_FALSE(GetIsDragged(browser()));
774 EXPECT_FALSE(GetIsDragged(new_browser
));
775 // After this both windows should still be manageable.
776 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
777 EXPECT_TRUE(IsWindowPositionManaged(
778 new_browser
->window()->GetNativeWindow()));
780 // The new window should be maximized.
781 EXPECT_TRUE(new_browser
->window()->IsMaximized());
784 // Deletes a tab being dragged before the user moved enough to start a drag.
785 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
786 DeleteBeforeStartedDragging
) {
788 AddTabAndResetBrowser(browser());
789 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
791 // Click on the first tab, but don't move it.
792 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
793 ASSERT_TRUE(PressInput(tab_0_center
));
795 // Should be dragging.
796 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
797 ASSERT_TRUE(TabDragController::IsActive());
799 // Delete the tab being dragged.
800 delete browser()->tab_strip_model()->GetWebContentsAt(0);
802 // Should have canceled dragging.
803 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
804 ASSERT_FALSE(TabDragController::IsActive());
806 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
807 EXPECT_FALSE(GetIsDragged(browser()));
810 #if defined(OS_CHROMEOS)
811 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
812 // compositor. crbug.com/331924
813 #define MAYBE_DeleteTabWhileAttached DISABLED_DeleteTabWhileAttached
815 #define MAYBE_DeleteTabWhileAttached DeleteTabWhileAttached
817 // Deletes a tab being dragged while still attached.
818 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
819 MAYBE_DeleteTabWhileAttached
) {
820 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
821 // compositor. crbug.com/331924
822 if (input_source() == INPUT_SOURCE_MOUSE
) {
823 VLOG(1) << "Test is DISABLED for mouse input.";
828 AddTabAndResetBrowser(browser());
829 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
831 // Click on the first tab and move it enough so that it starts dragging but is
833 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
834 ASSERT_TRUE(PressInput(tab_0_center
));
835 ASSERT_TRUE(DragInputTo(
836 gfx::Point(tab_0_center
.x() + 20, tab_0_center
.y())));
838 // Should be dragging.
839 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
840 ASSERT_TRUE(TabDragController::IsActive());
842 // Delete the tab being dragged.
843 delete browser()->tab_strip_model()->GetWebContentsAt(0);
845 // Should have canceled dragging.
846 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
847 ASSERT_FALSE(TabDragController::IsActive());
849 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
851 EXPECT_FALSE(GetIsDragged(browser()));
856 void DeleteWhileDetachedStep2(WebContents
* tab
) {
862 #if defined(OS_CHROMEOS)
863 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
864 // compositor. crbug.com/331924
865 #define MAYBE_DeleteTabWhileDetached DISABLED_DeleteTabWhileDetached
867 #define MAYBE_DeleteTabWhileDetached DeleteTabWhileDetached
869 // Deletes a tab being dragged after dragging a tab so that a new window is
871 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
872 MAYBE_DeleteTabWhileDetached
) {
874 AddTabAndResetBrowser(browser());
875 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
877 // Move to the first tab and drag it enough so that it detaches.
878 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
879 WebContents
* to_delete
=
880 browser()->tab_strip_model()->GetWebContentsAt(0);
881 ASSERT_TRUE(PressInput(tab_0_center
));
882 ASSERT_TRUE(DragInputToNotifyWhenDone(
883 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
884 base::Bind(&DeleteWhileDetachedStep2
, to_delete
)));
885 QuitWhenNotDragging();
887 // Should not be dragging.
888 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
889 ASSERT_FALSE(TabDragController::IsActive());
891 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
893 EXPECT_FALSE(GetIsDragged(browser()));
898 void DeleteSourceDetachedStep2(WebContents
* tab
,
899 const BrowserList
* browser_list
) {
900 ASSERT_EQ(2u, browser_list
->size());
901 Browser
* new_browser
= browser_list
->get(1);
902 // This ends up closing the source window.
905 ui_controls::SendKeyPress(new_browser
->window()->GetNativeWindow(),
906 ui::VKEY_ESCAPE
, false, false, false, false);
911 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
912 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
913 // compositor. crbug.com/331924
914 #define MAYBE_DeleteSourceDetached DISABLED_DeleteSourceDetached
916 #define MAYBE_DeleteSourceDetached DeleteSourceDetached
918 // Detaches a tab and while detached deletes a tab from the source so that the
919 // source window closes then presses escape to cancel the drag.
920 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
921 MAYBE_DeleteSourceDetached
) {
923 AddTabAndResetBrowser(browser());
924 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
926 // Move to the first tab and drag it enough so that it detaches.
927 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
928 WebContents
* to_delete
= browser()->tab_strip_model()->GetWebContentsAt(1);
929 ASSERT_TRUE(PressInput(tab_0_center
));
930 ASSERT_TRUE(DragInputToNotifyWhenDone(
931 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
932 base::Bind(&DeleteSourceDetachedStep2
, to_delete
, native_browser_list
)));
933 QuitWhenNotDragging();
935 // Should not be dragging.
936 ASSERT_EQ(1u, native_browser_list
->size());
937 Browser
* new_browser
= native_browser_list
->get(0);
938 ASSERT_FALSE(GetTabStripForBrowser(new_browser
)->IsDragSessionActive());
939 ASSERT_FALSE(TabDragController::IsActive());
941 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
943 EXPECT_FALSE(GetIsDragged(new_browser
));
945 // Remaining browser window should not be maximized
946 EXPECT_FALSE(new_browser
->window()->IsMaximized());
951 void PressEscapeWhileDetachedStep2(const BrowserList
* browser_list
) {
952 ASSERT_EQ(2u, browser_list
->size());
953 Browser
* new_browser
= browser_list
->get(1);
954 ui_controls::SendKeyPress(
955 new_browser
->window()->GetNativeWindow(), ui::VKEY_ESCAPE
, false, false,
961 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
962 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
963 // compositor. crbug.com/331924
964 #define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached
966 #define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached
968 // This is disabled until NativeViewHost::Detach really detaches.
969 // Detaches a tab and while detached presses escape to revert the drag.
970 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
971 MAYBE_PressEscapeWhileDetached
) {
973 AddTabAndResetBrowser(browser());
974 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
976 // Move to the first tab and drag it enough so that it detaches.
977 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
978 ASSERT_TRUE(PressInput(tab_0_center
));
979 ASSERT_TRUE(DragInputToNotifyWhenDone(
980 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
981 base::Bind(&PressEscapeWhileDetachedStep2
, native_browser_list
)));
982 QuitWhenNotDragging();
984 // Should not be dragging.
985 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
986 ASSERT_FALSE(TabDragController::IsActive());
988 // And there should only be one window.
989 EXPECT_EQ(1u, native_browser_list
->size());
991 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
993 // Remaining browser window should not be maximized
994 EXPECT_FALSE(browser()->window()->IsMaximized());
996 // The tab strip should no longer have capture because the drag was ended and
997 // mouse/touch was released.
998 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
1003 void DragAllStep2(DetachToBrowserTabDragControllerTest
* test
,
1004 const BrowserList
* browser_list
) {
1005 // Should only be one window.
1006 ASSERT_EQ(1u, browser_list
->size());
1007 if (test
->input_source() == INPUT_SOURCE_TOUCH
) {
1008 ASSERT_TRUE(test
->ReleaseInput());
1010 ASSERT_TRUE(test
->ReleaseMouseAsync());
1016 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1017 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1018 // compositor. crbug.com/331924
1019 #define MAYBE_DragAll DISABLED_DragAll
1021 #define MAYBE_DragAll DragAll
1023 // Selects multiple tabs and starts dragging the window.
1024 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, MAYBE_DragAll
) {
1026 AddTabAndResetBrowser(browser());
1027 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1028 browser()->tab_strip_model()->AddTabAtToSelection(0);
1029 browser()->tab_strip_model()->AddTabAtToSelection(1);
1031 // Move to the first tab and drag it enough so that it would normally
1033 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1034 ASSERT_TRUE(PressInput(tab_0_center
));
1035 ASSERT_TRUE(DragInputToNotifyWhenDone(
1036 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1037 base::Bind(&DragAllStep2
, this, native_browser_list
)));
1038 QuitWhenNotDragging();
1040 // Should not be dragging.
1041 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1042 ASSERT_FALSE(TabDragController::IsActive());
1044 // And there should only be one window.
1045 EXPECT_EQ(1u, native_browser_list
->size());
1047 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1049 EXPECT_FALSE(GetIsDragged(browser()));
1051 // Remaining browser window should not be maximized
1052 EXPECT_FALSE(browser()->window()->IsMaximized());
1057 // Invoked from the nested message loop.
1058 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1059 TabStrip
* attached_tab_strip
,
1060 TabStrip
* target_tab_strip
,
1061 const BrowserList
* browser_list
) {
1062 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1063 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1064 ASSERT_TRUE(TabDragController::IsActive());
1065 ASSERT_EQ(2u, browser_list
->size());
1067 // Drag to target_tab_strip. This should stop the nested loop from dragging
1069 gfx::Point
target_point(target_tab_strip
->width() - 1,
1070 target_tab_strip
->height() / 2);
1071 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1072 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1077 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1078 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1079 // compositor. crbug.com/331924
1080 #define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow
1082 #define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow
1084 // Creates two browsers, selects all tabs in first and drags into second.
1085 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1086 MAYBE_DragAllToSeparateWindow
) {
1087 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1089 // Add another tab to browser().
1090 AddTabAndResetBrowser(browser());
1092 // Create another browser.
1093 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1094 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1096 browser()->tab_strip_model()->AddTabAtToSelection(0);
1097 browser()->tab_strip_model()->AddTabAtToSelection(1);
1099 // Move to the first tab and drag it enough so that it detaches, but not
1100 // enough that it attaches to browser2.
1101 gfx::Point
tab_0_center(
1102 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1103 ASSERT_TRUE(PressInput(tab_0_center
));
1104 ASSERT_TRUE(DragInputToNotifyWhenDone(
1105 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1106 base::Bind(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1107 native_browser_list
)));
1108 QuitWhenNotDragging();
1110 // Should now be attached to tab_strip2.
1111 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1112 ASSERT_TRUE(TabDragController::IsActive());
1113 ASSERT_EQ(1u, native_browser_list
->size());
1115 // Release the mouse, stopping the drag session.
1116 ASSERT_TRUE(ReleaseInput());
1117 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1118 ASSERT_FALSE(TabDragController::IsActive());
1119 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1121 EXPECT_FALSE(GetIsDragged(browser2
));
1123 // Remaining browser window should not be maximized
1124 EXPECT_FALSE(browser2
->window()->IsMaximized());
1129 // Invoked from the nested message loop.
1130 void DragAllToSeparateWindowAndCancelStep2(
1131 DetachToBrowserTabDragControllerTest
* test
,
1132 TabStrip
* attached_tab_strip
,
1133 TabStrip
* target_tab_strip
,
1134 const BrowserList
* browser_list
) {
1135 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1136 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1137 ASSERT_TRUE(TabDragController::IsActive());
1138 ASSERT_EQ(2u, browser_list
->size());
1140 // Drag to target_tab_strip. This should stop the nested loop from dragging
1142 gfx::Point
target_point(target_tab_strip
->width() - 1,
1143 target_tab_strip
->height() / 2);
1144 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1145 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1150 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1151 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1152 // compositor. crbug.com/331924
1153 #define MAYBE_DragAllToSeparateWindowAndCancel \
1154 DISABLED_DragAllToSeparateWindowAndCancel
1156 #define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel
1158 // Creates two browsers, selects all tabs in first, drags into second, then hits
1160 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1161 MAYBE_DragAllToSeparateWindowAndCancel
) {
1162 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1164 // Add another tab to browser().
1165 AddTabAndResetBrowser(browser());
1167 // Create another browser.
1168 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1169 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1171 browser()->tab_strip_model()->AddTabAtToSelection(0);
1172 browser()->tab_strip_model()->AddTabAtToSelection(1);
1174 // Move to the first tab and drag it enough so that it detaches, but not
1175 // enough that it attaches to browser2.
1176 gfx::Point
tab_0_center(
1177 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1178 ASSERT_TRUE(PressInput(tab_0_center
));
1179 ASSERT_TRUE(DragInputToNotifyWhenDone(
1180 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1181 base::Bind(&DragAllToSeparateWindowAndCancelStep2
, this,
1182 tab_strip
, tab_strip2
, native_browser_list
)));
1183 QuitWhenNotDragging();
1185 // Should now be attached to tab_strip2.
1186 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1187 ASSERT_TRUE(TabDragController::IsActive());
1188 ASSERT_EQ(1u, native_browser_list
->size());
1191 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
1192 browser2
, ui::VKEY_ESCAPE
, false, false, false, false));
1194 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1195 ASSERT_FALSE(TabDragController::IsActive());
1196 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1198 // browser() will have been destroyed, but browser2 should remain.
1199 ASSERT_EQ(1u, native_browser_list
->size());
1201 EXPECT_FALSE(GetIsDragged(browser2
));
1203 // Remaining browser window should not be maximized
1204 EXPECT_FALSE(browser2
->window()->IsMaximized());
1207 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
1208 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1209 // compositor. crbug.com/331924
1210 #define MAYBE_DragDirectlyToSecondWindow DISABLED_DragDirectlyToSecondWindow
1212 #define MAYBE_DragDirectlyToSecondWindow DragDirectlyToSecondWindow
1214 // Creates two browsers, drags from first into the second in such a way that
1215 // no detaching should happen.
1216 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1217 MAYBE_DragDirectlyToSecondWindow
) {
1218 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1220 // Add another tab to browser().
1221 AddTabAndResetBrowser(browser());
1223 // Create another browser.
1224 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1225 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1227 // Move the tabstrip down enough so that we can detach.
1228 gfx::Rect
bounds(browser2
->window()->GetBounds());
1229 bounds
.Offset(0, 100);
1230 browser2
->window()->SetBounds(bounds
);
1232 // Move to the first tab and drag it enough so that it detaches, but not
1233 // enough that it attaches to browser2.
1234 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1235 ASSERT_TRUE(PressInput(tab_0_center
));
1237 gfx::Point
b2_location(5, 0);
1238 views::View::ConvertPointToScreen(tab_strip2
, &b2_location
);
1239 ASSERT_TRUE(DragInputTo(b2_location
));
1241 // Should now be attached to tab_strip2.
1242 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1243 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1244 ASSERT_TRUE(TabDragController::IsActive());
1246 // Release the mouse, stopping the drag session.
1247 ASSERT_TRUE(ReleaseInput());
1248 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1249 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1250 ASSERT_FALSE(TabDragController::IsActive());
1251 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1252 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1254 EXPECT_FALSE(GetIsDragged(browser()));
1255 EXPECT_FALSE(GetIsDragged(browser2
));
1257 // Both windows should not be maximized
1258 EXPECT_FALSE(browser()->window()->IsMaximized());
1259 EXPECT_FALSE(browser2
->window()->IsMaximized());
1262 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1263 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1264 // compositor. crbug.com/331924
1265 #define MAYBE_DragSingleTabToSeparateWindow \
1266 DISABLED_DragSingleTabToSeparateWindow
1268 #define MAYBE_DragSingleTabToSeparateWindow DragSingleTabToSeparateWindow
1270 // Creates two browsers, the first browser has a single tab and drags into the
1272 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1273 MAYBE_DragSingleTabToSeparateWindow
) {
1274 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1276 ResetIDs(browser()->tab_strip_model(), 0);
1278 // Create another browser.
1279 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1280 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1281 const gfx::Rect
initial_bounds(browser2
->window()->GetBounds());
1283 // Move to the first tab and drag it enough so that it detaches, but not
1284 // enough that it attaches to browser2.
1285 gfx::Point
tab_0_center(
1286 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1287 ASSERT_TRUE(PressInput(tab_0_center
));
1288 ASSERT_TRUE(DragInputToNotifyWhenDone(
1289 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1290 base::Bind(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1291 native_browser_list
)));
1292 QuitWhenNotDragging();
1294 // Should now be attached to tab_strip2.
1295 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1296 ASSERT_TRUE(TabDragController::IsActive());
1297 ASSERT_EQ(1u, native_browser_list
->size());
1299 // Release the mouse, stopping the drag session.
1300 ASSERT_TRUE(ReleaseInput());
1301 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1302 ASSERT_FALSE(TabDragController::IsActive());
1303 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
1305 EXPECT_FALSE(GetIsDragged(browser2
));
1307 // Remaining browser window should not be maximized
1308 EXPECT_FALSE(browser2
->window()->IsMaximized());
1310 // Make sure that the window is still managed and not user moved.
1311 EXPECT_TRUE(IsWindowPositionManaged(browser2
->window()->GetNativeWindow()));
1312 EXPECT_FALSE(HasUserChangedWindowPositionOrSize(
1313 browser2
->window()->GetNativeWindow()));
1314 // Also make sure that the drag to window position has not changed.
1315 EXPECT_EQ(initial_bounds
.ToString(),
1316 browser2
->window()->GetBounds().ToString());
1321 // Invoked from the nested message loop.
1322 void CancelOnNewTabWhenDraggingStep2(
1323 DetachToBrowserTabDragControllerTest
* test
,
1324 const BrowserList
* browser_list
) {
1325 ASSERT_TRUE(TabDragController::IsActive());
1326 ASSERT_EQ(2u, browser_list
->size());
1328 // Add another tab. This should trigger exiting the nested loop.
1329 test
->AddBlankTabAndShow(browser_list
->GetLastActive());
1334 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1335 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1336 // compositor. crbug.com/331924
1337 #define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging
1339 #define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging
1341 // Adds another tab, detaches into separate window, adds another tab and
1342 // verifies the run loop ends.
1343 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1344 MAYBE_CancelOnNewTabWhenDragging
) {
1345 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1347 // Add another tab to browser().
1348 AddTabAndResetBrowser(browser());
1350 // Move to the first tab and drag it enough so that it detaches.
1351 gfx::Point
tab_0_center(
1352 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1353 ASSERT_TRUE(PressInput(tab_0_center
));
1354 ASSERT_TRUE(DragInputToNotifyWhenDone(
1355 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1356 base::Bind(&CancelOnNewTabWhenDraggingStep2
, this, native_browser_list
)));
1357 QuitWhenNotDragging();
1359 // Should be two windows and not dragging.
1360 ASSERT_FALSE(TabDragController::IsActive());
1361 ASSERT_EQ(2u, native_browser_list
->size());
1362 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
1363 EXPECT_FALSE(GetIsDragged(*it
));
1364 // Should not be maximized
1365 EXPECT_FALSE(it
->window()->IsMaximized());
1369 #if defined(OS_CHROMEOS)
1370 // TODO(sky,sad): A number of tests below are disabled as they fail due to
1371 // resize locks with a real compositor. crbug.com/331924
1374 void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1376 TabStrip
* tab_strip
,
1377 const BrowserList
* browser_list
) {
1378 // There should be another browser.
1379 ASSERT_EQ(2u, browser_list
->size());
1380 Browser
* new_browser
= browser_list
->get(1);
1381 EXPECT_NE(browser
, new_browser
);
1382 ASSERT_TRUE(new_browser
->window()->IsActive());
1383 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1385 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1386 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1388 // Both windows should be visible.
1389 EXPECT_TRUE(tab_strip
->GetWidget()->IsVisible());
1390 EXPECT_TRUE(tab_strip2
->GetWidget()->IsVisible());
1393 ASSERT_TRUE(test
->ReleaseInput());
1398 // Creates a browser with two tabs, maximizes it, drags the tab out.
1399 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1400 DISABLED_DragInMaximizedWindow
) {
1401 AddTabAndResetBrowser(browser());
1402 browser()->window()->Maximize();
1404 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1406 // Move to the first tab and drag it enough so that it detaches.
1407 gfx::Point
tab_0_center(
1408 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1409 ASSERT_TRUE(PressInput(tab_0_center
));
1410 ASSERT_TRUE(DragInputToNotifyWhenDone(
1411 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1412 base::Bind(&DragInMaximizedWindowStep2
, this, browser(), tab_strip
,
1413 native_browser_list
)));
1414 QuitWhenNotDragging();
1416 ASSERT_FALSE(TabDragController::IsActive());
1418 // Should be two browsers.
1419 ASSERT_EQ(2u, native_browser_list
->size());
1420 Browser
* new_browser
= native_browser_list
->get(1);
1421 ASSERT_TRUE(new_browser
->window()->IsActive());
1423 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible());
1424 EXPECT_TRUE(new_browser
->window()->GetNativeWindow()->IsVisible());
1426 EXPECT_FALSE(GetIsDragged(browser()));
1427 EXPECT_FALSE(GetIsDragged(new_browser
));
1429 // The source window should be maximized.
1430 EXPECT_TRUE(browser()->window()->IsMaximized());
1431 // The new window should be maximized.
1432 EXPECT_TRUE(new_browser
->window()->IsMaximized());
1435 // Subclass of DetachToBrowserTabDragControllerTest that
1436 // creates multiple displays.
1437 class DetachToBrowserInSeparateDisplayTabDragControllerTest
1438 : public DetachToBrowserTabDragControllerTest
{
1440 DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1441 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1443 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1444 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1445 // Make screens sufficiently wide to host 2 browsers side by side.
1446 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1447 "0+0-600x600,601+0-600x600");
1451 DISALLOW_COPY_AND_ASSIGN(
1452 DetachToBrowserInSeparateDisplayTabDragControllerTest
);
1455 // Subclass of DetachToBrowserTabDragControllerTest that runs tests only with
1457 class DetachToBrowserTabDragControllerTestTouch
1458 : public DetachToBrowserTabDragControllerTest
{
1460 DetachToBrowserTabDragControllerTestTouch() {}
1461 virtual ~DetachToBrowserTabDragControllerTestTouch() {}
1464 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch
);
1469 void DragSingleTabToSeparateWindowInSecondDisplayStep3(
1470 DetachToBrowserTabDragControllerTest
* test
) {
1471 ASSERT_TRUE(test
->ReleaseInput());
1474 void DragSingleTabToSeparateWindowInSecondDisplayStep2(
1475 DetachToBrowserTabDragControllerTest
* test
,
1476 const gfx::Point
& target_point
) {
1477 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
1478 target_point
.x(), target_point
.y(),
1479 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3
, test
)));
1484 // Drags from browser to a second display and releases input.
1485 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1486 DISABLED_DragSingleTabToSeparateWindowInSecondDisplay
) {
1488 AddTabAndResetBrowser(browser());
1489 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1491 // Move to the first tab and drag it enough so that it detaches.
1492 // Then drag it to the final destination on the second screen.
1493 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1494 ASSERT_TRUE(PressInput(tab_0_center
));
1495 ASSERT_TRUE(DragInputToNotifyWhenDone(
1496 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1497 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2
,
1498 this, gfx::Point(600 + tab_0_center
.x(),
1500 + GetDetachY(tab_strip
)))));
1501 QuitWhenNotDragging();
1503 // Should no longer be dragging.
1504 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1505 ASSERT_FALSE(TabDragController::IsActive());
1507 // There should now be another browser.
1508 ASSERT_EQ(2u, native_browser_list
->size());
1509 Browser
* new_browser
= native_browser_list
->get(1);
1510 ASSERT_TRUE(new_browser
->window()->IsActive());
1511 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1512 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1514 // This other browser should be on the second screen (with mouse drag)
1515 // With the touch input the browser cannot be dragged from one screen
1516 // to another and the window stays on the first screen.
1517 if (input_source() == INPUT_SOURCE_MOUSE
) {
1518 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1519 ASSERT_EQ(2u, roots
.size());
1520 aura::Window
* second_root
= roots
[1];
1521 EXPECT_EQ(second_root
,
1522 new_browser
->window()->GetNativeWindow()->GetRootWindow());
1525 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
1526 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1528 // Both windows should not be maximized
1529 EXPECT_FALSE(browser()->window()->IsMaximized());
1530 EXPECT_FALSE(new_browser
->window()->IsMaximized());
1535 // Invoked from the nested message loop.
1536 void DragTabToWindowInSeparateDisplayStep2(
1537 DetachToBrowserTabDragControllerTest
* test
,
1538 TabStrip
* not_attached_tab_strip
,
1539 TabStrip
* target_tab_strip
) {
1540 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
1541 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1542 ASSERT_TRUE(TabDragController::IsActive());
1544 // Drag to target_tab_strip. This should stop the nested loop from dragging
1546 gfx::Point
target_point(
1547 GetCenterInScreenCoordinates(target_tab_strip
->tab_at(0)));
1549 // Move it close to the beginning of the target tabstrip.
1551 target_point
.x() - target_tab_strip
->tab_at(0)->width() / 2 + 10);
1552 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1557 // Drags from browser to another browser on a second display and releases input.
1558 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1559 DISABLED_DragTabToWindowInSeparateDisplay
) {
1561 AddTabAndResetBrowser(browser());
1562 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1564 // Create another browser.
1565 Browser
* browser2
= CreateBrowser(browser()->profile());
1566 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1567 ResetIDs(browser2
->tab_strip_model(), 100);
1569 // Move the second browser to the second display.
1570 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1571 ASSERT_EQ(2u, roots
.size());
1572 aura::Window
* second_root
= roots
[1];
1573 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1574 second_root
).work_area();
1575 browser2
->window()->SetBounds(work_area
);
1576 EXPECT_EQ(second_root
,
1577 browser2
->window()->GetNativeWindow()->GetRootWindow());
1579 // Move to the first tab and drag it enough so that it detaches, but not
1580 // enough that it attaches to browser2.
1581 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1582 ASSERT_TRUE(PressInput(tab_0_center
));
1583 ASSERT_TRUE(DragInputToNotifyWhenDone(
1584 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1585 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1586 this, tab_strip
, tab_strip2
)));
1587 QuitWhenNotDragging();
1589 // Should now be attached to tab_strip2.
1590 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1591 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1592 ASSERT_TRUE(TabDragController::IsActive());
1594 // Release the mouse, stopping the drag session.
1595 ASSERT_TRUE(ReleaseInput());
1596 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1597 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1598 ASSERT_FALSE(TabDragController::IsActive());
1599 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1600 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1602 // Both windows should not be maximized
1603 EXPECT_FALSE(browser()->window()->IsMaximized());
1604 EXPECT_FALSE(browser2
->window()->IsMaximized());
1607 // Drags from browser to another browser on a second display and releases input.
1608 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1609 DISABLED_DragTabToWindowOnSecondDisplay
) {
1611 AddTabAndResetBrowser(browser());
1612 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1614 // Create another browser.
1615 Browser
* browser2
= CreateBrowser(browser()->profile());
1616 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1617 ResetIDs(browser2
->tab_strip_model(), 100);
1619 // Move both browsers to the second display.
1620 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1621 ASSERT_EQ(2u, roots
.size());
1622 aura::Window
* second_root
= roots
[1];
1623 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1624 second_root
).work_area();
1625 browser()->window()->SetBounds(work_area
);
1627 // position both browser windows side by side on the second screen.
1628 gfx::Rect
work_area2(work_area
);
1629 work_area
.set_width(work_area
.width()/2);
1630 browser()->window()->SetBounds(work_area
);
1631 work_area2
.set_x(work_area2
.x() + work_area2
.width()/2);
1632 work_area2
.set_width(work_area2
.width()/2);
1633 browser2
->window()->SetBounds(work_area2
);
1634 EXPECT_EQ(second_root
,
1635 browser()->window()->GetNativeWindow()->GetRootWindow());
1636 EXPECT_EQ(second_root
,
1637 browser2
->window()->GetNativeWindow()->GetRootWindow());
1639 // Move to the first tab and drag it enough so that it detaches, but not
1640 // enough that it attaches to browser2.
1641 // SetEventGeneratorRootWindow sets correct (second) RootWindow
1642 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1643 SetEventGeneratorRootWindow(tab_0_center
);
1644 ASSERT_TRUE(PressInput(tab_0_center
));
1645 ASSERT_TRUE(DragInputToNotifyWhenDone(
1646 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1647 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1648 this, tab_strip
, tab_strip2
)));
1649 QuitWhenNotDragging();
1651 // Should now be attached to tab_strip2.
1652 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1653 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1654 ASSERT_TRUE(TabDragController::IsActive());
1656 // Release the mouse, stopping the drag session.
1657 ASSERT_TRUE(ReleaseInput());
1658 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1659 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1660 ASSERT_FALSE(TabDragController::IsActive());
1661 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1662 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1664 // Both windows should not be maximized
1665 EXPECT_FALSE(browser()->window()->IsMaximized());
1666 EXPECT_FALSE(browser2
->window()->IsMaximized());
1669 // Drags from a maximized browser to another non-maximized browser on a second
1670 // display and releases input.
1671 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1672 DISABLED_DragMaxTabToNonMaxWindowInSeparateDisplay
) {
1674 AddTabAndResetBrowser(browser());
1675 browser()->window()->Maximize();
1676 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1678 // Create another browser on the second display.
1679 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1680 ASSERT_EQ(2u, roots
.size());
1681 aura::Window
* first_root
= roots
[0];
1682 aura::Window
* second_root
= roots
[1];
1683 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1684 second_root
).work_area();
1685 work_area
.Inset(20, 20, 20, 60);
1686 Browser::CreateParams
params(browser()->profile(),
1687 browser()->host_desktop_type());
1688 params
.initial_show_state
= ui::SHOW_STATE_NORMAL
;
1689 params
.initial_bounds
= work_area
;
1690 Browser
* browser2
= new Browser(params
);
1691 AddBlankTabAndShow(browser2
);
1693 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1694 ResetIDs(browser2
->tab_strip_model(), 100);
1696 EXPECT_EQ(second_root
,
1697 browser2
->window()->GetNativeWindow()->GetRootWindow());
1698 EXPECT_EQ(first_root
,
1699 browser()->window()->GetNativeWindow()->GetRootWindow());
1700 EXPECT_EQ(2, tab_strip
->tab_count());
1701 EXPECT_EQ(1, tab_strip2
->tab_count());
1703 // Move to the first tab and drag it enough so that it detaches, but not
1704 // enough that it attaches to browser2.
1705 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1706 ASSERT_TRUE(PressInput(tab_0_center
));
1707 ASSERT_TRUE(DragInputToNotifyWhenDone(
1708 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1709 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1710 this, tab_strip
, tab_strip2
)));
1711 QuitWhenNotDragging();
1713 // Should now be attached to tab_strip2.
1714 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1715 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1716 ASSERT_TRUE(TabDragController::IsActive());
1718 // Release the mouse, stopping the drag session.
1719 ASSERT_TRUE(ReleaseInput());
1721 // tab should have moved
1722 EXPECT_EQ(1, tab_strip
->tab_count());
1723 EXPECT_EQ(2, tab_strip2
->tab_count());
1725 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1726 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1727 ASSERT_FALSE(TabDragController::IsActive());
1728 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1729 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1731 // Source browser should still be maximized, target should not
1732 EXPECT_TRUE(browser()->window()->IsMaximized());
1733 EXPECT_FALSE(browser2
->window()->IsMaximized());
1736 // Drags from a restored browser to an immersive fullscreen browser on a
1737 // second display and releases input.
1738 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1739 DISABLED_DragTabToImmersiveBrowserOnSeparateDisplay
) {
1741 AddTabAndResetBrowser(browser());
1742 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1744 // Create another browser.
1745 Browser
* browser2
= CreateBrowser(browser()->profile());
1746 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1747 ResetIDs(browser2
->tab_strip_model(), 100);
1749 // Move the second browser to the second display.
1750 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1751 ASSERT_EQ(2u, roots
.size());
1752 aura::Window
* second_root
= roots
[1];
1753 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1754 second_root
).work_area();
1755 browser2
->window()->SetBounds(work_area
);
1756 EXPECT_EQ(second_root
,
1757 browser2
->window()->GetNativeWindow()->GetRootWindow());
1759 // Put the second browser into immersive fullscreen.
1760 BrowserView
* browser_view2
= BrowserView::GetBrowserViewForBrowser(browser2
);
1761 ImmersiveModeController
* immersive_controller2
=
1762 browser_view2
->immersive_mode_controller();
1763 immersive_controller2
->SetupForTest();
1764 chrome::ToggleFullscreenMode(browser2
);
1765 ASSERT_TRUE(immersive_controller2
->IsEnabled());
1766 ASSERT_FALSE(immersive_controller2
->IsRevealed());
1767 ASSERT_TRUE(tab_strip2
->IsImmersiveStyle());
1769 // Move to the first tab and drag it enough so that it detaches, but not
1770 // enough that it attaches to browser2.
1771 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1772 ASSERT_TRUE(PressInput(tab_0_center
));
1773 ASSERT_TRUE(DragInputToNotifyWhenDone(
1774 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1775 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1776 this, tab_strip
, tab_strip2
)));
1777 QuitWhenNotDragging();
1779 // Should now be attached to tab_strip2.
1780 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1781 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1782 ASSERT_TRUE(TabDragController::IsActive());
1784 // browser2's top chrome should be revealed and the tab strip should be
1785 // at normal height while user is tragging tabs_strip2's tabs.
1786 ASSERT_TRUE(immersive_controller2
->IsRevealed());
1787 ASSERT_FALSE(tab_strip2
->IsImmersiveStyle());
1789 // Release the mouse, stopping the drag session.
1790 ASSERT_TRUE(ReleaseInput());
1791 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1792 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1793 ASSERT_FALSE(TabDragController::IsActive());
1794 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1795 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1797 // Move the mouse off of browser2's top chrome.
1798 aura::Window
* primary_root
= roots
[0];
1799 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
1800 primary_root
->GetBoundsInScreen().CenterPoint()));
1802 // The first browser window should not be in immersive fullscreen.
1803 // browser2 should still be in immersive fullscreen, but the top chrome should
1804 // no longer be revealed.
1805 BrowserView
* browser_view
= BrowserView::GetBrowserViewForBrowser(browser());
1806 EXPECT_FALSE(browser_view
->immersive_mode_controller()->IsEnabled());
1808 EXPECT_TRUE(immersive_controller2
->IsEnabled());
1809 EXPECT_FALSE(immersive_controller2
->IsRevealed());
1810 EXPECT_TRUE(tab_strip2
->IsImmersiveStyle());
1813 // Subclass of DetachToBrowserTabDragControllerTest that
1814 // creates multiple displays with different device scale factors.
1815 class DifferentDeviceScaleFactorDisplayTabDragControllerTest
1816 : public DetachToBrowserTabDragControllerTest
{
1818 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1819 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1821 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1822 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1823 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1824 "400x400,0+400-800x800*2");
1827 float GetCursorDeviceScaleFactor() const {
1828 ash::test::CursorManagerTestApi
cursor_test_api(
1829 ash::Shell::GetInstance()->cursor_manager());
1830 return cursor_test_api
.GetCurrentCursor().device_scale_factor();
1834 DISALLOW_COPY_AND_ASSIGN(
1835 DifferentDeviceScaleFactorDisplayTabDragControllerTest
);
1840 // The points where a tab is dragged in CursorDeviceScaleFactorStep.
1841 const struct DragPoint
{
1852 // The expected device scale factors before the cursor is moved to the
1853 // corresponding kDragPoints in CursorDeviceScaleFactorStep.
1854 const float kDeviceScaleFactorExpectations
[] = {
1863 arraysize(kDragPoints
) == arraysize(kDeviceScaleFactorExpectations
),
1864 "kDragPoints and kDeviceScaleFactorExpectations must have the same "
1865 "number of elements");
1867 // Drags tab to |kDragPoints[index]|, then calls the next step function.
1868 void CursorDeviceScaleFactorStep(
1869 DifferentDeviceScaleFactorDisplayTabDragControllerTest
* test
,
1870 TabStrip
* not_attached_tab_strip
,
1872 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
1873 ASSERT_TRUE(TabDragController::IsActive());
1875 if (index
< arraysize(kDragPoints
)) {
1876 EXPECT_EQ(kDeviceScaleFactorExpectations
[index
],
1877 test
->GetCursorDeviceScaleFactor());
1878 const DragPoint p
= kDragPoints
[index
];
1879 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
1880 p
.x
, p
.y
, base::Bind(&CursorDeviceScaleFactorStep
,
1881 test
, not_attached_tab_strip
, index
+ 1)));
1883 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag.
1884 EXPECT_EQ(1.0f
, test
->GetCursorDeviceScaleFactor());
1885 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
1886 ui_controls::LEFT
, ui_controls::UP
));
1892 // Verifies cursor's device scale factor is updated when a tab is moved across
1893 // displays with different device scale factors (http://crbug.com/154183).
1894 IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
1895 DISABLED_CursorDeviceScaleFactor
) {
1897 AddTabAndResetBrowser(browser());
1898 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1900 // Move the second browser to the second display.
1901 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1902 ASSERT_EQ(2u, roots
.size());
1904 // Move to the first tab and drag it enough so that it detaches.
1905 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1906 ASSERT_TRUE(PressInput(tab_0_center
));
1907 ASSERT_TRUE(DragInputToNotifyWhenDone(
1908 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1909 base::Bind(&CursorDeviceScaleFactorStep
,
1910 this, tab_strip
, 0)));
1911 QuitWhenNotDragging();
1916 class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
1917 : public TabDragControllerTest
{
1919 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {}
1921 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1922 TabDragControllerTest::SetUpCommandLine(command_line
);
1923 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1924 "0+0-250x250,251+0-250x250");
1927 bool Press(const gfx::Point
& position
) {
1928 return ui_test_utils::SendMouseMoveSync(position
) &&
1929 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT
,
1933 bool DragTabAndExecuteTaskWhenDone(const gfx::Point
& position
,
1934 const base::Closure
& task
) {
1935 return ui_controls::SendMouseMoveNotifyWhenDone(
1936 position
.x(), position
.y(), task
);
1939 void QuitWhenNotDragging() {
1940 test::QuitWhenNotDraggingImpl();
1941 base::MessageLoop::current()->Run();
1945 DISALLOW_COPY_AND_ASSIGN(
1946 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
);
1949 // Invoked from the nested message loop.
1950 void CancelDragTabToWindowInSeparateDisplayStep3(
1951 TabStrip
* tab_strip
,
1952 const BrowserList
* browser_list
) {
1953 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1954 ASSERT_TRUE(TabDragController::IsActive());
1955 ASSERT_EQ(2u, browser_list
->size());
1957 // Switching display mode should cancel the drag operation.
1958 ash::DisplayManager
* display_manager
=
1959 ash::Shell::GetInstance()->display_manager();
1960 display_manager
->AddRemoveDisplay();
1963 // Invoked from the nested message loop.
1964 void CancelDragTabToWindowInSeparateDisplayStep2(
1965 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
* test
,
1966 TabStrip
* tab_strip
,
1967 aura::Window
* current_root
,
1968 gfx::Point final_destination
,
1969 const BrowserList
* browser_list
) {
1970 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1971 ASSERT_TRUE(TabDragController::IsActive());
1972 ASSERT_EQ(2u, browser_list
->size());
1974 Browser
* new_browser
= browser_list
->get(1);
1975 EXPECT_EQ(current_root
,
1976 new_browser
->window()->GetNativeWindow()->GetRootWindow());
1978 ASSERT_TRUE(test
->DragTabAndExecuteTaskWhenDone(
1980 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3
,
1981 tab_strip
, browser_list
)));
1986 // Drags from browser to a second display and releases input.
1987 IN_PROC_BROWSER_TEST_F(
1988 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
1989 DISABLED_CancelDragTabToWindowIn2ndDisplay
) {
1991 AddTabAndResetBrowser(browser());
1992 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1994 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1996 // Move the second browser to the second display.
1997 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1998 ASSERT_EQ(2u, roots
.size());
1999 gfx::Point final_destination
=
2000 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2001 roots
[1]).work_area().CenterPoint();
2003 // Move to the first tab and drag it enough so that it detaches, but not
2004 // enough to move to another display.
2005 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2006 ASSERT_TRUE(Press(tab_0_dst
));
2007 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2008 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2009 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2010 this, tab_strip
, roots
[0], final_destination
,
2011 native_browser_list
)));
2012 QuitWhenNotDragging();
2014 ASSERT_EQ(1u, native_browser_list
->size());
2015 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2016 ASSERT_FALSE(TabDragController::IsActive());
2017 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2019 // Release the mouse
2020 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2021 ui_controls::LEFT
, ui_controls::UP
));
2024 // Drags from browser from a second display to primary and releases input.
2025 IN_PROC_BROWSER_TEST_F(
2026 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
2027 DISABLED_CancelDragTabToWindowIn1stDisplay
) {
2028 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2029 ASSERT_EQ(2u, roots
.size());
2032 AddTabAndResetBrowser(browser());
2033 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2035 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2036 EXPECT_EQ(roots
[0], browser()->window()->GetNativeWindow()->GetRootWindow());
2038 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->
2039 GetDisplayNearestWindow(roots
[1]).work_area();
2040 browser()->window()->SetBounds(work_area
);
2041 EXPECT_EQ(roots
[1], browser()->window()->GetNativeWindow()->GetRootWindow());
2043 // Move the second browser to the display.
2044 gfx::Point final_destination
=
2045 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2046 roots
[0]).work_area().CenterPoint();
2048 // Move to the first tab and drag it enough so that it detaches, but not
2049 // enough to move to another display.
2050 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2051 ASSERT_TRUE(Press(tab_0_dst
));
2052 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2053 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2054 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2055 this, tab_strip
, roots
[1], final_destination
,
2056 native_browser_list
)));
2057 QuitWhenNotDragging();
2059 ASSERT_EQ(1u, native_browser_list
->size());
2060 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2061 ASSERT_FALSE(TabDragController::IsActive());
2062 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2064 // Release the mouse
2065 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2066 ui_controls::LEFT
, ui_controls::UP
));
2071 void PressSecondFingerWhileDetachedStep2(
2072 DetachToBrowserTabDragControllerTest
* test
) {
2073 ASSERT_TRUE(TabDragController::IsActive());
2074 ASSERT_EQ(2u, test
->native_browser_list
->size());
2075 Browser
* new_browser
= test
->native_browser_list
->get(1);
2076 ASSERT_TRUE(new_browser
->window()->IsActive());
2078 ASSERT_TRUE(test
->PressInput2());
2083 // Detaches a tab and while detached presses a second finger.
2084 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch
,
2085 DISABLED_PressSecondFingerWhileDetached
) {
2086 gfx::Rect
bounds(browser()->window()->GetBounds());
2088 AddTabAndResetBrowser(browser());
2089 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2090 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2092 // Move to the first tab and drag it enough so that it detaches.
2093 gfx::Point
tab_0_center(
2094 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2095 ASSERT_TRUE(PressInput(tab_0_center
));
2096 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone(
2097 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2098 base::Bind(&PressSecondFingerWhileDetachedStep2
, this),
2099 base::TimeDelta::FromMilliseconds(60)));
2100 QuitWhenNotDragging();
2102 // The drag should have been reverted.
2103 ASSERT_EQ(1u, native_browser_list
->size());
2104 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2105 ASSERT_FALSE(TabDragController::IsActive());
2106 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2108 ASSERT_TRUE(ReleaseInput());
2109 ASSERT_TRUE(ReleaseInput2());
2112 #if defined(OS_CHROMEOS)
2116 void DetachToDockedWindowNextStep(
2117 DetachToBrowserTabDragControllerTest
* test
,
2118 const gfx::Point
& target_point
,
2120 ASSERT_EQ(2u, test
->native_browser_list
->size());
2121 Browser
* new_browser
= test
->native_browser_list
->get(1);
2122 ASSERT_TRUE(new_browser
->window()->IsActive());
2125 ASSERT_TRUE(test
->ReleaseInput());
2128 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
2129 target_point
.x(), target_point
.y(),
2130 base::Bind(&DetachToDockedWindowNextStep
,
2132 gfx::Point(target_point
.x(), 1 + target_point
.y()),
2138 // Drags from browser to separate window, docks that window and releases mouse.
2139 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
2140 DISABLED_DetachToDockedWindowFromMaximizedWindow
) {
2141 // Maximize the initial browser window.
2142 browser()->window()->Maximize();
2143 ASSERT_TRUE(browser()->window()->IsMaximized());
2146 AddTabAndResetBrowser(browser());
2147 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2149 // Move to the first tab and drag it enough so that it detaches.
2150 gfx::Point
tab_0_center(
2151 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2152 ASSERT_TRUE(PressInput(tab_0_center
));
2154 // The following matches kMovesBeforeAdjust in snap_sizer.cc
2155 const int kNumIterations
= 25 * 5 + 10;
2156 ASSERT_TRUE(DragInputToNotifyWhenDone(
2157 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2158 base::Bind(&DetachToDockedWindowNextStep
, this,
2159 gfx::Point(0, tab_0_center
.y() + GetDetachY(tab_strip
)),
2161 // Continue dragging enough times to go through snapping sequence and dock
2163 QuitWhenNotDragging();
2164 // Should no longer be dragging.
2165 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2166 ASSERT_FALSE(TabDragController::IsActive());
2168 // There should now be another browser.
2169 ASSERT_EQ(2u, native_browser_list
->size());
2170 Browser
* new_browser
= native_browser_list
->get(1);
2171 ASSERT_TRUE(new_browser
->window()->IsActive());
2172 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
2173 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
2175 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
2176 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
2178 // The bounds of the initial window should not have changed.
2179 EXPECT_TRUE(browser()->window()->IsMaximized());
2181 EXPECT_FALSE(GetIsDragged(browser()));
2182 EXPECT_FALSE(GetIsDragged(new_browser
));
2183 // After this both windows should still be manageable.
2184 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
2185 EXPECT_TRUE(IsWindowPositionManaged(
2186 new_browser
->window()->GetNativeWindow()));
2188 ash::wm::WindowState
* window_state
=
2189 ash::wm::GetWindowState(new_browser
->window()->GetNativeWindow());
2190 // The new window should not be maximized because it gets docked or snapped.
2191 EXPECT_FALSE(new_browser
->window()->IsMaximized());
2192 // The new window should be docked and not snapped.
2193 EXPECT_TRUE(window_state
->IsDocked());
2194 EXPECT_FALSE(window_state
->IsSnapped());
2197 #endif // OS_CHROMEOS
2201 #if defined(USE_ASH) && defined(OS_CHROMEOS) // TODO(win_ash,linux_ash)
2202 INSTANTIATE_TEST_CASE_P(TabDragging
,
2203 DetachToBrowserInSeparateDisplayTabDragControllerTest
,
2204 ::testing::Values("mouse", "touch"));
2205 INSTANTIATE_TEST_CASE_P(TabDragging
,
2206 DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
2207 ::testing::Values("mouse"));
2208 INSTANTIATE_TEST_CASE_P(TabDragging
,
2209 DetachToBrowserTabDragControllerTest
,
2210 ::testing::Values("mouse", "touch"));
2211 INSTANTIATE_TEST_CASE_P(TabDragging
,
2212 DetachToBrowserTabDragControllerTestTouch
,
2213 ::testing::Values("touch"));
2214 #elif defined(USE_ASH)
2215 INSTANTIATE_TEST_CASE_P(TabDragging
,
2216 DetachToBrowserTabDragControllerTest
,
2217 ::testing::Values("mouse"));