OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |