tab_drag_controller.h revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Use of this source code is governed by a BSD-style license that can be
383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius// found in the LICENSE file.
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <vector>
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/memory/scoped_ptr.h"
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/memory/weak_ptr.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/message_loop/message_loop.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "base/timer/timer.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/tabs/dock_info.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "chrome/browser/ui/views/tabs/tab_strip_types.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/notification_observer.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/notification_registrar.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "content/public/browser/web_contents_delegate.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/base/models/list_selection_model.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/gfx/rect.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ui/views/widget/widget_observer.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace gfx {
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Screen;
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace ui {
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass ListSelectionModel;
2950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querunamespace views {
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass View;
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Browser;
3450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass DraggedTabView;
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass Tab;
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct TabRendererData;
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabStrip;
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabStripModel;
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TabDragController is responsible for managing the tab dragging session. When
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the user presses the mouse on a tab a new TabDragController is created and
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Drag() is invoked as the mouse is dragged. If the mouse is dragged far enough
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// TabDragController starts a drag session. The drag session is completed when
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// EndDrag() is invoked (or the TabDragController is destroyed).
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// While dragging within a tab strip TabDragController sets the bounds of the
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// tabs (this is referred to as attached). When the user drags far enough such
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// that the tabs should be moved out of the tab strip two possible things
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// can happen (this state is referred to as detached):
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// . If |detach_into_browser_| is true then a new Browser is created and
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   RunMoveLoop() is invoked on the Widget to drag the browser around. This is
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   the default on aura.
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// . If |detach_into_browser_| is false a small representation of the active tab
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   is created and that is dragged around. This mode does not run a nested
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//   message loop.
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TabDragController : public content::WebContentsDelegate,
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          public content::NotificationObserver,
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          public base::MessageLoopForUI::Observer,
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          public views::WidgetObserver,
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                          public TabStripModelObserver {
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru public:
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum DetachBehavior {
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DETACHABLE,
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NOT_DETACHABLE
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // What should happen as the mouse is dragged within the tabstrip.
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum MoveBehavior {
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Only the set of visible tabs should change. This is only applicable when
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // using touch layout.
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    MOVE_VISIBILE_TABS,
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Typical behavior where tabs are dragged around.
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    REORDER
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Indicates the event source that initiated the drag.
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum EventSource {
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    EVENT_SOURCE_MOUSE,
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    EVENT_SOURCE_TOUCH,
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Amount above or below the tabstrip the user has to drag before detaching.
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  static const int kTouchVerticalDetachMagnetism;
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  static const int kVerticalDetachMagnetism;
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  TabDragController();
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual ~TabDragController();
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Initializes TabDragController to drag the tabs in |tabs| originating from
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // |source_tabstrip|. |source_tab| is the tab that initiated the drag and is
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // contained in |tabs|.  |mouse_offset| is the distance of the mouse pointer
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // from the origin of the first tab in |tabs| and |source_tab_offset| the
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // offset from |source_tab|. |source_tab_offset| is the horizontal offset of
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // |mouse_offset| relative to |source_tab|. |initial_selection_model| is the
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // selection model before the drag started and is only non-empty if
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // |source_tab| was not initially selected.
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void Init(TabStrip* source_tabstrip,
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Tab* source_tab,
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const std::vector<Tab*>& tabs,
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const gfx::Point& mouse_offset,
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int source_tab_offset,
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const ui::ListSelectionModel& initial_selection_model,
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            DetachBehavior detach_behavior,
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            MoveBehavior move_behavior,
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            EventSource event_source);
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Returns true if there is a drag underway and the drag is attached to
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // |tab_strip|.
11083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  // NOTE: this returns false if the TabDragController is in the process of
11183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  // finishing the drag.
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  static bool IsAttachedTo(TabStrip* tab_strip);
11383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
11483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  // Returns true if there is a drag underway.
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  static bool IsActive();
11683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
11783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  // Used to determine whether the tab drag controller detaches dragged tabs
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // into new browser windows while the drag is in process.
11983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  static bool ShouldDetachIntoNewBrowser();
12083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Sets the move behavior. Has no effect if started_drag() is true.
12283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  void SetMoveBehavior(MoveBehavior behavior);
12383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  MoveBehavior move_behavior() const { return move_behavior_; }
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
12583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  EventSource event_source() const { return event_source_; }
12683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // See description above fields for details on these.
12883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  bool active() const { return active_; }
12983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  const TabStrip* attached_tabstrip() const { return attached_tabstrip_; }
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Returns true if a drag started.
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  bool started_drag() const { return started_drag_; }
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Returns true if mutating the TabStripModel.
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  bool is_mutating() const { return is_mutating_; }
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Returns true if we've detached from a tabstrip and are running a nested
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // move message loop.
13983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  bool is_dragging_window() const { return is_dragging_window_; }
14083a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Invoked to drag to the new location, in screen coordinates.
14283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  void Drag(const gfx::Point& point_in_screen);
14383a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Complete the current drag session.
14583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  void EndDrag(EndDragReason reason);
14683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru private:
14883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  class DockDisplayer;
14983a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  friend class DockDisplayer;
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  typedef std::set<gfx::NativeView> DockWindows;
15283a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Used to indicate the direction the mouse has moved when attached.
15483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  static const int kMovedMouseLeft  = 1 << 0;
15583a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  static const int kMovedMouseRight = 1 << 1;
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  // Enumeration of the ways a drag session can end.
15883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius  enum EndDragType {
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Drag session exited normally: the user released the mouse.
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NORMAL,
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // The drag session was canceled (alt-tab during drag, escape ...)
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    CANCELED,
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // The tab (NavigationController) was destroyed during the drag.
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TAB_DESTROYED
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Whether Detach() should release capture or not.
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum ReleaseCapture {
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RELEASE_CAPTURE,
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DONT_RELEASE_CAPTURE,
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Specifies what should happen when RunMoveLoop completes.
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum EndRunLoopBehavior {
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Indicates the drag should end.
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_RUN_LOOP_STOP_DRAGGING,
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Indicates the drag should continue.
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_RUN_LOOP_CONTINUE_DRAGGING
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Enumeration of the possible positions the detached tab may detach from.
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum DetachPosition {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DETACH_BEFORE,
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DETACH_AFTER,
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DETACH_ABOVE_OR_BELOW
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Indicates what should happen after invoking DragBrowserToNewTabStrip().
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  enum DragBrowserResultType {
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // The caller should return immediately. This return value is used if a
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // nested message loop was created or we're in a nested message loop and
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // need to exit it.
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DRAG_BROWSER_RESULT_STOP,
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // The caller should continue.
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DRAG_BROWSER_RESULT_CONTINUE,
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Stores the date associated with a single tab that is being dragged.
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  struct TabDragData {
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TabDragData();
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ~TabDragData();
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // The WebContents being dragged.
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    content::WebContents* contents;
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // content::WebContentsDelegate for |contents| before it was detached from
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the browser window. We store this so that we can forward certain delegate
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // notifications back to it if we can't handle them locally.
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    content::WebContentsDelegate* original_delegate;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This is the index of the tab in |source_tabstrip_| when the drag
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // began. This is used to restore the previous state if the drag is aborted.
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int source_model_index;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If attached this is the tab in |attached_tabstrip_|.
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Tab* attached_tab;
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Is the tab pinned?
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    bool pinned;
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  };
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  typedef std::vector<TabDragData> DragData;
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Sets |drag_data| from |tab|. This also registers for necessary
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // notifications and resets the delegate of the WebContents.
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void InitTabDragData(Tab* tab, TabDragData* drag_data);
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Overridden from content::WebContentsDelegate:
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual content::WebContents* OpenURLFromTab(
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      content::WebContents* source,
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const content::OpenURLParams& params) OVERRIDE;
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void NavigationStateChanged(const content::WebContents* source,
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                      unsigned changed_flags) OVERRIDE;
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void AddNewContents(content::WebContents* source,
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              content::WebContents* new_contents,
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              WindowOpenDisposition disposition,
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              const gfx::Rect& initial_pos,
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              bool user_gesture,
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              bool* was_blocked) OVERRIDE;
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual bool ShouldSuppressDialogs() OVERRIDE;
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual content::JavaScriptDialogManager*
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      GetJavaScriptDialogManager() OVERRIDE;
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void RequestMediaAccessPermission(
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      content::WebContents* web_contents,
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const content::MediaStreamRequest& request,
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const content::MediaResponseCallback& callback) OVERRIDE;
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Overridden from content::NotificationObserver:
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void Observe(int type,
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       const content::NotificationSource& source,
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                       const content::NotificationDetails& details) OVERRIDE;
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Overridden from MessageLoop::Observer:
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual base::EventStatus WillProcessEvent(
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      const base::NativeEvent& event) OVERRIDE;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Overriden from views::WidgetObserver:
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void OnWidgetBoundsChanged(views::Widget* widget,
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     const gfx::Rect& new_bounds) OVERRIDE;
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Overriden from TabStripModelObserver:
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  virtual void TabStripEmpty() OVERRIDE;
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Initialize the offset used to calculate the position to create windows
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // in |GetWindowCreatePoint|. This should only be invoked from |Init|.
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void InitWindowCreatePoint();
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Returns the point where a detached window should be created given the
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // current mouse position |origin|.
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  gfx::Point GetWindowCreatePoint(const gfx::Point& origin) const;
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void UpdateDockInfo(const gfx::Point& point_in_screen);
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Saves focus in the window that the drag initiated from. Focus will be
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // restored appropriately if the drag ends within this same window.
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void SaveFocus();
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Restore focus to the View that had focus before the drag was started, if
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // the drag ends within the same Window as it began.
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  void RestoreFocus();
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  // Tests whether |point_in_screen| is past a minimum elasticity threshold
28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // required to start a drag.
29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  bool CanStartDrag(const gfx::Point& point_in_screen) const;
29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Move the DraggedTabView according to the current mouse screen position,
29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // potentially updating the source and other TabStrips.
29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  void ContinueDragging(const gfx::Point& point_in_screen);
29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Transitions dragging from |attached_tabstrip_| to |target_tabstrip|.
29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // |target_tabstrip| is NULL if the mouse is not over a valid tab strip.  See
29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // DragBrowserResultType for details of the return type.
29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  DragBrowserResultType DragBrowserToNewTabStrip(
30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      TabStrip* target_tabstrip,
30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      const gfx::Point& point_in_screen);
30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Handles dragging for a touch tabstrip when the tabs are stacked. Doesn't
30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // actually reorder the tabs in anyway, just changes what's visible.
30527f654740f2a26ad62a5c155af9199af9e69b889claireho  void DragActiveTabStacked(const gfx::Point& point_in_screen);
30627f654740f2a26ad62a5c155af9199af9e69b889claireho
30727f654740f2a26ad62a5c155af9199af9e69b889claireho  // Moves the active tab to the next/previous tab. Used when the next/previous
30827f654740f2a26ad62a5c155af9199af9e69b889claireho  // tab is stacked.
30927f654740f2a26ad62a5c155af9199af9e69b889claireho  void MoveAttachedToNextStackedIndex(const gfx::Point& point_in_screen);
31027f654740f2a26ad62a5c155af9199af9e69b889claireho  void MoveAttachedToPreviousStackedIndex(const gfx::Point& point_in_screen);
31127f654740f2a26ad62a5c155af9199af9e69b889claireho
31227f654740f2a26ad62a5c155af9199af9e69b889claireho  // Handles dragging tabs while the tabs are attached.
31327f654740f2a26ad62a5c155af9199af9e69b889claireho  void MoveAttached(const gfx::Point& point_in_screen);
31427f654740f2a26ad62a5c155af9199af9e69b889claireho
31527f654740f2a26ad62a5c155af9199af9e69b889claireho  // Handles dragging while the tabs are detached.
31627f654740f2a26ad62a5c155af9199af9e69b889claireho  void MoveDetached(const gfx::Point& point_in_screen);
31727f654740f2a26ad62a5c155af9199af9e69b889claireho
31827f654740f2a26ad62a5c155af9199af9e69b889claireho  // If necessary starts the |move_stacked_timer_|. The timer is started if
31927f654740f2a26ad62a5c155af9199af9e69b889claireho  // close enough to an edge with stacked tabs.
32027f654740f2a26ad62a5c155af9199af9e69b889claireho  void StartMoveStackedTimerIfNecessary(
32127f654740f2a26ad62a5c155af9199af9e69b889claireho      const gfx::Point& point_in_screen,
32227f654740f2a26ad62a5c155af9199af9e69b889claireho      int delay_ms);
32327f654740f2a26ad62a5c155af9199af9e69b889claireho
32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Returns the TabStrip for the specified window, or NULL if one doesn't exist
32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // or isn't compatible.
32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  TabStrip* GetTabStripForWindow(gfx::NativeWindow window);
32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Returns the compatible TabStrip to drag to at the specified point (screen
32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // coordinates), or NULL if there is none.
33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  TabStrip* GetTargetTabStripForPoint(const gfx::Point& point_in_screen);
33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Returns true if |tabstrip| contains the specified point in screen
33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // coordinates.
33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  bool DoesTabStripContain(TabStrip* tabstrip,
33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                           const gfx::Point& point_in_screen) const;
33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // Returns the DetachPosition given the specified location in screen
33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  // coordinates.
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  DetachPosition GetDetachPosition(const gfx::Point& point_in_screen);
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  DockInfo GetDockInfoAtPoint(const gfx::Point& point_in_screen);
342
343  // Attach the dragged Tab to the specified TabStrip.
344  void Attach(TabStrip* attached_tabstrip, const gfx::Point& point_in_screen);
345
346  // Detach the dragged Tab from the current TabStrip.
347  void Detach(ReleaseCapture release_capture);
348
349  // Detaches the tabs being dragged, creates a new Browser to contain them and
350  // runs a nested move loop.
351  void DetachIntoNewBrowserAndRunMoveLoop(const gfx::Point& point_in_screen);
352
353  // Runs a nested message loop that handles moving the current
354  // Browser. |drag_offset| is the offset from the window origin and is used in
355  // calculating the location of the window offset from the cursor while
356  // dragging.
357  void RunMoveLoop(const gfx::Vector2d& drag_offset);
358
359  // Determines the index to insert tabs at. |dragged_bounds| is the bounds of
360  // the tabs being dragged, |start| the index of the tab to start looking from
361  // and |delta| the amount to increment (1 or -1).
362  int GetInsertionIndexFrom(const gfx::Rect& dragged_bounds,
363                            int start,
364                            int delta) const;
365
366  // Returns the index where the dragged WebContents should be inserted into
367  // |attached_tabstrip_| given the DraggedTabView's bounds |dragged_bounds| in
368  // coordinates relative to |attached_tabstrip_| and has had the mirroring
369  // transformation applied.
370  // NOTE: this is invoked from Attach() before the tabs have been inserted.
371  int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds) const;
372
373  // Returns true if |dragged_bounds| is close enough to the next stacked tab
374  // so that the active tab should be dragged there.
375  bool ShouldDragToNextStackedTab(const gfx::Rect& dragged_bounds,
376                                  int index) const;
377
378  // Returns true if |dragged_bounds| is close enough to the previous stacked
379  // tab so that the active tab should be dragged there.
380  bool ShouldDragToPreviousStackedTab(const gfx::Rect& dragged_bounds,
381                                      int index) const;
382
383  // Used by GetInsertionIndexForDraggedBounds() when the tabstrip is stacked.
384  int GetInsertionIndexForDraggedBoundsStacked(
385      const gfx::Rect& dragged_bounds) const;
386
387  // Retrieve the bounds of the DraggedTabView relative to the attached
388  // TabStrip. |tab_strip_point| is in the attached TabStrip's coordinate
389  // system.
390  gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& tab_strip_point);
391
392  // Get the position of the dragged tab view relative to the attached tab
393  // strip with the mirroring transform applied.
394  gfx::Point GetAttachedDragPoint(const gfx::Point& point_in_screen);
395
396  // Finds the Tabs within the specified TabStrip that corresponds to the
397  // WebContents of the dragged tabs. Returns an empty vector if not attached.
398  std::vector<Tab*> GetTabsMatchingDraggedContents(TabStrip* tabstrip);
399
400  // Returns the bounds for the tabs based on the attached tab strip.
401  std::vector<gfx::Rect> CalculateBoundsForDraggedTabs();
402
403  // Does the work for EndDrag(). If we actually started a drag and |how_end| is
404  // not TAB_DESTROYED then one of EndDrag() or RevertDrag() is invoked.
405  void EndDragImpl(EndDragType how_end);
406
407  // Reverts a cancelled drag operation.
408  void RevertDrag();
409
410  // Reverts the tab at |drag_index| in |drag_data_|.
411  void RevertDragAt(size_t drag_index);
412
413  // Selects the dragged tabs in |model|. Does nothing if there are no longer
414  // any dragged contents (as happens when a WebContents is deleted out from
415  // under us).
416  void ResetSelection(TabStripModel* model);
417
418  // Finishes a succesful drag operation.
419  void CompleteDrag();
420
421  // Resets the delegates of the WebContents.
422  void ResetDelegates();
423
424  // Create the DraggedTabView.
425  void CreateDraggedView(const std::vector<TabRendererData>& data,
426                         const std::vector<gfx::Rect>& renderer_bounds);
427
428  // Returns the bounds (in screen coordinates) of the specified View.
429  gfx::Rect GetViewScreenBounds(views::View* tabstrip) const;
430
431  // Hides the frame for the window that contains the TabStrip the current
432  // drag session was initiated from.
433  void HideFrame();
434
435  // Closes a hidden frame at the end of a drag session.
436  void CleanUpHiddenFrame();
437
438  void DockDisplayerDestroyed(DockDisplayer* controller);
439
440  void BringWindowUnderPointToFront(const gfx::Point& point_in_screen);
441
442  // Convenience for getting the TabDragData corresponding to the tab the user
443  // started dragging.
444  TabDragData* source_tab_drag_data() {
445    return &(drag_data_[source_tab_index_]);
446  }
447
448  // Convenience for |source_tab_drag_data()->contents|.
449  content::WebContents* source_dragged_contents() {
450    return source_tab_drag_data()->contents;
451  }
452
453  // Returns the Widget of the currently attached TabStrip's BrowserView.
454  views::Widget* GetAttachedBrowserWidget();
455
456  // Returns true if the tabs were originality one after the other in
457  // |source_tabstrip_|.
458  bool AreTabsConsecutive();
459
460  // Creates and returns a new Browser to handle the drag.
461  Browser* CreateBrowserForDrag(TabStrip* source,
462                                const gfx::Point& point_in_screen,
463                                gfx::Vector2d* drag_offset,
464                                std::vector<gfx::Rect>* drag_bounds);
465
466  // Returns the TabStripModel for the specified tabstrip.
467  TabStripModel* GetModel(TabStrip* tabstrip) const;
468
469  // Returns the location of the cursor. This is either the location of the
470  // mouse or the location of the current touch point.
471  gfx::Point GetCursorScreenPoint();
472
473  // Returns the offset from the top left corner of the window to
474  // |point_in_screen|.
475  gfx::Vector2d GetWindowOffset(const gfx::Point& point_in_screen);
476
477  // Returns true if moving the mouse only changes the visible tabs.
478  bool move_only() const {
479    return (move_behavior_ == MOVE_VISIBILE_TABS) != 0;
480  }
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  // The visual representation of the dragged Tab.
507  scoped_ptr<DraggedTabView> view_;
508
509  // The position of the mouse (in screen coordinates) at the start of the drag
510  // operation. This is used to calculate minimum elasticity before a
511  // DraggedTabView is constructed.
512  gfx::Point start_point_in_screen_;
513
514  // This is the offset of the mouse from the top left of the first Tab where
515  // dragging began. This is used to ensure that the dragged view is always
516  // positioned at the correct location during the drag, and to ensure that the
517  // detached window is created at the right location.
518  gfx::Point mouse_offset_;
519
520  // Ratio of the x-coordinate of the |source_tab_offset| to the width of the
521  // tab.
522  float offset_to_width_ratio_;
523
524  // A hint to use when positioning new windows created by detaching Tabs. This
525  // is the distance of the mouse from the top left of the dragged tab as if it
526  // were the distance of the mouse from the top left of the first tab in the
527  // attached TabStrip from the top left of the window.
528  gfx::Point window_create_point_;
529
530  // Location of the first tab in the source tabstrip in screen coordinates.
531  // This is used to calculate |window_create_point_|.
532  gfx::Point first_source_tab_point_;
533
534  // The bounds of the browser window before the last Tab was detached. When
535  // the last Tab is detached, rather than destroying the frame (which would
536  // abort the drag session), the frame is moved off-screen. If the drag is
537  // aborted (e.g. by the user pressing Esc, or capture being lost), the Tab is
538  // attached to the hidden frame and the frame moved back to these bounds.
539  gfx::Rect restore_bounds_;
540
541  // ID of the last view that had focus in the window containing
542  // |source_tab_|. This is saved so that focus can be restored properly when a
543  // drag begins and ends within this same window.
544  const int old_focused_view_id_;
545
546  // The horizontal position of the mouse cursor in screen coordinates at the
547  // time of the last re-order event.
548  int last_move_screen_loc_;
549
550  DockInfo dock_info_;
551
552  DockWindows dock_windows_;
553
554  std::vector<DockDisplayer*> dock_controllers_;
555
556  // Timer used to bring the window under the cursor to front. If the user
557  // stops moving the mouse for a brief time over a browser window, it is
558  // brought to front.
559  base::OneShotTimer<TabDragController> bring_to_front_timer_;
560
561  // Timer used to move the stacked tabs. See comment aboue
562  // StartMoveStackedTimerIfNecessary().
563  base::OneShotTimer<TabDragController> move_stacked_timer_;
564
565  // Did the mouse move enough that we started a drag?
566  bool started_drag_;
567
568  // Is the drag active?
569  bool active_;
570
571  DragData drag_data_;
572
573  // Index of the source tab in |drag_data_|.
574  size_t source_tab_index_;
575
576  // True until MoveAttached() is first invoked.
577  bool initial_move_;
578
579  // The selection model before the drag started. See comment above Init() for
580  // details.
581  ui::ListSelectionModel initial_selection_model_;
582
583  // The selection model of |attached_tabstrip_| before the tabs were attached.
584  ui::ListSelectionModel selection_model_before_attach_;
585
586  // Initial x-coordinates of the tabs when the drag started. Only used for
587  // touch mode.
588  std::vector<int> initial_tab_positions_;
589
590  DetachBehavior detach_behavior_;
591  MoveBehavior move_behavior_;
592
593  // Updated as the mouse is moved when attached. Indicates whether the mouse
594  // has ever moved to the left or right. If the tabs are ever detached this
595  // is set to kMovedMouseRight | kMovedMouseLeft.
596  int mouse_move_direction_;
597
598  // Last location used in screen coordinates.
599  gfx::Point last_point_in_screen_;
600
601  // The following are needed when detaching into a browser
602  // (|detach_into_browser_| is true).
603
604  // See description above getter.
605  bool is_dragging_window_;
606
607  // True if |attached_tabstrip_| is in a browser specifically created for
608  // the drag.
609  bool is_dragging_new_browser_;
610
611  // True if |source_tabstrip_| was maximized before the drag.
612  bool was_source_maximized_;
613
614  // True if |source_tabstrip_| was in immersive fullscreen before the drag.
615  bool was_source_fullscreen_;
616
617  EndRunLoopBehavior end_run_loop_behavior_;
618
619  // If true, we're waiting for a move loop to complete.
620  bool waiting_for_run_loop_to_exit_;
621
622  // The TabStrip to attach to after the move loop completes.
623  TabStrip* tab_strip_to_attach_to_after_exit_;
624
625  // Non-null for the duration of RunMoveLoop.
626  views::Widget* move_loop_widget_;
627
628  // See description above getter.
629  bool is_mutating_;
630
631  // |attach_x_| and |attach_index_| are set to the x-coordinate of the mouse
632  // (in terms of the tabstrip) and the insertion index at the time tabs are
633  // dragged into a new browser (attached). They are used to ensure we don't
634  // shift the tabs around in the wrong direction. The two are only valid if
635  // |attach_index_| is not -1.
636  // See comment around use for more details.
637  int attach_x_;
638  int attach_index_;
639
640  base::WeakPtrFactory<TabDragController> weak_factory_;
641
642  DISALLOW_COPY_AND_ASSIGN(TabDragController);
643};
644
645#endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_DRAG_CONTROLLER_H_
646