summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h
blob: 4e757c69e862e538bf9e3a8bb89ffe3f3d8cc5ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
#define CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_

#include <gtk/gtk.h>

#include <set>
#include <vector>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer.h"
#include "chrome/browser/ui/gtk/tabs/drag_data.h"
#include "chrome/browser/ui/tabs/dock_info.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_delegate.h"
#include "ui/base/x/x11_util.h"

class DraggedViewGtk;
class TabGtk;
class TabStripGtk;
class TabStripModel;

class DraggedTabControllerGtk : public content::NotificationObserver,
                                public content::WebContentsDelegate {
 public:
  // |source_tabstrip| is the tabstrip where the tabs reside before any
  // dragging occurs. |source_tab| is the tab that is under the mouse pointer
  // when dragging starts, it also becomes the active tab if not active
  // already. |tabs| contains all the selected tabs when dragging starts.
  DraggedTabControllerGtk(TabStripGtk* source_tabstrip, TabGtk* source_tab,
                          const std::vector<TabGtk*>& tabs);
  virtual ~DraggedTabControllerGtk();

  // Capture information needed to be used during a drag session for this
  // controller's associated source Tab and TabStrip. |mouse_offset| is the
  // distance of the mouse pointer from the Tab's origin.
  void CaptureDragInfo(const gfx::Point& mouse_offset);

  // Responds to drag events subsequent to StartDrag. If the mouse moves a
  // sufficient distance before the mouse is released, a drag session is
  // initiated.
  void Drag();

  // Complete the current drag session. If the drag session was canceled
  // because the user pressed Escape or something interrupted it, |canceled|
  // is true so the helper can revert the state to the world before the drag
  // begun. Returns whether the tab has been destroyed.
  bool EndDrag(bool canceled);

  // Retrieve the tab that corresponds to |contents| if it is being dragged by
  // this controller, or NULL if |contents| does not correspond to any tab
  // being dragged.
  TabGtk* GetDraggedTabForContents(content::WebContents* contents);

  // Returns true if |tab| matches any tab being dragged.
  bool IsDraggingTab(const TabGtk* tab);

  // Returns true if |web_contents| matches any tab contents being dragged.
  bool IsDraggingWebContents(const content::WebContents* web_contents);

  // Returns true if the specified tab is detached.
  bool IsTabDetached(const TabGtk* tab);

 private:
  // Enumeration of the ways a drag session can end.
  enum EndDragType {
    // Drag session exited normally: the user released the mouse.
    NORMAL,

    // The drag session was canceled (alt-tab during drag, escape ...)
    CANCELED,

    // The tab (NavigationController) was destroyed during the drag.
    TAB_DESTROYED
  };

  DraggedTabData InitDraggedTabData(TabGtk* tab);

  // Overridden from content::WebContentsDelegate:
  virtual content::WebContents* OpenURLFromTab(
    content::WebContents* source,
    const content::OpenURLParams& params) OVERRIDE;
  virtual void NavigationStateChanged(const content::WebContents* source,
                                      unsigned changed_flags) OVERRIDE;
  virtual void AddNewContents(content::WebContents* source,
                              content::WebContents* new_contents,
                              WindowOpenDisposition disposition,
                              const gfx::Rect& initial_pos,
                              bool user_gesture,
                              bool* was_blocked) OVERRIDE;
  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
  virtual content::JavaScriptDialogManager*
      GetJavaScriptDialogManager() OVERRIDE;

  // Overridden from content::NotificationObserver:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Returns the point where a detached window should be created given the
  // current mouse position.
  gfx::Point GetWindowCreatePoint() const;

  // Move the DraggedTabView according to the current mouse screen position,
  // potentially updating the source and other TabStrips.
  void ContinueDragging();

  // Handles dragging tabs while the tabs are attached.
  void MoveAttached(const gfx::Point& screen_point);

  // Handles dragging while the tabs are detached.
  void MoveDetached(const gfx::Point& screen_point);

  // Selects the dragged tabs within |model|.
  void RestoreSelection(TabStripModel* model);

  // Returns the compatible TabStrip that is under the specified point (screen
  // coordinates), or NULL if there is none.
  TabStripGtk* GetTabStripForPoint(const gfx::Point& screen_point);

  // Returns the specified |tabstrip| if it contains the specified point
  // (screen coordinates), NULL if it does not.
  TabStripGtk* GetTabStripIfItContains(TabStripGtk* tabstrip,
                                       const gfx::Point& screen_point) const;

  // Attach the dragged Tab to the specified TabStrip.
  void Attach(TabStripGtk* attached_tabstrip, const gfx::Point& screen_point);

  // Detach the dragged Tab from the current TabStrip.
  void Detach();

  // Converts a screen point to a point relative to the tab strip.
  gfx::Point ConvertScreenPointToTabStripPoint(TabStripGtk* tabstrip,
                                               const gfx::Point& screen_point);

  // Retrieve the bounds of the DraggedTabGtk, relative to the attached
  // TabStrip, given location of the dragged tab in screen coordinates.
  gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& screen_point);

  // Returns the index where the dragged WebContents should be inserted into
  // the attached TabStripModel given the DraggedTabView's bounds
  // |dragged_bounds| in coordinates relative to the attached TabStrip.
  int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds);

  // Get the position of the dragged view relative to the upper left corner of
  // the screen. |screen_point| is the current position of mouse cursor.
  gfx::Point GetDraggedViewPoint(const gfx::Point& screen_point);

  // Finds the Tab within the specified TabStrip that corresponds to the
  // dragged WebContents.
  TabGtk* GetTabMatchingDraggedContents(TabStripGtk* tabstrip,
                                        content::WebContents* contents);

  // Finds all the tabs within the specified TabStrip that correspond to the
  // dragged WebContents.
  std::vector<TabGtk*> GetTabsMatchingDraggedContents(TabStripGtk* tabstrip);

  // Sets the visible and draggging property of all dragged tabs. If |repaint|
  // is true it also schedules a repaint.
  void SetDraggedTabsVisible(bool visible, bool repaint);

  // Does the work for EndDrag. Returns whether the tab has been destroyed.
  bool EndDragImpl(EndDragType how_end);

  // If the drag was aborted for some reason, this function is called to un-do
  // the changes made during the drag operation.
  void RevertDrag();

  // Finishes the drag operation. Returns true if the drag controller should
  // be destroyed immediately, false otherwise.
  bool CompleteDrag();

  // Resets the delegates of the WebContents.
  void ResetDelegates();

  // Create the DraggedViewGtk if it does not yet exist.
  void EnsureDraggedView();

  // Gets the bounds to animate the dragged view when dragging is over.
  gfx::Rect GetAnimateBounds();

  // Utility to convert the specified TabStripModel index to something valid
  // for the attached TabStrip.
  int NormalizeIndexToAttachedTabStrip(int index) const;

  // Hides the window that contains the tab strip the current drag session was
  // initiated from.
  void HideWindow();

  // Presents the window that was hidden by HideWindow.
  void ShowWindow();

  // Closes a hidden frame at the end of a drag session.
  void CleanUpHiddenFrame();

  // Cleans up all the dragged tabs when they are no longer used.
  void CleanUpDraggedTabs();

  // Completes the drag session after the view has animated to its final
  // position.
  void OnAnimateToBoundsComplete();

  // Activates whichever window is under the mouse.
  void BringWindowUnderMouseToFront();

  // Returns true if the tabs were originally one after the other in
  // |source_tabstrip_|.
  bool AreTabsConsecutive();

  // Handles registering for notifications.
  content::NotificationRegistrar registrar_;

  // The tab strip |source_tab_| originated from.
  TabStripGtk* source_tabstrip_;

  // Holds various data for each dragged tab needed to handle dragging.
  scoped_ptr<DragData> drag_data_;

  // The TabStrip the dragged Tab is currently attached to, or NULL if the
  // dragged Tab is detached.
  TabStripGtk* attached_tabstrip_;

  // The visual representation of all the dragged tabs.
  scoped_ptr<DraggedViewGtk> dragged_view_;

  // The position of the mouse (in screen coordinates) at the start of the drag
  // operation. This is used to calculate minimum elasticity before a
  // DraggedTabView is constructed.
  gfx::Point start_screen_point_;

  // This is the offset of the mouse from the top left of the Tab where
  // dragging begun. This is used to ensure that the dragged view is always
  // positioned at the correct location during the drag, and to ensure that the
  // detached window is created at the right location.
  gfx::Point mouse_offset_;

  // Whether we're in the destructor or not.  Makes sure we don't destroy the
  // drag controller more than once.
  bool in_destructor_;

  // The horizontal position of the mouse cursor in screen coordinates at the
  // time of the last re-order event.
  int last_move_screen_x_;

  // True until |MoveAttached| is invoked once.
  bool initial_move_;

  // DockInfo for the tabstrip.
  DockInfo dock_info_;

  typedef std::set<GtkWidget*> DockWindows;
  DockWindows dock_windows_;

  // Timer used to bring the window under the cursor to front. If the user
  // stops moving the mouse for a brief time over a browser window, it is
  // brought to front.
  base::OneShotTimer<DraggedTabControllerGtk> bring_to_front_timer_;

  DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk);
};

#endif  // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_