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_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
6 #define CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_
13 #include "base/basictypes.h"
14 #include "base/compiler_specific.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/timer/timer.h"
17 #include "chrome/browser/ui/gtk/tabs/drag_data.h"
18 #include "chrome/browser/ui/tabs/dock_info.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/web_contents_delegate.h"
22 #include "ui/base/x/x11_util.h"
29 class DraggedTabControllerGtk
: public content::NotificationObserver
,
30 public content::WebContentsDelegate
{
32 // |source_tabstrip| is the tabstrip where the tabs reside before any
33 // dragging occurs. |source_tab| is the tab that is under the mouse pointer
34 // when dragging starts, it also becomes the active tab if not active
35 // already. |tabs| contains all the selected tabs when dragging starts.
36 DraggedTabControllerGtk(TabStripGtk
* source_tabstrip
, TabGtk
* source_tab
,
37 const std::vector
<TabGtk
*>& tabs
);
38 virtual ~DraggedTabControllerGtk();
40 // Capture information needed to be used during a drag session for this
41 // controller's associated source Tab and TabStrip. |mouse_offset| is the
42 // distance of the mouse pointer from the Tab's origin.
43 void CaptureDragInfo(const gfx::Point
& mouse_offset
);
45 // Responds to drag events subsequent to StartDrag. If the mouse moves a
46 // sufficient distance before the mouse is released, a drag session is
50 // Complete the current drag session. If the drag session was canceled
51 // because the user pressed Escape or something interrupted it, |canceled|
52 // is true so the helper can revert the state to the world before the drag
53 // begun. Returns whether the tab has been destroyed.
54 bool EndDrag(bool canceled
);
56 // Retrieve the tab that corresponds to |contents| if it is being dragged by
57 // this controller, or NULL if |contents| does not correspond to any tab
59 TabGtk
* GetDraggedTabForContents(content::WebContents
* contents
);
61 // Returns true if |tab| matches any tab being dragged.
62 bool IsDraggingTab(const TabGtk
* tab
);
64 // Returns true if |web_contents| matches any tab contents being dragged.
65 bool IsDraggingWebContents(const content::WebContents
* web_contents
);
67 // Returns true if the specified tab is detached.
68 bool IsTabDetached(const TabGtk
* tab
);
71 // Enumeration of the ways a drag session can end.
73 // Drag session exited normally: the user released the mouse.
76 // The drag session was canceled (alt-tab during drag, escape ...)
79 // The tab (NavigationController) was destroyed during the drag.
83 DraggedTabData
InitDraggedTabData(TabGtk
* tab
);
85 // Overridden from content::WebContentsDelegate:
86 virtual content::WebContents
* OpenURLFromTab(
87 content::WebContents
* source
,
88 const content::OpenURLParams
& params
) OVERRIDE
;
89 virtual void NavigationStateChanged(const content::WebContents
* source
,
90 unsigned changed_flags
) OVERRIDE
;
91 virtual void AddNewContents(content::WebContents
* source
,
92 content::WebContents
* new_contents
,
93 WindowOpenDisposition disposition
,
94 const gfx::Rect
& initial_pos
,
96 bool* was_blocked
) OVERRIDE
;
97 virtual void LoadingStateChanged(content::WebContents
* source
) OVERRIDE
;
98 virtual content::JavaScriptDialogManager
*
99 GetJavaScriptDialogManager() OVERRIDE
;
100 virtual void RequestMediaAccessPermission(
101 content::WebContents
* web_contents
,
102 const content::MediaStreamRequest
& request
,
103 const content::MediaResponseCallback
& callback
) OVERRIDE
;
105 // Overridden from content::NotificationObserver:
106 virtual void Observe(int type
,
107 const content::NotificationSource
& source
,
108 const content::NotificationDetails
& details
) OVERRIDE
;
110 // Returns the point where a detached window should be created given the
111 // current mouse position.
112 gfx::Point
GetWindowCreatePoint() const;
114 // Move the DraggedTabView according to the current mouse screen position,
115 // potentially updating the source and other TabStrips.
116 void ContinueDragging();
118 // Handles dragging tabs while the tabs are attached.
119 void MoveAttached(const gfx::Point
& screen_point
);
121 // Handles dragging while the tabs are detached.
122 void MoveDetached(const gfx::Point
& screen_point
);
124 // Selects the dragged tabs within |model|.
125 void RestoreSelection(TabStripModel
* model
);
127 // Returns the compatible TabStrip that is under the specified point (screen
128 // coordinates), or NULL if there is none.
129 TabStripGtk
* GetTabStripForPoint(const gfx::Point
& screen_point
);
131 // Returns the specified |tabstrip| if it contains the specified point
132 // (screen coordinates), NULL if it does not.
133 TabStripGtk
* GetTabStripIfItContains(TabStripGtk
* tabstrip
,
134 const gfx::Point
& screen_point
) const;
136 // Attach the dragged Tab to the specified TabStrip.
137 void Attach(TabStripGtk
* attached_tabstrip
, const gfx::Point
& screen_point
);
139 // Detach the dragged Tab from the current TabStrip.
142 // Converts a screen point to a point relative to the tab strip.
143 gfx::Point
ConvertScreenPointToTabStripPoint(TabStripGtk
* tabstrip
,
144 const gfx::Point
& screen_point
);
146 // Retrieve the bounds of the DraggedTabGtk, relative to the attached
147 // TabStrip, given location of the dragged tab in screen coordinates.
148 gfx::Rect
GetDraggedViewTabStripBounds(const gfx::Point
& screen_point
);
150 // Returns the index where the dragged WebContents should be inserted into
151 // the attached TabStripModel given the DraggedTabView's bounds
152 // |dragged_bounds| in coordinates relative to the attached TabStrip.
153 int GetInsertionIndexForDraggedBounds(const gfx::Rect
& dragged_bounds
);
155 // Get the position of the dragged view relative to the upper left corner of
156 // the screen. |screen_point| is the current position of mouse cursor.
157 gfx::Point
GetDraggedViewPoint(const gfx::Point
& screen_point
);
159 // Finds the Tab within the specified TabStrip that corresponds to the
160 // dragged WebContents.
161 TabGtk
* GetTabMatchingDraggedContents(TabStripGtk
* tabstrip
,
162 content::WebContents
* contents
);
164 // Finds all the tabs within the specified TabStrip that correspond to the
165 // dragged WebContents.
166 std::vector
<TabGtk
*> GetTabsMatchingDraggedContents(TabStripGtk
* tabstrip
);
168 // Sets the visible and draggging property of all dragged tabs. If |repaint|
169 // is true it also schedules a repaint.
170 void SetDraggedTabsVisible(bool visible
, bool repaint
);
172 // Does the work for EndDrag. Returns whether the tab has been destroyed.
173 bool EndDragImpl(EndDragType how_end
);
175 // If the drag was aborted for some reason, this function is called to un-do
176 // the changes made during the drag operation.
179 // Finishes the drag operation. Returns true if the drag controller should
180 // be destroyed immediately, false otherwise.
183 // Resets the delegates of the WebContents.
184 void ResetDelegates();
186 // Create the DraggedViewGtk if it does not yet exist.
187 void EnsureDraggedView();
189 // Gets the bounds to animate the dragged view when dragging is over.
190 gfx::Rect
GetAnimateBounds();
192 // Utility to convert the specified TabStripModel index to something valid
193 // for the attached TabStrip.
194 int NormalizeIndexToAttachedTabStrip(int index
) const;
196 // Hides the window that contains the tab strip the current drag session was
200 // Presents the window that was hidden by HideWindow.
203 // Closes a hidden frame at the end of a drag session.
204 void CleanUpHiddenFrame();
206 // Cleans up all the dragged tabs when they are no longer used.
207 void CleanUpDraggedTabs();
209 // Completes the drag session after the view has animated to its final
211 void OnAnimateToBoundsComplete();
213 // Activates whichever window is under the mouse.
214 void BringWindowUnderMouseToFront();
216 // Returns true if the tabs were originally one after the other in
217 // |source_tabstrip_|.
218 bool AreTabsConsecutive();
220 // Handles registering for notifications.
221 content::NotificationRegistrar registrar_
;
223 // The tab strip |source_tab_| originated from.
224 TabStripGtk
* source_tabstrip_
;
226 // Holds various data for each dragged tab needed to handle dragging.
227 scoped_ptr
<DragData
> drag_data_
;
229 // The TabStrip the dragged Tab is currently attached to, or NULL if the
230 // dragged Tab is detached.
231 TabStripGtk
* attached_tabstrip_
;
233 // The visual representation of all the dragged tabs.
234 scoped_ptr
<DraggedViewGtk
> dragged_view_
;
236 // The position of the mouse (in screen coordinates) at the start of the drag
237 // operation. This is used to calculate minimum elasticity before a
238 // DraggedTabView is constructed.
239 gfx::Point start_screen_point_
;
241 // This is the offset of the mouse from the top left of the Tab where
242 // dragging begun. This is used to ensure that the dragged view is always
243 // positioned at the correct location during the drag, and to ensure that the
244 // detached window is created at the right location.
245 gfx::Point mouse_offset_
;
247 // Whether we're in the destructor or not. Makes sure we don't destroy the
248 // drag controller more than once.
251 // The horizontal position of the mouse cursor in screen coordinates at the
252 // time of the last re-order event.
253 int last_move_screen_x_
;
255 // True until |MoveAttached| is invoked once.
258 // DockInfo for the tabstrip.
261 typedef std::set
<GtkWidget
*> DockWindows
;
262 DockWindows dock_windows_
;
264 // Timer used to bring the window under the cursor to front. If the user
265 // stops moving the mouse for a brief time over a browser window, it is
267 base::OneShotTimer
<DraggedTabControllerGtk
> bring_to_front_timer_
;
269 DISALLOW_COPY_AND_ASSIGN(DraggedTabControllerGtk
);
272 #endif // CHROME_BROWSER_UI_GTK_TABS_DRAGGED_TAB_CONTROLLER_GTK_H_