| 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 |