• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
7 
8 #include <vector>
9 
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/timer/timer.h"
13 #include "chrome/browser/ui/host_desktop.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
15 #include "chrome/browser/ui/views/tabs/tab_strip_types.h"
16 #include "content/public/browser/notification_observer.h"
17 #include "content/public/browser/notification_registrar.h"
18 #include "content/public/browser/web_contents_delegate.h"
19 #include "ui/base/models/list_selection_model.h"
20 #include "ui/gfx/rect.h"
21 #include "ui/views/widget/widget_observer.h"
22 
23 namespace gfx {
24 class Screen;
25 }
26 namespace ui {
27 class EventHandler;
28 class ListSelectionModel;
29 }
30 namespace views {
31 class View;
32 }
33 class Browser;
34 class Tab;
35 struct TabRendererData;
36 class TabStrip;
37 class TabStripModel;
38 
39 // TabDragController is responsible for managing the tab dragging session. When
40 // the user presses the mouse on a tab a new TabDragController is created and
41 // Drag() is invoked as the mouse is dragged. If the mouse is dragged far enough
42 // TabDragController starts a drag session. The drag session is completed when
43 // EndDrag() is invoked (or the TabDragController is destroyed).
44 //
45 // While dragging within a tab strip TabDragController sets the bounds of the
46 // tabs (this is referred to as attached). When the user drags far enough such
47 // that the tabs should be moved out of the tab strip a new Browser is created
48 // and RunMoveLoop() is invoked on the Widget to drag the browser around. This
49 // is the default on aura.
50 class TabDragController : public content::WebContentsDelegate,
51                           public content::NotificationObserver,
52                           public views::WidgetObserver,
53                           public TabStripModelObserver {
54  public:
55   enum DetachBehavior {
56     DETACHABLE,
57     NOT_DETACHABLE
58   };
59 
60   // What should happen as the mouse is dragged within the tabstrip.
61   enum MoveBehavior {
62     // Only the set of visible tabs should change. This is only applicable when
63     // using touch layout.
64     MOVE_VISIBILE_TABS,
65 
66     // Typical behavior where tabs are dragged around.
67     REORDER
68   };
69 
70   // Indicates the event source that initiated the drag.
71   enum EventSource {
72     EVENT_SOURCE_MOUSE,
73     EVENT_SOURCE_TOUCH,
74   };
75 
76   // Amount above or below the tabstrip the user has to drag before detaching.
77   static const int kTouchVerticalDetachMagnetism;
78   static const int kVerticalDetachMagnetism;
79 
80   TabDragController();
81   virtual ~TabDragController();
82 
83   // Initializes TabDragController to drag the tabs in |tabs| originating from
84   // |source_tabstrip|. |source_tab| is the tab that initiated the drag and is
85   // contained in |tabs|.  |mouse_offset| is the distance of the mouse pointer
86   // from the origin of the first tab in |tabs| and |source_tab_offset| the
87   // offset from |source_tab|. |source_tab_offset| is the horizontal offset of
88   // |mouse_offset| relative to |source_tab|. |initial_selection_model| is the
89   // selection model before the drag started and is only non-empty if
90   // |source_tab| was not initially selected.
91   void Init(TabStrip* source_tabstrip,
92             Tab* source_tab,
93             const std::vector<Tab*>& tabs,
94             const gfx::Point& mouse_offset,
95             int source_tab_offset,
96             const ui::ListSelectionModel& initial_selection_model,
97             DetachBehavior detach_behavior,
98             MoveBehavior move_behavior,
99             EventSource event_source);
100 
101   // Returns true if there is a drag underway and the drag is attached to
102   // |tab_strip|.
103   // NOTE: this returns false if the TabDragController is in the process of
104   // finishing the drag.
105   static bool IsAttachedTo(const TabStrip* tab_strip);
106 
107   // Returns true if there is a drag underway.
108   static bool IsActive();
109 
110   // Sets the move behavior. Has no effect if started_drag() is true.
111   void SetMoveBehavior(MoveBehavior behavior);
move_behavior()112   MoveBehavior move_behavior() const { return move_behavior_; }
113 
event_source()114   EventSource event_source() const { return event_source_; }
115 
116   // See description above fields for details on these.
active()117   bool active() const { return active_; }
attached_tabstrip()118   const TabStrip* attached_tabstrip() const { return attached_tabstrip_; }
119 
120   // Returns true if a drag started.
started_drag()121   bool started_drag() const { return started_drag_; }
122 
123   // Returns true if mutating the TabStripModel.
is_mutating()124   bool is_mutating() const { return is_mutating_; }
125 
126   // Returns true if we've detached from a tabstrip and are running a nested
127   // move message loop.
is_dragging_window()128   bool is_dragging_window() const { return is_dragging_window_; }
129 
130   // Invoked to drag to the new location, in screen coordinates.
131   void Drag(const gfx::Point& point_in_screen);
132 
133   // Complete the current drag session.
134   void EndDrag(EndDragReason reason);
135 
136  private:
137   // Used to indicate the direction the mouse has moved when attached.
138   static const int kMovedMouseLeft  = 1 << 0;
139   static const int kMovedMouseRight = 1 << 1;
140 
141   // Enumeration of the ways a drag session can end.
142   enum EndDragType {
143     // Drag session exited normally: the user released the mouse.
144     NORMAL,
145 
146     // The drag session was canceled (alt-tab during drag, escape ...)
147     CANCELED,
148 
149     // The tab (NavigationController) was destroyed during the drag.
150     TAB_DESTROYED
151   };
152 
153   // Whether Detach() should release capture or not.
154   enum ReleaseCapture {
155     RELEASE_CAPTURE,
156     DONT_RELEASE_CAPTURE,
157   };
158 
159   // Specifies what should happen when RunMoveLoop completes.
160   enum EndRunLoopBehavior {
161     // Indicates the drag should end.
162     END_RUN_LOOP_STOP_DRAGGING,
163 
164     // Indicates the drag should continue.
165     END_RUN_LOOP_CONTINUE_DRAGGING
166   };
167 
168   // Enumeration of the possible positions the detached tab may detach from.
169   enum DetachPosition {
170     DETACH_BEFORE,
171     DETACH_AFTER,
172     DETACH_ABOVE_OR_BELOW
173   };
174 
175   // Indicates what should happen after invoking DragBrowserToNewTabStrip().
176   enum DragBrowserResultType {
177     // The caller should return immediately. This return value is used if a
178     // nested message loop was created or we're in a nested message loop and
179     // need to exit it.
180     DRAG_BROWSER_RESULT_STOP,
181 
182     // The caller should continue.
183     DRAG_BROWSER_RESULT_CONTINUE,
184   };
185 
186   // Stores the date associated with a single tab that is being dragged.
187   struct TabDragData {
188     TabDragData();
189     ~TabDragData();
190 
191     // The WebContents being dragged.
192     content::WebContents* contents;
193 
194     // content::WebContentsDelegate for |contents| before it was detached from
195     // the browser window. We store this so that we can forward certain delegate
196     // notifications back to it if we can't handle them locally.
197     content::WebContentsDelegate* original_delegate;
198 
199     // This is the index of the tab in |source_tabstrip_| when the drag
200     // began. This is used to restore the previous state if the drag is aborted.
201     int source_model_index;
202 
203     // If attached this is the tab in |attached_tabstrip_|.
204     Tab* attached_tab;
205 
206     // Is the tab pinned?
207     bool pinned;
208   };
209 
210   typedef std::vector<TabDragData> DragData;
211 
212   // Sets |drag_data| from |tab|. This also registers for necessary
213   // notifications and resets the delegate of the WebContents.
214   void InitTabDragData(Tab* tab, TabDragData* drag_data);
215 
216   // Overridden from content::WebContentsDelegate:
217   virtual content::WebContents* OpenURLFromTab(
218       content::WebContents* source,
219       const content::OpenURLParams& params) OVERRIDE;
220   virtual void NavigationStateChanged(const content::WebContents* source,
221                                       unsigned changed_flags) OVERRIDE;
222   virtual void AddNewContents(content::WebContents* source,
223                               content::WebContents* new_contents,
224                               WindowOpenDisposition disposition,
225                               const gfx::Rect& initial_pos,
226                               bool user_gesture,
227                               bool* was_blocked) OVERRIDE;
228   virtual bool ShouldSuppressDialogs() OVERRIDE;
229   virtual content::JavaScriptDialogManager*
230       GetJavaScriptDialogManager() OVERRIDE;
231   virtual void RequestMediaAccessPermission(
232       content::WebContents* web_contents,
233       const content::MediaStreamRequest& request,
234       const content::MediaResponseCallback& callback) OVERRIDE;
235 
236   // Overridden from content::NotificationObserver:
237   virtual void Observe(int type,
238                        const content::NotificationSource& source,
239                        const content::NotificationDetails& details) OVERRIDE;
240 
241   // Overriden from views::WidgetObserver:
242   virtual void OnWidgetBoundsChanged(views::Widget* widget,
243                                      const gfx::Rect& new_bounds) OVERRIDE;
244 
245   // Overriden from TabStripModelObserver:
246   virtual void TabStripEmpty() OVERRIDE;
247 
248   // Initialize the offset used to calculate the position to create windows
249   // in |GetWindowCreatePoint|. This should only be invoked from |Init|.
250   void InitWindowCreatePoint();
251 
252   // Returns the point where a detached window should be created given the
253   // current mouse position |origin|.
254   gfx::Point GetWindowCreatePoint(const gfx::Point& origin) const;
255 
256   void UpdateDockInfo(const gfx::Point& point_in_screen);
257 
258   // Saves focus in the window that the drag initiated from. Focus will be
259   // restored appropriately if the drag ends within this same window.
260   void SaveFocus();
261 
262   // Restore focus to the View that had focus before the drag was started, if
263   // the drag ends within the same Window as it began.
264   void RestoreFocus();
265 
266   // Tests whether |point_in_screen| is past a minimum elasticity threshold
267   // required to start a drag.
268   bool CanStartDrag(const gfx::Point& point_in_screen) const;
269 
270   // Invoked once a drag has started to determine the appropriate tabstrip to
271   // drag to (which may be the currently attached one).
272   void ContinueDragging(const gfx::Point& point_in_screen);
273 
274   // Transitions dragging from |attached_tabstrip_| to |target_tabstrip|.
275   // |target_tabstrip| is NULL if the mouse is not over a valid tab strip.  See
276   // DragBrowserResultType for details of the return type.
277   DragBrowserResultType DragBrowserToNewTabStrip(
278       TabStrip* target_tabstrip,
279       const gfx::Point& point_in_screen);
280 
281   // Handles dragging for a touch tabstrip when the tabs are stacked. Doesn't
282   // actually reorder the tabs in anyway, just changes what's visible.
283   void DragActiveTabStacked(const gfx::Point& point_in_screen);
284 
285   // Moves the active tab to the next/previous tab. Used when the next/previous
286   // tab is stacked.
287   void MoveAttachedToNextStackedIndex(const gfx::Point& point_in_screen);
288   void MoveAttachedToPreviousStackedIndex(const gfx::Point& point_in_screen);
289 
290   // Handles dragging tabs while the tabs are attached.
291   void MoveAttached(const gfx::Point& point_in_screen);
292 
293   // If necessary starts the |move_stacked_timer_|. The timer is started if
294   // close enough to an edge with stacked tabs.
295   void StartMoveStackedTimerIfNecessary(
296       const gfx::Point& point_in_screen,
297       int delay_ms);
298 
299   // Returns the TabStrip for the specified window, or NULL if one doesn't exist
300   // or isn't compatible.
301   TabStrip* GetTabStripForWindow(gfx::NativeWindow window);
302 
303   // Returns the compatible TabStrip to drag to at the specified point (screen
304   // coordinates), or NULL if there is none.
305   TabStrip* GetTargetTabStripForPoint(const gfx::Point& point_in_screen);
306 
307   // Returns true if |tabstrip| contains the specified point in screen
308   // coordinates.
309   bool DoesTabStripContain(TabStrip* tabstrip,
310                            const gfx::Point& point_in_screen) const;
311 
312   // Returns the DetachPosition given the specified location in screen
313   // coordinates.
314   DetachPosition GetDetachPosition(const gfx::Point& point_in_screen);
315 
316   // Attach the dragged Tab to the specified TabStrip.
317   void Attach(TabStrip* attached_tabstrip, const gfx::Point& point_in_screen);
318 
319   // Detach the dragged Tab from the current TabStrip.
320   void Detach(ReleaseCapture release_capture);
321 
322   // Detaches the tabs being dragged, creates a new Browser to contain them and
323   // runs a nested move loop.
324   void DetachIntoNewBrowserAndRunMoveLoop(const gfx::Point& point_in_screen);
325 
326   // Runs a nested message loop that handles moving the current
327   // Browser. |drag_offset| is the offset from the window origin and is used in
328   // calculating the location of the window offset from the cursor while
329   // dragging.
330   void RunMoveLoop(const gfx::Vector2d& drag_offset);
331 
332   // Determines the index to insert tabs at. |dragged_bounds| is the bounds of
333   // the tabs being dragged, |start| the index of the tab to start looking from.
334   // The search proceeds to the end of the strip.
335   int GetInsertionIndexFrom(const gfx::Rect& dragged_bounds, int start) const;
336 
337   // Like GetInsertionIndexFrom(), but searches backwards from |start| to the
338   // beginning of the strip.
339   int GetInsertionIndexFromReversed(const gfx::Rect& dragged_bounds,
340                                     int start) const;
341 
342   // Returns the index where the dragged WebContents should be inserted into
343   // |attached_tabstrip_| given the DraggedTabView's bounds |dragged_bounds| in
344   // coordinates relative to |attached_tabstrip_| and has had the mirroring
345   // transformation applied.
346   // NOTE: this is invoked from Attach() before the tabs have been inserted.
347   int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds) const;
348 
349   // Returns true if |dragged_bounds| is close enough to the next stacked tab
350   // so that the active tab should be dragged there.
351   bool ShouldDragToNextStackedTab(const gfx::Rect& dragged_bounds,
352                                   int index) const;
353 
354   // Returns true if |dragged_bounds| is close enough to the previous stacked
355   // tab so that the active tab should be dragged there.
356   bool ShouldDragToPreviousStackedTab(const gfx::Rect& dragged_bounds,
357                                       int index) const;
358 
359   // Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked.
360   int GetInsertionIndexForDraggedBoundsStacked(
361       const gfx::Rect& dragged_bounds) const;
362 
363   // Retrieve the bounds of the DraggedTabView relative to the attached
364   // TabStrip. |tab_strip_point| is in the attached TabStrip's coordinate
365   // system.
366   gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& tab_strip_point);
367 
368   // Get the position of the dragged tab view relative to the attached tab
369   // strip with the mirroring transform applied.
370   gfx::Point GetAttachedDragPoint(const gfx::Point& point_in_screen);
371 
372   // Finds the Tabs within the specified TabStrip that corresponds to the
373   // WebContents of the dragged tabs. Returns an empty vector if not attached.
374   std::vector<Tab*> GetTabsMatchingDraggedContents(TabStrip* tabstrip);
375 
376   // Returns the bounds for the tabs based on the attached tab strip.
377   std::vector<gfx::Rect> CalculateBoundsForDraggedTabs();
378 
379   // Does the work for EndDrag(). If we actually started a drag and |how_end| is
380   // not TAB_DESTROYED then one of EndDrag() or RevertDrag() is invoked.
381   void EndDragImpl(EndDragType how_end);
382 
383   // Reverts a cancelled drag operation.
384   void RevertDrag();
385 
386   // Reverts the tab at |drag_index| in |drag_data_|.
387   void RevertDragAt(size_t drag_index);
388 
389   // Selects the dragged tabs in |model|. Does nothing if there are no longer
390   // any dragged contents (as happens when a WebContents is deleted out from
391   // under us).
392   void ResetSelection(TabStripModel* model);
393 
394   // Restores |initial_selection_model_| to the |source_tabstrip_|.
395   void RestoreInitialSelection();
396 
397   // Finishes a succesful drag operation.
398   void CompleteDrag();
399 
400   // Maximizes the attached window.
401   void MaximizeAttachedWindow();
402 
403   // Resets the delegates of the WebContents.
404   void ResetDelegates();
405 
406   // Returns the bounds (in screen coordinates) of the specified View.
407   gfx::Rect GetViewScreenBounds(views::View* tabstrip) const;
408 
409   // Hides the frame for the window that contains the TabStrip the current
410   // drag session was initiated from.
411   void HideFrame();
412 
413   // Closes a hidden frame at the end of a drag session.
414   void CleanUpHiddenFrame();
415 
416   void BringWindowUnderPointToFront(const gfx::Point& point_in_screen);
417 
418   // Convenience for getting the TabDragData corresponding to the tab the user
419   // started dragging.
source_tab_drag_data()420   TabDragData* source_tab_drag_data() {
421     return &(drag_data_[source_tab_index_]);
422   }
423 
424   // Convenience for |source_tab_drag_data()->contents|.
source_dragged_contents()425   content::WebContents* source_dragged_contents() {
426     return source_tab_drag_data()->contents;
427   }
428 
429   // Returns the Widget of the currently attached TabStrip's BrowserView.
430   views::Widget* GetAttachedBrowserWidget();
431 
432   // Returns true if the tabs were originality one after the other in
433   // |source_tabstrip_|.
434   bool AreTabsConsecutive();
435 
436   // Calculates and returns new bounds for the dragged browser window.
437   // Takes into consideration current and restore bounds of |source| tab strip
438   // preventing the dragged size from being too small. Positions the new bounds
439   // such that the tab that was dragged remains under the |point_in_screen|.
440   // Offsets |drag_bounds| if necessary when dragging to the right from the
441   // source browser.
442   gfx::Rect CalculateDraggedBrowserBounds(TabStrip* source,
443                                           const gfx::Point& point_in_screen,
444                                           std::vector<gfx::Rect>* drag_bounds);
445 
446   // Calculates scaled |drag_bounds| for dragged tabs and sets the tabs bounds.
447   // Layout of the tabstrip is performed and a new tabstrip width calculated.
448   // When |last_tabstrip_width| is larger than the new tabstrip width the tabs
449   // in attached tabstrip are scaled and the attached browser is positioned such
450   // that the tab that was dragged remains under the |point_in_screen|.
451   void AdjustBrowserAndTabBoundsForDrag(int last_tabstrip_width,
452                                         const gfx::Point& point_in_screen,
453                                         std::vector<gfx::Rect>* drag_bounds);
454 
455   // Creates and returns a new Browser to handle the drag.
456   Browser* CreateBrowserForDrag(TabStrip* source,
457                                 const gfx::Point& point_in_screen,
458                                 gfx::Vector2d* drag_offset,
459                                 std::vector<gfx::Rect>* drag_bounds);
460 
461   // Returns the TabStripModel for the specified tabstrip.
462   TabStripModel* GetModel(TabStrip* tabstrip) const;
463 
464   // Returns the location of the cursor. This is either the location of the
465   // mouse or the location of the current touch point.
466   gfx::Point GetCursorScreenPoint();
467 
468   // Returns the offset from the top left corner of the window to
469   // |point_in_screen|.
470   gfx::Vector2d GetWindowOffset(const gfx::Point& point_in_screen);
471 
472   // Returns true if moving the mouse only changes the visible tabs.
move_only()473   bool move_only() const {
474     return (move_behavior_ == MOVE_VISIBILE_TABS) != 0;
475   }
476 
477   // Returns the NativeWindow at the specified point. If |exclude_dragged_view|
478   // is true, then the dragged view is not considered.
479   gfx::NativeWindow GetLocalProcessWindow(const gfx::Point& screen_point,
480                                           bool exclude_dragged_view);
481 
482   // If true detaching creates a new browser and enters a nested message loop.
483   bool detach_into_browser_;
484 
485   // Handles registering for notifications.
486   content::NotificationRegistrar registrar_;
487 
488   EventSource event_source_;
489 
490   // The TabStrip the drag originated from.
491   TabStrip* source_tabstrip_;
492 
493   // The TabStrip the dragged Tab is currently attached to, or NULL if the
494   // dragged Tab is detached.
495   TabStrip* attached_tabstrip_;
496 
497   // The screen that this drag is associated with. Cached, because other UI
498   // elements are NULLd at various points during the lifetime of this object.
499   gfx::Screen* screen_;
500 
501   // The desktop type that this drag is associated with. Cached, because other
502   // UI elements are NULLd at various points during the lifetime of this
503   // object.
504   chrome::HostDesktopType host_desktop_type_;
505 
506   // Aura mouse capture and release is used on Ash platforms as well as on
507   // Linux to ensure that pointer grab is not released prematurely.
508   bool use_aura_capture_policy_;
509 
510   // The position of the mouse (in screen coordinates) at the start of the drag
511   // operation. This is used to calculate minimum elasticity before a
512   // DraggedTabView is constructed.
513   gfx::Point start_point_in_screen_;
514 
515   // This is the offset of the mouse from the top left of the first Tab where
516   // dragging began. This is used to ensure that the dragged view is always
517   // positioned at the correct location during the drag, and to ensure that the
518   // detached window is created at the right location.
519   gfx::Point mouse_offset_;
520 
521   // Ratio of the x-coordinate of the |source_tab_offset| to the width of the
522   // tab.
523   float offset_to_width_ratio_;
524 
525   // A hint to use when positioning new windows created by detaching Tabs. This
526   // is the distance of the mouse from the top left of the dragged tab as if it
527   // were the distance of the mouse from the top left of the first tab in the
528   // attached TabStrip from the top left of the window.
529   gfx::Point window_create_point_;
530 
531   // Location of the first tab in the source tabstrip in screen coordinates.
532   // This is used to calculate |window_create_point_|.
533   gfx::Point first_source_tab_point_;
534 
535   // The bounds of the browser window before the last Tab was detached. When
536   // the last Tab is detached, rather than destroying the frame (which would
537   // abort the drag session), the frame is moved off-screen. If the drag is
538   // aborted (e.g. by the user pressing Esc, or capture being lost), the Tab is
539   // attached to the hidden frame and the frame moved back to these bounds.
540   gfx::Rect restore_bounds_;
541 
542   // Storage ID in ViewStorage where the last view that had focus in the window
543   // containing |source_tab_| is saved. This is saved so that focus can be
544   // restored properly when a drag begins and ends within this same window.
545   const int old_focused_view_id_;
546 
547   // The horizontal position of the mouse cursor in screen coordinates at the
548   // time of the last re-order event.
549   int last_move_screen_loc_;
550 
551   // Timer used to bring the window under the cursor to front. If the user
552   // stops moving the mouse for a brief time over a browser window, it is
553   // brought to front.
554   base::OneShotTimer<TabDragController> bring_to_front_timer_;
555 
556   // Timer used to move the stacked tabs. See comment aboue
557   // StartMoveStackedTimerIfNecessary().
558   base::OneShotTimer<TabDragController> move_stacked_timer_;
559 
560   // Did the mouse move enough that we started a drag?
561   bool started_drag_;
562 
563   // Is the drag active?
564   bool active_;
565 
566   DragData drag_data_;
567 
568   // Index of the source tab in |drag_data_|.
569   size_t source_tab_index_;
570 
571   // True until MoveAttached() is first invoked.
572   bool initial_move_;
573 
574   // The selection model before the drag started. See comment above Init() for
575   // details.
576   ui::ListSelectionModel initial_selection_model_;
577 
578   // The selection model of |attached_tabstrip_| before the tabs were attached.
579   ui::ListSelectionModel selection_model_before_attach_;
580 
581   // Initial x-coordinates of the tabs when the drag started. Only used for
582   // touch mode.
583   std::vector<int> initial_tab_positions_;
584 
585   DetachBehavior detach_behavior_;
586   MoveBehavior move_behavior_;
587 
588   // Updated as the mouse is moved when attached. Indicates whether the mouse
589   // has ever moved to the left or right. If the tabs are ever detached this
590   // is set to kMovedMouseRight | kMovedMouseLeft.
591   int mouse_move_direction_;
592 
593   // Last location used in screen coordinates.
594   gfx::Point last_point_in_screen_;
595 
596   // The following are needed when detaching into a browser
597   // (|detach_into_browser_| is true).
598 
599   // See description above getter.
600   bool is_dragging_window_;
601 
602   // True if |attached_tabstrip_| is in a browser specifically created for
603   // the drag.
604   bool is_dragging_new_browser_;
605 
606   // True if |source_tabstrip_| was maximized before the drag.
607   bool was_source_maximized_;
608 
609   // True if |source_tabstrip_| was in immersive fullscreen before the drag.
610   bool was_source_fullscreen_;
611 
612   // True if the initial drag resulted in restoring the window (because it was
613   // maximized).
614   bool did_restore_window_;
615 
616   EndRunLoopBehavior end_run_loop_behavior_;
617 
618   // If true, we're waiting for a move loop to complete.
619   bool waiting_for_run_loop_to_exit_;
620 
621   // The TabStrip to attach to after the move loop completes.
622   TabStrip* tab_strip_to_attach_to_after_exit_;
623 
624   // Non-null for the duration of RunMoveLoop.
625   views::Widget* move_loop_widget_;
626 
627   // See description above getter.
628   bool is_mutating_;
629 
630   // |attach_x_| and |attach_index_| are set to the x-coordinate of the mouse
631   // (in terms of the tabstrip) and the insertion index at the time tabs are
632   // dragged into a new browser (attached). They are used to ensure we don't
633   // shift the tabs around in the wrong direction. The two are only valid if
634   // |attach_index_| is not -1.
635   // See comment around use for more details.
636   int attach_x_;
637   int attach_index_;
638 
639   scoped_ptr<ui::EventHandler> escape_tracker_;
640 
641   base::WeakPtrFactory<TabDragController> weak_factory_;
642 
643   DISALLOW_COPY_AND_ASSIGN(TabDragController);
644 };
645 
646 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
647