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