• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/memory/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 
21 class DraggedTabGtk;
22 class TabGtk;
23 class TabStripGtk;
24 class TabContentsWrapper;
25 
26 class 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 UpdateTargetURL(TabContents* source, const GURL& url);
92 
93   // Overridden from NotificationObserver:
94   virtual void Observe(NotificationType type,
95                        const NotificationSource& source,
96                        const NotificationDetails& details);
97 
98   // Initialize the offset used to calculate the position to create windows
99   // in |GetWindowCreatePoint|.
100   void InitWindowCreatePoint();
101 
102   // Returns the point where a detached window should be created given the
103   // current mouse position.
104   gfx::Point GetWindowCreatePoint() const;
105 
106   // Sets the TabContents being dragged with the specified |new_contents|.
107   void SetDraggedContents(TabContentsWrapper* new_contents);
108 
109   // Move the DraggedTabView according to the current mouse screen position,
110   // potentially updating the source and other TabStrips.
111   void ContinueDragging();
112 
113   // Handles moving the Tab within a TabStrip as well as updating the View.
114   void MoveTab(const gfx::Point& screen_point);
115 
116   // Returns the compatible TabStrip that is under the specified point (screen
117   // coordinates), or NULL if there is none.
118   TabStripGtk* GetTabStripForPoint(const gfx::Point& screen_point);
119 
120   // Returns the specified |tabstrip| if it contains the specified point
121   // (screen coordinates), NULL if it does not.
122   TabStripGtk* GetTabStripIfItContains(TabStripGtk* tabstrip,
123                                        const gfx::Point& screen_point) const;
124 
125   // Attach the dragged Tab to the specified TabStrip.
126   void Attach(TabStripGtk* attached_tabstrip, const gfx::Point& screen_point);
127 
128   // Detach the dragged Tab from the current TabStrip.
129   void Detach();
130 
131   // Converts a screen point to a point relative to the tab strip.
132   gfx::Point ConvertScreenPointToTabStripPoint(TabStripGtk* tabstrip,
133                                                const gfx::Point& screen_point);
134 
135   // Retrieve the bounds of the DraggedTabGtk, relative to the attached
136   // TabStrip, given location of the dragged tab in screen coordinates.
137   gfx::Rect GetDraggedTabTabStripBounds(const gfx::Point& screen_point);
138 
139   // Returns the index where the dragged TabContents should be inserted into
140   // the attached TabStripModel given the DraggedTabView's bounds
141   // |dragged_bounds| in coordinates relative to the attached TabStrip.
142   // |is_tab_attached| is true if the tab has already been added.
143   int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds,
144                                         bool is_tab_attached) const;
145 
146   // Get the position of the dragged tab relative to the attached tab strip.
147   gfx::Point GetDraggedTabPoint(const gfx::Point& screen_point);
148 
149   // Finds the Tab within the specified TabStrip that corresponds to the
150   // dragged TabContents.
151   TabGtk* GetTabMatchingDraggedContents(TabStripGtk* tabstrip) const;
152 
153   // Does the work for EndDrag. Returns whether the tab has been destroyed.
154   bool EndDragImpl(EndDragType how_end);
155 
156   // If the drag was aborted for some reason, this function is called to un-do
157   // the changes made during the drag operation.
158   void RevertDrag();
159 
160   // Finishes the drag operation. Returns true if the drag controller should
161   // be destroyed immediately, false otherwise.
162   bool CompleteDrag();
163 
164   // Create the DraggedTabGtk if it does not yet exist.
165   void EnsureDraggedTab();
166 
167   // Utility for getting the mouse position in screen coordinates.
168   gfx::Point GetCursorScreenPoint() const;
169 
170   // Gets the screen bounds of a tab.
171   static gfx::Rect GetTabScreenBounds(TabGtk* tab);
172 
173   // Utility to convert the specified TabStripModel index to something valid
174   // for the attached TabStrip.
175   int NormalizeIndexToAttachedTabStrip(int index) const;
176 
177   // Hides the window that contains the tab strip the current drag session was
178   // initiated from.
179   void HideWindow();
180 
181   // Presents the window that was hidden by HideWindow.
182   void ShowWindow();
183 
184   // Closes a hidden frame at the end of a drag session.
185   void CleanUpHiddenFrame();
186 
187   // Cleans up a source tab that is no longer used.
188   void CleanUpSourceTab();
189 
190   // Completes the drag session after the view has animated to its final
191   // position.
192   void OnAnimateToBoundsComplete();
193 
194   // Activates whichever window is under the mouse.
195   void BringWindowUnderMouseToFront();
196 
197   // Handles registering for notifications.
198   NotificationRegistrar registrar_;
199 
200   // The TabContents being dragged.
201   TabContentsWrapper* dragged_contents_;
202 
203   // The original TabContentsDelegate of |dragged_contents_|, before it was
204   // detached from the browser window. We store this so that we can forward
205   // certain delegate notifications back to it if we can't handle them locally.
206   TabContentsDelegate* original_delegate_;
207 
208   // The tab that initiated the drag session.
209   TabGtk* source_tab_;
210 
211   // The tab strip |source_tab_| originated from.
212   TabStripGtk* source_tabstrip_;
213 
214   // This is the index of the |source_tab_| in |source_tabstrip_| when the drag
215   // began. This is used to restore the previous state if the drag is aborted.
216   int source_model_index_;
217 
218   // The TabStrip the dragged Tab is currently attached to, or NULL if the
219   // dragged Tab is detached.
220   TabStripGtk* attached_tabstrip_;
221 
222   // The visual representation of the dragged Tab.
223   scoped_ptr<DraggedTabGtk> dragged_tab_;
224 
225   // The position of the mouse (in screen coordinates) at the start of the drag
226   // operation. This is used to calculate minimum elasticity before a
227   // DraggedTabView is constructed.
228   gfx::Point start_screen_point_;
229 
230   // This is the offset of the mouse from the top left of the Tab where
231   // dragging begun. This is used to ensure that the dragged view is always
232   // positioned at the correct location during the drag, and to ensure that the
233   // detached window is created at the right location.
234   gfx::Point mouse_offset_;
235 
236   // A hint to use when positioning new windows created by detaching Tabs. This
237   // is the distance of the mouse from the top left of the dragged tab as if it
238   // were the distance of the mouse from the top left of the first tab in the
239   // attached TabStrip from the top left of the window.
240   gfx::Point window_create_point_;
241 
242   // Whether we're in the destructor or not.  Makes sure we don't destroy the
243   // drag controller more than once.
244   bool in_destructor_;
245 
246   // The horizontal position of the mouse cursor in screen coordinates at the
247   // time of the last re-order event.
248   int last_move_screen_x_;
249 
250   // DockInfo for the tabstrip.
251   DockInfo dock_info_;
252 
253   typedef std::set<GtkWidget*> DockWindows;
254   DockWindows dock_windows_;
255 
256   // Is the tab mini?
257   const bool mini_;
258 
259   // Is the tab pinned?
260   const bool pinned_;
261 
262   // Timer used to bring the window under the cursor to front. If the user
263   // stops moving the mouse for a brief time over a browser window, it is
264   // brought to front.
265   base::OneShotTimer<DraggedTabControllerGtk> bring_to_front_timer_;
266 
267   DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk);
268 };
269 
270 #endif  // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
271