tab_drag_controller_interactive_uitest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 "ash/wm/property_util.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/ui/browser.h" 14#include "chrome/browser/ui/browser_iterator.h" 15#include "chrome/browser/ui/browser_list.h" 16#include "chrome/browser/ui/host_desktop.h" 17#include "chrome/browser/ui/tabs/tab_strip_model.h" 18#include "chrome/browser/ui/views/frame/browser_view.h" 19#include "chrome/browser/ui/views/tabs/tab.h" 20#include "chrome/browser/ui/views/tabs/tab_drag_controller.h" 21#include "chrome/browser/ui/views/tabs/tab_strip.h" 22#include "chrome/common/chrome_notification_types.h" 23#include "chrome/common/chrome_switches.h" 24#include "chrome/test/base/in_process_browser_test.h" 25#include "chrome/test/base/interactive_test_utils.h" 26#include "chrome/test/base/ui_controls.h" 27#include "chrome/test/base/ui_test_utils.h" 28#include "content/public/browser/notification_details.h" 29#include "content/public/browser/notification_observer.h" 30#include "content/public/browser/notification_service.h" 31#include "content/public/browser/notification_source.h" 32#include "content/public/browser/web_contents.h" 33#include "ui/gfx/screen.h" 34#include "ui/views/view.h" 35#include "ui/views/widget/widget.h" 36 37#if defined(USE_ASH) 38#include "ash/display/display_controller.h" 39#include "ash/display/display_manager.h" 40#include "ash/shell.h" 41#include "ash/test/cursor_manager_test_api.h" 42#include "ash/wm/coordinate_conversion.h" 43#include "ash/wm/window_util.h" 44#include "ui/aura/client/screen_position_client.h" 45#include "ui/aura/root_window.h" 46#include "ui/aura/test/event_generator.h" 47#endif 48 49using content::WebContents; 50 51namespace test { 52 53namespace { 54 55const char kTabDragControllerInteractiveUITestUserDataKey[] = 56 "TabDragControllerInteractiveUITestUserData"; 57 58class TabDragControllerInteractiveUITestUserData 59 : public base::SupportsUserData::Data { 60 public: 61 explicit TabDragControllerInteractiveUITestUserData(int id) : id_(id) {} 62 virtual ~TabDragControllerInteractiveUITestUserData() {} 63 int id() { return id_; } 64 65 private: 66 int id_; 67}; 68 69} // namespace 70 71class QuitDraggingObserver : public content::NotificationObserver { 72 public: 73 QuitDraggingObserver() { 74 registrar_.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, 75 content::NotificationService::AllSources()); 76 } 77 78 virtual void Observe(int type, 79 const content::NotificationSource& source, 80 const content::NotificationDetails& details) OVERRIDE { 81 DCHECK_EQ(chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, type); 82 base::MessageLoopForUI::current()->Quit(); 83 delete this; 84 } 85 86 private: 87 virtual ~QuitDraggingObserver() {} 88 89 content::NotificationRegistrar registrar_; 90 91 DISALLOW_COPY_AND_ASSIGN(QuitDraggingObserver); 92}; 93 94gfx::Point GetCenterInScreenCoordinates(const views::View* view) { 95 gfx::Point center(view->width() / 2, view->height() / 2); 96 views::View::ConvertPointToScreen(view, ¢er); 97 return center; 98} 99 100void SetID(WebContents* web_contents, int id) { 101 web_contents->SetUserData(&kTabDragControllerInteractiveUITestUserDataKey, 102 new TabDragControllerInteractiveUITestUserData(id)); 103} 104 105void ResetIDs(TabStripModel* model, int start) { 106 for (int i = 0; i < model->count(); ++i) 107 SetID(model->GetWebContentsAt(i), start + i); 108} 109 110std::string IDString(TabStripModel* model) { 111 std::string result; 112 for (int i = 0; i < model->count(); ++i) { 113 if (i != 0) 114 result += " "; 115 WebContents* contents = model->GetWebContentsAt(i); 116 TabDragControllerInteractiveUITestUserData* user_data = 117 static_cast<TabDragControllerInteractiveUITestUserData*>( 118 contents->GetUserData( 119 &kTabDragControllerInteractiveUITestUserDataKey)); 120 if (user_data) 121 result += base::IntToString(user_data->id()); 122 else 123 result += "?"; 124 } 125 return result; 126} 127 128// Creates a listener that quits the message loop when no longer dragging. 129void QuitWhenNotDraggingImpl() { 130 new QuitDraggingObserver(); // QuitDraggingObserver deletes itself. 131} 132 133TabStrip* GetTabStripForBrowser(Browser* browser) { 134 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 135 return static_cast<TabStrip*>(browser_view->tabstrip()); 136} 137 138} // namespace test 139 140using test::GetCenterInScreenCoordinates; 141using test::SetID; 142using test::ResetIDs; 143using test::IDString; 144using test::GetTabStripForBrowser; 145 146TabDragControllerTest::TabDragControllerTest() 147 : native_browser_list(BrowserList::GetInstance( 148 chrome::HOST_DESKTOP_TYPE_NATIVE)) { 149} 150 151TabDragControllerTest::~TabDragControllerTest() { 152} 153 154void TabDragControllerTest::StopAnimating(TabStrip* tab_strip) { 155 tab_strip->StopAnimating(true); 156} 157 158void TabDragControllerTest::AddTabAndResetBrowser(Browser* browser) { 159 AddBlankTabAndShow(browser); 160 StopAnimating(GetTabStripForBrowser(browser)); 161 ResetIDs(browser->tab_strip_model(), 0); 162} 163 164Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() { 165 // Create another browser. 166 Browser* browser2 = CreateBrowser(browser()->profile()); 167 ResetIDs(browser2->tab_strip_model(), 100); 168 169 // Resize the two windows so they're right next to each other. 170 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 171 browser()->window()->GetNativeWindow()).work_area(); 172 gfx::Size half_size = 173 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10); 174 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size)); 175 browser2->window()->SetBounds(gfx::Rect( 176 work_area.x() + half_size.width(), work_area.y(), 177 half_size.width(), half_size.height())); 178 return browser2; 179} 180 181namespace { 182 183enum InputSource { 184 INPUT_SOURCE_MOUSE = 0, 185 INPUT_SOURCE_TOUCH = 1 186}; 187 188int GetDetachY(TabStrip* tab_strip) { 189 return std::max(TabDragController::kTouchVerticalDetachMagnetism, 190 TabDragController::kVerticalDetachMagnetism) + 191 tab_strip->height() + 1; 192} 193 194bool GetTrackedByWorkspace(Browser* browser) { 195#if !defined(USE_ASH) || defined(OS_WIN) // TODO(win_ash) 196 return true; 197#else 198 return ash::GetTrackedByWorkspace(browser->window()->GetNativeWindow()); 199#endif 200} 201 202} // namespace 203 204#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 205class ScreenEventGeneratorDelegate : public aura::test::EventGeneratorDelegate { 206 public: 207 explicit ScreenEventGeneratorDelegate(aura::RootWindow* root_window) 208 : root_window_(root_window) {} 209 virtual ~ScreenEventGeneratorDelegate() {} 210 211 // EventGeneratorDelegate overrides: 212 virtual aura::RootWindow* GetRootWindowAt( 213 const gfx::Point& point) const OVERRIDE { 214 return root_window_; 215 } 216 217 virtual aura::client::ScreenPositionClient* GetScreenPositionClient( 218 const aura::Window* window) const OVERRIDE { 219 return aura::client::GetScreenPositionClient(root_window_); 220 } 221 222 private: 223 aura::RootWindow* root_window_; 224 225 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate); 226}; 227 228#endif 229 230class DetachToBrowserTabDragControllerTest 231 : public TabDragControllerTest, 232 public ::testing::WithParamInterface<const char*> { 233 public: 234 DetachToBrowserTabDragControllerTest() {} 235 236 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 237 command_line->AppendSwitch(switches::kTabBrowserDragging); 238 } 239 240 virtual void SetUpOnMainThread() OVERRIDE { 241#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 242 event_generator_.reset(new aura::test::EventGenerator( 243 ash::Shell::GetPrimaryRootWindow())); 244#endif 245 } 246 247 InputSource input_source() const { 248 return !strcmp(GetParam(), "mouse") ? 249 INPUT_SOURCE_MOUSE : INPUT_SOURCE_TOUCH; 250 } 251 252 // Set root window from a point in screen coordinates 253 void SetEventGeneratorRootWindow(const gfx::Point& point) { 254 if (input_source() == INPUT_SOURCE_MOUSE) 255 return; 256#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 257 event_generator_.reset(new aura::test::EventGenerator( 258 new ScreenEventGeneratorDelegate(ash::wm::GetRootWindowAt(point)))); 259#endif 260 } 261 262 // The following methods update one of the mouse or touch input depending upon 263 // the InputSource. 264 bool PressInput(const gfx::Point& location) { 265 if (input_source() == INPUT_SOURCE_MOUSE) { 266 return ui_test_utils::SendMouseMoveSync(location) && 267 ui_test_utils::SendMouseEventsSync( 268 ui_controls::LEFT, ui_controls::DOWN); 269 } 270#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 271 event_generator_->set_current_location(location); 272 event_generator_->PressTouch(); 273#else 274 NOTREACHED(); 275#endif 276 return true; 277 } 278 279 bool DragInputTo(const gfx::Point& location) { 280 if (input_source() == INPUT_SOURCE_MOUSE) 281 return ui_test_utils::SendMouseMoveSync(location); 282#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 283 event_generator_->MoveTouch(location); 284#else 285 NOTREACHED(); 286#endif 287 return true; 288 } 289 290 bool DragInputToAsync(const gfx::Point& location) { 291 if (input_source() == INPUT_SOURCE_MOUSE) 292 return ui_controls::SendMouseMove(location.x(), location.y()); 293#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 294 event_generator_->MoveTouch(location); 295#else 296 NOTREACHED(); 297#endif 298 return true; 299 } 300 301 bool DragInputToNotifyWhenDone(int x, 302 int y, 303 const base::Closure& task) { 304 if (input_source() == INPUT_SOURCE_MOUSE) 305 return ui_controls::SendMouseMoveNotifyWhenDone(x, y, task); 306#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 307 base::MessageLoop::current()->PostTask(FROM_HERE, task); 308 event_generator_->MoveTouch(gfx::Point(x, y)); 309#else 310 NOTREACHED(); 311#endif 312 return true; 313 } 314 315 bool ReleaseInput() { 316 if (input_source() == INPUT_SOURCE_MOUSE) { 317 return ui_test_utils::SendMouseEventsSync( 318 ui_controls::LEFT, ui_controls::UP); 319 } 320#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 321 event_generator_->ReleaseTouch(); 322#else 323 NOTREACHED(); 324#endif 325 return true; 326 } 327 328 bool ReleaseMouseAsync() { 329 return input_source() == INPUT_SOURCE_MOUSE && 330 ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP); 331 } 332 333 void QuitWhenNotDragging() { 334 if (input_source() == INPUT_SOURCE_MOUSE) { 335 // Schedule observer to quit message loop when done dragging. This has to 336 // be async so the message loop can run. 337 test::QuitWhenNotDraggingImpl(); 338 base::MessageLoop::current()->Run(); 339 } else { 340 // Touch events are sync, so we know we're not in a drag session. But some 341 // tests rely on the browser fully closing, which is async. So, run all 342 // pending tasks. 343 base::RunLoop run_loop; 344 run_loop.RunUntilIdle(); 345 } 346 } 347 348 void AddBlankTabAndShow(Browser* browser) { 349 InProcessBrowserTest::AddBlankTabAndShow(browser); 350 } 351 352 Browser* browser() const { return InProcessBrowserTest::browser(); } 353 354 private: 355#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 356 scoped_ptr<aura::test::EventGenerator> event_generator_; 357#endif 358 359 DISALLOW_COPY_AND_ASSIGN(DetachToBrowserTabDragControllerTest); 360}; 361 362// Creates a browser with two tabs, drags the second to the first. 363// TODO(sky): this won't work with touch as it requires a long press. 364IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 365 DISABLED_DragInSameWindow) { 366 AddTabAndResetBrowser(browser()); 367 368 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 369 TabStripModel* model = browser()->tab_strip_model(); 370 371 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1))); 372 ASSERT_TRUE(PressInput(tab_1_center)); 373 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 374 ASSERT_TRUE(DragInputTo(tab_0_center)); 375 ASSERT_TRUE(ReleaseInput()); 376 EXPECT_EQ("1 0", IDString(model)); 377 EXPECT_FALSE(TabDragController::IsActive()); 378 EXPECT_FALSE(tab_strip->IsDragSessionActive()); 379} 380 381namespace { 382 383// Invoked from the nested message loop. 384void DragToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 385 TabStrip* not_attached_tab_strip, 386 TabStrip* target_tab_strip) { 387 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 388 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 389 ASSERT_TRUE(TabDragController::IsActive()); 390 391 // Drag to target_tab_strip. This should stop the nested loop from dragging 392 // the window. 393 gfx::Point target_point(target_tab_strip->width() -1, 394 target_tab_strip->height() / 2); 395 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 396 ASSERT_TRUE(test->DragInputToAsync(target_point)); 397} 398 399} // namespace 400 401// Creates two browsers, drags from first into second. 402IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 403 DragToSeparateWindow) { 404 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 405 406 // Add another tab to browser(). 407 AddTabAndResetBrowser(browser()); 408 409 // Create another browser. 410 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 411 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 412 413 // Move to the first tab and drag it enough so that it detaches, but not 414 // enough that it attaches to browser2. 415 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 416 ASSERT_TRUE(PressInput(tab_0_center)); 417 ASSERT_TRUE(DragInputToNotifyWhenDone( 418 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 419 base::Bind(&DragToSeparateWindowStep2, 420 this, tab_strip, tab_strip2))); 421 QuitWhenNotDragging(); 422 423 // Should now be attached to tab_strip2. 424 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 425 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 426 ASSERT_TRUE(TabDragController::IsActive()); 427 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 428 429 // Release the mouse, stopping the drag session. 430 ASSERT_TRUE(ReleaseInput()); 431 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 432 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 433 ASSERT_FALSE(TabDragController::IsActive()); 434 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 435 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 436 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 437 438 // Both windows should not be maximized 439 EXPECT_FALSE(browser()->window()->IsMaximized()); 440 EXPECT_FALSE(browser2->window()->IsMaximized()); 441} 442 443namespace { 444 445void DetachToOwnWindowStep2(DetachToBrowserTabDragControllerTest* test) { 446 if (test->input_source() == INPUT_SOURCE_TOUCH) 447 ASSERT_TRUE(test->ReleaseInput()); 448} 449 450#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 451bool IsWindowPositionManaged(aura::Window* window) { 452 return ash::wm::IsWindowPositionManaged(window); 453} 454bool HasUserChangedWindowPositionOrSize(aura::Window* window) { 455 return ash::wm::HasUserChangedWindowPositionOrSize(window); 456} 457#else 458bool IsWindowPositionManaged(gfx::NativeWindow window) { 459 return true; 460} 461bool HasUserChangedWindowPositionOrSize(gfx::NativeWindow window) { 462 return false; 463} 464#endif 465 466} // namespace 467 468// Drags from browser to separate window and releases mouse. 469IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 470 DetachToOwnWindow) { 471 const gfx::Rect initial_bounds(browser()->window()->GetBounds()); 472 // Add another tab. 473 AddTabAndResetBrowser(browser()); 474 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 475 476 // Move to the first tab and drag it enough so that it detaches. 477 gfx::Point tab_0_center( 478 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 479 ASSERT_TRUE(PressInput(tab_0_center)); 480 ASSERT_TRUE(DragInputToNotifyWhenDone( 481 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 482 base::Bind(&DetachToOwnWindowStep2, this))); 483 if (input_source() == INPUT_SOURCE_MOUSE) { 484 ASSERT_TRUE(ReleaseMouseAsync()); 485 QuitWhenNotDragging(); 486 } 487 488 // Should no longer be dragging. 489 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 490 ASSERT_FALSE(TabDragController::IsActive()); 491 492 // There should now be another browser. 493 ASSERT_EQ(2u, native_browser_list->size()); 494 Browser* new_browser = native_browser_list->get(1); 495 ASSERT_TRUE(new_browser->window()->IsActive()); 496 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 497 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 498 499 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 500 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 501 502 // The bounds of the initial window should not have changed. 503 EXPECT_EQ(initial_bounds.ToString(), 504 browser()->window()->GetBounds().ToString()); 505 506 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 507 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 508 // After this both windows should still be managable. 509 EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); 510 EXPECT_TRUE(IsWindowPositionManaged( 511 new_browser->window()->GetNativeWindow())); 512 513 // Both windows should not be maximized 514 EXPECT_FALSE(browser()->window()->IsMaximized()); 515 EXPECT_FALSE(new_browser->window()->IsMaximized()); 516} 517 518// Deletes a tab being dragged before the user moved enough to start a drag. 519IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 520 DeleteBeforeStartedDragging) { 521 // Add another tab. 522 AddTabAndResetBrowser(browser()); 523 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 524 525 // Click on the first tab, but don't move it. 526 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 527 ASSERT_TRUE(PressInput(tab_0_center)); 528 529 // Should be dragging. 530 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 531 ASSERT_TRUE(TabDragController::IsActive()); 532 533 // Delete the tab being dragged. 534 delete browser()->tab_strip_model()->GetWebContentsAt(0); 535 536 // Should have canceled dragging. 537 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 538 ASSERT_FALSE(TabDragController::IsActive()); 539 540 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 541 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 542} 543 544// Deletes a tab being dragged while still attached. 545IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 546 DeleteTabWhileAttached) { 547 // Add another tab. 548 AddTabAndResetBrowser(browser()); 549 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 550 551 // Click on the first tab and move it enough so that it starts dragging but is 552 // still attached. 553 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 554 ASSERT_TRUE(PressInput(tab_0_center)); 555 ASSERT_TRUE(DragInputTo( 556 gfx::Point(tab_0_center.x() + 20, tab_0_center.y()))); 557 558 // Should be dragging. 559 ASSERT_TRUE(tab_strip->IsDragSessionActive()); 560 ASSERT_TRUE(TabDragController::IsActive()); 561 562 // Delete the tab being dragged. 563 delete browser()->tab_strip_model()->GetWebContentsAt(0); 564 565 // Should have canceled dragging. 566 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 567 ASSERT_FALSE(TabDragController::IsActive()); 568 569 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 570 571 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 572} 573 574namespace { 575 576void DeleteWhileDetachedStep2(WebContents* tab) { 577 delete tab; 578} 579 580} // namespace 581 582// Deletes a tab being dragged after dragging a tab so that a new window is 583// created. 584IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 585 DeleteTabWhileDetached) { 586 // Add another tab. 587 AddTabAndResetBrowser(browser()); 588 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 589 590 // Move to the first tab and drag it enough so that it detaches. 591 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 592 WebContents* to_delete = 593 browser()->tab_strip_model()->GetWebContentsAt(0); 594 ASSERT_TRUE(PressInput(tab_0_center)); 595 ASSERT_TRUE(DragInputToNotifyWhenDone( 596 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 597 base::Bind(&DeleteWhileDetachedStep2, to_delete))); 598 QuitWhenNotDragging(); 599 600 // Should not be dragging. 601 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 602 ASSERT_FALSE(TabDragController::IsActive()); 603 604 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 605 606 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 607} 608 609namespace { 610 611void DeleteSourceDetachedStep2(WebContents* tab, 612 const BrowserList* browser_list) { 613 ASSERT_EQ(2u, browser_list->size()); 614 Browser* new_browser = browser_list->get(1); 615 // This ends up closing the source window. 616 delete tab; 617 // Cancel the drag. 618 ui_controls::SendKeyPress(new_browser->window()->GetNativeWindow(), 619 ui::VKEY_ESCAPE, false, false, false, false); 620} 621 622} // namespace 623 624// Detaches a tab and while detached deletes a tab from the source so that the 625// source window closes then presses escape to cancel the drag. 626IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 627 DeleteSourceDetached) { 628 // Add another tab. 629 AddTabAndResetBrowser(browser()); 630 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 631 632 // Move to the first tab and drag it enough so that it detaches. 633 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 634 WebContents* to_delete = browser()->tab_strip_model()->GetWebContentsAt(1); 635 ASSERT_TRUE(PressInput(tab_0_center)); 636 ASSERT_TRUE(DragInputToNotifyWhenDone( 637 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 638 base::Bind(&DeleteSourceDetachedStep2, to_delete, native_browser_list))); 639 QuitWhenNotDragging(); 640 641 // Should not be dragging. 642 ASSERT_EQ(1u, native_browser_list->size()); 643 Browser* new_browser = native_browser_list->get(0); 644 ASSERT_FALSE(GetTabStripForBrowser(new_browser)->IsDragSessionActive()); 645 ASSERT_FALSE(TabDragController::IsActive()); 646 647 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 648 649 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 650 651 // Remaining browser window should not be maximized 652 EXPECT_FALSE(new_browser->window()->IsMaximized()); 653} 654 655namespace { 656 657void PressEscapeWhileDetachedStep2(const BrowserList* browser_list) { 658 ASSERT_EQ(2u, browser_list->size()); 659 Browser* new_browser = browser_list->get(1); 660 ui_controls::SendKeyPress( 661 new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, 662 false, false); 663} 664 665} // namespace 666 667// This is disabled until NativeViewHost::Detach really detaches. 668// Detaches a tab and while detached presses escape to revert the drag. 669IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 670 PressEscapeWhileDetached) { 671 // Add another tab. 672 AddTabAndResetBrowser(browser()); 673 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 674 675 // Move to the first tab and drag it enough so that it detaches. 676 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 677 ASSERT_TRUE(PressInput(tab_0_center)); 678 ASSERT_TRUE(DragInputToNotifyWhenDone( 679 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 680 base::Bind(&PressEscapeWhileDetachedStep2, native_browser_list))); 681 QuitWhenNotDragging(); 682 683 // Should not be dragging. 684 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 685 ASSERT_FALSE(TabDragController::IsActive()); 686 687 // And there should only be one window. 688 EXPECT_EQ(1u, native_browser_list->size()); 689 690 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 691 692 // Remaining browser window should not be maximized 693 EXPECT_FALSE(browser()->window()->IsMaximized()); 694} 695 696namespace { 697 698void DragAllStep2(DetachToBrowserTabDragControllerTest* test, 699 const BrowserList* browser_list) { 700 // Should only be one window. 701 ASSERT_EQ(1u, browser_list->size()); 702 if (test->input_source() == INPUT_SOURCE_TOUCH) { 703 ASSERT_TRUE(test->ReleaseInput()); 704 } else { 705 ASSERT_TRUE(test->ReleaseMouseAsync()); 706 } 707} 708 709} // namespace 710 711// Selects multiple tabs and starts dragging the window. 712IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DragAll) { 713 // Add another tab. 714 AddTabAndResetBrowser(browser()); 715 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 716 browser()->tab_strip_model()->AddTabAtToSelection(0); 717 browser()->tab_strip_model()->AddTabAtToSelection(1); 718 719 // Move to the first tab and drag it enough so that it would normally 720 // detach. 721 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 722 ASSERT_TRUE(PressInput(tab_0_center)); 723 ASSERT_TRUE(DragInputToNotifyWhenDone( 724 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 725 base::Bind(&DragAllStep2, this, native_browser_list))); 726 QuitWhenNotDragging(); 727 728 // Should not be dragging. 729 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 730 ASSERT_FALSE(TabDragController::IsActive()); 731 732 // And there should only be one window. 733 EXPECT_EQ(1u, native_browser_list->size()); 734 735 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 736 737 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 738 739 // Remaining browser window should not be maximized 740 EXPECT_FALSE(browser()->window()->IsMaximized()); 741} 742 743namespace { 744 745// Invoked from the nested message loop. 746void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 747 TabStrip* attached_tab_strip, 748 TabStrip* target_tab_strip, 749 const BrowserList* browser_list) { 750 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 751 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 752 ASSERT_TRUE(TabDragController::IsActive()); 753 ASSERT_EQ(2u, browser_list->size()); 754 755 // Drag to target_tab_strip. This should stop the nested loop from dragging 756 // the window. 757 gfx::Point target_point(target_tab_strip->width() - 1, 758 target_tab_strip->height() / 2); 759 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 760 ASSERT_TRUE(test->DragInputToAsync(target_point)); 761} 762 763} // namespace 764 765// Creates two browsers, selects all tabs in first and drags into second. 766IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 767 DragAllToSeparateWindow) { 768 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 769 770 // Add another tab to browser(). 771 AddTabAndResetBrowser(browser()); 772 773 // Create another browser. 774 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 775 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 776 777 browser()->tab_strip_model()->AddTabAtToSelection(0); 778 browser()->tab_strip_model()->AddTabAtToSelection(1); 779 780 // Move to the first tab and drag it enough so that it detaches, but not 781 // enough that it attaches to browser2. 782 gfx::Point tab_0_center( 783 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 784 ASSERT_TRUE(PressInput(tab_0_center)); 785 ASSERT_TRUE(DragInputToNotifyWhenDone( 786 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 787 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 788 native_browser_list))); 789 QuitWhenNotDragging(); 790 791 // Should now be attached to tab_strip2. 792 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 793 ASSERT_TRUE(TabDragController::IsActive()); 794 ASSERT_EQ(1u, native_browser_list->size()); 795 796 // Release the mouse, stopping the drag session. 797 ASSERT_TRUE(ReleaseInput()); 798 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 799 ASSERT_FALSE(TabDragController::IsActive()); 800 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 801 802 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 803 804 // Remaining browser window should not be maximized 805 EXPECT_FALSE(browser2->window()->IsMaximized()); 806} 807 808namespace { 809 810// Invoked from the nested message loop. 811void DragAllToSeparateWindowAndCancelStep2( 812 DetachToBrowserTabDragControllerTest* test, 813 TabStrip* attached_tab_strip, 814 TabStrip* target_tab_strip, 815 const BrowserList* browser_list) { 816 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 817 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 818 ASSERT_TRUE(TabDragController::IsActive()); 819 ASSERT_EQ(2u, browser_list->size()); 820 821 // Drag to target_tab_strip. This should stop the nested loop from dragging 822 // the window. 823 gfx::Point target_point(target_tab_strip->width() - 1, 824 target_tab_strip->height() / 2); 825 views::View::ConvertPointToScreen(target_tab_strip, &target_point); 826 ASSERT_TRUE(test->DragInputToAsync(target_point)); 827} 828 829} // namespace 830 831// Creates two browsers, selects all tabs in first, drags into second, then hits 832// escape. 833IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 834 DragAllToSeparateWindowAndCancel) { 835 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 836 837 // Add another tab to browser(). 838 AddTabAndResetBrowser(browser()); 839 840 // Create another browser. 841 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 842 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 843 844 browser()->tab_strip_model()->AddTabAtToSelection(0); 845 browser()->tab_strip_model()->AddTabAtToSelection(1); 846 847 // Move to the first tab and drag it enough so that it detaches, but not 848 // enough that it attaches to browser2. 849 gfx::Point tab_0_center( 850 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 851 ASSERT_TRUE(PressInput(tab_0_center)); 852 ASSERT_TRUE(DragInputToNotifyWhenDone( 853 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 854 base::Bind(&DragAllToSeparateWindowAndCancelStep2, this, 855 tab_strip, tab_strip2, native_browser_list))); 856 QuitWhenNotDragging(); 857 858 // Should now be attached to tab_strip2. 859 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 860 ASSERT_TRUE(TabDragController::IsActive()); 861 ASSERT_EQ(1u, native_browser_list->size()); 862 863 // Cancel the drag. 864 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 865 browser2, ui::VKEY_ESCAPE, false, false, false, false)); 866 867 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 868 ASSERT_FALSE(TabDragController::IsActive()); 869 EXPECT_EQ("100 0 1", IDString(browser2->tab_strip_model())); 870 871 // browser() will have been destroyed, but browser2 should remain. 872 ASSERT_EQ(1u, native_browser_list->size()); 873 874 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 875 876 // Remaining browser window should not be maximized 877 EXPECT_FALSE(browser2->window()->IsMaximized()); 878} 879 880// Creates two browsers, drags from first into the second in such a way that 881// no detaching should happen. 882IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 883 DragDirectlyToSecondWindow) { 884 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 885 886 // Add another tab to browser(). 887 AddTabAndResetBrowser(browser()); 888 889 // Create another browser. 890 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 891 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 892 893 // Move the tabstrip down enough so that we can detach. 894 gfx::Rect bounds(browser2->window()->GetBounds()); 895 bounds.Offset(0, 100); 896 browser2->window()->SetBounds(bounds); 897 898 // Move to the first tab and drag it enough so that it detaches, but not 899 // enough that it attaches to browser2. 900 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 901 ASSERT_TRUE(PressInput(tab_0_center)); 902 903 gfx::Point b2_location(5, 0); 904 views::View::ConvertPointToScreen(tab_strip2, &b2_location); 905 ASSERT_TRUE(DragInputTo(b2_location)); 906 907 // Should now be attached to tab_strip2. 908 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 909 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 910 ASSERT_TRUE(TabDragController::IsActive()); 911 912 // Release the mouse, stopping the drag session. 913 ASSERT_TRUE(ReleaseInput()); 914 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 915 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 916 ASSERT_FALSE(TabDragController::IsActive()); 917 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 918 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 919 920 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 921 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 922 923 // Both windows should not be maximized 924 EXPECT_FALSE(browser()->window()->IsMaximized()); 925 EXPECT_FALSE(browser2->window()->IsMaximized()); 926} 927 928// Creates two browsers, the first browser has a single tab and drags into the 929// second browser. 930IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 931 DragSingleTabToSeparateWindow) { 932 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 933 934 ResetIDs(browser()->tab_strip_model(), 0); 935 936 // Create another browser. 937 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 938 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 939 const gfx::Rect initial_bounds(browser2->window()->GetBounds()); 940 941 // Move to the first tab and drag it enough so that it detaches, but not 942 // enough that it attaches to browser2. 943 gfx::Point tab_0_center( 944 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 945 ASSERT_TRUE(PressInput(tab_0_center)); 946 ASSERT_TRUE(DragInputToNotifyWhenDone( 947 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 948 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 949 native_browser_list))); 950 QuitWhenNotDragging(); 951 952 // Should now be attached to tab_strip2. 953 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 954 ASSERT_TRUE(TabDragController::IsActive()); 955 ASSERT_EQ(1u, native_browser_list->size()); 956 957 // Release the mouse, stopping the drag session. 958 ASSERT_TRUE(ReleaseInput()); 959 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 960 ASSERT_FALSE(TabDragController::IsActive()); 961 EXPECT_EQ("100 0", IDString(browser2->tab_strip_model())); 962 963 EXPECT_TRUE(GetTrackedByWorkspace(browser2)); 964 965 // Remaining browser window should not be maximized 966 EXPECT_FALSE(browser2->window()->IsMaximized()); 967 968 // Make sure that the window is still managed and not user moved. 969 EXPECT_TRUE(IsWindowPositionManaged(browser2->window()->GetNativeWindow())); 970 EXPECT_FALSE(HasUserChangedWindowPositionOrSize( 971 browser2->window()->GetNativeWindow())); 972 // Also make sure that the drag to window position has not changed. 973 EXPECT_EQ(initial_bounds.ToString(), 974 browser2->window()->GetBounds().ToString()); 975} 976 977namespace { 978 979// Invoked from the nested message loop. 980void CancelOnNewTabWhenDraggingStep2( 981 DetachToBrowserTabDragControllerTest* test, 982 const BrowserList* browser_list) { 983 ASSERT_TRUE(TabDragController::IsActive()); 984 ASSERT_EQ(2u, browser_list->size()); 985 986 // Add another tab. This should trigger exiting the nested loop. 987 test->AddBlankTabAndShow(browser_list->GetLastActive()); 988} 989 990} // namespace 991 992// Adds another tab, detaches into separate window, adds another tab and 993// verifies the run loop ends. 994IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 995 CancelOnNewTabWhenDragging) { 996 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 997 998 // Add another tab to browser(). 999 AddTabAndResetBrowser(browser()); 1000 1001 // Move to the first tab and drag it enough so that it detaches. 1002 gfx::Point tab_0_center( 1003 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1004 ASSERT_TRUE(PressInput(tab_0_center)); 1005 ASSERT_TRUE(DragInputToNotifyWhenDone( 1006 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1007 base::Bind(&CancelOnNewTabWhenDraggingStep2, this, native_browser_list))); 1008 QuitWhenNotDragging(); 1009 1010 // Should be two windows and not dragging. 1011 ASSERT_FALSE(TabDragController::IsActive()); 1012 ASSERT_EQ(2u, native_browser_list->size()); 1013 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 1014 EXPECT_TRUE(GetTrackedByWorkspace(*it)); 1015 // Should not be maximized 1016 EXPECT_FALSE(it->window()->IsMaximized()); 1017 } 1018} 1019 1020#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 1021 1022namespace { 1023 1024void DragInMaximizedWindowStep2(DetachToBrowserTabDragControllerTest* test, 1025 Browser* browser, 1026 TabStrip* tab_strip, 1027 const BrowserList* browser_list) { 1028 // There should be another browser. 1029 ASSERT_EQ(2u, browser_list->size()); 1030 Browser* new_browser = browser_list->get(1); 1031 EXPECT_NE(browser, new_browser); 1032 ASSERT_TRUE(new_browser->window()->IsActive()); 1033 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1034 1035 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1036 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1037 1038 // Both windows should be visible. 1039 EXPECT_TRUE(tab_strip->GetWidget()->IsVisible()); 1040 EXPECT_TRUE(tab_strip2->GetWidget()->IsVisible()); 1041 1042 // Stops dragging. 1043 ASSERT_TRUE(test->ReleaseInput()); 1044} 1045 1046} // namespace 1047 1048// Creates a browser with two tabs, maximizes it, drags the tab out. 1049IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 1050 DragInMaximizedWindow) { 1051 AddTabAndResetBrowser(browser()); 1052 browser()->window()->Maximize(); 1053 1054 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1055 1056 // Move to the first tab and drag it enough so that it detaches. 1057 gfx::Point tab_0_center( 1058 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1059 ASSERT_TRUE(PressInput(tab_0_center)); 1060 ASSERT_TRUE(DragInputToNotifyWhenDone( 1061 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1062 base::Bind(&DragInMaximizedWindowStep2, this, browser(), tab_strip, 1063 native_browser_list))); 1064 QuitWhenNotDragging(); 1065 1066 ASSERT_FALSE(TabDragController::IsActive()); 1067 1068 // Should be two browsers. 1069 ASSERT_EQ(2u, native_browser_list->size()); 1070 Browser* new_browser = native_browser_list->get(1); 1071 ASSERT_TRUE(new_browser->window()->IsActive()); 1072 1073 // Only the new browser should be visible. 1074 EXPECT_FALSE(browser()->window()->GetNativeWindow()->IsVisible()); 1075 EXPECT_TRUE(new_browser->window()->GetNativeWindow()->IsVisible()); 1076 1077 EXPECT_TRUE(GetTrackedByWorkspace(browser())); 1078 EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); 1079 1080 // Both windows should be maximized 1081 EXPECT_TRUE(browser()->window()->IsMaximized()); 1082 EXPECT_TRUE(new_browser->window()->IsMaximized()); 1083} 1084 1085// Subclass of DetachToBrowserInSeparateDisplayTabDragControllerTest that 1086// creates multiple displays. 1087class DetachToBrowserInSeparateDisplayTabDragControllerTest 1088 : public DetachToBrowserTabDragControllerTest { 1089 public: 1090 DetachToBrowserInSeparateDisplayTabDragControllerTest() {} 1091 1092 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1093 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1094 // Make screens sufficiently wide to host 2 browsers side by side. 1095 command_line->AppendSwitchASCII("ash-host-window-bounds", 1096 "0+0-600x600,601+0-600x600"); 1097 } 1098 1099 private: 1100 DISALLOW_COPY_AND_ASSIGN( 1101 DetachToBrowserInSeparateDisplayTabDragControllerTest); 1102}; 1103 1104namespace { 1105 1106void DragSingleTabToSeparateWindowInSecondDisplayStep3( 1107 DetachToBrowserTabDragControllerTest* test) { 1108 ASSERT_TRUE(test->ReleaseInput()); 1109} 1110 1111void DragSingleTabToSeparateWindowInSecondDisplayStep2( 1112 DetachToBrowserTabDragControllerTest* test, 1113 const gfx::Point& target_point) { 1114 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1115 target_point.x(), target_point.y(), 1116 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep3, test))); 1117} 1118 1119} // namespace 1120 1121// Drags from browser to a second display and releases input. 1122IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1123 DragSingleTabToSeparateWindowInSecondDisplay) { 1124 // Add another tab. 1125 AddTabAndResetBrowser(browser()); 1126 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1127 1128 // Move to the first tab and drag it enough so that it detaches. 1129 // Then drag it to the final destination on the second screen. 1130 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1131 ASSERT_TRUE(PressInput(tab_0_center)); 1132 ASSERT_TRUE(DragInputToNotifyWhenDone( 1133 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1134 base::Bind(&DragSingleTabToSeparateWindowInSecondDisplayStep2, 1135 this, gfx::Point(600 + tab_0_center.x(), 1136 tab_0_center.y() 1137 + GetDetachY(tab_strip))))); 1138 QuitWhenNotDragging(); 1139 1140 // Should no longer be dragging. 1141 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1142 ASSERT_FALSE(TabDragController::IsActive()); 1143 1144 // There should now be another browser. 1145 ASSERT_EQ(2u, native_browser_list->size()); 1146 Browser* new_browser = native_browser_list->get(1); 1147 ASSERT_TRUE(new_browser->window()->IsActive()); 1148 TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); 1149 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1150 1151 // This other browser should be on the second screen (with mouse drag) 1152 // With the touch input the browser cannot be dragged from one screen 1153 // to another and the window stays on the first screen. 1154 if (input_source() == INPUT_SOURCE_MOUSE) { 1155 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1156 ASSERT_EQ(2u, roots.size()); 1157 aura::RootWindow* second_root = roots[1]; 1158 EXPECT_EQ(second_root, 1159 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1160 } 1161 1162 EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); 1163 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1164 1165 // Both windows should not be maximized 1166 EXPECT_FALSE(browser()->window()->IsMaximized()); 1167 EXPECT_FALSE(new_browser->window()->IsMaximized()); 1168} 1169 1170namespace { 1171 1172// Invoked from the nested message loop. 1173void DragTabToWindowInSeparateDisplayStep2( 1174 DetachToBrowserTabDragControllerTest* test, 1175 TabStrip* not_attached_tab_strip, 1176 TabStrip* target_tab_strip) { 1177 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1178 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1179 ASSERT_TRUE(TabDragController::IsActive()); 1180 1181 // Drag to target_tab_strip. This should stop the nested loop from dragging 1182 // the window. 1183 gfx::Point target_point( 1184 GetCenterInScreenCoordinates(target_tab_strip->tab_at(0))); 1185 1186 // Move it close to the beginning of the target tabstrip. 1187 target_point.set_x( 1188 target_point.x() - target_tab_strip->tab_at(0)->width() / 2 + 10); 1189 ASSERT_TRUE(test->DragInputToAsync(target_point)); 1190} 1191 1192} // namespace 1193 1194// Drags from browser to another browser on a second display and releases input. 1195IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1196 DragTabToWindowInSeparateDisplay) { 1197 // Add another tab. 1198 AddTabAndResetBrowser(browser()); 1199 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1200 1201 // Create another browser. 1202 Browser* browser2 = CreateBrowser(browser()->profile()); 1203 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1204 ResetIDs(browser2->tab_strip_model(), 100); 1205 1206 // Move the second browser to the second display. 1207 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1208 ASSERT_EQ(2u, roots.size()); 1209 aura::RootWindow* second_root = roots[1]; 1210 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1211 second_root).work_area(); 1212 browser2->window()->SetBounds(work_area); 1213 EXPECT_EQ(second_root, 1214 browser2->window()->GetNativeWindow()->GetRootWindow()); 1215 1216 // Move to the first tab and drag it enough so that it detaches, but not 1217 // enough that it attaches to browser2. 1218 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1219 ASSERT_TRUE(PressInput(tab_0_center)); 1220 ASSERT_TRUE(DragInputToNotifyWhenDone( 1221 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1222 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1223 this, tab_strip, tab_strip2))); 1224 QuitWhenNotDragging(); 1225 1226 // Should now be attached to tab_strip2. 1227 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1228 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1229 ASSERT_TRUE(TabDragController::IsActive()); 1230 1231 // Release the mouse, stopping the drag session. 1232 ASSERT_TRUE(ReleaseInput()); 1233 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1234 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1235 ASSERT_FALSE(TabDragController::IsActive()); 1236 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1237 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1238 1239 // Both windows should not be maximized 1240 EXPECT_FALSE(browser()->window()->IsMaximized()); 1241 EXPECT_FALSE(browser2->window()->IsMaximized()); 1242} 1243 1244// Drags from browser to another browser on a second display and releases input. 1245IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1246 DragTabToWindowOnSecondDisplay) { 1247 // Add another tab. 1248 AddTabAndResetBrowser(browser()); 1249 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1250 1251 // Create another browser. 1252 Browser* browser2 = CreateBrowser(browser()->profile()); 1253 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1254 ResetIDs(browser2->tab_strip_model(), 100); 1255 1256 // Move both browsers to the second display. 1257 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1258 ASSERT_EQ(2u, roots.size()); 1259 aura::RootWindow* second_root = roots[1]; 1260 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1261 second_root).work_area(); 1262 browser()->window()->SetBounds(work_area); 1263 1264 // position both browser windows side by side on the second screen. 1265 gfx::Rect work_area2(work_area); 1266 work_area.set_width(work_area.width()/2); 1267 browser()->window()->SetBounds(work_area); 1268 work_area2.set_x(work_area2.x() + work_area2.width()/2); 1269 work_area2.set_width(work_area2.width()/2); 1270 browser2->window()->SetBounds(work_area2); 1271 EXPECT_EQ(second_root, 1272 browser()->window()->GetNativeWindow()->GetRootWindow()); 1273 EXPECT_EQ(second_root, 1274 browser2->window()->GetNativeWindow()->GetRootWindow()); 1275 1276 // Move to the first tab and drag it enough so that it detaches, but not 1277 // enough that it attaches to browser2. 1278 // SetEventGeneratorRootWindow sets correct (second) RootWindow 1279 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1280 SetEventGeneratorRootWindow(tab_0_center); 1281 ASSERT_TRUE(PressInput(tab_0_center)); 1282 ASSERT_TRUE(DragInputToNotifyWhenDone( 1283 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1284 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1285 this, tab_strip, tab_strip2))); 1286 QuitWhenNotDragging(); 1287 1288 // Should now be attached to tab_strip2. 1289 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1290 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1291 ASSERT_TRUE(TabDragController::IsActive()); 1292 1293 // Release the mouse, stopping the drag session. 1294 ASSERT_TRUE(ReleaseInput()); 1295 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1296 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1297 ASSERT_FALSE(TabDragController::IsActive()); 1298 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1299 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1300 1301 // Both windows should not be maximized 1302 EXPECT_FALSE(browser()->window()->IsMaximized()); 1303 EXPECT_FALSE(browser2->window()->IsMaximized()); 1304} 1305 1306// Drags from a maximized browser to another non-maximized browser on a second 1307// display and releases input. 1308IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest, 1309 DragMaxTabToNonMaxWindowInSeparateDisplay) { 1310 // Add another tab. 1311 AddTabAndResetBrowser(browser()); 1312 browser()->window()->Maximize(); 1313 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1314 1315 // Create another browser on the second display. 1316 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1317 ASSERT_EQ(2u, roots.size()); 1318 aura::RootWindow* first_root = roots[0]; 1319 aura::RootWindow* second_root = roots[1]; 1320 gfx::Rect work_area = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1321 second_root).work_area(); 1322 work_area.Inset(20,20,20,60); 1323 Browser::CreateParams params(browser()->profile(), 1324 chrome::HOST_DESKTOP_TYPE_NATIVE); 1325 params.initial_show_state = ui::SHOW_STATE_NORMAL; 1326 params.initial_bounds = work_area; 1327 Browser* browser2 = new Browser(params); 1328 AddBlankTabAndShow(browser2); 1329 1330 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1331 ResetIDs(browser2->tab_strip_model(), 100); 1332 1333 EXPECT_EQ(second_root, 1334 browser2->window()->GetNativeWindow()->GetRootWindow()); 1335 EXPECT_EQ(first_root, 1336 browser()->window()->GetNativeWindow()->GetRootWindow()); 1337 EXPECT_EQ(2, tab_strip->tab_count()); 1338 EXPECT_EQ(1, tab_strip2->tab_count()); 1339 1340 // Move to the first tab and drag it enough so that it detaches, but not 1341 // enough that it attaches to browser2. 1342 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1343 ASSERT_TRUE(PressInput(tab_0_center)); 1344 ASSERT_TRUE(DragInputToNotifyWhenDone( 1345 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1346 base::Bind(&DragTabToWindowInSeparateDisplayStep2, 1347 this, tab_strip, tab_strip2))); 1348 QuitWhenNotDragging(); 1349 1350 // Should now be attached to tab_strip2. 1351 ASSERT_TRUE(tab_strip2->IsDragSessionActive()); 1352 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1353 ASSERT_TRUE(TabDragController::IsActive()); 1354 1355 // Release the mouse, stopping the drag session. 1356 ASSERT_TRUE(ReleaseInput()); 1357 1358 // tab should have moved 1359 EXPECT_EQ(1, tab_strip->tab_count()); 1360 EXPECT_EQ(2, tab_strip2->tab_count()); 1361 1362 ASSERT_FALSE(tab_strip2->IsDragSessionActive()); 1363 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1364 ASSERT_FALSE(TabDragController::IsActive()); 1365 EXPECT_EQ("0 100", IDString(browser2->tab_strip_model())); 1366 EXPECT_EQ("1", IDString(browser()->tab_strip_model())); 1367 1368 // Source browser should still be maximized, target should not 1369 EXPECT_TRUE(browser()->window()->IsMaximized()); 1370 EXPECT_FALSE(browser2->window()->IsMaximized()); 1371} 1372 1373class DifferentDeviceScaleFactorDisplayTabDragControllerTest 1374 : public DetachToBrowserTabDragControllerTest { 1375 public: 1376 DifferentDeviceScaleFactorDisplayTabDragControllerTest() {} 1377 1378 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1379 DetachToBrowserTabDragControllerTest::SetUpCommandLine(command_line); 1380 command_line->AppendSwitchASCII("ash-host-window-bounds", 1381 "400x400,800x800*2"); 1382 } 1383 1384 float GetCursorDeviceScaleFactor() const { 1385 ash::test::CursorManagerTestApi cursor_test_api( 1386 ash::Shell::GetInstance()->cursor_manager()); 1387 return cursor_test_api.GetDisplay().device_scale_factor(); 1388 } 1389 1390 private: 1391 DISALLOW_COPY_AND_ASSIGN( 1392 DifferentDeviceScaleFactorDisplayTabDragControllerTest); 1393}; 1394 1395namespace { 1396 1397// The points where a tab is dragged in CursorDeviceScaleFactorStep. 1398const struct DragPoint { 1399 int x; 1400 int y; 1401} kDragPoints[] = { 1402 {300, 200}, 1403 {399, 200}, 1404 {500, 200}, 1405 {400, 200}, 1406 {300, 200}, 1407}; 1408 1409// The expected device scale factors before the cursor is moved to the 1410// corresponding kDragPoints in CursorDeviceScaleFactorStep. 1411const float kDeviceScaleFactorExpectations[] = { 1412 1.0f, 1413 1.0f, 1414 2.0f, 1415 2.0f, 1416 1.0f, 1417}; 1418 1419COMPILE_ASSERT( 1420 arraysize(kDragPoints) == arraysize(kDeviceScaleFactorExpectations), 1421 kDragPoints_and_kDeviceScaleFactorExpectations_must_have_same_size); 1422 1423// Drags tab to |kDragPoints[index]|, then calls the next step function. 1424void CursorDeviceScaleFactorStep( 1425 DifferentDeviceScaleFactorDisplayTabDragControllerTest* test, 1426 TabStrip* not_attached_tab_strip, 1427 size_t index) { 1428 ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive()); 1429 ASSERT_TRUE(TabDragController::IsActive()); 1430 1431 if (index < arraysize(kDragPoints)) { 1432 EXPECT_EQ(kDeviceScaleFactorExpectations[index], 1433 test->GetCursorDeviceScaleFactor()); 1434 const DragPoint p = kDragPoints[index]; 1435 ASSERT_TRUE(test->DragInputToNotifyWhenDone( 1436 p.x, p.y, base::Bind(&CursorDeviceScaleFactorStep, 1437 test, not_attached_tab_strip, index + 1))); 1438 } else { 1439 // Finishes a serise of CursorDeviceScaleFactorStep calls and ends drag. 1440 EXPECT_EQ(1.0f, test->GetCursorDeviceScaleFactor()); 1441 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1442 ui_controls::LEFT, ui_controls::UP)); 1443 } 1444} 1445 1446} // namespace 1447 1448// Verifies cursor's device scale factor is updated when a tab is moved across 1449// displays with different device scale factors (http://crbug.com/154183). 1450IN_PROC_BROWSER_TEST_P(DifferentDeviceScaleFactorDisplayTabDragControllerTest, 1451 CursorDeviceScaleFactor) { 1452 // Add another tab. 1453 AddTabAndResetBrowser(browser()); 1454 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1455 1456 // Move the second browser to the second display. 1457 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1458 ASSERT_EQ(2u, roots.size()); 1459 1460 // Move to the first tab and drag it enough so that it detaches. 1461 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1462 ASSERT_TRUE(PressInput(tab_0_center)); 1463 ASSERT_TRUE(DragInputToNotifyWhenDone( 1464 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1465 base::Bind(&CursorDeviceScaleFactorStep, 1466 this, tab_strip, 0))); 1467 QuitWhenNotDragging(); 1468} 1469 1470namespace { 1471 1472class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest 1473 : public TabDragControllerTest { 1474 public: 1475 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {} 1476 1477 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 1478 TabDragControllerTest::SetUpCommandLine(command_line); 1479 command_line->AppendSwitchASCII("ash-host-window-bounds", 1480 "0+0-250x250,251+0-250x250"); 1481 } 1482 1483 bool Press(const gfx::Point& position) { 1484 return ui_test_utils::SendMouseMoveSync(position) && 1485 ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, 1486 ui_controls::DOWN); 1487 } 1488 1489 bool DragTabAndExecuteTaskWhenDone(const gfx::Point& position, 1490 const base::Closure& task) { 1491 return ui_controls::SendMouseMoveNotifyWhenDone( 1492 position.x(), position.y(), task); 1493 } 1494 1495 void QuitWhenNotDragging() { 1496 test::QuitWhenNotDraggingImpl(); 1497 base::MessageLoop::current()->Run(); 1498 } 1499 1500 private: 1501 DISALLOW_COPY_AND_ASSIGN( 1502 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest); 1503}; 1504 1505// Invoked from the nested message loop. 1506void CancelDragTabToWindowInSeparateDisplayStep3( 1507 TabStrip* tab_strip, 1508 const BrowserList* browser_list) { 1509 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1510 ASSERT_TRUE(TabDragController::IsActive()); 1511 ASSERT_EQ(2u, browser_list->size()); 1512 1513 // Switching display mode should cancel the drag operation. 1514 ash::internal::DisplayManager* display_manager = 1515 ash::Shell::GetInstance()->display_manager(); 1516 display_manager->AddRemoveDisplay(); 1517} 1518 1519// Invoked from the nested message loop. 1520void CancelDragTabToWindowInSeparateDisplayStep2( 1521 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest* test, 1522 TabStrip* tab_strip, 1523 aura::RootWindow* current_root, 1524 gfx::Point final_destination, 1525 const BrowserList* browser_list) { 1526 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1527 ASSERT_TRUE(TabDragController::IsActive()); 1528 ASSERT_EQ(2u, browser_list->size()); 1529 1530 Browser* new_browser = browser_list->get(1); 1531 EXPECT_EQ(current_root, 1532 new_browser->window()->GetNativeWindow()->GetRootWindow()); 1533 1534 ASSERT_TRUE(test->DragTabAndExecuteTaskWhenDone( 1535 final_destination, 1536 base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3, 1537 tab_strip, browser_list))); 1538} 1539 1540} // namespace 1541 1542// Drags from browser to a second display and releases input. 1543IN_PROC_BROWSER_TEST_F( 1544 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 1545 CancelDragTabToWindowIn2ndDisplay) { 1546 // Add another tab. 1547 AddTabAndResetBrowser(browser()); 1548 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1549 1550 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1551 1552 // Move the second browser to the second display. 1553 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1554 ASSERT_EQ(2u, roots.size()); 1555 gfx::Point final_destination = 1556 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1557 roots[1]).work_area().CenterPoint(); 1558 1559 // Move to the first tab and drag it enough so that it detaches, but not 1560 // enough to move to another display. 1561 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1562 ASSERT_TRUE(Press(tab_0_dst)); 1563 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 1564 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 1565 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 1566 this, tab_strip, roots[0], final_destination, 1567 native_browser_list))); 1568 QuitWhenNotDragging(); 1569 1570 ASSERT_EQ(1u, native_browser_list->size()); 1571 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1572 ASSERT_FALSE(TabDragController::IsActive()); 1573 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1574 1575 // Release the mouse 1576 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1577 ui_controls::LEFT, ui_controls::UP)); 1578} 1579 1580// Drags from browser from a second display to primary and releases input. 1581IN_PROC_BROWSER_TEST_F( 1582 DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest, 1583 CancelDragTabToWindowIn1stDisplay) { 1584 std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows()); 1585 ASSERT_EQ(2u, roots.size()); 1586 1587 // Add another tab. 1588 AddTabAndResetBrowser(browser()); 1589 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1590 1591 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1592 EXPECT_EQ(roots[0], browser()->window()->GetNativeWindow()->GetRootWindow()); 1593 1594 gfx::Rect work_area = gfx::Screen::GetNativeScreen()-> 1595 GetDisplayNearestWindow(roots[1]).work_area(); 1596 browser()->window()->SetBounds(work_area); 1597 EXPECT_EQ(roots[1], browser()->window()->GetNativeWindow()->GetRootWindow()); 1598 1599 // Move the second browser to the display. 1600 gfx::Point final_destination = 1601 gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow( 1602 roots[0]).work_area().CenterPoint(); 1603 1604 // Move to the first tab and drag it enough so that it detaches, but not 1605 // enough to move to another display. 1606 gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1607 ASSERT_TRUE(Press(tab_0_dst)); 1608 tab_0_dst.Offset(0, GetDetachY(tab_strip)); 1609 ASSERT_TRUE(DragTabAndExecuteTaskWhenDone( 1610 tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2, 1611 this, tab_strip, roots[1], final_destination, 1612 native_browser_list))); 1613 QuitWhenNotDragging(); 1614 1615 ASSERT_EQ(1u, native_browser_list->size()); 1616 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1617 ASSERT_FALSE(TabDragController::IsActive()); 1618 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1619 1620 // Release the mouse 1621 ASSERT_TRUE(ui_test_utils::SendMouseEventsSync( 1622 ui_controls::LEFT, ui_controls::UP)); 1623} 1624 1625#endif 1626 1627#if defined(USE_ASH) && !defined(OS_WIN) // TODO(win_ash) 1628INSTANTIATE_TEST_CASE_P(TabDragging, 1629 DetachToBrowserInSeparateDisplayTabDragControllerTest, 1630 ::testing::Values("mouse", "touch")); 1631INSTANTIATE_TEST_CASE_P(TabDragging, 1632 DifferentDeviceScaleFactorDisplayTabDragControllerTest, 1633 ::testing::Values("mouse")); 1634INSTANTIATE_TEST_CASE_P(TabDragging, 1635 DetachToBrowserTabDragControllerTest, 1636 ::testing::Values("mouse", "touch")); 1637#else 1638INSTANTIATE_TEST_CASE_P(TabDragging, 1639 DetachToBrowserTabDragControllerTest, 1640 ::testing::Values("mouse")); 1641#endif 1642