browser_actions_toolbar_gtk.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_browser_event_router.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_context_menu_model.h" 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/image_loading_tracker.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/cairo_cached_surface.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_button.h" 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h" 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/hover_controller_gtk.h" 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/menu_gtk.h" 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/view_id_util.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_action.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_resource.h" 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_details.h" 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h" 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_source.h" 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_type.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h" 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "grit/theme_resources.h" 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia_paint.h" 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The width of the browser action buttons. 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kButtonWidth = 27; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// The padding between browser action buttons. 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kButtonPadding = 4; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The padding to the right of the browser action buttons (between the buttons 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// and chevron if they are both showing). 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kButtonChevronPadding = 2; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The padding to the left, top and bottom of the browser actions toolbar 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// separator. 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kSeparatorPadding = 2; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Width of the invisible gripper for resizing the toolbar. 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kResizeGripperWidth = 4; 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* kDragTarget = "application/x-chrome-browseraction"; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkTargetEntry GetDragTargetEntry() { 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static std::string drag_target_string(kDragTarget); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkTargetEntry drag_target; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_target.target = const_cast<char*>(drag_target_string.c_str()); 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_target.flags = GTK_TARGET_SAME_APP; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_target.info = 0; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return drag_target; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The minimum width in pixels of the button hbox if |icon_count| icons are 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// showing. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgint WidthForIconCount(gint icon_count) { 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing ui::SimpleMenuModel; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BrowserActionButton : public NotificationObserver, 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public ImageLoadingTracker::Observer, 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public ExtensionContextMenuModel::PopupDelegate, 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public MenuGtk::Delegate { 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionButton(BrowserActionsToolbarGtk* toolbar, 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension, 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkThemeService* theme_provider) 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : toolbar_(toolbar), 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension_(extension), 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_(NULL), 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracker_(this), 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_specific_icon_(NULL), 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default_icon_(NULL) { 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick button_.reset(new CustomDrawButton( 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick theme_provider, 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTION, 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTION_P, 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTION_H, 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL)); 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick alignment_.Own(gtk_alignment_new(0, 0, 1, 1)); 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_container_add(GTK_CONTAINER(alignment_.get()), button()); 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_show(button()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(extension_->browser_action()); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateState(); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The Browser Action API does not allow the default icon path to be 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // changed at runtime, so we can load this now and cache it. 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string path = extension_->browser_action()->default_icon_path(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!path.empty()) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tracker_.LoadImage(extension_, extension_->GetResource(path), 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size(Extension::kBrowserActionIconMaxSize, 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Extension::kBrowserActionIconMaxSize), 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ImageLoadingTracker::DONT_CACHE); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(button(), "button-press-event", 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnButtonPress), this); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(button(), "clicked", 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnClicked), this); 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(button(), "drag-begin", 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(&OnDragBegin), this); 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.ConnectAfter(widget(), "expose-event", 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick G_CALLBACK(OnExposeEvent), this); 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<ExtensionAction>(extension->browser_action())); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~BrowserActionButton() { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_specific_icon_) 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(tab_specific_icon_); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (default_icon_) 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(default_icon_); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick alignment_.Destroy(); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GtkWidget* button() { return button_->widget(); } 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GtkWidget* widget() { return alignment_.get(); } 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension() { return extension_; } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NotificationObserver implementation. 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Observe(NotificationType type, 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED) 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateState(); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ImageLoadingTracker::Observer implementation. 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int index) { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (image) { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default_skbitmap_ = *image; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default_icon_ = gfx::GdkPixbufFromSkBitmap(image); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateState(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Updates the button based on the latest state from the associated 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // browser action. 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateState() { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = toolbar_->GetCurrentTabId(); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id < 0) 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string tooltip = extension_->browser_action()->GetTitle(tab_id); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tooltip.empty()) 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_set_has_tooltip(button(), FALSE); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_set_tooltip_text(button(), tooltip.c_str()); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap image = extension_->browser_action()->GetIcon(tab_id); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!image.isNull()) { 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkPixbuf* previous_gdk_icon = tab_specific_icon_; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetImage(tab_specific_icon_); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (previous_gdk_icon) 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(previous_gdk_icon); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (default_icon_) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetImage(default_icon_); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_queue_draw(button()); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap GetIcon() { 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap& image = extension_->browser_action()->GetIcon( 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toolbar_->GetCurrentTabId()); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!image.isNull()) { 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return image; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return default_skbitmap_; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MenuGtk* GetContextMenu() { 20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!extension_->ShowConfigureContextMenus()) 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return NULL; 20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_model_ = 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new ExtensionContextMenuModel(extension_, toolbar_->browser(), this); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch context_menu_.reset( 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new MenuGtk(this, context_menu_model_.get())); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return context_menu_.get(); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MenuGtk::Delegate implementation. 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void StoppedShowing() { 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick button_->UnsetPaintOverride(); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the context menu was showing for the overflow menu, re-assert the 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // grab that was shadowed. 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (toolbar_->overflow_menu_.get()) 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::GrabAllInput(toolbar_->overflow_menu_->widget()); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void CommandWillBeExecuted() { 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the context menu was showing for the overflow menu, and a command 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is executed, then stop showing the overflow menu. 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (toolbar_->overflow_menu_.get()) 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch toolbar_->overflow_menu_->Cancel(); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true to prevent further processing of the event that caused us to 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // show the popup, or false to continue processing. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ShowPopup(bool devtools) { 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionAction* browser_action = extension_->browser_action(); 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = toolbar_->GetCurrentTabId(); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id < 0) { 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "No current tab."; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser_action->HasPopup(tab_id)) { 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionPopupGtk::Show( 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_action->GetPopupUrl(tab_id), toolbar_->browser(), 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget(), devtools); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ExtensionContextMenuModel::PopupDelegate implementation. 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void InspectPopup(ExtensionAction* action) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShowPopup(true); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetImage(GdkPixbuf* image) { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!image_) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch image_ = gtk_image_new_from_pixbuf(image); 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_button_set_image(GTK_BUTTON(button()), image_); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static gboolean OnButtonPress(GtkWidget* widget, 27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GdkEventButton* event, 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionButton* action) { 27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (event->button != 3) 27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return FALSE; 27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MenuGtk* menu = action->GetContextMenu(); 27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!menu) 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick action->button_->SetPaintOverride(GTK_STATE_ACTIVE); 28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen menu->PopupForWidget(widget, event->button, event->time); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void OnClicked(GtkWidget* widget, BrowserActionButton* action) { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action->ShowPopup(false)) 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionService* service = 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen action->toolbar_->browser()->profile()->GetExtensionService(); 29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen service->browser_event_router()->BrowserActionExecuted( 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch action->toolbar_->browser()->profile(), action->extension_->id(), 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch action->toolbar_->browser()); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static gboolean OnExposeEvent(GtkWidget* widget, 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventExpose* event, 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionButton* button) { 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = button->toolbar_->GetCurrentTabId(); 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id < 0) 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionAction* action = button->extension_->browser_action(); 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (action->GetBadgeText(tab_id).empty()) 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkiaPaint canvas(event, false); 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounding_rect(widget->allocation); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch action->PaintBadge(&canvas, bounding_rect, tab_id); 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void OnDragBegin(GtkWidget* widget, 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* drag_context, 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionButton* button) { 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Simply pass along the notification to the toolbar. The point of this 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // function is to tell the toolbar which BrowserActionButton initiated the 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // drag. 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button->toolbar_->DragStarted(button, drag_context); 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The toolbar containing this button. 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionsToolbarGtk* toolbar_; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The extension that contains this browser action. 326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension_; 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The button for this browser action. 3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<CustomDrawButton> button_; 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The top level widget (parent of |button_|). 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OwnedWidgetGtk alignment_; 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The one image subwidget in |button_|. We keep this out so we don't alter 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the widget hierarchy while changing the button image because changing the 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // GTK widget hierarchy invalidates all tooltips and several popular 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // extensions change browser action icon in a loop. 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* image_; 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Loads the button's icons for us on the file thread. 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ImageLoadingTracker tracker_; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are displaying a tab-specific icon, it will be here. 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkPixbuf* tab_specific_icon_; 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the browser action has a default icon, it will be here. 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkPixbuf* default_icon_; 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Same as |default_icon_|, but stored as SkBitmap. 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap default_skbitmap_; 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::GtkSignalRegistrar signals_; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The context menu view and model for this extension action. 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<MenuGtk> context_menu_; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<ExtensionContextMenuModel> context_menu_model_; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch friend class BrowserActionsToolbarGtk; 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserActionsToolbarGtk ---------------------------------------------------- 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : browser_(browser), 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_(browser->profile()), 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(GtkThemeService::GetFrom(browser->profile())), 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_(NULL), 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hbox_(gtk_hbox_new(FALSE, 0)), 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)), 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_button_(NULL), 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_index_(-1), 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resize_animation_(this), 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch desired_width_(0), 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_width_(0), 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_(this) { 37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* extension_service = profile_->GetExtensionService(); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The |extension_service| can be NULL in Incognito. 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!extension_service) 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overflow_button_.reset(new CustomDrawButton( 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_, 3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTIONS_OVERFLOW, 3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTIONS_OVERFLOW_P, 3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_BROWSER_ACTIONS_OVERFLOW_H, 3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, 3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE))); 3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* gripper = gtk_button_new(); 3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_set_size_request(gripper, kResizeGripperWidth, -1); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK); 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "motion-notify-event", 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperMotionNotifyThunk), this); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "expose-event", 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperExposeThunk), this); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "enter-notify-event", 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperEnterNotifyThunk), this); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "leave-notify-event", 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperLeaveNotifyThunk), this); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "button-release-event", 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperButtonReleaseThunk), this); 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(gripper, "button-press-event", 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnGripperButtonPressThunk), this); 4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(chevron(), "button-press-event", 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnOverflowButtonPressThunk), this); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // |overflow_alignment| adds padding to the right of the browser action 4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // buttons, but only appears when the overflow menu is showing. 4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick overflow_alignment_ = gtk_alignment_new(0, 0, 1, 1); 4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_container_add(GTK_CONTAINER(overflow_alignment_), chevron()); 4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // |overflow_area_| holds the overflow chevron and the separator, which 4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // is only shown in GTK+ theme mode. 4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick overflow_area_ = gtk_hbox_new(FALSE, 0); 4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_box_pack_start(GTK_BOX(overflow_area_), overflow_alignment_, 4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FALSE, FALSE, 0); 4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick separator_ = gtk_vseparator_new(); 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_box_pack_start(GTK_BOX(overflow_area_), separator_, 4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FALSE, FALSE, 0); 4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_set_no_show_all(separator_, TRUE); 4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_show_all(overflow_area_); 4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_set_no_show_all(overflow_area_, TRUE); 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0); 4303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_, FALSE, FALSE, 0); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_ = extension_service->toolbar_model(); 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->AddObserver(this); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetupDrags(); 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_->extensions_initialized()) { 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateAllButtons(); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetContainerWidth(); 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We want to connect to "set-focus" on the toplevel window; we have to wait 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // until we are added to a toplevel window to do so. 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(widget(), "hierarchy-changed", 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnHierarchyChangedThunk), this); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); 4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, 4493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationType::BROWSER_THEME_CHANGED, 4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService::AllSources()); 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->InitThemesFor(this); 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_) 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->RemoveObserver(this); 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_hbox_.Destroy(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hbox_.Destroy(); 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BrowserActionsToolbarGtk::GetCurrentTabId() { 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* selected_tab = browser_->GetSelectedTabContents(); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!selected_tab) 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return -1; 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return selected_tab->controller().session_id().id(); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::Update() { 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ExtensionButtonMap::iterator iter = extension_button_map_.begin(); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != extension_button_map_.end(); ++iter) { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter->second->UpdateState(); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowserActionsToolbarGtk::Observe(NotificationType type, 4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationSource& source, 4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const NotificationDetails& details) { 4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(NotificationType::BROWSER_THEME_CHANGED == type); 480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (theme_service_->UseGtkTheme()) 4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_show(separator_); 4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick else 4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_hide(separator_); 4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::SetupDrags() { 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkTargetEntry drag_target = GetDragTargetEntry(); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_ACTION_MOVE); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button_hbox_.get(), "drag-motion", 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDragMotionThunk), this); 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::CreateAllButtons() { 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension_button_map_.clear(); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int i = 0; 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ExtensionList::iterator iter = model_->begin(); 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != model_->end(); ++iter) { 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateButtonForExtension(*iter, i++); 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::SetContainerWidth() { 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int showing_actions = model_->GetVisibleIconCount(); 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (showing_actions >= 0) 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetButtonHBoxWidth(WidthForIconCount(showing_actions)); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 511513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserActionsToolbarGtk::CreateButtonForExtension( 512513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension, int index) { 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldDisplayBrowserAction(extension)) 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_->IsOffTheRecord()) 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = model_->OriginalIndexToIncognito(index); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveButtonForExtension(extension); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch linked_ptr<BrowserActionButton> button( 521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new BrowserActionButton(this, extension, theme_service_)); 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_shrinkable_hbox_pack_start( 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension_button_map_[extension->id()] = button; 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkTargetEntry drag_target = GetDragTargetEntry(); 5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1, 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GDK_ACTION_MOVE); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(button->button(), "drag-end", 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(&OnDragEndThunk), this); 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signals_.Connect(button->button(), "drag-failed", 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(&OnDragFailedThunk), this); 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any time a browser action button is shown or hidden we have to update 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the chevron state. 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button->widget(), "show", 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(&OnButtonShowOrHideThunk), this); 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button->widget(), "hide", 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(&OnButtonShowOrHideThunk), this); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(button->widget()); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateVisibility(); 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget( 549513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionButtonMap::iterator it = extension_button_map_.find( 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension->id()); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it == extension_button_map_.end()) 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return it->second.get()->widget(); 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 558513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserActionsToolbarGtk::RemoveButtonForExtension( 559513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (extension_button_map_.erase(extension->id())) 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateVisibility(); 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateChevronVisibility(); 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::UpdateVisibility() { 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (button_count() == 0) 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_hide(widget()); 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(widget()); 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction( 573513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only display incognito-enabled extensions while in incognito mode. 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (!profile_->IsOffTheRecord() || 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_->GetExtensionService()->IsIncognitoEnabled(extension->id())); 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::HidePopup() { 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (popup) 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch popup->DestroyPopup(); 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::AnimateToShowNIcons(int count) { 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch desired_width_ = WidthForIconCount(count); 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start_width_ = button_hbox_->allocation.width; 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resize_animation_.Reset(); 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resize_animation_.Show(); 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 592513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserActionsToolbarGtk::BrowserActionAdded(const Extension* extension, 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_.reset(); 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateButtonForExtension(extension, index); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are still initializing the container, don't bother animating. 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!model_->extensions_initialized()) 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Animate the addition if we are showing all browser action buttons. 6033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!GTK_WIDGET_VISIBLE(overflow_area_)) { 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToShowNIcons(button_count()); 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->SetVisibleIconCount(button_count()); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 609513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserActionsToolbarGtk::BrowserActionRemoved( 610513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_.reset(); 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_button_ != NULL) { 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Break the current drag. 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_grab_remove(button_hbox_.get()); 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RemoveButtonForExtension(extension); 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!GTK_WIDGET_VISIBLE(overflow_area_)) { 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToShowNIcons(button_count()); 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->SetVisibleIconCount(button_count()); 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 626513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BrowserActionsToolbarGtk::BrowserActionMoved(const Extension* extension, 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We initiated this move action, and have already moved the button. 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_button_ != NULL) 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* button_widget = GetBrowserActionWidget(extension); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!button_widget) { 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ShouldDisplayBrowserAction(extension)) 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_->IsOffTheRecord()) 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = model_->OriginalIndexToIncognito(index); 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button_widget, index); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::ModelLoaded() { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetContainerWidth(); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BrowserActionsToolbarGtk::AnimationProgressed( 6503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const ui::Animation* animation) { 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int width = start_width_ + (desired_width_ - start_width_) * 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation->GetCurrentValue(); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(button_hbox_.get(), width, -1); 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (width == desired_width_) 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resize_animation_.Reset(); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BrowserActionsToolbarGtk::AnimationEnded(const ui::Animation* animation) { 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(button_hbox_.get(), desired_width_, -1); 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateChevronVisibility(); 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BrowserActionsToolbarGtk::IsCommandIdChecked(int command_id) const { 66521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 66621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 66721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 66821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BrowserActionsToolbarGtk::IsCommandIdEnabled(int command_id) const { 66921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 67021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 67121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 67221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool BrowserActionsToolbarGtk::GetAcceleratorForCommandId( 67321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int command_id, 67472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::Accelerator* accelerator) { 67521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 67621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 67721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::ExecuteCommand(int command_id) { 679513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = model_->GetExtensionByIndex(command_id); 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionAction* browser_action = extension->browser_action(); 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tab_id = GetCurrentTabId(); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tab_id < 0) { 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "No current tab."; 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser_action->HasPopup(tab_id)) { 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionPopupGtk::Show( 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_action->GetPopupUrl(tab_id), browser(), 6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chevron(), 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch false); 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 69472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionService* service = browser()->profile()->GetExtensionService(); 69572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen service->browser_event_router()->BrowserActionExecuted( 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser()->profile(), extension->id(), browser()); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::StoppedShowing() { 7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick overflow_button_->UnsetPaintOverride(); 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool BrowserActionsToolbarGtk::AlwaysShowIconForCmd(int command_id) const { 705731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 706731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 707731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button, 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* drag_context) { 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No representation of the widget following the cursor. 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_drag_set_icon_pixbuf(drag_context, pixbuf, 0, 0); 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(pixbuf); 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!drag_button_); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_button_ = button; 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::SetButtonHBoxWidth(int new_width) { 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint max_width = WidthForIconCount(button_count()); 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_width = std::min(max_width, new_width); 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_width = std::max(new_width, 0); 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(button_hbox_.get(), new_width, -1); 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::UpdateChevronVisibility() { 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int showing_icon_count = 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_shrinkable_hbox_get_visible_child_count( 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (showing_icon_count == 0) { 7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0, 0, 0); 7323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 7333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0, 7343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kButtonChevronPadding, 0); 7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (button_count() > showing_icon_count) { 7383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!GTK_WIDGET_VISIBLE(overflow_area_)) { 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drag_button_) { 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // During drags, when the overflow chevron shows for the first time, 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // take that much space away from |button_hbox_| to make the drag look 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // smoother. 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkRequisition req; 7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_size_request(chevron(), &req); 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint overflow_width = req.width; 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_size_request(button_hbox_.get(), &req); 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint button_hbox_width = req.width; 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_hbox_width = std::max(button_hbox_width - overflow_width, 0); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1); 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_show(overflow_area_); 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_widget_hide(overflow_area_); 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget, 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* drag_context, 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint x, gint y, guint time) { 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only handle drags we initiated. 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!drag_button_) 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (base::i18n::IsRTL()) 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x = widget->allocation.width - x; 7683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick drop_index_ = x < kButtonWidth ? 0 : x / (kButtonWidth + kButtonPadding); 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will go ahead and reorder the child in order to provide visual feedback 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the user. We don't inform the model that it has moved until the drag 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ends. 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), drag_button_->widget(), 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_index_); 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_drag_status(drag_context, GDK_ACTION_MOVE, time); 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::OnDragEnd(GtkWidget* button, 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* drag_context) { 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_index_ != -1) { 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_->IsOffTheRecord()) 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_index_ = model_->IncognitoIndexToOriginal(drop_index_); 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->MoveBrowserAction(drag_button_->extension(), drop_index_); 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_button_ = NULL; 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_index_ = -1; 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnDragFailed(GtkWidget* widget, 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkDragContext* drag_context, 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkDragResult result) { 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We connect to this signal and return TRUE so that the default failure 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // animation (wherein the drag widget floats back to the start of the drag) 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // does not show, and the drag-end signal is emitted immediately instead of 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // several seconds later. 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::OnHierarchyChanged( 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget, GtkWidget* previous_toplevel) { 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* toplevel = gtk_widget_get_toplevel(widget); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GTK_WIDGET_TOPLEVEL(toplevel)) 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget, 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* focus_widget) { 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The focus of the parent window has changed. Close the popup. Delay the hide 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because it will destroy the RenderViewHost, which may still be on the 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // call stack. 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!popup || popup->being_inspected()) 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch method_factory_.NewRunnableMethod(&BrowserActionsToolbarGtk::HidePopup)); 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperMotionNotify( 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget, GdkEventMotion* event) { 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(event->state & GDK_BUTTON1_MASK)) 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Calculate how much the user dragged the gripper and subtract that off the 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // button container's width. 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int distance_dragged = base::i18n::IsRTL() ? 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch -event->x : 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->x - widget->allocation.width; 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gint new_width = button_hbox_->allocation.width - distance_dragged; 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetButtonHBoxWidth(new_width); 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperExpose(GtkWidget* gripper, 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventExpose* expose) { 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These three signal handlers (EnterNotify, LeaveNotify, and ButtonRelease) 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// are used to give the gripper the resize cursor. Since it doesn't have its 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// own window, we have to set the cursor whenever the pointer moves into the 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// button or leaves the button, and be sure to leave it on when the user is 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dragging. 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperEnterNotify( 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* gripper, GdkEventCrossing* event) { 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_window_set_cursor(gripper->window, 853201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW)); 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperLeaveNotify( 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* gripper, GdkEventCrossing* event) { 8593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(event->state & GDK_BUTTON1_MASK)) 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_window_set_cursor(gripper->window, NULL); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperButtonRelease( 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* gripper, GdkEventButton* event) { 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect gripper_rect(0, 0, 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gripper->allocation.width, gripper->allocation.height); 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point release_point(event->x, event->y); 8693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!gripper_rect.Contains(release_point)) 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdk_window_set_cursor(gripper->window, NULL); 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // After the user resizes the toolbar, we want to smartly resize it to be 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the perfect size to fit the buttons. 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int visible_icon_count = 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_shrinkable_hbox_get_visible_child_count( 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimateToShowNIcons(visible_icon_count); 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_->SetVisibleIconCount(visible_icon_count); 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnGripperButtonPress( 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* gripper, GdkEventButton* event) { 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resize_animation_.Reset(); 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnOverflowButtonPress( 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* overflow, GdkEventButton* event) { 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_model_.reset(new SimpleMenuModel(this)); 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int visible_icon_count = 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_shrinkable_hbox_get_visible_child_count( 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = visible_icon_count; i < button_count(); ++i) { 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int model_index = i; 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_->IsOffTheRecord()) 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_index = model_->IncognitoIndexToOriginal(i); 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 902513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = model_->GetExtensionByIndex(model_index); 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserActionButton* button = extension_button_map_[extension->id()].get(); 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_model_->AddItem(model_index, UTF8ToUTF16(extension->name())); 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_model_->SetIcon(overflow_menu_model_->GetItemCount() - 1, 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button->GetIcon()); 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(estade): set the menu item's tooltip. 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch overflow_menu_.reset(new MenuGtk(this, overflow_menu_model_.get())); 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(overflow_menu_->widget(), "button-press-event", 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnOverflowMenuButtonPressThunk), this); 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE); 9173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick overflow_menu_->PopupAsFromKeyEvent(chevron()); 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress( 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* overflow, GdkEventButton* event) { 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->button != 3) 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item; 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!menu_item) 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int item_index = g_list_index(GTK_MENU_SHELL(overflow)->children, menu_item); 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (item_index == -1) { 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item_index += gtk_chrome_shrinkable_hbox_get_visible_child_count( 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_->IsOffTheRecord()) 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item_index = model_->IncognitoIndexToOriginal(item_index); 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 942513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = model_->GetExtensionByIndex(item_index); 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ExtensionButtonMap::iterator it = extension_button_map_.find( 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch extension->id()); 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it == extension_button_map_.end()) { 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MenuGtk* menu = it->second.get()->GetContextMenu(); 95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!menu) 95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return FALSE; 95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen menu->PopupAsContext(gfx::Point(event->x_root, event->y_root), 95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event->time); 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!resize_animation_.is_animating()) 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UpdateChevronVisibility(); 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 963