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 "ash/accelerators/accelerator_commands.h" | 10 #include "ash/accelerators/accelerator_commands.h" |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 | 160 |
161 // static | 161 // static |
162 const int TabDragController::kVerticalDetachMagnetism = 15; | 162 const int TabDragController::kVerticalDetachMagnetism = 15; |
163 | 163 |
164 TabDragController::TabDragController() | 164 TabDragController::TabDragController() |
165 : event_source_(EVENT_SOURCE_MOUSE), | 165 : event_source_(EVENT_SOURCE_MOUSE), |
166 source_tabstrip_(NULL), | 166 source_tabstrip_(NULL), |
167 attached_tabstrip_(NULL), | 167 attached_tabstrip_(NULL), |
168 screen_(NULL), | 168 screen_(NULL), |
169 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), | 169 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), |
170 use_aura_capture_policy_(false), | 170 can_release_capture_(true), |
171 offset_to_width_ratio_(0), | 171 offset_to_width_ratio_(0), |
172 old_focused_view_id_( | 172 old_focused_view_id_( |
173 views::ViewStorage::GetInstance()->CreateStorageID()), | 173 views::ViewStorage::GetInstance()->CreateStorageID()), |
174 last_move_screen_loc_(0), | 174 last_move_screen_loc_(0), |
175 started_drag_(false), | 175 started_drag_(false), |
176 active_(true), | 176 active_(true), |
177 source_tab_index_(std::numeric_limits<size_t>::max()), | 177 source_tab_index_(std::numeric_limits<size_t>::max()), |
178 initial_move_(true), | 178 initial_move_(true), |
179 move_behavior_(REORDER), | 179 move_behavior_(REORDER), |
180 mouse_move_direction_(0), | 180 mouse_move_direction_(0), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 DCHECK(!tabs.empty()); | 227 DCHECK(!tabs.empty()); |
228 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); | 228 DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); |
229 source_tabstrip_ = source_tabstrip; | 229 source_tabstrip_ = source_tabstrip; |
230 was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized(); | 230 was_source_maximized_ = source_tabstrip->GetWidget()->IsMaximized(); |
231 was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen(); | 231 was_source_fullscreen_ = source_tabstrip->GetWidget()->IsFullscreen(); |
232 screen_ = gfx::Screen::GetScreenFor( | 232 screen_ = gfx::Screen::GetScreenFor( |
233 source_tabstrip->GetWidget()->GetNativeView()); | 233 source_tabstrip->GetWidget()->GetNativeView()); |
234 host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView( | 234 host_desktop_type_ = chrome::GetHostDesktopTypeForNativeView( |
235 source_tabstrip->GetWidget()->GetNativeView()); | 235 source_tabstrip->GetWidget()->GetNativeView()); |
236 #if defined(OS_LINUX) | 236 #if defined(OS_LINUX) |
237 use_aura_capture_policy_ = true; | 237 // Mouse capture is not synchronous on desktop Linux. Chrome makes |
238 // transferring capture between widgets without releasing capture appear | |
239 // synchronous on desktop Linux, so use that. | |
240 can_release_capture_ = false; | |
sky
2014/08/13 19:14:53
What about when running ash on linux (not chromeos
pkotwicz
2014/08/15 20:30:49
I moved the comments outside of the ifdefs. Should
| |
238 #else | 241 #else |
239 use_aura_capture_policy_ = | 242 // Do not release capture when transferring capture on Ash because releasing |
240 (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH); | 243 // capture cancels gestures. |
244 can_release_capture_ = | |
245 (host_desktop_type_ != chrome::HOST_DESKTOP_TYPE_ASH); | |
241 #endif | 246 #endif |
242 start_point_in_screen_ = gfx::Point(source_tab_offset, mouse_offset.y()); | 247 start_point_in_screen_ = gfx::Point(source_tab_offset, mouse_offset.y()); |
243 views::View::ConvertPointToScreen(source_tab, &start_point_in_screen_); | 248 views::View::ConvertPointToScreen(source_tab, &start_point_in_screen_); |
244 event_source_ = event_source; | 249 event_source_ = event_source; |
245 mouse_offset_ = mouse_offset; | 250 mouse_offset_ = mouse_offset; |
246 move_behavior_ = move_behavior; | 251 move_behavior_ = move_behavior; |
247 last_point_in_screen_ = start_point_in_screen_; | 252 last_point_in_screen_ = start_point_in_screen_; |
248 last_move_screen_loc_ = start_point_in_screen_.x(); | 253 last_move_screen_loc_ = start_point_in_screen_.x(); |
249 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); | 254 initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); |
250 | 255 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 "point_in_screen", point_in_screen.ToString()); | 546 "point_in_screen", point_in_screen.ToString()); |
542 | 547 |
543 if (!target_tabstrip) { | 548 if (!target_tabstrip) { |
544 DetachIntoNewBrowserAndRunMoveLoop(point_in_screen); | 549 DetachIntoNewBrowserAndRunMoveLoop(point_in_screen); |
545 return DRAG_BROWSER_RESULT_STOP; | 550 return DRAG_BROWSER_RESULT_STOP; |
546 } | 551 } |
547 if (is_dragging_window_) { | 552 if (is_dragging_window_) { |
548 // ReleaseCapture() is going to result in calling back to us (because it | 553 // ReleaseCapture() is going to result in calling back to us (because it |
549 // results in a move). That'll cause all sorts of problems. Reset the | 554 // results in a move). That'll cause all sorts of problems. Reset the |
550 // observer so we don't get notified and process the event. | 555 // observer so we don't get notified and process the event. |
551 if (use_aura_capture_policy_) { | 556 if (host_desktop_type_ == chrome::HOST_DESKTOP_TYPE_ASH) { |
sky
2014/08/13 19:14:53
Why isn't this can_release_capture_?
pkotwicz
2014/08/15 20:30:49
The behavior described in the comment applies to a
| |
552 move_loop_widget_->RemoveObserver(this); | 557 move_loop_widget_->RemoveObserver(this); |
553 move_loop_widget_ = NULL; | 558 move_loop_widget_ = NULL; |
554 } | 559 } |
555 views::Widget* browser_widget = GetAttachedBrowserWidget(); | 560 views::Widget* browser_widget = GetAttachedBrowserWidget(); |
556 // Need to release the drag controller before starting the move loop as it's | 561 // Need to release the drag controller before starting the move loop as it's |
557 // going to trigger capture lost, which cancels drag. | 562 // going to trigger capture lost, which cancels drag. |
558 attached_tabstrip_->ReleaseDragController(); | 563 attached_tabstrip_->ReleaseDragController(); |
559 target_tabstrip->OwnDragController(this); | 564 target_tabstrip->OwnDragController(this); |
560 // Disable animations so that we don't see a close animation on aero. | 565 // Disable animations so that we don't see a close animation on aero. |
561 browser_widget->SetVisibilityChangedAnimationsEnabled(false); | 566 browser_widget->SetVisibilityChangedAnimationsEnabled(false); |
562 // For aura we can't release capture, otherwise it'll cancel a gesture. | 567 if (can_release_capture_) |
563 // Instead we have to directly change capture. | 568 browser_widget->ReleaseCapture(); |
564 if (use_aura_capture_policy_) | 569 else |
565 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); | 570 target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); |
566 else | |
567 browser_widget->ReleaseCapture(); | |
568 #if defined(OS_WIN) | 571 #if defined(OS_WIN) |
569 // The Gesture recognizer does not work well currently when capture changes | 572 // The Gesture recognizer does not work well currently when capture changes |
570 // while a touch gesture is in progress. So we need to manually transfer | 573 // while a touch gesture is in progress. So we need to manually transfer |
571 // gesture sequence and the GR's touch events queue to the new window. This | 574 // gesture sequence and the GR's touch events queue to the new window. This |
572 // should really be done somewhere in capture change code and or inside the | 575 // should really be done somewhere in capture change code and or inside the |
573 // GR. But we currently do not have a consistent way for doing it that would | 576 // GR. But we currently do not have a consistent way for doing it that would |
574 // work in all cases. Hence this hack. | 577 // work in all cases. Hence this hack. |
575 ui::GestureRecognizer::Get()->TransferEventsTo( | 578 ui::GestureRecognizer::Get()->TransferEventsTo( |
576 browser_widget->GetNativeView(), | 579 browser_widget->GetNativeView(), |
577 target_tabstrip->GetWidget()->GetNativeView()); | 580 target_tabstrip->GetWidget()->GetNativeView()); |
578 #endif | 581 #endif |
579 | 582 |
580 // The window is going away. Since the drag is still on going we don't want | 583 // The window is going away. Since the drag is still on going we don't want |
581 // that to effect the position of any windows. | 584 // that to effect the position of any windows. |
582 SetWindowPositionManaged(browser_widget->GetNativeView(), false); | 585 SetWindowPositionManaged(browser_widget->GetNativeView(), false); |
583 | 586 |
584 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) | 587 #if !defined(OS_LINUX) || defined(OS_CHROMEOS) |
585 // EndMoveLoop is going to snap the window back to its original location. | 588 // EndMoveLoop is going to snap the window back to its original location. |
586 // Hide it so users don't see this. Hiding a window in Linux aura causes | 589 // Hide it so users don't see this. Hiding a window in Linux aura causes |
587 // it to lose capture so skip it. | 590 // it to lose capture so skip it. |
588 browser_widget->Hide(); | 591 browser_widget->Hide(); |
589 #endif | 592 #endif |
590 browser_widget->EndMoveLoop(); | 593 browser_widget->EndMoveLoop(); |
591 | 594 |
592 // Ideally we would always swap the tabs now, but on non-ash it seems that | 595 // Ideally we would always swap the tabs now, but on non-ash Windows, it |
sky
2014/08/13 19:14:53
This is confusing now as it doesn't mention can_re
pkotwicz
2014/08/15 20:30:49
I changed the comment to make it more accurate. I
| |
593 // running the move loop implicitly activates the window when done, leading | 596 // seems that running the move loop implicitly activates the window when |
594 // to all sorts of flicker. So, on non-ash, instead we process the move | 597 // done, leading to all sorts of flicker. So, on non-ash Windows, instead |
595 // after the loop completes. But on chromeos, we can do tab swapping now to | 598 // we process the move after the loop completes. But on chromeos, we can |
596 // avoid the tab flashing issue(crbug.com/116329). | 599 // do tab swapping now to avoid the tab flashing issue |
597 if (use_aura_capture_policy_) { | 600 // (crbug.com/116329). |
601 if (can_release_capture_) { | |
602 tab_strip_to_attach_to_after_exit_ = target_tabstrip; | |
603 } else { | |
598 is_dragging_window_ = false; | 604 is_dragging_window_ = false; |
599 Detach(DONT_RELEASE_CAPTURE); | 605 Detach(DONT_RELEASE_CAPTURE); |
600 Attach(target_tabstrip, point_in_screen); | 606 Attach(target_tabstrip, point_in_screen); |
601 // Move the tabs into position. | 607 // Move the tabs into position. |
602 MoveAttached(point_in_screen); | 608 MoveAttached(point_in_screen); |
603 attached_tabstrip_->GetWidget()->Activate(); | 609 attached_tabstrip_->GetWidget()->Activate(); |
604 } else { | |
605 tab_strip_to_attach_to_after_exit_ = target_tabstrip; | |
606 } | 610 } |
607 | 611 |
608 waiting_for_run_loop_to_exit_ = true; | 612 waiting_for_run_loop_to_exit_ = true; |
609 end_run_loop_behavior_ = END_RUN_LOOP_CONTINUE_DRAGGING; | 613 end_run_loop_behavior_ = END_RUN_LOOP_CONTINUE_DRAGGING; |
610 return DRAG_BROWSER_RESULT_STOP; | 614 return DRAG_BROWSER_RESULT_STOP; |
611 } | 615 } |
612 Detach(DONT_RELEASE_CAPTURE); | 616 Detach(DONT_RELEASE_CAPTURE); |
613 Attach(target_tabstrip, point_in_screen); | 617 Attach(target_tabstrip, point_in_screen); |
614 return DRAG_BROWSER_RESULT_CONTINUE; | 618 return DRAG_BROWSER_RESULT_CONTINUE; |
615 } | 619 } |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
984 std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); | 988 std::vector<gfx::Rect> drag_bounds = CalculateBoundsForDraggedTabs(); |
985 OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); | 989 OffsetX(GetAttachedDragPoint(point_in_screen).x(), &drag_bounds); |
986 | 990 |
987 gfx::Vector2d drag_offset; | 991 gfx::Vector2d drag_offset; |
988 Browser* browser = CreateBrowserForDrag( | 992 Browser* browser = CreateBrowserForDrag( |
989 attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); | 993 attached_tabstrip_, point_in_screen, &drag_offset, &drag_bounds); |
990 #if defined(OS_WIN) | 994 #if defined(OS_WIN) |
991 gfx::NativeView attached_native_view = | 995 gfx::NativeView attached_native_view = |
992 attached_tabstrip_->GetWidget()->GetNativeView(); | 996 attached_tabstrip_->GetWidget()->GetNativeView(); |
993 #endif | 997 #endif |
994 Detach(use_aura_capture_policy_ ? DONT_RELEASE_CAPTURE : RELEASE_CAPTURE); | 998 Detach(can_release_capture_ ? RELEASE_CAPTURE : DONT_RELEASE_CAPTURE); |
995 BrowserView* dragged_browser_view = | 999 BrowserView* dragged_browser_view = |
996 BrowserView::GetBrowserViewForBrowser(browser); | 1000 BrowserView::GetBrowserViewForBrowser(browser); |
997 views::Widget* dragged_widget = dragged_browser_view->GetWidget(); | 1001 views::Widget* dragged_widget = dragged_browser_view->GetWidget(); |
998 #if defined(OS_WIN) | 1002 #if defined(OS_WIN) |
999 // The Gesture recognizer does not work well currently when capture changes | 1003 // The Gesture recognizer does not work well currently when capture changes |
1000 // while a touch gesture is in progress. So we need to manually transfer | 1004 // while a touch gesture is in progress. So we need to manually transfer |
1001 // gesture sequence and the GR's touch events queue to the new window. This | 1005 // gesture sequence and the GR's touch events queue to the new window. This |
1002 // should really be done somewhere in capture change code and or inside the | 1006 // should really be done somewhere in capture change code and or inside the |
1003 // GR. But we currently do not have a consistent way for doing it that would | 1007 // GR. But we currently do not have a consistent way for doing it that would |
1004 // work in all cases. Hence this hack. | 1008 // work in all cases. Hence this hack. |
(...skipping 24 matching lines...) Expand all Loading... | |
1029 void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) { | 1033 void TabDragController::RunMoveLoop(const gfx::Vector2d& drag_offset) { |
1030 // If the user drags the whole window we'll assume they are going to attach to | 1034 // If the user drags the whole window we'll assume they are going to attach to |
1031 // another window and therefore want to reorder. | 1035 // another window and therefore want to reorder. |
1032 move_behavior_ = REORDER; | 1036 move_behavior_ = REORDER; |
1033 | 1037 |
1034 move_loop_widget_ = GetAttachedBrowserWidget(); | 1038 move_loop_widget_ = GetAttachedBrowserWidget(); |
1035 DCHECK(move_loop_widget_); | 1039 DCHECK(move_loop_widget_); |
1036 move_loop_widget_->AddObserver(this); | 1040 move_loop_widget_->AddObserver(this); |
1037 is_dragging_window_ = true; | 1041 is_dragging_window_ = true; |
1038 base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); | 1042 base::WeakPtr<TabDragController> ref(weak_factory_.GetWeakPtr()); |
1039 // Running the move loop releases mouse capture on non-ash, which triggers | 1043 if (can_release_capture_) { |
1040 // destroying the drag loop. Release mouse capture ourself before this while | 1044 // Running the move loop releases mouse capture, which triggers destroying |
1041 // the DragController isn't owned by the TabStrip. | 1045 // the drag loop. Release mouse capture now while the DragController is not |
1042 if (host_desktop_type_ != chrome::HOST_DESKTOP_TYPE_ASH) { | 1046 // owned by the TabStrip. |
1043 attached_tabstrip_->ReleaseDragController(); | 1047 attached_tabstrip_->ReleaseDragController(); |
1044 attached_tabstrip_->GetWidget()->ReleaseCapture(); | 1048 attached_tabstrip_->GetWidget()->ReleaseCapture(); |
1045 attached_tabstrip_->OwnDragController(this); | 1049 attached_tabstrip_->OwnDragController(this); |
1046 } | 1050 } |
1047 const views::Widget::MoveLoopSource move_loop_source = | 1051 const views::Widget::MoveLoopSource move_loop_source = |
1048 event_source_ == EVENT_SOURCE_MOUSE ? | 1052 event_source_ == EVENT_SOURCE_MOUSE ? |
1049 views::Widget::MOVE_LOOP_SOURCE_MOUSE : | 1053 views::Widget::MOVE_LOOP_SOURCE_MOUSE : |
1050 views::Widget::MOVE_LOOP_SOURCE_TOUCH; | 1054 views::Widget::MOVE_LOOP_SOURCE_TOUCH; |
1051 const views::Widget::MoveLoopEscapeBehavior escape_behavior = | 1055 const views::Widget::MoveLoopEscapeBehavior escape_behavior = |
1052 is_dragging_new_browser_ ? | 1056 is_dragging_new_browser_ ? |
1053 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE : | 1057 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE : |
1054 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE; | 1058 views::Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_DONT_HIDE; |
1055 views::Widget::MoveLoopResult result = | 1059 views::Widget::MoveLoopResult result = |
1056 move_loop_widget_->RunMoveLoop( | 1060 move_loop_widget_->RunMoveLoop( |
1057 drag_offset, move_loop_source, escape_behavior); | 1061 drag_offset, move_loop_source, escape_behavior); |
1058 content::NotificationService::current()->Notify( | 1062 content::NotificationService::current()->Notify( |
1059 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, | 1063 chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, |
1060 content::NotificationService::AllBrowserContextsAndSources(), | 1064 content::NotificationService::AllBrowserContextsAndSources(), |
1061 content::NotificationService::NoDetails()); | 1065 content::NotificationService::NoDetails()); |
1062 | 1066 |
1063 if (!ref) | 1067 if (!ref) |
1064 return; | 1068 return; |
1065 // Under chromeos we immediately set the |move_loop_widget_| to NULL. | |
1066 if (move_loop_widget_) { | 1069 if (move_loop_widget_) { |
1067 move_loop_widget_->RemoveObserver(this); | 1070 move_loop_widget_->RemoveObserver(this); |
1068 move_loop_widget_ = NULL; | 1071 move_loop_widget_ = NULL; |
1069 } | 1072 } |
1070 is_dragging_window_ = false; | 1073 is_dragging_window_ = false; |
1071 waiting_for_run_loop_to_exit_ = false; | 1074 waiting_for_run_loop_to_exit_ = false; |
1072 if (end_run_loop_behavior_ == END_RUN_LOOP_CONTINUE_DRAGGING) { | 1075 if (end_run_loop_behavior_ == END_RUN_LOOP_CONTINUE_DRAGGING) { |
1073 end_run_loop_behavior_ = END_RUN_LOOP_STOP_DRAGGING; | 1076 end_run_loop_behavior_ = END_RUN_LOOP_STOP_DRAGGING; |
1074 if (tab_strip_to_attach_to_after_exit_) { | 1077 if (tab_strip_to_attach_to_after_exit_) { |
1075 gfx::Point point_in_screen(GetCursorScreenPoint()); | 1078 gfx::Point point_in_screen(GetCursorScreenPoint()); |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1754 it != browser_list->end(); ++it) { | 1757 it != browser_list->end(); ++it) { |
1755 if ((*it)->tab_strip_model()->empty()) | 1758 if ((*it)->tab_strip_model()->empty()) |
1756 exclude.insert((*it)->window()->GetNativeWindow()); | 1759 exclude.insert((*it)->window()->GetNativeWindow()); |
1757 } | 1760 } |
1758 #endif | 1761 #endif |
1759 return GetLocalProcessWindowAtPoint(host_desktop_type_, | 1762 return GetLocalProcessWindowAtPoint(host_desktop_type_, |
1760 screen_point, | 1763 screen_point, |
1761 exclude); | 1764 exclude); |
1762 | 1765 |
1763 } | 1766 } |
OLD | NEW |