diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-04 00:12:48 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-04 00:12:48 +0000 |
commit | 27538b19124450f43392a965bb080817469f643c (patch) | |
tree | 5e5475a44d4b7051812f6d1cfe65c5b36c8b3846 /chrome/browser/gtk | |
parent | 2c1f5f7d9cc0b21a08fa876dc2bcc5f28b5428c6 (diff) | |
download | chromium_src-27538b19124450f43392a965bb080817469f643c.zip chromium_src-27538b19124450f43392a965bb080817469f643c.tar.gz chromium_src-27538b19124450f43392a965bb080817469f643c.tar.bz2 |
[GTK] More m6 toolbar fixes.
- make wrench menu a custom button rather than gtk_chrome_button (changes appearance slightly)
- correct sizing/spacing of wrench menu
- new overflow chevron graphic (also a CustomDrawButton converted from a gtk_chrome_button)
- fix things I broke when I was hastily fixing the build earlier
BUG=50682
TEST=visual
Review URL: http://codereview.chromium.org/3053038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54850 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk')
-rw-r--r-- | chrome/browser/gtk/browser_actions_toolbar_gtk.cc | 145 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_actions_toolbar_gtk.h | 25 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.cc | 101 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.h | 18 | ||||
-rw-r--r-- | chrome/browser/gtk/custom_button.cc | 82 | ||||
-rw-r--r-- | chrome/browser/gtk/custom_button.h | 37 | ||||
-rw-r--r-- | chrome/browser/gtk/owned_widget_gtk.cc | 3 |
7 files changed, 231 insertions, 180 deletions
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index 198b0e1..3edb179 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -33,20 +33,19 @@ #include "gfx/canvas_skia_paint.h" #include "gfx/gtk_util.h" #include "grit/app_resources.h" +#include "grit/theme_resources.h" namespace { -// The size of each button on the toolbar. -const int kButtonSize = 29; +// The width of the browser action buttons. +const int kButtonWidth = 27; -// The padding between browser action buttons. Visually, the actual number of -// "empty" (non-drawing) pixels is this value + 2 when adjacent browser icons -// use their maximum allowed size. -const int kButtonPadding = 1; +// The padding between browser action buttons. +const int kButtonPadding = 4; // The padding to the right of the browser action buttons (between the buttons -// and the separator, or chevron if it's showing). -const int kPaddingToRightOfButtons = 5; +// and chevron if they are both showing). +const int kButtonChevronPadding = 2; // The padding to the left, top and bottom of the browser actions toolbar // separator. @@ -69,7 +68,7 @@ GtkTargetEntry GetDragTargetEntry() { // The minimum width in pixels of the button hbox if |icon_count| icons are // showing. gint WidthForIconCount(gint icon_count) { - return std::max((kButtonSize + kButtonPadding) * icon_count - kButtonPadding, + return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding, 0); } @@ -83,20 +82,24 @@ class BrowserActionButton : public NotificationObserver, public MenuGtk::Delegate { public: BrowserActionButton(BrowserActionsToolbarGtk* toolbar, - Extension* extension) + Extension* extension, + GtkThemeProvider* theme_provider) : toolbar_(toolbar), extension_(extension), image_(NULL), tracker_(this), tab_specific_icon_(NULL), default_icon_(NULL) { - button_.Own( - GtkThemeProvider::GetFrom(toolbar->profile_)->BuildChromeButton()); + button_.reset(new CustomDrawButton( + theme_provider, + IDR_BROWSER_ACTION, + IDR_BROWSER_ACTION_P, + IDR_BROWSER_ACTION_H, + 0, + NULL)); DCHECK(extension_->browser_action()); - gtk_widget_set_size_request(button_.get(), kButtonSize, kButtonSize); - UpdateState(); // The Browser Action API does not allow the default icon path to be @@ -109,13 +112,13 @@ class BrowserActionButton : public NotificationObserver, ImageLoadingTracker::DONT_CACHE); } - signals_.Connect(button_.get(), "button-press-event", + signals_.Connect(button_->widget(), "button-press-event", G_CALLBACK(OnButtonPress), this); - signals_.Connect(button_.get(), "clicked", + signals_.Connect(button_->widget(), "clicked", G_CALLBACK(OnClicked), this); - signals_.ConnectAfter(button_.get(), "expose-event", + signals_.ConnectAfter(button_->widget(), "expose-event", G_CALLBACK(OnExposeEvent), this); - signals_.Connect(button_.get(), "drag-begin", + signals_.Connect(button_->widget(), "drag-begin", G_CALLBACK(&OnDragBegin), this); registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, @@ -128,11 +131,9 @@ class BrowserActionButton : public NotificationObserver, if (default_icon_) g_object_unref(default_icon_); - - button_.Destroy(); } - GtkWidget* widget() { return button_.get(); } + GtkWidget* widget() { return button_->widget(); } Extension* extension() { return extension_; } @@ -164,9 +165,9 @@ class BrowserActionButton : public NotificationObserver, std::string tooltip = extension_->browser_action()->GetTitle(tab_id); if (tooltip.empty()) - gtk_widget_set_has_tooltip(button_.get(), FALSE); + gtk_widget_set_has_tooltip(button_->widget(), FALSE); else - gtk_widget_set_tooltip_text(button_.get(), tooltip.c_str()); + gtk_widget_set_tooltip_text(button_->widget(), tooltip.c_str()); SkBitmap image = extension_->browser_action()->GetIcon(tab_id); if (!image.isNull()) { @@ -178,7 +179,7 @@ class BrowserActionButton : public NotificationObserver, } else if (default_icon_) { SetImage(default_icon_); } - gtk_widget_queue_draw(button_.get()); + gtk_widget_queue_draw(button_->widget()); } SkBitmap GetIcon() { @@ -202,7 +203,7 @@ class BrowserActionButton : public NotificationObserver, private: // MenuGtk::Delegate implementation. virtual void StoppedShowing() { - gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(button_.get())); + button_->UnsetPaintOverride(); // If the context menu was showing for the overflow menu, re-assert the // grab that was shadowed. @@ -246,7 +247,7 @@ class BrowserActionButton : public NotificationObserver, void SetImage(GdkPixbuf* image) { if (!image_) { image_ = gtk_image_new_from_pixbuf(image); - gtk_button_set_image(GTK_BUTTON(button_.get()), image_); + gtk_button_set_image(GTK_BUTTON(button_->widget()), image_); } else { gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image); } @@ -258,8 +259,7 @@ class BrowserActionButton : public NotificationObserver, if (event->button.button != 3) return FALSE; - gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(action->button_.get()), - GTK_STATE_PRELIGHT); + action->button_->SetPaintOverride(GTK_STATE_ACTIVE); action->GetContextMenu()->Popup(widget, event); return TRUE; @@ -306,8 +306,8 @@ class BrowserActionButton : public NotificationObserver, // The extension that contains this browser action. Extension* extension_; - // The gtk widget for this browser action. - OwnedWidgetGtk button_; + // The button for this browser action. + scoped_ptr<CustomDrawButton> button_; // 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 @@ -346,8 +346,6 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) model_(NULL), hbox_(gtk_hbox_new(FALSE, 0)), button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)), - overflow_button_(browser->profile()), - separator_(theme_provider_->CreateToolbarSeparator()), drag_button_(NULL), drop_index_(-1), resize_animation_(this), @@ -359,6 +357,14 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) if (!extension_service) return; + overflow_button_.reset(new CustomDrawButton( + theme_provider_, + 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_UNSET_FLAGS(gripper, GTK_CAN_FOCUS); @@ -375,19 +381,31 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) G_CALLBACK(OnGripperButtonReleaseThunk), this); signals_.Connect(gripper, "button-press-event", G_CALLBACK(OnGripperButtonPressThunk), this); - signals_.Connect(overflow_button_.widget(), "button-press-event", + signals_.Connect(overflow_button_->widget(), "button-press-event", G_CALLBACK(OnOverflowButtonPressThunk), this); - overflow_spacer_ = gtk_alignment_new(0, 0, 1, 1); - gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_spacer_), 0, 0, - kPaddingToRightOfButtons, 0); - gtk_container_add(GTK_CONTAINER(overflow_spacer_), overflow_button_.widget()); - gtk_widget_show(overflow_button_.widget()); + // |overflow_alignment| adds padding to the right of the browser action + // buttons, but only appears when the overflow menu is showing. + overflow_alignment_ = gtk_alignment_new(0, 0, 1, 1); + gtk_container_add(GTK_CONTAINER(overflow_alignment_), + overflow_button_->widget()); + + // |overflow_area_| holds the overflow chevron and the separator, which + // is only shown in GTK+ theme mode. + overflow_area_ = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(overflow_area_), overflow_alignment_, + FALSE, FALSE, 0); + + separator_ = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(overflow_area_), separator_, + FALSE, FALSE, 0); + gtk_widget_set_no_show_all(separator_, TRUE); + + gtk_widget_show_all(overflow_area_); 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_spacer_, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox_.get()), separator_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_, FALSE, FALSE, 0); model_ = extension_service->toolbar_model(); model_->AddObserver(this); @@ -404,6 +422,11 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) G_CALLBACK(OnHierarchyChangedThunk), this); ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); + + registrar_.Add(this, + NotificationType::BROWSER_THEME_CHANGED, + NotificationService::AllSources()); + theme_provider_->InitThemesFor(this); } BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { @@ -428,6 +451,16 @@ void BrowserActionsToolbarGtk::Update() { } } +void BrowserActionsToolbarGtk::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(NotificationType::BROWSER_THEME_CHANGED == type); + if (theme_provider_->UseGtkTheme()) + gtk_widget_show(separator_); + else + gtk_widget_hide(separator_); +} + void BrowserActionsToolbarGtk::SetupDrags() { GtkTargetEntry drag_target = GetDragTargetEntry(); gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, @@ -463,7 +496,7 @@ void BrowserActionsToolbarGtk::CreateButtonForExtension(Extension* extension, RemoveButtonForExtension(extension); linked_ptr<BrowserActionButton> button( - new BrowserActionButton(this, extension)); + new BrowserActionButton(this, extension, theme_provider_)); 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); @@ -544,7 +577,7 @@ void BrowserActionsToolbarGtk::BrowserActionAdded(Extension* extension, return; // Animate the addition if we are showing all browser action buttons. - if (!GTK_WIDGET_VISIBLE(overflow_spacer_)) { + if (!GTK_WIDGET_VISIBLE(overflow_area_)) { AnimateToShowNIcons(button_count()); model_->SetVisibleIconCount(button_count()); } @@ -560,7 +593,7 @@ void BrowserActionsToolbarGtk::BrowserActionRemoved(Extension* extension) { RemoveButtonForExtension(extension); - if (!GTK_WIDGET_VISIBLE(overflow_spacer_)) { + if (!GTK_WIDGET_VISIBLE(overflow_area_)) { AnimateToShowNIcons(button_count()); model_->SetVisibleIconCount(button_count()); } @@ -616,7 +649,7 @@ void BrowserActionsToolbarGtk::ExecuteCommand(int command_id) { if (browser_action->HasPopup(tab_id)) { ExtensionPopupGtk::Show( browser_action->GetPopupUrl(tab_id), browser(), - overflow_button_.widget(), + overflow_button_->widget(), false); } else { ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( @@ -625,8 +658,7 @@ void BrowserActionsToolbarGtk::ExecuteCommand(int command_id) { } void BrowserActionsToolbarGtk::StoppedShowing() { - gtk_chrome_button_unset_paint_state( - GTK_CHROME_BUTTON(overflow_button_.widget())); + overflow_button_->UnsetPaintOverride(); } void BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button, @@ -651,15 +683,21 @@ 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_), 0, 0, 0, 0); + } else { + gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_), 0, 0, + kButtonChevronPadding, 0); + } if (button_count() > showing_icon_count) { - if (!GTK_WIDGET_VISIBLE(overflow_spacer_)) { + if (!GTK_WIDGET_VISIBLE(overflow_area_)) { 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(overflow_spacer_, &req); + gtk_widget_size_request(overflow_button_->widget(), &req); gint overflow_width = req.width; gtk_widget_size_request(button_hbox_.get(), &req); gint button_hbox_width = req.width; @@ -667,10 +705,10 @@ void BrowserActionsToolbarGtk::UpdateChevronVisibility() { gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1); } - gtk_widget_show(overflow_spacer_); + gtk_widget_show(overflow_area_); } } else { - gtk_widget_hide(overflow_spacer_); + gtk_widget_hide(overflow_area_); } } @@ -683,7 +721,7 @@ gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget, if (base::i18n::IsRTL()) x = widget->allocation.width - x; - drop_index_ = x < kButtonSize ? 0 : x / (kButtonSize + kButtonPadding); + 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 @@ -831,9 +869,8 @@ gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress( signals_.Connect(overflow_menu_->widget(), "button-press-event", G_CALLBACK(OnOverflowMenuButtonPressThunk), this); - gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(overflow), - GTK_STATE_ACTIVE); - overflow_menu_->PopupAsFromKeyEvent(overflow); + overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE); + overflow_menu_->PopupAsFromKeyEvent(overflow_button_->widget()); return FALSE; } diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/gtk/browser_actions_toolbar_gtk.h index 9d2e44d..672e9c3 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -16,6 +16,7 @@ #include "base/linked_ptr.h" #include "base/task.h" #include "chrome/browser/extensions/extension_toolbar_model.h" +#include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/gtk/overflow_button.h" #include "chrome/browser/gtk/owned_widget_gtk.h" @@ -34,7 +35,8 @@ typedef struct _GtkWidget GtkWidget; class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer, public AnimationDelegate, public MenuGtk::Delegate, - public menus::SimpleMenuModel::Delegate { + public menus::SimpleMenuModel::Delegate, + public NotificationObserver { public: explicit BrowserActionsToolbarGtk(Browser* browser); virtual ~BrowserActionsToolbarGtk(); @@ -56,6 +58,11 @@ class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer, // Update the display of all buttons. void Update(); + // NotificationObserver implementation. + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: friend class BrowserActionButton; @@ -169,14 +176,16 @@ class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer, // Contains the browser action buttons. OwnedWidgetGtk button_hbox_; - OverflowButton overflow_button_; + // The overflow button for chrome theme mode. + scoped_ptr<CustomDrawButton> overflow_button_; + // The separator just next to the overflow button. Only shown in GTK+ theme + // mode. In Chrome theme mode, the overflow button has a separator built in. + GtkWidget* separator_; scoped_ptr<MenuGtk> overflow_menu_; scoped_ptr<menus::SimpleMenuModel> overflow_menu_model_; + GtkWidget* overflow_area_; // A widget for adding extra padding to the left of the overflow button. - GtkWidget* overflow_spacer_; - - // The vertical separator between the overflow button and the page/app menus. - GtkWidget* separator_; + GtkWidget* overflow_alignment_; // The button that is currently being dragged, or NULL. BrowserActionButton* drag_button_; @@ -200,6 +209,8 @@ class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer, GtkSignalRegistrar signals_; + NotificationRegistrar registrar_; + ScopedRunnableMethodFactory<BrowserActionsToolbarGtk> method_factory_; DISALLOW_COPY_AND_ASSIGN(BrowserActionsToolbarGtk); diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index b56a65b..d89e747 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -124,9 +124,8 @@ BrowserToolbarGtk::~BrowserToolbarGtk() { offscreen_entry_.Destroy(); - app_menu_.reset(); - app_menu_button_.Destroy(); - app_menu_image_.Destroy(); + wrench_menu_.reset(); + wrench_menu_image_.Destroy(); } void BrowserToolbarGtk::Init(Profile* profile, @@ -175,8 +174,7 @@ void BrowserToolbarGtk::Init(Profile* profile, 0); home_.reset(new CustomDrawButton(GtkThemeProvider::GetFrom(profile_), - IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0, GTK_STOCK_HOME, - GTK_ICON_SIZE_SMALL_TOOLBAR)); + IDR_HOME, IDR_HOME_P, IDR_HOME_H, 0, NULL)); gtk_widget_set_tooltip_text(home_->widget(), l10n_util::GetStringUTF8(IDS_TOOLTIP_HOME).c_str()); g_signal_connect(home_->widget(), "clicked", @@ -198,35 +196,34 @@ void BrowserToolbarGtk::Init(Profile* profile, gtk_box_pack_start(GTK_BOX(toolbar_), location_hbox_, TRUE, TRUE, ShouldOnlyShowLocation() ? 1 : 0); - toolbar_right_ = gtk_hbox_new(FALSE, 0); - if (!ShouldOnlyShowLocation()) { actions_toolbar_.reset(new BrowserActionsToolbarGtk(browser_)); - gtk_box_pack_start(GTK_BOX(toolbar_right_), actions_toolbar_->widget(), + gtk_box_pack_start(GTK_BOX(toolbar_), actions_toolbar_->widget(), FALSE, FALSE, 0); } - // We need another hbox for the menu buttons so we can place them together, - // but still have some padding to their collective left/right. - GtkWidget* menus_hbox = gtk_hbox_new(FALSE, 0); - GtkWidget* chrome_menu = BuildToolbarMenuButton( + wrench_menu_button_.reset(new CustomDrawButton( + GtkThemeProvider::GetFrom(profile_), + IDR_TOOLS, IDR_TOOLS_P, IDR_TOOLS_H, 0, + gtk_image_new_from_pixbuf( + theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS)))); + GtkWidget* wrench_button = wrench_menu_button_->widget(); + + gtk_widget_set_tooltip_text( + wrench_button, l10n_util::GetStringFUTF8(IDS_APPMENU_TOOLTIP, - WideToUTF16(l10n_util::GetString(IDS_PRODUCT_NAME))), - &app_menu_button_); - app_menu_image_.Own(gtk_image_new_from_pixbuf( - theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS))); - gtk_container_add(GTK_CONTAINER(chrome_menu), app_menu_image_.get()); - g_signal_connect_after(app_menu_image_.get(), "expose-event", - G_CALLBACK(OnAppMenuImageExposeThunk), this); - - app_menu_.reset(new MenuGtk(this, &wrench_menu_model_)); - gtk_box_pack_start(GTK_BOX(menus_hbox), chrome_menu, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(toolbar_right_), menus_hbox, FALSE, FALSE, - kToolbarWidgetSpacing); - g_signal_connect(app_menu_->widget(), "show", - G_CALLBACK(OnAppMenuShowThunk), this); + WideToUTF16(l10n_util::GetString(IDS_PRODUCT_NAME))).c_str()); + g_signal_connect(wrench_button, "button-press-event", + G_CALLBACK(OnMenuButtonPressEventThunk), this); + GTK_WIDGET_UNSET_FLAGS(wrench_button, GTK_CAN_FOCUS); + g_signal_connect_after(wrench_button, "expose-event", + G_CALLBACK(OnWrenchMenuImageExposeThunk), this); + gtk_box_pack_start(GTK_BOX(toolbar_), wrench_menu_button_->widget(), + FALSE, FALSE, 4); - gtk_box_pack_start(GTK_BOX(toolbar_), toolbar_right_, FALSE, FALSE, 0); + wrench_menu_.reset(new MenuGtk(this, &wrench_menu_model_)); + g_signal_connect(wrench_menu_->widget(), "show", + G_CALLBACK(OnWrenchMenuShowThunk), this); if (ShouldOnlyShowLocation()) { gtk_widget_show(event_box_); @@ -257,7 +254,7 @@ void BrowserToolbarGtk::SetViewIDs() { ViewIDUtil::SetID(reload_->widget(), VIEW_ID_RELOAD_BUTTON); ViewIDUtil::SetID(home_->widget(), VIEW_ID_HOME_BUTTON); ViewIDUtil::SetID(location_bar_->widget(), VIEW_ID_LOCATION_BAR); - ViewIDUtil::SetID(app_menu_button_.get(), VIEW_ID_APP_MENU); + ViewIDUtil::SetID(wrench_menu_button_->widget(), VIEW_ID_APP_MENU); } void BrowserToolbarGtk::Show() { @@ -281,10 +278,9 @@ void BrowserToolbarGtk::UpdateForBookmarkBarVisibility( } void BrowserToolbarGtk::ShowAppMenu() { - app_menu_->Cancel(); - gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(app_menu_button_.get()), - GTK_STATE_ACTIVE); - app_menu_->PopupAsFromKeyEvent(app_menu_button_.get()); + wrench_menu_->Cancel(); + wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE); + wrench_menu_->PopupAsFromKeyEvent(wrench_menu_button_->widget()); } // CommandUpdater::CommandObserver --------------------------------------------- @@ -321,9 +317,8 @@ void BrowserToolbarGtk::StoppedShowing() { // Without these calls, the hover state can get stuck since the leave-notify // event is not sent when clicking a button brings up the menu. gtk_chrome_button_set_hover_state( - GTK_CHROME_BUTTON(app_menu_button_.get()), 0.0); - gtk_chrome_button_unset_paint_state( - GTK_CHROME_BUTTON(app_menu_button_.get())); + GTK_CHROME_BUTTON(wrench_menu_button_->widget()), 0.0); + wrench_menu_button_->UnsetPaintOverride(); } GtkIconSet* BrowserToolbarGtk::GetIconSetForId(int idr) { @@ -380,11 +375,7 @@ void BrowserToolbarGtk::Observe(NotificationType type, bool use_gtk = theme_provider_->UseGtkTheme(); int border = use_gtk ? 0 : 2; gtk_container_set_border_width( - GTK_CONTAINER(app_menu_button_.get()), border); - - // Update the menu button image. - gtk_image_set_from_pixbuf(GTK_IMAGE(app_menu_image_.get()), - theme_provider_->GetRTLEnabledPixbufNamed(IDR_TOOLS)); + GTK_CONTAINER(wrench_menu_button_->widget()), border); // Force the height of the toolbar so we get the right amount of padding // above and below the location bar. We always force the size of the hboxes @@ -394,7 +385,6 @@ void BrowserToolbarGtk::Observe(NotificationType type, int toolbar_height = ShouldOnlyShowLocation() ? kToolbarHeightLocationBarOnly : kToolbarHeight; gtk_widget_set_size_request(toolbar_left_, -1, toolbar_height); - gtk_widget_set_size_request(toolbar_right_, -1, toolbar_height); gtk_widget_set_size_request(location_hbox_, -1, use_gtk ? -1 : toolbar_height); @@ -431,20 +421,6 @@ void BrowserToolbarGtk::UpdateTabContents(TabContents* contents, // BrowserToolbarGtk, private -------------------------------------------------- -GtkWidget* BrowserToolbarGtk::BuildToolbarMenuButton( - const std::string& localized_tooltip, - OwnedWidgetGtk* owner) { - GtkWidget* button = theme_provider_->BuildChromeButton(); - owner->Own(button); - - gtk_widget_set_tooltip_text(button, localized_tooltip.c_str()); - g_signal_connect(button, "button-press-event", - G_CALLBACK(OnMenuButtonPressEventThunk), this); - GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS); - - return button; -} - void BrowserToolbarGtk::SetUpDragForHomeButton(bool enable) { if (enable) { gtk_drag_dest_set(home_->widget(), GTK_DEST_DEFAULT_ALL, @@ -618,9 +594,8 @@ gboolean BrowserToolbarGtk::OnMenuButtonPressEvent(GtkWidget* button, if (event->button != 1) return FALSE; - gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(button), - GTK_STATE_ACTIVE); - app_menu_->Popup(button, reinterpret_cast<GdkEvent*>(event)); + wrench_menu_button_->SetPaintOverride(GTK_STATE_ACTIVE); + wrench_menu_->Popup(button, reinterpret_cast<GdkEvent*>(event)); return TRUE; } @@ -677,13 +652,13 @@ bool BrowserToolbarGtk::ShouldOnlyShowLocation() const { void BrowserToolbarGtk::AnimationEnded(const Animation* animation) { DCHECK_EQ(animation, &upgrade_reminder_animation_); - gtk_widget_queue_draw(app_menu_image_.get()); + gtk_widget_queue_draw(wrench_menu_image_.get()); } void BrowserToolbarGtk::AnimationProgressed(const Animation* animation) { DCHECK_EQ(animation, &upgrade_reminder_animation_); if (UpgradeAnimationIsFaded()) - gtk_widget_queue_draw(app_menu_image_.get()); + gtk_widget_queue_draw(wrench_menu_image_.get()); } void BrowserToolbarGtk::AnimationCanceled(const Animation* animation) { @@ -694,15 +669,15 @@ void BrowserToolbarGtk::ActiveWindowChanged(GdkWindow* active_window) { MaybeShowUpgradeReminder(); } -void BrowserToolbarGtk::OnAppMenuShow(GtkWidget* sender) { +void BrowserToolbarGtk::OnWrenchMenuShow(GtkWidget* sender) { if (upgrade_reminder_animation_.is_animating()) { upgrade_reminder_canceled_ = true; MaybeShowUpgradeReminder(); } } -gboolean BrowserToolbarGtk::OnAppMenuImageExpose(GtkWidget* sender, - GdkEventExpose* expose) { +gboolean BrowserToolbarGtk::OnWrenchMenuImageExpose(GtkWidget* sender, + GdkEventExpose* expose) { if (!Singleton<UpgradeDetector>::get()->notify_upgrade()) return FALSE; diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index 29dd47b..b0ade49 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -73,7 +73,7 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, ReloadButtonGtk* GetReloadButton() { return reload_.get(); } - GtkWidget* GetAppMenuButton() { return app_menu_button_.get(); } + GtkWidget* GetAppMenuButton() { return wrench_menu_button_->widget(); } BrowserActionsToolbarGtk* GetBrowserActionsToolbar() { return actions_toolbar_.get(); @@ -121,11 +121,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, virtual void ActiveWindowChanged(GdkWindow* active_window); private: - // Create a menu for the toolbar given the icon id and tooltip. Returns the - // widget created. - GtkWidget* BuildToolbarMenuButton(const std::string& localized_tooltip, - OwnedWidgetGtk* owner); - // Connect/Disconnect signals for dragging a url onto the home button. void SetUpDragForHomeButton(bool enable); @@ -158,10 +153,10 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, guint, guint); // Used to stop the upgrade notification animation. - CHROMEGTK_CALLBACK_0(BrowserToolbarGtk, void, OnAppMenuShow); + CHROMEGTK_CALLBACK_0(BrowserToolbarGtk, void, OnWrenchMenuShow); // Used to draw the upgrade notification badge. - CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnAppMenuImageExpose, + CHROMEGTK_CALLBACK_1(BrowserToolbarGtk, gboolean, OnWrenchMenuImageExpose, GdkEventExpose*); // Updates preference-dependent state. @@ -195,7 +190,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, // set their minimum sizes independently of |location_hbox_| which needs to // grow/shrink in GTK+ mode. GtkWidget* toolbar_left_; - GtkWidget* toolbar_right_; // Contains all the widgets of the location bar. GtkWidget* location_hbox_; @@ -208,18 +202,18 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, scoped_ptr<CustomDrawButton> home_; scoped_ptr<ReloadButtonGtk> reload_; scoped_ptr<BrowserActionsToolbarGtk> actions_toolbar_; - OwnedWidgetGtk app_menu_button_; + scoped_ptr<CustomDrawButton> wrench_menu_button_; // Keep a pointer to the menu button image because we change it when the theme // changes. - OwnedWidgetGtk app_menu_image_; + OwnedWidgetGtk wrench_menu_image_; // The model that contains the security level, text, icon to display... ToolbarModel* model_; GtkThemeProvider* theme_provider_; - scoped_ptr<MenuGtk> app_menu_; + scoped_ptr<MenuGtk> wrench_menu_; WrenchMenuModel wrench_menu_model_; diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc index 603b6a7..08cd54d 100644 --- a/chrome/browser/gtk/custom_button.cc +++ b/chrome/browser/gtk/custom_button.cc @@ -117,6 +117,10 @@ gboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget, cairo_destroy(cairo_context); + GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget)); + if (child) + gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e); + return TRUE; } @@ -182,9 +186,9 @@ void CustomDrawHoverController::Init(GtkWidget* widget) { DCHECK(widget_ == NULL); widget_ = widget; g_signal_connect(widget_, "enter-notify-event", - G_CALLBACK(OnEnter), this); + G_CALLBACK(OnEnterThunk), this); g_signal_connect(widget_, "leave-notify-event", - G_CALLBACK(OnLeave), this); + G_CALLBACK(OnLeaveThunk), this); } void CustomDrawHoverController::AnimationProgressed( @@ -192,25 +196,21 @@ void CustomDrawHoverController::AnimationProgressed( gtk_widget_queue_draw(widget_); } -// static gboolean CustomDrawHoverController::OnEnter( GtkWidget* widget, - GdkEventCrossing* event, - CustomDrawHoverController* controller) { - controller->slide_animation_.Show(); + GdkEventCrossing* event) { + slide_animation_.Show(); return FALSE; } -// static gboolean CustomDrawHoverController::OnLeave( GtkWidget* widget, - GdkEventCrossing* event, - CustomDrawHoverController* controller) { + GdkEventCrossing* event) { // When the user is holding a mouse button, we don't want to animate. if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) - controller->slide_animation_.Reset(); + slide_animation_.Reset(); else - controller->slide_animation_.Hide(); + slide_animation_.Hide(); return FALSE; } @@ -221,9 +221,7 @@ CustomDrawButton::CustomDrawButton(int normal_id, int hover_id, int disabled_id) : button_base_(NULL, normal_id, pressed_id, hover_id, disabled_id), - theme_provider_(NULL), - gtk_stock_name_(NULL), - icon_size_(GTK_ICON_SIZE_INVALID) { + theme_provider_(NULL) { Init(); // Initialize the theme stuff with no theme_provider. @@ -239,9 +237,27 @@ CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider, GtkIconSize stock_size) : button_base_(theme_provider, normal_id, pressed_id, hover_id, disabled_id), - theme_provider_(theme_provider), - gtk_stock_name_(stock_id), - icon_size_(stock_size) { + theme_provider_(theme_provider) { + native_widget_.Own(gtk_image_new_from_stock(stock_id, stock_size)); + + Init(); + + theme_provider_->InitThemesFor(this); + registrar_.Add(this, + NotificationType::BROWSER_THEME_CHANGED, + NotificationService::AllSources()); +} + +CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider, + int normal_id, + int pressed_id, + int hover_id, + int disabled_id, + GtkWidget* native_widget) + : button_base_(theme_provider, normal_id, pressed_id, hover_id, + disabled_id), + native_widget_(native_widget), + theme_provider_(theme_provider) { Init(); theme_provider_->InitThemesFor(this); @@ -252,13 +268,14 @@ CustomDrawButton::CustomDrawButton(GtkThemeProvider* theme_provider, CustomDrawButton::~CustomDrawButton() { widget_.Destroy(); + native_widget_.Destroy(); } void CustomDrawButton::Init() { widget_.Own(gtk_chrome_button_new()); GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS); g_signal_connect(widget(), "expose-event", - G_CALLBACK(OnCustomExpose), this); + G_CALLBACK(OnCustomExposeThunk), this); hover_controller_.Init(widget()); } @@ -285,16 +302,14 @@ void CustomDrawButton::SetBackground(SkColor color, button_base_.SetBackground(color, image, mask); } -// static -gboolean CustomDrawButton::OnCustomExpose(GtkWidget* widget, - GdkEventExpose* e, - CustomDrawButton* button) { - if (button->theme_provider_ && button->theme_provider_->UseGtkTheme()) { +gboolean CustomDrawButton::OnCustomExpose(GtkWidget* sender, + GdkEventExpose* e) { + if (UseGtkTheme()) { // Continue processing this expose event. return FALSE; } else { - double hover_state = button->hover_controller_.GetCurrentValue(); - return button->button_base_.OnExpose(widget, e, hover_state); + double hover_state = hover_controller_.GetCurrentValue(); + return button_base_.OnExpose(sender, e, hover_state); } } @@ -307,15 +322,14 @@ CustomDrawButton* CustomDrawButton::CloseButton( } void CustomDrawButton::SetBrowserTheme() { - bool use_gtk = theme_provider_ && theme_provider_->UseGtkTheme(); - - if (use_gtk && gtk_stock_name_) { - gtk_button_set_image( - GTK_BUTTON(widget()), - gtk_image_new_from_stock(gtk_stock_name_, icon_size_)); + if (UseGtkTheme()) { + if (native_widget_.get()) + gtk_button_set_image(GTK_BUTTON(widget()), native_widget_.get()); gtk_widget_set_size_request(widget(), -1, -1); gtk_widget_set_app_paintable(widget(), FALSE); } else { + if (native_widget_.get()) + gtk_button_set_image(GTK_BUTTON(widget()), NULL); gtk_widget_set_size_request(widget(), button_base_.Width(), button_base_.Height()); @@ -323,5 +337,9 @@ void CustomDrawButton::SetBrowserTheme() { } gtk_chrome_button_set_use_gtk_rendering( - GTK_CHROME_BUTTON(widget()), use_gtk); + GTK_CHROME_BUTTON(widget()), UseGtkTheme()); +} + +bool CustomDrawButton::UseGtkTheme() { + return theme_provider_ && theme_provider_->UseGtkTheme(); } diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h index 5cb38cb..387a6e2 100644 --- a/chrome/browser/gtk/custom_button.h +++ b/chrome/browser/gtk/custom_button.h @@ -10,6 +10,7 @@ #include <string> +#include "app/gtk_signal.h" #include "app/slide_animation.h" #include "base/scoped_ptr.h" #include "chrome/browser/gtk/owned_widget_gtk.h" @@ -114,10 +115,10 @@ class CustomDrawHoverController : public AnimationDelegate { private: virtual void AnimationProgressed(const Animation* animation); - static gboolean OnEnter(GtkWidget* widget, GdkEventCrossing* event, - CustomDrawHoverController* controller); - static gboolean OnLeave(GtkWidget* widget, GdkEventCrossing* event, - CustomDrawHoverController* controller); + CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnEnter, + GdkEventCrossing*); + CHROMEGTK_CALLBACK_1(CustomDrawHoverController, gboolean, OnLeave, + GdkEventCrossing*); SlideAnimation slide_animation_; GtkWidget* widget_; @@ -135,7 +136,8 @@ class CustomDrawButton : public NotificationObserver { int hover_id, int disabled_id); - // Same as above, but uses themed (and possibly tinted) images. + // Same as above, but uses themed (and possibly tinted) images. |stock_id| and + // |stock_size| are used for GTK+ theme mode. CustomDrawButton(GtkThemeProvider* theme_provider, int normal_id, int pressed_id, @@ -144,6 +146,15 @@ class CustomDrawButton : public NotificationObserver { const char* stock_id, GtkIconSize stock_size); + // As above, but uses an arbitrary GtkImage rather than a stock icon. This + // constructor takes ownership of |native_widget|. + CustomDrawButton(GtkThemeProvider* theme_provider, + int normal_id, + int pressed_id, + int hover_id, + int disabled_id, + GtkWidget* native_widget); + ~CustomDrawButton(); void Init(); @@ -187,10 +198,13 @@ class CustomDrawButton : public NotificationObserver { // Sets the button to themed or not. void SetBrowserTheme(); + // Whether to use the GTK+ theme. For this to be true, we have to be in GTK+ + // theme mode and we must have a valid stock icon resource. + bool UseGtkTheme(); + // Callback for custom button expose, used to draw the custom graphics. - static gboolean OnCustomExpose(GtkWidget* widget, - GdkEventExpose* e, - CustomDrawButton* obj); + CHROMEGTK_CALLBACK_1(CustomDrawButton, gboolean, OnCustomExpose, + GdkEventExpose*); // The actual button widget. OwnedWidgetGtk widget_; @@ -199,13 +213,12 @@ class CustomDrawButton : public NotificationObserver { CustomDrawHoverController hover_controller_; + // The widget to use when we are displaying in GTK+ theme mode. + OwnedWidgetGtk native_widget_; + // Our theme provider. GtkThemeProvider* theme_provider_; - // The stock icon name and size. - const char* gtk_stock_name_; - GtkIconSize icon_size_; - // Used to listen for theme change notifications. NotificationRegistrar registrar_; diff --git a/chrome/browser/gtk/owned_widget_gtk.cc b/chrome/browser/gtk/owned_widget_gtk.cc index db3bd30..2315371 100644 --- a/chrome/browser/gtk/owned_widget_gtk.cc +++ b/chrome/browser/gtk/owned_widget_gtk.cc @@ -13,6 +13,9 @@ OwnedWidgetGtk::~OwnedWidgetGtk() { } void OwnedWidgetGtk::Own(GtkWidget* widget) { + if (!widget) + return; + DCHECK(!widget_); // We want to make sure that Own() was called properly, right after the // widget was created. There should be a floating reference. |