Commit 51d19100 authored by Taylor Bergquist's avatar Taylor Bergquist Committed by Commit Bot

Move GetInsertionIndexForDraggedBounds into TabStrip

Change-Id: I55ce7bb115c6b1202f503f9c7ddeff3fb348c381
Reviewed-on: https://chromium-review.googlesource.com/c/1300676
Commit-Queue: Taylor Bergquist <tbergquist@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604434}
parent ba1da125
......@@ -81,22 +81,12 @@ const int kMoveAttachedSubsequentDelay = 300;
const int kHorizontalMoveThreshold = 16; // DIPs.
// Distance from the next/previous stacked before before we consider the tab
// close enough to trigger moving.
const int kStackedDistance = 36;
// A dragged window is forced to be a bit smaller than maximized bounds during a
// drag. This prevents the dragged browser widget from getting maximized at
// creation and makes it easier to drag tabs out of a restored window that had
// maximized size.
const int kMaximizedWindowInset = 10; // DIPs.
// Given the bounds of a dragged tab, return the X coordinate to use for
// computing where in the strip to insert/move the tab.
int GetDraggedX(const gfx::Rect& dragged_bounds) {
return dragged_bounds.x() + TabStyle::GetTabInternalPadding().left();
}
#if defined(OS_CHROMEOS)
// Returns the aura::Window which stores the window properties for tab-dragging.
......@@ -357,7 +347,8 @@ TabDragController::TabDragController()
initial_move_(true),
detach_behavior_(DETACHABLE),
move_behavior_(REORDER),
mouse_move_direction_(0),
mouse_has_ever_moved_left_(false),
mouse_has_ever_moved_right_(false),
is_dragging_window_(false),
is_dragging_new_browser_(false),
was_source_maximized_(false),
......@@ -721,9 +712,9 @@ TabDragController::Liveness TabDragController::ContinueDragging(
if (attached_tabstrip_) {
int move_delta = point_in_screen.x() - last_point_in_screen_.x();
if (move_delta > 0)
mouse_move_direction_ |= kMovedMouseRight;
mouse_has_ever_moved_right_ = true;
else if (move_delta < 0)
mouse_move_direction_ |= kMovedMouseLeft;
mouse_has_ever_moved_left_ = true;
}
last_point_in_screen_ = point_in_screen;
......@@ -899,8 +890,10 @@ void TabDragController::MoveAttached(const gfx::Point& point_in_screen) {
if ((abs(point_in_screen.x() - last_move_screen_loc_) > threshold ||
(initial_move_ && !AreTabsConsecutive()))) {
TabStripModel* attached_model = GetModel(attached_tabstrip_);
int to_index = GetInsertionIndexForDraggedBounds(
GetDraggedViewTabStripBounds(dragged_view_point));
int to_index = attached_tabstrip_->GetInsertionIndexForDraggedBounds(
GetDraggedViewTabStripBounds(dragged_view_point), false,
static_cast<int>(drag_data_.size()), mouse_has_ever_moved_left_,
mouse_has_ever_moved_right_);
bool do_move = true;
// While dragging within a tabstrip the expectation is the insertion index
// is based on the left edge of the tabs being dragged. OTOH when dragging
......@@ -975,12 +968,14 @@ void TabDragController::StartMoveStackedTimerIfNecessary(
gfx::Point dragged_view_point = GetAttachedDragPoint(point_in_screen);
gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point);
int index = touch_layout->active_index();
if (ShouldDragToNextStackedTab(bounds, index)) {
if (attached_tabstrip_->ShouldDragToNextStackedTab(
bounds, index, mouse_has_ever_moved_right_)) {
move_stacked_timer_.Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
base::Bind(&TabDragController::MoveAttachedToNextStackedIndex,
base::Unretained(this), point_in_screen));
} else if (ShouldDragToPreviousStackedTab(bounds, index)) {
} else if (attached_tabstrip_->ShouldDragToPreviousStackedTab(
bounds, index, mouse_has_ever_moved_left_)) {
move_stacked_timer_.Start(
FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
base::Bind(&TabDragController::MoveAttachedToPreviousStackedIndex,
......@@ -1119,8 +1114,10 @@ void TabDragController::Attach(TabStrip* attached_tabstrip,
tab_strip_point.set_x(
attached_tabstrip_->GetMirroredXInView(tab_strip_point.x()));
tab_strip_point.Offset(0, -mouse_offset_.y());
int index = GetInsertionIndexForDraggedBounds(
GetDraggedViewTabStripBounds(tab_strip_point));
int index = attached_tabstrip_->GetInsertionIndexForDraggedBounds(
GetDraggedViewTabStripBounds(tab_strip_point), true,
static_cast<int>(drag_data_.size()), mouse_has_ever_moved_left_,
mouse_has_ever_moved_right_);
attach_index_ = index;
attach_x_ = tab_strip_point.x();
base::AutoReset<bool> setter(&is_mutating_, true);
......@@ -1192,7 +1189,8 @@ void TabDragController::Detach(ReleaseCapture release_capture) {
if (release_capture == RELEASE_CAPTURE)
attached_tabstrip_->GetWidget()->ReleaseCapture();
mouse_move_direction_ = kMovedMouseLeft | kMovedMouseRight;
mouse_has_ever_moved_left_ = true;
mouse_has_ever_moved_right_ = true;
std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs();
TabStripModel* attached_model = GetModel(attached_tabstrip_);
......@@ -1345,143 +1343,6 @@ void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) {
}
}
int TabDragController::GetInsertionIndexFrom(const gfx::Rect& dragged_bounds,
int start) const {
const int last_tab = attached_tabstrip_->tab_count() - 1;
const int dragged_x = GetDraggedX(dragged_bounds);
if (start < 0 || start > last_tab ||
dragged_x < attached_tabstrip_->ideal_bounds(start).x())
return -1;
for (int i = start; i <= last_tab; ++i) {
if (dragged_x < attached_tabstrip_->ideal_bounds(i).CenterPoint().x())
return i;
}
return (dragged_x < attached_tabstrip_->ideal_bounds(last_tab).right()) ?
(last_tab + 1) : -1;
}
int TabDragController::GetInsertionIndexFromReversed(
const gfx::Rect& dragged_bounds,
int start) const {
const int dragged_x = GetDraggedX(dragged_bounds);
if (start < 0 || start >= attached_tabstrip_->tab_count() ||
dragged_x >= attached_tabstrip_->ideal_bounds(start).right())
return -1;
for (int i = start; i >= 0; --i) {
if (dragged_x >= attached_tabstrip_->ideal_bounds(i).CenterPoint().x())
return i + 1;
}
return (dragged_x >= attached_tabstrip_->ideal_bounds(0).x()) ? 0 : -1;
}
int TabDragController::GetInsertionIndexForDraggedBounds(
const gfx::Rect& dragged_bounds) const {
// If the strip has no tabs, the only position to insert at is 0.
const int tab_count = attached_tabstrip_->tab_count();
if (!tab_count)
return 0;
int index = -1;
if (attached_tabstrip_->touch_layout_.get()) {
index = GetInsertionIndexForDraggedBoundsStacked(dragged_bounds);
if (index != -1) {
// Only move the tab to the left/right if the user actually moved the
// mouse that way. This is necessary as tabs with stacked tabs
// before/after them have multiple drag positions.
int active_index = attached_tabstrip_->touch_layout_->active_index();
if ((index < active_index &&
(mouse_move_direction_ & kMovedMouseLeft) == 0) ||
(index > active_index &&
(mouse_move_direction_ & kMovedMouseRight) == 0)) {
index = active_index;
}
}
} else {
index = GetInsertionIndexFrom(dragged_bounds, 0);
}
if (index == -1) {
const int last_tab_right =
attached_tabstrip_->ideal_bounds(tab_count - 1).right();
index = (dragged_bounds.right() > last_tab_right) ? tab_count : 0;
}
const Tab* last_visible_tab = attached_tabstrip_->GetLastVisibleTab();
int last_insertion_point = last_visible_tab ?
(attached_tabstrip_->GetModelIndexOfTab(last_visible_tab) + 1) : 0;
if (drag_data_[0].attached_tab) {
// We're not in the process of attaching, so clamp the insertion point to
// keep it within the visible region.
last_insertion_point = std::max(
0, last_insertion_point - static_cast<int>(drag_data_.size()));
}
// Ensure the first dragged tab always stays in the visible index range.
return std::min(index, last_insertion_point);
}
bool TabDragController::ShouldDragToNextStackedTab(
const gfx::Rect& dragged_bounds,
int index) const {
if (index + 1 >= attached_tabstrip_->tab_count() ||
!attached_tabstrip_->touch_layout_->IsStacked(index + 1) ||
(mouse_move_direction_ & kMovedMouseRight) == 0)
return false;
int active_x = attached_tabstrip_->ideal_bounds(index).x();
int next_x = attached_tabstrip_->ideal_bounds(index + 1).x();
int mid_x = std::min(next_x - kStackedDistance,
active_x + (next_x - active_x) / 4);
return GetDraggedX(dragged_bounds) >= mid_x;
}
bool TabDragController::ShouldDragToPreviousStackedTab(
const gfx::Rect& dragged_bounds,
int index) const {
if (index - 1 < attached_tabstrip_->GetPinnedTabCount() ||
!attached_tabstrip_->touch_layout_->IsStacked(index - 1) ||
(mouse_move_direction_ & kMovedMouseLeft) == 0)
return false;
int active_x = attached_tabstrip_->ideal_bounds(index).x();
int previous_x = attached_tabstrip_->ideal_bounds(index - 1).x();
int mid_x = std::max(previous_x + kStackedDistance,
active_x - (active_x - previous_x) / 4);
return GetDraggedX(dragged_bounds) <= mid_x;
}
int TabDragController::GetInsertionIndexForDraggedBoundsStacked(
const gfx::Rect& dragged_bounds) const {
StackedTabStripLayout* touch_layout = attached_tabstrip_->touch_layout_.get();
int active_index = touch_layout->active_index();
// Search from the active index to the front of the tabstrip. Do this as tabs
// overlap each other from the active index.
int index = GetInsertionIndexFromReversed(dragged_bounds, active_index);
if (index != active_index)
return index;
if (index == -1)
return GetInsertionIndexFrom(dragged_bounds, active_index + 1);
// The position to drag to corresponds to the active tab. If the next/previous
// tab is stacked, then shorten the distance used to determine insertion
// bounds. We do this as GetInsertionIndexFrom() uses the bounds of the
// tabs. When tabs are stacked the next/previous tab is on top of the tab.
if (active_index + 1 < attached_tabstrip_->tab_count() &&
touch_layout->IsStacked(active_index + 1)) {
index = GetInsertionIndexFrom(dragged_bounds, active_index + 1);
if (index == -1 && ShouldDragToNextStackedTab(dragged_bounds, active_index))
index = active_index + 1;
else if (index == -1)
index = active_index;
} else if (ShouldDragToPreviousStackedTab(dragged_bounds, active_index)) {
index = active_index - 1;
}
return index;
}
gfx::Rect TabDragController::GetDraggedViewTabStripBounds(
const gfx::Point& tab_strip_point) {
// attached_tab is NULL when inserting into a new tabstrip.
......
......@@ -331,37 +331,6 @@ class TabDragController : public views::WidgetObserver,
// dragging.
void RunMoveLoop(const gfx::Vector2d& drag_offset);
// Determines the index to insert tabs at. |dragged_bounds| is the bounds of
// the tab being dragged, |start| the index of the tab to start looking from.
// The search proceeds to the end of the strip.
int GetInsertionIndexFrom(const gfx::Rect& dragged_bounds, int start) const;
// Like GetInsertionIndexFrom(), but searches backwards from |start| to the
// beginning of the strip.
int GetInsertionIndexFromReversed(const gfx::Rect& dragged_bounds,
int start) const;
// Returns the index where the dragged WebContents should be inserted into
// |attached_tabstrip_| given the DraggedTabView's bounds |dragged_bounds| in
// coordinates relative to |attached_tabstrip_| and has had the mirroring
// transformation applied.
// NOTE: this is invoked from Attach() before the tabs have been inserted.
int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds) const;
// Returns true if |dragged_bounds| is close enough to the next stacked tab
// so that the active tab should be dragged there.
bool ShouldDragToNextStackedTab(const gfx::Rect& dragged_bounds,
int index) const;
// Returns true if |dragged_bounds| is close enough to the previous stacked
// tab so that the active tab should be dragged there.
bool ShouldDragToPreviousStackedTab(const gfx::Rect& dragged_bounds,
int index) const;
// Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked.
int GetInsertionIndexForDraggedBoundsStacked(
const gfx::Rect& dragged_bounds) const;
// Retrieves the bounds of the dragged tabs relative to the attached TabStrip.
// |tab_strip_point| is in the attached TabStrip's coordinate system.
gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& tab_strip_point);
......@@ -600,9 +569,14 @@ class TabDragController : public views::WidgetObserver,
MoveBehavior move_behavior_;
// Updated as the mouse is moved when attached. Indicates whether the mouse
// has ever moved to the left or right. If the tabs are ever detached this
// is set to kMovedMouseRight | kMovedMouseLeft.
int mouse_move_direction_;
// has ever moved to the left. If the tabs are ever detached this is set to
// true.
bool mouse_has_ever_moved_left_;
// Updated as the mouse is moved when attached. Indicates whether the mouse
// has ever moved to the right. If the tabs are ever detached this is set
// to true.
bool mouse_has_ever_moved_right_;
// Last location used in screen coordinates.
gfx::Point last_point_in_screen_;
......
......@@ -86,6 +86,16 @@ using MD = ui::MaterialDesignController;
namespace {
// Distance from the next/previous stacked before before we consider the tab
// close enough to trigger moving.
const int kStackedDistance = 36;
// Given the bounds of a dragged tab, return the X coordinate to use for
// computing where in the strip to insert/move the tab.
int GetDraggedX(const gfx::Rect& dragged_bounds) {
return dragged_bounds.x() + TabStyle::GetTabInternalPadding().left();
}
// Max number of stacked tabs.
constexpr int kMaxStackedCount = 4;
......@@ -763,6 +773,81 @@ bool TabStrip::IsDragSessionActive() const {
return drag_controller_ != nullptr;
}
int TabStrip::GetInsertionIndexForDraggedBounds(
const gfx::Rect& dragged_bounds,
bool attaching,
int num_dragged_tabs,
bool mouse_has_ever_moved_left,
bool mouse_has_ever_moved_right) const {
// If the strip has no tabs, the only position to insert at is 0.
if (!tab_count())
return 0;
int index = -1;
if (touch_layout_.get()) {
index = GetInsertionIndexForDraggedBoundsStacked(
dragged_bounds, mouse_has_ever_moved_left, mouse_has_ever_moved_right);
if (index != -1) {
// Only move the tab to the left/right if the user actually moved the
// mouse that way. This is necessary as tabs with stacked tabs
// before/after them have multiple drag positions.
int active_index = touch_layout_->active_index();
if ((index < active_index && !mouse_has_ever_moved_left) ||
(index > active_index && !mouse_has_ever_moved_right)) {
index = active_index;
}
}
} else {
index = GetInsertionIndexFrom(dragged_bounds, 0);
}
if (index == -1) {
const int last_tab_right = ideal_bounds(tab_count() - 1).right();
index = (dragged_bounds.right() > last_tab_right) ? tab_count() : 0;
}
const Tab* last_visible_tab = GetLastVisibleTab();
int last_insertion_point =
last_visible_tab ? (GetModelIndexOfTab(last_visible_tab) + 1) : 0;
if (!attaching) {
// We're not in the process of attaching, so clamp the insertion point to
// keep it within the visible region.
last_insertion_point = std::max(0, last_insertion_point - num_dragged_tabs);
}
// Ensure the first dragged tab always stays in the visible index range.
return std::min(index, last_insertion_point);
}
bool TabStrip::ShouldDragToNextStackedTab(
const gfx::Rect& dragged_bounds,
int index,
bool mouse_has_ever_moved_right) const {
if (index + 1 >= this->tab_count() ||
!this->touch_layout_->IsStacked(index + 1) || !mouse_has_ever_moved_right)
return false;
int active_x = this->ideal_bounds(index).x();
int next_x = this->ideal_bounds(index + 1).x();
int mid_x =
std::min(next_x - kStackedDistance, active_x + (next_x - active_x) / 4);
return GetDraggedX(dragged_bounds) >= mid_x;
}
bool TabStrip::ShouldDragToPreviousStackedTab(
const gfx::Rect& dragged_bounds,
int index,
bool mouse_has_ever_moved_left) const {
if (index - 1 < this->GetPinnedTabCount() ||
!this->touch_layout_->IsStacked(index - 1) || !mouse_has_ever_moved_left)
return false;
int active_x = this->ideal_bounds(index).x();
int previous_x = this->ideal_bounds(index - 1).x();
int mid_x = std::max(previous_x + kStackedDistance,
active_x - (active_x - previous_x) / 4);
return GetDraggedX(dragged_bounds) <= mid_x;
}
bool TabStrip::IsActiveDropTarget() const {
for (int i = 0; i < tab_count(); ++i) {
Tab* tab = tab_at(i);
......@@ -1711,6 +1796,69 @@ std::vector<gfx::Rect> TabStrip::CalculateBoundsForDraggedTabs(
return bounds;
}
int TabStrip::GetInsertionIndexForDraggedBoundsStacked(
const gfx::Rect& dragged_bounds,
bool mouse_has_ever_moved_left,
bool mouse_has_ever_moved_right) const {
StackedTabStripLayout* touch_layout = touch_layout_.get();
int active_index = touch_layout->active_index();
// Search from the active index to the front of the tabstrip. Do this as tabs
// overlap each other from the active index.
int index = GetInsertionIndexFromReversed(dragged_bounds, active_index);
if (index != active_index)
return index;
if (index == -1)
return GetInsertionIndexFrom(dragged_bounds, active_index + 1);
// The position to drag to corresponds to the active tab. If the next/previous
// tab is stacked, then shorten the distance used to determine insertion
// bounds. We do this as GetInsertionIndexFrom() uses the bounds of the
// tabs. When tabs are stacked the next/previous tab is on top of the tab.
if (active_index + 1 < tab_count() &&
touch_layout->IsStacked(active_index + 1)) {
index = GetInsertionIndexFrom(dragged_bounds, active_index + 1);
if (index == -1 && ShouldDragToNextStackedTab(dragged_bounds, active_index,
mouse_has_ever_moved_right))
index = active_index + 1;
else if (index == -1)
index = active_index;
} else if (ShouldDragToPreviousStackedTab(dragged_bounds, active_index,
mouse_has_ever_moved_left)) {
index = active_index - 1;
}
return index;
}
int TabStrip::GetInsertionIndexFrom(const gfx::Rect& dragged_bounds,
int start) const {
const int last_tab = tab_count() - 1;
const int dragged_x = GetDraggedX(dragged_bounds);
if (start < 0 || start > last_tab || dragged_x < ideal_bounds(start).x())
return -1;
for (int i = start; i <= last_tab; ++i) {
if (dragged_x < ideal_bounds(i).CenterPoint().x())
return i;
}
return (dragged_x < ideal_bounds(last_tab).right()) ? (last_tab + 1) : -1;
}
int TabStrip::GetInsertionIndexFromReversed(const gfx::Rect& dragged_bounds,
int start) const {
const int dragged_x = GetDraggedX(dragged_bounds);
if (start < 0 || start >= tab_count() ||
dragged_x >= ideal_bounds(start).right())
return -1;
for (int i = start; i >= 0; --i) {
if (dragged_x >= ideal_bounds(i).CenterPoint().x())
return i + 1;
}
return (dragged_x >= ideal_bounds(0).x()) ? 0 : -1;
}
int TabStrip::TabStartX() const {
if (controller_->GetNewTabButtonPosition() != LEADING)
return 0;
......
......@@ -199,6 +199,31 @@ class TabStrip : public views::AccessiblePaneView,
// Returns true if a drag session is currently active.
bool IsDragSessionActive() const;
// Returns the index where the dragged WebContents should be inserted into
// this tabstrip given the DraggedTabView's bounds |dragged_bounds| in
// coordinates relative to |attached_tabstrip_| and has had the mirroring
// transformation applied.
// |mouse_has_ever_moved_left| and |mouse_has_ever_moved_right| are used
// only in stacked tabs cases.
// NOTE: this is invoked from Attach() before the tabs have been inserted.
int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds,
bool attaching,
int num_dragged_tabs,
bool mouse_has_ever_moved_left,
bool mouse_has_ever_moved_right) const;
// Returns true if |dragged_bounds| is close enough to the next stacked tab
// so that the active tab should be dragged there.
bool ShouldDragToNextStackedTab(const gfx::Rect& dragged_bounds,
int index,
bool mouse_has_ever_moved_right) const;
// Returns true if |dragged_bounds| is close enough to the previous stacked
// tab so that the active tab should be dragged there.
bool ShouldDragToPreviousStackedTab(const gfx::Rect& dragged_bounds,
int index,
bool mouse_has_ever_moved_left) const;
// Returns true if a tab is being dragged into this tab strip.
bool IsActiveDropTarget() const;
......@@ -384,6 +409,22 @@ class TabStrip : public views::AccessiblePaneView,
// coordinate of 0 for the left edge of the first tab's bounds.
static std::vector<gfx::Rect> CalculateBoundsForDraggedTabs(const Tabs& tabs);
// Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked.
int GetInsertionIndexForDraggedBoundsStacked(
const gfx::Rect& dragged_bounds,
bool mouse_has_ever_moved_left,
bool mouse_has_ever_moved_right) const;
// Determines the index to insert tabs at. |dragged_bounds| is the bounds of
// the tab being dragged, |start| the index of the tab to start looking from.
// The search proceeds to the end of the strip.
int GetInsertionIndexFrom(const gfx::Rect& dragged_bounds, int start) const;
// Like GetInsertionIndexFrom(), but searches backwards from |start| to the
// beginning of the strip.
int GetInsertionIndexFromReversed(const gfx::Rect& dragged_bounds,
int start) const;
// Returns the X coordinate the first tab should start at.
int TabStartX() const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment