tab_drag_controller_interactive_uitest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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. 4 5#include "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h" 6 7#include <algorithm> 8 9#include "ash/wm/window_state.h" 10#include "base/bind.h" 11#include "base/callback.h" 12#include "base/command_line.h" 13#include "base/run_loop.h" 14#include "base/strings/string_number_conversions.h" 15#include "chrome/browser/chrome_notification_types.h" 16#include "chrome/browser/ui/browser.h" 17#include "chrome/browser/ui/browser_commands.h" 18#include "chrome/browser/ui/browser_iterator.h" 19#include "chrome/browser/ui/browser_list.h" 20#include "chrome/browser/ui/host_desktop.h" 21#include "chrome/browser/ui/tabs/tab_strip_model.h" 22#include "chrome/browser/ui/views/frame/browser_view.h" 23#include "chrome/browser/ui/views/frame/native_browser_frame_factory.h" 24#include "chrome/browser/ui/views/tabs/tab.h" 25#include "chrome/browser/ui/views/tabs/tab_drag_controller.h" 26#include "chrome/browser/ui/views/tabs/tab_strip.h" 27#include "chrome/test/base/in_process_browser_test.h" 28#include "chrome/test/base/interactive_test_utils.h" 29#include "chrome/test/base/ui_test_utils.h" 30#include "content/public/browser/notification_details.h" 31#include "content/public/browser/notification_observer.h" 32#include "content/public/browser/notification_service.h" 33#include "content/public/browser/notification_source.h" 34#include "content/public/browser/web_contents.h" 35#include "ui/base/test/ui_controls.h" 36#include "ui/gfx/screen.h" 37#include "ui/views/view.h" 38#include "ui/views/widget/widget.h" 39 40#if defined(USE_AURA) && !defined(OS_CHROMEOS) 41#include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h" 42#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" 43#endif 44 45#if defined(USE_ASH) 46#include "ash/display/display_controller.h" 47#include "ash/display/display_manager.h" 48#include "ash/shell.h" 49#include "ash/test/cursor_manager_test_api.h" 50#include "ash/wm/coordinate_conversion.h" 51#include "ash/wm/window_util.h" 52#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" 53#include "ui/aura/client/screen_position_client.h" 54#include "ui/aura/test/event_generator.h" 55#include "ui/aura/window_event_dispatcher.h" 56#endif 57 58using content::WebContents; 59 60namespace test { 61 62namespace { 63 64const char kTabDragControllerInteractiveUITestUserDataKey[] = 65 "TabDragControllerInteractiveUITestUserData"; 66 67class TabDragControllerInteractiveUITestUserData 68 : public base::SupportsUserData::Data { 69 public: 70 explicit TabDragControllerInteractiveUITestUserData(int id) : id_(id) {} 71 virtual ~TabDragControllerInteractiveUITestUserData() {} 72 int id() { return id_; } 73 74 private: 75 int id_; 76}; 77 78} // namespace 79 80class QuitDraggingObserver : public content::NotificationObserver { 81 public: 82 QuitDraggingObserver() { 83 registrar_.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, 84 content::NotificationService::AllSources()); 85 } 86 87 virtual void Observe(int type, 88 const content::NotificationSource& source, 89 const content::NotificationDetails& details) OVERRIDE { 90 DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, type); 91 base::MessageLoopForUI::current()->Quit(); 92 delete this; 93 } 94 95 private: 96 virtual ~QuitDraggingObserver() {} 97 98 content::NotificationRegistrar registrar_; 99 100 DISALLOW_COPY_AND_ASSIGN(QuitDraggingObserver); 101}; 102 103gfx::Point GetCenterInScreenCoordinates(const views::View* view) { 104 gfx::Point center(view->width() / 2, view->height() / 2); 105 views::View::ConvertPointToScreen(view, ¢er); 106 return center; 107} 108 109void SetID(WebContents* web_contents, int id) { 110 web_contents->SetUserData(&kTabDragControllerInteractiveUITestUserDataKey, 111 new TabDragControllerInteractiveUITestUserData(id)); 112} 113 114void ResetIDs(TabStripModel* model, int start) { 115 for (int i = 0; i < model->count(); ++i) 116 SetID(model->GetWebContentsAt(i), start + i); 117} 118 119std::string IDString(TabStripModel* model) { 120 std::string result; 121 for (int i = 0; i < model->count(); ++i) { 122 if (i != 0) 123 result += " "; 124 WebContents* contents = model->GetWebContentsAt(i); 125 TabDragControllerInteractiveUITestUserData* user_data = 126 static_cast<TabDragControllerInteractiveUITestUserData*>( 127 contents->GetUserData( 128 &kTabDragControllerInteractiveUITestUserDataKey)); 129 if (user_data) 130 result += base::IntToString(user_data->id()); 131 else 132 result += "?"; 133 } 134 return result; 135} 136 137// Creates a listener that quits the message loop when no longer dragging. 138void QuitWhenNotDraggingImpl() { 139 new QuitDraggingObserver(); // QuitDraggingObserver deletes itself. 140} 141 142TabStrip* GetTabStripForBrowser(Browser* browser) { 143 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 144 return static_cast<TabStrip*>(browser_view->tabstrip()); 145} 146 147} // namespace test 148 149using test::GetCenterInScreenCoordinates; 150using test::SetID; 151using test::ResetIDs; 152using test::IDString; 153using test::GetTabStripForBrowser; 154 155TabDragControllerTest::TabDragControllerTest() 156 : native_browser_list(BrowserList::GetInstance( 157 chrome::HOST_DESKTOP_TYPE_NATIVE)) { 158} 159 160TabDragControllerTest::~TabDragControllerTest() { 161} 162 163void TabDragControllerTest::StopAnimating(TabStrip* tab_strip) { 164 tab_strip->StopAnimating(true); 165} 166 167void TabDragControllerTest::AddTabAndResetBrowser(Browser* browser) { 168 AddBlankTabAndShow(browser); 169 StopAnimating(GetTabStripForBrowser(browser)); 170 ResetIDs(browser->tab_strip_model(), 0); 171} 172 173Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() { 174 // Create another browser. 175 Browser* browser2 = CreateBrowser(browser()->profile()); 176 ResetIDs(browser2->tab_strip_model(), 100); 177 178 // Resize the two windows so they're right next to each other. 179 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 180 browser()->window()->GetNativeWindow()).work_area(); 181 gfx::Size half_size = 182 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10); 183 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size)); 184 browser2->window()->SetBounds(gfx::Rect( 185 work_area.x() + half_size.width(), work_area.y(), 186 half_size.width(), half_size.height())); 187 return browser2; 188} 189 190namespace { 191 192enum InputSource { 193 INPUT_SOURCE_MOUSE = 0, 194 INPUT_SOURCE_TOUCH = 1 195}; 196 197int GetDetachY(TabStrip* tab_strip) { 198 return std::max(TabDragController::kTouchVerticalDetachMagnetism, 199 TabDragController::kVerticalDetachMagnetism) + 200 tab_strip->height() + 1; 201} 202 203bool GetIsDragged(Browser* browser) { 204#if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash) 205 return false; 206#else 207 return ash::wm::GetWindowState(browser->window()->GetNativeWindow())-> 208 is_dragged(); 209#endif 210} 211 212} // namespace 213 214#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 215class ScreenEventGeneratorDelegate : public aura::test::EventGeneratorDelegate { 216 public: 217 explicit ScreenEventGeneratorDelegate(aura::Window* root_window) 218 : root_window_(root_window) {} 219 virtual ~ScreenEventGeneratorDelegate() {} 220 221 // EventGeneratorDelegate overrides: 222 virtual aura::WindowTreeHost* GetHostAt( 223 const gfx::Point& point) const OVERRIDE { 224 return root_window_->GetHost(); 225 } 226 227 virtual aura::client::ScreenPositionClient* GetScreenPositionClient( 228 const aura::Window* window) const OVERRIDE { 229 return aura::client::GetScreenPositionClient(root_window_); 230 } 231 232 private: 233 aura::Window* root_window_; 234 235 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate); 236}; 237 238#endif 239 240#if !defined(OS_CHROMEOS) 241 242// Following classes verify a crash scenario. Specifically on Windows when focus 243// changes it can trigger capture being lost. This was causing a crash in tab 244// dragging as it wasn't set up to handle this scenario. These classes 245// synthesize this scenario. 246 247// Allows making ClearNativeFocus() invoke ReleaseCapture(). 248class TestDesktopBrowserFrameAura : public DesktopBrowserFrameAura { 249 public: 250 TestDesktopBrowserFrameAura( 251 BrowserFrame* browser_frame, 252 BrowserView* browser_view) 253 : DesktopBrowserFrameAura(browser_frame, browser_view), 254 release_capture_(false) {} 255 virtual ~TestDesktopBrowserFrameAura() {} 256 257 void ReleaseCaptureOnNextClear() { 258 release_capture_ = true; 259 } 260 261 virtual void ClearNativeFocus() OVERRIDE { 262 views::DesktopNativeWidgetAura::ClearNativeFocus(); 263 if (release_capture_) { 264 release_capture_ = false; 265 GetWidget()->ReleaseCapture(); 266 } 267 } 268 269 private: 270 // If true ReleaseCapture() is invoked in ClearNativeFocus(). 271 bool release_capture_; 272 273 DISALLOW_COPY_AND_ASSIGN(TestDesktopBrowserFrameAura); 274}; 275 276// Factory for creating a TestDesktopBrowserFrameAura. 277class TestNativeBrowserFrameFactory : public NativeBrowserFrameFactory { 278 public: 279 TestNativeBrowserFrameFactory() {} 280 virtual ~TestNativeBrowserFrameFactory() {} 281 282 virtual NativeBrowserFrame* Create( 283 BrowserFrame* browser_frame, 284 BrowserView* browser_view) OVERRIDE { 285 return new TestDesktopBrowserFrameAura(browser_frame, browser_view); 286 } 287 288 private: 289 DISALLOW_COPY_AND_ASSIGN(TestNativeBrowserFrameFactory); 290}; 291 292class TabDragCaptureLostTest : public TabDragControllerTest { 293 public: 294 TabDragCaptureLostTest() { 295 NativeBrowserFrameFactory::Set(new TestNativeBrowserFrameFactory); 296 } 297 298 private: 299 DISALLOW_COPY_AND_ASSIGN(TabDragCaptureLostTest); 300}; 301 302// See description above for details. 303IN_PROC_BROWSER_TEST_F(TabDragCaptureLostTest, ReleaseCaptureOnDrag) { 304 AddTabAndResetBrowser(browser()); 305 306 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 307 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1))); 308 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_1_center) && 309 ui_test_utils::SendMouseEventsSync( 310 ui_controls::LEFT, ui_controls::DOWN)); 311 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 312 TestDesktopBrowserFrameAura* frame = 313 static_cast<TestDesktopBrowserFrameAura*>( 314 BrowserView::GetBrowserViewForBrowser(browser())->GetWidget()-> 315 native_widget_private()); 316 // Invoke ReleaseCaptureOnDrag() so that when the drag happens and focus 317 // changes capture is released and the drag cancels. 318 frame->ReleaseCaptureOnNextClear(); 319 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_0_center)); 320 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 321} 322 323IN_PROC_BROWSER_TEST_F(TabDragControllerTest, GestureEndShouldEndDragTest) { 324 AddTabAndResetBrowser(browser()); 325 326 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 327 328 Tab* tab1 = tab_strip->tab_at(1); 329 gfx::Point tab_1_center(tab1->width() / 2, tab1->height() / 2); 330 331 ui::GestureEvent gesture_begin(ui::ET_GESTURE_BEGIN, tab_1_center.x(), 332 tab_1_center.x(), 0, base::TimeDelta(), 333 ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0.0f, 0.0f), 0); 334 tab_strip->MaybeStartDrag(tab1, gesture_begin, 335 tab_strip->GetSelectionModel()); 336 EXPECT_TRUE(TabDragController::IsActive()); 337 338 ui::GestureEvent gesture_end(ui::ET_GESTURE_END, tab_1_center.x(), 339 tab_1_center.x(), 0, base::TimeDelta(), 340 ui::GestureEventDetails(ui::ET_GESTURE_END, 0.0f, 0.0f), 0); 341 tab_strip->OnGestureEvent(&gesture_end); 342 EXPECT_FALSE(TabDragController::IsActive()); 343 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 344} 345 346#endif 347 348class DetachToBrowserTabDragControllerTest 349 : public TabDragControllerTest, 350 public ::testing::WithParamInterface<const char*> { 351 public: 352 DetachToBrowserTabDragControllerTest() {} 353 354 virtual void SetUpOnMainThread() OVERRIDE { 355#if defined(OS_CHROMEOS) 356 event_generator_.reset(new aura::test::EventGenerator( 357 ash::Shell::GetPrimaryRootWindow())); 358#endif 359 } 360 361 InputSource input_source() const { 362 return strstr(GetParam(), "mouse") ? 363 INPUT_SOURCE_MOUSE : INPUT_SOURCE_TOUCH; 364 } 365 366 // Set root window from a point in screen coordinates 367 void SetEventGeneratorRootWindow(const gfx::Point& point) { 368 if (input_source() == INPUT_SOURCE_MOUSE) 369 return; 370#if defined(OS_CHROMEOS) 371 event_generator_.reset(new aura::test::EventGenerator( 372 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point)))); 373#endif 374 } 375 376 // The following methods update one of the mouse or touch input depending upon 377 // the InputSource. 378 bool PressInput(const gfx::Point& location) { 379 if (input_source() == INPUT_SOURCE_MOUSE) { 380 return ui_test_utils::SendMouseMoveSync(location) && 381 ui_test_utils::SendMouseEventsSync( 382 ui_controls::LEFT, ui_controls::DOWN); 383 } 384#if defined(OS_CHROMEOS) 385 event_generator_->set_current_location(location); 386 event_generator_->PressTouch(); 387#else 388 NOTREACHED(); 389#endif 390 return true; 391 } 392 393 bool PressInput2() { 394 // Second touch input is only used for touch sequence tests. 395 EXPECT_EQ(INPUT_SOURCE_TOUCH, input_source()); 396#if defined(OS_CHROMEOS) 397 event_generator_->set_current_location( 398 event_generator_->current_location()); 399 event_generator_->PressTouchId(1); 400#else 401 NOTREACHED(); 402#endif 403 return true; 404 } 405 406 bool DragInputTo(const gfx::Point& location) { 407 if (input_source() == INPUT_SOURCE_MOUSE) 408 return ui_test_utils::SendMouseMoveSync(location); 409#if defined(OS_CHROMEOS) 410 event_generator_->MoveTouch(location); 411#else 412 NOTREACHED(); 413#endif 414 return true; 415 } 416 417 bool DragInputToAsync(const gfx::Point& location) { 418 if (input_source() == INPUT_SOURCE_MOUSE) 419 return ui_controls::SendMouseMove(location.x(), location.y()); 420#if defined(OS_CHROMEOS) 421 event_generator_->MoveTouch(location); 422#else 423 NOTREACHED(); 424#endif 425 return true; 426 } 427 428 bool DragInputToNotifyWhenDone(int x, 429 int y, 430 const base::Closure& task) { 431 if (input_source() == INPUT_SOURCE_MOUSE) 432 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 433#if defined(OS_CHROMEOS) 434 base::MessageLoop::current()->PostTask(FROM_HERE, task); 435 event_generator_->MoveTouch(gfx::Point(x, y)); 436#else 437 NOTREACHED(); 438#endif 439 return true; 440 } 441 442 bool DragInputToDelayedNotifyWhenDone(int x, 443 int y, 444 const base::Closure& task, 445 base::TimeDelta delay) { 446 if (input_source() == INPUT_SOURCE_MOUSE) 447 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 448#if defined(OS_CHROMEOS) 449 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, task, delay); 450 event_generator_->MoveTouch(gfx::Point(x, y)); 451#else 452 NOTREACHED(); 453#endif 454 return true; 455 } 456 457 bool DragInput2ToNotifyWhenDone(int x, 458 int y, 459 const base::Closure& task) { 460 if (input_source() == INPUT_SOURCE_MOUSE) 461 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 462#if defined(OS_CHROMEOS) 463 base::MessageLoop::current()->PostTask(FROM_HERE, task); 464 event_generator_->MoveTouchId(gfx::Point(x, y), 1); 465#else 466 NOTREACHED(); 467#endif 468 return true; 469 } 470 471 bool ReleaseInput() { 472 if (input_source() == INPUT_SOURCE_MOUSE) { 473 return ui_test_utils::SendMouseEventsSync( 474 ui_controls::LEFT, ui_controls::UP); 475 } 476#if defined(OS_CHROMEOS) 477 event_generator_->ReleaseTouch(); 478#else 479 NOTREACHED(); 480#endif 481 return true; 482 } 483 484 bool ReleaseInput2() { 485 if (input_source() == INPUT_SOURCE_MOUSE) { 486 return ui_test_utils::SendMouseEventsSync( 487 ui_controls::LEFT, ui_controls::UP); 488 } 489#if defined(OS_CHROMEOS) 490 event_generator_->ReleaseTouchId(1); 491#else 492 NOTREACHED(); 493#endif 494 return true; 495 } 496 497 bool ReleaseMouseAsync() { 498 return input_source() == INPUT_SOURCE_MOUSE && 499 ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP); 500 } 501 502 void QuitWhenNotDragging() { 503 if (input_source() == INPUT_SOURCE_MOUSE) { 504 // Schedule observer to quit message loop when done dragging. This has to 505 // be async so the message loop can run. 506 test::QuitWhenNotDraggingImpl(); 507 base::MessageLoop::current()->Run(); 508 } else { 509 // Touch events are sync, so we know we're not in a drag session. But some 510 // tests rely on the browser fully closing, which is async. So, run all 511 // pending tasks. 512 base::RunLoop run_loop; 513 run_loop.RunUntilIdle(); 514 } 515 } 516 517 void AddBlankTabAndShow(Browser* browser) { 518 InProcessBrowserTest::AddBlankTabAndShow(browser); 519 } 520 521 Browser* browser() const { return InProcessBrowserTest::browser(); } 522 523 private: 524#if defined(OS_CHROMEOS) 525 scoped_ptr<aura::test::EventGenerator> event_generator_; 526#endif 527 528 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest); 529}; 530 531// Creates a browser with two tabs, drags the second to the first. 532IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragInSameWindow) { 533 // TODO(sky): this won't work with touch as it requires a long press. 534 if (input_source() == INPUT_SOURCE_TOUCH) { 535 VLOG(1) << "Test is DISABLED for touch input."; 536 return; 537 } 538 539 AddTabAndResetBrowser(browser()); 540 541 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 542 TabStripModel* model = browser()->tab_strip_model(); 543 544 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1))); 545 ASSERT_TRUE(PressInput(tab_1_center)); 546 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 547 ASSERT_TRUE(DragInputTo(tab_0_center)); 548 ASSERT_TRUE(ReleaseInput()); 549 EXPECT_EQ("1 0", IDString(model)); 550 EXPECT_FALSE(TabDragController::IsActive()); 551 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 552 553 // The tab strip should no longer have capture because the drag was ended and 554 // mouse/touch was released. 555 EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); 556} 557 558namespace { 559 560// Invoked from the nested message loop. 561void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 562 TabStrip* not_attached_tab_strip, 563 TabStrip* target_tab_strip) { 564 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 565 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 566 ASSERT_TRUE(TabDragController::IsActive()); 567 568 // Drag to target_tab_strip. This should stop the nested loop from dragging 569 // the window. 570 gfx::Point target_point(target_tab_strip->width() -1, 571 target_tab_strip->height() / 2); 572 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 573 ASSERT_TRUE(test->DragInputToAsync(target_point)); 574} 575 576} // namespace 577 578#if defined(OS_CHROMEOS) || defined(OS_LINUX) 579// TODO(sky,sad): Disabled as it fails due to resize locks with a real 580// compositor. crbug.com/331924 581#define MAYBE_DragToSeparateWindow DISABLED_DragToSeparateWindow 582#else 583#define MAYBE_DragToSeparateWindow DragToSeparateWindow 584#endif 585// Creates two browsers, drags from first into second. 586IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 587 MAYBE_DragToSeparateWindow) { 588 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 589 590 // Add another tab to browser(). 591 AddTabAndResetBrowser(browser()); 592 593 // Create another browser. 594 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 595 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 596 597 // Move to the first tab and drag it enough so that it detaches, but not 598 // enough that it attaches to browser2. 599 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 600 ASSERT_TRUE(PressInput(tab_0_center)); 601 ASSERT_TRUE(DragInputToNotifyWhenDone( 602 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 603 base::Bind(&DragToSeparateWindowStep2, 604 this, tab_strip, tab_strip2))); 605 QuitWhenNotDragging(); 606 607 // Should now be attached to tab_strip2. 608 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 609 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 610 ASSERT_TRUE(TabDragController::IsActive()); 611 EXPECT_FALSE(GetIsDragged(browser())); 612 613 // Release mouse or touch, stopping the drag session. 614 ASSERT_TRUE(ReleaseInput()); 615 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 616 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 617 ASSERT_FALSE(TabDragController::IsActive()); 618 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 619 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 620 EXPECT_FALSE(GetIsDragged(browser2)); 621 622 // Both windows should not be maximized 623 EXPECT_FALSE(browser()->window()->IsMaximized()); 624 EXPECT_FALSE(browser2->window()->IsMaximized()); 625 626 // The tab strip should no longer have capture because the drag was ended and 627 // mouse/touch was released. 628 EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); 629 EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); 630} 631 632namespace { 633 634void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest* test) { 635 if (test->input_source() == INPUT_SOURCE_TOUCH) 636 ASSERT_TRUE(test->ReleaseInput()); 637} 638 639#if defined(OS_CHROMEOS) 640bool IsWindowPositionManaged(aura::Window* window) { 641 return ash::wm::GetWindowState(window)->window_position_managed(); 642} 643bool HasUserChangedWindowPositionOrSize(aura::Window* window) { 644 return ash::wm::GetWindowState(window)->bounds_changed_by_user(); 645} 646#else 647bool IsWindowPositionManaged(gfx::NativeWindow window) { 648 return true; 649} 650bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window) { 651 return false; 652} 653#endif 654 655} // namespace 656 657#if defined(OS_CHROMEOS) || defined(OS_LINUX) 658// TODO(sky,sad): Disabled as it fails due to resize locks with a real 659// compositor. crbug.com/331924 660#define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow 661#else 662#define MAYBE_DetachToOwnWindow DetachToOwnWindow 663#endif 664// Drags from browser to separate window and releases mouse. 665IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 666 MAYBE_DetachToOwnWindow) { 667 const gfx::Rect initial_bounds(browser()->window()->GetBounds()); 668 // Add another tab. 669 AddTabAndResetBrowser(browser()); 670 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 671 672 // Move to the first tab and drag it enough so that it detaches. 673 gfx::Point tab_0_center( 674 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 675 ASSERT_TRUE(PressInput(tab_0_center)); 676 ASSERT_TRUE(DragInputToNotifyWhenDone( 677 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 678 base::Bind(&DetachToOwnWindowStep2, this))); 679 if (input_source() == INPUT_SOURCE_MOUSE) { 680 ASSERT_TRUE(ReleaseMouseAsync()); 681 QuitWhenNotDragging(); 682 } 683 684 // Should no longer be dragging. 685 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 686 ASSERT_FALSE(TabDragController::IsActive()); 687 688 // There should now be another browser. 689 ASSERT_EQ(2u, native_browser_list->size()); 690 Browser* new_browser = native_browser_list->get(1); 691 ASSERT_TRUE(new_browser->window()->IsActive()); 692 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 693 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 694 695 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 696 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 697 698 // The bounds of the initial window should not have changed. 699 EXPECT_EQ(initial_bounds.ToString(), 700 browser()->window()->GetBounds().ToString()); 701 702 EXPECT_FALSE(GetIsDragged(browser())); 703 EXPECT_FALSE(GetIsDragged(new_browser)); 704 // After this both windows should still be manageable. 705 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 706 EXPECT_TRUE(IsWindowPositionManaged( 707 new_browser->window()->GetNativeWindow())); 708 709 // Both windows should not be maximized 710 EXPECT_FALSE(browser()->window()->IsMaximized()); 711 EXPECT_FALSE(new_browser->window()->IsMaximized()); 712 713 // The tab strip should no longer have capture because the drag was ended and 714 // mouse/touch was released. 715 EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); 716 EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); 717} 718 719#if defined(OS_CHROMEOS) || defined(OS_LINUX) 720// TODO(sky,sad): Disabled as it fails due to resize locks with a real 721// compositor. crbug.com/331924 722#define MAYBE_DetachToOwnWindowFromMaximizedWindow \ 723 DISABLED_DetachToOwnWindowFromMaximizedWindow 724#else 725#define MAYBE_DetachToOwnWindowFromMaximizedWindow \ 726 DetachToOwnWindowFromMaximizedWindow 727#endif 728// Drags from browser to a separate window and releases mouse. 729IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 730 MAYBE_DetachToOwnWindowFromMaximizedWindow) { 731 // Maximize the initial browser window. 732 browser()->window()->Maximize(); 733 ASSERT_TRUE(browser()->window()->IsMaximized()); 734 735 // Add another tab. 736 AddTabAndResetBrowser(browser()); 737 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 738 739 // Move to the first tab and drag it enough so that it detaches. 740 gfx::Point tab_0_center( 741 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 742 ASSERT_TRUE(PressInput(tab_0_center)); 743 ASSERT_TRUE(DragInputToNotifyWhenDone( 744 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 745 base::Bind(&DetachToOwnWindowStep2, this))); 746 if (input_source() == INPUT_SOURCE_MOUSE) { 747 ASSERT_TRUE(ReleaseMouseAsync()); 748 QuitWhenNotDragging(); 749 } 750 751 // Should no longer be dragging. 752 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 753 ASSERT_FALSE(TabDragController::IsActive()); 754 755 // There should now be another browser. 756 ASSERT_EQ(2u, native_browser_list->size()); 757 Browser* new_browser = native_browser_list->get(1); 758 ASSERT_TRUE(new_browser->window()->IsActive()); 759 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 760 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 761 762 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 763 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 764 765 // The bounds of the initial window should not have changed. 766 EXPECT_TRUE(browser()->window()->IsMaximized()); 767 768 EXPECT_FALSE(GetIsDragged(browser())); 769 EXPECT_FALSE(GetIsDragged(new_browser)); 770 // After this both windows should still be manageable. 771 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 772 EXPECT_TRUE(IsWindowPositionManaged( 773 new_browser->window()->GetNativeWindow())); 774 775 // The new window should be maximized. 776 EXPECT_TRUE(new_browser->window()->IsMaximized()); 777} 778 779// Deletes a tab being dragged before the user moved enough to start a drag. 780IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 781 DeleteBeforeStartedDragging) { 782 // Add another tab. 783 AddTabAndResetBrowser(browser()); 784 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 785 786 // Click on the first tab, but don't move it. 787 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 788 ASSERT_TRUE(PressInput(tab_0_center)); 789 790 // Should be dragging. 791 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 792 ASSERT_TRUE(TabDragController::IsActive()); 793 794 // Delete the tab being dragged. 795 delete browser()->tab_strip_model()->GetWebContentsAt(0); 796 797 // Should have canceled dragging. 798 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 799 ASSERT_FALSE(TabDragController::IsActive()); 800 801 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 802 EXPECT_FALSE(GetIsDragged(browser())); 803} 804 805#if defined(OS_CHROMEOS) 806// TODO(sky,sad): Disabled as it fails due to resize locks with a real 807// compositor. crbug.com/331924 808#define MAYBE_DeleteTabWhileAttached DISABLED_DeleteTabWhileAttached 809#else 810#define MAYBE_DeleteTabWhileAttached DeleteTabWhileAttached 811#endif 812// Deletes a tab being dragged while still attached. 813IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 814 MAYBE_DeleteTabWhileAttached) { 815 // TODO(sky,sad): Disabled as it fails due to resize locks with a real 816 // compositor. crbug.com/331924 817 if (input_source() == INPUT_SOURCE_MOUSE) { 818 VLOG(1) << "Test is DISABLED for mouse input."; 819 return; 820 } 821 822 // Add another tab. 823 AddTabAndResetBrowser(browser()); 824 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 825 826 // Click on the first tab and move it enough so that it starts dragging but is 827 // still attached. 828 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 829 ASSERT_TRUE(PressInput(tab_0_center)); 830 ASSERT_TRUE(DragInputTo( 831 gfx::Point(tab_0_center.x() + 20, tab_0_center.y()))); 832 833 // Should be dragging. 834 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 835 ASSERT_TRUE(TabDragController::IsActive()); 836 837 // Delete the tab being dragged. 838 delete browser()->tab_strip_model()->GetWebContentsAt(0); 839 840 // Should have canceled dragging. 841 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 842 ASSERT_FALSE(TabDragController::IsActive()); 843 844 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 845 846 EXPECT_FALSE(GetIsDragged(browser())); 847} 848 849namespace { 850 851void DeleteWhileDetachedStep2(WebContents* tab) { 852 delete tab; 853} 854 855} // namespace 856 857#if defined(OS_CHROMEOS) 858// TODO(sky,sad): Disabled as it fails due to resize locks with a real 859// compositor. crbug.com/331924 860#define MAYBE_DeleteTabWhileDetached DISABLED_DeleteTabWhileDetached 861#else 862#define MAYBE_DeleteTabWhileDetached DeleteTabWhileDetached 863#endif 864// Deletes a tab being dragged after dragging a tab so that a new window is 865// created. 866IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 867 MAYBE_DeleteTabWhileDetached) { 868 // Add another tab. 869 AddTabAndResetBrowser(browser()); 870 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 871 872 // Move to the first tab and drag it enough so that it detaches. 873 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 874 WebContents* to_delete = 875 browser()->tab_strip_model()->GetWebContentsAt(0); 876 ASSERT_TRUE(PressInput(tab_0_center)); 877 ASSERT_TRUE(DragInputToNotifyWhenDone( 878 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 879 base::Bind(&DeleteWhileDetachedStep2, to_delete))); 880 QuitWhenNotDragging(); 881 882 // Should not be dragging. 883 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 884 ASSERT_FALSE(TabDragController::IsActive()); 885 886 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 887 888 EXPECT_FALSE(GetIsDragged(browser())); 889} 890 891namespace { 892 893void DeleteSourceDetachedStep2(WebContents* tab, 894 const BrowserList* browser_list) { 895 ASSERT_EQ(2u, browser_list->size()); 896 Browser* new_browser = browser_list->get(1); 897 // This ends up closing the source window. 898 delete tab; 899 // Cancel the drag. 900 ui_controls::SendKeyPress(new_browser->window()->GetNativeWindow(), 901 ui::VKEY_ESCAPE, false, false, false, false); 902} 903 904} // namespace 905 906#if defined(OS_CHROMEOS) || defined(OS_LINUX) 907// TODO(sky,sad): Disabled as it fails due to resize locks with a real 908// compositor. crbug.com/331924 909#define MAYBE_DeleteSourceDetached DISABLED_DeleteSourceDetached 910#else 911#define MAYBE_DeleteSourceDetached DeleteSourceDetached 912#endif 913// Detaches a tab and while detached deletes a tab from the source so that the 914// source window closes then presses escape to cancel the drag. 915IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 916 MAYBE_DeleteSourceDetached) { 917 // Add another tab. 918 AddTabAndResetBrowser(browser()); 919 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 920 921 // Move to the first tab and drag it enough so that it detaches. 922 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 923 WebContents* to_delete = browser()->tab_strip_model()->GetWebContentsAt(1); 924 ASSERT_TRUE(PressInput(tab_0_center)); 925 ASSERT_TRUE(DragInputToNotifyWhenDone( 926 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 927 base::Bind(&DeleteSourceDetachedStep2, to_delete, native_browser_list))); 928 QuitWhenNotDragging(); 929 930 // Should not be dragging. 931 ASSERT_EQ(1u, native_browser_list->size()); 932 Browser* new_browser = native_browser_list->get(0); 933 ASSERT_FALSE(GetTabStripForBrowser(new_browser)->IsDragSessionActive()); 934 ASSERT_FALSE(TabDragController::IsActive()); 935 936 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 937 938 EXPECT_FALSE(GetIsDragged(new_browser)); 939 940 // Remaining browser window should not be maximized 941 EXPECT_FALSE(new_browser->window()->IsMaximized()); 942} 943 944namespace { 945 946void PressEscapeWhileDetachedStep2(const BrowserList* browser_list) { 947 ASSERT_EQ(2u, browser_list->size()); 948 Browser* new_browser = browser_list->get(1); 949 ui_controls::SendKeyPress( 950 new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, 951 false, false); 952} 953 954} // namespace 955 956#if defined(OS_CHROMEOS) || defined(OS_LINUX) 957// TODO(sky,sad): Disabled as it fails due to resize locks with a real 958// compositor. crbug.com/331924 959#define MAYBE_PressEscapeWhileDetached DISABLED_PressEscapeWhileDetached 960#else 961#define MAYBE_PressEscapeWhileDetached PressEscapeWhileDetached 962#endif 963// This is disabled until NativeViewHost::Detach really detaches. 964// Detaches a tab and while detached presses escape to revert the drag. 965IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 966 MAYBE_PressEscapeWhileDetached) { 967 // Add another tab. 968 AddTabAndResetBrowser(browser()); 969 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 970 971 // Move to the first tab and drag it enough so that it detaches. 972 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 973 ASSERT_TRUE(PressInput(tab_0_center)); 974 ASSERT_TRUE(DragInputToNotifyWhenDone( 975 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 976 base::Bind(&PressEscapeWhileDetachedStep2, native_browser_list))); 977 QuitWhenNotDragging(); 978 979 // Should not be dragging. 980 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 981 ASSERT_FALSE(TabDragController::IsActive()); 982 983 // And there should only be one window. 984 EXPECT_EQ(1u, native_browser_list->size()); 985 986 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 987 988 // Remaining browser window should not be maximized 989 EXPECT_FALSE(browser()->window()->IsMaximized()); 990 991 // The tab strip should no longer have capture because the drag was ended and 992 // mouse/touch was released. 993 EXPECT_FALSE(tab_strip->GetWidget()->HasCapture()); 994} 995 996namespace { 997 998void DragAllStep2(DetachToBrowserTabDragControllerTest* test, 999 const BrowserList* browser_list) { 1000 // Should only be one window. 1001 ASSERT_EQ(1u, browser_list->size()); 1002 if (test->input_source() == INPUT_SOURCE_TOUCH) { 1003 ASSERT_TRUE(test->ReleaseInput()); 1004 } else { 1005 ASSERT_TRUE(test->ReleaseMouseAsync()); 1006 } 1007} 1008 1009} // namespace 1010 1011#if defined(OS_CHROMEOS) || defined(OS_LINUX) 1012// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1013// compositor. crbug.com/331924 1014#define MAYBE_DragAll DISABLED_DragAll 1015#else 1016#define MAYBE_DragAll DragAll 1017#endif 1018// Selects multiple tabs and starts dragging the window. 1019IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) { 1020 // Add another tab. 1021 AddTabAndResetBrowser(browser()); 1022 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1023 browser()->tab_strip_model()->AddTabAtToSelection(0); 1024 browser()->tab_strip_model()->AddTabAtToSelection(1); 1025 1026 // Move to the first tab and drag it enough so that it would normally 1027 // detach. 1028 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1029 ASSERT_TRUE(PressInput(tab_0_center)); 1030 ASSERT_TRUE(DragInputToNotifyWhenDone( 1031 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1032 base::Bind(&DragAllStep2, this, native_browser_list))); 1033 QuitWhenNotDragging(); 1034 1035 // Should not be dragging. 1036 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1037 ASSERT_FALSE(TabDragController::IsActive()); 1038 1039 // And there should only be one window. 1040 EXPECT_EQ(1u, native_browser_list->size()); 1041 1042 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1043 1044 EXPECT_FALSE(GetIsDragged(browser())); 1045 1046 // Remaining browser window should not be maximized 1047 EXPECT_FALSE(browser()->window()->IsMaximized()); 1048} 1049 1050namespace { 1051 1052// Invoked from the nested message loop. 1053void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 1054 TabStrip* attached_tab_strip, 1055 TabStrip* target_tab_strip, 1056 const BrowserList* browser_list) { 1057 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 1058 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1059 ASSERT_TRUE(TabDragController::IsActive()); 1060 ASSERT_EQ(2u, browser_list->size()); 1061 1062 // Drag to target_tab_strip. This should stop the nested loop from dragging 1063 // the window. 1064 gfx::Point target_point(target_tab_strip->width() - 1, 1065 target_tab_strip->height() / 2); 1066 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 1067 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1068} 1069 1070} // namespace 1071 1072#if defined(OS_CHROMEOS) || defined(OS_LINUX) 1073// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1074// compositor. crbug.com/331924 1075#define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow 1076#else 1077#define MAYBE_DragAllToSeparateWindow DragAllToSeparateWindow 1078#endif 1079// Creates two browsers, selects all tabs in first and drags into second. 1080IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1081 MAYBE_DragAllToSeparateWindow) { 1082 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1083 1084 // Add another tab to browser(). 1085 AddTabAndResetBrowser(browser()); 1086 1087 // Create another browser. 1088 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1089 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1090 1091 browser()->tab_strip_model()->AddTabAtToSelection(0); 1092 browser()->tab_strip_model()->AddTabAtToSelection(1); 1093 1094 // Move to the first tab and drag it enough so that it detaches, but not 1095 // enough that it attaches to browser2. 1096 gfx::Point tab_0_center( 1097 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1098 ASSERT_TRUE(PressInput(tab_0_center)); 1099 ASSERT_TRUE(DragInputToNotifyWhenDone( 1100 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1101 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 1102 native_browser_list))); 1103 QuitWhenNotDragging(); 1104 1105 // Should now be attached to tab_strip2. 1106 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1107 ASSERT_TRUE(TabDragController::IsActive()); 1108 ASSERT_EQ(1u, native_browser_list->size()); 1109 1110 // Release the mouse, stopping the drag session. 1111 ASSERT_TRUE(ReleaseInput()); 1112 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1113 ASSERT_FALSE(TabDragController::IsActive()); 1114 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 1115 1116 EXPECT_FALSE(GetIsDragged(browser2)); 1117 1118 // Remaining browser window should not be maximized 1119 EXPECT_FALSE(browser2->window()->IsMaximized()); 1120} 1121 1122namespace { 1123 1124// Invoked from the nested message loop. 1125void DragAllToSeparateWindowAndCancelStep2( 1126 DetachToBrowserTabDragControllerTest* test, 1127 TabStrip* attached_tab_strip, 1128 TabStrip* target_tab_strip, 1129 const BrowserList* browser_list) { 1130 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 1131 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1132 ASSERT_TRUE(TabDragController::IsActive()); 1133 ASSERT_EQ(2u, browser_list->size()); 1134 1135 // Drag to target_tab_strip. This should stop the nested loop from dragging 1136 // the window. 1137 gfx::Point target_point(target_tab_strip->width() - 1, 1138 target_tab_strip->height() / 2); 1139 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 1140 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1141} 1142 1143} // namespace 1144 1145#if defined(OS_CHROMEOS) || defined(OS_LINUX) 1146// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1147// compositor. crbug.com/331924 1148#define MAYBE_DragAllToSeparateWindowAndCancel \ 1149 DISABLED_DragAllToSeparateWindowAndCancel 1150#else 1151#define MAYBE_DragAllToSeparateWindowAndCancel DragAllToSeparateWindowAndCancel 1152#endif 1153// Creates two browsers, selects all tabs in first, drags into second, then hits 1154// escape. 1155IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1156 MAYBE_DragAllToSeparateWindowAndCancel) { 1157 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1158 1159 // Add another tab to browser(). 1160 AddTabAndResetBrowser(browser()); 1161 1162 // Create another browser. 1163 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1164 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1165 1166 browser()->tab_strip_model()->AddTabAtToSelection(0); 1167 browser()->tab_strip_model()->AddTabAtToSelection(1); 1168 1169 // Move to the first tab and drag it enough so that it detaches, but not 1170 // enough that it attaches to browser2. 1171 gfx::Point tab_0_center( 1172 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1173 ASSERT_TRUE(PressInput(tab_0_center)); 1174 ASSERT_TRUE(DragInputToNotifyWhenDone( 1175 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1176 base::Bind(&DragAllToSeparateWindowAndCancelStep2, this, 1177 tab_strip, tab_strip2, native_browser_list))); 1178 QuitWhenNotDragging(); 1179 1180 // Should now be attached to tab_strip2. 1181 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1182 ASSERT_TRUE(TabDragController::IsActive()); 1183 ASSERT_EQ(1u, native_browser_list->size()); 1184 1185 // Cancel the drag. 1186 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 1187 browser2, ui::VKEY_ESCAPE, false, false, false, false)); 1188 1189 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1190 ASSERT_FALSE(TabDragController::IsActive()); 1191 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 1192 1193 // browser() will have been destroyed, but browser2 should remain. 1194 ASSERT_EQ(1u, native_browser_list->size()); 1195 1196 EXPECT_FALSE(GetIsDragged(browser2)); 1197 1198 // Remaining browser window should not be maximized 1199 EXPECT_FALSE(browser2->window()->IsMaximized()); 1200} 1201 1202#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN) 1203// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1204// compositor. crbug.com/331924 1205#define MAYBE_DragDirectlyToSecondWindow DISABLED_DragDirectlyToSecondWindow 1206#else 1207#define MAYBE_DragDirectlyToSecondWindow DragDirectlyToSecondWindow 1208#endif 1209// Creates two browsers, drags from first into the second in such a way that 1210// no detaching should happen. 1211IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1212 MAYBE_DragDirectlyToSecondWindow) { 1213 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1214 1215 // Add another tab to browser(). 1216 AddTabAndResetBrowser(browser()); 1217 1218 // Create another browser. 1219 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1220 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1221 1222 // Move the tabstrip down enough so that we can detach. 1223 gfx::Rect bounds(browser2->window()->GetBounds()); 1224 bounds.Offset(0, 100); 1225 browser2->window()->SetBounds(bounds); 1226 1227 // Move to the first tab and drag it enough so that it detaches, but not 1228 // enough that it attaches to browser2. 1229 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1230 ASSERT_TRUE(PressInput(tab_0_center)); 1231 1232 gfx::Point b2_location(5, 0); 1233 views::View::ConvertPointToScreen(tab_strip2, &b2_location); 1234 ASSERT_TRUE(DragInputTo(b2_location)); 1235 1236 // Should now be attached to tab_strip2. 1237 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1238 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1239 ASSERT_TRUE(TabDragController::IsActive()); 1240 1241 // Release the mouse, stopping the drag session. 1242 ASSERT_TRUE(ReleaseInput()); 1243 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1244 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1245 ASSERT_FALSE(TabDragController::IsActive()); 1246 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1247 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1248 1249 EXPECT_FALSE(GetIsDragged(browser())); 1250 EXPECT_FALSE(GetIsDragged(browser2)); 1251 1252 // Both windows should not be maximized 1253 EXPECT_FALSE(browser()->window()->IsMaximized()); 1254 EXPECT_FALSE(browser2->window()->IsMaximized()); 1255} 1256 1257#if defined(OS_CHROMEOS) || defined(OS_LINUX) 1258// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1259// compositor. crbug.com/331924 1260#define MAYBE_DragSingleTabToSeparateWindow \ 1261 DISABLED_DragSingleTabToSeparateWindow 1262#else 1263#define MAYBE_DragSingleTabToSeparateWindow DragSingleTabToSeparateWindow 1264#endif 1265// Creates two browsers, the first browser has a single tab and drags into the 1266// second browser. 1267IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1268 MAYBE_DragSingleTabToSeparateWindow) { 1269 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1270 1271 ResetIDs(browser()->tab_strip_model(), 0); 1272 1273 // Create another browser. 1274 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1275 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1276 const gfx::Rect initial_bounds(browser2->window()->GetBounds()); 1277 1278 // Move to the first tab and drag it enough so that it detaches, but not 1279 // enough that it attaches to browser2. 1280 gfx::Point tab_0_center( 1281 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1282 ASSERT_TRUE(PressInput(tab_0_center)); 1283 ASSERT_TRUE(DragInputToNotifyWhenDone( 1284 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1285 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 1286 native_browser_list))); 1287 QuitWhenNotDragging(); 1288 1289 // Should now be attached to tab_strip2. 1290 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1291 ASSERT_TRUE(TabDragController::IsActive()); 1292 ASSERT_EQ(1u, native_browser_list->size()); 1293 1294 // Release the mouse, stopping the drag session. 1295 ASSERT_TRUE(ReleaseInput()); 1296 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1297 ASSERT_FALSE(TabDragController::IsActive()); 1298 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 1299 1300 EXPECT_FALSE(GetIsDragged(browser2)); 1301 1302 // Remaining browser window should not be maximized 1303 EXPECT_FALSE(browser2->window()->IsMaximized()); 1304 1305 // Make sure that the window is still managed and not user moved. 1306 EXPECT_TRUE(IsWindowPositionManaged(browser2->window()->GetNativeWindow())); 1307 EXPECT_FALSE(HasUserChangedWindowPositionOrSize( 1308 browser2->window()->GetNativeWindow())); 1309 // Also make sure that the drag to window position has not changed. 1310 EXPECT_EQ(initial_bounds.ToString(), 1311 browser2->window()->GetBounds().ToString()); 1312} 1313 1314namespace { 1315 1316// Invoked from the nested message loop. 1317void CancelOnNewTabWhenDraggingStep2( 1318 DetachToBrowserTabDragControllerTest* test, 1319 const BrowserList* browser_list) { 1320 ASSERT_TRUE(TabDragController::IsActive()); 1321 ASSERT_EQ(2u, browser_list->size()); 1322 1323 // Add another tab. This should trigger exiting the nested loop. 1324 test->AddBlankTabAndShow(browser_list->GetLastActive()); 1325} 1326 1327} // namespace 1328 1329#if defined(OS_CHROMEOS) || defined(OS_LINUX) 1330// TODO(sky,sad): Disabled as it fails due to resize locks with a real 1331// compositor. crbug.com/331924 1332#define MAYBE_CancelOnNewTabWhenDragging DISABLED_CancelOnNewTabWhenDragging 1333#else 1334#define MAYBE_CancelOnNewTabWhenDragging CancelOnNewTabWhenDragging 1335#endif 1336// Adds another tab, detaches into separate window, adds another tab and 1337// verifies the run loop ends. 1338IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1339 MAYBE_CancelOnNewTabWhenDragging) { 1340 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1341 1342 // Add another tab to browser(). 1343 AddTabAndResetBrowser(browser()); 1344 1345 // Move to the first tab and drag it enough so that it detaches. 1346 gfx::Point tab_0_center( 1347 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1348 ASSERT_TRUE(PressInput(tab_0_center)); 1349 ASSERT_TRUE(DragInputToNotifyWhenDone( 1350 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1351 base::Bind(&CancelOnNewTabWhenDraggingStep2, this, native_browser_list))); 1352 QuitWhenNotDragging(); 1353 1354 // Should be two windows and not dragging. 1355 ASSERT_FALSE(TabDragController::IsActive()); 1356 ASSERT_EQ(2u, native_browser_list->size()); 1357 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 1358 EXPECT_FALSE(GetIsDragged(*it)); 1359 // Should not be maximized 1360 EXPECT_FALSE(it->window()->IsMaximized()); 1361 } 1362} 1363 1364#if defined(OS_CHROMEOS) 1365// TODO(sky,sad): A number of tests below are disabled as they fail due to 1366// resize locks with a real compositor. crbug.com/331924 1367namespace { 1368 1369void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest* test, 1370 Browser* browser, 1371 TabStrip* tab_strip, 1372 const BrowserList* browser_list) { 1373 // There should be another browser. 1374 ASSERT_EQ(2u, browser_list->size()); 1375 Browser* new_browser = browser_list->get(1); 1376 EXPECT_NE(browser, new_browser); 1377 ASSERT_TRUE(new_browser->window()->IsActive()); 1378 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1379 1380 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1381 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1382 1383 // Both windows should be visible. 1384 EXPECT_TRUE(tab_strip->GetWidget()->IsVisible()); 1385 EXPECT_TRUE(tab_strip2->GetWidget()->IsVisible()); 1386 1387 // Stops dragging. 1388 ASSERT_TRUE(test->ReleaseInput()); 1389} 1390 1391} // namespace 1392 1393// Creates a browser with two tabs, maximizes it, drags the tab out. 1394IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1395 DISABLED_DragInMaximizedWindow) { 1396 AddTabAndResetBrowser(browser()); 1397 browser()->window()->Maximize(); 1398 1399 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1400 1401 // Move to the first tab and drag it enough so that it detaches. 1402 gfx::Point tab_0_center( 1403 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1404 ASSERT_TRUE(PressInput(tab_0_center)); 1405 ASSERT_TRUE(DragInputToNotifyWhenDone( 1406 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1407 base::Bind(&DragInMaximizedWindowStep2, this, browser(), tab_strip, 1408 native_browser_list))); 1409 QuitWhenNotDragging(); 1410 1411 ASSERT_FALSE(TabDragController::IsActive()); 1412 1413 // Should be two browsers. 1414 ASSERT_EQ(2u, native_browser_list->size()); 1415 Browser* new_browser = native_browser_list->get(1); 1416 ASSERT_TRUE(new_browser->window()->IsActive()); 1417 1418 EXPECT_TRUE(browser()->window()->GetNativeWindow()->IsVisible()); 1419 EXPECT_TRUE(new_browser->window()->GetNativeWindow()->IsVisible()); 1420 1421 EXPECT_FALSE(GetIsDragged(browser())); 1422 EXPECT_FALSE(GetIsDragged(new_browser)); 1423 1424 // The source window should be maximized. 1425 EXPECT_TRUE(browser()->window()->IsMaximized()); 1426 // The new window should be maximized. 1427 EXPECT_TRUE(new_browser->window()->IsMaximized()); 1428} 1429 1430// Subclass of DetachToBrowserTabDragControllerTest that 1431// creates multiple displays. 1432class DetachToBrowserInSeparateDisplayTabDragControllerTest 1433 : public DetachToBrowserTabDragControllerTest { 1434 public: 1435 DetachToBrowserInSeparateDisplayTabDragControllerTest() {} 1436 virtual ~DetachToBrowserInSeparateDisplayTabDragControllerTest() {} 1437 1438 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1439 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1440 // Make screens sufficiently wide to host 2 browsers side by side. 1441 command_line->AppendSwitchASCII("ash-host-window-bounds", 1442 "0+0-600x600,601+0-600x600"); 1443 } 1444 1445 private: 1446 DISALLOW_COPY_AND_ASSIGN( 1447 DetachToBrowserInSeparateDisplayTabDragControllerTest); 1448}; 1449 1450// Subclass of DetachToBrowserTabDragControllerTest that runs tests only with 1451// touch input. 1452class DetachToBrowserTabDragControllerTestTouch 1453 : public DetachToBrowserTabDragControllerTest { 1454 public: 1455 DetachToBrowserTabDragControllerTestTouch() {} 1456 virtual ~DetachToBrowserTabDragControllerTestTouch() {} 1457 1458 private: 1459 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTestTouch); 1460}; 1461 1462namespace { 1463 1464void DragSingleTabToSeparateWindowInSecondDisplayStep3( 1465 DetachToBrowserTabDragControllerTest* test) { 1466 ASSERT_TRUE(test->ReleaseInput()); 1467} 1468 1469void DragSingleTabToSeparateWindowInSecondDisplayStep2( 1470 DetachToBrowserTabDragControllerTest* test, 1471 const gfx::Point& target_point) { 1472 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1473 target_point.x(), target_point.y(), 1474 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3, test))); 1475} 1476 1477} // namespace 1478 1479// Drags from browser to a second display and releases input. 1480IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1481 DISABLED_DragSingleTabToSeparateWindowInSecondDisplay) { 1482 // Add another tab. 1483 AddTabAndResetBrowser(browser()); 1484 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1485 1486 // Move to the first tab and drag it enough so that it detaches. 1487 // Then drag it to the final destination on the second screen. 1488 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1489 ASSERT_TRUE(PressInput(tab_0_center)); 1490 ASSERT_TRUE(DragInputToNotifyWhenDone( 1491 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1492 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2, 1493 this, gfx::Point(600 + tab_0_center.x(), 1494 tab_0_center.y() 1495 + GetDetachY(tab_strip))))); 1496 QuitWhenNotDragging(); 1497 1498 // Should no longer be dragging. 1499 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1500 ASSERT_FALSE(TabDragController::IsActive()); 1501 1502 // There should now be another browser. 1503 ASSERT_EQ(2u, native_browser_list->size()); 1504 Browser* new_browser = native_browser_list->get(1); 1505 ASSERT_TRUE(new_browser->window()->IsActive()); 1506 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1507 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1508 1509 // This other browser should be on the second screen (with mouse drag) 1510 // With the touch input the browser cannot be dragged from one screen 1511 // to another and the window stays on the first screen. 1512 if (input_source() == INPUT_SOURCE_MOUSE) { 1513 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1514 ASSERT_EQ(2u, roots.size()); 1515 aura::Window* second_root = roots[1]; 1516 EXPECT_EQ(second_root, 1517 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1518 } 1519 1520 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 1521 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1522 1523 // Both windows should not be maximized 1524 EXPECT_FALSE(browser()->window()->IsMaximized()); 1525 EXPECT_FALSE(new_browser->window()->IsMaximized()); 1526} 1527 1528namespace { 1529 1530// Invoked from the nested message loop. 1531void DragTabToWindowInSeparateDisplayStep2( 1532 DetachToBrowserTabDragControllerTest* test, 1533 TabStrip* not_attached_tab_strip, 1534 TabStrip* target_tab_strip) { 1535 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1536 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1537 ASSERT_TRUE(TabDragController::IsActive()); 1538 1539 // Drag to target_tab_strip. This should stop the nested loop from dragging 1540 // the window. 1541 gfx::Point target_point( 1542 GetCenterInScreenCoordinates(target_tab_strip->tab_at(0))); 1543 1544 // Move it close to the beginning of the target tabstrip. 1545 target_point.set_x( 1546 target_point.x() - target_tab_strip->tab_at(0)->width() / 2 + 10); 1547 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1548} 1549 1550} // namespace 1551 1552// Drags from browser to another browser on a second display and releases input. 1553IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1554 DISABLED_DragTabToWindowInSeparateDisplay) { 1555 // Add another tab. 1556 AddTabAndResetBrowser(browser()); 1557 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1558 1559 // Create another browser. 1560 Browser* browser2 = CreateBrowser(browser()->profile()); 1561 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1562 ResetIDs(browser2->tab_strip_model(), 100); 1563 1564 // Move the second browser to the second display. 1565 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1566 ASSERT_EQ(2u, roots.size()); 1567 aura::Window* second_root = roots[1]; 1568 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1569 second_root).work_area(); 1570 browser2->window()->SetBounds(work_area); 1571 EXPECT_EQ(second_root, 1572 browser2->window()->GetNativeWindow()->GetRootWindow()); 1573 1574 // Move to the first tab and drag it enough so that it detaches, but not 1575 // enough that it attaches to browser2. 1576 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1577 ASSERT_TRUE(PressInput(tab_0_center)); 1578 ASSERT_TRUE(DragInputToNotifyWhenDone( 1579 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1580 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1581 this, tab_strip, tab_strip2))); 1582 QuitWhenNotDragging(); 1583 1584 // Should now be attached to tab_strip2. 1585 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1586 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1587 ASSERT_TRUE(TabDragController::IsActive()); 1588 1589 // Release the mouse, stopping the drag session. 1590 ASSERT_TRUE(ReleaseInput()); 1591 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1592 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1593 ASSERT_FALSE(TabDragController::IsActive()); 1594 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1595 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1596 1597 // Both windows should not be maximized 1598 EXPECT_FALSE(browser()->window()->IsMaximized()); 1599 EXPECT_FALSE(browser2->window()->IsMaximized()); 1600} 1601 1602// Drags from browser to another browser on a second display and releases input. 1603IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1604 DISABLED_DragTabToWindowOnSecondDisplay) { 1605 // Add another tab. 1606 AddTabAndResetBrowser(browser()); 1607 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1608 1609 // Create another browser. 1610 Browser* browser2 = CreateBrowser(browser()->profile()); 1611 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1612 ResetIDs(browser2->tab_strip_model(), 100); 1613 1614 // Move both browsers to the second display. 1615 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1616 ASSERT_EQ(2u, roots.size()); 1617 aura::Window* second_root = roots[1]; 1618 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1619 second_root).work_area(); 1620 browser()->window()->SetBounds(work_area); 1621 1622 // position both browser windows side by side on the second screen. 1623 gfx::Rect work_area2(work_area); 1624 work_area.set_width(work_area.width()/2); 1625 browser()->window()->SetBounds(work_area); 1626 work_area2.set_x(work_area2.x() + work_area2.width()/2); 1627 work_area2.set_width(work_area2.width()/2); 1628 browser2->window()->SetBounds(work_area2); 1629 EXPECT_EQ(second_root, 1630 browser()->window()->GetNativeWindow()->GetRootWindow()); 1631 EXPECT_EQ(second_root, 1632 browser2->window()->GetNativeWindow()->GetRootWindow()); 1633 1634 // Move to the first tab and drag it enough so that it detaches, but not 1635 // enough that it attaches to browser2. 1636 // SetEventGeneratorRootWindow sets correct (second) RootWindow 1637 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1638 SetEventGeneratorRootWindow(tab_0_center); 1639 ASSERT_TRUE(PressInput(tab_0_center)); 1640 ASSERT_TRUE(DragInputToNotifyWhenDone( 1641 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1642 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1643 this, tab_strip, tab_strip2))); 1644 QuitWhenNotDragging(); 1645 1646 // Should now be attached to tab_strip2. 1647 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1648 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1649 ASSERT_TRUE(TabDragController::IsActive()); 1650 1651 // Release the mouse, stopping the drag session. 1652 ASSERT_TRUE(ReleaseInput()); 1653 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1654 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1655 ASSERT_FALSE(TabDragController::IsActive()); 1656 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1657 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1658 1659 // Both windows should not be maximized 1660 EXPECT_FALSE(browser()->window()->IsMaximized()); 1661 EXPECT_FALSE(browser2->window()->IsMaximized()); 1662} 1663 1664// Drags from a maximized browser to another non-maximized browser on a second 1665// display and releases input. 1666IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1667 DISABLED_DragMaxTabToNonMaxWindowInSeparateDisplay) { 1668 // Add another tab. 1669 AddTabAndResetBrowser(browser()); 1670 browser()->window()->Maximize(); 1671 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1672 1673 // Create another browser on the second display. 1674 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1675 ASSERT_EQ(2u, roots.size()); 1676 aura::Window* first_root = roots[0]; 1677 aura::Window* second_root = roots[1]; 1678 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1679 second_root).work_area(); 1680 work_area.Inset(20, 20, 20, 60); 1681 Browser::CreateParams params(browser()->profile(), 1682 browser()->host_desktop_type()); 1683 params.initial_show_state = ui::SHOW_STATE_NORMAL; 1684 params.initial_bounds = work_area; 1685 Browser* browser2 = new Browser(params); 1686 AddBlankTabAndShow(browser2); 1687 1688 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1689 ResetIDs(browser2->tab_strip_model(), 100); 1690 1691 EXPECT_EQ(second_root, 1692 browser2->window()->GetNativeWindow()->GetRootWindow()); 1693 EXPECT_EQ(first_root, 1694 browser()->window()->GetNativeWindow()->GetRootWindow()); 1695 EXPECT_EQ(2, tab_strip->tab_count()); 1696 EXPECT_EQ(1, tab_strip2->tab_count()); 1697 1698 // Move to the first tab and drag it enough so that it detaches, but not 1699 // enough that it attaches to browser2. 1700 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1701 ASSERT_TRUE(PressInput(tab_0_center)); 1702 ASSERT_TRUE(DragInputToNotifyWhenDone( 1703 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1704 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1705 this, tab_strip, tab_strip2))); 1706 QuitWhenNotDragging(); 1707 1708 // Should now be attached to tab_strip2. 1709 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1710 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1711 ASSERT_TRUE(TabDragController::IsActive()); 1712 1713 // Release the mouse, stopping the drag session. 1714 ASSERT_TRUE(ReleaseInput()); 1715 1716 // tab should have moved 1717 EXPECT_EQ(1, tab_strip->tab_count()); 1718 EXPECT_EQ(2, tab_strip2->tab_count()); 1719 1720 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1721 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1722 ASSERT_FALSE(TabDragController::IsActive()); 1723 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1724 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1725 1726 // Source browser should still be maximized, target should not 1727 EXPECT_TRUE(browser()->window()->IsMaximized()); 1728 EXPECT_FALSE(browser2->window()->IsMaximized()); 1729} 1730 1731// Drags from a restored browser to an immersive fullscreen browser on a 1732// second display and releases input. 1733IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1734 DISABLED_DragTabToImmersiveBrowserOnSeparateDisplay) { 1735 // Add another tab. 1736 AddTabAndResetBrowser(browser()); 1737 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1738 1739 // Create another browser. 1740 Browser* browser2 = CreateBrowser(browser()->profile()); 1741 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1742 ResetIDs(browser2->tab_strip_model(), 100); 1743 1744 // Move the second browser to the second display. 1745 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1746 ASSERT_EQ(2u, roots.size()); 1747 aura::Window* second_root = roots[1]; 1748 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1749 second_root).work_area(); 1750 browser2->window()->SetBounds(work_area); 1751 EXPECT_EQ(second_root, 1752 browser2->window()->GetNativeWindow()->GetRootWindow()); 1753 1754 // Put the second browser into immersive fullscreen. 1755 BrowserView* browser_view2 = BrowserView::GetBrowserViewForBrowser(browser2); 1756 ImmersiveModeController* immersive_controller2 = 1757 browser_view2->immersive_mode_controller(); 1758 immersive_controller2->SetupForTest(); 1759 chrome::ToggleFullscreenMode(browser2); 1760 ASSERT_TRUE(immersive_controller2->IsEnabled()); 1761 ASSERT_FALSE(immersive_controller2->IsRevealed()); 1762 ASSERT_TRUE(tab_strip2->IsImmersiveStyle()); 1763 1764 // Move to the first tab and drag it enough so that it detaches, but not 1765 // enough that it attaches to browser2. 1766 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1767 ASSERT_TRUE(PressInput(tab_0_center)); 1768 ASSERT_TRUE(DragInputToNotifyWhenDone( 1769 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1770 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1771 this, tab_strip, tab_strip2))); 1772 QuitWhenNotDragging(); 1773 1774 // Should now be attached to tab_strip2. 1775 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1776 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1777 ASSERT_TRUE(TabDragController::IsActive()); 1778 1779 // browser2's top chrome should be revealed and the tab strip should be 1780 // at normal height while user is tragging tabs_strip2's tabs. 1781 ASSERT_TRUE(immersive_controller2->IsRevealed()); 1782 ASSERT_FALSE(tab_strip2->IsImmersiveStyle()); 1783 1784 // Release the mouse, stopping the drag session. 1785 ASSERT_TRUE(ReleaseInput()); 1786 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1787 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1788 ASSERT_FALSE(TabDragController::IsActive()); 1789 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1790 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1791 1792 // Move the mouse off of browser2's top chrome. 1793 aura::Window* primary_root = roots[0]; 1794 ASSERT_TRUE(ui_test_utils::SendMouseMoveSync( 1795 primary_root->GetBoundsInScreen().CenterPoint())); 1796 1797 // The first browser window should not be in immersive fullscreen. 1798 // browser2 should still be in immersive fullscreen, but the top chrome should 1799 // no longer be revealed. 1800 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); 1801 EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); 1802 1803 EXPECT_TRUE(immersive_controller2->IsEnabled()); 1804 EXPECT_FALSE(immersive_controller2->IsRevealed()); 1805 EXPECT_TRUE(tab_strip2->IsImmersiveStyle()); 1806} 1807 1808// Subclass of DetachToBrowserTabDragControllerTest that 1809// creates multiple displays with different device scale factors. 1810class DifferentDeviceScaleFactorDisplayTabDragControllerTest 1811 : public DetachToBrowserTabDragControllerTest { 1812 public: 1813 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {} 1814 virtual ~DifferentDeviceScaleFactorDisplayTabDragControllerTest() {} 1815 1816 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1817 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1818 command_line->AppendSwitchASCII("ash-host-window-bounds", 1819 "400x400,0+400-800x800*2"); 1820 } 1821 1822 float GetCursorDeviceScaleFactor() const { 1823 ash::test::CursorManagerTestApi cursor_test_api( 1824 ash::Shell::GetInstance()->cursor_manager()); 1825 return cursor_test_api.GetCurrentCursor().device_scale_factor(); 1826 } 1827 1828 private: 1829 DISALLOW_COPY_AND_ASSIGN( 1830 DifferentDeviceScaleFactorDisplayTabDragControllerTest); 1831}; 1832 1833namespace { 1834 1835// The points where a tab is dragged in CursorDeviceScaleFactorStep. 1836const struct DragPoint { 1837 int x; 1838 int y; 1839} kDragPoints[] = { 1840 {300, 200}, 1841 {399, 200}, 1842 {500, 200}, 1843 {400, 200}, 1844 {300, 200}, 1845}; 1846 1847// The expected device scale factors before the cursor is moved to the 1848// corresponding kDragPoints in CursorDeviceScaleFactorStep. 1849const float kDeviceScaleFactorExpectations[] = { 1850 1.0f, 1851 1.0f, 1852 2.0f, 1853 2.0f, 1854 1.0f, 1855}; 1856 1857COMPILE_ASSERT( 1858 arraysize(kDragPoints) == arraysize(kDeviceScaleFactorExpectations), 1859 kDragPoints_and_kDeviceScaleFactorExpectations_must_have_same_size); 1860 1861// Drags tab to |kDragPoints[index]|, then calls the next step function. 1862void CursorDeviceScaleFactorStep( 1863 DifferentDeviceScaleFactorDisplayTabDragControllerTest* test, 1864 TabStrip* not_attached_tab_strip, 1865 size_t index) { 1866 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1867 ASSERT_TRUE(TabDragController::IsActive()); 1868 1869 if (index < arraysize(kDragPoints)) { 1870 EXPECT_EQ(kDeviceScaleFactorExpectations[index], 1871 test->GetCursorDeviceScaleFactor()); 1872 const DragPoint p = kDragPoints[index]; 1873 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1874 p.x, p.y, base::Bind(&CursorDeviceScaleFactorStep, 1875 test, not_attached_tab_strip, index + 1))); 1876 } else { 1877 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag. 1878 EXPECT_EQ(1.0f, test->GetCursorDeviceScaleFactor()); 1879 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1880 ui_controls::LEFT, ui_controls::UP)); 1881 } 1882} 1883 1884} // namespace 1885 1886// Verifies cursor's device scale factor is updated when a tab is moved across 1887// displays with different device scale factors (http://crbug.com/154183). 1888IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest, 1889 DISABLED_CursorDeviceScaleFactor) { 1890 // Add another tab. 1891 AddTabAndResetBrowser(browser()); 1892 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1893 1894 // Move the second browser to the second display. 1895 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1896 ASSERT_EQ(2u, roots.size()); 1897 1898 // Move to the first tab and drag it enough so that it detaches. 1899 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1900 ASSERT_TRUE(PressInput(tab_0_center)); 1901 ASSERT_TRUE(DragInputToNotifyWhenDone( 1902 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1903 base::Bind(&CursorDeviceScaleFactorStep, 1904 this, tab_strip, 0))); 1905 QuitWhenNotDragging(); 1906} 1907 1908namespace { 1909 1910class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest 1911 : public TabDragControllerTest { 1912 public: 1913 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {} 1914 1915 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1916 TabDragControllerTest::SetUpCommandLine(command_line); 1917 command_line->AppendSwitchASCII("ash-host-window-bounds", 1918 "0+0-250x250,251+0-250x250"); 1919 } 1920 1921 bool Press(const gfx::Point& position) { 1922 return ui_test_utils::SendMouseMoveSync(position) && 1923 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, 1924 ui_controls::DOWN); 1925 } 1926 1927 bool DragTabAndExecuteTaskWhenDone(const gfx::Point& position, 1928 const base::Closure& task) { 1929 return ui_controls::SendMouseMoveNotifyWhenDone( 1930 position.x(), position.y(), task); 1931 } 1932 1933 void QuitWhenNotDragging() { 1934 test::QuitWhenNotDraggingImpl(); 1935 base::MessageLoop::current()->Run(); 1936 } 1937 1938 private: 1939 DISALLOW_COPY_AND_ASSIGN( 1940 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest); 1941}; 1942 1943// Invoked from the nested message loop. 1944void CancelDragTabToWindowInSeparateDisplayStep3( 1945 TabStrip* tab_strip, 1946 const BrowserList* browser_list) { 1947 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1948 ASSERT_TRUE(TabDragController::IsActive()); 1949 ASSERT_EQ(2u, browser_list->size()); 1950 1951 // Switching display mode should cancel the drag operation. 1952 ash::DisplayManager* display_manager = 1953 ash::Shell::GetInstance()->display_manager(); 1954 display_manager->AddRemoveDisplay(); 1955} 1956 1957// Invoked from the nested message loop. 1958void CancelDragTabToWindowInSeparateDisplayStep2( 1959 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest* test, 1960 TabStrip* tab_strip, 1961 aura::Window* current_root, 1962 gfx::Point final_destination, 1963 const BrowserList* browser_list) { 1964 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1965 ASSERT_TRUE(TabDragController::IsActive()); 1966 ASSERT_EQ(2u, browser_list->size()); 1967 1968 Browser* new_browser = browser_list->get(1); 1969 EXPECT_EQ(current_root, 1970 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1971 1972 ASSERT_TRUE(test->DragTabAndExecuteTaskWhenDone( 1973 final_destination, 1974 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3, 1975 tab_strip, browser_list))); 1976} 1977 1978} // namespace 1979 1980// Drags from browser to a second display and releases input. 1981IN_PROC_BROWSER_TEST_F( 1982 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 1983 DISABLED_CancelDragTabToWindowIn2ndDisplay) { 1984 // Add another tab. 1985 AddTabAndResetBrowser(browser()); 1986 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1987 1988 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1989 1990 // Move the second browser to the second display. 1991 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 1992 ASSERT_EQ(2u, roots.size()); 1993 gfx::Point final_destination = 1994 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1995 roots[1]).work_area().CenterPoint(); 1996 1997 // Move to the first tab and drag it enough so that it detaches, but not 1998 // enough to move to another display. 1999 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2000 ASSERT_TRUE(Press(tab_0_dst)); 2001 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 2002 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 2003 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 2004 this, tab_strip, roots[0], final_destination, 2005 native_browser_list))); 2006 QuitWhenNotDragging(); 2007 2008 ASSERT_EQ(1u, native_browser_list->size()); 2009 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 2010 ASSERT_FALSE(TabDragController::IsActive()); 2011 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 2012 2013 // Release the mouse 2014 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 2015 ui_controls::LEFT, ui_controls::UP)); 2016} 2017 2018// Drags from browser from a second display to primary and releases input. 2019IN_PROC_BROWSER_TEST_F( 2020 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 2021 DISABLED_CancelDragTabToWindowIn1stDisplay) { 2022 aura::Window::Windows roots = ash::Shell::GetAllRootWindows(); 2023 ASSERT_EQ(2u, roots.size()); 2024 2025 // Add another tab. 2026 AddTabAndResetBrowser(browser()); 2027 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 2028 2029 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 2030 EXPECT_EQ(roots[0], browser()->window()->GetNativeWindow()->GetRootWindow()); 2031 2032 gfx::Rect work_area = gfx::Screen::GetNativeScreen()-> 2033 GetDisplayNearestWindow(roots[1]).work_area(); 2034 browser()->window()->SetBounds(work_area); 2035 EXPECT_EQ(roots[1], browser()->window()->GetNativeWindow()->GetRootWindow()); 2036 2037 // Move the second browser to the display. 2038 gfx::Point final_destination = 2039 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 2040 roots[0]).work_area().CenterPoint(); 2041 2042 // Move to the first tab and drag it enough so that it detaches, but not 2043 // enough to move to another display. 2044 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2045 ASSERT_TRUE(Press(tab_0_dst)); 2046 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 2047 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 2048 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 2049 this, tab_strip, roots[1], final_destination, 2050 native_browser_list))); 2051 QuitWhenNotDragging(); 2052 2053 ASSERT_EQ(1u, native_browser_list->size()); 2054 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 2055 ASSERT_FALSE(TabDragController::IsActive()); 2056 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 2057 2058 // Release the mouse 2059 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 2060 ui_controls::LEFT, ui_controls::UP)); 2061} 2062 2063namespace { 2064 2065void PressSecondFingerWhileDetachedStep2( 2066 DetachToBrowserTabDragControllerTest* test) { 2067 ASSERT_TRUE(TabDragController::IsActive()); 2068 ASSERT_EQ(2u, test->native_browser_list->size()); 2069 Browser* new_browser = test->native_browser_list->get(1); 2070 ASSERT_TRUE(new_browser->window()->IsActive()); 2071 2072 ASSERT_TRUE(test->PressInput2()); 2073} 2074 2075} // namespace 2076 2077// Detaches a tab and while detached presses a second finger. 2078IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestTouch, 2079 DISABLED_PressSecondFingerWhileDetached) { 2080 gfx::Rect bounds(browser()->window()->GetBounds()); 2081 // Add another tab. 2082 AddTabAndResetBrowser(browser()); 2083 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 2084 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 2085 2086 // Move to the first tab and drag it enough so that it detaches. 2087 gfx::Point tab_0_center( 2088 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2089 ASSERT_TRUE(PressInput(tab_0_center)); 2090 ASSERT_TRUE(DragInputToDelayedNotifyWhenDone( 2091 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 2092 base::Bind(&PressSecondFingerWhileDetachedStep2, this), 2093 base::TimeDelta::FromMilliseconds(60))); 2094 QuitWhenNotDragging(); 2095 2096 // The drag should have been reverted. 2097 ASSERT_EQ(1u, native_browser_list->size()); 2098 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 2099 ASSERT_FALSE(TabDragController::IsActive()); 2100 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 2101 2102 ASSERT_TRUE(ReleaseInput()); 2103 ASSERT_TRUE(ReleaseInput2()); 2104} 2105 2106#if defined(OS_CHROMEOS) 2107 2108namespace { 2109 2110void DetachToDockedWindowNextStep( 2111 DetachToBrowserTabDragControllerTest* test, 2112 const gfx::Point& target_point, 2113 int iteration) { 2114 ASSERT_EQ(2u, test->native_browser_list->size()); 2115 Browser* new_browser = test->native_browser_list->get(1); 2116 ASSERT_TRUE(new_browser->window()->IsActive()); 2117 2118 if (!iteration) { 2119 ASSERT_TRUE(test->ReleaseInput()); 2120 return; 2121 } 2122 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 2123 target_point.x(), target_point.y(), 2124 base::Bind(&DetachToDockedWindowNextStep, 2125 test, 2126 gfx::Point(target_point.x(), 1 + target_point.y()), 2127 iteration - 1))); 2128} 2129 2130} // namespace 2131 2132// Drags from browser to separate window, docks that window and releases mouse. 2133IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 2134 DISABLED_DetachToDockedWindowFromMaximizedWindow) { 2135 // Maximize the initial browser window. 2136 browser()->window()->Maximize(); 2137 ASSERT_TRUE(browser()->window()->IsMaximized()); 2138 2139 // Add another tab. 2140 AddTabAndResetBrowser(browser()); 2141 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 2142 2143 // Move to the first tab and drag it enough so that it detaches. 2144 gfx::Point tab_0_center( 2145 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 2146 ASSERT_TRUE(PressInput(tab_0_center)); 2147 2148 // The following matches kMovesBeforeAdjust in snap_sizer.cc 2149 const int kNumIterations = 25 * 5 + 10; 2150 ASSERT_TRUE(DragInputToNotifyWhenDone( 2151 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 2152 base::Bind(&DetachToDockedWindowNextStep, this, 2153 gfx::Point(0, tab_0_center.y() + GetDetachY(tab_strip)), 2154 kNumIterations))); 2155 // Continue dragging enough times to go through snapping sequence and dock 2156 // the window. 2157 QuitWhenNotDragging(); 2158 // Should no longer be dragging. 2159 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 2160 ASSERT_FALSE(TabDragController::IsActive()); 2161 2162 // There should now be another browser. 2163 ASSERT_EQ(2u, native_browser_list->size()); 2164 Browser* new_browser = native_browser_list->get(1); 2165 ASSERT_TRUE(new_browser->window()->IsActive()); 2166 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 2167 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 2168 2169 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 2170 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 2171 2172 // The bounds of the initial window should not have changed. 2173 EXPECT_TRUE(browser()->window()->IsMaximized()); 2174 2175 EXPECT_FALSE(GetIsDragged(browser())); 2176 EXPECT_FALSE(GetIsDragged(new_browser)); 2177 // After this both windows should still be manageable. 2178 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 2179 EXPECT_TRUE(IsWindowPositionManaged( 2180 new_browser->window()->GetNativeWindow())); 2181 2182 ash::wm::WindowState* window_state = 2183 ash::wm::GetWindowState(new_browser->window()->GetNativeWindow()); 2184 // The new window should not be maximized because it gets docked or snapped. 2185 EXPECT_FALSE(new_browser->window()->IsMaximized()); 2186 // The new window should be docked and not snapped. 2187 EXPECT_TRUE(window_state->IsDocked()); 2188 EXPECT_FALSE(window_state->IsSnapped()); 2189} 2190 2191#endif // OS_CHROMEOS 2192 2193#endif 2194 2195#if defined(USE_ASH) && defined(OS_CHROMEOS) // TODO(win_ash,linux_ash) 2196INSTANTIATE_TEST_CASE_P(TabDragging, 2197 DetachToBrowserInSeparateDisplayTabDragControllerTest, 2198 ::testing::Values("mouse", "touch")); 2199INSTANTIATE_TEST_CASE_P(TabDragging, 2200 DifferentDeviceScaleFactorDisplayTabDragControllerTest, 2201 ::testing::Values("mouse")); 2202INSTANTIATE_TEST_CASE_P(TabDragging, 2203 DetachToBrowserTabDragControllerTest, 2204 ::testing::Values("mouse", "touch")); 2205INSTANTIATE_TEST_CASE_P(TabDragging, 2206 DetachToBrowserTabDragControllerTestTouch, 2207 ::testing::Values("touch")); 2208#elif defined(USE_ASH) 2209INSTANTIATE_TEST_CASE_P(TabDragging, 2210 DetachToBrowserTabDragControllerTest, 2211 ::testing::Values("mouse")); 2212#endif 2213