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/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 | 174 |
175 // static | 175 // static |
176 const int TabDragController::kVerticalDetachMagnetism = 15; | 176 const int TabDragController::kVerticalDetachMagnetism = 15; |
177 | 177 |
178 TabDragController::TabDragController() | 178 TabDragController::TabDragController() |
179 : event_source_(EVENT_SOURCE_MOUSE), | 179 : event_source_(EVENT_SOURCE_MOUSE), |
180 source_tabstrip_(NULL), | 180 source_tabstrip_(NULL), |
181 attached_tabstrip_(NULL), | 181 attached_tabstrip_(NULL), |
182 screen_(NULL), | 182 screen_(NULL), |
183 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), | 183 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), |
184 use_aura_capture_policy_(false), | 184 can_release_capture_(true), |
185 offset_to_width_ratio_(0), | 185 offset_to_width_ratio_(0), |
186 old_focused_view_id_( | 186 old_focused_view_id_( |
187 views::ViewStorage::GetInstance()->CreateStorageID()), | 187 views::ViewStorage::GetInstance()->CreateStorageID()), |
188 last_move_screen_loc_(0), | 188 last_move_screen_loc_(0), |
189 started_drag_(false), | 189 started_drag_(false), |
190 active_(true), | 190 active_(true), |
191 source_tab_index_(std::numeric_limits<size_t>::max()), | 191 source_tab_index_(std::numeric_limits<size_t>::max()), |
192 initial_move_(true), | 192 initial_move_(true), |
193 detach_behavior_(DETACHABLE), | 193 detach_behavior_(DETACHABLE), |
194 move_behavior_(REORDER), | 194 move_behavior_(REORDER), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 EventSource event_source) { | 241 EventSource event_source) { |
242 DCHECK(!tabs.empty()); | 242 DCHECK(!tabs.empty()); |
243 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); | 243 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); |
244 source_tabstrip_ = source_tabstrip; | 244 source_tabstrip_ = source_tabstrip; |
245 was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized(); | 245 was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized(); |
246 was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen(); | 246 was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen(); |
247 screen_ = gfx::Screen::GetScreenFor( | 247 screen_ = gfx::Screen::GetScreenFor( |
248 source_tabstrip->GetWidget()->GetNativeView()); | 248 source_tabstrip->GetWidget()->GetNativeView()); |
249 host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView( | 249 host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView( |
250 source_tabstrip->GetWidget()->GetNativeView()); | 250 source_tabstrip->GetWidget()->GetNativeView()); |
| 251 // Do not release capture when transferring capture between widgets on: |
| 252 // - Desktop Linux |
| 253 // Mouse capture is not synchronous on desktop Linux. Chrome makes |
| 254 // transferring capture between widgets without releasing capture appear |
| 255 // synchronous on desktop Linux, so use that. |
| 256 // - Ash |
| 257 // Releasing capture on Ash cancels gestures so avoid it. |
251 #if defined(OS_LINUX) | 258 #if defined(OS_LINUX) |
252 use_aura_capture_policy_ = true; | 259 can_release_capture_ = false; |
253 #else | 260 #else |
254 use_aura_capture_policy_ = | 261 can_release_capture_ = |
255 (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH); | 262 (host_desktop_type_ != chrome::HOST_DESKTOP_TYPE_ASH); |
256 #endif | 263 #endif |
257 start_point_in_screen_ = gfx::Point(source_tab_offset, mouse_offset.y()); | 264 start_point_in_screen_ = gfx::Point(source_tab_offset, mouse_offset.y()); |
258 views::View::ConvertPointToScreen(source_tab, &start_point_in_screen_); | 265 views::View::ConvertPointToScreen(source_tab, &start_point_in_screen_); |
259 event_source_ = event_source; | 266 event_source_ = event_source; |
260 mouse_offset_ = mouse_offset; | 267 mouse_offset_ = mouse_offset; |
261 move_behavior_ = move_behavior; | 268 move_behavior_ = move_behavior; |
262 last_point_in_screen_ = start_point_in_screen_; | 269 last_point_in_screen_ = start_point_in_screen_; |
263 last_move_screen_loc_ = start_point_in_screen_.x(); | 270 last_move_screen_loc_ = start_point_in_screen_.x(); |
264 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); | 271 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); |
265 | 272 |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 "point_in_screen", point_in_screen.ToString()); | 572 "point_in_screen", point_in_screen.ToString()); |
566 | 573 |
567 if (!target_tabstrip) { | 574 if (!target_tabstrip) { |
568 DetachIntoNewBrowserAndRunMoveLoop(point_in_screen); | 575 DetachIntoNewBrowserAndRunMoveLoop(point_in_screen); |
569 return DRAG_BROWSER_RESULT_STOP; | 576 return DRAG_BROWSER_RESULT_STOP; |
570 } | 577 } |
571 if (is_dragging_window_) { | 578 if (is_dragging_window_) { |
572 // ReleaseCapture() is going to result in calling back to us (because it | 579 // ReleaseCapture() is going to result in calling back to us (because it |
573 // results in a move). That'll cause all sorts of problems. Reset the | 580 // results in a move). That'll cause all sorts of problems. Reset the |
574 // observer so we don't get notified and process the event. | 581 // observer so we don't get notified and process the event. |
575 if (use_aura_capture_policy_) { | 582 if (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) { |
576 move_loop_widget_->RemoveObserver(this); | 583 move_loop_widget_->RemoveObserver(this); |
577 move_loop_widget_ = NULL; | 584 move_loop_widget_ = NULL; |
578 } | 585 } |
579 views::Widget* browser_widget = GetAttachedBrowserWidget(); | 586 views::Widget* browser_widget = GetAttachedBrowserWidget(); |
580 // Need to release the drag controller before starting the move loop as it's | 587 // Need to release the drag controller before starting the move loop as it's |
581 // going to trigger capture lost, which cancels drag. | 588 // going to trigger capture lost, which cancels drag. |
582 attached_tabstrip_->ReleaseDragController(); | 589 attached_tabstrip_->ReleaseDragController(); |
583 target_tabstrip->OwnDragController(this); | 590 target_tabstrip->OwnDragController(this); |
584 // Disable animations so that we don't see a close animation on aero. | 591 // Disable animations so that we don't see a close animation on aero. |
585 browser_widget->SetVisibilityChangedAnimationsEnabled(false); | 592 browser_widget->SetVisibilityChangedAnimationsEnabled(false); |
586 // For aura we can't release capture, otherwise it'll cancel a gesture. | 593 if (can_release_capture_) |
587 // Instead we have to directly change capture. | 594 browser_widget->ReleaseCapture(); |
588 if (use_aura_capture_policy_) | 595 else |
589 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); | 596 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); |
590 else | |
591 browser_widget->ReleaseCapture(); | |
592 #if defined(OS_WIN) | 597 #if defined(OS_WIN) |
593 // The Gesture recognizer does not work well currently when capture changes | 598 // The Gesture recognizer does not work well currently when capture changes |
594 // while a touch gesture is in progress. So we need to manually transfer | 599 // while a touch gesture is in progress. So we need to manually transfer |
595 // gesture sequence and the GR's touch events queue to the new window. This | 600 // gesture sequence and the GR's touch events queue to the new window. This |
596 // should really be done somewhere in capture change code and or inside the | 601 // should really be done somewhere in capture change code and or inside the |
597 // GR. But we currently do not have a consistent way for doing it that would | 602 // GR. But we currently do not have a consistent way for doing it that would |
598 // work in all cases. Hence this hack. | 603 // work in all cases. Hence this hack. |
599 ui::GestureRecognizer::Get()->TransferEventsTo( | 604 ui::GestureRecognizer::Get()->TransferEventsTo( |
600 browser_widget->GetNativeView(), | 605 browser_widget->GetNativeView(), |
601 target_tabstrip->GetWidget()->GetNativeView()); | 606 target_tabstrip->GetWidget()->GetNativeView()); |
602 #endif | 607 #endif |
603 | 608 |
604 // The window is going away. Since the drag is still on going we don't want | 609 // The window is going away. Since the drag is still on going we don't want |
605 // that to effect the position of any windows. | 610 // that to effect the position of any windows. |
606 SetWindowPositionManaged(browser_widget->GetNativeView(), false); | 611 SetWindowPositionManaged(browser_widget->GetNativeView(), false); |
607 | 612 |
608 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) | 613 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) |
609 // EndMoveLoop is going to snap the window back to its original location. | 614 // EndMoveLoop is going to snap the window back to its original location. |
610 // Hide it so users don't see this. Hiding a window in Linux aura causes | 615 // Hide it so users don't see this. Hiding a window in Linux aura causes |
611 // it to lose capture so skip it. | 616 // it to lose capture so skip it. |
612 browser_widget->Hide(); | 617 browser_widget->Hide(); |
613 #endif | 618 #endif |
614 browser_widget->EndMoveLoop(); | 619 browser_widget->EndMoveLoop(); |
615 | 620 |
616 // Ideally we would always swap the tabs now, but on non-ash it seems that | 621 // Ideally we would always swap the tabs now, but on non-ash Windows, it |
617 // running the move loop implicitly activates the window when done, leading | 622 // seems that running the move loop implicitly activates the window when |
618 // to all sorts of flicker. So, on non-ash, instead we process the move | 623 // done, leading to all sorts of flicker. So, on non-ash Windows, instead |
619 // after the loop completes. But on chromeos, we can do tab swapping now to | 624 // we process the move after the loop completes. But on chromeos, we can |
620 // avoid the tab flashing issue(crbug.com/116329). | 625 // do tab swapping now to avoid the tab flashing issue |
621 if (use_aura_capture_policy_) { | 626 // (crbug.com/116329). |
| 627 if (can_release_capture_) { |
| 628 tab_strip_to_attach_to_after_exit_ = target_tabstrip; |
| 629 } else { |
622 is_dragging_window_ = false; | 630 is_dragging_window_ = false; |
623 Detach(DONT_RELEASE_CAPTURE); | 631 Detach(DONT_RELEASE_CAPTURE); |
624 Attach(target_tabstrip, point_in_screen); | 632 Attach(target_tabstrip, point_in_screen); |
625 // Move the tabs into position. | 633 // Move the tabs into position. |
626 MoveAttached(point_in_screen); | 634 MoveAttached(point_in_screen); |
627 attached_tabstrip_->GetWidget()->Activate(); | 635 attached_tabstrip_->GetWidget()->Activate(); |
628 } else { | |
629 tab_strip_to_attach_to_after_exit_ = target_tabstrip; | |
630 } | 636 } |
631 | 637 |
632 waiting_for_run_loop_to_exit_ = true; | 638 waiting_for_run_loop_to_exit_ = true; |
633 end_run_loop_behavior_ = END_RUN_LOOP_CONTINUE_DRAGGING; | 639 end_run_loop_behavior_ = END_RUN_LOOP_CONTINUE_DRAGGING; |
634 return DRAG_BROWSER_RESULT_STOP; | 640 return DRAG_BROWSER_RESULT_STOP; |
635 } | 641 } |
636 Detach(DONT_RELEASE_CAPTURE); | 642 Detach(DONT_RELEASE_CAPTURE); |
637 Attach(target_tabstrip, point_in_screen); | 643 Attach(target_tabstrip, point_in_screen); |
638 return DRAG_BROWSER_RESULT_CONTINUE; | 644 return DRAG_BROWSER_RESULT_CONTINUE; |
639 } | 645 } |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); | 1014 std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); |
1009 OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); | 1015 OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); |
1010 | 1016 |
1011 gfx::Vector2d drag_offset; | 1017 gfx::Vector2d drag_offset; |
1012 Browser* browser = CreateBrowserForDrag( | 1018 Browser* browser = CreateBrowserForDrag( |
1013 attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); | 1019 attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); |
1014 #if defined(OS_WIN) | 1020 #if defined(OS_WIN) |
1015 gfx::NativeView attached_native_view = | 1021 gfx::NativeView attached_native_view = |
1016 attached_tabstrip_->GetWidget()->GetNativeView(); | 1022 attached_tabstrip_->GetWidget()->GetNativeView(); |
1017 #endif | 1023 #endif |
1018 Detach(use_aura_capture_policy_ ? DONT_RELEASE_CAPTURE : RELEASE_CAPTURE); | 1024 Detach(can_release_capture_ ? RELEASE_CAPTURE : DONT_RELEASE_CAPTURE); |
1019 BrowserView* dragged_browser_view = | 1025 BrowserView* dragged_browser_view = |
1020 BrowserView::GetBrowserViewForBrowser(browser); | 1026 BrowserView::GetBrowserViewForBrowser(browser); |
1021 views::Widget* dragged_widget = dragged_browser_view->GetWidget(); | 1027 views::Widget* dragged_widget = dragged_browser_view->GetWidget(); |
1022 #if defined(OS_WIN) | 1028 #if defined(OS_WIN) |
1023 // The Gesture recognizer does not work well currently when capture changes | 1029 // The Gesture recognizer does not work well currently when capture changes |
1024 // while a touch gesture is in progress. So we need to manually transfer | 1030 // while a touch gesture is in progress. So we need to manually transfer |
1025 // gesture sequence and the GR's touch events queue to the new window. This | 1031 // gesture sequence and the GR's touch events queue to the new window. This |
1026 // should really be done somewhere in capture change code and or inside the | 1032 // should really be done somewhere in capture change code and or inside the |
1027 // GR. But we currently do not have a consistent way for doing it that would | 1033 // GR. But we currently do not have a consistent way for doing it that would |
1028 // work in all cases. Hence this hack. | 1034 // work in all cases. Hence this hack. |
(...skipping 24 matching lines...) Expand all Loading... |
1053 void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) { | 1059 void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) { |
1054 // If the user drags the whole window we'll assume they are going to attach to | 1060 // If the user drags the whole window we'll assume they are going to attach to |
1055 // another window and therefore want to reorder. | 1061 // another window and therefore want to reorder. |
1056 move_behavior_ = REORDER; | 1062 move_behavior_ = REORDER; |
1057 | 1063 |
1058 move_loop_widget_ = GetAttachedBrowserWidget(); | 1064 move_loop_widget_ = GetAttachedBrowserWidget(); |
1059 DCHECK(move_loop_widget_); | 1065 DCHECK(move_loop_widget_); |
1060 move_loop_widget_->AddObserver(this); | 1066 move_loop_widget_->AddObserver(this); |
1061 is_dragging_window_ = true; | 1067 is_dragging_window_ = true; |
1062 base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); | 1068 base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); |
1063 // Running the move loop releases mouse capture on non-ash, which triggers | 1069 if (can_release_capture_) { |
1064 // destroying the drag loop. Release mouse capture ourself before this while | 1070 // Running the move loop releases mouse capture, which triggers destroying |
1065 // the DragController isn't owned by the TabStrip. | 1071 // the drag loop. Release mouse capture now while the DragController is not |
1066 if (host_desktop_type_ != chrome::HOST_DESKTOP_TYPE_ASH) { | 1072 // owned by the TabStrip. |
1067 attached_tabstrip_->ReleaseDragController(); | 1073 attached_tabstrip_->ReleaseDragController(); |
1068 attached_tabstrip_->GetWidget()->ReleaseCapture(); | 1074 attached_tabstrip_->GetWidget()->ReleaseCapture(); |
1069 attached_tabstrip_->OwnDragController(this); | 1075 attached_tabstrip_->OwnDragController(this); |
1070 } | 1076 } |
1071 const views::Widget::MoveLoopSource move_loop_source = | 1077 const views::Widget::MoveLoopSource move_loop_source = |
1072 event_source_ == EVENT_SOURCE_MOUSE ? | 1078 event_source_ == EVENT_SOURCE_MOUSE ? |
1073 views::Widget::MOVE_LOOP_SOURCE_MOUSE : | 1079 views::Widget::MOVE_LOOP_SOURCE_MOUSE : |
1074 views::Widget::MOVE_LOOP_SOURCE_TOUCH; | 1080 views::Widget::MOVE_LOOP_SOURCE_TOUCH; |
1075 const views::Widget::MoveLoopEscapeBehavior escape_behavior = | 1081 const views::Widget::MoveLoopEscapeBehavior escape_behavior = |
1076 is_dragging_new_browser_ ? | 1082 is_dragging_new_browser_ ? |
1077 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE : | 1083 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE : |
1078 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE; | 1084 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE; |
1079 views::Widget::MoveLoopResult result = | 1085 views::Widget::MoveLoopResult result = |
1080 move_loop_widget_->RunMoveLoop( | 1086 move_loop_widget_->RunMoveLoop( |
1081 drag_offset, move_loop_source, escape_behavior); | 1087 drag_offset, move_loop_source, escape_behavior); |
1082 content::NotificationService::current()->Notify( | 1088 content::NotificationService::current()->Notify( |
1083 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, | 1089 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, |
1084 content::NotificationService::AllBrowserContextsAndSources(), | 1090 content::NotificationService::AllBrowserContextsAndSources(), |
1085 content::NotificationService::NoDetails()); | 1091 content::NotificationService::NoDetails()); |
1086 | 1092 |
1087 if (!ref) | 1093 if (!ref) |
1088 return; | 1094 return; |
1089 // Under chromeos we immediately set the |move_loop_widget_| to NULL. | |
1090 if (move_loop_widget_) { | 1095 if (move_loop_widget_) { |
1091 move_loop_widget_->RemoveObserver(this); | 1096 move_loop_widget_->RemoveObserver(this); |
1092 move_loop_widget_ = NULL; | 1097 move_loop_widget_ = NULL; |
1093 } | 1098 } |
1094 is_dragging_window_ = false; | 1099 is_dragging_window_ = false; |
1095 waiting_for_run_loop_to_exit_ = false; | 1100 waiting_for_run_loop_to_exit_ = false; |
1096 if (end_run_loop_behavior_ == END_RUN_LOOP_CONTINUE_DRAGGING) { | 1101 if (end_run_loop_behavior_ == END_RUN_LOOP_CONTINUE_DRAGGING) { |
1097 end_run_loop_behavior_ = END_RUN_LOOP_STOP_DRAGGING; | 1102 end_run_loop_behavior_ = END_RUN_LOOP_STOP_DRAGGING; |
1098 if (tab_strip_to_attach_to_after_exit_) { | 1103 if (tab_strip_to_attach_to_after_exit_) { |
1099 gfx::Point point_in_screen(GetCursorScreenPoint()); | 1104 gfx::Point point_in_screen(GetCursorScreenPoint()); |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 it != browser_list->end(); ++it) { | 1785 it != browser_list->end(); ++it) { |
1781 if ((*it)->tab_strip_model()->empty()) | 1786 if ((*it)->tab_strip_model()->empty()) |
1782 exclude.insert((*it)->window()->GetNativeWindow()); | 1787 exclude.insert((*it)->window()->GetNativeWindow()); |
1783 } | 1788 } |
1784 #endif | 1789 #endif |
1785 return GetLocalProcessWindowAtPoint(host_desktop_type_, | 1790 return GetLocalProcessWindowAtPoint(host_desktop_type_, |
1786 screen_point, | 1791 screen_point, |
1787 exclude); | 1792 exclude); |
1788 | 1793 |
1789 } | 1794 } |
OLD | NEW |