summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-04 06:27:53 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-04 06:27:53 +0000
commitbc069bc0c5602c7c8e021072cec2d103d7113fcf (patch)
treedae644380adc0e476afc5800c71c003c645ed052
parent012bc60b448eef3d189784c6510b3b06c0b448f7 (diff)
downloadchromium_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.cc77
-rw-r--r--chrome/browser/ui/views/tabs/tab_drag_controller.h4
-rw-r--r--chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc62
-rw-r--r--chrome/browser/ui/views/tabs/tab_strip.cc12
-rw-r--r--chrome/browser/ui/views/tabs/tab_strip.h10
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, &center);
- 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();