diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-04 06:27:53 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-04 06:27:53 +0000 |
commit | bc069bc0c5602c7c8e021072cec2d103d7113fcf (patch) | |
tree | dae644380adc0e476afc5800c71c003c645ed052 | |
parent | 012bc60b448eef3d189784c6510b3b06c0b448f7 (diff) | |
download | chromium_src-bc069bc0c5602c7c8e021072cec2d103d7113fcf.zip chromium_src-bc069bc0c5602c7c8e021072cec2d103d7113fcf.tar.gz chromium_src-bc069bc0c5602c7c8e021072cec2d103d7113fcf.tar.bz2 |
Make new dragged tab windows take on the restored window size.
Exploratory CL to cause new windows created as the result of a drag operation to be sized according to the restored window bounds. This applies to the "detach into new window while dragging" code path used by Aura, not the "make a semi-transparent preview window while dragging codepath" used on non-Aura Windows.
Also, always position tabs of such new windows to the left of the tabstrip. If this isn't done, then when dragging a tab from the right of a maximized window, the tab will be placed beyond the bounds of the restored window.
BUG=175448
TEST=Maximize a window in WinAura, then drag tabs off it.
Review URL: https://chromiumcodereview.appspot.com/17724003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210142 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_drag_controller.cc | 77 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_drag_controller.h | 4 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc | 62 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_strip.cc | 12 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_strip.h | 10 |
5 files changed, 144 insertions, 21 deletions
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 3b432ce..3412b5d 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc @@ -201,15 +201,6 @@ void SetWindowPositionManaged(gfx::NativeWindow window, bool value) { #endif } -bool ShouldDetachIntoNewBrowser() { -#if defined(USE_AURA) - return true; -#else - return CommandLine::ForCurrentProcess()->HasSwitch( - switches::kTabBrowserDragging); -#endif -} - // Returns true if |bounds| contains the y-coordinate |y|. The y-coordinate // of |bounds| is adjusted by |vertical_adjustment|. bool DoesRectContainVerticalPointExpanded( @@ -479,6 +470,16 @@ bool TabDragController::IsActive() { return instance_ && instance_->active(); } +// static +bool TabDragController::ShouldDetachIntoNewBrowser() { +#if defined(USE_AURA) + return true; +#else + return CommandLine::ForCurrentProcess()->HasSwitch( + switches::kTabBrowserDragging); +#endif +} + void TabDragController::SetMoveBehavior(MoveBehavior behavior) { if (started_drag()) return; @@ -1307,7 +1308,6 @@ void TabDragController::DetachIntoNewBrowserAndRunMoveLoop( // Create a new browser to house the dragged tabs and have the OS run a move // loop. - gfx::Point attached_point = GetAttachedDragPoint(point_in_screen); // Calculate the bounds for the tabs from the attached_tab_strip. We do this @@ -1315,6 +1315,11 @@ void TabDragController::DetachIntoNewBrowserAndRunMoveLoop( std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(attached_point.x()); + // Stash the current window size and tab area width. + gfx::Size source_size = + attached_tabstrip_->GetWidget()->GetWindowBoundsInScreen().size(); + int available_source_width = attached_tabstrip_->tab_area_width(); + gfx::Vector2d drag_offset; Browser* browser = CreateBrowserForDrag( attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); @@ -1324,7 +1329,50 @@ void TabDragController::DetachIntoNewBrowserAndRunMoveLoop( dragged_browser_view->GetWidget()->SetVisibilityChangedAnimationsEnabled( false); Attach(dragged_browser_view->tabstrip(), gfx::Point()); - // TODO: come up with a cleaner way to do this. + + // If the window size has changed, the tab positioning will be quite off. + if (source_size != + attached_tabstrip_->GetWidget()->GetWindowBoundsInScreen().size()) { + // First, scale the drag bounds such that they fit within the new window + // while maintaining the same relative positions. This scales the tabs + // down so that they occupy the same relative width on the new tab strip, + // clamping to minimum tab width. + int available_attached_width = attached_tabstrip_->tab_area_width(); + float x_scale = + static_cast<float>(available_attached_width) / available_source_width; + int x_offset = std::ceil((1.0 - x_scale) * drag_bounds[0].x()); + int accumulated_width_offset = 0; + for (size_t i = 0; i < drag_bounds.size(); ++i) { + gfx::Rect& tab_bounds = drag_bounds[i]; + tab_bounds.Offset(-(x_offset + accumulated_width_offset), 0); + int old_width = tab_bounds.width(); + int min_width = (i == source_tab_index_) ? + drag_data_[i].attached_tab->GetMinimumSelectedSize().width() : + drag_data_[i].attached_tab->GetMinimumUnselectedSize().width(); + int new_width = + std::max(min_width, static_cast<int>(std::ceil(old_width * x_scale))); + tab_bounds.set_width(new_width); + accumulated_width_offset += (old_width - tab_bounds.width()); + } + + // Next, re-position the restored window such that the tab that was dragged + // remains centered under the mouse cursor. The two offsets needed here are + // the offset of the dragged tab in widget coordinates, and half the dragged + // tab width. The sum of these is the horizontal distance from the mouse + // cursor to the window edge. + gfx::Point offset(drag_bounds[source_tab_index_].origin()); + views::View::ConvertPointToWidget(attached_tabstrip_, &offset); + int half_tab_width = drag_bounds[source_tab_index_].width() / 2; + gfx::Rect new_bounds = browser->window()->GetBounds(); + new_bounds.set_x(point_in_screen.x() - offset.x() - half_tab_width); + + // To account for the extra vertical on restored windows that is absent + // on maximized windows, add an additional vertical offset extracted from + // the tab strip. + new_bounds.Offset(0, -attached_tabstrip_->button_v_offset()); + browser->window()->SetBounds(new_bounds); + } + attached_tabstrip_->SetTabBoundsForDrag(drag_bounds); WindowPositionManagedUpdater updater; @@ -2003,14 +2051,13 @@ Browser* TabDragController::CreateBrowserForDrag( std::vector<gfx::Rect>* drag_bounds) { gfx::Point center(0, source->height() / 2); views::View::ConvertPointToWidget(source, ¢er); - gfx::Rect new_bounds(source->GetWidget()->GetWindowBoundsInScreen()); + gfx::Rect new_bounds(source->GetWidget()->GetRestoredBounds()); new_bounds.set_y(point_in_screen.y() - center.y()); switch (GetDetachPosition(point_in_screen)) { case DETACH_BEFORE: new_bounds.set_x(point_in_screen.x() - center.x()); new_bounds.Offset(-mouse_offset_.x(), 0); break; - case DETACH_AFTER: { gfx::Point right_edge(source->width(), 0); views::View::ConvertPointToWidget(source, &right_edge); @@ -2021,7 +2068,6 @@ Browser* TabDragController::CreateBrowserForDrag( (*drag_bounds)[i].Offset(-delta, 0); break; } - default: break; // Nothing to do for DETACH_ABOVE_OR_BELOW. } @@ -2041,9 +2087,6 @@ Browser* TabDragController::CreateBrowserForDrag( // We need to reset them again so they are honored. browser->window()->SetBounds(new_bounds); - // If source window was maximized - maximize the new window as well. - if (source->GetWidget()->IsMaximized() || source->GetWidget()->IsFullscreen()) - browser->window()->Maximize(); return browser; } diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h index 7323976..2f5a37a 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.h +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h @@ -113,6 +113,10 @@ class TabDragController : public content::WebContentsDelegate, // Returns true if there is a drag underway. static bool IsActive(); + // Used to determine whether the tab drag controller detaches dragged tabs + // into new browser windows while the drag is in process. + static bool ShouldDetachIntoNewBrowser(); + // Sets the move behavior. Has no effect if started_drag() is true. void SetMoveBehavior(MoveBehavior behavior); MoveBehavior move_behavior() const { return move_behavior_; } diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index f1e896a..8beba3f 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc @@ -518,6 +518,63 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, EXPECT_FALSE(new_browser->window()->IsMaximized()); } +// Drags from browser to separate window and releases mouse. +IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, + DetachToOwnWindowFromMaximizedWindow) { + if (!TabDragController::ShouldDetachIntoNewBrowser()) { + VLOG(1) + << "Skipping DetachToOwnWindowFromMaximizedWindow on this platform."; + return; + } + + // Maximize the initial browser window. + browser()->window()->Maximize(); + ASSERT_TRUE(browser()->window()->IsMaximized()); + + // Add another tab. + AddTabAndResetBrowser(browser()); + TabStrip* tab_strip = GetTabStripForBrowser(browser()); + + // Move to the first tab and drag it enough so that it detaches. + gfx::Point tab_0_center( + GetCenterInScreenCoordinates(tab_strip->tab_at(0))); + ASSERT_TRUE(PressInput(tab_0_center)); + ASSERT_TRUE(DragInputToNotifyWhenDone( + tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), + base::Bind(&DetachToOwnWindowStep2, this))); + if (input_source() == INPUT_SOURCE_MOUSE) { + ASSERT_TRUE(ReleaseMouseAsync()); + QuitWhenNotDragging(); + } + + // Should no longer be dragging. + ASSERT_FALSE(tab_strip->IsDragSessionActive()); + ASSERT_FALSE(TabDragController::IsActive()); + + // There should now be another browser. + ASSERT_EQ(2u, native_browser_list->size()); + Browser* new_browser = native_browser_list->get(1); + ASSERT_TRUE(new_browser->window()->IsActive()); + TabStrip* tab_strip2 = GetTabStripForBrowser(new_browser); + ASSERT_FALSE(tab_strip2->IsDragSessionActive()); + + EXPECT_EQ("0", IDString(new_browser->tab_strip_model())); + EXPECT_EQ("1", IDString(browser()->tab_strip_model())); + + // The bounds of the initial window should not have changed. + EXPECT_TRUE(browser()->window()->IsMaximized()); + + EXPECT_TRUE(GetTrackedByWorkspace(browser())); + EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); + // After this both windows should still be managable. + EXPECT_TRUE(IsWindowPositionManaged(browser()->window()->GetNativeWindow())); + EXPECT_TRUE(IsWindowPositionManaged( + new_browser->window()->GetNativeWindow())); + + // The new window should not be maximized. + EXPECT_FALSE(new_browser->window()->IsMaximized()); +} + // Deletes a tab being dragged before the user moved enough to start a drag. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, DeleteBeforeStartedDragging) { @@ -1079,9 +1136,10 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, EXPECT_TRUE(GetTrackedByWorkspace(browser())); EXPECT_TRUE(GetTrackedByWorkspace(new_browser)); - // Both windows should be maximized + // The source window should be maximized, but the new window should now + // be restored. EXPECT_TRUE(browser()->window()->IsMaximized()); - EXPECT_TRUE(new_browser->window()->IsMaximized()); + EXPECT_FALSE(new_browser->window()->IsMaximized()); } // Subclass of DetachToBrowserInSeparateDisplayTabDragControllerTest that diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index e0356c8..a99257d 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc @@ -2505,10 +2505,20 @@ int TabStrip::GenerateIdealBoundsForMiniTabs(int* first_non_mini_index) { return next_x; } -int TabStrip::new_tab_button_width() const { +// static +int TabStrip::new_tab_button_width() { return newtab_button_asset_width() + newtab_button_h_offset(); } +// static +int TabStrip::button_v_offset() { + return newtab_button_v_offset(); +} + +int TabStrip::tab_area_width() const { + return width() - new_tab_button_width(); +} + void TabStrip::StartResizeLayoutAnimation() { PrepareForAnimation(); GenerateIdealBounds(); diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index a78cff7..9ace500 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h @@ -475,7 +475,15 @@ class TabStrip : public views::View, int GenerateIdealBoundsForMiniTabs(int* first_non_mini_index); // Returns the width needed for the new tab button (and padding). - int new_tab_button_width() const; + static int new_tab_button_width(); + + // Returns the vertical offset of the tab strip button. This offset applies + // only to restored windows. + static int button_v_offset(); + + // Returns the width of the area that contains tabs. This does not include + // the width of the new tab button. + int tab_area_width() const; // Starts various types of TabStrip animations. void StartResizeLayoutAnimation(); |