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"
7 #include "ash/wm/window_state.h"
9 #include "base/callback.h"
10 #include "base/command_line.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/browser_iterator.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "chrome/browser/ui/host_desktop.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/browser/ui/views/frame/browser_view.h"
21 #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h"
22 #include "chrome/browser/ui/views/tabs/tab.h"
23 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
24 #include "chrome/browser/ui/views/tabs/tab_strip.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/test/base/in_process_browser_test.h"
27 #include "chrome/test/base/interactive_test_utils.h"
28 #include "chrome/test/base/ui_test_utils.h"
29 #include "content/public/browser/notification_details.h"
30 #include "content/public/browser/notification_observer.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/notification_source.h"
33 #include "content/public/browser/web_contents.h"
34 #include "ui/base/test/ui_controls.h"
35 #include "ui/gfx/screen.h"
36 #include "ui/views/view.h"
37 #include "ui/views/widget/widget.h"
39 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
40 #include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h"
41 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
45 #include "ash/ash_switches.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_state.h"
52 #include "ash/wm/window_util.h"
53 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
54 #include "ui/aura/client/screen_position_client.h"
55 #include "ui/aura/test/event_generator.h"
56 #include "ui/aura/window_event_dispatcher.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 virtual ~TabDragControllerInteractiveUITestUserData() {}
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 virtual 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 virtual ~QuitDraggingObserver() {}
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
: public aura::test::EventGeneratorDelegate
{
218 explicit ScreenEventGeneratorDelegate(aura::Window
* root_window
)
219 : root_window_(root_window
) {}
220 virtual ~ScreenEventGeneratorDelegate() {}
222 // EventGeneratorDelegate overrides:
223 virtual aura::WindowTreeHost
* GetHostAt(
224 const gfx::Point
& point
) const OVERRIDE
{
225 return root_window_
->GetHost();
228 virtual 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 virtual ~TestDesktopBrowserFrameAura() {}
258 void ReleaseCaptureOnNextClear() {
259 release_capture_
= true;
262 virtual 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 virtual ~TestNativeBrowserFrameFactory() {}
283 virtual NativeBrowserFrame
* Create(
284 BrowserFrame
* browser_frame
,
285 BrowserView
* browser_view
) OVERRIDE
{
286 return new TestDesktopBrowserFrameAura(browser_frame
, browser_view
);
290 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory
);
293 class TabDragCaptureLostTest
: public TabDragControllerTest
{
295 TabDragCaptureLostTest() {
296 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory
);
300 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest
);
303 // See description above for details.
304 IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest
, ReleaseCaptureOnDrag
) {
305 AddTabAndResetBrowser(browser());
307 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
308 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
309 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center
) &&
310 ui_test_utils::SendMouseEventsSync(
311 ui_controls::LEFT
, ui_controls::DOWN
));
312 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
313 TestDesktopBrowserFrameAura
* frame
=
314 static_cast<TestDesktopBrowserFrameAura
*>(
315 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()->
316 native_widget_private());
317 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus
318 // changes capture is released and the drag cancels.
319 frame
->ReleaseCaptureOnNextClear();
320 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center
));
321 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
324 IN_PROC_BROWSER_TEST_F(TabDragControllerTest
, GestureEndShouldEndDragTest
) {
325 AddTabAndResetBrowser(browser());
327 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
329 Tab
* tab1
= tab_strip
->tab_at(1);
330 gfx::Point
tab_1_center(tab1
->width() / 2, tab1
->height() / 2);
332 ui::GestureEvent
gesture_begin(ui::ET_GESTURE_BEGIN
, tab_1_center
.x(),
333 tab_1_center
.x(), 0, base::TimeDelta(),
334 ui::GestureEventDetails(ui::ET_GESTURE_BEGIN
, 0.0f
, 0.0f
), 0);
335 tab_strip
->MaybeStartDrag(tab1
, gesture_begin
,
336 tab_strip
->GetSelectionModel());
337 //tab_strip->tab_at(1)->OnGestureEvent(&gesture_begin);
338 EXPECT_TRUE(TabDragController::IsActive());
340 ui::GestureEvent
gesture_end(ui::ET_GESTURE_END
, tab_1_center
.x(),
341 tab_1_center
.x(), 0, base::TimeDelta(),
342 ui::GestureEventDetails(ui::ET_GESTURE_END
, 0.0f
, 0.0f
), 0);
343 tab_strip
->OnGestureEvent(&gesture_end
);
344 EXPECT_FALSE(TabDragController::IsActive());
345 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
350 class DetachToBrowserTabDragControllerTest
351 : public TabDragControllerTest
,
352 public ::testing::WithParamInterface
<const char*> {
354 DetachToBrowserTabDragControllerTest() {}
356 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
357 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
358 if (!docked_windows_enabled()) {
359 CommandLine::ForCurrentProcess()->AppendSwitch(
360 ash::switches::kAshDisableDockedWindows
);
365 virtual void SetUpOnMainThread() OVERRIDE
{
366 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
367 event_generator_
.reset(new aura::test::EventGenerator(
368 ash::Shell::GetPrimaryRootWindow()));
372 InputSource
input_source() const {
373 return strstr(GetParam(), "mouse") ?
374 INPUT_SOURCE_MOUSE
: INPUT_SOURCE_TOUCH
;
377 bool docked_windows_enabled() const {
378 return (strstr(GetParam(), "docked") != NULL
);
381 // Set root window from a point in screen coordinates
382 void SetEventGeneratorRootWindow(const gfx::Point
& point
) {
383 if (input_source() == INPUT_SOURCE_MOUSE
)
385 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
386 event_generator_
.reset(new aura::test::EventGenerator(
387 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point
))));
391 // The following methods update one of the mouse or touch input depending upon
393 bool PressInput(const gfx::Point
& location
) {
394 if (input_source() == INPUT_SOURCE_MOUSE
) {
395 return ui_test_utils::SendMouseMoveSync(location
) &&
396 ui_test_utils::SendMouseEventsSync(
397 ui_controls::LEFT
, ui_controls::DOWN
);
399 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
400 event_generator_
->set_current_location(location
);
401 event_generator_
->PressTouch();
409 // Second touch input is only used for touch sequence tests.
410 EXPECT_EQ(INPUT_SOURCE_TOUCH
, input_source());
411 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
412 event_generator_
->set_current_location(
413 event_generator_
->current_location());
414 event_generator_
->PressTouchId(1);
421 bool DragInputTo(const gfx::Point
& location
) {
422 if (input_source() == INPUT_SOURCE_MOUSE
)
423 return ui_test_utils::SendMouseMoveSync(location
);
424 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
425 event_generator_
->MoveTouch(location
);
432 bool DragInputToAsync(const gfx::Point
& location
) {
433 if (input_source() == INPUT_SOURCE_MOUSE
)
434 return ui_controls::SendMouseMove(location
.x(), location
.y());
435 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
436 event_generator_
->MoveTouch(location
);
443 bool DragInputToNotifyWhenDone(int x
,
445 const base::Closure
& task
) {
446 if (input_source() == INPUT_SOURCE_MOUSE
)
447 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
448 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
449 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
450 event_generator_
->MoveTouch(gfx::Point(x
, y
));
457 bool DragInputToDelayedNotifyWhenDone(int x
,
459 const base::Closure
& task
,
460 base::TimeDelta delay
) {
461 if (input_source() == INPUT_SOURCE_MOUSE
)
462 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
463 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
464 base::MessageLoop::current()->PostDelayedTask(FROM_HERE
, task
, delay
);
465 event_generator_
->MoveTouch(gfx::Point(x
, y
));
472 bool DragInput2ToNotifyWhenDone(int x
,
474 const base::Closure
& task
) {
475 if (input_source() == INPUT_SOURCE_MOUSE
)
476 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
477 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
478 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
479 event_generator_
->MoveTouchId(gfx::Point(x
, y
), 1);
486 bool ReleaseInput() {
487 if (input_source() == INPUT_SOURCE_MOUSE
) {
488 return ui_test_utils::SendMouseEventsSync(
489 ui_controls::LEFT
, ui_controls::UP
);
491 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
492 event_generator_
->ReleaseTouch();
499 bool ReleaseInput2() {
500 if (input_source() == INPUT_SOURCE_MOUSE
) {
501 return ui_test_utils::SendMouseEventsSync(
502 ui_controls::LEFT
, ui_controls::UP
);
504 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
505 event_generator_
->ReleaseTouchId(1);
512 bool ReleaseMouseAsync() {
513 return input_source() == INPUT_SOURCE_MOUSE
&&
514 ui_controls::SendMouseEvents(ui_controls::LEFT
, ui_controls::UP
);
517 void QuitWhenNotDragging() {
518 if (input_source() == INPUT_SOURCE_MOUSE
) {
519 // Schedule observer to quit message loop when done dragging. This has to
520 // be async so the message loop can run.
521 test::QuitWhenNotDraggingImpl();
522 base::MessageLoop::current()->Run();
524 // Touch events are sync, so we know we're not in a drag session. But some
525 // tests rely on the browser fully closing, which is async. So, run all
527 base::RunLoop run_loop
;
528 run_loop
.RunUntilIdle();
532 void AddBlankTabAndShow(Browser
* browser
) {
533 InProcessBrowserTest::AddBlankTabAndShow(browser
);
536 Browser
* browser() const { return InProcessBrowserTest::browser(); }
539 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
540 scoped_ptr
<aura::test::EventGenerator
> event_generator_
;
543 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest
);
546 // Creates a browser with two tabs, drags the second to the first.
547 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, DragInSameWindow
) {
548 // TODO(sky): this won't work with touch as it requires a long press.
549 if (input_source() == INPUT_SOURCE_TOUCH
) {
550 VLOG(1) << "Test is DISABLED for touch input.";
554 AddTabAndResetBrowser(browser());
556 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
557 TabStripModel
* model
= browser()->tab_strip_model();
559 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
560 ASSERT_TRUE(PressInput(tab_1_center
));
561 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
562 ASSERT_TRUE(DragInputTo(tab_0_center
));
563 ASSERT_TRUE(ReleaseInput());
564 EXPECT_EQ("1 0", IDString(model
));
565 EXPECT_FALSE(TabDragController::IsActive());
566 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
568 // The tab strip should no longer have capture because the drag was ended and
569 // mouse/touch was released.
570 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
575 // Invoked from the nested message loop.
576 void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
577 TabStrip
* not_attached_tab_strip
,
578 TabStrip
* target_tab_strip
) {
579 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
580 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
581 ASSERT_TRUE(TabDragController::IsActive());
583 // Drag to target_tab_strip. This should stop the nested loop from dragging
585 gfx::Point
target_point(target_tab_strip
->width() -1,
586 target_tab_strip
->height() / 2);
587 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
588 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
593 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
594 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
595 // compositor. crbug.com/331924
596 #define MAYBE_DragToSeparateWindow DISABLED_DragToSeparateWindow
598 #define MAYBE_DragToSeparateWindow DragToSeparateWindow
600 // Creates two browsers, drags from first into second.
601 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
602 MAYBE_DragToSeparateWindow
) {
603 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
605 // Add another tab to browser().
606 AddTabAndResetBrowser(browser());
608 // Create another browser.
609 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
610 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
612 // Move to the first tab and drag it enough so that it detaches, but not
613 // enough that it attaches to browser2.
614 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
615 ASSERT_TRUE(PressInput(tab_0_center
));
616 ASSERT_TRUE(DragInputToNotifyWhenDone(
617 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
618 base::Bind(&DragToSeparateWindowStep2
,
619 this, tab_strip
, tab_strip2
)));
620 QuitWhenNotDragging();
622 // Should now be attached to tab_strip2.
623 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
624 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
625 ASSERT_TRUE(TabDragController::IsActive());
626 EXPECT_FALSE(GetIsDragged(browser()));
628 // Release mouse or touch, stopping the drag session.
629 ASSERT_TRUE(ReleaseInput());
630 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
631 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
632 ASSERT_FALSE(TabDragController::IsActive());
633 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
634 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
635 EXPECT_FALSE(GetIsDragged(browser2
));
637 // Both windows should not be maximized
638 EXPECT_FALSE(browser()->window()->IsMaximized());
639 EXPECT_FALSE(browser2
->window()->IsMaximized());
641 // The tab strip should no longer have capture because the drag was ended and
642 // mouse/touch was released.
643 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
644 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
649 void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest
* test
) {
650 if (test
->input_source() == INPUT_SOURCE_TOUCH
)
651 ASSERT_TRUE(test
->ReleaseInput());
654 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
655 bool IsWindowPositionManaged(aura::Window
* window
) {
656 return ash::wm::GetWindowState(window
)->window_position_managed();
658 bool HasUserChangedWindowPositionOrSize(aura::Window
* window
) {
659 return ash::wm::GetWindowState(window
)->bounds_changed_by_user();
662 bool IsWindowPositionManaged(gfx::NativeWindow window
) {
665 bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window
) {
672 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
673 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
674 // compositor. crbug.com/331924
675 #define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow
677 #define MAYBE_DetachToOwnWindow DetachToOwnWindow
679 // Drags from browser to separate window and releases mouse.
680 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
681 MAYBE_DetachToOwnWindow
) {
682 const gfx::Rect
initial_bounds(browser()->window()->GetBounds());
684 AddTabAndResetBrowser(browser());
685 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
687 // Move to the first tab and drag it enough so that it detaches.
688 gfx::Point
tab_0_center(
689 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
690 ASSERT_TRUE(PressInput(tab_0_center
));
691 ASSERT_TRUE(DragInputToNotifyWhenDone(
692 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
693 base::Bind(&DetachToOwnWindowStep2
, this)));
694 if (input_source() == INPUT_SOURCE_MOUSE
) {
695 ASSERT_TRUE(ReleaseMouseAsync());
696 QuitWhenNotDragging();
699 // Should no longer be dragging.
700 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
701 ASSERT_FALSE(TabDragController::IsActive());
703 // There should now be another browser.
704 ASSERT_EQ(2u, native_browser_list
->size());
705 Browser
* new_browser
= native_browser_list
->get(1);
706 ASSERT_TRUE(new_browser
->window()->IsActive());
707 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
708 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
710 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
711 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
713 // The bounds of the initial window should not have changed.
714 EXPECT_EQ(initial_bounds
.ToString(),
715 browser()->window()->GetBounds().ToString());
717 EXPECT_FALSE(GetIsDragged(browser()));
718 EXPECT_FALSE(GetIsDragged(new_browser
));
719 // After this both windows should still be manageable.
720 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
721 EXPECT_TRUE(IsWindowPositionManaged(
722 new_browser
->window()->GetNativeWindow()));
724 // Both windows should not be maximized
725 EXPECT_FALSE(browser()->window()->IsMaximized());
726 EXPECT_FALSE(new_browser
->window()->IsMaximized());
728 // The tab strip should no longer have capture because the drag was ended and
729 // mouse/touch was released.
730 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
731 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
734 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
735 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
736 // compositor. crbug.com/331924
737 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
738 DISABLED_DetachToOwnWindowFromMaximizedWindow
740 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
741 DetachToOwnWindowFromMaximizedWindow
743 // Drags from browser to a separate window and releases mouse.
744 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
745 MAYBE_DetachToOwnWindowFromMaximizedWindow
) {
746 // Maximize the initial browser window.
747 browser()->window()->Maximize();
748 ASSERT_TRUE(browser()->window()->IsMaximized());
751 AddTabAndResetBrowser(browser());
752 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
754 // Move to the first tab and drag it enough so that it detaches.
755 gfx::Point
tab_0_center(
756 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
757 ASSERT_TRUE(PressInput(tab_0_center
));
758 ASSERT_TRUE(DragInputToNotifyWhenDone(
759 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
760 base::Bind(&DetachToOwnWindowStep2
, this)));
761 if (input_source() == INPUT_SOURCE_MOUSE
) {
762 ASSERT_TRUE(ReleaseMouseAsync());
763 QuitWhenNotDragging();
766 // Should no longer be dragging.
767 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
768 ASSERT_FALSE(TabDragController::IsActive());
770 // There should now be another browser.
771 ASSERT_EQ(2u, native_browser_list
->size());
772 Browser
* new_browser
= native_browser_list
->get(1);
773 ASSERT_TRUE(new_browser
->window()->IsActive());
774 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
775 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
777 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
778 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
780 // The bounds of the initial window should not have changed.
781 EXPECT_TRUE(browser()->window()->IsMaximized());
783 EXPECT_FALSE(GetIsDragged(browser()));
784 EXPECT_FALSE(GetIsDragged(new_browser
));
785 // After this both windows should still be manageable.
786 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
787 EXPECT_TRUE(IsWindowPositionManaged(
788 new_browser
->window()->GetNativeWindow()));
790 // The new window should be maximized.
791 EXPECT_TRUE(new_browser
->window()->IsMaximized());
794 // Deletes a tab being dragged before the user moved enough to start a drag.
795 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
796 DeleteBeforeStartedDragging
) {
798 AddTabAndResetBrowser(browser());
799 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
801 // Click on the first tab, but don't move it.
802 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
803 ASSERT_TRUE(PressInput(tab_0_center
));
805 // Should be dragging.
806 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
807 ASSERT_TRUE(TabDragController::IsActive());
809 // Delete the tab being dragged.
810 delete browser()->tab_strip_model()->GetWebContentsAt(0);
812 // Should have canceled dragging.
813 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
814 ASSERT_FALSE(TabDragController::IsActive());
816 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
817 EXPECT_FALSE(GetIsDragged(browser()));
820 #if defined(OS_CHROMEOS)
821 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
822 // compositor. crbug.com/331924
823 #define MAYBE_DeleteTabWhileAttached DISABLED_DeleteTabWhileAttached
825 #define MAYBE_DeleteTabWhileAttached DeleteTabWhileAttached
827 // Deletes a tab being dragged while still attached.
828 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
829 MAYBE_DeleteTabWhileAttached
) {
830 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
831 // compositor. crbug.com/331924
832 if (input_source() == INPUT_SOURCE_MOUSE
) {
833 VLOG(1) << "Test is DISABLED for mouse input.";
838 AddTabAndResetBrowser(browser());
839 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
841 // Click on the first tab and move it enough so that it starts dragging but is
843 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
844 ASSERT_TRUE(PressInput(tab_0_center
));
845 ASSERT_TRUE(DragInputTo(
846 gfx::Point(tab_0_center
.x() + 20, tab_0_center
.y())));
848 // Should be dragging.
849 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
850 ASSERT_TRUE(TabDragController::IsActive());
852 // Delete the tab being dragged.
853 delete browser()->tab_strip_model()->GetWebContentsAt(0);
855 // Should have canceled dragging.
856 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
857 ASSERT_FALSE(TabDragController::IsActive());
859 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
861 EXPECT_FALSE(GetIsDragged(browser()));
866 void DeleteWhileDetachedStep2(WebContents
* tab
) {
872 #if defined(OS_CHROMEOS)
873 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
874 // compositor. crbug.com/331924
875 #define MAYBE_DeleteTabWhileDetached DISABLED_DeleteTabWhileDetached
877 #define MAYBE_DeleteTabWhileDetached DeleteTabWhileDetached
879 // Deletes a tab being dragged after dragging a tab so that a new window is
881 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
882 MAYBE_DeleteTabWhileDetached
) {
884 AddTabAndResetBrowser(browser());
885 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
887 // Move to the first tab and drag it enough so that it detaches.
888 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
889 WebContents
* to_delete
=
890 browser()->tab_strip_model()->GetWebContentsAt(0);
891 ASSERT_TRUE(PressInput(tab_0_center
));
892 ASSERT_TRUE(DragInputToNotifyWhenDone(
893 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
894 base::Bind(&DeleteWhileDetachedStep2
, to_delete
)));
895 QuitWhenNotDragging();
897 // Should not be dragging.
898 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
899 ASSERT_FALSE(TabDragController::IsActive());
901 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
903 EXPECT_FALSE(GetIsDragged(browser()));
908 void DeleteSourceDetachedStep2(WebContents
* tab
,
909 const BrowserList
* browser_list
) {
910 ASSERT_EQ(2u, browser_list
->size());
911 Browser
* new_browser
= browser_list
->get(1);
912 // This ends up closing the source window.
915 ui_controls::SendKeyPress(new_browser
->window()->GetNativeWindow(),
916 ui::VKEY_ESCAPE
, false, false, false, false);
921 #if defined(OS_CHROMEOS)
922 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
923 // compositor. crbug.com/331924
924 #define MAYBE_DeleteSourceDetached DISABLED_DeleteSourceDetached
926 #define MAYBE_DeleteSourceDetached DeleteSourceDetached
928 // Detaches a tab and while detached deletes a tab from the source so that the
929 // source window closes then presses escape to cancel the drag.
930 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
931 MAYBE_DeleteSourceDetached
) {
933 AddTabAndResetBrowser(browser());
934 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
936 // Move to the first tab and drag it enough so that it detaches.
937 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
938 WebContents
* to_delete
= browser()->tab_strip_model()->GetWebContentsAt(1);
939 ASSERT_TRUE(PressInput(tab_0_center
));
940 ASSERT_TRUE(DragInputToNotifyWhenDone(
941 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
942 base::Bind(&DeleteSourceDetachedStep2
, to_delete
, native_browser_list
)));
943 QuitWhenNotDragging();
945 // Should not be dragging.
946 ASSERT_EQ(1u, native_browser_list
->size());
947 Browser
* new_browser
= native_browser_list
->get(0);
948 ASSERT_FALSE(GetTabStripForBrowser(new_browser
)->IsDragSessionActive());
949 ASSERT_FALSE(TabDragController::IsActive());
951 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
953 EXPECT_FALSE(GetIsDragged(new_browser
));
955 // Remaining browser window should not be maximized
956 EXPECT_FALSE(new_browser
->window()->IsMaximized());
961 void PressEscapeWhileDetachedStep2(const BrowserList
* browser_list
) {
962 ASSERT_EQ(2u, browser_list
->size());
963 Browser
* new_browser
= browser_list
->get(1);
964 ui_controls::SendKeyPress(
965 new_browser
->window()->GetNativeWindow(), ui::VKEY_ESCAPE
, false, false,
971 #if defined(OS_CHROMEOS)
972 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
973 // compositor. crbug.com/331924
974 #define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached
976 #define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached
978 // This is disabled until NativeViewHost::Detach really detaches.
979 // Detaches a tab and while detached presses escape to revert the drag.
980 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
981 MAYBE_PressEscapeWhileDetached
) {
983 AddTabAndResetBrowser(browser());
984 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
986 // Move to the first tab and drag it enough so that it detaches.
987 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
988 ASSERT_TRUE(PressInput(tab_0_center
));
989 ASSERT_TRUE(DragInputToNotifyWhenDone(
990 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
991 base::Bind(&PressEscapeWhileDetachedStep2
, native_browser_list
)));
992 QuitWhenNotDragging();
994 // Should not be dragging.
995 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
996 ASSERT_FALSE(TabDragController::IsActive());
998 // And there should only be one window.
999 EXPECT_EQ(1u, native_browser_list
->size());
1001 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1003 // Remaining browser window should not be maximized
1004 EXPECT_FALSE(browser()->window()->IsMaximized());
1006 // The tab strip should no longer have capture because the drag was ended and
1007 // mouse/touch was released.
1008 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
1013 void DragAllStep2(DetachToBrowserTabDragControllerTest
* test
,
1014 const BrowserList
* browser_list
) {
1015 // Should only be one window.
1016 ASSERT_EQ(1u, browser_list
->size());
1017 if (test
->input_source() == INPUT_SOURCE_TOUCH
) {
1018 ASSERT_TRUE(test
->ReleaseInput());
1020 ASSERT_TRUE(test
->ReleaseMouseAsync());
1026 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1027 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1028 // compositor. crbug.com/331924
1029 #define MAYBE_DragAll DISABLED_DragAll
1031 #define MAYBE_DragAll DragAll
1033 // Selects multiple tabs and starts dragging the window.
1034 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, MAYBE_DragAll
) {
1036 AddTabAndResetBrowser(browser());
1037 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1038 browser()->tab_strip_model()->AddTabAtToSelection(0);
1039 browser()->tab_strip_model()->AddTabAtToSelection(1);
1041 // Move to the first tab and drag it enough so that it would normally
1043 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1044 ASSERT_TRUE(PressInput(tab_0_center
));
1045 ASSERT_TRUE(DragInputToNotifyWhenDone(
1046 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1047 base::Bind(&DragAllStep2
, this, native_browser_list
)));
1048 QuitWhenNotDragging();
1050 // Should not be dragging.
1051 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1052 ASSERT_FALSE(TabDragController::IsActive());
1054 // And there should only be one window.
1055 EXPECT_EQ(1u, native_browser_list
->size());
1057 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1059 EXPECT_FALSE(GetIsDragged(browser()));
1061 // Remaining browser window should not be maximized
1062 EXPECT_FALSE(browser()->window()->IsMaximized());
1067 // Invoked from the nested message loop.
1068 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1069 TabStrip
* attached_tab_strip
,
1070 TabStrip
* target_tab_strip
,
1071 const BrowserList
* browser_list
) {
1072 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1073 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1074 ASSERT_TRUE(TabDragController::IsActive());
1075 ASSERT_EQ(2u, browser_list
->size());
1077 // Drag to target_tab_strip. This should stop the nested loop from dragging
1079 gfx::Point
target_point(target_tab_strip
->width() - 1,
1080 target_tab_strip
->height() / 2);
1081 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1082 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1087 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1088 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1089 // compositor. crbug.com/331924
1090 #define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow
1092 #define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow
1094 // Creates two browsers, selects all tabs in first and drags into second.
1095 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1096 MAYBE_DragAllToSeparateWindow
) {
1097 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1099 // Add another tab to browser().
1100 AddTabAndResetBrowser(browser());
1102 // Create another browser.
1103 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1104 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1106 browser()->tab_strip_model()->AddTabAtToSelection(0);
1107 browser()->tab_strip_model()->AddTabAtToSelection(1);
1109 // Move to the first tab and drag it enough so that it detaches, but not
1110 // enough that it attaches to browser2.
1111 gfx::Point
tab_0_center(
1112 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1113 ASSERT_TRUE(PressInput(tab_0_center
));
1114 ASSERT_TRUE(DragInputToNotifyWhenDone(
1115 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1116 base::Bind(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1117 native_browser_list
)));
1118 QuitWhenNotDragging();
1120 // Should now be attached to tab_strip2.
1121 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1122 ASSERT_TRUE(TabDragController::IsActive());
1123 ASSERT_EQ(1u, native_browser_list
->size());
1125 // Release the mouse, stopping the drag session.
1126 ASSERT_TRUE(ReleaseInput());
1127 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1128 ASSERT_FALSE(TabDragController::IsActive());
1129 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1131 EXPECT_FALSE(GetIsDragged(browser2
));
1133 // Remaining browser window should not be maximized
1134 EXPECT_FALSE(browser2
->window()->IsMaximized());
1139 // Invoked from the nested message loop.
1140 void DragAllToSeparateWindowAndCancelStep2(
1141 DetachToBrowserTabDragControllerTest
* test
,
1142 TabStrip
* attached_tab_strip
,
1143 TabStrip
* target_tab_strip
,
1144 const BrowserList
* browser_list
) {
1145 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1146 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1147 ASSERT_TRUE(TabDragController::IsActive());
1148 ASSERT_EQ(2u, browser_list
->size());
1150 // Drag to target_tab_strip. This should stop the nested loop from dragging
1152 gfx::Point
target_point(target_tab_strip
->width() - 1,
1153 target_tab_strip
->height() / 2);
1154 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1155 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1160 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1161 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1162 // compositor. crbug.com/331924
1163 #define MAYBE_DragAllToSeparateWindowAndCancel \
1164 DISABLED_DragAllToSeparateWindowAndCancel
1166 #define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel
1168 // Creates two browsers, selects all tabs in first, drags into second, then hits
1170 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1171 MAYBE_DragAllToSeparateWindowAndCancel
) {
1172 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1174 // Add another tab to browser().
1175 AddTabAndResetBrowser(browser());
1177 // Create another browser.
1178 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1179 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1181 browser()->tab_strip_model()->AddTabAtToSelection(0);
1182 browser()->tab_strip_model()->AddTabAtToSelection(1);
1184 // Move to the first tab and drag it enough so that it detaches, but not
1185 // enough that it attaches to browser2.
1186 gfx::Point
tab_0_center(
1187 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1188 ASSERT_TRUE(PressInput(tab_0_center
));
1189 ASSERT_TRUE(DragInputToNotifyWhenDone(
1190 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1191 base::Bind(&DragAllToSeparateWindowAndCancelStep2
, this,
1192 tab_strip
, tab_strip2
, native_browser_list
)));
1193 QuitWhenNotDragging();
1195 // Should now be attached to tab_strip2.
1196 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1197 ASSERT_TRUE(TabDragController::IsActive());
1198 ASSERT_EQ(1u, native_browser_list
->size());
1201 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
1202 browser2
, ui::VKEY_ESCAPE
, false, false, false, false));
1204 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1205 ASSERT_FALSE(TabDragController::IsActive());
1206 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1208 // browser() will have been destroyed, but browser2 should remain.
1209 ASSERT_EQ(1u, native_browser_list
->size());
1211 EXPECT_FALSE(GetIsDragged(browser2
));
1213 // Remaining browser window should not be maximized
1214 EXPECT_FALSE(browser2
->window()->IsMaximized());
1217 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1218 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1219 // compositor. crbug.com/331924
1220 #define MAYBE_DragDirectlyToSecondWindow DISABLED_DragDirectlyToSecondWindow
1222 #define MAYBE_DragDirectlyToSecondWindow DragDirectlyToSecondWindow
1224 // Creates two browsers, drags from first into the second in such a way that
1225 // no detaching should happen.
1226 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1227 MAYBE_DragDirectlyToSecondWindow
) {
1228 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1230 // Add another tab to browser().
1231 AddTabAndResetBrowser(browser());
1233 // Create another browser.
1234 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1235 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1237 // Move the tabstrip down enough so that we can detach.
1238 gfx::Rect
bounds(browser2
->window()->GetBounds());
1239 bounds
.Offset(0, 100);
1240 browser2
->window()->SetBounds(bounds
);
1242 // Move to the first tab and drag it enough so that it detaches, but not
1243 // enough that it attaches to browser2.
1244 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1245 ASSERT_TRUE(PressInput(tab_0_center
));
1247 gfx::Point
b2_location(5, 0);
1248 views::View::ConvertPointToScreen(tab_strip2
, &b2_location
);
1249 ASSERT_TRUE(DragInputTo(b2_location
));
1251 // Should now be attached to tab_strip2.
1252 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1253 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1254 ASSERT_TRUE(TabDragController::IsActive());
1256 // Release the mouse, stopping the drag session.
1257 ASSERT_TRUE(ReleaseInput());
1258 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1259 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1260 ASSERT_FALSE(TabDragController::IsActive());
1261 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1262 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1264 EXPECT_FALSE(GetIsDragged(browser()));
1265 EXPECT_FALSE(GetIsDragged(browser2
));
1267 // Both windows should not be maximized
1268 EXPECT_FALSE(browser()->window()->IsMaximized());
1269 EXPECT_FALSE(browser2
->window()->IsMaximized());
1272 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1273 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1274 // compositor. crbug.com/331924
1275 #define MAYBE_DragSingleTabToSeparateWindow \
1276 DISABLED_DragSingleTabToSeparateWindow
1278 #define MAYBE_DragSingleTabToSeparateWindow DragSingleTabToSeparateWindow
1280 // Creates two browsers, the first browser has a single tab and drags into the
1282 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1283 MAYBE_DragSingleTabToSeparateWindow
) {
1284 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1286 ResetIDs(browser()->tab_strip_model(), 0);
1288 // Create another browser.
1289 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1290 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1291 const gfx::Rect
initial_bounds(browser2
->window()->GetBounds());
1293 // Move to the first tab and drag it enough so that it detaches, but not
1294 // enough that it attaches to browser2.
1295 gfx::Point
tab_0_center(
1296 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1297 ASSERT_TRUE(PressInput(tab_0_center
));
1298 ASSERT_TRUE(DragInputToNotifyWhenDone(
1299 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1300 base::Bind(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1301 native_browser_list
)));
1302 QuitWhenNotDragging();
1304 // Should now be attached to tab_strip2.
1305 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1306 ASSERT_TRUE(TabDragController::IsActive());
1307 ASSERT_EQ(1u, native_browser_list
->size());
1309 // Release the mouse, stopping the drag session.
1310 ASSERT_TRUE(ReleaseInput());
1311 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1312 ASSERT_FALSE(TabDragController::IsActive());
1313 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
1315 EXPECT_FALSE(GetIsDragged(browser2
));
1317 // Remaining browser window should not be maximized
1318 EXPECT_FALSE(browser2
->window()->IsMaximized());
1320 // Make sure that the window is still managed and not user moved.
1321 EXPECT_TRUE(IsWindowPositionManaged(browser2
->window()->GetNativeWindow()));
1322 EXPECT_FALSE(HasUserChangedWindowPositionOrSize(
1323 browser2
->window()->GetNativeWindow()));
1324 // Also make sure that the drag to window position has not changed.
1325 EXPECT_EQ(initial_bounds
.ToString(),
1326 browser2
->window()->GetBounds().ToString());
1331 // Invoked from the nested message loop.
1332 void CancelOnNewTabWhenDraggingStep2(
1333 DetachToBrowserTabDragControllerTest
* test
,
1334 const BrowserList
* browser_list
) {
1335 ASSERT_TRUE(TabDragController::IsActive());
1336 ASSERT_EQ(2u, browser_list
->size());
1338 // Add another tab. This should trigger exiting the nested loop.
1339 test
->AddBlankTabAndShow(browser_list
->GetLastActive());
1344 #if defined(OS_CHROMEOS)
1345 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1346 // compositor. crbug.com/331924
1347 #define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging
1349 #define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging
1351 // Adds another tab, detaches into separate window, adds another tab and
1352 // verifies the run loop ends.
1353 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1354 MAYBE_CancelOnNewTabWhenDragging
) {
1355 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1357 // Add another tab to browser().
1358 AddTabAndResetBrowser(browser());
1360 // Move to the first tab and drag it enough so that it detaches.
1361 gfx::Point
tab_0_center(
1362 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1363 ASSERT_TRUE(PressInput(tab_0_center
));
1364 ASSERT_TRUE(DragInputToNotifyWhenDone(
1365 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1366 base::Bind(&CancelOnNewTabWhenDraggingStep2
, this, native_browser_list
)));
1367 QuitWhenNotDragging();
1369 // Should be two windows and not dragging.
1370 ASSERT_FALSE(TabDragController::IsActive());
1371 ASSERT_EQ(2u, native_browser_list
->size());
1372 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
1373 EXPECT_FALSE(GetIsDragged(*it
));
1374 // Should not be maximized
1375 EXPECT_FALSE(it
->window()->IsMaximized());
1379 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
1383 void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1385 TabStrip
* tab_strip
,
1386 const BrowserList
* browser_list
) {
1387 // There should be another browser.
1388 ASSERT_EQ(2u, browser_list
->size());
1389 Browser
* new_browser
= browser_list
->get(1);
1390 EXPECT_NE(browser
, new_browser
);
1391 ASSERT_TRUE(new_browser
->window()->IsActive());
1392 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1394 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1395 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1397 // Both windows should be visible.
1398 EXPECT_TRUE(tab_strip
->GetWidget()->IsVisible());
1399 EXPECT_TRUE(tab_strip2
->GetWidget()->IsVisible());
1402 ASSERT_TRUE(test
->ReleaseInput());
1407 #if defined(OS_CHROMEOS)
1408 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1409 // compositor. crbug.com/331924
1410 #define MAYBE_DragInMaximizedWindow DISABLED_DragInMaximizedWindow
1412 #define MAYBE_DragInMaximizedWindow DragInMaximizedWindow
1414 // Creates a browser with two tabs, maximizes it, drags the tab out.
1415 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1416 MAYBE_DragInMaximizedWindow
) {
1417 AddTabAndResetBrowser(browser());
1418 browser()->window()->Maximize();
1420 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1422 // Move to the first tab and drag it enough so that it detaches.
1423 gfx::Point
tab_0_center(
1424 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1425 ASSERT_TRUE(PressInput(tab_0_center
));
1426 ASSERT_TRUE(DragInputToNotifyWhenDone(
1427 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1428 base::Bind(&DragInMaximizedWindowStep2
, this, browser(), tab_strip
,
1429 native_browser_list
)));
1430 QuitWhenNotDragging();
1432 ASSERT_FALSE(TabDragController::IsActive());
1434 // Should be two browsers.
1435 ASSERT_EQ(2u, native_browser_list
->size());
1436 Browser
* new_browser
= native_browser_list
->get(1);
1437 ASSERT_TRUE(new_browser
->window()->IsActive());
1439 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible());
1440 EXPECT_TRUE(new_browser
->window()->GetNativeWindow()->IsVisible());
1442 EXPECT_FALSE(GetIsDragged(browser()));
1443 EXPECT_FALSE(GetIsDragged(new_browser
));
1445 // The source window should be maximized.
1446 EXPECT_TRUE(browser()->window()->IsMaximized());
1447 // The new window should be maximized.
1448 EXPECT_TRUE(new_browser
->window()->IsMaximized());
1451 // Subclass of DetachToBrowserTabDragControllerTest that
1452 // creates multiple displays.
1453 class DetachToBrowserInSeparateDisplayTabDragControllerTest
1454 : public DetachToBrowserTabDragControllerTest
{
1456 DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1457 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1459 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
1460 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1461 // Make screens sufficiently wide to host 2 browsers side by side.
1462 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1463 "0+0-600x600,601+0-600x600");
1467 DISALLOW_COPY_AND_ASSIGN(
1468 DetachToBrowserInSeparateDisplayTabDragControllerTest
);
1471 // Subclass of DetachToBrowserTabDragControllerTest that runs tests only with
1473 class DetachToBrowserTabDragControllerTestTouch
1474 : public DetachToBrowserTabDragControllerTest
{
1476 DetachToBrowserTabDragControllerTestTouch() {}
1477 virtual ~DetachToBrowserTabDragControllerTestTouch() {}
1480 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch
);
1485 void DragSingleTabToSeparateWindowInSecondDisplayStep3(
1486 DetachToBrowserTabDragControllerTest
* test
) {
1487 ASSERT_TRUE(test
->ReleaseInput());
1490 void DragSingleTabToSeparateWindowInSecondDisplayStep2(
1491 DetachToBrowserTabDragControllerTest
* test
,
1492 const gfx::Point
& target_point
) {
1493 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
1494 target_point
.x(), target_point
.y(),
1495 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3
, test
)));
1500 #if defined(OS_CHROMEOS)
1501 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1502 // compositor. crbug.com/331924
1503 #define MAYBE_DragSingleTabToSeparateWindowInSecondDisplay \
1504 DISABLED_DragSingleTabToSeparateWindowInSecondDisplay
1506 #define MAYBE_DragSingleTabToSeparateWindowInSecondDisplay \
1507 DragSingleTabToSeparateWindowInSecondDisplay
1509 // Drags from browser to a second display and releases input.
1510 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1511 MAYBE_DragSingleTabToSeparateWindowInSecondDisplay
) {
1513 AddTabAndResetBrowser(browser());
1514 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1516 // Move to the first tab and drag it enough so that it detaches.
1517 // Then drag it to the final destination on the second screen.
1518 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1519 ASSERT_TRUE(PressInput(tab_0_center
));
1520 ASSERT_TRUE(DragInputToNotifyWhenDone(
1521 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1522 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2
,
1523 this, gfx::Point(600 + tab_0_center
.x(),
1525 + GetDetachY(tab_strip
)))));
1526 QuitWhenNotDragging();
1528 // Should no longer be dragging.
1529 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1530 ASSERT_FALSE(TabDragController::IsActive());
1532 // There should now be another browser.
1533 ASSERT_EQ(2u, native_browser_list
->size());
1534 Browser
* new_browser
= native_browser_list
->get(1);
1535 ASSERT_TRUE(new_browser
->window()->IsActive());
1536 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1537 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1539 // This other browser should be on the second screen (with mouse drag)
1540 // With the touch input the browser cannot be dragged from one screen
1541 // to another and the window stays on the first screen.
1542 if (input_source() == INPUT_SOURCE_MOUSE
) {
1543 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1544 ASSERT_EQ(2u, roots
.size());
1545 aura::Window
* second_root
= roots
[1];
1546 EXPECT_EQ(second_root
,
1547 new_browser
->window()->GetNativeWindow()->GetRootWindow());
1550 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
1551 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1553 // Both windows should not be maximized
1554 EXPECT_FALSE(browser()->window()->IsMaximized());
1555 EXPECT_FALSE(new_browser
->window()->IsMaximized());
1560 // Invoked from the nested message loop.
1561 void DragTabToWindowInSeparateDisplayStep2(
1562 DetachToBrowserTabDragControllerTest
* test
,
1563 TabStrip
* not_attached_tab_strip
,
1564 TabStrip
* target_tab_strip
) {
1565 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
1566 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1567 ASSERT_TRUE(TabDragController::IsActive());
1569 // Drag to target_tab_strip. This should stop the nested loop from dragging
1571 gfx::Point
target_point(
1572 GetCenterInScreenCoordinates(target_tab_strip
->tab_at(0)));
1574 // Move it close to the beginning of the target tabstrip.
1576 target_point
.x() - target_tab_strip
->tab_at(0)->width() / 2 + 10);
1577 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1582 #if defined(OS_CHROMEOS)
1583 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1584 // compositor. crbug.com/331924
1585 #define MAYBE_DragTabToWindowInSeparateDisplay \
1586 DISABLED_DragTabToWindowInSeparateDisplay
1588 #define MAYBE_DragTabToWindowInSeparateDisplay DragTabToWindowInSeparateDisplay
1590 // Drags from browser to another browser on a second display and releases input.
1591 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1592 MAYBE_DragTabToWindowInSeparateDisplay
) {
1594 AddTabAndResetBrowser(browser());
1595 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1597 // Create another browser.
1598 Browser
* browser2
= CreateBrowser(browser()->profile());
1599 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1600 ResetIDs(browser2
->tab_strip_model(), 100);
1602 // Move the second browser to the second display.
1603 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1604 ASSERT_EQ(2u, roots
.size());
1605 aura::Window
* second_root
= roots
[1];
1606 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1607 second_root
).work_area();
1608 browser2
->window()->SetBounds(work_area
);
1609 EXPECT_EQ(second_root
,
1610 browser2
->window()->GetNativeWindow()->GetRootWindow());
1612 // Move to the first tab and drag it enough so that it detaches, but not
1613 // enough that it attaches to browser2.
1614 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1615 ASSERT_TRUE(PressInput(tab_0_center
));
1616 ASSERT_TRUE(DragInputToNotifyWhenDone(
1617 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1618 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1619 this, tab_strip
, tab_strip2
)));
1620 QuitWhenNotDragging();
1622 // Should now be attached to tab_strip2.
1623 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1624 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1625 ASSERT_TRUE(TabDragController::IsActive());
1627 // Release the mouse, stopping the drag session.
1628 ASSERT_TRUE(ReleaseInput());
1629 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1630 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1631 ASSERT_FALSE(TabDragController::IsActive());
1632 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1633 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1635 // Both windows should not be maximized
1636 EXPECT_FALSE(browser()->window()->IsMaximized());
1637 EXPECT_FALSE(browser2
->window()->IsMaximized());
1640 #if defined(OS_CHROMEOS)
1641 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1642 // compositor. crbug.com/331924
1643 #define MAYBE_DragTabToWindowOnSecondDisplay \
1644 DISABLED_DragTabToWindowOnSecondDisplay
1646 #define MAYBE_DragTabToWindowOnSecondDisplay DragTabToWindowOnSecondDisplay
1648 // Drags from browser to another browser on a second display and releases input.
1649 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1650 MAYBE_DragTabToWindowOnSecondDisplay
) {
1652 AddTabAndResetBrowser(browser());
1653 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1655 // Create another browser.
1656 Browser
* browser2
= CreateBrowser(browser()->profile());
1657 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1658 ResetIDs(browser2
->tab_strip_model(), 100);
1660 // Move both browsers to the second display.
1661 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1662 ASSERT_EQ(2u, roots
.size());
1663 aura::Window
* second_root
= roots
[1];
1664 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1665 second_root
).work_area();
1666 browser()->window()->SetBounds(work_area
);
1668 // position both browser windows side by side on the second screen.
1669 gfx::Rect
work_area2(work_area
);
1670 work_area
.set_width(work_area
.width()/2);
1671 browser()->window()->SetBounds(work_area
);
1672 work_area2
.set_x(work_area2
.x() + work_area2
.width()/2);
1673 work_area2
.set_width(work_area2
.width()/2);
1674 browser2
->window()->SetBounds(work_area2
);
1675 EXPECT_EQ(second_root
,
1676 browser()->window()->GetNativeWindow()->GetRootWindow());
1677 EXPECT_EQ(second_root
,
1678 browser2
->window()->GetNativeWindow()->GetRootWindow());
1680 // Move to the first tab and drag it enough so that it detaches, but not
1681 // enough that it attaches to browser2.
1682 // SetEventGeneratorRootWindow sets correct (second) RootWindow
1683 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1684 SetEventGeneratorRootWindow(tab_0_center
);
1685 ASSERT_TRUE(PressInput(tab_0_center
));
1686 ASSERT_TRUE(DragInputToNotifyWhenDone(
1687 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1688 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1689 this, tab_strip
, tab_strip2
)));
1690 QuitWhenNotDragging();
1692 // Should now be attached to tab_strip2.
1693 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1694 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1695 ASSERT_TRUE(TabDragController::IsActive());
1697 // Release the mouse, stopping the drag session.
1698 ASSERT_TRUE(ReleaseInput());
1699 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1700 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1701 ASSERT_FALSE(TabDragController::IsActive());
1702 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1703 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1705 // Both windows should not be maximized
1706 EXPECT_FALSE(browser()->window()->IsMaximized());
1707 EXPECT_FALSE(browser2
->window()->IsMaximized());
1710 #if defined(OS_CHROMEOS)
1711 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1712 // compositor. crbug.com/331924
1713 #define MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay \
1714 DISABLED_DragMaxTabToNonMaxWindowInSeparateDisplay
1716 #define MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay \
1717 DragMaxTabToNonMaxWindowInSeparateDisplay
1719 // Drags from a maximized browser to another non-maximized browser on a second
1720 // display and releases input.
1721 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1722 MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay
) {
1724 AddTabAndResetBrowser(browser());
1725 browser()->window()->Maximize();
1726 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1728 // Create another browser on the second display.
1729 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1730 ASSERT_EQ(2u, roots
.size());
1731 aura::Window
* first_root
= roots
[0];
1732 aura::Window
* second_root
= roots
[1];
1733 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1734 second_root
).work_area();
1735 work_area
.Inset(20,20,20,60);
1736 Browser::CreateParams
params(browser()->profile(),
1737 browser()->host_desktop_type());
1738 params
.initial_show_state
= ui::SHOW_STATE_NORMAL
;
1739 params
.initial_bounds
= work_area
;
1740 Browser
* browser2
= new Browser(params
);
1741 AddBlankTabAndShow(browser2
);
1743 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1744 ResetIDs(browser2
->tab_strip_model(), 100);
1746 EXPECT_EQ(second_root
,
1747 browser2
->window()->GetNativeWindow()->GetRootWindow());
1748 EXPECT_EQ(first_root
,
1749 browser()->window()->GetNativeWindow()->GetRootWindow());
1750 EXPECT_EQ(2, tab_strip
->tab_count());
1751 EXPECT_EQ(1, tab_strip2
->tab_count());
1753 // Move to the first tab and drag it enough so that it detaches, but not
1754 // enough that it attaches to browser2.
1755 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1756 ASSERT_TRUE(PressInput(tab_0_center
));
1757 ASSERT_TRUE(DragInputToNotifyWhenDone(
1758 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1759 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1760 this, tab_strip
, tab_strip2
)));
1761 QuitWhenNotDragging();
1763 // Should now be attached to tab_strip2.
1764 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1765 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1766 ASSERT_TRUE(TabDragController::IsActive());
1768 // Release the mouse, stopping the drag session.
1769 ASSERT_TRUE(ReleaseInput());
1771 // tab should have moved
1772 EXPECT_EQ(1, tab_strip
->tab_count());
1773 EXPECT_EQ(2, tab_strip2
->tab_count());
1775 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1776 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1777 ASSERT_FALSE(TabDragController::IsActive());
1778 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1779 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1781 // Source browser should still be maximized, target should not
1782 EXPECT_TRUE(browser()->window()->IsMaximized());
1783 EXPECT_FALSE(browser2
->window()->IsMaximized());
1786 // Immersive fullscreen is Ash only. However, Windows Ash does not support
1787 // multiple displays.
1788 #if defined(OS_CHROMEOS)
1789 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1790 // compositor. crbug.com/331924
1791 #define MAYBE_DragTabToImmersiveBrowserOnSeparateDisplay \
1792 DISABLED_DragTabToImmersiveBrowserOnSeparateDisplay
1793 // Drags from a restored browser to an immersive fullscreen browser on a
1794 // second display and releases input.
1795 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1796 MAYBE_DragTabToImmersiveBrowserOnSeparateDisplay
) {
1798 AddTabAndResetBrowser(browser());
1799 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1801 // Create another browser.
1802 Browser
* browser2
= CreateBrowser(browser()->profile());
1803 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1804 ResetIDs(browser2
->tab_strip_model(), 100);
1806 // Move the second browser to the second display.
1807 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1808 ASSERT_EQ(2u, roots
.size());
1809 aura::Window
* second_root
= roots
[1];
1810 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1811 second_root
).work_area();
1812 browser2
->window()->SetBounds(work_area
);
1813 EXPECT_EQ(second_root
,
1814 browser2
->window()->GetNativeWindow()->GetRootWindow());
1816 // Put the second browser into immersive fullscreen.
1817 BrowserView
* browser_view2
= BrowserView::GetBrowserViewForBrowser(browser2
);
1818 ImmersiveModeController
* immersive_controller2
=
1819 browser_view2
->immersive_mode_controller();
1820 immersive_controller2
->SetupForTest();
1821 chrome::ToggleFullscreenMode(browser2
);
1822 ASSERT_TRUE(immersive_controller2
->IsEnabled());
1823 ASSERT_FALSE(immersive_controller2
->IsRevealed());
1824 ASSERT_TRUE(tab_strip2
->IsImmersiveStyle());
1826 // Move to the first tab and drag it enough so that it detaches, but not
1827 // enough that it attaches to browser2.
1828 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1829 ASSERT_TRUE(PressInput(tab_0_center
));
1830 ASSERT_TRUE(DragInputToNotifyWhenDone(
1831 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1832 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1833 this, tab_strip
, tab_strip2
)));
1834 QuitWhenNotDragging();
1836 // Should now be attached to tab_strip2.
1837 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1838 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1839 ASSERT_TRUE(TabDragController::IsActive());
1841 // browser2's top chrome should be revealed and the tab strip should be
1842 // at normal height while user is tragging tabs_strip2's tabs.
1843 ASSERT_TRUE(immersive_controller2
->IsRevealed());
1844 ASSERT_FALSE(tab_strip2
->IsImmersiveStyle());
1846 // Release the mouse, stopping the drag session.
1847 ASSERT_TRUE(ReleaseInput());
1848 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1849 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1850 ASSERT_FALSE(TabDragController::IsActive());
1851 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1852 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1854 // Move the mouse off of browser2's top chrome.
1855 aura::Window
* primary_root
= roots
[0];
1856 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
1857 primary_root
->GetBoundsInScreen().CenterPoint()));
1859 // The first browser window should not be in immersive fullscreen.
1860 // browser2 should still be in immersive fullscreen, but the top chrome should
1861 // no longer be revealed.
1862 BrowserView
* browser_view
= BrowserView::GetBrowserViewForBrowser(browser());
1863 EXPECT_FALSE(browser_view
->immersive_mode_controller()->IsEnabled());
1865 EXPECT_TRUE(immersive_controller2
->IsEnabled());
1866 EXPECT_FALSE(immersive_controller2
->IsRevealed());
1867 EXPECT_TRUE(tab_strip2
->IsImmersiveStyle());
1869 #endif // OS_CHROMEOS
1871 // Subclass of DetachToBrowserTabDragControllerTest that
1872 // creates multiple displays with different device scale factors.
1873 class DifferentDeviceScaleFactorDisplayTabDragControllerTest
1874 : public DetachToBrowserTabDragControllerTest
{
1876 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1877 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1879 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
1880 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1881 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1882 "400x400,0+400-800x800*2");
1885 float GetCursorDeviceScaleFactor() const {
1886 ash::test::CursorManagerTestApi
cursor_test_api(
1887 ash::Shell::GetInstance()->cursor_manager());
1888 return cursor_test_api
.GetCurrentCursor().device_scale_factor();
1892 DISALLOW_COPY_AND_ASSIGN(
1893 DifferentDeviceScaleFactorDisplayTabDragControllerTest
);
1898 // The points where a tab is dragged in CursorDeviceScaleFactorStep.
1899 const struct DragPoint
{
1910 // The expected device scale factors before the cursor is moved to the
1911 // corresponding kDragPoints in CursorDeviceScaleFactorStep.
1912 const float kDeviceScaleFactorExpectations
[] = {
1921 arraysize(kDragPoints
) == arraysize(kDeviceScaleFactorExpectations
),
1922 kDragPoints_and_kDeviceScaleFactorExpectations_must_have_same_size
);
1924 // Drags tab to |kDragPoints[index]|, then calls the next step function.
1925 void CursorDeviceScaleFactorStep(
1926 DifferentDeviceScaleFactorDisplayTabDragControllerTest
* test
,
1927 TabStrip
* not_attached_tab_strip
,
1929 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
1930 ASSERT_TRUE(TabDragController::IsActive());
1932 if (index
< arraysize(kDragPoints
)) {
1933 EXPECT_EQ(kDeviceScaleFactorExpectations
[index
],
1934 test
->GetCursorDeviceScaleFactor());
1935 const DragPoint p
= kDragPoints
[index
];
1936 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
1937 p
.x
, p
.y
, base::Bind(&CursorDeviceScaleFactorStep
,
1938 test
, not_attached_tab_strip
, index
+ 1)));
1940 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag.
1941 EXPECT_EQ(1.0f
, test
->GetCursorDeviceScaleFactor());
1942 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
1943 ui_controls::LEFT
, ui_controls::UP
));
1949 #if defined(OS_CHROMEOS)
1950 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1951 // compositor. crbug.com/331924
1952 #define MAYBE_CursorDeviceScaleFactor DISABLED_CursorDeviceScaleFactor
1954 #define MAYBE_CursorDeviceScaleFactor CursorDeviceScaleFactor
1956 // Verifies cursor's device scale factor is updated when a tab is moved across
1957 // displays with different device scale factors (http://crbug.com/154183).
1958 IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
1959 MAYBE_CursorDeviceScaleFactor
) {
1961 AddTabAndResetBrowser(browser());
1962 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1964 // Move the second browser to the second display.
1965 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1966 ASSERT_EQ(2u, roots
.size());
1968 // Move to the first tab and drag it enough so that it detaches.
1969 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1970 ASSERT_TRUE(PressInput(tab_0_center
));
1971 ASSERT_TRUE(DragInputToNotifyWhenDone(
1972 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1973 base::Bind(&CursorDeviceScaleFactorStep
,
1974 this, tab_strip
, 0)));
1975 QuitWhenNotDragging();
1980 class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
1981 : public TabDragControllerTest
{
1983 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {}
1985 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
1986 TabDragControllerTest::SetUpCommandLine(command_line
);
1987 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1988 "0+0-250x250,251+0-250x250");
1991 bool Press(const gfx::Point
& position
) {
1992 return ui_test_utils::SendMouseMoveSync(position
) &&
1993 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT
,
1997 bool DragTabAndExecuteTaskWhenDone(const gfx::Point
& position
,
1998 const base::Closure
& task
) {
1999 return ui_controls::SendMouseMoveNotifyWhenDone(
2000 position
.x(), position
.y(), task
);
2003 void QuitWhenNotDragging() {
2004 test::QuitWhenNotDraggingImpl();
2005 base::MessageLoop::current()->Run();
2009 DISALLOW_COPY_AND_ASSIGN(
2010 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
);
2013 // Invoked from the nested message loop.
2014 void CancelDragTabToWindowInSeparateDisplayStep3(
2015 TabStrip
* tab_strip
,
2016 const BrowserList
* browser_list
) {
2017 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2018 ASSERT_TRUE(TabDragController::IsActive());
2019 ASSERT_EQ(2u, browser_list
->size());
2021 // Switching display mode should cancel the drag operation.
2022 ash::DisplayManager
* display_manager
=
2023 ash::Shell::GetInstance()->display_manager();
2024 display_manager
->AddRemoveDisplay();
2027 // Invoked from the nested message loop.
2028 void CancelDragTabToWindowInSeparateDisplayStep2(
2029 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
* test
,
2030 TabStrip
* tab_strip
,
2031 aura::Window
* current_root
,
2032 gfx::Point final_destination
,
2033 const BrowserList
* browser_list
) {
2034 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2035 ASSERT_TRUE(TabDragController::IsActive());
2036 ASSERT_EQ(2u, browser_list
->size());
2038 Browser
* new_browser
= browser_list
->get(1);
2039 EXPECT_EQ(current_root
,
2040 new_browser
->window()->GetNativeWindow()->GetRootWindow());
2042 ASSERT_TRUE(test
->DragTabAndExecuteTaskWhenDone(
2044 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3
,
2045 tab_strip
, browser_list
)));
2050 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
2051 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2052 // compositor. crbug.com/331924
2053 #define MAYBE_CancelDragTabToWindowIn2ndDisplay \
2054 DISABLED_CancelDragTabToWindowIn2ndDisplay
2056 #define MAYBE_CancelDragTabToWindowIn2ndDisplay \
2057 CancelDragTabToWindowIn2ndDisplay
2059 // Drags from browser to a second display and releases input.
2060 IN_PROC_BROWSER_TEST_F(
2061 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
2062 MAYBE_CancelDragTabToWindowIn2ndDisplay
) {
2064 AddTabAndResetBrowser(browser());
2065 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2067 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2069 // Move the second browser to the second display.
2070 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2071 ASSERT_EQ(2u, roots
.size());
2072 gfx::Point final_destination
=
2073 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2074 roots
[1]).work_area().CenterPoint();
2076 // Move to the first tab and drag it enough so that it detaches, but not
2077 // enough to move to another display.
2078 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2079 ASSERT_TRUE(Press(tab_0_dst
));
2080 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2081 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2082 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2083 this, tab_strip
, roots
[0], final_destination
,
2084 native_browser_list
)));
2085 QuitWhenNotDragging();
2087 ASSERT_EQ(1u, native_browser_list
->size());
2088 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2089 ASSERT_FALSE(TabDragController::IsActive());
2090 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2092 // Release the mouse
2093 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2094 ui_controls::LEFT
, ui_controls::UP
));
2097 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
2098 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2099 // compositor. crbug.com/331924
2100 #define MAYBE_CancelDragTabToWindowIn1stDisplay \
2101 DISABLED_CancelDragTabToWindowIn1stDisplay
2103 #define MAYBE_CancelDragTabToWindowIn1stDisplay \
2104 CancelDragTabToWindowIn1stDisplay
2106 // Drags from browser from a second display to primary and releases input.
2107 IN_PROC_BROWSER_TEST_F(
2108 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
2109 MAYBE_CancelDragTabToWindowIn1stDisplay
) {
2110 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2111 ASSERT_EQ(2u, roots
.size());
2114 AddTabAndResetBrowser(browser());
2115 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2117 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2118 EXPECT_EQ(roots
[0], browser()->window()->GetNativeWindow()->GetRootWindow());
2120 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->
2121 GetDisplayNearestWindow(roots
[1]).work_area();
2122 browser()->window()->SetBounds(work_area
);
2123 EXPECT_EQ(roots
[1], browser()->window()->GetNativeWindow()->GetRootWindow());
2125 // Move the second browser to the display.
2126 gfx::Point final_destination
=
2127 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2128 roots
[0]).work_area().CenterPoint();
2130 // Move to the first tab and drag it enough so that it detaches, but not
2131 // enough to move to another display.
2132 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2133 ASSERT_TRUE(Press(tab_0_dst
));
2134 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2135 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2136 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2137 this, tab_strip
, roots
[1], final_destination
,
2138 native_browser_list
)));
2139 QuitWhenNotDragging();
2141 ASSERT_EQ(1u, native_browser_list
->size());
2142 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2143 ASSERT_FALSE(TabDragController::IsActive());
2144 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2146 // Release the mouse
2147 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2148 ui_controls::LEFT
, ui_controls::UP
));
2153 void PressSecondFingerWhileDetachedStep2(
2154 DetachToBrowserTabDragControllerTest
* test
) {
2155 ASSERT_TRUE(TabDragController::IsActive());
2156 ASSERT_EQ(2u, test
->native_browser_list
->size());
2157 Browser
* new_browser
= test
->native_browser_list
->get(1);
2158 ASSERT_TRUE(new_browser
->window()->IsActive());
2160 ASSERT_TRUE(test
->PressInput2());
2165 #if defined(OS_CHROMEOS)
2166 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2167 // compositor. crbug.com/331924
2168 #define MAYBE_PressSecondFingerWhileDetached DISABLED_PressSecondFingerWhileDetached
2170 #define MAYBE_PressSecondFingerWhileDetached PressSecondFingerWhileDetached
2172 // Detaches a tab and while detached presses a second finger.
2173 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch
,
2174 MAYBE_PressSecondFingerWhileDetached
) {
2175 gfx::Rect
bounds(browser()->window()->GetBounds());
2177 AddTabAndResetBrowser(browser());
2178 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2179 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2181 // Move to the first tab and drag it enough so that it detaches.
2182 gfx::Point
tab_0_center(
2183 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2184 ASSERT_TRUE(PressInput(tab_0_center
));
2185 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone(
2186 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2187 base::Bind(&PressSecondFingerWhileDetachedStep2
, this),
2188 base::TimeDelta::FromMilliseconds(60)));
2189 QuitWhenNotDragging();
2191 // The drag should have been reverted.
2192 ASSERT_EQ(1u, native_browser_list
->size());
2193 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2194 ASSERT_FALSE(TabDragController::IsActive());
2195 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2197 ASSERT_TRUE(ReleaseInput());
2198 ASSERT_TRUE(ReleaseInput2());
2201 // Subclass of DetachToBrowserTabDragControllerTest that runs tests with
2202 // docked windows enabled and disabled.
2203 class DetachToDockedTabDragControllerTest
2204 : public DetachToBrowserTabDragControllerTest
{
2206 DetachToDockedTabDragControllerTest() {}
2207 virtual ~DetachToDockedTabDragControllerTest() {}
2210 DISALLOW_COPY_AND_ASSIGN(DetachToDockedTabDragControllerTest
);
2215 void DetachToDockedWindowNextStep(
2216 DetachToDockedTabDragControllerTest
* test
,
2217 const gfx::Point
& target_point
,
2219 ASSERT_EQ(2u, test
->native_browser_list
->size());
2220 Browser
* new_browser
= test
->native_browser_list
->get(1);
2221 ASSERT_TRUE(new_browser
->window()->IsActive());
2224 ASSERT_TRUE(test
->ReleaseInput());
2227 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
2228 target_point
.x(), target_point
.y(),
2229 base::Bind(&DetachToDockedWindowNextStep
,
2231 gfx::Point(target_point
.x(), 1 + target_point
.y()),
2237 #if defined(OS_CHROMEOS)
2238 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2239 // compositor. crbug.com/331924
2240 #define MAYBE_DetachToDockedWindowFromMaximizedWindow \
2241 DISABLED_DetachToDockedWindowFromMaximizedWindow
2243 #define MAYBE_DetachToDockedWindowFromMaximizedWindow \
2244 DetachToDockedWindowFromMaximizedWindow
2246 // Drags from browser to separate window, docks that window and releases mouse.
2247 IN_PROC_BROWSER_TEST_P(DetachToDockedTabDragControllerTest
,
2248 MAYBE_DetachToDockedWindowFromMaximizedWindow
) {
2249 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2250 // compositor. crbug.com/331924
2251 if (docked_windows_enabled()) {
2252 VLOG(1) << "Test is DISABLED for docked windows.";
2256 // Maximize the initial browser window.
2257 browser()->window()->Maximize();
2258 ASSERT_TRUE(browser()->window()->IsMaximized());
2261 AddTabAndResetBrowser(browser());
2262 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2264 // Move to the first tab and drag it enough so that it detaches.
2265 gfx::Point
tab_0_center(
2266 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2267 ASSERT_TRUE(PressInput(tab_0_center
));
2269 // The following matches kMovesBeforeAdjust in snap_sizer.cc
2270 const int kNumIterations
= 25 * 5 + 10;
2271 ASSERT_TRUE(DragInputToNotifyWhenDone(
2272 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2273 base::Bind(&DetachToDockedWindowNextStep
, this,
2274 gfx::Point(0, tab_0_center
.y() + GetDetachY(tab_strip
)),
2276 // Continue dragging enough times to go through snapping sequence and dock
2278 QuitWhenNotDragging();
2279 // Should no longer be dragging.
2280 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2281 ASSERT_FALSE(TabDragController::IsActive());
2283 // There should now be another browser.
2284 ASSERT_EQ(2u, native_browser_list
->size());
2285 Browser
* new_browser
= native_browser_list
->get(1);
2286 ASSERT_TRUE(new_browser
->window()->IsActive());
2287 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
2288 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
2290 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
2291 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
2293 // The bounds of the initial window should not have changed.
2294 EXPECT_TRUE(browser()->window()->IsMaximized());
2296 EXPECT_FALSE(GetIsDragged(browser()));
2297 EXPECT_FALSE(GetIsDragged(new_browser
));
2298 // After this both windows should still be manageable.
2299 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
2300 EXPECT_TRUE(IsWindowPositionManaged(
2301 new_browser
->window()->GetNativeWindow()));
2303 ash::wm::WindowState
* window_state
=
2304 ash::wm::GetWindowState(new_browser
->window()->GetNativeWindow());
2305 // The new window should not be maximized because it gets docked or snapped.
2306 EXPECT_FALSE(new_browser
->window()->IsMaximized());
2307 if (docked_windows_enabled()) {
2308 // The new window should be docked and not snapped if docking is allowed.
2309 EXPECT_TRUE(window_state
->IsDocked());
2310 EXPECT_FALSE(window_state
->IsSnapped());
2312 // The new window should be snapped and not docked if docking is disabled.
2313 EXPECT_FALSE(window_state
->IsDocked());
2314 EXPECT_TRUE(window_state
->IsSnapped());
2321 #if defined(USE_ASH) && defined(OS_CHROMEOS) // TODO(win_ash,linux_ash)
2322 INSTANTIATE_TEST_CASE_P(TabDragging
,
2323 DetachToBrowserInSeparateDisplayTabDragControllerTest
,
2324 ::testing::Values("mouse", "touch"));
2325 INSTANTIATE_TEST_CASE_P(TabDragging
,
2326 DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
2327 ::testing::Values("mouse"));
2328 INSTANTIATE_TEST_CASE_P(TabDragging
,
2329 DetachToBrowserTabDragControllerTest
,
2330 ::testing::Values("mouse", "touch"));
2331 INSTANTIATE_TEST_CASE_P(TabDragging
,
2332 DetachToDockedTabDragControllerTest
,
2333 ::testing::Values("mouse", "mouse docked"));
2334 INSTANTIATE_TEST_CASE_P(TabDragging
,
2335 DetachToBrowserTabDragControllerTestTouch
,
2336 ::testing::Values("touch", "touch docked"));
2337 #elif defined(USE_ASH) && !defined(OS_LINUX) // TODO(linux_ash)
2338 INSTANTIATE_TEST_CASE_P(TabDragging
,
2339 DetachToBrowserTabDragControllerTest
,
2340 ::testing::Values("mouse"));