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