OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/gtk/browser_actions_toolbar_gtk.h" | 5 #include "chrome/browser/gtk/browser_actions_toolbar_gtk.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
10 #include "chrome/browser/browser.h" | 10 #include "chrome/browser/browser.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 tracker_(this), | 90 tracker_(this), |
91 tab_specific_icon_(NULL), | 91 tab_specific_icon_(NULL), |
92 default_icon_(NULL) { | 92 default_icon_(NULL) { |
93 button_.reset(new CustomDrawButton( | 93 button_.reset(new CustomDrawButton( |
94 theme_provider, | 94 theme_provider, |
95 IDR_BROWSER_ACTION, | 95 IDR_BROWSER_ACTION, |
96 IDR_BROWSER_ACTION_P, | 96 IDR_BROWSER_ACTION_P, |
97 IDR_BROWSER_ACTION_H, | 97 IDR_BROWSER_ACTION_H, |
98 0, | 98 0, |
99 NULL)); | 99 NULL)); |
| 100 alignment_.Own(gtk_alignment_new(0, 0, 1, 1)); |
| 101 gtk_container_add(GTK_CONTAINER(alignment_.get()), button()); |
| 102 gtk_widget_show(button()); |
100 | 103 |
101 DCHECK(extension_->browser_action()); | 104 DCHECK(extension_->browser_action()); |
102 | 105 |
103 UpdateState(); | 106 UpdateState(); |
104 | 107 |
105 // The Browser Action API does not allow the default icon path to be | 108 // The Browser Action API does not allow the default icon path to be |
106 // changed at runtime, so we can load this now and cache it. | 109 // changed at runtime, so we can load this now and cache it. |
107 std::string path = extension_->browser_action()->default_icon_path(); | 110 std::string path = extension_->browser_action()->default_icon_path(); |
108 if (!path.empty()) { | 111 if (!path.empty()) { |
109 tracker_.LoadImage(extension_, extension_->GetResource(path), | 112 tracker_.LoadImage(extension_, extension_->GetResource(path), |
110 gfx::Size(Extension::kBrowserActionIconMaxSize, | 113 gfx::Size(Extension::kBrowserActionIconMaxSize, |
111 Extension::kBrowserActionIconMaxSize), | 114 Extension::kBrowserActionIconMaxSize), |
112 ImageLoadingTracker::DONT_CACHE); | 115 ImageLoadingTracker::DONT_CACHE); |
113 } | 116 } |
114 | 117 |
115 signals_.Connect(button_->widget(), "button-press-event", | 118 signals_.Connect(button(), "button-press-event", |
116 G_CALLBACK(OnButtonPress), this); | 119 G_CALLBACK(OnButtonPress), this); |
117 signals_.Connect(button_->widget(), "clicked", | 120 signals_.Connect(button(), "clicked", |
118 G_CALLBACK(OnClicked), this); | 121 G_CALLBACK(OnClicked), this); |
119 signals_.ConnectAfter(button_->widget(), "expose-event", | 122 signals_.Connect(button(), "drag-begin", |
| 123 G_CALLBACK(&OnDragBegin), this); |
| 124 signals_.ConnectAfter(widget(), "expose-event", |
120 G_CALLBACK(OnExposeEvent), this); | 125 G_CALLBACK(OnExposeEvent), this); |
121 signals_.Connect(button_->widget(), "drag-begin", | |
122 G_CALLBACK(&OnDragBegin), this); | |
123 | 126 |
124 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, | 127 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, |
125 Source<ExtensionAction>(extension->browser_action())); | 128 Source<ExtensionAction>(extension->browser_action())); |
126 } | 129 } |
127 | 130 |
128 ~BrowserActionButton() { | 131 ~BrowserActionButton() { |
129 if (tab_specific_icon_) | 132 if (tab_specific_icon_) |
130 g_object_unref(tab_specific_icon_); | 133 g_object_unref(tab_specific_icon_); |
131 | 134 |
132 if (default_icon_) | 135 if (default_icon_) |
133 g_object_unref(default_icon_); | 136 g_object_unref(default_icon_); |
| 137 |
| 138 alignment_.Destroy(); |
134 } | 139 } |
135 | 140 |
136 GtkWidget* widget() { return button_->widget(); } | 141 GtkWidget* button() { return button_->widget(); } |
| 142 |
| 143 GtkWidget* widget() { return alignment_.get(); } |
137 | 144 |
138 Extension* extension() { return extension_; } | 145 Extension* extension() { return extension_; } |
139 | 146 |
140 // NotificationObserver implementation. | 147 // NotificationObserver implementation. |
141 void Observe(NotificationType type, | 148 void Observe(NotificationType type, |
142 const NotificationSource& source, | 149 const NotificationSource& source, |
143 const NotificationDetails& details) { | 150 const NotificationDetails& details) { |
144 if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED) | 151 if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED) |
145 UpdateState(); | 152 UpdateState(); |
146 else | 153 else |
(...skipping 11 matching lines...) Expand all Loading... |
158 | 165 |
159 // Updates the button based on the latest state from the associated | 166 // Updates the button based on the latest state from the associated |
160 // browser action. | 167 // browser action. |
161 void UpdateState() { | 168 void UpdateState() { |
162 int tab_id = toolbar_->GetCurrentTabId(); | 169 int tab_id = toolbar_->GetCurrentTabId(); |
163 if (tab_id < 0) | 170 if (tab_id < 0) |
164 return; | 171 return; |
165 | 172 |
166 std::string tooltip = extension_->browser_action()->GetTitle(tab_id); | 173 std::string tooltip = extension_->browser_action()->GetTitle(tab_id); |
167 if (tooltip.empty()) | 174 if (tooltip.empty()) |
168 gtk_widget_set_has_tooltip(button_->widget(), FALSE); | 175 gtk_widget_set_has_tooltip(button(), FALSE); |
169 else | 176 else |
170 gtk_widget_set_tooltip_text(button_->widget(), tooltip.c_str()); | 177 gtk_widget_set_tooltip_text(button(), tooltip.c_str()); |
171 | 178 |
172 SkBitmap image = extension_->browser_action()->GetIcon(tab_id); | 179 SkBitmap image = extension_->browser_action()->GetIcon(tab_id); |
173 if (!image.isNull()) { | 180 if (!image.isNull()) { |
174 GdkPixbuf* previous_gdk_icon = tab_specific_icon_; | 181 GdkPixbuf* previous_gdk_icon = tab_specific_icon_; |
175 tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image); | 182 tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image); |
176 SetImage(tab_specific_icon_); | 183 SetImage(tab_specific_icon_); |
177 if (previous_gdk_icon) | 184 if (previous_gdk_icon) |
178 g_object_unref(previous_gdk_icon); | 185 g_object_unref(previous_gdk_icon); |
179 } else if (default_icon_) { | 186 } else if (default_icon_) { |
180 SetImage(default_icon_); | 187 SetImage(default_icon_); |
181 } | 188 } |
182 gtk_widget_queue_draw(button_->widget()); | 189 gtk_widget_queue_draw(button()); |
183 } | 190 } |
184 | 191 |
185 SkBitmap GetIcon() { | 192 SkBitmap GetIcon() { |
186 const SkBitmap& image = extension_->browser_action()->GetIcon( | 193 const SkBitmap& image = extension_->browser_action()->GetIcon( |
187 toolbar_->GetCurrentTabId()); | 194 toolbar_->GetCurrentTabId()); |
188 if (!image.isNull()) { | 195 if (!image.isNull()) { |
189 return image; | 196 return image; |
190 } else { | 197 } else { |
191 return default_skbitmap_; | 198 return default_skbitmap_; |
192 } | 199 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 } | 247 } |
241 | 248 |
242 // ExtensionContextMenuModel::PopupDelegate implementation. | 249 // ExtensionContextMenuModel::PopupDelegate implementation. |
243 virtual void InspectPopup(ExtensionAction* action) { | 250 virtual void InspectPopup(ExtensionAction* action) { |
244 ShowPopup(true); | 251 ShowPopup(true); |
245 } | 252 } |
246 | 253 |
247 void SetImage(GdkPixbuf* image) { | 254 void SetImage(GdkPixbuf* image) { |
248 if (!image_) { | 255 if (!image_) { |
249 image_ = gtk_image_new_from_pixbuf(image); | 256 image_ = gtk_image_new_from_pixbuf(image); |
250 gtk_button_set_image(GTK_BUTTON(button_->widget()), image_); | 257 gtk_button_set_image(GTK_BUTTON(button()), image_); |
251 } else { | 258 } else { |
252 gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image); | 259 gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image); |
253 } | 260 } |
254 } | 261 } |
255 | 262 |
256 static gboolean OnButtonPress(GtkWidget* widget, | 263 static gboolean OnButtonPress(GtkWidget* widget, |
257 GdkEvent* event, | 264 GdkEvent* event, |
258 BrowserActionButton* action) { | 265 BrowserActionButton* action) { |
259 if (event->button.button != 3) | 266 if (event->button.button != 3) |
260 return FALSE; | 267 return FALSE; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 | 309 |
303 // The toolbar containing this button. | 310 // The toolbar containing this button. |
304 BrowserActionsToolbarGtk* toolbar_; | 311 BrowserActionsToolbarGtk* toolbar_; |
305 | 312 |
306 // The extension that contains this browser action. | 313 // The extension that contains this browser action. |
307 Extension* extension_; | 314 Extension* extension_; |
308 | 315 |
309 // The button for this browser action. | 316 // The button for this browser action. |
310 scoped_ptr<CustomDrawButton> button_; | 317 scoped_ptr<CustomDrawButton> button_; |
311 | 318 |
| 319 // The top level widget (parent of |button_|). |
| 320 OwnedWidgetGtk alignment_; |
| 321 |
312 // The one image subwidget in |button_|. We keep this out so we don't alter | 322 // The one image subwidget in |button_|. We keep this out so we don't alter |
313 // the widget hierarchy while changing the button image because changing the | 323 // the widget hierarchy while changing the button image because changing the |
314 // GTK widget hierarchy invalidates all tooltips and several popular | 324 // GTK widget hierarchy invalidates all tooltips and several popular |
315 // extensions change browser action icon in a loop. | 325 // extensions change browser action icon in a loop. |
316 GtkWidget* image_; | 326 GtkWidget* image_; |
317 | 327 |
318 // Loads the button's icons for us on the file thread. | 328 // Loads the button's icons for us on the file thread. |
319 ImageLoadingTracker tracker_; | 329 ImageLoadingTracker tracker_; |
320 | 330 |
321 // If we are displaying a tab-specific icon, it will be here. | 331 // If we are displaying a tab-specific icon, it will be here. |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 | 506 |
497 RemoveButtonForExtension(extension); | 507 RemoveButtonForExtension(extension); |
498 linked_ptr<BrowserActionButton> button( | 508 linked_ptr<BrowserActionButton> button( |
499 new BrowserActionButton(this, extension, theme_provider_)); | 509 new BrowserActionButton(this, extension, theme_provider_)); |
500 gtk_chrome_shrinkable_hbox_pack_start( | 510 gtk_chrome_shrinkable_hbox_pack_start( |
501 GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); | 511 GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); |
502 gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); | 512 gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); |
503 extension_button_map_[extension->id()] = button; | 513 extension_button_map_[extension->id()] = button; |
504 | 514 |
505 GtkTargetEntry drag_target = GetDragTargetEntry(); | 515 GtkTargetEntry drag_target = GetDragTargetEntry(); |
506 gtk_drag_source_set(button->widget(), GDK_BUTTON1_MASK, &drag_target, 1, | 516 gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1, |
507 GDK_ACTION_MOVE); | 517 GDK_ACTION_MOVE); |
508 // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. | 518 // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. |
509 signals_.Connect(button->widget(), "drag-end", | 519 signals_.Connect(button->button(), "drag-end", |
510 G_CALLBACK(&OnDragEndThunk), this); | 520 G_CALLBACK(&OnDragEndThunk), this); |
511 signals_.Connect(button->widget(), "drag-failed", | 521 signals_.Connect(button->button(), "drag-failed", |
512 G_CALLBACK(&OnDragFailedThunk), this); | 522 G_CALLBACK(&OnDragFailedThunk), this); |
513 | 523 |
514 // Any time a browser action button is shown or hidden we have to update | 524 // Any time a browser action button is shown or hidden we have to update |
515 // the chevron state. | 525 // the chevron state. |
516 signals_.Connect(button->widget(), "show", | 526 signals_.Connect(button->widget(), "show", |
517 G_CALLBACK(&OnButtonShowOrHideThunk), this); | 527 G_CALLBACK(&OnButtonShowOrHideThunk), this); |
518 signals_.Connect(button->widget(), "hide", | 528 signals_.Connect(button->widget(), "hide", |
519 G_CALLBACK(&OnButtonShowOrHideThunk), this); | 529 G_CALLBACK(&OnButtonShowOrHideThunk), this); |
520 | 530 |
521 gtk_widget_show(button->widget()); | 531 gtk_widget_show(button->widget()); |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 } | 914 } |
905 | 915 |
906 it->second.get()->GetContextMenu()->PopupAsContext(event->time); | 916 it->second.get()->GetContextMenu()->PopupAsContext(event->time); |
907 return TRUE; | 917 return TRUE; |
908 } | 918 } |
909 | 919 |
910 void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { | 920 void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { |
911 if (!resize_animation_.is_animating()) | 921 if (!resize_animation_.is_animating()) |
912 UpdateChevronVisibility(); | 922 UpdateChevronVisibility(); |
913 } | 923 } |
OLD | NEW |