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