Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3963)

Unified Diff: chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc

Issue 231733005: Delete the GTK+ port of Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remerge to ToT Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
deleted file mode 100644
index 9091988e16ff5a69e3b05b4b1e7c75973c0d5065..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
+++ /dev/null
@@ -1,1125 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h"
-
-#include <gtk/gtk.h>
-
-#include <algorithm>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/i18n/rtl.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/api/commands/command_service.h"
-#include "chrome/browser/extensions/extension_action.h"
-#include "chrome/browser/extensions/extension_action_icon_factory.h"
-#include "chrome/browser/extensions/extension_action_manager.h"
-#include "chrome/browser/extensions/extension_context_menu_model.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_toolbar_model.h"
-#include "chrome/browser/extensions/extension_util.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/gtk/browser_window_gtk.h"
-#include "chrome/browser/ui/gtk/custom_button.h"
-#include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h"
-#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
-#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
-#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#include "chrome/browser/ui/gtk/gtk_util.h"
-#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
-#include "chrome/browser/ui/gtk/menu_gtk.h"
-#include "chrome/browser/ui/gtk/view_id_util.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/extension.h"
-#include "extensions/common/manifest_constants.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#include "ui/base/accelerators/platform_accelerator_gtk.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/canvas_skia_paint.h"
-#include "ui/gfx/gtk_compat.h"
-#include "ui/gfx/gtk_util.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia_operations.h"
-
-using extensions::Extension;
-using extensions::ExtensionActionManager;
-
-namespace {
-
-// The width of the browser action buttons.
-const int kButtonWidth = 27;
-
-// The padding between browser action buttons.
-const int kButtonPadding = 4;
-
-// The padding to the right of the browser action buttons (between the buttons
-// and chevron if they are both showing).
-const int kButtonChevronPadding = 2;
-
-// Width of the invisible gripper for resizing the toolbar.
-const int kResizeGripperWidth = 4;
-
-const char kDragTarget[] = "application/x-chrome-browseraction";
-
-GtkTargetEntry GetDragTargetEntry() {
- GtkTargetEntry drag_target;
- drag_target.target = const_cast<char*>(kDragTarget);
- drag_target.flags = GTK_TARGET_SAME_APP;
- drag_target.info = 0;
- return drag_target;
-}
-
-// The minimum width in pixels of the button hbox if |icon_count| icons are
-// showing.
-gint WidthForIconCount(gint icon_count) {
- return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding,
- 0);
-}
-
-} // namespace
-
-using ui::SimpleMenuModel;
-
-class BrowserActionButton : public content::NotificationObserver,
- public ExtensionActionIconFactory::Observer,
- public ExtensionContextMenuModel::PopupDelegate,
- public MenuGtk::Delegate {
- public:
- BrowserActionButton(BrowserActionsToolbarGtk* toolbar,
- const Extension* extension,
- GtkThemeService* theme_provider)
- : toolbar_(toolbar),
- extension_(extension),
- image_(NULL),
- icon_factory_(toolbar->browser()->profile(), extension,
- browser_action(), this),
- accel_group_(NULL) {
- button_.reset(new CustomDrawButton(
- theme_provider,
- IDR_BROWSER_ACTION,
- IDR_BROWSER_ACTION_P,
- IDR_BROWSER_ACTION_H,
- 0,
- NULL));
- gtk_widget_set_size_request(button(), kButtonWidth, kButtonWidth);
- alignment_.Own(gtk_alignment_new(0, 0, 1, 1));
- gtk_container_add(GTK_CONTAINER(alignment_.get()), button());
- gtk_widget_show(button());
-
- DCHECK(browser_action());
-
- UpdateState();
-
- signals_.Connect(button(), "button-press-event",
- G_CALLBACK(OnButtonPress), this);
- signals_.Connect(button(), "clicked",
- G_CALLBACK(OnClicked), this);
- signals_.Connect(button(), "drag-begin",
- G_CALLBACK(OnDragBegin), this);
- signals_.ConnectAfter(widget(), "expose-event",
- G_CALLBACK(OnExposeEvent), this);
- if (toolbar_->browser()->window()) {
- // If the window exists already, then the browser action button has been
- // recreated after the window was created, for example when the extension
- // is reloaded.
- ConnectBrowserActionPopupAccelerator();
- } else {
- // Window doesn't exist yet, wait for it.
- signals_.Connect(toolbar->widget(), "realize",
- G_CALLBACK(OnRealize), this);
- }
-
- registrar_.Add(
- this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
- content::Source<ExtensionAction>(browser_action()));
- registrar_.Add(
- this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
- content::Source<Profile>(
- toolbar->browser()->profile()->GetOriginalProfile()));
- registrar_.Add(
- this, chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED,
- content::Source<Profile>(
- toolbar->browser()->profile()->GetOriginalProfile()));
- registrar_.Add(
- this, chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED,
- content::Source<Profile>(
- toolbar->browser()->profile()->GetOriginalProfile()));
- }
-
- virtual ~BrowserActionButton() {
- DisconnectBrowserActionPopupAccelerator();
-
- alignment_.Destroy();
- }
-
- GtkWidget* button() { return button_->widget(); }
-
- GtkWidget* widget() { return alignment_.get(); }
-
- const Extension* extension() { return extension_; }
-
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE {
- switch (type) {
- case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED:
- UpdateState();
- break;
- case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
- case chrome::NOTIFICATION_WINDOW_CLOSED:
- DisconnectBrowserActionPopupAccelerator();
- break;
- case chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED:
- case chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED: {
- std::pair<const std::string, const std::string>* payload =
- content::Details<std::pair<const std::string, const std::string> >(
- details).ptr();
- if (extension_->id() == payload->first &&
- payload->second ==
- extensions::manifest_values::kBrowserActionCommandEvent) {
- if (type == chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED)
- ConnectBrowserActionPopupAccelerator();
- else
- DisconnectBrowserActionPopupAccelerator();
- }
- break;
- }
- default:
- NOTREACHED();
- break;
- }
- }
-
- // ExtensionActionIconFactory::Observer implementation.
- virtual void OnIconUpdated() OVERRIDE {
- UpdateState();
- }
-
- // Updates the button based on the latest state from the associated
- // browser action.
- void UpdateState() {
- int tab_id = toolbar_->GetCurrentTabId();
- if (tab_id < 0)
- return;
-
- std::string tooltip = browser_action()->GetTitle(tab_id);
- if (tooltip.empty())
- gtk_widget_set_has_tooltip(button(), FALSE);
- else
- gtk_widget_set_tooltip_text(button(), tooltip.c_str());
-
- enabled_ = browser_action()->GetIsVisible(tab_id);
- if (!enabled_)
- button_->SetPaintOverride(GTK_STATE_INSENSITIVE);
- else
- button_->UnsetPaintOverride();
-
- gfx::Image image = icon_factory_.GetIcon(tab_id);
- if (!image.IsEmpty()) {
- if (enabled_) {
- SetImage(image);
- } else {
- SetImage(gfx::Image(gfx::ImageSkiaOperations::CreateTransparentImage(
- image.AsImageSkia(), .25)));
- }
- }
-
- gtk_widget_queue_draw(button());
- }
-
- gfx::Image GetIcon() {
- return icon_factory_.GetIcon(toolbar_->GetCurrentTabId());
- }
-
- MenuGtk* GetContextMenu() {
- if (!extension_->ShowConfigureContextMenus())
- return NULL;
-
- context_menu_model_ =
- new ExtensionContextMenuModel(extension_, toolbar_->browser(), this);
- context_menu_.reset(
- new MenuGtk(this, context_menu_model_.get()));
- return context_menu_.get();
- }
-
- private:
- // Activate the browser action. Returns true if a popup was shown. Showing the
- // popup will grant tab permissions if |should_grant| is true. Popup's shown
- // via an API should not grant permissions.
- bool Activate(GtkWidget* widget, bool should_grant) {
- extensions::ExtensionToolbarModel* model = toolbar_->model();
- const Extension* extension = extension_;
- Browser* browser = toolbar_->browser();
- GURL popup_url;
-
- switch (model->ExecuteBrowserAction(
- extension, browser, &popup_url, should_grant)) {
- case extensions::ExtensionToolbarModel::ACTION_NONE:
- break;
- case extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP:
- ExtensionPopupGtk::Show(popup_url, browser, widget,
- ExtensionPopupGtk::SHOW);
- return true;
- }
- return false;
- }
-
- // MenuGtk::Delegate implementation.
- virtual void StoppedShowing() OVERRIDE {
- if (enabled_)
- button_->UnsetPaintOverride();
- else
- button_->SetPaintOverride(GTK_STATE_INSENSITIVE);
-
- // If the context menu was showing for the overflow menu, re-assert the
- // grab that was shadowed.
- if (toolbar_->overflow_menu_.get())
- gtk_util::GrabAllInput(toolbar_->overflow_menu_->widget());
- }
-
- virtual void CommandWillBeExecuted() OVERRIDE {
- // If the context menu was showing for the overflow menu, and a command
- // is executed, then stop showing the overflow menu.
- if (toolbar_->overflow_menu_.get())
- toolbar_->overflow_menu_->Cancel();
- }
-
- // ExtensionContextMenuModel::PopupDelegate implementation.
- virtual void InspectPopup(ExtensionAction* action) OVERRIDE {
- GURL popup_url = action->GetPopupUrl(toolbar_->GetCurrentTabId());
- ExtensionPopupGtk::Show(popup_url, toolbar_->browser(), widget(),
- ExtensionPopupGtk::SHOW_AND_INSPECT);
- }
-
- void SetImage(const gfx::Image& image) {
- if (!image_) {
- image_ = gtk_image_new_from_pixbuf(image.ToGdkPixbuf());
- gtk_button_set_image(GTK_BUTTON(button()), image_);
- } else {
- gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image.ToGdkPixbuf());
- }
- }
-
- static gboolean OnButtonPress(GtkWidget* widget,
- GdkEventButton* event,
- BrowserActionButton* button) {
- if (event->button != 3)
- return FALSE;
-
- MenuGtk* menu = button->GetContextMenu();
- if (!menu)
- return FALSE;
-
- button->button_->SetPaintOverride(GTK_STATE_ACTIVE);
- menu->PopupForWidget(widget, event->button, event->time);
-
- return TRUE;
- }
-
- static void OnClicked(GtkWidget* widget, BrowserActionButton* button) {
- if (button->enabled_)
- button->Activate(widget, true);
- }
-
- static gboolean OnExposeEvent(GtkWidget* widget,
- GdkEventExpose* event,
- BrowserActionButton* button) {
- int tab_id = button->toolbar_->GetCurrentTabId();
- if (tab_id < 0)
- return FALSE;
-
- ExtensionAction* action = button->browser_action();
- if (action->GetBadgeText(tab_id).empty())
- return FALSE;
-
- gfx::CanvasSkiaPaint canvas(event, false);
- GtkAllocation allocation;
- gtk_widget_get_allocation(widget, &allocation);
- action->PaintBadge(&canvas, gfx::Rect(allocation), tab_id);
- return FALSE;
- }
-
- static void OnDragBegin(GtkWidget* widget,
- GdkDragContext* drag_context,
- BrowserActionButton* button) {
- // Simply pass along the notification to the toolbar. The point of this
- // function is to tell the toolbar which BrowserActionButton initiated the
- // drag.
- button->toolbar_->DragStarted(button, drag_context);
- }
-
- // The accelerator handler for when the shortcuts to open the popup is struck.
- static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group,
- GObject* acceleratable,
- guint keyval,
- GdkModifierType modifier,
- BrowserActionButton* button) {
- // Open the popup for this extension.
- GtkWidget* anchor = button->widget();
- // The anchor might be in the overflow menu. Then we point to the chevron.
- if (!gtk_widget_get_visible(anchor))
- anchor = button->toolbar_->chevron();
- button->Activate(anchor, true);
- return TRUE;
- }
-
- // The handler for when the browser action is realized. |user_data| contains a
- // pointer to the BrowserAction shown.
- static void OnRealize(GtkWidget* widget, void* user_data) {
- BrowserActionButton* button = static_cast<BrowserActionButton*>(user_data);
- button->ConnectBrowserActionPopupAccelerator();
- }
-
- // Connect the accelerator for the browser action popup.
- void ConnectBrowserActionPopupAccelerator() {
- extensions::CommandService* command_service =
- extensions::CommandService::Get(toolbar_->browser()->profile());
- extensions::Command command;
- if (command_service->GetBrowserActionCommand(extension_->id(),
- extensions::CommandService::ACTIVE_ONLY,
- &command,
- NULL)) {
- // Found the browser action shortcut command, register it.
- keybinding_ = command.accelerator();
-
- gfx::NativeWindow window =
- toolbar_->browser()->window()->GetNativeWindow();
- accel_group_ = gtk_accel_group_new();
- gtk_window_add_accel_group(window, accel_group_);
-
- gtk_accel_group_connect(
- accel_group_,
- ui::GetGdkKeyCodeForAccelerator(keybinding_),
- ui::GetGdkModifierForAccelerator(keybinding_),
- GtkAccelFlags(0),
- g_cclosure_new(G_CALLBACK(OnGtkAccelerator), this, NULL));
-
- // Since we've added an accelerator, we'll need to unregister it before
- // the window is closed, so we listen for the window being closed.
- registrar_.Add(this,
- chrome::NOTIFICATION_WINDOW_CLOSED,
- content::Source<GtkWindow>(window));
- }
- }
-
- // Disconnect the accelerator for the browser action popup and delete clean up
- // the accelerator group registration.
- void DisconnectBrowserActionPopupAccelerator() {
- if (accel_group_) {
- gfx::NativeWindow window =
- toolbar_->browser()->window()->GetNativeWindow();
- gtk_accel_group_disconnect_key(
- accel_group_,
- ui::GetGdkKeyCodeForAccelerator(keybinding_),
- GetGdkModifierForAccelerator(keybinding_));
- gtk_window_remove_accel_group(window, accel_group_);
- g_object_unref(accel_group_);
- accel_group_ = NULL;
- keybinding_ = ui::Accelerator();
-
- // We've removed the accelerator, so no need to listen to this anymore.
- registrar_.Remove(this,
- chrome::NOTIFICATION_WINDOW_CLOSED,
- content::Source<GtkWindow>(window));
- }
- }
-
- ExtensionAction* browser_action() const {
- return ExtensionActionManager::Get(toolbar_->browser()->profile())->
- GetBrowserAction(*extension_);
- }
-
- // The toolbar containing this button.
- BrowserActionsToolbarGtk* toolbar_;
-
- // The extension that contains this browser action.
- const Extension* extension_;
-
- // The button for this browser action.
- scoped_ptr<CustomDrawButton> button_;
-
- // Whether the browser action is enabled (equivalent to whether a page action
- // is visible).
- bool enabled_;
-
- // The top level widget (parent of |button_|).
- ui::OwnedWidgetGtk alignment_;
-
- // The one image subwidget in |button_|. We keep this out so we don't alter
- // the widget hierarchy while changing the button image because changing the
- // GTK widget hierarchy invalidates all tooltips and several popular
- // extensions change browser action icon in a loop.
- GtkWidget* image_;
-
- // The object that will be used to get the browser action icon for us.
- // It may load the icon asynchronously (in which case the initial icon
- // returned by the factory will be transparent), so we have to observe it for
- // updates to the icon.
- ExtensionActionIconFactory icon_factory_;
-
- // Same as |default_icon_|, but stored as SkBitmap.
- SkBitmap default_skbitmap_;
-
- ui::GtkSignalRegistrar signals_;
- content::NotificationRegistrar registrar_;
-
- // The accelerator group used to handle accelerators, owned by this object.
- GtkAccelGroup* accel_group_;
-
- // The keybinding accelerator registered to show the browser action popup.
- ui::Accelerator keybinding_;
-
- // The context menu view and model for this extension action.
- scoped_ptr<MenuGtk> context_menu_;
- scoped_refptr<ExtensionContextMenuModel> context_menu_model_;
-
- friend class BrowserActionsToolbarGtk;
-};
-
-// BrowserActionsToolbarGtk ----------------------------------------------------
-
-BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser)
- : browser_(browser),
- profile_(browser->profile()),
- theme_service_(GtkThemeService::GetFrom(browser->profile())),
- model_(NULL),
- hbox_(gtk_hbox_new(FALSE, 0)),
- button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)),
- drag_button_(NULL),
- drop_index_(-1),
- resize_animation_(this),
- desired_width_(0),
- start_width_(0),
- weak_factory_(this) {
- model_ = extensions::ExtensionToolbarModel::Get(profile_);
- if (!model_)
- return;
-
- overflow_button_.reset(new CustomDrawButton(
- theme_service_,
- IDR_BROWSER_ACTIONS_OVERFLOW,
- IDR_BROWSER_ACTIONS_OVERFLOW_P,
- IDR_BROWSER_ACTIONS_OVERFLOW_H,
- 0,
- gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)));
-
- GtkWidget* gripper = gtk_button_new();
- gtk_widget_set_size_request(gripper, kResizeGripperWidth, -1);
- gtk_widget_set_can_focus(gripper, FALSE);
-
- gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK);
- signals_.Connect(gripper, "motion-notify-event",
- G_CALLBACK(OnGripperMotionNotifyThunk), this);
- signals_.Connect(gripper, "expose-event",
- G_CALLBACK(OnGripperExposeThunk), this);
- signals_.Connect(gripper, "enter-notify-event",
- G_CALLBACK(OnGripperEnterNotifyThunk), this);
- signals_.Connect(gripper, "leave-notify-event",
- G_CALLBACK(OnGripperLeaveNotifyThunk), this);
- signals_.Connect(gripper, "button-release-event",
- G_CALLBACK(OnGripperButtonReleaseThunk), this);
- signals_.Connect(gripper, "button-press-event",
- G_CALLBACK(OnGripperButtonPressThunk), this);
- signals_.Connect(chevron(), "button-press-event",
- G_CALLBACK(OnOverflowButtonPressThunk), this);
-
- // |overflow_alignment| adds padding to the right of the browser action
- // buttons, but only appears when the overflow menu is showing.
- overflow_alignment_.Own(gtk_alignment_new(0, 0, 1, 1));
- gtk_container_add(GTK_CONTAINER(overflow_alignment_.get()), chevron());
-
- // |overflow_area_| holds the overflow chevron and the separator, which
- // is only shown in GTK+ theme mode.
- overflow_area_.Own(gtk_hbox_new(FALSE, 0));
- gtk_box_pack_start(GTK_BOX(overflow_area_.get()), overflow_alignment_.get(),
- FALSE, FALSE, 0);
-
- separator_.Own(gtk_vseparator_new());
- gtk_box_pack_start(GTK_BOX(overflow_area_.get()), separator_.get(),
- FALSE, FALSE, 0);
- gtk_widget_set_no_show_all(separator_.get(), TRUE);
-
- gtk_widget_show_all(overflow_area_.get());
- gtk_widget_set_no_show_all(overflow_area_.get(), TRUE);
-
- gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_.get(), FALSE, FALSE,
- 0);
-
- model_->AddObserver(this);
- SetupDrags();
-
- if (model_->extensions_initialized()) {
- CreateAllButtons();
- SetContainerWidth();
- }
-
- // We want to connect to "set-focus" on the toplevel window; we have to wait
- // until we are added to a toplevel window to do so.
- signals_.Connect(widget(), "hierarchy-changed",
- G_CALLBACK(OnHierarchyChangedThunk), this);
-
- ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR);
-
- registrar_.Add(this,
- chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
- content::Source<ThemeService>(theme_service_));
- theme_service_->InitThemesFor(this);
-}
-
-BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() {
- if (model_)
- model_->RemoveObserver(this);
- button_hbox_.Destroy();
- hbox_.Destroy();
-}
-
-int BrowserActionsToolbarGtk::GetCurrentTabId() const {
- content::WebContents* active_tab =
- browser_->tab_strip_model()->GetActiveWebContents();
- if (!active_tab)
- return -1;
-
- return SessionTabHelper::FromWebContents(active_tab)->session_id().id();
-}
-
-void BrowserActionsToolbarGtk::Update() {
- for (ExtensionButtonMap::iterator iter = extension_button_map_.begin();
- iter != extension_button_map_.end(); ++iter) {
- iter->second->UpdateState();
- }
-}
-
-void BrowserActionsToolbarGtk::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(chrome::NOTIFICATION_BROWSER_THEME_CHANGED == type);
- gtk_widget_set_visible(separator_.get(), theme_service_->UsingNativeTheme());
-}
-
-void BrowserActionsToolbarGtk::SetupDrags() {
- GtkTargetEntry drag_target = GetDragTargetEntry();
- gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1,
- GDK_ACTION_MOVE);
-
- signals_.Connect(button_hbox_.get(), "drag-motion",
- G_CALLBACK(OnDragMotionThunk), this);
-}
-
-void BrowserActionsToolbarGtk::CreateAllButtons() {
- extension_button_map_.clear();
-
- int i = 0;
- const extensions::ExtensionList& toolbar_items = model_->toolbar_items();
- for (extensions::ExtensionList::const_iterator iter = toolbar_items.begin();
- iter != toolbar_items.end(); ++iter) {
- CreateButtonForExtension(iter->get(), i++);
- }
-}
-
-void BrowserActionsToolbarGtk::SetContainerWidth() {
- int showing_actions = model_->GetVisibleIconCount();
- if (showing_actions >= 0)
- SetButtonHBoxWidth(WidthForIconCount(showing_actions));
-}
-
-void BrowserActionsToolbarGtk::CreateButtonForExtension(
- const Extension* extension, int index) {
- if (!ShouldDisplayBrowserAction(extension))
- return;
-
- if (profile_->IsOffTheRecord())
- index = model_->OriginalIndexToIncognito(index);
-
- RemoveButtonForExtension(extension);
- linked_ptr<BrowserActionButton> button(
- new BrowserActionButton(this, extension, theme_service_));
- gtk_chrome_shrinkable_hbox_pack_start(
- GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0);
- gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index);
- extension_button_map_[extension->id()] = button;
-
- GtkTargetEntry drag_target = GetDragTargetEntry();
- gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1,
- GDK_ACTION_MOVE);
- // We ignore whether the drag was a "success" or "failure" in Gtk's opinion.
- signals_.Connect(button->button(), "drag-end",
- G_CALLBACK(&OnDragEndThunk), this);
- signals_.Connect(button->button(), "drag-failed",
- G_CALLBACK(&OnDragFailedThunk), this);
-
- // Any time a browser action button is shown or hidden we have to update
- // the chevron state.
- signals_.Connect(button->widget(), "show",
- G_CALLBACK(&OnButtonShowOrHideThunk), this);
- signals_.Connect(button->widget(), "hide",
- G_CALLBACK(&OnButtonShowOrHideThunk), this);
-
- gtk_widget_show(button->widget());
-
- UpdateVisibility();
-}
-
-BrowserActionButton* BrowserActionsToolbarGtk::GetBrowserActionButton(
- const Extension* extension) {
- ExtensionButtonMap::iterator it = extension_button_map_.find(
- extension->id());
- return it == extension_button_map_.end() ? NULL : it->second.get();
-}
-
-GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget(
- const Extension* extension) {
- BrowserActionButton* button = GetBrowserActionButton(extension);
- return button == NULL ? NULL : button->widget();
-}
-
-void BrowserActionsToolbarGtk::RemoveButtonForExtension(
- const Extension* extension) {
- if (extension_button_map_.erase(extension->id()))
- UpdateVisibility();
- UpdateChevronVisibility();
-}
-
-void BrowserActionsToolbarGtk::UpdateVisibility() {
- gtk_widget_set_visible(widget(), button_count() != 0);
-}
-
-bool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction(
- const Extension* extension) {
- // Only display incognito-enabled extensions while in incognito mode.
- return (!profile_->IsOffTheRecord() ||
- extensions::util::IsIncognitoEnabled(extension->id(), profile_));
-}
-
-void BrowserActionsToolbarGtk::HidePopup() {
- ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
- if (popup)
- popup->DestroyPopup();
-}
-
-void BrowserActionsToolbarGtk::AnimateToShowNIcons(int count) {
- desired_width_ = WidthForIconCount(count);
-
- GtkAllocation allocation;
- gtk_widget_get_allocation(button_hbox_.get(), &allocation);
- start_width_ = allocation.width;
-
- resize_animation_.Reset();
- resize_animation_.Show();
-}
-
-void BrowserActionsToolbarGtk::BrowserActionAdded(const Extension* extension,
- int index) {
- overflow_menu_.reset();
-
- CreateButtonForExtension(extension, index);
-
- // If we are still initializing the container, don't bother animating.
- if (!model_->extensions_initialized())
- return;
-
- // Animate the addition if we are showing all browser action buttons.
- if (!gtk_widget_get_visible(overflow_area_.get())) {
- AnimateToShowNIcons(button_count());
- model_->SetVisibleIconCount(button_count());
- }
-}
-
-void BrowserActionsToolbarGtk::BrowserActionRemoved(
- const Extension* extension) {
- overflow_menu_.reset();
-
- if (drag_button_ != NULL) {
- // Break the current drag.
- gtk_grab_remove(button_hbox_.get());
- }
-
- RemoveButtonForExtension(extension);
-
- if (!gtk_widget_get_visible(overflow_area_.get())) {
- AnimateToShowNIcons(button_count());
- model_->SetVisibleIconCount(button_count());
- }
-}
-
-void BrowserActionsToolbarGtk::BrowserActionMoved(const Extension* extension,
- int index) {
- // We initiated this move action, and have already moved the button.
- if (drag_button_ != NULL)
- return;
-
- GtkWidget* button_widget = GetBrowserActionWidget(extension);
- if (!button_widget) {
- if (ShouldDisplayBrowserAction(extension))
- NOTREACHED();
- return;
- }
-
- if (profile_->IsOffTheRecord())
- index = model_->OriginalIndexToIncognito(index);
-
- gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button_widget, index);
-}
-
-bool BrowserActionsToolbarGtk::BrowserActionShowPopup(
- const Extension* extension) {
- // Do not override other popups and only show in active window.
- if (ExtensionPopupGtk::get_current_extension_popup() ||
- !browser_->window()->IsActive()) {
- return false;
- }
-
- BrowserActionButton* button = GetBrowserActionButton(extension);
- if (button == NULL || button->widget() == NULL)
- return false;
-
- GtkWidget* anchor = button->widget();
- if (!gtk_widget_get_visible(anchor))
- anchor = button->toolbar_->chevron();
- return button->Activate(anchor, false);
-}
-
-void BrowserActionsToolbarGtk::VisibleCountChanged() {
- SetContainerWidth();
-}
-
-void BrowserActionsToolbarGtk::AnimationProgressed(
- const gfx::Animation* animation) {
- int width = start_width_ + (desired_width_ - start_width_) *
- animation->GetCurrentValue();
- gtk_widget_set_size_request(button_hbox_.get(), width, -1);
-
- if (width == desired_width_)
- resize_animation_.Reset();
-}
-
-void BrowserActionsToolbarGtk::AnimationEnded(const gfx::Animation* animation) {
- gtk_widget_set_size_request(button_hbox_.get(), desired_width_, -1);
- UpdateChevronVisibility();
-}
-
-bool BrowserActionsToolbarGtk::IsCommandIdChecked(int command_id) const {
- return false;
-}
-
-bool BrowserActionsToolbarGtk::IsCommandIdEnabled(int command_id) const {
- const Extension* extension = model_->toolbar_items()[command_id].get();
- return ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension)
- ->GetIsVisible(GetCurrentTabId());
-}
-
-bool BrowserActionsToolbarGtk::GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) {
- return false;
-}
-
-void BrowserActionsToolbarGtk::ExecuteCommand(int command_id, int event_flags) {
- const Extension* extension = model_->toolbar_items()[command_id].get();
- GURL popup_url;
-
- switch (model_->ExecuteBrowserAction(
- extension, browser(), &popup_url, true)) {
- case extensions::ExtensionToolbarModel::ACTION_NONE:
- break;
- case extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP:
- ExtensionPopupGtk::Show(popup_url, browser(), chevron(),
- ExtensionPopupGtk::SHOW);
- break;
- }
-}
-
-void BrowserActionsToolbarGtk::StoppedShowing() {
- overflow_button_->UnsetPaintOverride();
-}
-
-bool BrowserActionsToolbarGtk::AlwaysShowIconForCmd(int command_id) const {
- return true;
-}
-
-void BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button,
- GdkDragContext* drag_context) {
- // No representation of the widget following the cursor.
- GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
- gtk_drag_set_icon_pixbuf(drag_context, pixbuf, 0, 0);
- g_object_unref(pixbuf);
-
- DCHECK(!drag_button_);
- drag_button_ = button;
-}
-
-void BrowserActionsToolbarGtk::SetButtonHBoxWidth(int new_width) {
- gint max_width = WidthForIconCount(button_count());
- new_width = std::min(max_width, new_width);
- new_width = std::max(new_width, 0);
- gtk_widget_set_size_request(button_hbox_.get(), new_width, -1);
-}
-
-void BrowserActionsToolbarGtk::UpdateChevronVisibility() {
- int showing_icon_count =
- gtk_chrome_shrinkable_hbox_get_visible_child_count(
- GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
- if (showing_icon_count == 0) {
- gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_.get()),
- 0, 0, 0, 0);
- } else {
- gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_.get()),
- 0, 0, kButtonChevronPadding, 0);
- }
-
- if (button_count() > showing_icon_count) {
- if (!gtk_widget_get_visible(overflow_area_.get())) {
- if (drag_button_) {
- // During drags, when the overflow chevron shows for the first time,
- // take that much space away from |button_hbox_| to make the drag look
- // smoother.
- GtkRequisition req;
- gtk_widget_size_request(chevron(), &req);
- gint overflow_width = req.width;
- gtk_widget_size_request(button_hbox_.get(), &req);
- gint button_hbox_width = req.width;
- button_hbox_width = std::max(button_hbox_width - overflow_width, 0);
- gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1);
- }
-
- gtk_widget_show(overflow_area_.get());
- }
- } else {
- gtk_widget_hide(overflow_area_.get());
- }
-}
-
-gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget,
- GdkDragContext* drag_context,
- gint x, gint y, guint time) {
- // Only handle drags we initiated.
- if (!drag_button_)
- return FALSE;
-
- if (base::i18n::IsRTL()) {
- GtkAllocation allocation;
- gtk_widget_get_allocation(widget, &allocation);
- x = allocation.width - x;
- }
-
- drop_index_ = x < kButtonWidth ? 0 : x / (kButtonWidth + kButtonPadding);
-
- // We will go ahead and reorder the child in order to provide visual feedback
- // to the user. We don't inform the model that it has moved until the drag
- // ends.
- gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), drag_button_->widget(),
- drop_index_);
-
- gdk_drag_status(drag_context, GDK_ACTION_MOVE, time);
- return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnDragEnd(GtkWidget* button,
- GdkDragContext* drag_context) {
- if (drop_index_ != -1) {
- if (profile_->IsOffTheRecord())
- drop_index_ = model_->IncognitoIndexToOriginal(drop_index_);
-
- model_->MoveBrowserAction(drag_button_->extension(), drop_index_);
- }
-
- drag_button_ = NULL;
- drop_index_ = -1;
-}
-
-gboolean BrowserActionsToolbarGtk::OnDragFailed(GtkWidget* widget,
- GdkDragContext* drag_context,
- GtkDragResult result) {
- // We connect to this signal and return TRUE so that the default failure
- // animation (wherein the drag widget floats back to the start of the drag)
- // does not show, and the drag-end signal is emitted immediately instead of
- // several seconds later.
- return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnHierarchyChanged(
- GtkWidget* widget, GtkWidget* previous_toplevel) {
- GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
- if (!gtk_widget_is_toplevel(toplevel))
- return;
-
- signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this);
-}
-
-void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget,
- GtkWidget* focus_widget) {
- ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup();
- // The focus of the parent window has changed. Close the popup. Delay the hide
- // because it will destroy the RenderViewHost, which may still be on the
- // call stack.
- if (!popup || popup->being_inspected())
- return;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserActionsToolbarGtk::HidePopup,
- weak_factory_.GetWeakPtr()));
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperMotionNotify(
- GtkWidget* widget, GdkEventMotion* event) {
- if (!(event->state & GDK_BUTTON1_MASK))
- return FALSE;
-
- // Calculate how much the user dragged the gripper and subtract that off the
- // button container's width.
- int distance_dragged;
- if (base::i18n::IsRTL()) {
- distance_dragged = -event->x;
- } else {
- GtkAllocation widget_allocation;
- gtk_widget_get_allocation(widget, &widget_allocation);
- distance_dragged = event->x - widget_allocation.width;
- }
-
- GtkAllocation button_hbox_allocation;
- gtk_widget_get_allocation(button_hbox_.get(), &button_hbox_allocation);
- gint new_width = button_hbox_allocation.width - distance_dragged;
- SetButtonHBoxWidth(new_width);
-
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperExpose(GtkWidget* gripper,
- GdkEventExpose* expose) {
- return TRUE;
-}
-
-// These three signal handlers (EnterNotify, LeaveNotify, and ButtonRelease)
-// are used to give the gripper the resize cursor. Since it doesn't have its
-// own window, we have to set the cursor whenever the pointer moves into the
-// button or leaves the button, and be sure to leave it on when the user is
-// dragging.
-gboolean BrowserActionsToolbarGtk::OnGripperEnterNotify(
- GtkWidget* gripper, GdkEventCrossing* event) {
- gdk_window_set_cursor(gtk_widget_get_window(gripper),
- gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW));
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperLeaveNotify(
- GtkWidget* gripper, GdkEventCrossing* event) {
- if (!(event->state & GDK_BUTTON1_MASK))
- gdk_window_set_cursor(gtk_widget_get_window(gripper), NULL);
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperButtonRelease(
- GtkWidget* gripper, GdkEventButton* event) {
- GtkAllocation allocation;
- gtk_widget_get_allocation(gripper, &allocation);
- gfx::Rect gripper_rect(0, 0, allocation.width, allocation.height);
-
- gfx::Point release_point(event->x, event->y);
- if (!gripper_rect.Contains(release_point))
- gdk_window_set_cursor(gtk_widget_get_window(gripper), NULL);
-
- // After the user resizes the toolbar, we want to smartly resize it to be
- // the perfect size to fit the buttons.
- int visible_icon_count =
- gtk_chrome_shrinkable_hbox_get_visible_child_count(
- GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
- AnimateToShowNIcons(visible_icon_count);
- model_->SetVisibleIconCount(visible_icon_count);
-
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnGripperButtonPress(
- GtkWidget* gripper, GdkEventButton* event) {
- resize_animation_.Reset();
-
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress(
- GtkWidget* overflow, GdkEventButton* event) {
- overflow_menu_model_.reset(new SimpleMenuModel(this));
-
- int visible_icon_count =
- gtk_chrome_shrinkable_hbox_get_visible_child_count(
- GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
- for (int i = visible_icon_count; i < button_count(); ++i) {
- int model_index = i;
- if (profile_->IsOffTheRecord())
- model_index = model_->IncognitoIndexToOriginal(i);
-
- const Extension* extension = model_->toolbar_items()[model_index].get();
- BrowserActionButton* button = extension_button_map_[extension->id()].get();
-
- overflow_menu_model_->AddItem(model_index,
- base::UTF8ToUTF16(extension->name()));
- overflow_menu_model_->SetIcon(overflow_menu_model_->GetItemCount() - 1,
- button->GetIcon());
-
- // TODO(estade): set the menu item's tooltip.
- }
-
- overflow_menu_.reset(new MenuGtk(this, overflow_menu_model_.get()));
- signals_.Connect(overflow_menu_->widget(), "button-press-event",
- G_CALLBACK(OnOverflowMenuButtonPressThunk), this);
-
- overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE);
- overflow_menu_->PopupAsFromKeyEvent(chevron());
-
- return FALSE;
-}
-
-gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress(
- GtkWidget* overflow, GdkEventButton* event) {
- if (event->button != 3)
- return FALSE;
-
- GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item;
- if (!menu_item)
- return FALSE;
-
- int item_index = g_list_index(GTK_MENU_SHELL(overflow)->children, menu_item);
- if (item_index == -1) {
- NOTREACHED();
- return FALSE;
- }
-
- item_index += gtk_chrome_shrinkable_hbox_get_visible_child_count(
- GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()));
- if (profile_->IsOffTheRecord())
- item_index = model_->IncognitoIndexToOriginal(item_index);
-
- const Extension* extension = model_->toolbar_items()[item_index].get();
- BrowserActionButton* button = GetBrowserActionButton(extension);
- if (button == NULL) {
- NOTREACHED();
- return FALSE;
- }
-
- MenuGtk* menu = button->GetContextMenu();
- if (!menu)
- return FALSE;
-
- menu->PopupAsContext(gfx::Point(event->x_root, event->y_root),
- event->time);
- return TRUE;
-}
-
-void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) {
- if (!resize_animation_.is_animating())
- UpdateChevronVisibility();
-}

Powered by Google App Engine
This is Rietveld 408576698