Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: chrome/browser/ui/views/tabs/default_tab_drag_controller.cc

Issue 10267023: Gets tab dragging to work in touch mode. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/tabs/default_tab_drag_controller.h" 5 #include "chrome/browser/ui/views/tabs/default_tab_drag_controller.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <set> 8 #include <set>
9 9
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 #elif defined(OS_WIN) 47 #elif defined(OS_WIN)
48 #include "chrome/browser/ui/views/tabs/tab_drag_controller2.h" 48 #include "chrome/browser/ui/views/tabs/tab_drag_controller2.h"
49 #endif 49 #endif
50 50
51 using content::OpenURLParams; 51 using content::OpenURLParams;
52 using content::UserMetricsAction; 52 using content::UserMetricsAction;
53 using content::WebContents; 53 using content::WebContents;
54 54
55 static const int kHorizontalMoveThreshold = 16; // Pixels. 55 static const int kHorizontalMoveThreshold = 16; // Pixels.
56 56
57 // Distance from the next/previous stacked before before we consider the tab
58 // close enough to trigger moving.
59 static const int kStackedDistance = 36;
60
57 // If non-null there is a drag underway. 61 // If non-null there is a drag underway.
58 static DefaultTabDragController* instance_ = NULL; 62 static DefaultTabDragController* instance_ = NULL;
59 63
60 namespace { 64 namespace {
61 65
62 // Delay, in ms, during dragging before we bring a window to front. 66 // Delay, in ms, during dragging before we bring a window to front.
63 const int kBringToFrontDelay = 750; 67 const int kBringToFrontDelay = 750;
64 68
69 // Initial delay before moving tabs when the dragged tab is close to the edge of
70 // the stacked tabs.
71 const int kMoveAttachedInitialDelay = 600;
72
73 // Delay for moving tabs after the initial delay has passed.
74 const int kMoveAttachedSubsequentDelay = 300;
75
65 // Radius of the rect drawn by DockView. 76 // Radius of the rect drawn by DockView.
66 const int kRoundedRectRadius = 4; 77 const int kRoundedRectRadius = 4;
67 78
68 // Spacing between tab icons when DockView is showing a docking location that 79 // Spacing between tab icons when DockView is showing a docking location that
69 // contains more than one tab. 80 // contains more than one tab.
70 const int kTabSpacing = 4; 81 const int kTabSpacing = 4;
71 82
72 // DockView is the view responsible for giving a visual indicator of where a 83 // DockView is the view responsible for giving a visual indicator of where a
73 // dock is going to occur. 84 // dock is going to occur.
74 85
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 SkPaint paint; 180 SkPaint paint;
170 paint.setAlpha(128); 181 paint.setAlpha(128);
171 canvas->DrawBitmapInt(image, x, y, paint); 182 canvas->DrawBitmapInt(image, x, y, paint);
172 } 183 }
173 184
174 DockInfo::Type type_; 185 DockInfo::Type type_;
175 186
176 DISALLOW_COPY_AND_ASSIGN(DockView); 187 DISALLOW_COPY_AND_ASSIGN(DockView);
177 }; 188 };
178 189
179 // Returns the the x-coordinate of |point| if the type of tabstrip is horizontal 190 // Returns the x-coordinate of |point| if the type of tabstrip is horizontal
180 // otherwise returns the y-coordinate. 191 // otherwise returns the y-coordinate.
181 int MajorAxisValue(const gfx::Point& point, TabStrip* tabstrip) { 192 int MajorAxisValue(const gfx::Point& point, TabStrip* tabstrip) {
182 return point.x(); 193 return point.x();
183 } 194 }
184 195
185 } // namespace 196 } // namespace
186 197
187 /////////////////////////////////////////////////////////////////////////////// 198 ///////////////////////////////////////////////////////////////////////////////
188 // DockDisplayer 199 // DockDisplayer
189 200
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 : source_tabstrip_(NULL), 325 : source_tabstrip_(NULL),
315 attached_tabstrip_(NULL), 326 attached_tabstrip_(NULL),
316 source_tab_offset_(0), 327 source_tab_offset_(0),
317 offset_to_width_ratio_(0), 328 offset_to_width_ratio_(0),
318 old_focused_view_(NULL), 329 old_focused_view_(NULL),
319 last_move_screen_loc_(0), 330 last_move_screen_loc_(0),
320 started_drag_(false), 331 started_drag_(false),
321 active_(true), 332 active_(true),
322 source_tab_index_(std::numeric_limits<size_t>::max()), 333 source_tab_index_(std::numeric_limits<size_t>::max()),
323 initial_move_(true), 334 initial_move_(true),
324 move_only_(false) { 335 move_only_(false),
336 mouse_move_direction_(0) {
325 instance_ = this; 337 instance_ = this;
326 } 338 }
327 339
328 DefaultTabDragController::~DefaultTabDragController() { 340 DefaultTabDragController::~DefaultTabDragController() {
329 if (instance_ == this) 341 if (instance_ == this)
330 instance_ = NULL; 342 instance_ = NULL;
331 343
332 MessageLoopForUI::current()->RemoveObserver(this); 344 MessageLoopForUI::current()->RemoveObserver(this);
333 345
334 // Need to delete the view here manually _before_ we reset the dragged 346 // Need to delete the view here manually _before_ we reset the dragged
(...skipping 15 matching lines...) Expand all
350 int source_tab_offset, 362 int source_tab_offset,
351 const TabStripSelectionModel& initial_selection_model, 363 const TabStripSelectionModel& initial_selection_model,
352 bool move_only) { 364 bool move_only) {
353 DCHECK(!tabs.empty()); 365 DCHECK(!tabs.empty());
354 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); 366 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end());
355 source_tabstrip_ = source_tabstrip; 367 source_tabstrip_ = source_tabstrip;
356 source_tab_offset_ = source_tab_offset; 368 source_tab_offset_ = source_tab_offset;
357 start_screen_point_ = GetCursorScreenPoint(); 369 start_screen_point_ = GetCursorScreenPoint();
358 mouse_offset_ = mouse_offset; 370 mouse_offset_ = mouse_offset;
359 move_only_ = move_only; 371 move_only_ = move_only;
372 last_screen_point_ = start_screen_point_;
360 373
361 if (move_only_) { 374 if (move_only_) {
362 last_move_screen_loc_ = 375 last_move_screen_loc_ =
363 MajorAxisValue(start_screen_point_, attached_tabstrip_); 376 MajorAxisValue(start_screen_point_, attached_tabstrip_);
364 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); 377 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates();
365 } 378 }
366 379
367 drag_data_.resize(tabs.size()); 380 drag_data_.resize(tabs.size());
368 for (size_t i = 0; i < tabs.size(); ++i) 381 for (size_t i = 0; i < tabs.size(); ++i)
369 InitTabDragData(tabs[i], &(drag_data_[i])); 382 InitTabDragData(tabs[i], &(drag_data_[i]));
(...skipping 26 matching lines...) Expand all
396 // We need to be the delegate so we receive messages about stuff, otherwise 409 // We need to be the delegate so we receive messages about stuff, otherwise
397 // our dragged WebContents may be replaced and subsequently 410 // our dragged WebContents may be replaced and subsequently
398 // collected/destroyed while the drag is in process, leading to nasty crashes. 411 // collected/destroyed while the drag is in process, leading to nasty crashes.
399 drag_data->original_delegate = 412 drag_data->original_delegate =
400 drag_data->contents->web_contents()->GetDelegate(); 413 drag_data->contents->web_contents()->GetDelegate();
401 drag_data->contents->web_contents()->SetDelegate(this); 414 drag_data->contents->web_contents()->SetDelegate(this);
402 } 415 }
403 416
404 void DefaultTabDragController::Drag() { 417 void DefaultTabDragController::Drag() {
405 bring_to_front_timer_.Stop(); 418 bring_to_front_timer_.Stop();
419 move_stacked_timer_.Stop();
406 420
407 if (!started_drag_) { 421 if (!started_drag_) {
408 if (!CanStartDrag()) 422 if (!CanStartDrag())
409 return; // User hasn't dragged far enough yet. 423 return; // User hasn't dragged far enough yet.
410 424
411 started_drag_ = true; 425 started_drag_ = true;
412 SaveFocus(); 426 SaveFocus();
413 Attach(source_tabstrip_, gfx::Point()); 427 Attach(source_tabstrip_, gfx::Point());
414 // Redirect all mouse events to the TabStrip so that the tab that 428 // Redirect all mouse events to the TabStrip so that the tab that
415 // originated the drag can safely be deleted. 429 // originated the drag can safely be deleted.
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 if (!target_tabstrip) { 686 if (!target_tabstrip) {
673 bring_to_front_timer_.Start(FROM_HERE, 687 bring_to_front_timer_.Start(FROM_HERE,
674 base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this, 688 base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this,
675 &DefaultTabDragController::BringWindowUnderMouseToFront); 689 &DefaultTabDragController::BringWindowUnderMouseToFront);
676 } 690 }
677 691
678 UpdateDockInfo(screen_point); 692 UpdateDockInfo(screen_point);
679 693
680 if (attached_tabstrip_) { 694 if (attached_tabstrip_) {
681 if (move_only_) 695 if (move_only_)
682 MoveAttachedStacked(screen_point); 696 DragActiveTabStacked(screen_point);
683 else 697 else
684 MoveAttached(screen_point); 698 MoveAttached(screen_point);
685 } else { 699 } else {
686 MoveDetached(screen_point); 700 MoveDetached(screen_point);
687 } 701 }
688 } 702 }
689 703
690 void DefaultTabDragController::MoveAttachedStacked( 704 void DefaultTabDragController::DragActiveTabStacked(
691 const gfx::Point& screen_point) { 705 const gfx::Point& screen_point) {
692 if (attached_tabstrip_->tab_count() != 706 if (attached_tabstrip_->tab_count() !=
693 static_cast<int>(initial_tab_positions_.size())) 707 static_cast<int>(initial_tab_positions_.size()))
694 return; // TODO: should cancel drag if this happens. 708 return; // TODO: should cancel drag if this happens.
695 709
696 int delta = screen_point.x() - start_screen_point_.x(); 710 int delta = screen_point.x() - start_screen_point_.x();
697 attached_tabstrip_->DragActiveTab(initial_tab_positions_, delta); 711 attached_tabstrip_->DragActiveTab(initial_tab_positions_, delta);
698 } 712 }
699 713
714 void DefaultTabDragController::MoveAttachedToNextStackedIndex() {
715 int index = attached_tabstrip_->touch_layout_->active_index();
716 if (index + 1 >= attached_tabstrip_->tab_count())
717 return;
718
719 GetModel(attached_tabstrip_)->MoveSelectedTabsTo(index + 1);
720 StartMoveStackedTimerIfNecessary(kMoveAttachedSubsequentDelay);
721 }
722
723 void DefaultTabDragController::MoveAttachedToPreviousStackedIndex() {
724 int index = attached_tabstrip_->touch_layout_->active_index();
725 if (index <= attached_tabstrip_->GetMiniTabCount())
726 return;
727
728 GetModel(attached_tabstrip_)->MoveSelectedTabsTo(index - 1);
729 StartMoveStackedTimerIfNecessary(kMoveAttachedSubsequentDelay);
730 }
731
700 void DefaultTabDragController::MoveAttached(const gfx::Point& screen_point) { 732 void DefaultTabDragController::MoveAttached(const gfx::Point& screen_point) {
701 DCHECK(attached_tabstrip_); 733 DCHECK(attached_tabstrip_);
702 DCHECK(!view_.get()); 734 DCHECK(!view_.get());
703 735
736 int move_delta = screen_point.x() - last_screen_point_.x();
737 if (move_delta > 0)
738 mouse_move_direction_ |= kMovedMouseRight;
739 else if (move_delta < 0)
740 mouse_move_direction_ |= kMovedMouseLeft;
741 last_screen_point_ = screen_point;
742
704 gfx::Point dragged_view_point = GetAttachedDragPoint(screen_point); 743 gfx::Point dragged_view_point = GetAttachedDragPoint(screen_point);
705 744
706 TabStrip* tab_strip = static_cast<TabStrip*>(attached_tabstrip_);
707
708 // Determine the horizontal move threshold. This is dependent on the width 745 // Determine the horizontal move threshold. This is dependent on the width
709 // of tabs. The smaller the tabs compared to the standard size, the smaller 746 // of tabs. The smaller the tabs compared to the standard size, the smaller
710 // the threshold. 747 // the threshold.
711 double unselected, selected; 748 int threshold = kHorizontalMoveThreshold;
712 tab_strip->GetCurrentTabWidths(&unselected, &selected); 749 if (!attached_tabstrip_->touch_layout_.get()) {
713 double ratio = unselected / Tab::GetStandardSize().width(); 750 double unselected, selected;
714 int threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); 751 attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
752 double ratio = unselected / Tab::GetStandardSize().width();
753 threshold = static_cast<int>(ratio * kHorizontalMoveThreshold);
754 }
755 // else case: touch tabs never shrink.
715 756
716 std::vector<BaseTab*> tabs(drag_data_.size()); 757 std::vector<BaseTab*> tabs(drag_data_.size());
717 for (size_t i = 0; i < drag_data_.size(); ++i) 758 for (size_t i = 0; i < drag_data_.size(); ++i)
718 tabs[i] = drag_data_[i].attached_tab; 759 tabs[i] = drag_data_[i].attached_tab;
719 760
720 bool did_layout = false; 761 bool did_layout = false;
721 // Update the model, moving the WebContents from one index to another. Do this 762 // Update the model, moving the WebContents from one index to another. Do this
722 // only if we have moved a minimum distance since the last reorder (to prevent 763 // only if we have moved a minimum distance since the last reorder (to prevent
723 // jitter) or if this the first move and the tabs are not consecutive. 764 // jitter) or if this the first move and the tabs are not consecutive.
724 if ((abs(MajorAxisValue(screen_point, attached_tabstrip_) - 765 if ((abs(MajorAxisValue(screen_point, attached_tabstrip_) -
725 last_move_screen_loc_) > threshold || 766 last_move_screen_loc_) > threshold ||
726 (initial_move_ && !AreTabsConsecutive()))) { 767 (initial_move_ && !AreTabsConsecutive()))) {
727 TabStripModel* attached_model = GetModel(attached_tabstrip_); 768 TabStripModel* attached_model = GetModel(attached_tabstrip_);
728 gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point); 769 gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point);
729 int to_index = GetInsertionIndexForDraggedBounds(bounds); 770 int to_index = GetInsertionIndexForDraggedBounds(bounds);
730 TabContentsWrapper* last_contents = 771 TabContentsWrapper* last_contents =
731 drag_data_[drag_data_.size() - 1].contents; 772 drag_data_[drag_data_.size() - 1].contents;
732 int index_of_last_item = 773 int index_of_last_item =
733 attached_model->GetIndexOfTabContents(last_contents); 774 attached_model->GetIndexOfTabContents(last_contents);
734 if (initial_move_) { 775 if (initial_move_) {
735 // TabStrip determines if the tabs needs to be animated based on model 776 // TabStrip determines if the tabs needs to be animated based on model
736 // position. This means we need to invoke LayoutDraggedTabsAt before 777 // position. This means we need to invoke LayoutDraggedTabsAt before
737 // changing the model. 778 // changing the model.
738 attached_tabstrip_->LayoutDraggedTabsAt( 779 attached_tabstrip_->LayoutDraggedTabsAt(
739 tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 780 tabs, source_tab_drag_data()->attached_tab, dragged_view_point,
740 initial_move_); 781 initial_move_);
741 did_layout = true; 782 did_layout = true;
742 } 783 }
743 attached_model->MoveSelectedTabsTo(to_index); 784 attached_model->MoveSelectedTabsTo(to_index);
785
744 // Move may do nothing in certain situations (such as when dragging pinned 786 // Move may do nothing in certain situations (such as when dragging pinned
745 // tabs). Make sure the tabstrip actually changed before updating 787 // tabs). Make sure the tabstrip actually changed before updating
746 // last_move_screen_loc_. 788 // last_move_screen_loc_.
747 if (index_of_last_item != 789 if (index_of_last_item !=
748 attached_model->GetIndexOfTabContents(last_contents)) { 790 attached_model->GetIndexOfTabContents(last_contents)) {
749 last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip_); 791 last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip_);
750 } 792 }
751 } 793 }
752 794
753 if (!did_layout) { 795 if (!did_layout) {
754 attached_tabstrip_->LayoutDraggedTabsAt( 796 attached_tabstrip_->LayoutDraggedTabsAt(
755 tabs, source_tab_drag_data()->attached_tab, dragged_view_point, 797 tabs, source_tab_drag_data()->attached_tab, dragged_view_point,
756 initial_move_); 798 initial_move_);
757 } 799 }
758 800
801 StartMoveStackedTimerIfNecessary(kMoveAttachedInitialDelay);
802
759 initial_move_ = false; 803 initial_move_ = false;
760 } 804 }
761 805
762 void DefaultTabDragController::MoveDetached(const gfx::Point& screen_point) { 806 void DefaultTabDragController::MoveDetached(const gfx::Point& screen_point) {
763 DCHECK(!attached_tabstrip_); 807 DCHECK(!attached_tabstrip_);
764 DCHECK(view_.get()); 808 DCHECK(view_.get());
765 809
766 // Move the View. There are no changes to the model if we're detached. 810 // Move the View. There are no changes to the model if we're detached.
767 view_->MoveTo(screen_point); 811 view_->MoveTo(screen_point);
768 } 812 }
769 813
814 void DefaultTabDragController::StartMoveStackedTimerIfNecessary(int delay_ms) {
815 DCHECK(attached_tabstrip_);
816
817 TouchTabStripLayout* touch_layout = attached_tabstrip_->touch_layout_.get();
818 if (!touch_layout)
819 return;
820
821 gfx::Point screen_point = GetCursorScreenPoint();
822 gfx::Point dragged_view_point = GetAttachedDragPoint(screen_point);
823 gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point);
824 int index = touch_layout->active_index();
825 if (ShouldDragToNextStackedTab(bounds, index)) {
826 move_stacked_timer_.Start(
827 FROM_HERE,
828 base::TimeDelta::FromMilliseconds(delay_ms), this,
829 &DefaultTabDragController::MoveAttachedToNextStackedIndex);
830 } else if (ShouldDragToPreviousStackedTab(bounds, index)) {
831 move_stacked_timer_.Start(
832 FROM_HERE,
833 base::TimeDelta::FromMilliseconds(delay_ms), this,
834 &DefaultTabDragController::MoveAttachedToPreviousStackedIndex);
835 }
836 }
837
770 DockInfo DefaultTabDragController::GetDockInfoAtPoint( 838 DockInfo DefaultTabDragController::GetDockInfoAtPoint(
771 const gfx::Point& screen_point) { 839 const gfx::Point& screen_point) {
772 if (attached_tabstrip_) { 840 if (attached_tabstrip_) {
773 // If the mouse is over a tab strip, don't offer a dock position. 841 // If the mouse is over a tab strip, don't offer a dock position.
774 return DockInfo(); 842 return DockInfo();
775 } 843 }
776 844
777 if (dock_info_.IsValidForPoint(screen_point)) { 845 if (dock_info_.IsValidForPoint(screen_point)) {
778 // It's possible any given screen coordinate has multiple docking 846 // It's possible any given screen coordinate has multiple docking
779 // positions. Check the current info first to avoid having the docking 847 // positions. Check the current info first to avoid having the docking
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 gfx::Point tab_strip_point(screen_point); 948 gfx::Point tab_strip_point(screen_point);
881 views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_strip_point); 949 views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_strip_point);
882 tab_strip_point.set_x( 950 tab_strip_point.set_x(
883 attached_tabstrip_->GetMirroredXInView(tab_strip_point.x())); 951 attached_tabstrip_->GetMirroredXInView(tab_strip_point.x()));
884 tab_strip_point.Offset(-mouse_offset_.x(), -mouse_offset_.y()); 952 tab_strip_point.Offset(-mouse_offset_.x(), -mouse_offset_.y());
885 gfx::Rect bounds = GetDraggedViewTabStripBounds(tab_strip_point); 953 gfx::Rect bounds = GetDraggedViewTabStripBounds(tab_strip_point);
886 int index = GetInsertionIndexForDraggedBounds(bounds); 954 int index = GetInsertionIndexForDraggedBounds(bounds);
887 attached_tabstrip_->set_attaching_dragged_tab(true); 955 attached_tabstrip_->set_attaching_dragged_tab(true);
888 for (size_t i = 0; i < drag_data_.size(); ++i) { 956 for (size_t i = 0; i < drag_data_.size(); ++i) {
889 int add_types = TabStripModel::ADD_NONE; 957 int add_types = TabStripModel::ADD_NONE;
958 if (attached_tabstrip_->touch_layout_.get()) {
959 // TouchTabStripLayout positions relative to the active tab, if we don't
960 // add the tab as active things bounce around.
961 DCHECK_EQ(1u, drag_data_.size());
962 add_types |= TabStripModel::ADD_ACTIVE;
963 }
890 if (drag_data_[i].pinned) 964 if (drag_data_[i].pinned)
891 add_types |= TabStripModel::ADD_PINNED; 965 add_types |= TabStripModel::ADD_PINNED;
892 GetModel(attached_tabstrip_)->InsertTabContentsAt( 966 GetModel(attached_tabstrip_)->InsertTabContentsAt(
893 index + i, drag_data_[i].contents, add_types); 967 index + i, drag_data_[i].contents, add_types);
894 } 968 }
895 attached_tabstrip_->set_attaching_dragged_tab(false); 969 attached_tabstrip_->set_attaching_dragged_tab(false);
896 970
897 tabs = GetTabsMatchingDraggedContents(attached_tabstrip_); 971 tabs = GetTabsMatchingDraggedContents(attached_tabstrip_);
898 } 972 }
899 DCHECK_EQ(tabs.size(), drag_data_.size()); 973 DCHECK_EQ(tabs.size(), drag_data_.size());
(...skipping 13 matching lines...) Expand all
913 tabs[source_tab_index_]->width() + 987 tabs[source_tab_index_]->width() +
914 static_cast<int>(offset_to_width_ratio_ * 988 static_cast<int>(offset_to_width_ratio_ *
915 tabs[source_tab_index_]->width()); 989 tabs[source_tab_index_]->width());
916 mouse_offset_.set_x(new_x); 990 mouse_offset_.set_x(new_x);
917 991
918 // Move the corresponding window to the front. 992 // Move the corresponding window to the front.
919 attached_tabstrip_->GetWidget()->Activate(); 993 attached_tabstrip_->GetWidget()->Activate();
920 } 994 }
921 995
922 void DefaultTabDragController::Detach() { 996 void DefaultTabDragController::Detach() {
997 mouse_move_direction_ = kMovedMouseLeft | kMovedMouseRight;
998
923 // Prevent the WebContents HWND from being hidden by any of the model 999 // Prevent the WebContents HWND from being hidden by any of the model
924 // operations performed during the drag. 1000 // operations performed during the drag.
925 source_dragged_contents()->web_contents()->SetCapturingContents(true); 1001 source_dragged_contents()->web_contents()->SetCapturingContents(true);
926 1002
927 // Calculate the drag bounds. 1003 // Calculate the drag bounds.
928 std::vector<gfx::Rect> drag_bounds; 1004 std::vector<gfx::Rect> drag_bounds;
929 std::vector<BaseTab*> attached_tabs; 1005 std::vector<BaseTab*> attached_tabs;
930 for (size_t i = 0; i < drag_data_.size(); ++i) 1006 for (size_t i = 0; i < drag_data_.size(); ++i)
931 attached_tabs.push_back(drag_data_[i].attached_tab); 1007 attached_tabs.push_back(drag_data_[i].attached_tab);
932 attached_tabstrip_->CalculateBoundsForDraggedTabs(attached_tabs, 1008 attached_tabstrip_->CalculateBoundsForDraggedTabs(attached_tabs,
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 attached_model->SetSelectionFromModel(selection_model); 1054 attached_model->SetSelectionFromModel(selection_model);
979 } 1055 }
980 1056
981 // Create the dragged view. 1057 // Create the dragged view.
982 CreateDraggedView(tab_data, drag_bounds); 1058 CreateDraggedView(tab_data, drag_bounds);
983 1059
984 attached_tabstrip_->DraggedTabsDetached(); 1060 attached_tabstrip_->DraggedTabsDetached();
985 attached_tabstrip_ = NULL; 1061 attached_tabstrip_ = NULL;
986 } 1062 }
987 1063
1064 int DefaultTabDragController::GetInsertionIndexFrom(
1065 const gfx::Rect& dragged_bounds,
1066 int start,
1067 int delta) const {
1068 for (int i = start, tab_count = attached_tabstrip_->tab_count();
1069 i >= 0 && i < tab_count; i += delta) {
1070 const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i);
1071 gfx::Rect left_half, right_half;
1072 ideal_bounds.SplitVertically(&left_half, &right_half);
1073 if (dragged_bounds.x() >= right_half.x() &&
1074 dragged_bounds.x() < right_half.right()) {
1075 return i + 1;
1076 } else if (dragged_bounds.x() >= left_half.x() &&
1077 dragged_bounds.x() < left_half.right()) {
1078 return i;
1079 }
1080 }
1081 return -1;
1082 }
1083
988 int DefaultTabDragController::GetInsertionIndexForDraggedBounds( 1084 int DefaultTabDragController::GetInsertionIndexForDraggedBounds(
989 const gfx::Rect& dragged_bounds) const { 1085 const gfx::Rect& dragged_bounds) const {
990 int right_tab_x = 0;
991 int index = -1; 1086 int index = -1;
992 for (int i = 0; i < attached_tabstrip_->tab_count(); ++i) { 1087 if (attached_tabstrip_->touch_layout_.get()) {
993 const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); 1088 index = GetInsertionIndexForDraggedBoundsStacked(dragged_bounds);
994 gfx::Rect left_half, right_half; 1089 if (index != -1) {
995 ideal_bounds.SplitVertically(&left_half, &right_half); 1090 // Only move the tab to the left/right if the user actually moved the
996 right_tab_x = right_half.right(); 1091 // mouse that way. This is necessary as tabs with stacked tabs
997 if (dragged_bounds.x() >= right_half.x() && 1092 // before/after them have multiple drag positions.
998 dragged_bounds.x() < right_half.right()) { 1093 int active_index = attached_tabstrip_->touch_layout_->active_index();
999 index = i + 1; 1094 if ((index < active_index &&
1000 break; 1095 (mouse_move_direction_ & kMovedMouseLeft) == 0) ||
1001 } else if (dragged_bounds.x() >= left_half.x() && 1096 (index > active_index &&
1002 dragged_bounds.x() < left_half.right()) { 1097 (mouse_move_direction_ & kMovedMouseRight) == 0)) {
1003 index = i; 1098 index = active_index;
1004 break; 1099 }
1005 } 1100 }
1101 } else {
1102 index = GetInsertionIndexFrom(dragged_bounds, 0, 1);
1006 } 1103 }
1007 if (index == -1) { 1104 if (index == -1) {
1105 int tab_count = attached_tabstrip_->tab_count();
1106 int right_tab_x = tab_count == 0 ? 0 :
1107 attached_tabstrip_->ideal_bounds(tab_count - 1).right();
1008 if (dragged_bounds.right() > right_tab_x) { 1108 if (dragged_bounds.right() > right_tab_x) {
1009 index = GetModel(attached_tabstrip_)->count(); 1109 index = GetModel(attached_tabstrip_)->count();
1010 } else { 1110 } else {
1011 index = 0; 1111 index = 0;
1012 } 1112 }
1013 } 1113 }
1014 1114
1015 if (!drag_data_[0].attached_tab) { 1115 if (!drag_data_[0].attached_tab) {
1016 // If 'attached_tab' is NULL, it means we're in the process of attaching and 1116 // If 'attached_tab' is NULL, it means we're in the process of attaching and
1017 // don't need to constrain the index. 1117 // don't need to constrain the index.
1018 return index; 1118 return index;
1019 } 1119 }
1020 1120
1021 int max_index = GetModel(attached_tabstrip_)->count() - 1121 int max_index = GetModel(attached_tabstrip_)->count() -
1022 static_cast<int>(drag_data_.size()); 1122 static_cast<int>(drag_data_.size());
1023 return std::max(0, std::min(max_index, index)); 1123 return std::max(0, std::min(max_index, index));
1024 } 1124 }
1025 1125
1126 bool DefaultTabDragController::ShouldDragToNextStackedTab(
1127 const gfx::Rect& dragged_bounds,
1128 int index) const {
1129 if (index + 1 >= attached_tabstrip_->tab_count() ||
1130 !attached_tabstrip_->touch_layout_->IsStacked(index + 1) ||
1131 (mouse_move_direction_ & kMovedMouseRight) == 0)
1132 return false;
1133
1134 int active_x = attached_tabstrip_->ideal_bounds(index).x();
1135 int next_x = attached_tabstrip_->ideal_bounds(index + 1).x();
1136 int mid_x = std::min(next_x - kStackedDistance,
1137 active_x + (next_x - active_x) / 4);
1138 return dragged_bounds.x() >= mid_x;
1139 }
1140
1141 bool DefaultTabDragController::ShouldDragToPreviousStackedTab(
1142 const gfx::Rect& dragged_bounds,
1143 int index) const {
1144 if (index - 1 < attached_tabstrip_->GetMiniTabCount() ||
1145 !attached_tabstrip_->touch_layout_->IsStacked(index - 1) ||
1146 (mouse_move_direction_ & kMovedMouseLeft) == 0)
1147 return false;
1148
1149 int active_x = attached_tabstrip_->ideal_bounds(index).x();
1150 int previous_x = attached_tabstrip_->ideal_bounds(index - 1).x();
1151 int mid_x = std::max(previous_x + kStackedDistance,
1152 active_x - (active_x - previous_x) / 4);
1153 return dragged_bounds.x() <= mid_x;
1154 }
1155
1156 int DefaultTabDragController::GetInsertionIndexForDraggedBoundsStacked(
1157 const gfx::Rect& dragged_bounds) const {
1158 TouchTabStripLayout* touch_layout = attached_tabstrip_->touch_layout_.get();
1159 int active_index = touch_layout->active_index();
1160 // Search from the active index to the front of the tabstrip. Do this as tabs
1161 // overlap each other from the active index.
1162 int index = GetInsertionIndexFrom(dragged_bounds, active_index, -1);
1163 if (index != active_index)
1164 return index;
1165 if (index == -1)
1166 return GetInsertionIndexFrom(dragged_bounds, active_index + 1, 1);
1167
1168 // The position to drag to corresponds to the active tab. If the next/previous
1169 // tab is stacked, then shorten the distance used to determine insertion
1170 // bounds. We do this as GetInsertionIndexFrom() uses the bounds of the
1171 // tabs. When tabs are stacked the next/previous tab is on top of the tab.
1172 if (active_index + 1 < attached_tabstrip_->tab_count() &&
1173 touch_layout->IsStacked(active_index + 1)) {
1174 index = GetInsertionIndexFrom(dragged_bounds, active_index + 1, 1);
1175 if (index == -1 && ShouldDragToNextStackedTab(dragged_bounds, active_index))
1176 index = active_index + 1;
1177 else if (index == -1)
1178 index = active_index;
1179 } else if (ShouldDragToPreviousStackedTab(dragged_bounds, active_index)) {
1180 index = active_index - 1;
1181 }
1182 return index;
1183 }
1184
1026 gfx::Rect DefaultTabDragController::GetDraggedViewTabStripBounds( 1185 gfx::Rect DefaultTabDragController::GetDraggedViewTabStripBounds(
1027 const gfx::Point& tab_strip_point) { 1186 const gfx::Point& tab_strip_point) {
1028 // attached_tab is NULL when inserting into a new tabstrip. 1187 // attached_tab is NULL when inserting into a new tabstrip.
1029 if (source_tab_drag_data()->attached_tab) { 1188 if (source_tab_drag_data()->attached_tab) {
1030 return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 1189 return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(),
1031 source_tab_drag_data()->attached_tab->width(), 1190 source_tab_drag_data()->attached_tab->width(),
1032 source_tab_drag_data()->attached_tab->height()); 1191 source_tab_drag_data()->attached_tab->height());
1033 } 1192 }
1034 1193
1035 double sel_width, unselected_width; 1194 double sel_width, unselected_width;
1036 static_cast<TabStrip*>(attached_tabstrip_)->GetCurrentTabWidths( 1195 static_cast<TabStrip*>(attached_tabstrip_)->GetCurrentTabWidths(
1037 &sel_width, &unselected_width); 1196 &sel_width, &unselected_width);
1038 return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(), 1197 return gfx::Rect(tab_strip_point.x(), tab_strip_point.y(),
1039 static_cast<int>(sel_width), 1198 static_cast<int>(sel_width),
1040 Tab::GetStandardSize().height()); 1199 Tab::GetStandardSize().height());
1041 } 1200 }
1042 1201
1043 gfx::Point DefaultTabDragController::GetAttachedDragPoint( 1202 gfx::Point DefaultTabDragController::GetAttachedDragPoint(
1044 const gfx::Point& screen_point) { 1203 const gfx::Point& screen_point) {
1045 DCHECK(attached_tabstrip_); // The tab must be attached. 1204 DCHECK(attached_tabstrip_); // The tab must be attached.
1046 1205
1047 gfx::Point tab_loc(screen_point); 1206 gfx::Point tab_loc(screen_point);
1048 views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_loc); 1207 views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_loc);
1049 int x = 1208 int x =
1050 attached_tabstrip_->GetMirroredXInView(tab_loc.x()) - mouse_offset_.x(); 1209 attached_tabstrip_->GetMirroredXInView(tab_loc.x()) - mouse_offset_.x();
1051 int y = tab_loc.y() - mouse_offset_.y();
1052 1210
1053 // TODO: consider caching this. 1211 // TODO: consider caching this.
1054 std::vector<BaseTab*> attached_tabs; 1212 std::vector<BaseTab*> attached_tabs;
1055 for (size_t i = 0; i < drag_data_.size(); ++i) 1213 for (size_t i = 0; i < drag_data_.size(); ++i)
1056 attached_tabs.push_back(drag_data_[i].attached_tab); 1214 attached_tabs.push_back(drag_data_[i].attached_tab);
1057
1058 int size = attached_tabstrip_->GetSizeNeededForTabs(attached_tabs); 1215 int size = attached_tabstrip_->GetSizeNeededForTabs(attached_tabs);
1059
1060 int max_x = attached_tabstrip_->width() - size; 1216 int max_x = attached_tabstrip_->width() - size;
1061 x = std::min(std::max(x, 0), max_x); 1217 return gfx::Point(std::min(std::max(x, 0), max_x), 0);
1062 y = 0;
1063 return gfx::Point(x, y);
1064 } 1218 }
1065 1219
1066 std::vector<BaseTab*> DefaultTabDragController::GetTabsMatchingDraggedContents( 1220 std::vector<BaseTab*> DefaultTabDragController::GetTabsMatchingDraggedContents(
1067 TabStrip* tabstrip) { 1221 TabStrip* tabstrip) {
1068 TabStripModel* model = GetModel(attached_tabstrip_); 1222 TabStripModel* model = GetModel(attached_tabstrip_);
1069 std::vector<BaseTab*> tabs; 1223 std::vector<BaseTab*> tabs;
1070 for (size_t i = 0; i < drag_data_.size(); ++i) { 1224 for (size_t i = 0; i < drag_data_.size(); ++i) {
1071 int model_index = model->GetIndexOfTabContents(drag_data_[i].contents); 1225 int model_index = model->GetIndexOfTabContents(drag_data_[i].contents);
1072 if (model_index == TabStripModel::kNoTab) 1226 if (model_index == TabStripModel::kNoTab)
1073 return std::vector<BaseTab*>(); 1227 return std::vector<BaseTab*>();
1074 tabs.push_back(tabstrip->tab_at(model_index)); 1228 tabs.push_back(tabstrip->tab_at(model_index));
1075 } 1229 }
1076 return tabs; 1230 return tabs;
1077 } 1231 }
1078 1232
1079 void DefaultTabDragController::EndDragImpl(EndDragType type) { 1233 void DefaultTabDragController::EndDragImpl(EndDragType type) {
1080 active_ = false; 1234 active_ = false;
1081 1235
1082 bring_to_front_timer_.Stop(); 1236 bring_to_front_timer_.Stop();
1237 move_stacked_timer_.Stop();
1083 1238
1084 // Hide the current dock controllers. 1239 // Hide the current dock controllers.
1085 for (size_t i = 0; i < dock_controllers_.size(); ++i) { 1240 for (size_t i = 0; i < dock_controllers_.size(); ++i) {
1086 // Be sure and clear the controller first, that way if Hide ends up 1241 // Be sure and clear the controller first, that way if Hide ends up
1087 // deleting the controller it won't call us back. 1242 // deleting the controller it won't call us back.
1088 dock_controllers_[i]->clear_controller(); 1243 dock_controllers_[i]->clear_controller();
1089 dock_controllers_[i]->Hide(); 1244 dock_controllers_[i]->Hide();
1090 } 1245 }
1091 dock_controllers_.clear(); 1246 dock_controllers_.clear();
1092 dock_windows_.clear(); 1247 dock_windows_.clear();
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 } 1644 }
1490 1645
1491 // static 1646 // static
1492 bool TabDragController::IsActive() { 1647 bool TabDragController::IsActive() {
1493 #if defined(USE_AURA) || defined(OS_WIN) 1648 #if defined(USE_AURA) || defined(OS_WIN)
1494 return TabDragController2::IsActive() || (instance_ && instance_->active()); 1649 return TabDragController2::IsActive() || (instance_ && instance_->active());
1495 #else 1650 #else
1496 return instance_ && instance_->active(); 1651 return instance_ && instance_->active();
1497 #endif 1652 #endif
1498 } 1653 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/default_tab_drag_controller.h ('k') | chrome/browser/ui/views/tabs/tab_strip.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698