dragged_tab_controller_gtk.h revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2011 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_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
6#define CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
7#pragma once
8
9#include <gtk/gtk.h>
10
11#include <set>
12
13#include "base/scoped_ptr.h"
14#include "base/timer.h"
15#include "chrome/browser/ui/tabs/dock_info.h"
16#include "content/browser/tab_contents/tab_contents_delegate.h"
17#include "content/common/notification_observer.h"
18#include "content/common/notification_registrar.h"
19#include "ui/base/x/x11_util.h"
20
21class DraggedTabGtk;
22class TabGtk;
23class TabStripGtk;
24class TabContentsWrapper;
25
26class DraggedTabControllerGtk : public NotificationObserver,
27                                public TabContentsDelegate {
28 public:
29  DraggedTabControllerGtk(TabGtk* source_tab, TabStripGtk* source_tabstrip);
30  virtual ~DraggedTabControllerGtk();
31
32  // Capture information needed to be used during a drag session for this
33  // controller's associated source Tab and TabStrip. |mouse_offset| is the
34  // distance of the mouse pointer from the Tab's origin.
35  void CaptureDragInfo(const gfx::Point& mouse_offset);
36
37  // Responds to drag events subsequent to StartDrag. If the mouse moves a
38  // sufficient distance before the mouse is released, a drag session is
39  // initiated.
40  void Drag();
41
42  // Complete the current drag session. If the drag session was canceled
43  // because the user pressed Escape or something interrupted it, |canceled|
44  // is true so the helper can revert the state to the world before the drag
45  // begun. Returns whether the tab has been destroyed.
46  bool EndDrag(bool canceled);
47
48  // Retrieve the source tab if the TabContents specified matches the one being
49  // dragged by this controller, or NULL if the specified TabContents is not
50  // the same as the one being dragged.
51  TabGtk* GetDragSourceTabForContents(TabContents* contents) const;
52
53  // Returns true if the specified tab matches the tab being dragged.
54  bool IsDragSourceTab(const TabGtk* tab) const;
55
56  // Returns true if the specified tab is detached.
57  bool IsTabDetached(const TabGtk* tab) const;
58
59 private:
60  // Enumeration of the ways a drag session can end.
61  enum EndDragType {
62    // Drag session exited normally: the user released the mouse.
63    NORMAL,
64
65    // The drag session was canceled (alt-tab during drag, escape ...)
66    CANCELED,
67
68    // The tab (NavigationController) was destroyed during the drag.
69    TAB_DESTROYED
70  };
71
72  // Overridden from TabContentsDelegate:
73  virtual void OpenURLFromTab(TabContents* source,
74                              const GURL& url,
75                              const GURL& referrer,
76                              WindowOpenDisposition disposition,
77                              PageTransition::Type transition);
78  virtual void NavigationStateChanged(const TabContents* source,
79                                      unsigned changed_flags);
80  virtual void AddNewContents(TabContents* source,
81                              TabContents* new_contents,
82                              WindowOpenDisposition disposition,
83                              const gfx::Rect& initial_pos,
84                              bool user_gesture);
85  virtual void ActivateContents(TabContents* contents);
86  virtual void DeactivateContents(TabContents* contents);
87  virtual void LoadingStateChanged(TabContents* source);
88  virtual void CloseContents(TabContents* source);
89  virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
90  virtual bool IsPopup(const TabContents* source) const;
91  virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
92  virtual void UpdateTargetURL(TabContents* source, const GURL& url);
93
94  // Overridden from NotificationObserver:
95  virtual void Observe(NotificationType type,
96                       const NotificationSource& source,
97                       const NotificationDetails& details);
98
99  // Initialize the offset used to calculate the position to create windows
100  // in |GetWindowCreatePoint|.
101  void InitWindowCreatePoint();
102
103  // Returns the point where a detached window should be created given the
104  // current mouse position.
105  gfx::Point GetWindowCreatePoint() const;
106
107  // Sets the TabContents being dragged with the specified |new_contents|.
108  void SetDraggedContents(TabContentsWrapper* new_contents);
109
110  // Move the DraggedTabView according to the current mouse screen position,
111  // potentially updating the source and other TabStrips.
112  void ContinueDragging();
113
114  // Handles moving the Tab within a TabStrip as well as updating the View.
115  void MoveTab(const gfx::Point& screen_point);
116
117  // Returns the compatible TabStrip that is under the specified point (screen
118  // coordinates), or NULL if there is none.
119  TabStripGtk* GetTabStripForPoint(const gfx::Point& screen_point);
120
121  // Returns the specified |tabstrip| if it contains the specified point
122  // (screen coordinates), NULL if it does not.
123  TabStripGtk* GetTabStripIfItContains(TabStripGtk* tabstrip,
124                                       const gfx::Point& screen_point) const;
125
126  // Attach the dragged Tab to the specified TabStrip.
127  void Attach(TabStripGtk* attached_tabstrip, const gfx::Point& screen_point);
128
129  // Detach the dragged Tab from the current TabStrip.
130  void Detach();
131
132  // Converts a screen point to a point relative to the tab strip.
133  gfx::Point ConvertScreenPointToTabStripPoint(TabStripGtk* tabstrip,
134                                               const gfx::Point& screen_point);
135
136  // Retrieve the bounds of the DraggedTabGtk, relative to the attached
137  // TabStrip, given location of the dragged tab in screen coordinates.
138  gfx::Rect GetDraggedTabTabStripBounds(const gfx::Point& screen_point);
139
140  // Returns the index where the dragged TabContents should be inserted into
141  // the attached TabStripModel given the DraggedTabView's bounds
142  // |dragged_bounds| in coordinates relative to the attached TabStrip.
143  // |is_tab_attached| is true if the tab has already been added.
144  int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds,
145                                        bool is_tab_attached) const;
146
147  // Get the position of the dragged tab relative to the attached tab strip.
148  gfx::Point GetDraggedTabPoint(const gfx::Point& screen_point);
149
150  // Finds the Tab within the specified TabStrip that corresponds to the
151  // dragged TabContents.
152  TabGtk* GetTabMatchingDraggedContents(TabStripGtk* tabstrip) const;
153
154  // Does the work for EndDrag. Returns whether the tab has been destroyed.
155  bool EndDragImpl(EndDragType how_end);
156
157  // If the drag was aborted for some reason, this function is called to un-do
158  // the changes made during the drag operation.
159  void RevertDrag();
160
161  // Finishes the drag operation. Returns true if the drag controller should
162  // be destroyed immediately, false otherwise.
163  bool CompleteDrag();
164
165  // Create the DraggedTabGtk if it does not yet exist.
166  void EnsureDraggedTab();
167
168  // Utility for getting the mouse position in screen coordinates.
169  gfx::Point GetCursorScreenPoint() const;
170
171  // Gets the screen bounds of a tab.
172  static gfx::Rect GetTabScreenBounds(TabGtk* tab);
173
174  // Utility to convert the specified TabStripModel index to something valid
175  // for the attached TabStrip.
176  int NormalizeIndexToAttachedTabStrip(int index) const;
177
178  // Hides the window that contains the tab strip the current drag session was
179  // initiated from.
180  void HideWindow();
181
182  // Presents the window that was hidden by HideWindow.
183  void ShowWindow();
184
185  // Closes a hidden frame at the end of a drag session.
186  void CleanUpHiddenFrame();
187
188  // Cleans up a source tab that is no longer used.
189  void CleanUpSourceTab();
190
191  // Completes the drag session after the view has animated to its final
192  // position.
193  void OnAnimateToBoundsComplete();
194
195  // Activates whichever window is under the mouse.
196  void BringWindowUnderMouseToFront();
197
198  // Handles registering for notifications.
199  NotificationRegistrar registrar_;
200
201  // The TabContents being dragged.
202  TabContentsWrapper* dragged_contents_;
203
204  // The original TabContentsDelegate of |dragged_contents_|, before it was
205  // detached from the browser window. We store this so that we can forward
206  // certain delegate notifications back to it if we can't handle them locally.
207  TabContentsDelegate* original_delegate_;
208
209  // The tab that initiated the drag session.
210  TabGtk* source_tab_;
211
212  // The tab strip |source_tab_| originated from.
213  TabStripGtk* source_tabstrip_;
214
215  // This is the index of the |source_tab_| in |source_tabstrip_| when the drag
216  // began. This is used to restore the previous state if the drag is aborted.
217  int source_model_index_;
218
219  // The TabStrip the dragged Tab is currently attached to, or NULL if the
220  // dragged Tab is detached.
221  TabStripGtk* attached_tabstrip_;
222
223  // The visual representation of the dragged Tab.
224  scoped_ptr<DraggedTabGtk> dragged_tab_;
225
226  // The position of the mouse (in screen coordinates) at the start of the drag
227  // operation. This is used to calculate minimum elasticity before a
228  // DraggedTabView is constructed.
229  gfx::Point start_screen_point_;
230
231  // This is the offset of the mouse from the top left of the Tab where
232  // dragging begun. This is used to ensure that the dragged view is always
233  // positioned at the correct location during the drag, and to ensure that the
234  // detached window is created at the right location.
235  gfx::Point mouse_offset_;
236
237  // A hint to use when positioning new windows created by detaching Tabs. This
238  // is the distance of the mouse from the top left of the dragged tab as if it
239  // were the distance of the mouse from the top left of the first tab in the
240  // attached TabStrip from the top left of the window.
241  gfx::Point window_create_point_;
242
243  // Whether we're in the destructor or not.  Makes sure we don't destroy the
244  // drag controller more than once.
245  bool in_destructor_;
246
247  // The horizontal position of the mouse cursor in screen coordinates at the
248  // time of the last re-order event.
249  int last_move_screen_x_;
250
251  // DockInfo for the tabstrip.
252  DockInfo dock_info_;
253
254  typedef std::set<GtkWidget*> DockWindows;
255  DockWindows dock_windows_;
256
257  // Is the tab mini?
258  const bool mini_;
259
260  // Is the tab pinned?
261  const bool pinned_;
262
263  // Timer used to bring the window under the cursor to front. If the user
264  // stops moving the mouse for a brief time over a browser window, it is
265  // brought to front.
266  base::OneShotTimer<DraggedTabControllerGtk> bring_to_front_timer_;
267
268  DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk);
269};
270
271#endif  // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
272