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/tab_drag_controller.h" | 5 #include "chrome/browser/ui/views/tabs/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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 | 199 |
200 bool ShouldDetachIntoNewBrowser() { | 200 bool ShouldDetachIntoNewBrowser() { |
201 #if defined(USE_AURA) | 201 #if defined(USE_AURA) |
202 return true; | 202 return true; |
203 #else | 203 #else |
204 return CommandLine::ForCurrentProcess()->HasSwitch( | 204 return CommandLine::ForCurrentProcess()->HasSwitch( |
205 switches::kTabBrowserDragging); | 205 switches::kTabBrowserDragging); |
206 #endif | 206 #endif |
207 } | 207 } |
208 | 208 |
| 209 // Returns true if |bounds| contains the y-coordinate |y|. The y-coordinate |
| 210 // of |bounds| is adjusted by |vertical_adjustment|. |
| 211 bool DoesRectContainVerticalPointExpanded( |
| 212 const gfx::Rect& bounds, |
| 213 int vertical_adjustment, |
| 214 int y) { |
| 215 int upper_threshold = bounds.bottom() + vertical_adjustment; |
| 216 int lower_threshold = bounds.y() - vertical_adjustment; |
| 217 return y >= lower_threshold && y <= upper_threshold; |
| 218 } |
| 219 |
209 } // namespace | 220 } // namespace |
210 | 221 |
211 /////////////////////////////////////////////////////////////////////////////// | 222 /////////////////////////////////////////////////////////////////////////////// |
212 // DockDisplayer | 223 // DockDisplayer |
213 | 224 |
214 // DockDisplayer is responsible for giving the user a visual indication of a | 225 // DockDisplayer is responsible for giving the user a visual indication of a |
215 // possible dock position (as represented by DockInfo). DockDisplayer shows | 226 // possible dock position (as represented by DockInfo). DockDisplayer shows |
216 // a window with a DockView in it. Two animations are used that correspond to | 227 // a window with a DockView in it. Two animations are used that correspond to |
217 // the state of DockInfo::in_enable_area. | 228 // the state of DockInfo::in_enable_area. |
218 class TabDragController::DockDisplayer : public ui::AnimationDelegate { | 229 class TabDragController::DockDisplayer : public ui::AnimationDelegate { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 attached_tab(NULL), | 331 attached_tab(NULL), |
321 pinned(false) { | 332 pinned(false) { |
322 } | 333 } |
323 | 334 |
324 TabDragController::TabDragData::~TabDragData() { | 335 TabDragController::TabDragData::~TabDragData() { |
325 } | 336 } |
326 | 337 |
327 /////////////////////////////////////////////////////////////////////////////// | 338 /////////////////////////////////////////////////////////////////////////////// |
328 // TabDragController, public: | 339 // TabDragController, public: |
329 | 340 |
| 341 // static |
| 342 const int TabDragController::kTouchVerticalDetachMagnetism = 50; |
| 343 |
| 344 // static |
| 345 const int TabDragController::kVerticalDetachMagnetism = 15; |
| 346 |
330 TabDragController::TabDragController() | 347 TabDragController::TabDragController() |
331 : detach_into_browser_(ShouldDetachIntoNewBrowser()), | 348 : detach_into_browser_(ShouldDetachIntoNewBrowser()), |
332 source_tabstrip_(NULL), | 349 source_tabstrip_(NULL), |
333 attached_tabstrip_(NULL), | 350 attached_tabstrip_(NULL), |
334 source_tab_offset_(0), | 351 source_tab_offset_(0), |
335 offset_to_width_ratio_(0), | 352 offset_to_width_ratio_(0), |
336 old_focused_view_(NULL), | 353 old_focused_view_(NULL), |
337 last_move_screen_loc_(0), | 354 last_move_screen_loc_(0), |
338 started_drag_(false), | 355 started_drag_(false), |
339 active_(true), | 356 active_(true), |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x()); | 734 int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x()); |
718 int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y()); | 735 int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y()); |
719 return sqrt(pow(static_cast<float>(x_offset), 2) + | 736 return sqrt(pow(static_cast<float>(x_offset), 2) + |
720 pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; | 737 pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; |
721 } | 738 } |
722 | 739 |
723 void TabDragController::ContinueDragging(const gfx::Point& point_in_screen) { | 740 void TabDragController::ContinueDragging(const gfx::Point& point_in_screen) { |
724 DCHECK(!detach_into_browser_ || attached_tabstrip_); | 741 DCHECK(!detach_into_browser_ || attached_tabstrip_); |
725 | 742 |
726 TabStrip* target_tabstrip = detach_behavior_ == DETACHABLE ? | 743 TabStrip* target_tabstrip = detach_behavior_ == DETACHABLE ? |
727 GetTabStripForPoint(point_in_screen) : source_tabstrip_; | 744 GetTargetTabStripForPoint(point_in_screen) : source_tabstrip_; |
728 bool tab_strip_changed = (target_tabstrip != attached_tabstrip_); | 745 bool tab_strip_changed = (target_tabstrip != attached_tabstrip_); |
729 | 746 |
730 if (attached_tabstrip_) { | 747 if (attached_tabstrip_) { |
731 int move_delta = point_in_screen.x() - last_point_in_screen_.x(); | 748 int move_delta = point_in_screen.x() - last_point_in_screen_.x(); |
732 if (move_delta > 0) | 749 if (move_delta > 0) |
733 mouse_move_direction_ |= kMovedMouseRight; | 750 mouse_move_direction_ |= kMovedMouseRight; |
734 else if (move_delta < 0) | 751 else if (move_delta < 0) |
735 mouse_move_direction_ |= kMovedMouseLeft; | 752 mouse_move_direction_ |= kMovedMouseLeft; |
736 } | 753 } |
737 last_point_in_screen_ = point_in_screen; | 754 last_point_in_screen_ = point_in_screen; |
(...skipping 15 matching lines...) Expand all Loading... |
753 base::TimeDelta::FromMilliseconds(kBringToFrontDelay), | 770 base::TimeDelta::FromMilliseconds(kBringToFrontDelay), |
754 base::Bind(&TabDragController::BringWindowUnderPointToFront, | 771 base::Bind(&TabDragController::BringWindowUnderPointToFront, |
755 base::Unretained(this), point_in_screen)); | 772 base::Unretained(this), point_in_screen)); |
756 } | 773 } |
757 | 774 |
758 UpdateDockInfo(point_in_screen); | 775 UpdateDockInfo(point_in_screen); |
759 | 776 |
760 if (!is_dragging_window_) { | 777 if (!is_dragging_window_) { |
761 if (attached_tabstrip_) { | 778 if (attached_tabstrip_) { |
762 if (move_only()) { | 779 if (move_only()) { |
763 DragActiveTabStacked(point_in_screen); | 780 if (attached_tabstrip_->touch_layout_.get()) |
| 781 DragActiveTabStacked(point_in_screen); |
764 } else { | 782 } else { |
765 MoveAttached(point_in_screen); | 783 MoveAttached(point_in_screen); |
766 if (tab_strip_changed) { | 784 if (tab_strip_changed) { |
767 // Move the corresponding window to the front. We do this after the | 785 // Move the corresponding window to the front. We do this after the |
768 // move as on windows activate triggers a synchronous paint. | 786 // move as on windows activate triggers a synchronous paint. |
769 attached_tabstrip_->GetWidget()->Activate(); | 787 attached_tabstrip_->GetWidget()->Activate(); |
770 } | 788 } |
771 } | 789 } |
772 } else { | 790 } else { |
773 MoveDetached(point_in_screen); | 791 MoveDetached(point_in_screen); |
(...skipping 18 matching lines...) Expand all Loading... |
792 move_loop_widget_ = NULL; | 810 move_loop_widget_ = NULL; |
793 #endif | 811 #endif |
794 views::Widget* browser_widget = GetAttachedBrowserWidget(); | 812 views::Widget* browser_widget = GetAttachedBrowserWidget(); |
795 // Need to release the drag controller before starting the move loop as it's | 813 // Need to release the drag controller before starting the move loop as it's |
796 // going to trigger capture lost, which cancels drag. | 814 // going to trigger capture lost, which cancels drag. |
797 attached_tabstrip_->ReleaseDragController(); | 815 attached_tabstrip_->ReleaseDragController(); |
798 target_tabstrip->OwnDragController(this); | 816 target_tabstrip->OwnDragController(this); |
799 // Disable animations so that we don't see a close animation on aero. | 817 // Disable animations so that we don't see a close animation on aero. |
800 browser_widget->SetVisibilityChangedAnimationsEnabled(false); | 818 browser_widget->SetVisibilityChangedAnimationsEnabled(false); |
801 // For aura we can't release capture, otherwise it'll cancel a gesture. | 819 // For aura we can't release capture, otherwise it'll cancel a gesture. |
802 // Insteat we have to directly change capture. | 820 // Instead we have to directly change capture. |
803 #if !defined(USE_ASH) | 821 #if !defined(USE_ASH) |
804 browser_widget->ReleaseCapture(); | 822 browser_widget->ReleaseCapture(); |
805 #else | 823 #else |
806 attached_tabstrip_->ReleaseDragController(); | 824 attached_tabstrip_->ReleaseDragController(); |
807 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); | 825 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); |
808 #endif | 826 #endif |
809 // EndMoveLoop is going to snap the window back to its original location. | 827 // EndMoveLoop is going to snap the window back to its original location. |
810 // Hide it so users don't see this. | 828 // Hide it so users don't see this. |
811 browser_widget->Hide(); | 829 browser_widget->Hide(); |
812 browser_widget->EndMoveLoop(); | 830 browser_widget->EndMoveLoop(); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 return dock_info_; | 1015 return dock_info_; |
998 } | 1016 } |
999 | 1017 |
1000 gfx::NativeView dragged_view = view_->GetWidget()->GetNativeView(); | 1018 gfx::NativeView dragged_view = view_->GetWidget()->GetNativeView(); |
1001 dock_windows_.insert(dragged_view); | 1019 dock_windows_.insert(dragged_view); |
1002 DockInfo info = DockInfo::GetDockInfoAtPoint(point_in_screen, dock_windows_); | 1020 DockInfo info = DockInfo::GetDockInfoAtPoint(point_in_screen, dock_windows_); |
1003 dock_windows_.erase(dragged_view); | 1021 dock_windows_.erase(dragged_view); |
1004 return info; | 1022 return info; |
1005 } | 1023 } |
1006 | 1024 |
1007 TabStrip* TabDragController::GetTabStripForPoint( | 1025 TabStrip* TabDragController::GetTargetTabStripForPoint( |
1008 const gfx::Point& point_in_screen) { | 1026 const gfx::Point& point_in_screen) { |
| 1027 if (move_only() && attached_tabstrip_) { |
| 1028 DCHECK_EQ(DETACHABLE, detach_behavior_); |
| 1029 // move_only() is intended for touch, in which case we only want to detach |
| 1030 // if the touch point moves significantly in the vertical distance. |
| 1031 gfx::Rect tabstrip_bounds = GetViewScreenBounds(attached_tabstrip_); |
| 1032 if (DoesRectContainVerticalPointExpanded(tabstrip_bounds, |
| 1033 kTouchVerticalDetachMagnetism, |
| 1034 point_in_screen.y())) |
| 1035 return attached_tabstrip_; |
| 1036 } |
1009 gfx::NativeView dragged_view = NULL; | 1037 gfx::NativeView dragged_view = NULL; |
1010 if (view_.get()) | 1038 if (view_.get()) |
1011 dragged_view = view_->GetWidget()->GetNativeView(); | 1039 dragged_view = view_->GetWidget()->GetNativeView(); |
1012 else if (is_dragging_window_) | 1040 else if (is_dragging_window_) |
1013 dragged_view = attached_tabstrip_->GetWidget()->GetNativeView(); | 1041 dragged_view = attached_tabstrip_->GetWidget()->GetNativeView(); |
1014 if (dragged_view) | 1042 if (dragged_view) |
1015 dock_windows_.insert(dragged_view); | 1043 dock_windows_.insert(dragged_view); |
1016 gfx::NativeWindow local_window = | 1044 gfx::NativeWindow local_window = |
1017 DockInfo::GetLocalProcessWindowAtPoint(point_in_screen, dock_windows_); | 1045 DockInfo::GetLocalProcessWindowAtPoint(point_in_screen, dock_windows_); |
1018 if (dragged_view) | 1046 if (dragged_view) |
(...skipping 20 matching lines...) Expand all Loading... |
1039 attached_tabstrip_ ? attached_tabstrip_ : source_tabstrip_; | 1067 attached_tabstrip_ ? attached_tabstrip_ : source_tabstrip_; |
1040 DCHECK(tab_strip); | 1068 DCHECK(tab_strip); |
1041 | 1069 |
1042 return other_tabstrip->controller()->IsCompatibleWith(tab_strip) ? | 1070 return other_tabstrip->controller()->IsCompatibleWith(tab_strip) ? |
1043 other_tabstrip : NULL; | 1071 other_tabstrip : NULL; |
1044 } | 1072 } |
1045 | 1073 |
1046 bool TabDragController::DoesTabStripContain( | 1074 bool TabDragController::DoesTabStripContain( |
1047 TabStrip* tabstrip, | 1075 TabStrip* tabstrip, |
1048 const gfx::Point& point_in_screen) const { | 1076 const gfx::Point& point_in_screen) const { |
1049 static const int kVerticalDetachMagnetism = 15; | |
1050 // Make sure the specified screen point is actually within the bounds of the | 1077 // Make sure the specified screen point is actually within the bounds of the |
1051 // specified tabstrip... | 1078 // specified tabstrip... |
1052 gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); | 1079 gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); |
1053 if (point_in_screen.x() < tabstrip_bounds.right() && | 1080 return point_in_screen.x() < tabstrip_bounds.right() && |
1054 point_in_screen.x() >= tabstrip_bounds.x()) { | 1081 point_in_screen.x() >= tabstrip_bounds.x() && |
1055 // TODO(beng): make this be relative to the start position of the mouse | 1082 DoesRectContainVerticalPointExpanded(tabstrip_bounds, |
1056 // for the source TabStrip. | 1083 kVerticalDetachMagnetism, |
1057 int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism; | 1084 point_in_screen.y()); |
1058 int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism; | |
1059 return point_in_screen.y() >= lower_threshold && | |
1060 point_in_screen.y() <= upper_threshold; | |
1061 } | |
1062 return false; | |
1063 } | 1085 } |
1064 | 1086 |
1065 void TabDragController::Attach(TabStrip* attached_tabstrip, | 1087 void TabDragController::Attach(TabStrip* attached_tabstrip, |
1066 const gfx::Point& point_in_screen) { | 1088 const gfx::Point& point_in_screen) { |
1067 DCHECK(!attached_tabstrip_); // We should already have detached by the time | 1089 DCHECK(!attached_tabstrip_); // We should already have detached by the time |
1068 // we get here. | 1090 // we get here. |
1069 | 1091 |
1070 attached_tabstrip_ = attached_tabstrip; | 1092 attached_tabstrip_ = attached_tabstrip; |
1071 | 1093 |
1072 // And we don't need the dragged view. | 1094 // And we don't need the dragged view. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 // Redirect all mouse events to the TabStrip so that the tab that originated | 1176 // Redirect all mouse events to the TabStrip so that the tab that originated |
1155 // the drag can safely be deleted. | 1177 // the drag can safely be deleted. |
1156 if (detach_into_browser_ || attached_tabstrip_ == source_tabstrip_) { | 1178 if (detach_into_browser_ || attached_tabstrip_ == source_tabstrip_) { |
1157 static_cast<views::internal::RootView*>( | 1179 static_cast<views::internal::RootView*>( |
1158 attached_tabstrip_->GetWidget()->GetRootView())->SetMouseHandler( | 1180 attached_tabstrip_->GetWidget()->GetRootView())->SetMouseHandler( |
1159 attached_tabstrip_); | 1181 attached_tabstrip_); |
1160 } | 1182 } |
1161 } | 1183 } |
1162 | 1184 |
1163 void TabDragController::Detach(ReleaseCapture release_capture) { | 1185 void TabDragController::Detach(ReleaseCapture release_capture) { |
| 1186 // When the user detaches we assume they want to reorder. |
| 1187 move_behavior_ = REORDER; |
| 1188 |
1164 // Release ownership of the drag controller and mouse capture. When we | 1189 // Release ownership of the drag controller and mouse capture. When we |
1165 // reattach ownership is transfered. | 1190 // reattach ownership is transfered. |
1166 if (detach_into_browser_) { | 1191 if (detach_into_browser_) { |
1167 attached_tabstrip_->ReleaseDragController(); | 1192 attached_tabstrip_->ReleaseDragController(); |
1168 if (release_capture == RELEASE_CAPTURE) | 1193 if (release_capture == RELEASE_CAPTURE) |
1169 attached_tabstrip_->GetWidget()->ReleaseCapture(); | 1194 attached_tabstrip_->GetWidget()->ReleaseCapture(); |
1170 } | 1195 } |
1171 | 1196 |
1172 mouse_move_direction_ = kMovedMouseLeft | kMovedMouseRight; | 1197 mouse_move_direction_ = kMovedMouseLeft | kMovedMouseRight; |
1173 | 1198 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 attached_tabstrip_->SetTabBoundsForDrag(drag_bounds); | 1291 attached_tabstrip_->SetTabBoundsForDrag(drag_bounds); |
1267 | 1292 |
1268 browser->window()->Show(); | 1293 browser->window()->Show(); |
1269 browser->window()->Activate(); | 1294 browser->window()->Activate(); |
1270 dragged_browser_view->GetWidget()->SetVisibilityChangedAnimationsEnabled( | 1295 dragged_browser_view->GetWidget()->SetVisibilityChangedAnimationsEnabled( |
1271 true); | 1296 true); |
1272 RunMoveLoop(); | 1297 RunMoveLoop(); |
1273 } | 1298 } |
1274 | 1299 |
1275 void TabDragController::RunMoveLoop() { | 1300 void TabDragController::RunMoveLoop() { |
| 1301 // If the user drags the whole window we'll assume they are going to attach to |
| 1302 // another window and therefor want to reorder. |
| 1303 move_behavior_ = REORDER; |
| 1304 |
1276 move_loop_widget_ = GetAttachedBrowserWidget(); | 1305 move_loop_widget_ = GetAttachedBrowserWidget(); |
1277 DCHECK(move_loop_widget_); | 1306 DCHECK(move_loop_widget_); |
1278 move_loop_widget_->AddObserver(this); | 1307 move_loop_widget_->AddObserver(this); |
1279 is_dragging_window_ = true; | 1308 is_dragging_window_ = true; |
1280 bool destroyed = false; | 1309 bool destroyed = false; |
1281 destroyed_ = &destroyed; | 1310 destroyed_ = &destroyed; |
1282 // Running the move loop releases mouse capture on windows, which triggers | 1311 #if !defined(USE_ASH) |
| 1312 // Running the move loop releases mouse capture on Windows, which triggers |
1283 // destroying the drag loop. Release mouse capture ourself before this while | 1313 // destroying the drag loop. Release mouse capture ourself before this while |
1284 // the DragController isn't owned by the TabStrip. | 1314 // the DragController isn't owned by the TabStrip. |
1285 attached_tabstrip_->ReleaseDragController(); | 1315 attached_tabstrip_->ReleaseDragController(); |
1286 attached_tabstrip_->GetWidget()->ReleaseCapture(); | 1316 attached_tabstrip_->GetWidget()->ReleaseCapture(); |
1287 attached_tabstrip_->OwnDragController(this); | 1317 attached_tabstrip_->OwnDragController(this); |
| 1318 #endif |
1288 views::Widget::MoveLoopResult result = move_loop_widget_->RunMoveLoop(); | 1319 views::Widget::MoveLoopResult result = move_loop_widget_->RunMoveLoop(); |
1289 content::NotificationService::current()->Notify( | 1320 content::NotificationService::current()->Notify( |
1290 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, | 1321 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, |
1291 content::NotificationService::AllBrowserContextsAndSources(), | 1322 content::NotificationService::AllBrowserContextsAndSources(), |
1292 content::NotificationService::NoDetails()); | 1323 content::NotificationService::NoDetails()); |
1293 | 1324 |
1294 if (destroyed) | 1325 if (destroyed) |
1295 return; | 1326 return; |
1296 destroyed_ = NULL; | 1327 destroyed_ = NULL; |
1297 // Under chromeos we immediately set the |move_loop_widget_| to NULL. | 1328 // Under chromeos we immediately set the |move_loop_widget_| to NULL. |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 gfx::Point touch_point; | 1957 gfx::Point touch_point; |
1927 bool got_touch_point = widget_window->GetRootWindow()-> | 1958 bool got_touch_point = widget_window->GetRootWindow()-> |
1928 gesture_recognizer()->GetLastTouchPointForTarget(widget_window, | 1959 gesture_recognizer()->GetLastTouchPointForTarget(widget_window, |
1929 &touch_point); | 1960 &touch_point); |
1930 DCHECK(got_touch_point); | 1961 DCHECK(got_touch_point); |
1931 return touch_point; | 1962 return touch_point; |
1932 } | 1963 } |
1933 #endif | 1964 #endif |
1934 return gfx::Screen::GetCursorScreenPoint(); | 1965 return gfx::Screen::GetCursorScreenPoint(); |
1935 } | 1966 } |
OLD | NEW |