Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / chrome / browser / ui / views / tabs / tab_drag_controller_interactive_uitest.cc
blob5f5831b13634040dbf4cf6d8747c2df86d968928
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"
8 #include "base/bind.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"
42 #endif
44 #if defined(USE_ASH)
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/root_window.h"
56 #include "ui/aura/test/event_generator.h"
57 #endif
59 using content::WebContents;
61 namespace test {
63 namespace {
65 const char kTabDragControllerInteractiveUITestUserDataKey[] =
66 "TabDragControllerInteractiveUITestUserData";
68 class TabDragControllerInteractiveUITestUserData
69 : public base::SupportsUserData::Data {
70 public:
71 explicit TabDragControllerInteractiveUITestUserData(int id) : id_(id) {}
72 virtual ~TabDragControllerInteractiveUITestUserData() {}
73 int id() { return id_; }
75 private:
76 int id_;
79 } // namespace
81 class QuitDraggingObserver : public content::NotificationObserver {
82 public:
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();
93 delete this;
96 private:
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, &center);
107 return center;
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) {
121 std::string result;
122 for (int i = 0; i < model->count(); ++i) {
123 if (i != 0)
124 result += " ";
125 WebContents* contents = model->GetWebContentsAt(i);
126 TabDragControllerInteractiveUITestUserData* user_data =
127 static_cast<TabDragControllerInteractiveUITestUserData*>(
128 contents->GetUserData(
129 &kTabDragControllerInteractiveUITestUserDataKey));
130 if (user_data)
131 result += base::IntToString(user_data->id());
132 else
133 result += "?";
135 return result;
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());
148 } // namespace test
150 using test::GetCenterInScreenCoordinates;
151 using test::SetID;
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::SetUp() {
165 // TODO(danakj): Remove this when the tests are not flaky (crbug.com/270065)
166 // or we use test contexts in the renderer to keep things fast enough to
167 // avoid the flake (crbug.com/270918).
168 UseRealGLBindings();
170 InProcessBrowserTest::SetUp();
173 void TabDragControllerTest::StopAnimating(TabStrip* tab_strip) {
174 tab_strip->StopAnimating(true);
177 void TabDragControllerTest::AddTabAndResetBrowser(Browser* browser) {
178 AddBlankTabAndShow(browser);
179 StopAnimating(GetTabStripForBrowser(browser));
180 ResetIDs(browser->tab_strip_model(), 0);
183 Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
184 // Create another browser.
185 Browser* browser2 = CreateBrowser(browser()->profile());
186 ResetIDs(browser2->tab_strip_model(), 100);
188 // Resize the two windows so they're right next to each other.
189 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
190 browser()->window()->GetNativeWindow()).work_area();
191 gfx::Size half_size =
192 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10);
193 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size));
194 browser2->window()->SetBounds(gfx::Rect(
195 work_area.x() + half_size.width(), work_area.y(),
196 half_size.width(), half_size.height()));
197 return browser2;
200 namespace {
202 enum InputSource {
203 INPUT_SOURCE_MOUSE = 0,
204 INPUT_SOURCE_TOUCH = 1
207 int GetDetachY(TabStrip* tab_strip) {
208 return std::max(TabDragController::kTouchVerticalDetachMagnetism,
209 TabDragController::kVerticalDetachMagnetism) +
210 tab_strip->height() + 1;
213 bool GetIsDragged(Browser* browser) {
214 #if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash)
215 return false;
216 #else
217 return ash::wm::GetWindowState(browser->window()->GetNativeWindow())->
218 is_dragged();
219 #endif
222 } // namespace
224 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
225 class ScreenEventGeneratorDelegate : public aura::test::EventGeneratorDelegate {
226 public:
227 explicit ScreenEventGeneratorDelegate(aura::Window* root_window)
228 : root_window_(root_window) {}
229 virtual ~ScreenEventGeneratorDelegate() {}
231 // EventGeneratorDelegate overrides:
232 virtual aura::RootWindow* GetRootWindowAt(
233 const gfx::Point& point) const OVERRIDE {
234 return root_window_->GetDispatcher();
237 virtual aura::client::ScreenPositionClient* GetScreenPositionClient(
238 const aura::Window* window) const OVERRIDE {
239 return aura::client::GetScreenPositionClient(root_window_);
242 private:
243 aura::Window* root_window_;
245 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate);
248 #endif
250 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
252 // Following classes verify a crash scenario. Specifically on Windows when focus
253 // changes it can trigger capture being lost. This was causing a crash in tab
254 // dragging as it wasn't set up to handle this scenario. These classes
255 // synthesize this scenario.
257 // Allows making ClearNativeFocus() invoke ReleaseCapture().
258 class TestDesktopBrowserFrameAura : public DesktopBrowserFrameAura {
259 public:
260 TestDesktopBrowserFrameAura(
261 BrowserFrame* browser_frame,
262 BrowserView* browser_view)
263 : DesktopBrowserFrameAura(browser_frame, browser_view),
264 release_capture_(false) {}
265 virtual ~TestDesktopBrowserFrameAura() {}
267 void ReleaseCaptureOnNextClear() {
268 release_capture_ = true;
271 virtual void ClearNativeFocus() OVERRIDE {
272 views::DesktopNativeWidgetAura::ClearNativeFocus();
273 if (release_capture_) {
274 release_capture_ = false;
275 GetWidget()->ReleaseCapture();
279 private:
280 // If true ReleaseCapture() is invoked in ClearNativeFocus().
281 bool release_capture_;
283 DISALLOW_COPY_AND_ASSIGN(TestDesktopBrowserFrameAura);
286 // Factory for creating a TestDesktopBrowserFrameAura.
287 class TestNativeBrowserFrameFactory : public NativeBrowserFrameFactory {
288 public:
289 TestNativeBrowserFrameFactory() {}
290 virtual ~TestNativeBrowserFrameFactory() {}
292 virtual NativeBrowserFrame* Create(
293 BrowserFrame* browser_frame,
294 BrowserView* browser_view) OVERRIDE {
295 return new TestDesktopBrowserFrameAura(browser_frame, browser_view);
298 private:
299 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory);
302 class TabDragCaptureLostTest : public TabDragControllerTest {
303 public:
304 TabDragCaptureLostTest() {
305 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory);
308 private:
309 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest);
312 // See description above for details.
313 IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest, ReleaseCaptureOnDrag) {
314 AddTabAndResetBrowser(browser());
316 TabStrip* tab_strip = GetTabStripForBrowser(browser());
317 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1)));
318 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center) &&
319 ui_test_utils::SendMouseEventsSync(
320 ui_controls::LEFT, ui_controls::DOWN));
321 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
322 TestDesktopBrowserFrameAura* frame =
323 static_cast<TestDesktopBrowserFrameAura*>(
324 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()->
325 native_widget_private());
326 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus
327 // changes capture is released and the drag cancels.
328 frame->ReleaseCaptureOnNextClear();
329 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center));
330 EXPECT_FALSE(tab_strip->IsDragSessionActive());
333 IN_PROC_BROWSER_TEST_F(TabDragControllerTest, GestureEndShouldEndDragTest) {
334 AddTabAndResetBrowser(browser());
336 TabStrip* tab_strip = GetTabStripForBrowser(browser());
337 TabStripModel* model = browser()->tab_strip_model();
339 Tab* tab1 = tab_strip->tab_at(1);
340 gfx::Point tab_1_center(tab1->width() / 2, tab1->height() / 2);
342 ui::GestureEvent gesture_begin(ui::ET_GESTURE_BEGIN, tab_1_center.x(),
343 tab_1_center.x(), 0, base::TimeDelta(),
344 ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0.0f, 0.0f), 0);
345 tab_strip->MaybeStartDrag(tab1, gesture_begin,
346 tab_strip->GetSelectionModel());
347 //tab_strip->tab_at(1)->OnGestureEvent(&gesture_begin);
348 EXPECT_TRUE(TabDragController::IsActive());
350 ui::GestureEvent gesture_end(ui::ET_GESTURE_END, tab_1_center.x(),
351 tab_1_center.x(), 0, base::TimeDelta(),
352 ui::GestureEventDetails(ui::ET_GESTURE_END, 0.0f, 0.0f), 0);
353 tab_strip->OnGestureEvent(&gesture_end);
354 EXPECT_FALSE(TabDragController::IsActive());
355 EXPECT_FALSE(tab_strip->IsDragSessionActive());
358 #endif
360 class DetachToBrowserTabDragControllerTest
361 : public TabDragControllerTest,
362 public ::testing::WithParamInterface<const char*> {
363 public:
364 DetachToBrowserTabDragControllerTest() {}
366 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
367 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
368 if (!docked_windows_enabled()) {
369 CommandLine::ForCurrentProcess()->AppendSwitch(
370 ash::switches::kAshDisableDockedWindows);
372 #endif
375 virtual void SetUpOnMainThread() OVERRIDE {
376 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
377 event_generator_.reset(new aura::test::EventGenerator(
378 ash::Shell::GetPrimaryRootWindow()));
379 #endif
382 InputSource input_source() const {
383 return strstr(GetParam(), "mouse") ?
384 INPUT_SOURCE_MOUSE : INPUT_SOURCE_TOUCH;
387 bool docked_windows_enabled() const {
388 return (strstr(GetParam(), "docked") != NULL);
391 // Set root window from a point in screen coordinates
392 void SetEventGeneratorRootWindow(const gfx::Point& point) {
393 if (input_source() == INPUT_SOURCE_MOUSE)
394 return;
395 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
396 event_generator_.reset(new aura::test::EventGenerator(
397 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point))));
398 #endif
401 // The following methods update one of the mouse or touch input depending upon
402 // the InputSource.
403 bool PressInput(const gfx::Point& location) {
404 if (input_source() == INPUT_SOURCE_MOUSE) {
405 return ui_test_utils::SendMouseMoveSync(location) &&
406 ui_test_utils::SendMouseEventsSync(
407 ui_controls::LEFT, ui_controls::DOWN);
409 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
410 event_generator_->set_current_location(location);
411 event_generator_->PressTouch();
412 #else
413 NOTREACHED();
414 #endif
415 return true;
418 bool PressInput2() {
419 // Second touch input is only used for touch sequence tests.
420 EXPECT_EQ(INPUT_SOURCE_TOUCH, input_source());
421 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
422 event_generator_->set_current_location(
423 event_generator_->current_location());
424 event_generator_->PressTouchId(1);
425 #else
426 NOTREACHED();
427 #endif
428 return true;
431 bool DragInputTo(const gfx::Point& location) {
432 if (input_source() == INPUT_SOURCE_MOUSE)
433 return ui_test_utils::SendMouseMoveSync(location);
434 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
435 event_generator_->MoveTouch(location);
436 #else
437 NOTREACHED();
438 #endif
439 return true;
442 bool DragInputToAsync(const gfx::Point& location) {
443 if (input_source() == INPUT_SOURCE_MOUSE)
444 return ui_controls::SendMouseMove(location.x(), location.y());
445 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
446 event_generator_->MoveTouch(location);
447 #else
448 NOTREACHED();
449 #endif
450 return true;
453 bool DragInputToNotifyWhenDone(int x,
454 int y,
455 const base::Closure& task) {
456 if (input_source() == INPUT_SOURCE_MOUSE)
457 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task);
458 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
459 base::MessageLoop::current()->PostTask(FROM_HERE, task);
460 event_generator_->MoveTouch(gfx::Point(x, y));
461 #else
462 NOTREACHED();
463 #endif
464 return true;
467 bool DragInputToDelayedNotifyWhenDone(int x,
468 int y,
469 const base::Closure& task,
470 base::TimeDelta delay) {
471 if (input_source() == INPUT_SOURCE_MOUSE)
472 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task);
473 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
474 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, task, delay);
475 event_generator_->MoveTouch(gfx::Point(x, y));
476 #else
477 NOTREACHED();
478 #endif
479 return true;
482 bool DragInput2ToNotifyWhenDone(int x,
483 int y,
484 const base::Closure& task) {
485 if (input_source() == INPUT_SOURCE_MOUSE)
486 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task);
487 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
488 base::MessageLoop::current()->PostTask(FROM_HERE, task);
489 event_generator_->MoveTouchId(gfx::Point(x, y), 1);
490 #else
491 NOTREACHED();
492 #endif
493 return true;
496 bool ReleaseInput() {
497 if (input_source() == INPUT_SOURCE_MOUSE) {
498 return ui_test_utils::SendMouseEventsSync(
499 ui_controls::LEFT, ui_controls::UP);
501 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
502 event_generator_->ReleaseTouch();
503 #else
504 NOTREACHED();
505 #endif
506 return true;
509 bool ReleaseInput2() {
510 if (input_source() == INPUT_SOURCE_MOUSE) {
511 return ui_test_utils::SendMouseEventsSync(
512 ui_controls::LEFT, ui_controls::UP);
514 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
515 event_generator_->ReleaseTouchId(1);
516 #else
517 NOTREACHED();
518 #endif
519 return true;
522 bool ReleaseMouseAsync() {
523 return input_source() == INPUT_SOURCE_MOUSE &&
524 ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP);
527 void QuitWhenNotDragging() {
528 if (input_source() == INPUT_SOURCE_MOUSE) {
529 // Schedule observer to quit message loop when done dragging. This has to
530 // be async so the message loop can run.
531 test::QuitWhenNotDraggingImpl();
532 base::MessageLoop::current()->Run();
533 } else {
534 // Touch events are sync, so we know we're not in a drag session. But some
535 // tests rely on the browser fully closing, which is async. So, run all
536 // pending tasks.
537 base::RunLoop run_loop;
538 run_loop.RunUntilIdle();
542 void AddBlankTabAndShow(Browser* browser) {
543 InProcessBrowserTest::AddBlankTabAndShow(browser);
546 Browser* browser() const { return InProcessBrowserTest::browser(); }
548 private:
549 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
550 scoped_ptr<aura::test::EventGenerator> event_generator_;
551 #endif
553 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest);
556 // Creates a browser with two tabs, drags the second to the first.
557 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragInSameWindow) {
558 // TODO(sky): this won't work with touch as it requires a long press.
559 if (input_source() == INPUT_SOURCE_TOUCH) {
560 VLOG(1) << "Test is DISABLED for touch input.";
561 return;
564 AddTabAndResetBrowser(browser());
566 TabStrip* tab_strip = GetTabStripForBrowser(browser());
567 TabStripModel* model = browser()->tab_strip_model();
569 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1)));
570 ASSERT_TRUE(PressInput(tab_1_center));
571 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
572 ASSERT_TRUE(DragInputTo(tab_0_center));
573 ASSERT_TRUE(ReleaseInput());
574 EXPECT_EQ("1 0", IDString(model));
575 EXPECT_FALSE(TabDragController::IsActive());
576 EXPECT_FALSE(tab_strip->IsDragSessionActive());
579 namespace {
581 // Invoked from the nested message loop.
582 void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test,
583 TabStrip* not_attached_tab_strip,
584 TabStrip* target_tab_strip) {
585 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive());
586 ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
587 ASSERT_TRUE(TabDragController::IsActive());
589 // Drag to target_tab_strip. This should stop the nested loop from dragging
590 // the window.
591 gfx::Point target_point(target_tab_strip->width() -1,
592 target_tab_strip->height() / 2);
593 views::View::ConvertPointToScreen(target_tab_strip, &target_point);
594 ASSERT_TRUE(test->DragInputToAsync(target_point));
597 } // namespace
599 #if defined(OS_CHROMEOS)
600 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
601 // compositor. crbug.com/331924
602 #define MAYBE_DragToSeparateWindow DISABLED_DragToSeparateWindow
603 #else
604 #define MAYBE_DragToSeparateWindow DragToSeparateWindow
605 #endif
606 // Creates two browsers, drags from first into second.
607 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
608 MAYBE_DragToSeparateWindow) {
609 TabStrip* tab_strip = GetTabStripForBrowser(browser());
611 // Add another tab to browser().
612 AddTabAndResetBrowser(browser());
614 // Create another browser.
615 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
616 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
618 // Move to the first tab and drag it enough so that it detaches, but not
619 // enough that it attaches to browser2.
620 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
621 ASSERT_TRUE(PressInput(tab_0_center));
622 ASSERT_TRUE(DragInputToNotifyWhenDone(
623 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
624 base::Bind(&DragToSeparateWindowStep2,
625 this, tab_strip, tab_strip2)));
626 QuitWhenNotDragging();
628 // Should now be attached to tab_strip2.
629 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
630 ASSERT_FALSE(tab_strip->IsDragSessionActive());
631 ASSERT_TRUE(TabDragController::IsActive());
632 EXPECT_FALSE(GetIsDragged(browser()));
634 // Release the mouse, stopping the drag session.
635 ASSERT_TRUE(ReleaseInput());
636 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
637 ASSERT_FALSE(tab_strip->IsDragSessionActive());
638 ASSERT_FALSE(TabDragController::IsActive());
639 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model()));
640 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
641 EXPECT_FALSE(GetIsDragged(browser2));
643 // Both windows should not be maximized
644 EXPECT_FALSE(browser()->window()->IsMaximized());
645 EXPECT_FALSE(browser2->window()->IsMaximized());
648 namespace {
650 void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest* test) {
651 if (test->input_source() == INPUT_SOURCE_TOUCH)
652 ASSERT_TRUE(test->ReleaseInput());
655 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
656 bool IsWindowPositionManaged(aura::Window* window) {
657 return ash::wm::GetWindowState(window)->window_position_managed();
659 bool HasUserChangedWindowPositionOrSize(aura::Window* window) {
660 return ash::wm::GetWindowState(window)->bounds_changed_by_user();
662 #else
663 bool IsWindowPositionManaged(gfx::NativeWindow window) {
664 return true;
666 bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window) {
667 return false;
669 #endif
671 } // namespace
673 #if defined(OS_CHROMEOS)
674 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
675 // compositor. crbug.com/331924
676 #define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow
677 #else
678 #define MAYBE_DetachToOwnWindow DetachToOwnWindow
679 #endif
680 // Drags from browser to separate window and releases mouse.
681 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
682 MAYBE_DetachToOwnWindow) {
683 const gfx::Rect initial_bounds(browser()->window()->GetBounds());
684 // Add another tab.
685 AddTabAndResetBrowser(browser());
686 TabStrip* tab_strip = GetTabStripForBrowser(browser());
688 // Move to the first tab and drag it enough so that it detaches.
689 gfx::Point tab_0_center(
690 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
691 ASSERT_TRUE(PressInput(tab_0_center));
692 ASSERT_TRUE(DragInputToNotifyWhenDone(
693 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
694 base::Bind(&DetachToOwnWindowStep2, this)));
695 if (input_source() == INPUT_SOURCE_MOUSE) {
696 ASSERT_TRUE(ReleaseMouseAsync());
697 QuitWhenNotDragging();
700 // Should no longer be dragging.
701 ASSERT_FALSE(tab_strip->IsDragSessionActive());
702 ASSERT_FALSE(TabDragController::IsActive());
704 // There should now be another browser.
705 ASSERT_EQ(2u, native_browser_list->size());
706 Browser* new_browser = native_browser_list->get(1);
707 ASSERT_TRUE(new_browser->window()->IsActive());
708 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser);
709 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
711 EXPECT_EQ("0", IDString(new_browser->tab_strip_model()));
712 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
714 // The bounds of the initial window should not have changed.
715 EXPECT_EQ(initial_bounds.ToString(),
716 browser()->window()->GetBounds().ToString());
718 EXPECT_FALSE(GetIsDragged(browser()));
719 EXPECT_FALSE(GetIsDragged(new_browser));
720 // After this both windows should still be manageable.
721 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
722 EXPECT_TRUE(IsWindowPositionManaged(
723 new_browser->window()->GetNativeWindow()));
725 // Both windows should not be maximized
726 EXPECT_FALSE(browser()->window()->IsMaximized());
727 EXPECT_FALSE(new_browser->window()->IsMaximized());
730 #if defined(OS_CHROMEOS)
731 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
732 // compositor. crbug.com/331924
733 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
734 DISABLED_DetachToOwnWindowFromMaximizedWindow
735 #else
736 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \
737 DetachToOwnWindowFromMaximizedWindow
738 #endif
739 // Drags from browser to separate window and releases mouse.
740 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
741 MAYBE_DetachToOwnWindowFromMaximizedWindow) {
742 // Maximize the initial browser window.
743 browser()->window()->Maximize();
744 ASSERT_TRUE(browser()->window()->IsMaximized());
746 // Add another tab.
747 AddTabAndResetBrowser(browser());
748 TabStrip* tab_strip = GetTabStripForBrowser(browser());
750 // Move to the first tab and drag it enough so that it detaches.
751 gfx::Point tab_0_center(
752 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
753 ASSERT_TRUE(PressInput(tab_0_center));
754 ASSERT_TRUE(DragInputToNotifyWhenDone(
755 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
756 base::Bind(&DetachToOwnWindowStep2, this)));
757 if (input_source() == INPUT_SOURCE_MOUSE) {
758 ASSERT_TRUE(ReleaseMouseAsync());
759 QuitWhenNotDragging();
762 // Should no longer be dragging.
763 ASSERT_FALSE(tab_strip->IsDragSessionActive());
764 ASSERT_FALSE(TabDragController::IsActive());
766 // There should now be another browser.
767 ASSERT_EQ(2u, native_browser_list->size());
768 Browser* new_browser = native_browser_list->get(1);
769 ASSERT_TRUE(new_browser->window()->IsActive());
770 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser);
771 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
773 EXPECT_EQ("0", IDString(new_browser->tab_strip_model()));
774 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
776 // The bounds of the initial window should not have changed.
777 EXPECT_TRUE(browser()->window()->IsMaximized());
779 EXPECT_FALSE(GetIsDragged(browser()));
780 EXPECT_FALSE(GetIsDragged(new_browser));
781 // After this both windows should still be manageable.
782 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
783 EXPECT_TRUE(IsWindowPositionManaged(
784 new_browser->window()->GetNativeWindow()));
786 // The new window should be maximized.
787 EXPECT_TRUE(new_browser->window()->IsMaximized());
790 // Deletes a tab being dragged before the user moved enough to start a drag.
791 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
792 DeleteBeforeStartedDragging) {
793 // Add another tab.
794 AddTabAndResetBrowser(browser());
795 TabStrip* tab_strip = GetTabStripForBrowser(browser());
797 // Click on the first tab, but don't move it.
798 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
799 ASSERT_TRUE(PressInput(tab_0_center));
801 // Should be dragging.
802 ASSERT_TRUE(tab_strip->IsDragSessionActive());
803 ASSERT_TRUE(TabDragController::IsActive());
805 // Delete the tab being dragged.
806 delete browser()->tab_strip_model()->GetWebContentsAt(0);
808 // Should have canceled dragging.
809 ASSERT_FALSE(tab_strip->IsDragSessionActive());
810 ASSERT_FALSE(TabDragController::IsActive());
812 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
813 EXPECT_FALSE(GetIsDragged(browser()));
816 // Deletes a tab being dragged while still attached.
817 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
818 DeleteTabWhileAttached) {
819 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
820 // compositor. crbug.com/331924
821 if (input_source() == INPUT_SOURCE_MOUSE) {
822 VLOG(1) << "Test is DISABLED for mouse input.";
823 return;
826 // Add another tab.
827 AddTabAndResetBrowser(browser());
828 TabStrip* tab_strip = GetTabStripForBrowser(browser());
830 // Click on the first tab and move it enough so that it starts dragging but is
831 // still attached.
832 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
833 ASSERT_TRUE(PressInput(tab_0_center));
834 ASSERT_TRUE(DragInputTo(
835 gfx::Point(tab_0_center.x() + 20, tab_0_center.y())));
837 // Should be dragging.
838 ASSERT_TRUE(tab_strip->IsDragSessionActive());
839 ASSERT_TRUE(TabDragController::IsActive());
841 // Delete the tab being dragged.
842 delete browser()->tab_strip_model()->GetWebContentsAt(0);
844 // Should have canceled dragging.
845 ASSERT_FALSE(tab_strip->IsDragSessionActive());
846 ASSERT_FALSE(TabDragController::IsActive());
848 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
850 EXPECT_FALSE(GetIsDragged(browser()));
853 namespace {
855 void DeleteWhileDetachedStep2(WebContents* tab) {
856 delete tab;
859 } // namespace
861 // Deletes a tab being dragged after dragging a tab so that a new window is
862 // created.
863 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
864 DeleteTabWhileDetached) {
865 // Add another tab.
866 AddTabAndResetBrowser(browser());
867 TabStrip* tab_strip = GetTabStripForBrowser(browser());
869 // Move to the first tab and drag it enough so that it detaches.
870 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
871 WebContents* to_delete =
872 browser()->tab_strip_model()->GetWebContentsAt(0);
873 ASSERT_TRUE(PressInput(tab_0_center));
874 ASSERT_TRUE(DragInputToNotifyWhenDone(
875 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
876 base::Bind(&DeleteWhileDetachedStep2, to_delete)));
877 QuitWhenNotDragging();
879 // Should not be dragging.
880 ASSERT_FALSE(tab_strip->IsDragSessionActive());
881 ASSERT_FALSE(TabDragController::IsActive());
883 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
885 EXPECT_FALSE(GetIsDragged(browser()));
888 namespace {
890 void DeleteSourceDetachedStep2(WebContents* tab,
891 const BrowserList* browser_list) {
892 ASSERT_EQ(2u, browser_list->size());
893 Browser* new_browser = browser_list->get(1);
894 // This ends up closing the source window.
895 delete tab;
896 // Cancel the drag.
897 ui_controls::SendKeyPress(new_browser->window()->GetNativeWindow(),
898 ui::VKEY_ESCAPE, false, false, false, false);
901 } // namespace
903 #if defined(OS_CHROMEOS)
904 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
905 // compositor. crbug.com/331924
906 #define MAYBE_DeleteSourceDetached DISABLED_DeleteSourceDetached
907 #else
908 #define MAYBE_DeleteSourceDetached DeleteSourceDetached
909 #endif
910 // Detaches a tab and while detached deletes a tab from the source so that the
911 // source window closes then presses escape to cancel the drag.
912 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
913 DeleteSourceDetached) {
914 // Add another tab.
915 AddTabAndResetBrowser(browser());
916 TabStrip* tab_strip = GetTabStripForBrowser(browser());
918 // Move to the first tab and drag it enough so that it detaches.
919 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
920 WebContents* to_delete = browser()->tab_strip_model()->GetWebContentsAt(1);
921 ASSERT_TRUE(PressInput(tab_0_center));
922 ASSERT_TRUE(DragInputToNotifyWhenDone(
923 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
924 base::Bind(&DeleteSourceDetachedStep2, to_delete, native_browser_list)));
925 QuitWhenNotDragging();
927 // Should not be dragging.
928 ASSERT_EQ(1u, native_browser_list->size());
929 Browser* new_browser = native_browser_list->get(0);
930 ASSERT_FALSE(GetTabStripForBrowser(new_browser)->IsDragSessionActive());
931 ASSERT_FALSE(TabDragController::IsActive());
933 EXPECT_EQ("0", IDString(new_browser->tab_strip_model()));
935 EXPECT_FALSE(GetIsDragged(new_browser));
937 // Remaining browser window should not be maximized
938 EXPECT_FALSE(new_browser->window()->IsMaximized());
941 namespace {
943 void PressEscapeWhileDetachedStep2(const BrowserList* browser_list) {
944 ASSERT_EQ(2u, browser_list->size());
945 Browser* new_browser = browser_list->get(1);
946 ui_controls::SendKeyPress(
947 new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false,
948 false, false);
951 } // namespace
953 #if defined(OS_CHROMEOS)
954 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
955 // compositor. crbug.com/331924
956 #define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached
957 #else
958 #define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached
959 #endif
960 // This is disabled until NativeViewHost::Detach really detaches.
961 // Detaches a tab and while detached presses escape to revert the drag.
962 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
963 MAYBE_PressEscapeWhileDetached) {
964 // Add another tab.
965 AddTabAndResetBrowser(browser());
966 TabStrip* tab_strip = GetTabStripForBrowser(browser());
968 // Move to the first tab and drag it enough so that it detaches.
969 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
970 ASSERT_TRUE(PressInput(tab_0_center));
971 ASSERT_TRUE(DragInputToNotifyWhenDone(
972 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
973 base::Bind(&PressEscapeWhileDetachedStep2, native_browser_list)));
974 QuitWhenNotDragging();
976 // Should not be dragging.
977 ASSERT_FALSE(tab_strip->IsDragSessionActive());
978 ASSERT_FALSE(TabDragController::IsActive());
980 // And there should only be one window.
981 EXPECT_EQ(1u, native_browser_list->size());
983 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
985 // Remaining browser window should not be maximized
986 EXPECT_FALSE(browser()->window()->IsMaximized());
989 namespace {
991 void DragAllStep2(DetachToBrowserTabDragControllerTest* test,
992 const BrowserList* browser_list) {
993 // Should only be one window.
994 ASSERT_EQ(1u, browser_list->size());
995 if (test->input_source() == INPUT_SOURCE_TOUCH) {
996 ASSERT_TRUE(test->ReleaseInput());
997 } else {
998 ASSERT_TRUE(test->ReleaseMouseAsync());
1002 } // namespace
1004 #if defined(OS_CHROMEOS)
1005 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1006 // compositor. crbug.com/331924
1007 #define MAYBE_DragAll DISABLED_DragAll
1008 #else
1009 #define MAYBE_DragAll DragAll
1010 #endif
1011 // Selects multiple tabs and starts dragging the window.
1012 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) {
1013 // Add another tab.
1014 AddTabAndResetBrowser(browser());
1015 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1016 browser()->tab_strip_model()->AddTabAtToSelection(0);
1017 browser()->tab_strip_model()->AddTabAtToSelection(1);
1019 // Move to the first tab and drag it enough so that it would normally
1020 // detach.
1021 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1022 ASSERT_TRUE(PressInput(tab_0_center));
1023 ASSERT_TRUE(DragInputToNotifyWhenDone(
1024 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1025 base::Bind(&DragAllStep2, this, native_browser_list)));
1026 QuitWhenNotDragging();
1028 // Should not be dragging.
1029 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1030 ASSERT_FALSE(TabDragController::IsActive());
1032 // And there should only be one window.
1033 EXPECT_EQ(1u, native_browser_list->size());
1035 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1037 EXPECT_FALSE(GetIsDragged(browser()));
1039 // Remaining browser window should not be maximized
1040 EXPECT_FALSE(browser()->window()->IsMaximized());
1043 namespace {
1045 // Invoked from the nested message loop.
1046 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test,
1047 TabStrip* attached_tab_strip,
1048 TabStrip* target_tab_strip,
1049 const BrowserList* browser_list) {
1050 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive());
1051 ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
1052 ASSERT_TRUE(TabDragController::IsActive());
1053 ASSERT_EQ(2u, browser_list->size());
1055 // Drag to target_tab_strip. This should stop the nested loop from dragging
1056 // the window.
1057 gfx::Point target_point(target_tab_strip->width() - 1,
1058 target_tab_strip->height() / 2);
1059 views::View::ConvertPointToScreen(target_tab_strip, &target_point);
1060 ASSERT_TRUE(test->DragInputToAsync(target_point));
1063 } // namespace
1065 #if defined(OS_CHROMEOS)
1066 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1067 // compositor. crbug.com/331924
1068 #define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow
1069 #else
1070 #define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow
1071 #endif
1072 // Creates two browsers, selects all tabs in first and drags into second.
1073 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1074 MAYBE_DragAllToSeparateWindow) {
1075 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1077 // Add another tab to browser().
1078 AddTabAndResetBrowser(browser());
1080 // Create another browser.
1081 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
1082 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1084 browser()->tab_strip_model()->AddTabAtToSelection(0);
1085 browser()->tab_strip_model()->AddTabAtToSelection(1);
1087 // Move to the first tab and drag it enough so that it detaches, but not
1088 // enough that it attaches to browser2.
1089 gfx::Point tab_0_center(
1090 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1091 ASSERT_TRUE(PressInput(tab_0_center));
1092 ASSERT_TRUE(DragInputToNotifyWhenDone(
1093 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1094 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2,
1095 native_browser_list)));
1096 QuitWhenNotDragging();
1098 // Should now be attached to tab_strip2.
1099 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1100 ASSERT_TRUE(TabDragController::IsActive());
1101 ASSERT_EQ(1u, native_browser_list->size());
1103 // Release the mouse, stopping the drag session.
1104 ASSERT_TRUE(ReleaseInput());
1105 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1106 ASSERT_FALSE(TabDragController::IsActive());
1107 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model()));
1109 EXPECT_FALSE(GetIsDragged(browser2));
1111 // Remaining browser window should not be maximized
1112 EXPECT_FALSE(browser2->window()->IsMaximized());
1115 namespace {
1117 // Invoked from the nested message loop.
1118 void DragAllToSeparateWindowAndCancelStep2(
1119 DetachToBrowserTabDragControllerTest* test,
1120 TabStrip* attached_tab_strip,
1121 TabStrip* target_tab_strip,
1122 const BrowserList* browser_list) {
1123 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive());
1124 ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
1125 ASSERT_TRUE(TabDragController::IsActive());
1126 ASSERT_EQ(2u, browser_list->size());
1128 // Drag to target_tab_strip. This should stop the nested loop from dragging
1129 // the window.
1130 gfx::Point target_point(target_tab_strip->width() - 1,
1131 target_tab_strip->height() / 2);
1132 views::View::ConvertPointToScreen(target_tab_strip, &target_point);
1133 ASSERT_TRUE(test->DragInputToAsync(target_point));
1136 } // namespace
1138 #if defined(OS_CHROMEOS)
1139 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1140 // compositor. crbug.com/331924
1141 #define MAYBE_DragAllToSeparateWindowAndCancel \
1142 DISABLED_DragAllToSeparateWindowAndCancel
1143 #else
1144 #define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel
1145 #endif
1146 // Creates two browsers, selects all tabs in first, drags into second, then hits
1147 // escape.
1148 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1149 MAYBE_DragAllToSeparateWindowAndCancel) {
1150 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1152 // Add another tab to browser().
1153 AddTabAndResetBrowser(browser());
1155 // Create another browser.
1156 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
1157 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1159 browser()->tab_strip_model()->AddTabAtToSelection(0);
1160 browser()->tab_strip_model()->AddTabAtToSelection(1);
1162 // Move to the first tab and drag it enough so that it detaches, but not
1163 // enough that it attaches to browser2.
1164 gfx::Point tab_0_center(
1165 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1166 ASSERT_TRUE(PressInput(tab_0_center));
1167 ASSERT_TRUE(DragInputToNotifyWhenDone(
1168 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1169 base::Bind(&DragAllToSeparateWindowAndCancelStep2, this,
1170 tab_strip, tab_strip2, native_browser_list)));
1171 QuitWhenNotDragging();
1173 // Should now be attached to tab_strip2.
1174 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1175 ASSERT_TRUE(TabDragController::IsActive());
1176 ASSERT_EQ(1u, native_browser_list->size());
1178 // Cancel the drag.
1179 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
1180 browser2, ui::VKEY_ESCAPE, false, false, false, false));
1182 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1183 ASSERT_FALSE(TabDragController::IsActive());
1184 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model()));
1186 // browser() will have been destroyed, but browser2 should remain.
1187 ASSERT_EQ(1u, native_browser_list->size());
1189 EXPECT_FALSE(GetIsDragged(browser2));
1191 // Remaining browser window should not be maximized
1192 EXPECT_FALSE(browser2->window()->IsMaximized());
1195 #if defined(OS_CHROMEOS)
1196 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1197 // compositor. crbug.com/331924
1198 #define MAYBE_DragDirectlyToSecondWindow DISABLED_DragDirectlyToSecondWindow
1199 #else
1200 #define MAYBE_DragDirectlyToSecondWindow DragDirectlyToSecondWindow
1201 #endif
1202 // Creates two browsers, drags from first into the second in such a way that
1203 // no detaching should happen.
1204 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1205 MAYBE_DragDirectlyToSecondWindow) {
1206 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1208 // Add another tab to browser().
1209 AddTabAndResetBrowser(browser());
1211 // Create another browser.
1212 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
1213 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1215 // Move the tabstrip down enough so that we can detach.
1216 gfx::Rect bounds(browser2->window()->GetBounds());
1217 bounds.Offset(0, 100);
1218 browser2->window()->SetBounds(bounds);
1220 // Move to the first tab and drag it enough so that it detaches, but not
1221 // enough that it attaches to browser2.
1222 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1223 ASSERT_TRUE(PressInput(tab_0_center));
1225 gfx::Point b2_location(5, 0);
1226 views::View::ConvertPointToScreen(tab_strip2, &b2_location);
1227 ASSERT_TRUE(DragInputTo(b2_location));
1229 // Should now be attached to tab_strip2.
1230 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1231 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1232 ASSERT_TRUE(TabDragController::IsActive());
1234 // Release the mouse, stopping the drag session.
1235 ASSERT_TRUE(ReleaseInput());
1236 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1237 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1238 ASSERT_FALSE(TabDragController::IsActive());
1239 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model()));
1240 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1242 EXPECT_FALSE(GetIsDragged(browser()));
1243 EXPECT_FALSE(GetIsDragged(browser2));
1245 // Both windows should not be maximized
1246 EXPECT_FALSE(browser()->window()->IsMaximized());
1247 EXPECT_FALSE(browser2->window()->IsMaximized());
1250 #if defined(OS_CHROMEOS)
1251 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1252 // compositor. crbug.com/331924
1253 #define MAYBE_DragSingleTabToSeparateWindow \
1254 DISABLED_DragSingleTabToSeparateWindow
1255 #else
1256 #define MAYBE_DragSingleTabToSeparateWindow DragSingleTabToSeparateWindow
1257 #endif
1258 // Creates two browsers, the first browser has a single tab and drags into the
1259 // second browser.
1260 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1261 MAYBE_DragSingleTabToSeparateWindow) {
1262 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1264 ResetIDs(browser()->tab_strip_model(), 0);
1266 // Create another browser.
1267 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
1268 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1269 const gfx::Rect initial_bounds(browser2->window()->GetBounds());
1271 // Move to the first tab and drag it enough so that it detaches, but not
1272 // enough that it attaches to browser2.
1273 gfx::Point tab_0_center(
1274 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1275 ASSERT_TRUE(PressInput(tab_0_center));
1276 ASSERT_TRUE(DragInputToNotifyWhenDone(
1277 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1278 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2,
1279 native_browser_list)));
1280 QuitWhenNotDragging();
1282 // Should now be attached to tab_strip2.
1283 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1284 ASSERT_TRUE(TabDragController::IsActive());
1285 ASSERT_EQ(1u, native_browser_list->size());
1287 // Release the mouse, stopping the drag session.
1288 ASSERT_TRUE(ReleaseInput());
1289 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1290 ASSERT_FALSE(TabDragController::IsActive());
1291 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model()));
1293 EXPECT_FALSE(GetIsDragged(browser2));
1295 // Remaining browser window should not be maximized
1296 EXPECT_FALSE(browser2->window()->IsMaximized());
1298 // Make sure that the window is still managed and not user moved.
1299 EXPECT_TRUE(IsWindowPositionManaged(browser2->window()->GetNativeWindow()));
1300 EXPECT_FALSE(HasUserChangedWindowPositionOrSize(
1301 browser2->window()->GetNativeWindow()));
1302 // Also make sure that the drag to window position has not changed.
1303 EXPECT_EQ(initial_bounds.ToString(),
1304 browser2->window()->GetBounds().ToString());
1307 namespace {
1309 // Invoked from the nested message loop.
1310 void CancelOnNewTabWhenDraggingStep2(
1311 DetachToBrowserTabDragControllerTest* test,
1312 const BrowserList* browser_list) {
1313 ASSERT_TRUE(TabDragController::IsActive());
1314 ASSERT_EQ(2u, browser_list->size());
1316 // Add another tab. This should trigger exiting the nested loop.
1317 test->AddBlankTabAndShow(browser_list->GetLastActive());
1320 } // namespace
1322 #if defined(OS_CHROMEOS)
1323 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1324 // compositor. crbug.com/331924
1325 #define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging
1326 #else
1327 #define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging
1328 #endif
1329 // Adds another tab, detaches into separate window, adds another tab and
1330 // verifies the run loop ends.
1331 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1332 CancelOnNewTabWhenDragging) {
1333 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1335 // Add another tab to browser().
1336 AddTabAndResetBrowser(browser());
1338 // Move to the first tab and drag it enough so that it detaches.
1339 gfx::Point tab_0_center(
1340 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1341 ASSERT_TRUE(PressInput(tab_0_center));
1342 ASSERT_TRUE(DragInputToNotifyWhenDone(
1343 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1344 base::Bind(&CancelOnNewTabWhenDraggingStep2, this, native_browser_list)));
1345 QuitWhenNotDragging();
1347 // Should be two windows and not dragging.
1348 ASSERT_FALSE(TabDragController::IsActive());
1349 ASSERT_EQ(2u, native_browser_list->size());
1350 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
1351 EXPECT_FALSE(GetIsDragged(*it));
1352 // Should not be maximized
1353 EXPECT_FALSE(it->window()->IsMaximized());
1357 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
1359 namespace {
1361 void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest* test,
1362 Browser* browser,
1363 TabStrip* tab_strip,
1364 const BrowserList* browser_list) {
1365 // There should be another browser.
1366 ASSERT_EQ(2u, browser_list->size());
1367 Browser* new_browser = browser_list->get(1);
1368 EXPECT_NE(browser, new_browser);
1369 ASSERT_TRUE(new_browser->window()->IsActive());
1370 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser);
1372 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1373 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1375 // Both windows should be visible.
1376 EXPECT_TRUE(tab_strip->GetWidget()->IsVisible());
1377 EXPECT_TRUE(tab_strip2->GetWidget()->IsVisible());
1379 // Stops dragging.
1380 ASSERT_TRUE(test->ReleaseInput());
1383 } // namespace
1385 #if defined(OS_CHROMEOS)
1386 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1387 // compositor. crbug.com/331924
1388 #define MAYBE_DragInMaximizedWindow DISABLED_DragInMaximizedWindow
1389 #else
1390 #define MAYBE_DragInMaximizedWindow DragInMaximizedWindow
1391 #endif
1392 // Creates a browser with two tabs, maximizes it, drags the tab out.
1393 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1394 MAYBE_DragInMaximizedWindow) {
1395 AddTabAndResetBrowser(browser());
1396 browser()->window()->Maximize();
1398 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1400 // Move to the first tab and drag it enough so that it detaches.
1401 gfx::Point tab_0_center(
1402 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1403 ASSERT_TRUE(PressInput(tab_0_center));
1404 ASSERT_TRUE(DragInputToNotifyWhenDone(
1405 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1406 base::Bind(&DragInMaximizedWindowStep2, this, browser(), tab_strip,
1407 native_browser_list)));
1408 QuitWhenNotDragging();
1410 ASSERT_FALSE(TabDragController::IsActive());
1412 // Should be two browsers.
1413 ASSERT_EQ(2u, native_browser_list->size());
1414 Browser* new_browser = native_browser_list->get(1);
1415 ASSERT_TRUE(new_browser->window()->IsActive());
1417 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible());
1418 EXPECT_TRUE(new_browser->window()->GetNativeWindow()->IsVisible());
1420 EXPECT_FALSE(GetIsDragged(browser()));
1421 EXPECT_FALSE(GetIsDragged(new_browser));
1423 // The source window should be maximized.
1424 EXPECT_TRUE(browser()->window()->IsMaximized());
1425 // The new window should be maximized.
1426 EXPECT_TRUE(new_browser->window()->IsMaximized());
1429 // Subclass of DetachToBrowserTabDragControllerTest that
1430 // creates multiple displays.
1431 class DetachToBrowserInSeparateDisplayTabDragControllerTest
1432 : public DetachToBrowserTabDragControllerTest {
1433 public:
1434 DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1435 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {}
1437 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1438 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line);
1439 // Make screens sufficiently wide to host 2 browsers side by side.
1440 command_line->AppendSwitchASCII("ash-host-window-bounds",
1441 "0+0-600x600,601+0-600x600");
1444 private:
1445 DISALLOW_COPY_AND_ASSIGN(
1446 DetachToBrowserInSeparateDisplayTabDragControllerTest);
1449 // Subclass of DetachToBrowserTabDragControllerTest that runs tests only with
1450 // touch input.
1451 class DetachToBrowserTabDragControllerTestTouch
1452 : public DetachToBrowserTabDragControllerTest {
1453 public:
1454 DetachToBrowserTabDragControllerTestTouch() {}
1455 virtual ~DetachToBrowserTabDragControllerTestTouch() {}
1457 private:
1458 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch);
1461 namespace {
1463 void DragSingleTabToSeparateWindowInSecondDisplayStep3(
1464 DetachToBrowserTabDragControllerTest* test) {
1465 ASSERT_TRUE(test->ReleaseInput());
1468 void DragSingleTabToSeparateWindowInSecondDisplayStep2(
1469 DetachToBrowserTabDragControllerTest* test,
1470 const gfx::Point& target_point) {
1471 ASSERT_TRUE(test->DragInputToNotifyWhenDone(
1472 target_point.x(), target_point.y(),
1473 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3, test)));
1476 } // namespace
1478 // Drags from browser to a second display and releases input.
1479 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
1480 DragSingleTabToSeparateWindowInSecondDisplay) {
1481 // Add another tab.
1482 AddTabAndResetBrowser(browser());
1483 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1485 // Move to the first tab and drag it enough so that it detaches.
1486 // Then drag it to the final destination on the second screen.
1487 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1488 ASSERT_TRUE(PressInput(tab_0_center));
1489 ASSERT_TRUE(DragInputToNotifyWhenDone(
1490 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1491 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2,
1492 this, gfx::Point(600 + tab_0_center.x(),
1493 tab_0_center.y()
1494 + GetDetachY(tab_strip)))));
1495 QuitWhenNotDragging();
1497 // Should no longer be dragging.
1498 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1499 ASSERT_FALSE(TabDragController::IsActive());
1501 // There should now be another browser.
1502 ASSERT_EQ(2u, native_browser_list->size());
1503 Browser* new_browser = native_browser_list->get(1);
1504 ASSERT_TRUE(new_browser->window()->IsActive());
1505 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser);
1506 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1508 // This other browser should be on the second screen (with mouse drag)
1509 // With the touch input the browser cannot be dragged from one screen
1510 // to another and the window stays on the first screen.
1511 if (input_source() == INPUT_SOURCE_MOUSE) {
1512 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1513 ASSERT_EQ(2u, roots.size());
1514 aura::Window* second_root = roots[1];
1515 EXPECT_EQ(second_root,
1516 new_browser->window()->GetNativeWindow()->GetRootWindow());
1519 EXPECT_EQ("0", IDString(new_browser->tab_strip_model()));
1520 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1522 // Both windows should not be maximized
1523 EXPECT_FALSE(browser()->window()->IsMaximized());
1524 EXPECT_FALSE(new_browser->window()->IsMaximized());
1527 namespace {
1529 // Invoked from the nested message loop.
1530 void DragTabToWindowInSeparateDisplayStep2(
1531 DetachToBrowserTabDragControllerTest* test,
1532 TabStrip* not_attached_tab_strip,
1533 TabStrip* target_tab_strip) {
1534 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive());
1535 ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
1536 ASSERT_TRUE(TabDragController::IsActive());
1538 // Drag to target_tab_strip. This should stop the nested loop from dragging
1539 // the window.
1540 gfx::Point target_point(
1541 GetCenterInScreenCoordinates(target_tab_strip->tab_at(0)));
1543 // Move it close to the beginning of the target tabstrip.
1544 target_point.set_x(
1545 target_point.x() - target_tab_strip->tab_at(0)->width() / 2 + 10);
1546 ASSERT_TRUE(test->DragInputToAsync(target_point));
1549 } // namespace
1551 #if defined(OS_CHROMEOS)
1552 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1553 // compositor. crbug.com/331924
1554 #define MAYBE_DragTabToWindowInSeparateDisplay \
1555 DISABLED_DragTabToWindowInSeparateDisplay
1556 #else
1557 #define MAYBE_DragTabToWindowInSeparateDisplay DragTabToWindowInSeparateDisplay
1558 #endif
1559 // Drags from browser to another browser on a second display and releases input.
1560 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
1561 MAYBE_DragTabToWindowInSeparateDisplay) {
1562 // Add another tab.
1563 AddTabAndResetBrowser(browser());
1564 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1566 // Create another browser.
1567 Browser* browser2 = CreateBrowser(browser()->profile());
1568 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1569 ResetIDs(browser2->tab_strip_model(), 100);
1571 // Move the second browser to the second display.
1572 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1573 ASSERT_EQ(2u, roots.size());
1574 aura::Window* second_root = roots[1];
1575 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1576 second_root).work_area();
1577 browser2->window()->SetBounds(work_area);
1578 EXPECT_EQ(second_root,
1579 browser2->window()->GetNativeWindow()->GetRootWindow());
1581 // Move to the first tab and drag it enough so that it detaches, but not
1582 // enough that it attaches to browser2.
1583 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1584 ASSERT_TRUE(PressInput(tab_0_center));
1585 ASSERT_TRUE(DragInputToNotifyWhenDone(
1586 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1587 base::Bind(&DragTabToWindowInSeparateDisplayStep2,
1588 this, tab_strip, tab_strip2)));
1589 QuitWhenNotDragging();
1591 // Should now be attached to tab_strip2.
1592 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1593 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1594 ASSERT_TRUE(TabDragController::IsActive());
1596 // Release the mouse, stopping the drag session.
1597 ASSERT_TRUE(ReleaseInput());
1598 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1599 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1600 ASSERT_FALSE(TabDragController::IsActive());
1601 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model()));
1602 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1604 // Both windows should not be maximized
1605 EXPECT_FALSE(browser()->window()->IsMaximized());
1606 EXPECT_FALSE(browser2->window()->IsMaximized());
1609 #if defined(OS_CHROMEOS)
1610 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1611 // compositor. crbug.com/331924
1612 #define MAYBE_DragTabToWindowOnSecondDisplay \
1613 DISABLED_DragTabToWindowOnSecondDisplay
1614 #else
1615 #define MAYBE_DragTabToWindowOnSecondDisplay DragTabToWindowOnSecondDisplay
1616 #endif
1617 // Drags from browser to another browser on a second display and releases input.
1618 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
1619 MAYBE_DragTabToWindowOnSecondDisplay) {
1620 // Add another tab.
1621 AddTabAndResetBrowser(browser());
1622 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1624 // Create another browser.
1625 Browser* browser2 = CreateBrowser(browser()->profile());
1626 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1627 ResetIDs(browser2->tab_strip_model(), 100);
1629 // Move both browsers to the second display.
1630 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1631 ASSERT_EQ(2u, roots.size());
1632 aura::Window* second_root = roots[1];
1633 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1634 second_root).work_area();
1635 browser()->window()->SetBounds(work_area);
1637 // position both browser windows side by side on the second screen.
1638 gfx::Rect work_area2(work_area);
1639 work_area.set_width(work_area.width()/2);
1640 browser()->window()->SetBounds(work_area);
1641 work_area2.set_x(work_area2.x() + work_area2.width()/2);
1642 work_area2.set_width(work_area2.width()/2);
1643 browser2->window()->SetBounds(work_area2);
1644 EXPECT_EQ(second_root,
1645 browser()->window()->GetNativeWindow()->GetRootWindow());
1646 EXPECT_EQ(second_root,
1647 browser2->window()->GetNativeWindow()->GetRootWindow());
1649 // Move to the first tab and drag it enough so that it detaches, but not
1650 // enough that it attaches to browser2.
1651 // SetEventGeneratorRootWindow sets correct (second) RootWindow
1652 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1653 SetEventGeneratorRootWindow(tab_0_center);
1654 ASSERT_TRUE(PressInput(tab_0_center));
1655 ASSERT_TRUE(DragInputToNotifyWhenDone(
1656 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1657 base::Bind(&DragTabToWindowInSeparateDisplayStep2,
1658 this, tab_strip, tab_strip2)));
1659 QuitWhenNotDragging();
1661 // Should now be attached to tab_strip2.
1662 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1663 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1664 ASSERT_TRUE(TabDragController::IsActive());
1666 // Release the mouse, stopping the drag session.
1667 ASSERT_TRUE(ReleaseInput());
1668 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1669 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1670 ASSERT_FALSE(TabDragController::IsActive());
1671 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model()));
1672 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1674 // Both windows should not be maximized
1675 EXPECT_FALSE(browser()->window()->IsMaximized());
1676 EXPECT_FALSE(browser2->window()->IsMaximized());
1679 #if defined(OS_CHROMEOS)
1680 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1681 // compositor. crbug.com/331924
1682 #define MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay \
1683 DISABLED_DragMaxTabToNonMaxWindowInSeparateDisplay
1684 #else
1685 #define MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay \
1686 DragMaxTabToNonMaxWindowInSeparateDisplay
1687 #endif
1688 // Drags from a maximized browser to another non-maximized browser on a second
1689 // display and releases input.
1690 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
1691 MAYBE_DragMaxTabToNonMaxWindowInSeparateDisplay) {
1692 // Add another tab.
1693 AddTabAndResetBrowser(browser());
1694 browser()->window()->Maximize();
1695 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1697 // Create another browser on the second display.
1698 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1699 ASSERT_EQ(2u, roots.size());
1700 aura::Window* first_root = roots[0];
1701 aura::Window* second_root = roots[1];
1702 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1703 second_root).work_area();
1704 work_area.Inset(20,20,20,60);
1705 Browser::CreateParams params(browser()->profile(),
1706 browser()->host_desktop_type());
1707 params.initial_show_state = ui::SHOW_STATE_NORMAL;
1708 params.initial_bounds = work_area;
1709 Browser* browser2 = new Browser(params);
1710 AddBlankTabAndShow(browser2);
1712 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1713 ResetIDs(browser2->tab_strip_model(), 100);
1715 EXPECT_EQ(second_root,
1716 browser2->window()->GetNativeWindow()->GetRootWindow());
1717 EXPECT_EQ(first_root,
1718 browser()->window()->GetNativeWindow()->GetRootWindow());
1719 EXPECT_EQ(2, tab_strip->tab_count());
1720 EXPECT_EQ(1, tab_strip2->tab_count());
1722 // Move to the first tab and drag it enough so that it detaches, but not
1723 // enough that it attaches to browser2.
1724 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1725 ASSERT_TRUE(PressInput(tab_0_center));
1726 ASSERT_TRUE(DragInputToNotifyWhenDone(
1727 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1728 base::Bind(&DragTabToWindowInSeparateDisplayStep2,
1729 this, tab_strip, tab_strip2)));
1730 QuitWhenNotDragging();
1732 // Should now be attached to tab_strip2.
1733 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1734 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1735 ASSERT_TRUE(TabDragController::IsActive());
1737 // Release the mouse, stopping the drag session.
1738 ASSERT_TRUE(ReleaseInput());
1740 // tab should have moved
1741 EXPECT_EQ(1, tab_strip->tab_count());
1742 EXPECT_EQ(2, tab_strip2->tab_count());
1744 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1745 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1746 ASSERT_FALSE(TabDragController::IsActive());
1747 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model()));
1748 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1750 // Source browser should still be maximized, target should not
1751 EXPECT_TRUE(browser()->window()->IsMaximized());
1752 EXPECT_FALSE(browser2->window()->IsMaximized());
1755 // Immersive fullscreen is ChromeOS only.
1756 #if defined(OS_CHROMEOS)
1757 // Drags from a restored browser to an immersive fullscreen browser on a
1758 // second display and releases input.
1759 IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
1760 DragTabToImmersiveBrowserOnSeparateDisplay) {
1761 // Add another tab.
1762 AddTabAndResetBrowser(browser());
1763 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1765 // Create another browser.
1766 Browser* browser2 = CreateBrowser(browser()->profile());
1767 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1768 ResetIDs(browser2->tab_strip_model(), 100);
1770 // Move the second browser to the second display.
1771 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1772 ASSERT_EQ(2u, roots.size());
1773 aura::Window* second_root = roots[1];
1774 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
1775 second_root).work_area();
1776 browser2->window()->SetBounds(work_area);
1777 EXPECT_EQ(second_root,
1778 browser2->window()->GetNativeWindow()->GetRootWindow());
1780 // Put the second browser into immersive fullscreen.
1781 BrowserView* browser_view2 = BrowserView::GetBrowserViewForBrowser(browser2);
1782 ImmersiveModeController* immersive_controller2 =
1783 browser_view2->immersive_mode_controller();
1784 immersive_controller2->SetupForTest();
1785 chrome::ToggleFullscreenMode(browser2);
1786 ASSERT_TRUE(immersive_controller2->IsEnabled());
1787 ASSERT_FALSE(immersive_controller2->IsRevealed());
1788 ASSERT_TRUE(tab_strip2->IsImmersiveStyle());
1790 // Move to the first tab and drag it enough so that it detaches, but not
1791 // enough that it attaches to browser2.
1792 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1793 ASSERT_TRUE(PressInput(tab_0_center));
1794 ASSERT_TRUE(DragInputToNotifyWhenDone(
1795 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1796 base::Bind(&DragTabToWindowInSeparateDisplayStep2,
1797 this, tab_strip, tab_strip2)));
1798 QuitWhenNotDragging();
1800 // Should now be attached to tab_strip2.
1801 ASSERT_TRUE(tab_strip2->IsDragSessionActive());
1802 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1803 ASSERT_TRUE(TabDragController::IsActive());
1805 // browser2's top chrome should be revealed and the tab strip should be
1806 // at normal height while user is tragging tabs_strip2's tabs.
1807 ASSERT_TRUE(immersive_controller2->IsRevealed());
1808 ASSERT_FALSE(tab_strip2->IsImmersiveStyle());
1810 // Release the mouse, stopping the drag session.
1811 ASSERT_TRUE(ReleaseInput());
1812 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
1813 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1814 ASSERT_FALSE(TabDragController::IsActive());
1815 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model()));
1816 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1818 // Move the mouse off of browser2's top chrome.
1819 aura::Window* primary_root = roots[0];
1820 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
1821 primary_root->GetBoundsInScreen().CenterPoint()));
1823 // The first browser window should not be in immersive fullscreen.
1824 // browser2 should still be in immersive fullscreen, but the top chrome should
1825 // no longer be revealed.
1826 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
1827 EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled());
1829 EXPECT_TRUE(immersive_controller2->IsEnabled());
1830 EXPECT_FALSE(immersive_controller2->IsRevealed());
1831 EXPECT_TRUE(tab_strip2->IsImmersiveStyle());
1833 #endif // OS_CHROMEOS
1835 // Subclass of DetachToBrowserTabDragControllerTest that
1836 // creates multiple displays with different device scale factors.
1837 class DifferentDeviceScaleFactorDisplayTabDragControllerTest
1838 : public DetachToBrowserTabDragControllerTest {
1839 public:
1840 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1841 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {}
1843 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1844 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line);
1845 command_line->AppendSwitchASCII("ash-host-window-bounds",
1846 "400x400,0+400-800x800*2");
1849 float GetCursorDeviceScaleFactor() const {
1850 ash::test::CursorManagerTestApi cursor_test_api(
1851 ash::Shell::GetInstance()->cursor_manager());
1852 return cursor_test_api.GetDisplay().device_scale_factor();
1855 private:
1856 DISALLOW_COPY_AND_ASSIGN(
1857 DifferentDeviceScaleFactorDisplayTabDragControllerTest);
1860 namespace {
1862 // The points where a tab is dragged in CursorDeviceScaleFactorStep.
1863 const struct DragPoint {
1864 int x;
1865 int y;
1866 } kDragPoints[] = {
1867 {300, 200},
1868 {399, 200},
1869 {500, 200},
1870 {400, 200},
1871 {300, 200},
1874 // The expected device scale factors before the cursor is moved to the
1875 // corresponding kDragPoints in CursorDeviceScaleFactorStep.
1876 const float kDeviceScaleFactorExpectations[] = {
1877 1.0f,
1878 1.0f,
1879 2.0f,
1880 2.0f,
1881 1.0f,
1884 COMPILE_ASSERT(
1885 arraysize(kDragPoints) == arraysize(kDeviceScaleFactorExpectations),
1886 kDragPoints_and_kDeviceScaleFactorExpectations_must_have_same_size);
1888 // Drags tab to |kDragPoints[index]|, then calls the next step function.
1889 void CursorDeviceScaleFactorStep(
1890 DifferentDeviceScaleFactorDisplayTabDragControllerTest* test,
1891 TabStrip* not_attached_tab_strip,
1892 size_t index) {
1893 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive());
1894 ASSERT_TRUE(TabDragController::IsActive());
1896 if (index < arraysize(kDragPoints)) {
1897 EXPECT_EQ(kDeviceScaleFactorExpectations[index],
1898 test->GetCursorDeviceScaleFactor());
1899 const DragPoint p = kDragPoints[index];
1900 ASSERT_TRUE(test->DragInputToNotifyWhenDone(
1901 p.x, p.y, base::Bind(&CursorDeviceScaleFactorStep,
1902 test, not_attached_tab_strip, index + 1)));
1903 } else {
1904 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag.
1905 EXPECT_EQ(1.0f, test->GetCursorDeviceScaleFactor());
1906 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
1907 ui_controls::LEFT, ui_controls::UP));
1911 } // namespace
1913 #if defined(OS_CHROMEOS)
1914 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
1915 // compositor. crbug.com/331924
1916 #define MAYBE_CursorDeviceScaleFactor DISABLED_CursorDeviceScaleFactor
1917 #else
1918 #define MAYBE_CursorDeviceScaleFactor CursorDeviceScaleFactor
1919 #endif
1920 // Verifies cursor's device scale factor is updated when a tab is moved across
1921 // displays with different device scale factors (http://crbug.com/154183).
1922 IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest,
1923 MAYBE_CursorDeviceScaleFactor) {
1924 // Add another tab.
1925 AddTabAndResetBrowser(browser());
1926 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1928 // Move the second browser to the second display.
1929 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
1930 ASSERT_EQ(2u, roots.size());
1932 // Move to the first tab and drag it enough so that it detaches.
1933 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1934 ASSERT_TRUE(PressInput(tab_0_center));
1935 ASSERT_TRUE(DragInputToNotifyWhenDone(
1936 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1937 base::Bind(&CursorDeviceScaleFactorStep,
1938 this, tab_strip, 0)));
1939 QuitWhenNotDragging();
1942 namespace {
1944 class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
1945 : public TabDragControllerTest {
1946 public:
1947 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {}
1949 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1950 TabDragControllerTest::SetUpCommandLine(command_line);
1951 command_line->AppendSwitchASCII("ash-host-window-bounds",
1952 "0+0-250x250,251+0-250x250");
1955 bool Press(const gfx::Point& position) {
1956 return ui_test_utils::SendMouseMoveSync(position) &&
1957 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT,
1958 ui_controls::DOWN);
1961 bool DragTabAndExecuteTaskWhenDone(const gfx::Point& position,
1962 const base::Closure& task) {
1963 return ui_controls::SendMouseMoveNotifyWhenDone(
1964 position.x(), position.y(), task);
1967 void QuitWhenNotDragging() {
1968 test::QuitWhenNotDraggingImpl();
1969 base::MessageLoop::current()->Run();
1972 private:
1973 DISALLOW_COPY_AND_ASSIGN(
1974 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest);
1977 // Invoked from the nested message loop.
1978 void CancelDragTabToWindowInSeparateDisplayStep3(
1979 TabStrip* tab_strip,
1980 const BrowserList* browser_list) {
1981 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1982 ASSERT_TRUE(TabDragController::IsActive());
1983 ASSERT_EQ(2u, browser_list->size());
1985 // Switching display mode should cancel the drag operation.
1986 ash::internal::DisplayManager* display_manager =
1987 ash::Shell::GetInstance()->display_manager();
1988 display_manager->AddRemoveDisplay();
1991 // Invoked from the nested message loop.
1992 void CancelDragTabToWindowInSeparateDisplayStep2(
1993 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest* test,
1994 TabStrip* tab_strip,
1995 aura::Window* current_root,
1996 gfx::Point final_destination,
1997 const BrowserList* browser_list) {
1998 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1999 ASSERT_TRUE(TabDragController::IsActive());
2000 ASSERT_EQ(2u, browser_list->size());
2002 Browser* new_browser = browser_list->get(1);
2003 EXPECT_EQ(current_root,
2004 new_browser->window()->GetNativeWindow()->GetRootWindow());
2006 ASSERT_TRUE(test->DragTabAndExecuteTaskWhenDone(
2007 final_destination,
2008 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3,
2009 tab_strip, browser_list)));
2012 } // namespace
2014 #if defined(OS_CHROMEOS)
2015 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2016 // compositor. crbug.com/331924
2017 #define MAYBE_CancelDragTabToWindowIn2ndDisplay \
2018 DISABLED_CancelDragTabToWindowIn2ndDisplay
2019 #else
2020 #define MAYBE_CancelDragTabToWindowIn2ndDisplay \
2021 CancelDragTabToWindowIn2ndDisplay
2022 #endif
2023 // Drags from browser to a second display and releases input.
2024 IN_PROC_BROWSER_TEST_F(
2025 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest,
2026 MAYBE_CancelDragTabToWindowIn2ndDisplay) {
2027 // Add another tab.
2028 AddTabAndResetBrowser(browser());
2029 TabStrip* tab_strip = GetTabStripForBrowser(browser());
2031 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2033 // Move the second browser to the second display.
2034 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
2035 ASSERT_EQ(2u, roots.size());
2036 gfx::Point final_destination =
2037 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2038 roots[1]).work_area().CenterPoint();
2040 // Move to the first tab and drag it enough so that it detaches, but not
2041 // enough to move to another display.
2042 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
2043 ASSERT_TRUE(Press(tab_0_dst));
2044 tab_0_dst.Offset(0, GetDetachY(tab_strip));
2045 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2046 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2,
2047 this, tab_strip, roots[0], final_destination,
2048 native_browser_list)));
2049 QuitWhenNotDragging();
2051 ASSERT_EQ(1u, native_browser_list->size());
2052 ASSERT_FALSE(tab_strip->IsDragSessionActive());
2053 ASSERT_FALSE(TabDragController::IsActive());
2054 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2056 // Release the mouse
2057 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2058 ui_controls::LEFT, ui_controls::UP));
2061 // Drags from browser from a second display to primary and releases input.
2062 IN_PROC_BROWSER_TEST_F(
2063 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest,
2064 CancelDragTabToWindowIn1stDisplay) {
2065 aura::Window::Windows roots = ash::Shell::GetAllRootWindows();
2066 ASSERT_EQ(2u, roots.size());
2068 // Add another tab.
2069 AddTabAndResetBrowser(browser());
2070 TabStrip* tab_strip = GetTabStripForBrowser(browser());
2072 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2073 EXPECT_EQ(roots[0], browser()->window()->GetNativeWindow()->GetRootWindow());
2075 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->
2076 GetDisplayNearestWindow(roots[1]).work_area();
2077 browser()->window()->SetBounds(work_area);
2078 EXPECT_EQ(roots[1], browser()->window()->GetNativeWindow()->GetRootWindow());
2080 // Move the second browser to the display.
2081 gfx::Point final_destination =
2082 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
2083 roots[0]).work_area().CenterPoint();
2085 // Move to the first tab and drag it enough so that it detaches, but not
2086 // enough to move to another display.
2087 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
2088 ASSERT_TRUE(Press(tab_0_dst));
2089 tab_0_dst.Offset(0, GetDetachY(tab_strip));
2090 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
2091 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2,
2092 this, tab_strip, roots[1], final_destination,
2093 native_browser_list)));
2094 QuitWhenNotDragging();
2096 ASSERT_EQ(1u, native_browser_list->size());
2097 ASSERT_FALSE(tab_strip->IsDragSessionActive());
2098 ASSERT_FALSE(TabDragController::IsActive());
2099 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
2101 // Release the mouse
2102 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
2103 ui_controls::LEFT, ui_controls::UP));
2106 namespace {
2108 void DetachToOwnWindowTwoFingersDragStep5(
2109 DetachToBrowserTabDragControllerTest* test) {
2110 ASSERT_EQ(2u, test->native_browser_list->size());
2111 Browser* new_browser = test->native_browser_list->get(1);
2112 ASSERT_TRUE(new_browser->window()->IsActive());
2114 ASSERT_TRUE(test->ReleaseInput());
2115 ASSERT_TRUE(test->ReleaseInput2());
2116 ASSERT_TRUE(new_browser->window()->IsActive());
2119 void DetachToOwnWindowTwoFingersDragStep4(
2120 DetachToBrowserTabDragControllerTest* test,
2121 const gfx::Point& target_point) {
2122 ASSERT_EQ(2u, test->native_browser_list->size());
2123 Browser* new_browser = test->native_browser_list->get(1);
2124 ASSERT_TRUE(new_browser->window()->IsActive());
2126 ASSERT_TRUE(test->DragInput2ToNotifyWhenDone(
2127 target_point.x(), target_point.y(),
2128 base::Bind(&DetachToOwnWindowTwoFingersDragStep5, test)));
2131 void DetachToOwnWindowTwoFingersDragStep3(
2132 DetachToBrowserTabDragControllerTest* test,
2133 const gfx::Point& target_point) {
2134 ASSERT_TRUE(test->PressInput2());
2136 ASSERT_EQ(2u, test->native_browser_list->size());
2137 Browser* new_browser = test->native_browser_list->get(1);
2138 ASSERT_TRUE(new_browser->window()->IsActive());
2140 ASSERT_TRUE(test->DragInputToDelayedNotifyWhenDone(
2141 target_point.x(), target_point.y(),
2142 base::Bind(&DetachToOwnWindowTwoFingersDragStep4,
2143 test,
2144 target_point),
2145 base::TimeDelta::FromMilliseconds(60)));
2148 void DetachToOwnWindowTwoFingersDragStep2(
2149 DetachToBrowserTabDragControllerTest* test,
2150 const gfx::Point& target_point) {
2151 ASSERT_EQ(2u, test->native_browser_list->size());
2152 Browser* new_browser = test->native_browser_list->get(1);
2153 ASSERT_TRUE(new_browser->window()->IsActive());
2155 ASSERT_TRUE(test->DragInputToDelayedNotifyWhenDone(
2156 target_point.x(), target_point.y(),
2157 base::Bind(&DetachToOwnWindowTwoFingersDragStep3,
2158 test,
2159 target_point + gfx::Vector2d(-2, 1)),
2160 base::TimeDelta::FromMilliseconds(60)));
2163 } // namespace
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_DetachToOwnWindowTwoFingers DISABLED_DetachToOwnWindowTwoFingers
2169 #else
2170 #define MAYBE_DetachToOwnWindowTwoFingers DetachToOwnWindowTwoFingers
2171 #endif
2172 // Drags from browser to separate window starting with one finger and
2173 // then continuing with two fingers.
2174 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch,
2175 MAYBE_DetachToOwnWindowTwoFingers) {
2176 gfx::Rect bounds(browser()->window()->GetBounds());
2177 // Add another tab.
2178 AddTabAndResetBrowser(browser());
2179 TabStrip* tab_strip = GetTabStripForBrowser(browser());
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 // Drags in this test are very short to avoid fling.
2186 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone(
2187 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
2188 base::Bind(&DetachToOwnWindowTwoFingersDragStep2,
2189 this, gfx::Point(5 + tab_0_center.x(),
2190 1 + tab_0_center.y()
2191 + GetDetachY(tab_strip))),
2192 base::TimeDelta::FromMilliseconds(60)));
2193 // Continue dragging, first with one finger, then with two fingers.
2194 QuitWhenNotDragging();
2196 // There should now be another browser.
2197 ASSERT_EQ(2u, native_browser_list->size());
2198 Browser* new_browser = native_browser_list->get(1);
2199 ASSERT_TRUE(new_browser->window()->IsActive());
2200 // The sequence of drags should successfully move the browser window.
2201 bounds += gfx::Vector2d(5 - 2, 1 + 1 + GetDetachY(tab_strip));
2202 EXPECT_EQ(bounds.ToString(),
2203 new_browser->window()->GetNativeWindow()->bounds().ToString());
2206 // Subclass of DetachToBrowserTabDragControllerTest that runs tests with
2207 // docked windows enabled and disabled.
2208 class DetachToDockedTabDragControllerTest
2209 : public DetachToBrowserTabDragControllerTest {
2210 public:
2211 DetachToDockedTabDragControllerTest() {}
2212 virtual ~DetachToDockedTabDragControllerTest() {}
2214 private:
2215 DISALLOW_COPY_AND_ASSIGN(DetachToDockedTabDragControllerTest);
2218 namespace {
2220 void DetachToDockedWindowNextStep(
2221 DetachToDockedTabDragControllerTest* test,
2222 const gfx::Point& target_point,
2223 int iteration) {
2224 ASSERT_EQ(2u, test->native_browser_list->size());
2225 Browser* new_browser = test->native_browser_list->get(1);
2226 ASSERT_TRUE(new_browser->window()->IsActive());
2228 if (!iteration) {
2229 ASSERT_TRUE(test->ReleaseInput());
2230 return;
2232 ASSERT_TRUE(test->DragInputToNotifyWhenDone(
2233 target_point.x(), target_point.y(),
2234 base::Bind(&DetachToDockedWindowNextStep,
2235 test,
2236 gfx::Point(target_point.x(), 1 + target_point.y()),
2237 iteration - 1)));
2240 } // namespace
2242 // Drags from browser to separate window, docks that window and releases mouse.
2243 IN_PROC_BROWSER_TEST_P(DetachToDockedTabDragControllerTest,
2244 DetachToDockedWindowFromMaximizedWindow) {
2245 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
2246 // compositor. crbug.com/331924
2247 if (docked_windows_enabled()) {
2248 VLOG(1) << "Test is DISABLED for docked windows.";
2249 return;
2252 // Maximize the initial browser window.
2253 browser()->window()->Maximize();
2254 ASSERT_TRUE(browser()->window()->IsMaximized());
2256 // Add another tab.
2257 AddTabAndResetBrowser(browser());
2258 TabStrip* tab_strip = GetTabStripForBrowser(browser());
2260 // Move to the first tab and drag it enough so that it detaches.
2261 gfx::Point tab_0_center(
2262 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
2263 ASSERT_TRUE(PressInput(tab_0_center));
2265 // The following matches kMovesBeforeAdjust in snap_sizer.cc
2266 const int kNumIterations = 25 * 5 + 10;
2267 ASSERT_TRUE(DragInputToNotifyWhenDone(
2268 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
2269 base::Bind(&DetachToDockedWindowNextStep, this,
2270 gfx::Point(0, tab_0_center.y() + GetDetachY(tab_strip)),
2271 kNumIterations)));
2272 // Continue dragging enough times to go through snapping sequence and dock
2273 // the window.
2274 QuitWhenNotDragging();
2275 // Should no longer be dragging.
2276 ASSERT_FALSE(tab_strip->IsDragSessionActive());
2277 ASSERT_FALSE(TabDragController::IsActive());
2279 // There should now be another browser.
2280 ASSERT_EQ(2u, native_browser_list->size());
2281 Browser* new_browser = native_browser_list->get(1);
2282 ASSERT_TRUE(new_browser->window()->IsActive());
2283 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser);
2284 ASSERT_FALSE(tab_strip2->IsDragSessionActive());
2286 EXPECT_EQ("0", IDString(new_browser->tab_strip_model()));
2287 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
2289 // The bounds of the initial window should not have changed.
2290 EXPECT_TRUE(browser()->window()->IsMaximized());
2292 EXPECT_FALSE(GetIsDragged(browser()));
2293 EXPECT_FALSE(GetIsDragged(new_browser));
2294 // After this both windows should still be manageable.
2295 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow()));
2296 EXPECT_TRUE(IsWindowPositionManaged(
2297 new_browser->window()->GetNativeWindow()));
2299 ash::wm::WindowState* window_state =
2300 ash::wm::GetWindowState(new_browser->window()->GetNativeWindow());
2301 // The new window should not be maximized because it gets docked or snapped.
2302 EXPECT_FALSE(new_browser->window()->IsMaximized());
2303 if (docked_windows_enabled()) {
2304 // The new window should be docked and not snapped if docking is allowed.
2305 EXPECT_TRUE(window_state->IsDocked());
2306 EXPECT_FALSE(window_state->IsSnapped());
2307 } else {
2308 // The new window should be snapped and not docked if docking is disabled.
2309 EXPECT_FALSE(window_state->IsDocked());
2310 EXPECT_TRUE(window_state->IsSnapped());
2315 #endif
2317 #if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash)
2318 INSTANTIATE_TEST_CASE_P(TabDragging,
2319 DetachToBrowserInSeparateDisplayTabDragControllerTest,
2320 ::testing::Values("mouse", "touch"));
2321 INSTANTIATE_TEST_CASE_P(TabDragging,
2322 DifferentDeviceScaleFactorDisplayTabDragControllerTest,
2323 ::testing::Values("mouse"));
2324 INSTANTIATE_TEST_CASE_P(TabDragging,
2325 DetachToBrowserTabDragControllerTest,
2326 ::testing::Values("mouse", "touch"));
2327 INSTANTIATE_TEST_CASE_P(TabDragging,
2328 DetachToDockedTabDragControllerTest,
2329 ::testing::Values("mouse", "mouse docked"));
2330 INSTANTIATE_TEST_CASE_P(TabDragging,
2331 DetachToBrowserTabDragControllerTestTouch,
2332 ::testing::Values("touch", "touch docked"));
2333 #else
2334 INSTANTIATE_TEST_CASE_P(TabDragging,
2335 DetachToBrowserTabDragControllerTest,
2336 ::testing::Values("mouse"));
2337 #endif