Home | History | Annotate | Download | only in tabs
      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