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/browser_tabstrip.h"
21 #include "chrome/browser/ui/host_desktop.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/browser/ui/views/frame/browser_view.h"
24 #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h"
25 #include "chrome/browser/ui/views/tabs/tab.h"
26 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
27 #include "chrome/browser/ui/views/tabs/tab_strip.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/interactive_test_utils.h"
30 #include "chrome/test/base/ui_test_utils.h"
31 #include "content/public/browser/notification_details.h"
32 #include "content/public/browser/notification_observer.h"
33 #include "content/public/browser/notification_service.h"
34 #include "content/public/browser/notification_source.h"
35 #include "content/public/browser/web_contents.h"
36 #include "ui/base/test/ui_controls.h"
37 #include "ui/gfx/screen.h"
38 #include "ui/views/view.h"
39 #include "ui/views/widget/widget.h"
42 #include "ui/aura/client/aura_constants.h"
43 #include "ui/aura/test/test_window_delegate.h"
44 #include "ui/aura/test/test_windows.h"
45 #include "ui/aura/window_targeter.h"
48 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
49 #include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h"
50 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
54 #include "ash/display/display_manager.h"
55 #include "ash/shell.h"
56 #include "ash/test/cursor_manager_test_api.h"
57 #include "ash/wm/coordinate_conversion.h"
58 #include "ash/wm/window_util.h"
59 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
60 #include "ui/aura/client/screen_position_client.h"
61 #include "ui/aura/test/event_generator_delegate_aura.h"
62 #include "ui/aura/window_event_dispatcher.h"
63 #include "ui/events/test/event_generator.h"
66 using content::WebContents
;
72 const char kTabDragControllerInteractiveUITestUserDataKey
[] =
73 "TabDragControllerInteractiveUITestUserData";
75 class TabDragControllerInteractiveUITestUserData
76 : public base::SupportsUserData::Data
{
78 explicit TabDragControllerInteractiveUITestUserData(int id
) : id_(id
) {}
79 ~TabDragControllerInteractiveUITestUserData() override
{}
80 int id() { return id_
; }
88 class QuitDraggingObserver
: public content::NotificationObserver
{
90 QuitDraggingObserver() {
91 registrar_
.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE
,
92 content::NotificationService::AllSources());
95 void Observe(int type
,
96 const content::NotificationSource
& source
,
97 const content::NotificationDetails
& details
) override
{
98 DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE
, type
);
99 base::MessageLoopForUI::current()->Quit();
104 ~QuitDraggingObserver() override
{}
106 content::NotificationRegistrar registrar_
;
108 DISALLOW_COPY_AND_ASSIGN(QuitDraggingObserver
);
111 gfx::Point
GetCenterInScreenCoordinates(const views::View
* view
) {
112 gfx::Point
center(view
->width() / 2, view
->height() / 2);
113 views::View::ConvertPointToScreen(view
, ¢er
);
117 void SetID(WebContents
* web_contents
, int id
) {
118 web_contents
->SetUserData(&kTabDragControllerInteractiveUITestUserDataKey
,
119 new TabDragControllerInteractiveUITestUserData(id
));
122 void ResetIDs(TabStripModel
* model
, int start
) {
123 for (int i
= 0; i
< model
->count(); ++i
)
124 SetID(model
->GetWebContentsAt(i
), start
+ i
);
127 std::string
IDString(TabStripModel
* model
) {
129 for (int i
= 0; i
< model
->count(); ++i
) {
132 WebContents
* contents
= model
->GetWebContentsAt(i
);
133 TabDragControllerInteractiveUITestUserData
* user_data
=
134 static_cast<TabDragControllerInteractiveUITestUserData
*>(
135 contents
->GetUserData(
136 &kTabDragControllerInteractiveUITestUserDataKey
));
138 result
+= base::IntToString(user_data
->id());
145 // Creates a listener that quits the message loop when no longer dragging.
146 void QuitWhenNotDraggingImpl() {
147 new QuitDraggingObserver(); // QuitDraggingObserver deletes itself.
150 TabStrip
* GetTabStripForBrowser(Browser
* browser
) {
151 BrowserView
* browser_view
= BrowserView::GetBrowserViewForBrowser(browser
);
152 return static_cast<TabStrip
*>(browser_view
->tabstrip());
157 using test::GetCenterInScreenCoordinates
;
159 using test::ResetIDs
;
160 using test::IDString
;
161 using test::GetTabStripForBrowser
;
163 TabDragControllerTest::TabDragControllerTest()
164 : native_browser_list(BrowserList::GetInstance(
165 chrome::HOST_DESKTOP_TYPE_NATIVE
)) {
168 TabDragControllerTest::~TabDragControllerTest() {
171 void TabDragControllerTest::StopAnimating(TabStrip
* tab_strip
) {
172 tab_strip
->StopAnimating(true);
175 void TabDragControllerTest::AddTabAndResetBrowser(Browser
* browser
) {
176 AddBlankTabAndShow(browser
);
177 StopAnimating(GetTabStripForBrowser(browser
));
178 ResetIDs(browser
->tab_strip_model(), 0);
181 Browser
* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
182 // Create another browser.
183 Browser
* browser2
= CreateBrowser(browser()->profile());
184 ResetIDs(browser2
->tab_strip_model(), 100);
186 // Resize the two windows so they're right next to each other.
187 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
188 browser()->window()->GetNativeWindow()).work_area();
189 gfx::Size half_size
=
190 gfx::Size(work_area
.width() / 3 - 10, work_area
.height() / 2 - 10);
191 browser()->window()->SetBounds(gfx::Rect(work_area
.origin(), half_size
));
192 browser2
->window()->SetBounds(gfx::Rect(
193 work_area
.x() + half_size
.width(), work_area
.y(),
194 half_size
.width(), half_size
.height()));
201 INPUT_SOURCE_MOUSE
= 0,
202 INPUT_SOURCE_TOUCH
= 1
205 int GetDetachY(TabStrip
* tab_strip
) {
206 return std::max(TabDragController::kTouchVerticalDetachMagnetism
,
207 TabDragController::kVerticalDetachMagnetism
) +
208 tab_strip
->height() + 1;
211 bool GetIsDragged(Browser
* browser
) {
212 #if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash)
215 return ash::wm::GetWindowState(browser
->window()->GetNativeWindow())->
222 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
223 class ScreenEventGeneratorDelegate
224 : public aura::test::EventGeneratorDelegateAura
{
226 explicit ScreenEventGeneratorDelegate(aura::Window
* root_window
)
227 : root_window_(root_window
) {}
228 ~ScreenEventGeneratorDelegate() override
{}
230 // EventGeneratorDelegateAura overrides:
231 aura::WindowTreeHost
* GetHostAt(const gfx::Point
& point
) const override
{
232 return root_window_
->GetHost();
235 aura::client::ScreenPositionClient
* GetScreenPositionClient(
236 const aura::Window
* window
) const override
{
237 return aura::client::GetScreenPositionClient(root_window_
);
241 aura::Window
* root_window_
;
243 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate
);
248 #if !defined(OS_CHROMEOS)
250 // Following classes verify a crash scenario. Specifically on Windows when focus
251 // changes it can trigger capture being lost. This was causing a crash in tab
252 // dragging as it wasn't set up to handle this scenario. These classes
253 // synthesize this scenario.
255 // Allows making ClearNativeFocus() invoke ReleaseCapture().
256 class TestDesktopBrowserFrameAura
: public DesktopBrowserFrameAura
{
258 TestDesktopBrowserFrameAura(
259 BrowserFrame
* browser_frame
,
260 BrowserView
* browser_view
)
261 : DesktopBrowserFrameAura(browser_frame
, browser_view
),
262 release_capture_(false) {}
263 ~TestDesktopBrowserFrameAura() override
{}
265 void ReleaseCaptureOnNextClear() {
266 release_capture_
= true;
269 void ClearNativeFocus() override
{
270 views::DesktopNativeWidgetAura::ClearNativeFocus();
271 if (release_capture_
) {
272 release_capture_
= false;
273 GetWidget()->ReleaseCapture();
278 // If true ReleaseCapture() is invoked in ClearNativeFocus().
279 bool release_capture_
;
281 DISALLOW_COPY_AND_ASSIGN(TestDesktopBrowserFrameAura
);
284 // Factory for creating a TestDesktopBrowserFrameAura.
285 class TestNativeBrowserFrameFactory
: public NativeBrowserFrameFactory
{
287 TestNativeBrowserFrameFactory() {}
288 ~TestNativeBrowserFrameFactory() override
{}
290 NativeBrowserFrame
* Create(BrowserFrame
* browser_frame
,
291 BrowserView
* browser_view
) override
{
292 return new TestDesktopBrowserFrameAura(browser_frame
, browser_view
);
296 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory
);
299 class TabDragCaptureLostTest
: public TabDragControllerTest
{
301 TabDragCaptureLostTest() {
302 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory
);
306 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest
);
309 // See description above for details.
310 IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest
, ReleaseCaptureOnDrag
) {
311 AddTabAndResetBrowser(browser());
313 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
314 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
315 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center
) &&
316 ui_test_utils::SendMouseEventsSync(
317 ui_controls::LEFT
, ui_controls::DOWN
));
318 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
319 TestDesktopBrowserFrameAura
* frame
=
320 static_cast<TestDesktopBrowserFrameAura
*>(
321 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()->
322 native_widget_private());
323 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus
324 // changes capture is released and the drag cancels.
325 frame
->ReleaseCaptureOnNextClear();
326 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center
));
327 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
330 IN_PROC_BROWSER_TEST_F(TabDragControllerTest
, GestureEndShouldEndDragTest
) {
331 AddTabAndResetBrowser(browser());
333 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
335 Tab
* tab1
= tab_strip
->tab_at(1);
336 gfx::Point
tab_1_center(tab1
->width() / 2, tab1
->height() / 2);
338 ui::GestureEvent
gesture_tap_down(
343 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
344 tab_strip
->MaybeStartDrag(tab1
, gesture_tap_down
,
345 tab_strip
->GetSelectionModel());
346 EXPECT_TRUE(TabDragController::IsActive());
348 ui::GestureEvent
gesture_end(tab_1_center
.x(),
352 ui::GestureEventDetails(ui::ET_GESTURE_END
));
353 tab_strip
->OnGestureEvent(&gesture_end
);
354 EXPECT_FALSE(TabDragController::IsActive());
355 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
360 class DetachToBrowserTabDragControllerTest
361 : public TabDragControllerTest
,
362 public ::testing::WithParamInterface
<const char*> {
364 DetachToBrowserTabDragControllerTest() {}
366 void SetUpOnMainThread() override
{
367 #if defined(OS_CHROMEOS)
368 event_generator_
.reset(
369 new ui::test::EventGenerator(ash::Shell::GetPrimaryRootWindow()));
373 InputSource
input_source() const {
374 return strstr(GetParam(), "mouse") ?
375 INPUT_SOURCE_MOUSE
: INPUT_SOURCE_TOUCH
;
378 // Set root window from a point in screen coordinates
379 void SetEventGeneratorRootWindow(const gfx::Point
& point
) {
380 if (input_source() == INPUT_SOURCE_MOUSE
)
382 #if defined(OS_CHROMEOS)
383 event_generator_
.reset(new ui::test::EventGenerator(
384 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point
))));
388 // The following methods update one of the mouse or touch input depending upon
390 bool PressInput(const gfx::Point
& location
) {
391 if (input_source() == INPUT_SOURCE_MOUSE
) {
392 return ui_test_utils::SendMouseMoveSync(location
) &&
393 ui_test_utils::SendMouseEventsSync(
394 ui_controls::LEFT
, ui_controls::DOWN
);
396 #if defined(OS_CHROMEOS)
397 event_generator_
->set_current_location(location
);
398 event_generator_
->PressTouch();
406 // Second touch input is only used for touch sequence tests.
407 EXPECT_EQ(INPUT_SOURCE_TOUCH
, input_source());
408 #if defined(OS_CHROMEOS)
409 event_generator_
->set_current_location(
410 event_generator_
->current_location());
411 event_generator_
->PressTouchId(1);
418 bool DragInputTo(const gfx::Point
& location
) {
419 if (input_source() == INPUT_SOURCE_MOUSE
)
420 return ui_test_utils::SendMouseMoveSync(location
);
421 #if defined(OS_CHROMEOS)
422 event_generator_
->MoveTouch(location
);
429 bool DragInputToAsync(const gfx::Point
& location
) {
430 if (input_source() == INPUT_SOURCE_MOUSE
)
431 return ui_controls::SendMouseMove(location
.x(), location
.y());
432 #if defined(OS_CHROMEOS)
433 event_generator_
->MoveTouch(location
);
440 bool DragInputToNotifyWhenDone(int x
,
442 const base::Closure
& task
) {
443 if (input_source() == INPUT_SOURCE_MOUSE
)
444 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
445 #if defined(OS_CHROMEOS)
446 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
447 event_generator_
->MoveTouch(gfx::Point(x
, y
));
454 bool DragInputToDelayedNotifyWhenDone(int x
,
456 const base::Closure
& task
,
457 base::TimeDelta delay
) {
458 if (input_source() == INPUT_SOURCE_MOUSE
)
459 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
460 #if defined(OS_CHROMEOS)
461 base::MessageLoop::current()->PostDelayedTask(FROM_HERE
, task
, delay
);
462 event_generator_
->MoveTouch(gfx::Point(x
, y
));
469 bool DragInput2ToNotifyWhenDone(int x
,
471 const base::Closure
& task
) {
472 if (input_source() == INPUT_SOURCE_MOUSE
)
473 return ui_controls::SendMouseMoveNotifyWhenDone(x
, y
, task
);
474 #if defined(OS_CHROMEOS)
475 base::MessageLoop::current()->PostTask(FROM_HERE
, task
);
476 event_generator_
->MoveTouchId(gfx::Point(x
, y
), 1);
483 bool ReleaseInput() {
484 if (input_source() == INPUT_SOURCE_MOUSE
) {
485 return ui_test_utils::SendMouseEventsSync(
486 ui_controls::LEFT
, ui_controls::UP
);
488 #if defined(OS_CHROMEOS)
489 event_generator_
->ReleaseTouch();
496 bool ReleaseInput2() {
497 if (input_source() == INPUT_SOURCE_MOUSE
) {
498 return ui_test_utils::SendMouseEventsSync(
499 ui_controls::LEFT
, ui_controls::UP
);
501 #if defined(OS_CHROMEOS)
502 event_generator_
->ReleaseTouchId(1);
509 bool ReleaseMouseAsync() {
510 return input_source() == INPUT_SOURCE_MOUSE
&&
511 ui_controls::SendMouseEvents(ui_controls::LEFT
, ui_controls::UP
);
514 void QuitWhenNotDragging() {
515 if (input_source() == INPUT_SOURCE_MOUSE
) {
516 // Schedule observer to quit message loop when done dragging. This has to
517 // be async so the message loop can run.
518 test::QuitWhenNotDraggingImpl();
519 base::MessageLoop::current()->Run();
521 // Touch events are sync, so we know we're not in a drag session. But some
522 // tests rely on the browser fully closing, which is async. So, run all
524 base::RunLoop run_loop
;
525 run_loop
.RunUntilIdle();
529 void AddBlankTabAndShow(Browser
* browser
) {
530 InProcessBrowserTest::AddBlankTabAndShow(browser
);
533 Browser
* browser() const { return InProcessBrowserTest::browser(); }
536 #if defined(OS_CHROMEOS)
537 scoped_ptr
<ui::test::EventGenerator
> event_generator_
;
540 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest
);
543 // Creates a browser with two tabs, drags the second to the first.
544 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, DragInSameWindow
) {
545 // TODO(sky): this won't work with touch as it requires a long press.
546 if (input_source() == INPUT_SOURCE_TOUCH
) {
547 VLOG(1) << "Test is DISABLED for touch input.";
551 AddTabAndResetBrowser(browser());
553 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
554 TabStripModel
* model
= browser()->tab_strip_model();
556 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
557 ASSERT_TRUE(PressInput(tab_1_center
));
558 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
559 ASSERT_TRUE(DragInputTo(tab_0_center
));
560 ASSERT_TRUE(ReleaseInput());
561 EXPECT_EQ("1 0", IDString(model
));
562 EXPECT_FALSE(TabDragController::IsActive());
563 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
565 // The tab strip should no longer have capture because the drag was ended and
566 // mouse/touch was released.
567 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
570 #if defined(USE_AURA)
573 // We need both MaskedWindowTargeter and MaskedWindowDelegate as they
574 // are used in two different pathes. crbug.com/493354.
575 class MaskedWindowTargeter
: public aura::WindowTargeter
{
577 MaskedWindowTargeter() {}
578 ~MaskedWindowTargeter() override
{}
580 // aura::WindowTargeter:
581 bool EventLocationInsideBounds(aura::Window
* target
,
582 const ui::LocatedEvent
& event
) const override
{
583 aura::Window
* window
= static_cast<aura::Window
*>(target
);
584 gfx::Point local_point
= event
.location();
585 if (window
->parent())
586 aura::Window::ConvertPointToTarget(window
->parent(), window
,
588 return window
->GetEventHandlerForPoint(local_point
);
592 DISALLOW_COPY_AND_ASSIGN(MaskedWindowTargeter
);
597 // The logic to find the target tabstrip should take the window mask into
598 // account. This test hangs without the fix. crbug.com/473080.
599 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
600 DragWithMaskedWindows
) {
601 AddTabAndResetBrowser(browser());
603 aura::Window
* browser_window
= browser()->window()->GetNativeWindow();
604 const gfx::Rect bounds
= browser_window
->GetBoundsInScreen();
605 aura::test::MaskedWindowDelegate
masked_window_delegate(
606 gfx::Rect(bounds
.width() - 10, 0, 10, bounds
.height()));
607 gfx::Rect
test(bounds
);
608 masked_window_delegate
.set_can_focus(false);
609 scoped_ptr
<aura::Window
> masked_window(
610 aura::test::CreateTestWindowWithDelegate(&masked_window_delegate
, 10,
611 test
, browser_window
->parent()));
612 masked_window
->SetEventTargeter(
613 scoped_ptr
<ui::EventTargeter
>(new MaskedWindowTargeter()));
615 ASSERT_FALSE(masked_window
->GetEventHandlerForPoint(
616 gfx::Point(bounds
.width() - 11, 0)));
617 ASSERT_TRUE(masked_window
->GetEventHandlerForPoint(
618 gfx::Point(bounds
.width() - 9, 0)));
619 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
620 TabStripModel
* model
= browser()->tab_strip_model();
622 gfx::Point
tab_1_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(1)));
623 ASSERT_TRUE(PressInput(tab_1_center
));
624 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
625 ASSERT_TRUE(DragInputTo(tab_0_center
));
626 ASSERT_TRUE(ReleaseInput());
627 EXPECT_EQ("1 0", IDString(model
));
628 EXPECT_FALSE(TabDragController::IsActive());
629 EXPECT_FALSE(tab_strip
->IsDragSessionActive());
635 // Invoked from the nested message loop.
636 void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
637 TabStrip
* not_attached_tab_strip
,
638 TabStrip
* target_tab_strip
) {
639 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
640 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
641 ASSERT_TRUE(TabDragController::IsActive());
643 // Drag to target_tab_strip. This should stop the nested loop from dragging
645 gfx::Point
target_point(target_tab_strip
->width() -1,
646 target_tab_strip
->height() / 2);
647 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
648 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
653 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
654 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
655 // compositor. crbug.com/331924
656 #define MAYBE_DragToSeparateWindow DISABLED_DragToSeparateWindow
658 #define MAYBE_DragToSeparateWindow DragToSeparateWindow
660 // Creates two browsers, drags from first into second.
661 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
662 MAYBE_DragToSeparateWindow
) {
663 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
665 // Add another tab to browser().
666 AddTabAndResetBrowser(browser());
668 // Create another browser.
669 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
670 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
672 // Move to the first tab and drag it enough so that it detaches, but not
673 // enough that it attaches to browser2.
674 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
675 ASSERT_TRUE(PressInput(tab_0_center
));
676 ASSERT_TRUE(DragInputToNotifyWhenDone(
677 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
678 base::Bind(&DragToSeparateWindowStep2
,
679 this, tab_strip
, tab_strip2
)));
680 QuitWhenNotDragging();
682 // Should now be attached to tab_strip2.
683 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
684 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
685 ASSERT_TRUE(TabDragController::IsActive());
686 EXPECT_FALSE(GetIsDragged(browser()));
688 // Release mouse or touch, stopping the drag session.
689 ASSERT_TRUE(ReleaseInput());
690 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
691 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
692 ASSERT_FALSE(TabDragController::IsActive());
693 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
694 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
695 EXPECT_FALSE(GetIsDragged(browser2
));
697 // Both windows should not be maximized
698 EXPECT_FALSE(browser()->window()->IsMaximized());
699 EXPECT_FALSE(browser2
->window()->IsMaximized());
701 // The tab strip should no longer have capture because the drag was ended and
702 // mouse/touch was released.
703 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
704 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
709 void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest
* test
) {
710 if (test
->input_source() == INPUT_SOURCE_TOUCH
)
711 ASSERT_TRUE(test
->ReleaseInput());
714 #if defined(OS_CHROMEOS)
715 bool IsWindowPositionManaged(aura::Window
* window
) {
716 return ash::wm::GetWindowState(window
)->window_position_managed();
718 bool HasUserChangedWindowPositionOrSize(aura::Window
* window
) {
719 return ash::wm::GetWindowState(window
)->bounds_changed_by_user();
722 bool IsWindowPositionManaged(gfx::NativeWindow window
) {
725 bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window
) {
732 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
733 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
734 // compositor. crbug.com/331924
735 #define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow
737 #define MAYBE_DetachToOwnWindow DetachToOwnWindow
739 // Drags from browser to separate window and releases mouse.
740 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
741 MAYBE_DetachToOwnWindow
) {
742 const gfx::Rect
initial_bounds(browser()->window()->GetBounds());
744 AddTabAndResetBrowser(browser());
745 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
747 // Move to the first tab and drag it enough so that it detaches.
748 gfx::Point
tab_0_center(
749 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
750 ASSERT_TRUE(PressInput(tab_0_center
));
751 ASSERT_TRUE(DragInputToNotifyWhenDone(
752 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
753 base::Bind(&DetachToOwnWindowStep2
, this)));
754 if (input_source() == INPUT_SOURCE_MOUSE
) {
755 ASSERT_TRUE(ReleaseMouseAsync());
756 QuitWhenNotDragging();
759 // Should no longer be dragging.
760 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
761 ASSERT_FALSE(TabDragController::IsActive());
763 // There should now be another browser.
764 ASSERT_EQ(2u, native_browser_list
->size());
765 Browser
* new_browser
= native_browser_list
->get(1);
766 ASSERT_TRUE(new_browser
->window()->IsActive());
767 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
768 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
770 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
771 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
773 // The bounds of the initial window should not have changed.
774 EXPECT_EQ(initial_bounds
.ToString(),
775 browser()->window()->GetBounds().ToString());
777 EXPECT_FALSE(GetIsDragged(browser()));
778 EXPECT_FALSE(GetIsDragged(new_browser
));
779 // After this both windows should still be manageable.
780 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
781 EXPECT_TRUE(IsWindowPositionManaged(
782 new_browser
->window()->GetNativeWindow()));
784 // Both windows should not be maximized
785 EXPECT_FALSE(browser()->window()->IsMaximized());
786 EXPECT_FALSE(new_browser
->window()->IsMaximized());
788 // The tab strip should no longer have capture because the drag was ended and
789 // mouse/touch was released.
790 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
791 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
794 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
795 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
796 // compositor. crbug.com/331924
797 #define MAYBE_DetachFromFullsizeWindow DISABLED_DetachFromFullsizeWindow
799 #define MAYBE_DetachFromFullsizeWindow DetachFromFullsizeWindow
801 // Tests that a tab can be dragged from a browser window that is resized to full
803 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
804 MAYBE_DetachFromFullsizeWindow
) {
805 // Resize the browser window so that it is as big as the work area.
806 gfx::Rect work_area
=
807 gfx::Screen::GetNativeScreen()
808 ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow())
810 browser()->window()->SetBounds(work_area
);
811 const gfx::Rect
initial_bounds(browser()->window()->GetBounds());
813 AddTabAndResetBrowser(browser());
814 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
816 // Move to the first tab and drag it enough so that it detaches.
817 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
818 ASSERT_TRUE(PressInput(tab_0_center
));
819 ASSERT_TRUE(DragInputToNotifyWhenDone(
820 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
821 base::Bind(&DetachToOwnWindowStep2
, this)));
822 if (input_source() == INPUT_SOURCE_MOUSE
) {
823 ASSERT_TRUE(ReleaseMouseAsync());
824 QuitWhenNotDragging();
827 // Should no longer be dragging.
828 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
829 ASSERT_FALSE(TabDragController::IsActive());
831 // There should now be another browser.
832 ASSERT_EQ(2u, native_browser_list
->size());
833 Browser
* new_browser
= native_browser_list
->get(1);
834 ASSERT_TRUE(new_browser
->window()->IsActive());
835 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
836 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
838 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
839 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
841 // The bounds of the initial window should not have changed.
842 EXPECT_EQ(initial_bounds
.ToString(),
843 browser()->window()->GetBounds().ToString());
845 EXPECT_FALSE(GetIsDragged(browser()));
846 EXPECT_FALSE(GetIsDragged(new_browser
));
847 // After this both windows should still be manageable.
848 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
850 IsWindowPositionManaged(new_browser
->window()->GetNativeWindow()));
852 // Only second window should be maximized.
853 EXPECT_FALSE(browser()->window()->IsMaximized());
854 EXPECT_TRUE(new_browser
->window()->IsMaximized());
856 // The tab strip should no longer have capture because the drag was ended and
857 // mouse/touch was released.
858 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
859 EXPECT_FALSE(tab_strip2
->GetWidget()->HasCapture());
862 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
863 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
864 // compositor. crbug.com/331924
865 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
866 DISABLED_DetachToOwnWindowFromMaximizedWindow
868 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
869 DetachToOwnWindowFromMaximizedWindow
871 // Drags from browser to a separate window and releases mouse.
872 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
873 MAYBE_DetachToOwnWindowFromMaximizedWindow
) {
874 // Maximize the initial browser window.
875 browser()->window()->Maximize();
876 ASSERT_TRUE(browser()->window()->IsMaximized());
879 AddTabAndResetBrowser(browser());
880 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
882 // Move to the first tab and drag it enough so that it detaches.
883 gfx::Point
tab_0_center(
884 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
885 ASSERT_TRUE(PressInput(tab_0_center
));
886 ASSERT_TRUE(DragInputToNotifyWhenDone(
887 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
888 base::Bind(&DetachToOwnWindowStep2
, this)));
889 if (input_source() == INPUT_SOURCE_MOUSE
) {
890 ASSERT_TRUE(ReleaseMouseAsync());
891 QuitWhenNotDragging();
894 // Should no longer be dragging.
895 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
896 ASSERT_FALSE(TabDragController::IsActive());
898 // There should now be another browser.
899 ASSERT_EQ(2u, native_browser_list
->size());
900 Browser
* new_browser
= native_browser_list
->get(1);
901 ASSERT_TRUE(new_browser
->window()->IsActive());
902 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
903 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
905 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
906 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
908 // The bounds of the initial window should not have changed.
909 EXPECT_TRUE(browser()->window()->IsMaximized());
911 EXPECT_FALSE(GetIsDragged(browser()));
912 EXPECT_FALSE(GetIsDragged(new_browser
));
913 // After this both windows should still be manageable.
914 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
915 EXPECT_TRUE(IsWindowPositionManaged(
916 new_browser
->window()->GetNativeWindow()));
918 // The new window should be maximized.
919 EXPECT_TRUE(new_browser
->window()->IsMaximized());
922 // Deletes a tab being dragged before the user moved enough to start a drag.
923 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
924 DeleteBeforeStartedDragging
) {
926 AddTabAndResetBrowser(browser());
927 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
929 // Click on the first tab, but don't move it.
930 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
931 ASSERT_TRUE(PressInput(tab_0_center
));
933 // Should be dragging.
934 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
935 ASSERT_TRUE(TabDragController::IsActive());
937 // Delete the tab being dragged.
938 delete browser()->tab_strip_model()->GetWebContentsAt(0);
940 // Should have canceled dragging.
941 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
942 ASSERT_FALSE(TabDragController::IsActive());
944 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
945 EXPECT_FALSE(GetIsDragged(browser()));
948 #if defined(OS_CHROMEOS)
949 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
950 // compositor. crbug.com/331924
951 #define MAYBE_DeleteTabWhileAttached DISABLED_DeleteTabWhileAttached
953 #define MAYBE_DeleteTabWhileAttached DeleteTabWhileAttached
955 // Deletes a tab being dragged while still attached.
956 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
957 MAYBE_DeleteTabWhileAttached
) {
958 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
959 // compositor. crbug.com/331924
960 if (input_source() == INPUT_SOURCE_MOUSE
) {
961 VLOG(1) << "Test is DISABLED for mouse input.";
966 AddTabAndResetBrowser(browser());
967 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
969 // Click on the first tab and move it enough so that it starts dragging but is
971 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
972 ASSERT_TRUE(PressInput(tab_0_center
));
973 ASSERT_TRUE(DragInputTo(
974 gfx::Point(tab_0_center
.x() + 20, tab_0_center
.y())));
976 // Should be dragging.
977 ASSERT_TRUE(tab_strip
->IsDragSessionActive());
978 ASSERT_TRUE(TabDragController::IsActive());
980 // Delete the tab being dragged.
981 delete browser()->tab_strip_model()->GetWebContentsAt(0);
983 // Should have canceled dragging.
984 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
985 ASSERT_FALSE(TabDragController::IsActive());
987 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
989 EXPECT_FALSE(GetIsDragged(browser()));
994 void DeleteWhileDetachedStep2(WebContents
* tab
) {
1000 #if defined(OS_CHROMEOS)
1001 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1002 // compositor. crbug.com/331924
1003 #define MAYBE_DeleteTabWhileDetached DISABLED_DeleteTabWhileDetached
1005 #define MAYBE_DeleteTabWhileDetached DeleteTabWhileDetached
1007 // Deletes a tab being dragged after dragging a tab so that a new window is
1009 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1010 MAYBE_DeleteTabWhileDetached
) {
1012 AddTabAndResetBrowser(browser());
1013 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1015 // Move to the first tab and drag it enough so that it detaches.
1016 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1017 WebContents
* to_delete
=
1018 browser()->tab_strip_model()->GetWebContentsAt(0);
1019 ASSERT_TRUE(PressInput(tab_0_center
));
1020 ASSERT_TRUE(DragInputToNotifyWhenDone(
1021 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1022 base::Bind(&DeleteWhileDetachedStep2
, to_delete
)));
1023 QuitWhenNotDragging();
1025 // Should not be dragging.
1026 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1027 ASSERT_FALSE(TabDragController::IsActive());
1029 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1031 EXPECT_FALSE(GetIsDragged(browser()));
1036 void DeleteSourceDetachedStep2(WebContents
* tab
,
1037 const BrowserList
* browser_list
) {
1038 ASSERT_EQ(2u, browser_list
->size());
1039 Browser
* new_browser
= browser_list
->get(1);
1040 // This ends up closing the source window.
1043 ui_controls::SendKeyPress(new_browser
->window()->GetNativeWindow(),
1044 ui::VKEY_ESCAPE
, false, false, false, false);
1049 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1050 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1051 // compositor. crbug.com/331924
1052 #define MAYBE_DeleteSourceDetached DISABLED_DeleteSourceDetached
1054 #define MAYBE_DeleteSourceDetached DeleteSourceDetached
1056 // Detaches a tab and while detached deletes a tab from the source so that the
1057 // source window closes then presses escape to cancel the drag.
1058 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1059 MAYBE_DeleteSourceDetached
) {
1061 AddTabAndResetBrowser(browser());
1062 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1064 // Move to the first tab and drag it enough so that it detaches.
1065 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1066 WebContents
* to_delete
= browser()->tab_strip_model()->GetWebContentsAt(1);
1067 ASSERT_TRUE(PressInput(tab_0_center
));
1068 ASSERT_TRUE(DragInputToNotifyWhenDone(
1069 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1070 base::Bind(&DeleteSourceDetachedStep2
, to_delete
, native_browser_list
)));
1071 QuitWhenNotDragging();
1073 // Should not be dragging.
1074 ASSERT_EQ(1u, native_browser_list
->size());
1075 Browser
* new_browser
= native_browser_list
->get(0);
1076 ASSERT_FALSE(GetTabStripForBrowser(new_browser
)->IsDragSessionActive());
1077 ASSERT_FALSE(TabDragController::IsActive());
1079 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
1081 EXPECT_FALSE(GetIsDragged(new_browser
));
1083 // Remaining browser window should not be maximized
1084 EXPECT_FALSE(new_browser
->window()->IsMaximized());
1089 void PressEscapeWhileDetachedStep2(const BrowserList
* browser_list
) {
1090 ASSERT_EQ(2u, browser_list
->size());
1091 Browser
* new_browser
= browser_list
->get(1);
1092 ui_controls::SendKeyPress(
1093 new_browser
->window()->GetNativeWindow(), ui::VKEY_ESCAPE
, false, false,
1099 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1100 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1101 // compositor. crbug.com/331924
1102 #define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached
1104 #define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached
1106 // This is disabled until NativeViewHost::Detach really detaches.
1107 // Detaches a tab and while detached presses escape to revert the drag.
1108 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1109 MAYBE_PressEscapeWhileDetached
) {
1111 AddTabAndResetBrowser(browser());
1112 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1114 // Move to the first tab and drag it enough so that it detaches.
1115 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1116 ASSERT_TRUE(PressInput(tab_0_center
));
1117 ASSERT_TRUE(DragInputToNotifyWhenDone(
1118 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1119 base::Bind(&PressEscapeWhileDetachedStep2
, native_browser_list
)));
1120 QuitWhenNotDragging();
1122 // Should not be dragging.
1123 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1124 ASSERT_FALSE(TabDragController::IsActive());
1126 // And there should only be one window.
1127 EXPECT_EQ(1u, native_browser_list
->size());
1129 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1131 // Remaining browser window should not be maximized
1132 EXPECT_FALSE(browser()->window()->IsMaximized());
1134 // The tab strip should no longer have capture because the drag was ended and
1135 // mouse/touch was released.
1136 EXPECT_FALSE(tab_strip
->GetWidget()->HasCapture());
1141 void DragAllStep2(DetachToBrowserTabDragControllerTest
* test
,
1142 const BrowserList
* browser_list
) {
1143 // Should only be one window.
1144 ASSERT_EQ(1u, browser_list
->size());
1145 if (test
->input_source() == INPUT_SOURCE_TOUCH
) {
1146 ASSERT_TRUE(test
->ReleaseInput());
1148 ASSERT_TRUE(test
->ReleaseMouseAsync());
1154 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1155 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1156 // compositor. crbug.com/331924
1157 #define MAYBE_DragAll DISABLED_DragAll
1159 #define MAYBE_DragAll DragAll
1161 // Selects multiple tabs and starts dragging the window.
1162 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
, MAYBE_DragAll
) {
1164 AddTabAndResetBrowser(browser());
1165 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1166 browser()->tab_strip_model()->AddTabAtToSelection(0);
1167 browser()->tab_strip_model()->AddTabAtToSelection(1);
1169 // Move to the first tab and drag it enough so that it would normally
1171 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1172 ASSERT_TRUE(PressInput(tab_0_center
));
1173 ASSERT_TRUE(DragInputToNotifyWhenDone(
1174 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1175 base::Bind(&DragAllStep2
, this, native_browser_list
)));
1176 QuitWhenNotDragging();
1178 // Should not be dragging.
1179 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1180 ASSERT_FALSE(TabDragController::IsActive());
1182 // And there should only be one window.
1183 EXPECT_EQ(1u, native_browser_list
->size());
1185 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1187 EXPECT_FALSE(GetIsDragged(browser()));
1189 // Remaining browser window should not be maximized
1190 EXPECT_FALSE(browser()->window()->IsMaximized());
1195 // Invoked from the nested message loop.
1196 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1197 TabStrip
* attached_tab_strip
,
1198 TabStrip
* target_tab_strip
,
1199 const BrowserList
* browser_list
) {
1200 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1201 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1202 ASSERT_TRUE(TabDragController::IsActive());
1203 ASSERT_EQ(2u, browser_list
->size());
1205 // Drag to target_tab_strip. This should stop the nested loop from dragging
1207 gfx::Point
target_point(target_tab_strip
->width() - 1,
1208 target_tab_strip
->height() / 2);
1209 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1210 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1215 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1216 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1217 // compositor. crbug.com/331924
1218 #define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow
1220 #define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow
1222 // Creates two browsers, selects all tabs in first and drags into second.
1223 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1224 MAYBE_DragAllToSeparateWindow
) {
1225 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1227 // Add another tab to browser().
1228 AddTabAndResetBrowser(browser());
1230 // Create another browser.
1231 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1232 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1234 browser()->tab_strip_model()->AddTabAtToSelection(0);
1235 browser()->tab_strip_model()->AddTabAtToSelection(1);
1237 // Move to the first tab and drag it enough so that it detaches, but not
1238 // enough that it attaches to browser2.
1239 gfx::Point
tab_0_center(
1240 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1241 ASSERT_TRUE(PressInput(tab_0_center
));
1242 ASSERT_TRUE(DragInputToNotifyWhenDone(
1243 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1244 base::Bind(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1245 native_browser_list
)));
1246 QuitWhenNotDragging();
1248 // Should now be attached to tab_strip2.
1249 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1250 ASSERT_TRUE(TabDragController::IsActive());
1251 ASSERT_EQ(1u, native_browser_list
->size());
1253 // Release the mouse, stopping the drag session.
1254 ASSERT_TRUE(ReleaseInput());
1255 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1256 ASSERT_FALSE(TabDragController::IsActive());
1257 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1259 EXPECT_FALSE(GetIsDragged(browser2
));
1261 // Remaining browser window should not be maximized
1262 EXPECT_FALSE(browser2
->window()->IsMaximized());
1267 // Invoked from the nested message loop.
1268 void DragAllToSeparateWindowAndCancelStep2(
1269 DetachToBrowserTabDragControllerTest
* test
,
1270 TabStrip
* attached_tab_strip
,
1271 TabStrip
* target_tab_strip
,
1272 const BrowserList
* browser_list
) {
1273 ASSERT_TRUE(attached_tab_strip
->IsDragSessionActive());
1274 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1275 ASSERT_TRUE(TabDragController::IsActive());
1276 ASSERT_EQ(2u, browser_list
->size());
1278 // Drag to target_tab_strip. This should stop the nested loop from dragging
1280 gfx::Point
target_point(target_tab_strip
->width() - 1,
1281 target_tab_strip
->height() / 2);
1282 views::View::ConvertPointToScreen(target_tab_strip
, &target_point
);
1283 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1288 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1289 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1290 // compositor. crbug.com/331924
1291 #define MAYBE_DragAllToSeparateWindowAndCancel \
1292 DISABLED_DragAllToSeparateWindowAndCancel
1294 #define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel
1296 // Creates two browsers, selects all tabs in first, drags into second, then hits
1298 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1299 MAYBE_DragAllToSeparateWindowAndCancel
) {
1300 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1302 // Add another tab to browser().
1303 AddTabAndResetBrowser(browser());
1305 // Create another browser.
1306 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1307 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1309 browser()->tab_strip_model()->AddTabAtToSelection(0);
1310 browser()->tab_strip_model()->AddTabAtToSelection(1);
1312 // Move to the first tab and drag it enough so that it detaches, but not
1313 // enough that it attaches to browser2.
1314 gfx::Point
tab_0_center(
1315 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1316 ASSERT_TRUE(PressInput(tab_0_center
));
1317 ASSERT_TRUE(DragInputToNotifyWhenDone(
1318 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1319 base::Bind(&DragAllToSeparateWindowAndCancelStep2
, this,
1320 tab_strip
, tab_strip2
, native_browser_list
)));
1321 QuitWhenNotDragging();
1323 // Should now be attached to tab_strip2.
1324 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1325 ASSERT_TRUE(TabDragController::IsActive());
1326 ASSERT_EQ(1u, native_browser_list
->size());
1329 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
1330 browser2
, ui::VKEY_ESCAPE
, false, false, false, false));
1332 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1333 ASSERT_FALSE(TabDragController::IsActive());
1334 EXPECT_EQ("100 0 1", IDString(browser2
->tab_strip_model()));
1336 // browser() will have been destroyed, but browser2 should remain.
1337 ASSERT_EQ(1u, native_browser_list
->size());
1339 EXPECT_FALSE(GetIsDragged(browser2
));
1341 // Remaining browser window should not be maximized
1342 EXPECT_FALSE(browser2
->window()->IsMaximized());
1345 #if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
1346 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1347 // compositor. crbug.com/331924
1348 #define MAYBE_DragDirectlyToSecondWindow DISABLED_DragDirectlyToSecondWindow
1350 #define MAYBE_DragDirectlyToSecondWindow DragDirectlyToSecondWindow
1352 // Creates two browsers, drags from first into the second in such a way that
1353 // no detaching should happen.
1354 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1355 MAYBE_DragDirectlyToSecondWindow
) {
1356 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1358 // Add another tab to browser().
1359 AddTabAndResetBrowser(browser());
1361 // Create another browser.
1362 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1363 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1365 // Move the tabstrip down enough so that we can detach.
1366 gfx::Rect
bounds(browser2
->window()->GetBounds());
1367 bounds
.Offset(0, 100);
1368 browser2
->window()->SetBounds(bounds
);
1370 // Move to the first tab and drag it enough so that it detaches, but not
1371 // enough that it attaches to browser2.
1372 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1373 ASSERT_TRUE(PressInput(tab_0_center
));
1375 gfx::Point
b2_location(5, 0);
1376 views::View::ConvertPointToScreen(tab_strip2
, &b2_location
);
1377 ASSERT_TRUE(DragInputTo(b2_location
));
1379 // Should now be attached to tab_strip2.
1380 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1381 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1382 ASSERT_TRUE(TabDragController::IsActive());
1384 // Release the mouse, stopping the drag session.
1385 ASSERT_TRUE(ReleaseInput());
1386 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1387 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1388 ASSERT_FALSE(TabDragController::IsActive());
1389 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1390 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1392 EXPECT_FALSE(GetIsDragged(browser()));
1393 EXPECT_FALSE(GetIsDragged(browser2
));
1395 // Both windows should not be maximized
1396 EXPECT_FALSE(browser()->window()->IsMaximized());
1397 EXPECT_FALSE(browser2
->window()->IsMaximized());
1400 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1401 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1402 // compositor. crbug.com/331924
1403 #define MAYBE_DragSingleTabToSeparateWindow \
1404 DISABLED_DragSingleTabToSeparateWindow
1406 #define MAYBE_DragSingleTabToSeparateWindow DragSingleTabToSeparateWindow
1408 // Creates two browsers, the first browser has a single tab and drags into the
1410 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1411 MAYBE_DragSingleTabToSeparateWindow
) {
1412 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1414 ResetIDs(browser()->tab_strip_model(), 0);
1416 // Create another browser.
1417 Browser
* browser2
= CreateAnotherWindowBrowserAndRelayout();
1418 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1419 const gfx::Rect
initial_bounds(browser2
->window()->GetBounds());
1421 // Move to the first tab and drag it enough so that it detaches, but not
1422 // enough that it attaches to browser2.
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(&DragAllToSeparateWindowStep2
, this, tab_strip
, tab_strip2
,
1429 native_browser_list
)));
1430 QuitWhenNotDragging();
1432 // Should now be attached to tab_strip2.
1433 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1434 ASSERT_TRUE(TabDragController::IsActive());
1435 ASSERT_EQ(1u, native_browser_list
->size());
1437 // Release the mouse, stopping the drag session.
1438 ASSERT_TRUE(ReleaseInput());
1439 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1440 ASSERT_FALSE(TabDragController::IsActive());
1441 EXPECT_EQ("100 0", IDString(browser2
->tab_strip_model()));
1443 EXPECT_FALSE(GetIsDragged(browser2
));
1445 // Remaining browser window should not be maximized
1446 EXPECT_FALSE(browser2
->window()->IsMaximized());
1448 // Make sure that the window is still managed and not user moved.
1449 EXPECT_TRUE(IsWindowPositionManaged(browser2
->window()->GetNativeWindow()));
1450 EXPECT_FALSE(HasUserChangedWindowPositionOrSize(
1451 browser2
->window()->GetNativeWindow()));
1452 // Also make sure that the drag to window position has not changed.
1453 EXPECT_EQ(initial_bounds
.ToString(),
1454 browser2
->window()->GetBounds().ToString());
1459 // Invoked from the nested message loop.
1460 void CancelOnNewTabWhenDraggingStep2(
1461 DetachToBrowserTabDragControllerTest
* test
,
1462 const BrowserList
* browser_list
) {
1463 ASSERT_TRUE(TabDragController::IsActive());
1464 ASSERT_EQ(2u, browser_list
->size());
1466 // Add another tab. This should trigger exiting the nested loop. Add at the
1467 // to exercise past crash when model/tabstrip got out of sync (474082).
1468 content::WindowedNotificationObserver
observer(
1469 content::NOTIFICATION_LOAD_STOP
,
1470 content::NotificationService::AllSources());
1471 chrome::AddTabAt(browser_list
->GetLastActive(), GURL(url::kAboutBlankURL
),
1478 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1479 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1480 // compositor. crbug.com/331924
1481 #define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging
1483 #define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging
1485 // Adds another tab, detaches into separate window, adds another tab and
1486 // verifies the run loop ends.
1487 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1488 MAYBE_CancelOnNewTabWhenDragging
) {
1489 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1491 // Add another tab to browser().
1492 AddTabAndResetBrowser(browser());
1494 // Move to the first tab and drag it enough so that it detaches.
1495 gfx::Point
tab_0_center(
1496 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1497 ASSERT_TRUE(PressInput(tab_0_center
));
1498 ASSERT_TRUE(DragInputToNotifyWhenDone(
1499 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1500 base::Bind(&CancelOnNewTabWhenDraggingStep2
, this, native_browser_list
)));
1501 QuitWhenNotDragging();
1503 // Should be two windows and not dragging.
1504 ASSERT_FALSE(TabDragController::IsActive());
1505 ASSERT_EQ(2u, native_browser_list
->size());
1506 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
1507 EXPECT_FALSE(GetIsDragged(*it
));
1508 // Should not be maximized
1509 EXPECT_FALSE(it
->window()->IsMaximized());
1513 #if defined(OS_CHROMEOS)
1514 // TODO(sky,sad): A number of tests below are disabled as they fail due to
1515 // resize locks with a real compositor. crbug.com/331924
1518 void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest
* test
,
1520 TabStrip
* tab_strip
,
1521 const BrowserList
* browser_list
) {
1522 // There should be another browser.
1523 ASSERT_EQ(2u, browser_list
->size());
1524 Browser
* new_browser
= browser_list
->get(1);
1525 EXPECT_NE(browser
, new_browser
);
1526 ASSERT_TRUE(new_browser
->window()->IsActive());
1527 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1529 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1530 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1532 // Both windows should be visible.
1533 EXPECT_TRUE(tab_strip
->GetWidget()->IsVisible());
1534 EXPECT_TRUE(tab_strip2
->GetWidget()->IsVisible());
1537 ASSERT_TRUE(test
->ReleaseInput());
1542 // Creates a browser with two tabs, maximizes it, drags the tab out.
1543 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
1544 DISABLED_DragInMaximizedWindow
) {
1545 AddTabAndResetBrowser(browser());
1546 browser()->window()->Maximize();
1548 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1550 // Move to the first tab and drag it enough so that it detaches.
1551 gfx::Point
tab_0_center(
1552 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1553 ASSERT_TRUE(PressInput(tab_0_center
));
1554 ASSERT_TRUE(DragInputToNotifyWhenDone(
1555 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1556 base::Bind(&DragInMaximizedWindowStep2
, this, browser(), tab_strip
,
1557 native_browser_list
)));
1558 QuitWhenNotDragging();
1560 ASSERT_FALSE(TabDragController::IsActive());
1562 // Should be two browsers.
1563 ASSERT_EQ(2u, native_browser_list
->size());
1564 Browser
* new_browser
= native_browser_list
->get(1);
1565 ASSERT_TRUE(new_browser
->window()->IsActive());
1567 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible());
1568 EXPECT_TRUE(new_browser
->window()->GetNativeWindow()->IsVisible());
1570 EXPECT_FALSE(GetIsDragged(browser()));
1571 EXPECT_FALSE(GetIsDragged(new_browser
));
1573 // The source window should be maximized.
1574 EXPECT_TRUE(browser()->window()->IsMaximized());
1575 // The new window should be maximized.
1576 EXPECT_TRUE(new_browser
->window()->IsMaximized());
1579 // Subclass of DetachToBrowserTabDragControllerTest that
1580 // creates multiple displays.
1581 class DetachToBrowserInSeparateDisplayTabDragControllerTest
1582 : public DetachToBrowserTabDragControllerTest
{
1584 DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1585 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1587 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1588 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1589 // Make screens sufficiently wide to host 2 browsers side by side.
1590 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1591 "0+0-600x600,601+0-600x600");
1595 DISALLOW_COPY_AND_ASSIGN(
1596 DetachToBrowserInSeparateDisplayTabDragControllerTest
);
1599 // Subclass of DetachToBrowserTabDragControllerTest that runs tests only with
1601 class DetachToBrowserTabDragControllerTestTouch
1602 : public DetachToBrowserTabDragControllerTest
{
1604 DetachToBrowserTabDragControllerTestTouch() {}
1605 virtual ~DetachToBrowserTabDragControllerTestTouch() {}
1608 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch
);
1613 void DragSingleTabToSeparateWindowInSecondDisplayStep3(
1614 DetachToBrowserTabDragControllerTest
* test
) {
1615 ASSERT_TRUE(test
->ReleaseInput());
1618 void DragSingleTabToSeparateWindowInSecondDisplayStep2(
1619 DetachToBrowserTabDragControllerTest
* test
,
1620 const gfx::Point
& target_point
) {
1621 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
1622 target_point
.x(), target_point
.y(),
1623 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3
, test
)));
1628 // Drags from browser to a second display and releases input.
1629 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1630 DISABLED_DragSingleTabToSeparateWindowInSecondDisplay
) {
1632 AddTabAndResetBrowser(browser());
1633 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1635 // Move to the first tab and drag it enough so that it detaches.
1636 // Then drag it to the final destination on the second screen.
1637 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1638 ASSERT_TRUE(PressInput(tab_0_center
));
1639 ASSERT_TRUE(DragInputToNotifyWhenDone(
1640 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1641 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2
,
1642 this, gfx::Point(600 + tab_0_center
.x(),
1644 + GetDetachY(tab_strip
)))));
1645 QuitWhenNotDragging();
1647 // Should no longer be dragging.
1648 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1649 ASSERT_FALSE(TabDragController::IsActive());
1651 // There should now be another browser.
1652 ASSERT_EQ(2u, native_browser_list
->size());
1653 Browser
* new_browser
= native_browser_list
->get(1);
1654 ASSERT_TRUE(new_browser
->window()->IsActive());
1655 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
1656 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1658 // This other browser should be on the second screen (with mouse drag)
1659 // With the touch input the browser cannot be dragged from one screen
1660 // to another and the window stays on the first screen.
1661 if (input_source() == INPUT_SOURCE_MOUSE
) {
1662 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1663 ASSERT_EQ(2u, roots
.size());
1664 aura::Window
* second_root
= roots
[1];
1665 EXPECT_EQ(second_root
,
1666 new_browser
->window()->GetNativeWindow()->GetRootWindow());
1669 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
1670 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1672 // Both windows should not be maximized
1673 EXPECT_FALSE(browser()->window()->IsMaximized());
1674 EXPECT_FALSE(new_browser
->window()->IsMaximized());
1679 // Invoked from the nested message loop.
1680 void DragTabToWindowInSeparateDisplayStep2(
1681 DetachToBrowserTabDragControllerTest
* test
,
1682 TabStrip
* not_attached_tab_strip
,
1683 TabStrip
* target_tab_strip
) {
1684 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
1685 ASSERT_FALSE(target_tab_strip
->IsDragSessionActive());
1686 ASSERT_TRUE(TabDragController::IsActive());
1688 // Drag to target_tab_strip. This should stop the nested loop from dragging
1690 gfx::Point
target_point(
1691 GetCenterInScreenCoordinates(target_tab_strip
->tab_at(0)));
1693 // Move it close to the beginning of the target tabstrip.
1695 target_point
.x() - target_tab_strip
->tab_at(0)->width() / 2 + 10);
1696 ASSERT_TRUE(test
->DragInputToAsync(target_point
));
1701 // Drags from browser to another browser on a second display and releases input.
1702 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1703 DISABLED_DragTabToWindowInSeparateDisplay
) {
1705 AddTabAndResetBrowser(browser());
1706 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1708 // Create another browser.
1709 Browser
* browser2
= CreateBrowser(browser()->profile());
1710 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1711 ResetIDs(browser2
->tab_strip_model(), 100);
1713 // Move the second browser to the second display.
1714 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1715 ASSERT_EQ(2u, roots
.size());
1716 aura::Window
* second_root
= roots
[1];
1717 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1718 second_root
).work_area();
1719 browser2
->window()->SetBounds(work_area
);
1720 EXPECT_EQ(second_root
,
1721 browser2
->window()->GetNativeWindow()->GetRootWindow());
1723 // Move to the first tab and drag it enough so that it detaches, but not
1724 // enough that it attaches to browser2.
1725 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1726 ASSERT_TRUE(PressInput(tab_0_center
));
1727 ASSERT_TRUE(DragInputToNotifyWhenDone(
1728 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1729 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1730 this, tab_strip
, tab_strip2
)));
1731 QuitWhenNotDragging();
1733 // Should now be attached to tab_strip2.
1734 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1735 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1736 ASSERT_TRUE(TabDragController::IsActive());
1738 // Release the mouse, stopping the drag session.
1739 ASSERT_TRUE(ReleaseInput());
1740 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1741 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1742 ASSERT_FALSE(TabDragController::IsActive());
1743 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1744 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1746 // Both windows should not be maximized
1747 EXPECT_FALSE(browser()->window()->IsMaximized());
1748 EXPECT_FALSE(browser2
->window()->IsMaximized());
1751 // Drags from browser to another browser on a second display and releases input.
1752 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1753 DISABLED_DragTabToWindowOnSecondDisplay
) {
1755 AddTabAndResetBrowser(browser());
1756 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1758 // Create another browser.
1759 Browser
* browser2
= CreateBrowser(browser()->profile());
1760 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1761 ResetIDs(browser2
->tab_strip_model(), 100);
1763 // Move both browsers to the second display.
1764 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1765 ASSERT_EQ(2u, roots
.size());
1766 aura::Window
* second_root
= roots
[1];
1767 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1768 second_root
).work_area();
1769 browser()->window()->SetBounds(work_area
);
1771 // position both browser windows side by side on the second screen.
1772 gfx::Rect
work_area2(work_area
);
1773 work_area
.set_width(work_area
.width()/2);
1774 browser()->window()->SetBounds(work_area
);
1775 work_area2
.set_x(work_area2
.x() + work_area2
.width()/2);
1776 work_area2
.set_width(work_area2
.width()/2);
1777 browser2
->window()->SetBounds(work_area2
);
1778 EXPECT_EQ(second_root
,
1779 browser()->window()->GetNativeWindow()->GetRootWindow());
1780 EXPECT_EQ(second_root
,
1781 browser2
->window()->GetNativeWindow()->GetRootWindow());
1783 // Move to the first tab and drag it enough so that it detaches, but not
1784 // enough that it attaches to browser2.
1785 // SetEventGeneratorRootWindow sets correct (second) RootWindow
1786 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1787 SetEventGeneratorRootWindow(tab_0_center
);
1788 ASSERT_TRUE(PressInput(tab_0_center
));
1789 ASSERT_TRUE(DragInputToNotifyWhenDone(
1790 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1791 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1792 this, tab_strip
, tab_strip2
)));
1793 QuitWhenNotDragging();
1795 // Should now be attached to tab_strip2.
1796 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1797 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1798 ASSERT_TRUE(TabDragController::IsActive());
1800 // Release the mouse, stopping the drag session.
1801 ASSERT_TRUE(ReleaseInput());
1802 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1803 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1804 ASSERT_FALSE(TabDragController::IsActive());
1805 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1806 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1808 // Both windows should not be maximized
1809 EXPECT_FALSE(browser()->window()->IsMaximized());
1810 EXPECT_FALSE(browser2
->window()->IsMaximized());
1813 // Drags from a maximized browser to another non-maximized browser on a second
1814 // display and releases input.
1815 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1816 DISABLED_DragMaxTabToNonMaxWindowInSeparateDisplay
) {
1818 AddTabAndResetBrowser(browser());
1819 browser()->window()->Maximize();
1820 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1822 // Create another browser on the second display.
1823 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1824 ASSERT_EQ(2u, roots
.size());
1825 aura::Window
* first_root
= roots
[0];
1826 aura::Window
* second_root
= roots
[1];
1827 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1828 second_root
).work_area();
1829 work_area
.Inset(20, 20, 20, 60);
1830 Browser::CreateParams
params(browser()->profile(),
1831 browser()->host_desktop_type());
1832 params
.initial_show_state
= ui::SHOW_STATE_NORMAL
;
1833 params
.initial_bounds
= work_area
;
1834 Browser
* browser2
= new Browser(params
);
1835 AddBlankTabAndShow(browser2
);
1837 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1838 ResetIDs(browser2
->tab_strip_model(), 100);
1840 EXPECT_EQ(second_root
,
1841 browser2
->window()->GetNativeWindow()->GetRootWindow());
1842 EXPECT_EQ(first_root
,
1843 browser()->window()->GetNativeWindow()->GetRootWindow());
1844 EXPECT_EQ(2, tab_strip
->tab_count());
1845 EXPECT_EQ(1, tab_strip2
->tab_count());
1847 // Move to the first tab and drag it enough so that it detaches, but not
1848 // enough that it attaches to browser2.
1849 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1850 ASSERT_TRUE(PressInput(tab_0_center
));
1851 ASSERT_TRUE(DragInputToNotifyWhenDone(
1852 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1853 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1854 this, tab_strip
, tab_strip2
)));
1855 QuitWhenNotDragging();
1857 // Should now be attached to tab_strip2.
1858 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1859 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1860 ASSERT_TRUE(TabDragController::IsActive());
1862 // Release the mouse, stopping the drag session.
1863 ASSERT_TRUE(ReleaseInput());
1865 // tab should have moved
1866 EXPECT_EQ(1, tab_strip
->tab_count());
1867 EXPECT_EQ(2, tab_strip2
->tab_count());
1869 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1870 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1871 ASSERT_FALSE(TabDragController::IsActive());
1872 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1873 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1875 // Source browser should still be maximized, target should not
1876 EXPECT_TRUE(browser()->window()->IsMaximized());
1877 EXPECT_FALSE(browser2
->window()->IsMaximized());
1880 // Drags from a restored browser to an immersive fullscreen browser on a
1881 // second display and releases input.
1882 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest
,
1883 DISABLED_DragTabToImmersiveBrowserOnSeparateDisplay
) {
1885 AddTabAndResetBrowser(browser());
1886 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
1888 // Create another browser.
1889 Browser
* browser2
= CreateBrowser(browser()->profile());
1890 TabStrip
* tab_strip2
= GetTabStripForBrowser(browser2
);
1891 ResetIDs(browser2
->tab_strip_model(), 100);
1893 // Move the second browser to the second display.
1894 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
1895 ASSERT_EQ(2u, roots
.size());
1896 aura::Window
* second_root
= roots
[1];
1897 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1898 second_root
).work_area();
1899 browser2
->window()->SetBounds(work_area
);
1900 EXPECT_EQ(second_root
,
1901 browser2
->window()->GetNativeWindow()->GetRootWindow());
1903 // Put the second browser into immersive fullscreen.
1904 BrowserView
* browser_view2
= BrowserView::GetBrowserViewForBrowser(browser2
);
1905 ImmersiveModeController
* immersive_controller2
=
1906 browser_view2
->immersive_mode_controller();
1907 immersive_controller2
->SetupForTest();
1908 chrome::ToggleFullscreenMode(browser2
);
1909 ASSERT_TRUE(immersive_controller2
->IsEnabled());
1910 ASSERT_FALSE(immersive_controller2
->IsRevealed());
1911 ASSERT_TRUE(tab_strip2
->IsImmersiveStyle());
1913 // Move to the first tab and drag it enough so that it detaches, but not
1914 // enough that it attaches to browser2.
1915 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
1916 ASSERT_TRUE(PressInput(tab_0_center
));
1917 ASSERT_TRUE(DragInputToNotifyWhenDone(
1918 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
1919 base::Bind(&DragTabToWindowInSeparateDisplayStep2
,
1920 this, tab_strip
, tab_strip2
)));
1921 QuitWhenNotDragging();
1923 // Should now be attached to tab_strip2.
1924 ASSERT_TRUE(tab_strip2
->IsDragSessionActive());
1925 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1926 ASSERT_TRUE(TabDragController::IsActive());
1928 // browser2's top chrome should be revealed and the tab strip should be
1929 // at normal height while user is tragging tabs_strip2's tabs.
1930 ASSERT_TRUE(immersive_controller2
->IsRevealed());
1931 ASSERT_FALSE(tab_strip2
->IsImmersiveStyle());
1933 // Release the mouse, stopping the drag session.
1934 ASSERT_TRUE(ReleaseInput());
1935 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
1936 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
1937 ASSERT_FALSE(TabDragController::IsActive());
1938 EXPECT_EQ("0 100", IDString(browser2
->tab_strip_model()));
1939 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1941 // Move the mouse off of browser2's top chrome.
1942 aura::Window
* primary_root
= roots
[0];
1943 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
1944 primary_root
->GetBoundsInScreen().CenterPoint()));
1946 // The first browser window should not be in immersive fullscreen.
1947 // browser2 should still be in immersive fullscreen, but the top chrome should
1948 // no longer be revealed.
1949 BrowserView
* browser_view
= BrowserView::GetBrowserViewForBrowser(browser());
1950 EXPECT_FALSE(browser_view
->immersive_mode_controller()->IsEnabled());
1952 EXPECT_TRUE(immersive_controller2
->IsEnabled());
1953 EXPECT_FALSE(immersive_controller2
->IsRevealed());
1954 EXPECT_TRUE(tab_strip2
->IsImmersiveStyle());
1957 // Subclass of DetachToBrowserTabDragControllerTest that
1958 // creates multiple displays with different device scale factors.
1959 class DifferentDeviceScaleFactorDisplayTabDragControllerTest
1960 : public DetachToBrowserTabDragControllerTest
{
1962 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1963 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1965 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
1966 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line
);
1967 command_line
->AppendSwitchASCII("ash-host-window-bounds",
1968 "400x400,0+400-800x800*2");
1971 float GetCursorDeviceScaleFactor() const {
1972 ash::test::CursorManagerTestApi
cursor_test_api(
1973 ash::Shell::GetInstance()->cursor_manager());
1974 return cursor_test_api
.GetCurrentCursor().device_scale_factor();
1978 DISALLOW_COPY_AND_ASSIGN(
1979 DifferentDeviceScaleFactorDisplayTabDragControllerTest
);
1984 // The points where a tab is dragged in CursorDeviceScaleFactorStep.
1985 const struct DragPoint
{
1996 // The expected device scale factors before the cursor is moved to the
1997 // corresponding kDragPoints in CursorDeviceScaleFactorStep.
1998 const float kDeviceScaleFactorExpectations
[] = {
2007 arraysize(kDragPoints
) == arraysize(kDeviceScaleFactorExpectations
),
2008 "kDragPoints and kDeviceScaleFactorExpectations must have the same "
2009 "number of elements");
2011 // Drags tab to |kDragPoints[index]|, then calls the next step function.
2012 void CursorDeviceScaleFactorStep(
2013 DifferentDeviceScaleFactorDisplayTabDragControllerTest
* test
,
2014 TabStrip
* not_attached_tab_strip
,
2016 ASSERT_FALSE(not_attached_tab_strip
->IsDragSessionActive());
2017 ASSERT_TRUE(TabDragController::IsActive());
2019 if (index
< arraysize(kDragPoints
)) {
2020 EXPECT_EQ(kDeviceScaleFactorExpectations
[index
],
2021 test
->GetCursorDeviceScaleFactor());
2022 const DragPoint p
= kDragPoints
[index
];
2023 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
2024 p
.x
, p
.y
, base::Bind(&CursorDeviceScaleFactorStep
,
2025 test
, not_attached_tab_strip
, index
+ 1)));
2027 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag.
2028 EXPECT_EQ(1.0f
, test
->GetCursorDeviceScaleFactor());
2029 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2030 ui_controls::LEFT
, ui_controls::UP
));
2036 // Verifies cursor's device scale factor is updated when a tab is moved across
2037 // displays with different device scale factors (http://crbug.com/154183).
2038 IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
2039 DISABLED_CursorDeviceScaleFactor
) {
2041 AddTabAndResetBrowser(browser());
2042 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2044 // Move the second browser to the second display.
2045 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2046 ASSERT_EQ(2u, roots
.size());
2048 // Move to the first tab and drag it enough so that it detaches.
2049 gfx::Point
tab_0_center(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2050 ASSERT_TRUE(PressInput(tab_0_center
));
2051 ASSERT_TRUE(DragInputToNotifyWhenDone(
2052 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2053 base::Bind(&CursorDeviceScaleFactorStep
,
2054 this, tab_strip
, 0)));
2055 QuitWhenNotDragging();
2060 class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
2061 : public TabDragControllerTest
{
2063 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {}
2065 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
2066 TabDragControllerTest::SetUpCommandLine(command_line
);
2067 command_line
->AppendSwitchASCII("ash-host-window-bounds",
2068 "0+0-250x250,251+0-250x250");
2071 bool Press(const gfx::Point
& position
) {
2072 return ui_test_utils::SendMouseMoveSync(position
) &&
2073 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT
,
2077 bool DragTabAndExecuteTaskWhenDone(const gfx::Point
& position
,
2078 const base::Closure
& task
) {
2079 return ui_controls::SendMouseMoveNotifyWhenDone(
2080 position
.x(), position
.y(), task
);
2083 void QuitWhenNotDragging() {
2084 test::QuitWhenNotDraggingImpl();
2085 base::MessageLoop::current()->Run();
2089 DISALLOW_COPY_AND_ASSIGN(
2090 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
);
2093 // Invoked from the nested message loop.
2094 void CancelDragTabToWindowInSeparateDisplayStep3(
2095 TabStrip
* tab_strip
,
2096 const BrowserList
* browser_list
) {
2097 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2098 ASSERT_TRUE(TabDragController::IsActive());
2099 ASSERT_EQ(2u, browser_list
->size());
2101 // Switching display mode should cancel the drag operation.
2102 ash::DisplayManager
* display_manager
=
2103 ash::Shell::GetInstance()->display_manager();
2104 display_manager
->AddRemoveDisplay();
2107 // Invoked from the nested message loop.
2108 void CancelDragTabToWindowInSeparateDisplayStep2(
2109 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
* test
,
2110 TabStrip
* tab_strip
,
2111 aura::Window
* current_root
,
2112 gfx::Point final_destination
,
2113 const BrowserList
* browser_list
) {
2114 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2115 ASSERT_TRUE(TabDragController::IsActive());
2116 ASSERT_EQ(2u, browser_list
->size());
2118 Browser
* new_browser
= browser_list
->get(1);
2119 EXPECT_EQ(current_root
,
2120 new_browser
->window()->GetNativeWindow()->GetRootWindow());
2122 ASSERT_TRUE(test
->DragTabAndExecuteTaskWhenDone(
2124 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3
,
2125 tab_strip
, browser_list
)));
2130 // Drags from browser to a second display and releases input.
2131 IN_PROC_BROWSER_TEST_F(
2132 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
2133 DISABLED_CancelDragTabToWindowIn2ndDisplay
) {
2135 AddTabAndResetBrowser(browser());
2136 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2138 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2140 // Move the second browser to the second display.
2141 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2142 ASSERT_EQ(2u, roots
.size());
2143 gfx::Point final_destination
=
2144 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2145 roots
[1]).work_area().CenterPoint();
2147 // Move to the first tab and drag it enough so that it detaches, but not
2148 // enough to move to another display.
2149 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2150 ASSERT_TRUE(Press(tab_0_dst
));
2151 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2152 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2153 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2154 this, tab_strip
, roots
[0], final_destination
,
2155 native_browser_list
)));
2156 QuitWhenNotDragging();
2158 ASSERT_EQ(1u, native_browser_list
->size());
2159 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2160 ASSERT_FALSE(TabDragController::IsActive());
2161 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2163 // Release the mouse
2164 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2165 ui_controls::LEFT
, ui_controls::UP
));
2168 // Drags from browser from a second display to primary and releases input.
2169 IN_PROC_BROWSER_TEST_F(
2170 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
,
2171 DISABLED_CancelDragTabToWindowIn1stDisplay
) {
2172 aura::Window::Windows roots
= ash::Shell::GetAllRootWindows();
2173 ASSERT_EQ(2u, roots
.size());
2176 AddTabAndResetBrowser(browser());
2177 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2179 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2180 EXPECT_EQ(roots
[0], browser()->window()->GetNativeWindow()->GetRootWindow());
2182 gfx::Rect work_area
= gfx::Screen::GetNativeScreen()->
2183 GetDisplayNearestWindow(roots
[1]).work_area();
2184 browser()->window()->SetBounds(work_area
);
2185 EXPECT_EQ(roots
[1], browser()->window()->GetNativeWindow()->GetRootWindow());
2187 // Move the second browser to the display.
2188 gfx::Point final_destination
=
2189 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2190 roots
[0]).work_area().CenterPoint();
2192 // Move to the first tab and drag it enough so that it detaches, but not
2193 // enough to move to another display.
2194 gfx::Point
tab_0_dst(GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2195 ASSERT_TRUE(Press(tab_0_dst
));
2196 tab_0_dst
.Offset(0, GetDetachY(tab_strip
));
2197 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2198 tab_0_dst
, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2
,
2199 this, tab_strip
, roots
[1], final_destination
,
2200 native_browser_list
)));
2201 QuitWhenNotDragging();
2203 ASSERT_EQ(1u, native_browser_list
->size());
2204 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2205 ASSERT_FALSE(TabDragController::IsActive());
2206 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2208 // Release the mouse
2209 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2210 ui_controls::LEFT
, ui_controls::UP
));
2215 void PressSecondFingerWhileDetachedStep2(
2216 DetachToBrowserTabDragControllerTest
* test
) {
2217 ASSERT_TRUE(TabDragController::IsActive());
2218 ASSERT_EQ(2u, test
->native_browser_list
->size());
2219 Browser
* new_browser
= test
->native_browser_list
->get(1);
2220 ASSERT_TRUE(new_browser
->window()->IsActive());
2222 ASSERT_TRUE(test
->PressInput2());
2227 // Detaches a tab and while detached presses a second finger.
2228 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch
,
2229 DISABLED_PressSecondFingerWhileDetached
) {
2230 gfx::Rect
bounds(browser()->window()->GetBounds());
2232 AddTabAndResetBrowser(browser());
2233 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2234 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2236 // Move to the first tab and drag it enough so that it detaches.
2237 gfx::Point
tab_0_center(
2238 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2239 ASSERT_TRUE(PressInput(tab_0_center
));
2240 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone(
2241 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2242 base::Bind(&PressSecondFingerWhileDetachedStep2
, this),
2243 base::TimeDelta::FromMilliseconds(60)));
2244 QuitWhenNotDragging();
2246 // The drag should have been reverted.
2247 ASSERT_EQ(1u, native_browser_list
->size());
2248 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2249 ASSERT_FALSE(TabDragController::IsActive());
2250 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2252 ASSERT_TRUE(ReleaseInput());
2253 ASSERT_TRUE(ReleaseInput2());
2256 #if defined(OS_CHROMEOS)
2260 void DetachToDockedWindowNextStep(
2261 DetachToBrowserTabDragControllerTest
* test
,
2262 const gfx::Point
& target_point
,
2264 ASSERT_EQ(2u, test
->native_browser_list
->size());
2265 Browser
* new_browser
= test
->native_browser_list
->get(1);
2266 ASSERT_TRUE(new_browser
->window()->IsActive());
2269 ASSERT_TRUE(test
->ReleaseInput());
2272 ASSERT_TRUE(test
->DragInputToNotifyWhenDone(
2273 target_point
.x(), target_point
.y(),
2274 base::Bind(&DetachToDockedWindowNextStep
,
2276 gfx::Point(target_point
.x(), 1 + target_point
.y()),
2282 // Drags from browser to separate window, docks that window and releases mouse.
2283 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest
,
2284 DISABLED_DetachToDockedWindowFromMaximizedWindow
) {
2285 // Maximize the initial browser window.
2286 browser()->window()->Maximize();
2287 ASSERT_TRUE(browser()->window()->IsMaximized());
2290 AddTabAndResetBrowser(browser());
2291 TabStrip
* tab_strip
= GetTabStripForBrowser(browser());
2293 // Move to the first tab and drag it enough so that it detaches.
2294 gfx::Point
tab_0_center(
2295 GetCenterInScreenCoordinates(tab_strip
->tab_at(0)));
2296 ASSERT_TRUE(PressInput(tab_0_center
));
2298 // The following matches kMovesBeforeAdjust in snap_sizer.cc
2299 const int kNumIterations
= 25 * 5 + 10;
2300 ASSERT_TRUE(DragInputToNotifyWhenDone(
2301 tab_0_center
.x(), tab_0_center
.y() + GetDetachY(tab_strip
),
2302 base::Bind(&DetachToDockedWindowNextStep
, this,
2303 gfx::Point(0, tab_0_center
.y() + GetDetachY(tab_strip
)),
2305 // Continue dragging enough times to go through snapping sequence and dock
2307 QuitWhenNotDragging();
2308 // Should no longer be dragging.
2309 ASSERT_FALSE(tab_strip
->IsDragSessionActive());
2310 ASSERT_FALSE(TabDragController::IsActive());
2312 // There should now be another browser.
2313 ASSERT_EQ(2u, native_browser_list
->size());
2314 Browser
* new_browser
= native_browser_list
->get(1);
2315 ASSERT_TRUE(new_browser
->window()->IsActive());
2316 TabStrip
* tab_strip2
= GetTabStripForBrowser(new_browser
);
2317 ASSERT_FALSE(tab_strip2
->IsDragSessionActive());
2319 EXPECT_EQ("0", IDString(new_browser
->tab_strip_model()));
2320 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
2322 // The bounds of the initial window should not have changed.
2323 EXPECT_TRUE(browser()->window()->IsMaximized());
2325 EXPECT_FALSE(GetIsDragged(browser()));
2326 EXPECT_FALSE(GetIsDragged(new_browser
));
2327 // After this both windows should still be manageable.
2328 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
2329 EXPECT_TRUE(IsWindowPositionManaged(
2330 new_browser
->window()->GetNativeWindow()));
2332 ash::wm::WindowState
* window_state
=
2333 ash::wm::GetWindowState(new_browser
->window()->GetNativeWindow());
2334 // The new window should not be maximized because it gets docked or snapped.
2335 EXPECT_FALSE(new_browser
->window()->IsMaximized());
2336 // The new window should be docked and not snapped.
2337 EXPECT_TRUE(window_state
->IsDocked());
2338 EXPECT_FALSE(window_state
->IsSnapped());
2341 #endif // OS_CHROMEOS
2345 #if defined(USE_ASH) && defined(OS_CHROMEOS) // TODO(win_ash,linux_ash)
2346 INSTANTIATE_TEST_CASE_P(TabDragging
,
2347 DetachToBrowserInSeparateDisplayTabDragControllerTest
,
2348 ::testing::Values("mouse", "touch"));
2349 INSTANTIATE_TEST_CASE_P(TabDragging
,
2350 DifferentDeviceScaleFactorDisplayTabDragControllerTest
,
2351 ::testing::Values("mouse"));
2352 INSTANTIATE_TEST_CASE_P(TabDragging
,
2353 DetachToBrowserTabDragControllerTest
,
2354 ::testing::Values("mouse", "touch"));
2355 INSTANTIATE_TEST_CASE_P(TabDragging
,
2356 DetachToBrowserTabDragControllerTestTouch
,
2357 ::testing::Values("touch"));
2358 #elif defined(USE_ASH)
2359 INSTANTIATE_TEST_CASE_P(TabDragging
,
2360 DetachToBrowserTabDragControllerTest
,
2361 ::testing::Values("mouse"));