Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / tabs / tab_gtk.h
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.
4
5 #ifndef CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_
6 #define CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_
7
8 #include "base/basictypes.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "ui/base/gtk/gtk_signal.h"
15
16 class TabStripMenuController;
17 class ThemeService;
18
19 class TabGtk : public TabRendererGtk, public base::MessageLoopForUI::Observer {
20  public:
21   // An interface implemented by an object that can help this Tab complete
22   // various actions. The index parameter is the index of this Tab in the
23   // TabRenderer::Model.
24   class TabDelegate {
25    public:
26     // Returns true if the specified Tab is active.
27     virtual bool IsTabActive(const TabGtk* tab) const = 0;
28
29     // Returns true if the specified Tab is selected.
30     virtual bool IsTabSelected(const TabGtk* tab) const = 0;
31
32     // Returns true if the specified Tab is pinned.
33     virtual bool IsTabPinned(const TabGtk* tab) const = 0;
34
35     // Returns true if the specified Tab is detached.
36     virtual bool IsTabDetached(const TabGtk* tab) const = 0;
37
38     // Activates the specified Tab.
39     virtual void ActivateTab(TabGtk* tab) = 0;
40
41     // Toggles selection of the specified Tab.
42     virtual void ToggleTabSelection(TabGtk* tab) = 0;
43
44     // Extends selection from the anchor to the specified Tab.
45     virtual void ExtendTabSelection(TabGtk* tab) = 0;
46
47     // Closes the specified Tab.
48     virtual void CloseTab(TabGtk* tab) = 0;
49
50     // Returns true if the specified command is enabled for the specified Tab.
51     virtual bool IsCommandEnabledForTab(
52         TabStripModel::ContextMenuCommand command_id,
53         const TabGtk* tab) const = 0;
54
55     // Executes the specified command for the specified Tab.
56     virtual void ExecuteCommandForTab(
57         TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
58
59     // Starts/Stops highlighting the tabs that will be affected by the
60     // specified command for the specified Tab.
61     virtual void StartHighlightTabsForCommand(
62         TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
63     virtual void StopHighlightTabsForCommand(
64         TabStripModel::ContextMenuCommand command_id, TabGtk* tab) = 0;
65     virtual void StopAllHighlighting() = 0;
66
67     // Potentially starts a drag for the specified Tab.
68     virtual void MaybeStartDrag(TabGtk* tab, const gfx::Point& point) = 0;
69
70     // Continues dragging a Tab.
71     virtual void ContinueDrag(GdkDragContext* context) = 0;
72
73     // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way
74     // other than the user releasing the mouse. Returns whether the tab has been
75     // destroyed.
76     virtual bool EndDrag(bool canceled) = 0;
77
78     // Returns true if the associated TabStrip's delegate supports tab moving or
79     // detaching. Used by the Frame to determine if dragging on the Tab
80     // itself should move the window in cases where there's only one
81     // non drag-able Tab.
82     virtual bool HasAvailableDragActions() const = 0;
83
84     // Returns the theme provider for icons and colors.
85     virtual GtkThemeService* GetThemeProvider() = 0;
86
87     // Returns a context menu controller for |tab|. Caller takes ownership of
88     // the pointed object.
89     virtual TabStripMenuController* GetTabStripMenuControllerForTab(
90         TabGtk* tab) = 0;
91
92    protected:
93     virtual ~TabDelegate() {}
94   };
95
96   explicit TabGtk(TabDelegate* delegate);
97   virtual ~TabGtk();
98
99   // Access the delegate.
100   TabDelegate* delegate() const { return delegate_; }
101
102   GtkWidget* widget() const { return event_box_; }
103
104   // Used to set/check whether this Tab is being animated closed.
105   void set_closing(bool closing) { closing_ = closing; }
106   bool closing() const { return closing_; }
107
108   // Used to set/check whether this Tab is being dragged.
109   void set_dragging(bool dragging) { dragging_ = dragging; }
110   bool dragging() const { return dragging_; }
111
112   // Raise to top of Z-order.
113   void Raise() const;
114
115   // TabRendererGtk overrides:
116   virtual bool IsActive() const OVERRIDE;
117   virtual bool IsSelected() const OVERRIDE;
118   virtual bool IsVisible() const OVERRIDE;
119   virtual void SetVisible(bool visible) const OVERRIDE;
120   virtual void CloseButtonClicked() OVERRIDE;
121   virtual void UpdateData(content::WebContents* contents,
122                           bool app,
123                           bool loading_only) OVERRIDE;
124   virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
125
126  private:
127   class TabGtkObserverHelper;
128
129   // MessageLoop::Observer implementation:
130   virtual void WillProcessEvent(GdkEvent* event) OVERRIDE;
131   virtual void DidProcessEvent(GdkEvent* event) OVERRIDE;
132
133   // button-press-event handler that handles mouse clicks.
134   CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonPressEvent, GdkEventButton*);
135
136   // button-release-event handler that handles mouse click releases.
137   CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnButtonReleaseEvent, GdkEventButton*);
138
139   // drag-begin is emitted when the drag is started. We connect so that we can
140   // set the drag icon to a transparent pixbuf.
141   CHROMEGTK_CALLBACK_1(TabGtk, void, OnDragBegin, GdkDragContext*);
142
143   // drag-failed is emitted when the drag is finished.  In our case the signal
144   // does not imply failure as we don't use the drag-n-drop API to transfer drop
145   // data.
146   CHROMEGTK_CALLBACK_2(TabGtk, gboolean, OnDragFailed, GdkDragContext*,
147                        GtkDragResult);
148
149   // When a drag is ending, a fake button release event is passed to the drag
150   // widget to fake letting go of the mouse button.  We need a callback for
151   // this event because it is the only way to catch drag end events when the
152   // user presses space or return.
153   CHROMEGTK_CALLBACK_1(TabGtk, gboolean, OnDragButtonReleased, GdkEventButton*);
154
155   // Invoked when the context menu closes.
156   void ContextMenuClosed();
157
158   // Sets whether the tooltip should be shown or not, depending on the size of
159   // the tab.
160   void UpdateTooltipState();
161
162   // Creates the drag widget used to track a drag operation.
163   void CreateDragWidget();
164
165   // Destroys the drag widget.
166   void DestroyDragWidget();
167
168   // Starts the dragging operation.  |drag_offset| is the offset inside the tab
169   // bounds where the grab occurred.
170   void StartDragging(gfx::Point drag_offset);
171
172   // Ends the dragging operations.  |canceled| is true if the operation was
173   // canceled.
174   void EndDrag(bool canceled);
175
176   // An instance of a delegate object that can perform various actions based on
177   // user gestures.
178   TabDelegate* delegate_;
179
180   // True if the tab is being animated closed.
181   bool closing_;
182
183   // True if the tab is being dragged.
184   bool dragging_;
185
186   // The context menu controller.
187   scoped_ptr<TabStripMenuController> menu_controller_;
188
189   // The windowless widget used to collect input events for the tab.  We can't
190   // use an OwnedWidgetGtk because of the way the dragged tab controller
191   // destroys the source tab.  The source tab is destroyed when the drag ends
192   // before we let gtk handle the end of the drag.  This results in the widget
193   // having an extra reference, which will cause OwnedWidgetGtk.Destroy to
194   // DCHECK.
195   GtkWidget* event_box_;
196
197   // A copy of the last button press event, used to initiate a drag.
198   GdkEvent* last_mouse_down_;
199
200   // A GtkInivisible used to track the drag event.  GtkInvisibles are of the
201   // type GInitiallyUnowned, but the widget initialization code sinks the
202   // reference, so we can't used an OwnedWidgetGtk here.
203   GtkWidget* drag_widget_;
204
205   // The cached width of the title in pixels, updated whenever the title
206   // changes.
207   int title_width_;
208
209   // Keep track of whether or not we have an observer.
210   scoped_ptr<TabGtkObserverHelper> observer_;
211
212   // Used to destroy the drag widget after a return to the message loop.
213   base::WeakPtrFactory<TabGtk> destroy_factory_;
214
215   // Due to a bug in GTK+, we need to force the end of a drag when we get a
216   // mouse release event on the the dragged widget, otherwise, we don't know
217   // when the drag has ended when the user presses space or enter.  We queue
218   // a task to end the drag and only run it if GTK+ didn't send us the
219   // drag-failed event.
220   base::WeakPtrFactory<TabGtk> drag_end_factory_;
221
222   DISALLOW_COPY_AND_ASSIGN(TabGtk);
223 };
224
225 #endif  // CHROME_BROWSER_UI_GTK_TABS_TAB_GTK_H_