OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/gtk/tabs/tab_gtk.h" | 5 #include "chrome/browser/ui/gtk/tabs/tab_gtk.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 | 8 |
9 #include "base/memory/singleton.h" | 9 #include "base/memory/singleton.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
11 #include "chrome/app/chrome_command_ids.h" | 11 #include "chrome/app/chrome_command_ids.h" |
12 #include "chrome/browser/ui/gtk/accelerators_gtk.h" | 12 #include "chrome/browser/ui/gtk/accelerators_gtk.h" |
13 #include "chrome/browser/ui/gtk/menu_gtk.h" | 13 #include "chrome/browser/ui/gtk/menu_gtk.h" |
14 #include "chrome/browser/ui/gtk/tabs/tab_strip_menu_controller.h" | |
14 #include "chrome/browser/ui/tabs/tab_menu_model.h" | 15 #include "chrome/browser/ui/tabs/tab_menu_model.h" |
15 #include "grit/generated_resources.h" | 16 #include "grit/generated_resources.h" |
16 #include "grit/theme_resources.h" | 17 #include "grit/theme_resources.h" |
17 #include "ui/base/dragdrop/gtk_dnd_util.h" | 18 #include "ui/base/dragdrop/gtk_dnd_util.h" |
18 #include "ui/base/models/accelerator_gtk.h" | 19 #include "ui/base/models/accelerator_gtk.h" |
19 #include "ui/gfx/path.h" | 20 #include "ui/gfx/path.h" |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 // Returns the width of the title for the current font, in pixels. | 24 // Returns the width of the title for the current font, in pixels. |
24 int GetTitleWidth(gfx::Font* font, string16 title) { | 25 int GetTitleWidth(gfx::Font* font, string16 title) { |
25 DCHECK(font); | 26 DCHECK(font); |
26 if (title.empty()) | 27 if (title.empty()) |
27 return 0; | 28 return 0; |
28 | 29 |
29 return font->GetStringWidth(title); | 30 return font->GetStringWidth(title); |
30 } | 31 } |
31 | 32 |
32 } // namespace | 33 } // namespace |
33 | 34 |
34 class TabGtk::ContextMenuController : public ui::SimpleMenuModel::Delegate, | |
35 public MenuGtk::Delegate { | |
36 public: | |
37 explicit ContextMenuController(TabGtk* tab) | |
38 : tab_(tab), | |
39 model_(this, tab->delegate()->IsTabPinned(tab)) { | |
40 menu_.reset(new MenuGtk(this, &model_)); | |
41 } | |
42 | |
43 virtual ~ContextMenuController() {} | |
44 | |
45 void RunMenu(const gfx::Point& point, guint32 event_time) { | |
46 menu_->PopupAsContext(point, event_time); | |
47 } | |
48 | |
49 void Cancel() { | |
50 tab_ = NULL; | |
51 menu_->Cancel(); | |
52 } | |
53 | |
54 private: | |
55 // Overridden from ui::SimpleMenuModel::Delegate: | |
56 virtual bool IsCommandIdChecked(int command_id) const { | |
57 return false; | |
58 } | |
59 virtual bool IsCommandIdEnabled(int command_id) const { | |
60 return tab_ && tab_->delegate()->IsCommandEnabledForTab( | |
61 static_cast<TabStripModel::ContextMenuCommand>(command_id), | |
62 tab_); | |
63 } | |
64 virtual bool GetAcceleratorForCommandId( | |
65 int command_id, | |
66 ui::Accelerator* accelerator) { | |
67 int browser_command; | |
68 if (!TabStripModel::ContextMenuCommandToBrowserCommand(command_id, | |
69 &browser_command)) | |
70 return false; | |
71 const ui::AcceleratorGtk* accelerator_gtk = | |
72 AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand( | |
73 browser_command); | |
74 if (accelerator_gtk) | |
75 *accelerator = *accelerator_gtk; | |
76 return !!accelerator_gtk; | |
77 } | |
78 | |
79 virtual void ExecuteCommand(int command_id) { | |
80 if (!tab_) | |
81 return; | |
82 tab_->delegate()->ExecuteCommandForTab( | |
83 static_cast<TabStripModel::ContextMenuCommand>(command_id), tab_); | |
84 } | |
85 | |
86 GtkWidget* GetImageForCommandId(int command_id) const { | |
87 int browser_cmd_id; | |
88 return TabStripModel::ContextMenuCommandToBrowserCommand(command_id, | |
89 &browser_cmd_id) ? | |
90 MenuGtk::Delegate::GetDefaultImageForCommandId(browser_cmd_id) : | |
91 NULL; | |
92 } | |
93 | |
94 // The context menu. | |
95 scoped_ptr<MenuGtk> menu_; | |
96 | |
97 // The Tab the context menu was brought up for. Set to NULL when the menu | |
98 // is canceled. | |
99 TabGtk* tab_; | |
100 | |
101 // The model. | |
102 TabMenuModel model_; | |
103 | |
104 DISALLOW_COPY_AND_ASSIGN(ContextMenuController); | |
105 }; | |
106 | |
107 class TabGtk::TabGtkObserverHelper { | 35 class TabGtk::TabGtkObserverHelper { |
108 public: | 36 public: |
109 explicit TabGtkObserverHelper(TabGtk* tab) | 37 explicit TabGtkObserverHelper(TabGtk* tab) |
110 : tab_(tab) { | 38 : tab_(tab) { |
111 MessageLoopForUI::current()->AddObserver(tab_); | 39 MessageLoopForUI::current()->AddObserver(tab_); |
112 } | 40 } |
113 | 41 |
114 ~TabGtkObserverHelper() { | 42 ~TabGtkObserverHelper() { |
115 MessageLoopForUI::current()->RemoveObserver(tab_); | 43 MessageLoopForUI::current()->RemoveObserver(tab_); |
116 } | 44 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 } | 97 } |
170 } | 98 } |
171 | 99 |
172 gboolean TabGtk::OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event) { | 100 gboolean TabGtk::OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event) { |
173 // Every button press ensures either a button-release-event or a drag-fail | 101 // Every button press ensures either a button-release-event or a drag-fail |
174 // signal for |widget|. | 102 // signal for |widget|. |
175 if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { | 103 if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { |
176 // Store whether or not we were selected just now... we only want to be | 104 // Store whether or not we were selected just now... we only want to be |
177 // able to drag foreground tabs, so we don't start dragging the tab if | 105 // able to drag foreground tabs, so we don't start dragging the tab if |
178 // it was in the background. | 106 // it was in the background. |
179 bool just_selected = !IsSelected(); | 107 if (!IsActive() && (event->state & |
James Hawkins
2011/05/12 00:53:54
&& !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_
dpapad
2011/05/12 16:37:08
Done.
| |
180 if (just_selected) { | 108 (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) == 0) { |
181 delegate_->SelectTab(this); | 109 delegate_->ActivateTab(this); |
110 } else if (!IsActive() && (event->state & GDK_CONTROL_MASK) == | |
James Hawkins
2011/05/12 00:53:54
It's merely enough to check `event->state & GDK_CO
dpapad
2011/05/12 16:37:08
Done.
| |
111 GDK_CONTROL_MASK) { | |
112 delegate_->ToggleTabSelection(this); | |
113 } else if (!IsActive() && (event->state & GDK_SHIFT_MASK) == | |
114 GDK_SHIFT_MASK) { | |
115 delegate_->ExtendTabSelection(this); | |
182 } | 116 } |
183 | |
184 // Hook into the message loop to handle dragging. | 117 // Hook into the message loop to handle dragging. |
185 observer_.reset(new TabGtkObserverHelper(this)); | 118 observer_.reset(new TabGtkObserverHelper(this)); |
186 | 119 |
187 // Store the button press event, used to initiate a drag. | 120 // Store the button press event, used to initiate a drag. |
188 last_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event)); | 121 last_mouse_down_ = gdk_event_copy(reinterpret_cast<GdkEvent*>(event)); |
189 } else if (event->button == 3) { | 122 } else if (event->button == 3) { |
190 // Only show the context menu if the left mouse button isn't down (i.e., | 123 // Only show the context menu if the left mouse button isn't down (i.e., |
191 // the user might want to drag instead). | 124 // the user might want to drag instead). |
192 if (!last_mouse_down_) { | 125 if (!last_mouse_down_) { |
193 menu_controller_.reset(new ContextMenuController(this)); | 126 menu_controller_.reset(delegate()->GetContextMenuControllerForTab(this)); |
194 menu_controller_->RunMenu(gfx::Point(event->x_root, event->y_root), | 127 menu_controller_->RunMenu(gfx::Point(event->x_root, event->y_root), |
195 event->time); | 128 event->time); |
196 } | 129 } |
197 } | 130 } |
198 | 131 |
199 return TRUE; | 132 return TRUE; |
200 } | 133 } |
201 | 134 |
202 gboolean TabGtk::OnButtonReleaseEvent(GtkWidget* widget, | 135 gboolean TabGtk::OnButtonReleaseEvent(GtkWidget* widget, |
203 GdkEventButton* event) { | 136 GdkEventButton* event) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 static_cast<gint>(new_x), static_cast<gint>(new_y))) { | 219 static_cast<gint>(new_x), static_cast<gint>(new_y))) { |
287 StartDragging(gfx::Point( | 220 StartDragging(gfx::Point( |
288 static_cast<int>(last_mouse_down_->button.x), | 221 static_cast<int>(last_mouse_down_->button.x), |
289 static_cast<int>(last_mouse_down_->button.y))); | 222 static_cast<int>(last_mouse_down_->button.y))); |
290 } | 223 } |
291 } | 224 } |
292 | 225 |
293 /////////////////////////////////////////////////////////////////////////////// | 226 /////////////////////////////////////////////////////////////////////////////// |
294 // TabGtk, TabRendererGtk overrides: | 227 // TabGtk, TabRendererGtk overrides: |
295 | 228 |
229 bool TabGtk::IsActive() const { | |
230 return delegate_->IsTabActive(this); | |
231 } | |
232 | |
296 bool TabGtk::IsSelected() const { | 233 bool TabGtk::IsSelected() const { |
297 return delegate_->IsTabSelected(this); | 234 return delegate_->IsTabSelected(this); |
298 } | 235 } |
299 | 236 |
300 bool TabGtk::IsVisible() const { | 237 bool TabGtk::IsVisible() const { |
301 return GTK_WIDGET_FLAGS(event_box_) & GTK_VISIBLE; | 238 return GTK_WIDGET_FLAGS(event_box_) & GTK_VISIBLE; |
302 } | 239 } |
303 | 240 |
304 void TabGtk::SetVisible(bool visible) const { | 241 void TabGtk::SetVisible(bool visible) const { |
305 if (visible) { | 242 if (visible) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 gdk_event_free(last_mouse_down_); | 324 gdk_event_free(last_mouse_down_); |
388 last_mouse_down_ = NULL; | 325 last_mouse_down_ = NULL; |
389 } | 326 } |
390 | 327 |
391 // Notify the drag helper that we're done with any potential drag operations. | 328 // Notify the drag helper that we're done with any potential drag operations. |
392 // Clean up the drag helper, which is re-created on the next mouse press. | 329 // Clean up the drag helper, which is re-created on the next mouse press. |
393 delegate_->EndDrag(canceled); | 330 delegate_->EndDrag(canceled); |
394 | 331 |
395 observer_.reset(); | 332 observer_.reset(); |
396 } | 333 } |
OLD | NEW |