diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 22:16:33 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-30 22:16:33 +0000 |
commit | 6dce30b06f8f099a7e2a753126dab23f0c02c874 (patch) | |
tree | 7a42079c12f906ceaaa54606b2ad209944409869 | |
parent | 00d272fd44bc771e0d35de57a0deae6f8fc78296 (diff) | |
download | chromium_src-6dce30b06f8f099a7e2a753126dab23f0c02c874.zip chromium_src-6dce30b06f8f099a7e2a753126dab23f0c02c874.tar.gz chromium_src-6dce30b06f8f099a7e2a753126dab23f0c02c874.tar.bz2 |
GTK: Implement popup favicon menu.
BUG=18181
Review URL: http://codereview.chromium.org/244029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27666 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/browser_titlebar.cc | 148 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_titlebar.h | 10 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.cc | 30 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.h | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/standard_menus.cc | 27 | ||||
-rw-r--r-- | chrome/browser/gtk/standard_menus.h | 7 |
6 files changed, 154 insertions, 69 deletions
diff --git a/chrome/browser/gtk/browser_titlebar.cc b/chrome/browser/gtk/browser_titlebar.cc index 705b4f1..a78954d 100644 --- a/chrome/browser/gtk/browser_titlebar.cc +++ b/chrome/browser/gtk/browser_titlebar.cc @@ -16,6 +16,7 @@ #include "base/gfx/gtk_util.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser.h" +#include "chrome/browser/encoding_menu_controller.h" #include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/gtk_theme_provider.h" @@ -121,6 +122,59 @@ GdkColor PickLuminosityContrastingColor(const GdkColor* base, return *one; } +MenuCreateMaterial g_favicon_menu[] = { + { MENU_NORMAL, IDC_BACK, IDS_CONTENT_CONTEXT_BACK, 0, NULL, + GDK_Left, GDK_MOD1_MASK, true }, + { MENU_NORMAL, IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD, 0, NULL, + GDK_Right, GDK_MOD1_MASK, true }, + { MENU_NORMAL, IDC_RELOAD, IDS_APP_MENU_RELOAD, 0, NULL, + GDK_R, GDK_CONTROL_MASK, true }, + { MENU_SEPARATOR }, + { MENU_NORMAL, IDC_RESTORE_TAB, IDS_APP_MENU_RELOAD, 0, NULL, + GDK_T, GDK_CONTROL_MASK | GDK_SHIFT_MASK, true }, + { MENU_NORMAL, IDC_DUPLICATE_TAB, IDS_APP_MENU_DUPLICATE_APP_WINDOW }, + { MENU_NORMAL, IDC_COPY_URL, IDS_APP_MENU_COPY_URL }, + { MENU_NORMAL, IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB }, + { MENU_NORMAL, IDC_NEW_TAB, IDS_APP_MENU_NEW_WEB_PAGE, 0, NULL, + GDK_T, GDK_CONTROL_MASK }, +}; + +const MenuCreateMaterial* GetFaviconMenu(Profile* profile, + MenuGtk::Delegate* delegate) { + static bool favicon_menu_built = false; + static MenuCreateMaterial* favicon_menu; + if (!favicon_menu_built) { + const MenuCreateMaterial* standard_page = + GetStandardPageMenu(profile, delegate); + int standard_page_menu_length = 1; + // Don't include the Create App Shortcut menu item. + int start_offset = 0; + for (int i = 0; standard_page[i].type != MENU_END; ++i) { + if (standard_page[i].id == IDC_CREATE_SHORTCUTS) { + // Pass the separator as well. + start_offset = i + 2; + ++i; + continue; + } else if (start_offset == 0) { + // The Create App Shortcut menu item is the first menu item, and if that + // ever changes we'll probably have to re-evaluate this code. + NOTREACHED(); + continue; + } + + standard_page_menu_length++; + } + favicon_menu = new MenuCreateMaterial[arraysize(g_favicon_menu) + + standard_page_menu_length]; + memcpy(favicon_menu, g_favicon_menu, + arraysize(g_favicon_menu) * sizeof(MenuCreateMaterial)); + memcpy(favicon_menu + arraysize(g_favicon_menu), + standard_page + start_offset, + (standard_page_menu_length) * sizeof(MenuCreateMaterial)); + } + return favicon_menu; +} + } // namespace BrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window, @@ -209,14 +263,20 @@ void BrowserTitlebar::Init() { gtk_box_pack_start(GTK_BOX(app_mode_hbox), browser_window_->tabstrip()->widget(), FALSE, FALSE, 0); + GtkWidget* favicon_event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(favicon_event_box), FALSE); + g_signal_connect(favicon_event_box, "button-press-event", + G_CALLBACK(OnButtonPressed), this); + gtk_box_pack_start(GTK_BOX(app_mode_hbox), favicon_event_box, FALSE, + FALSE, 0); // We use the app logo as a placeholder image so the title doesn't jump // around. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - // TODO(tc): Add a left click menu to this icon. app_mode_favicon_ = gtk_image_new_from_pixbuf( rb.GetRTLEnabledPixbufNamed(IDR_PRODUCT_LOGO_16)); - gtk_box_pack_start(GTK_BOX(app_mode_hbox), app_mode_favicon_, FALSE, - FALSE, 0); + g_object_set_data(G_OBJECT(app_mode_favicon_), "left-align-popup", + reinterpret_cast<void*>(true)); + gtk_container_add(GTK_CONTAINER(favicon_event_box), app_mode_favicon_); app_mode_title_ = gtk_label_new(NULL); gtk_label_set_ellipsize(GTK_LABEL(app_mode_title_), PANGO_ELLIPSIZE_END); @@ -434,6 +494,15 @@ void BrowserTitlebar::UpdateTextColor() { } } +void BrowserTitlebar::ShowFaviconMenu(GdkEventButton* event) { + if (!favicon_menu_.get()) { + favicon_menu_.reset(new MenuGtk(this, + GetFaviconMenu(browser_window_->browser()->profile(), this), NULL)); + } + + favicon_menu_->Popup(app_mode_favicon_, reinterpret_cast<GdkEvent*>(event)); +} + // static gboolean BrowserTitlebar::OnWindowStateChanged(GtkWindow* window, GdkEventWindowState* event, BrowserTitlebar* titlebar) { @@ -480,6 +549,17 @@ void BrowserTitlebar::OnButtonClicked(GtkWidget* button, } } +// static +gboolean BrowserTitlebar::OnButtonPressed(GtkWidget* widget, + GdkEventButton* event, + BrowserTitlebar* titlebar) { + if (event->button != 1) + return FALSE; + + titlebar->ShowFaviconMenu(event); + return TRUE; +} + void BrowserTitlebar::ShowContextMenu() { if (!context_menu_.get()) { static const MenuCreateMaterial context_menu_blueprint[] = { @@ -505,48 +585,44 @@ void BrowserTitlebar::ShowContextMenu() { } bool BrowserTitlebar::IsCommandEnabled(int command_id) const { - switch (command_id) { - case IDC_NEW_TAB: - case kShowWindowDecorationsCommand: - return true; + if (command_id == kShowWindowDecorationsCommand) + return true; - case IDC_RESTORE_TAB: - return browser_window_->browser()->CanRestoreTab(); + return browser_window_->browser()->command_updater()-> + IsCommandEnabled(command_id); +} - case IDC_TASK_MANAGER: - return true; +bool BrowserTitlebar::IsItemChecked(int command_id) const { + if (command_id == kShowWindowDecorationsCommand) { + PrefService* prefs = browser_window_->browser()->profile()->GetPrefs(); + return !prefs->GetBoolean(prefs::kUseCustomChromeFrame); + } - default: - NOTREACHED(); + EncodingMenuController controller; + if (controller.DoesCommandBelongToEncodingMenu(command_id)) { + TabContents* tab_contents = + browser_window_->browser()->GetSelectedTabContents(); + if (tab_contents) { + return controller.IsItemChecked(browser_window_->browser()->profile(), + tab_contents->encoding(), + command_id); + } + return false; } - return false; -} -bool BrowserTitlebar::IsItemChecked(int command_id) const { - DCHECK(command_id == kShowWindowDecorationsCommand); - PrefService* prefs = browser_window_->browser()->profile()->GetPrefs(); - return !prefs->GetBoolean(prefs::kUseCustomChromeFrame); + NOTREACHED(); + return false; } void BrowserTitlebar::ExecuteCommand(int command_id) { - switch (command_id) { - case IDC_NEW_TAB: - case IDC_RESTORE_TAB: - case IDC_TASK_MANAGER: - browser_window_->browser()->ExecuteCommand(command_id); - break; - - case kShowWindowDecorationsCommand: - { - PrefService* prefs = browser_window_->browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kUseCustomChromeFrame, - !prefs->GetBoolean(prefs::kUseCustomChromeFrame)); - break; - } - - default: - NOTREACHED(); + if (command_id == kShowWindowDecorationsCommand) { + PrefService* prefs = browser_window_->browser()->profile()->GetPrefs(); + prefs->SetBoolean(prefs::kUseCustomChromeFrame, + !prefs->GetBoolean(prefs::kUseCustomChromeFrame)); + return; } + + browser_window_->browser()->ExecuteCommand(command_id); } void BrowserTitlebar::Observe(NotificationType type, diff --git a/chrome/browser/gtk/browser_titlebar.h b/chrome/browser/gtk/browser_titlebar.h index 84d9236..a9ace55 100644 --- a/chrome/browser/gtk/browser_titlebar.h +++ b/chrome/browser/gtk/browser_titlebar.h @@ -95,6 +95,9 @@ class BrowserTitlebar : public MenuGtk::Delegate, // change in the window. void UpdateTextColor(); + // Show the menu that the user gets from left-clicking the favicon. + void ShowFaviconMenu(GdkEventButton* event); + // Callback for changes to window state. This includes // maximizing/restoring/minimizing the window. static gboolean OnWindowStateChanged(GtkWindow* window, @@ -108,6 +111,10 @@ class BrowserTitlebar : public MenuGtk::Delegate, // Callback for min/max/close buttons. static void OnButtonClicked(GtkWidget* button, BrowserTitlebar* window); + // Callback for favicon. + static gboolean OnButtonPressed(GtkWidget* widget, GdkEventButton* event, + BrowserTitlebar* titlebar); + // -- Context Menu ----------------------------------------------------------- // MenuGtk::Delegate implementation: @@ -166,6 +173,9 @@ class BrowserTitlebar : public MenuGtk::Delegate, // The context menu. scoped_ptr<MenuGtk> context_menu_; + // The favicon menu. + scoped_ptr<MenuGtk> favicon_menu_; + // The throbber used when the window is in app mode or popup window mode. Throbber throbber_; diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index 0a0aad3..ce1984e 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -103,33 +103,6 @@ BrowserToolbarGtk::~BrowserToolbarGtk() { g_object_unref(accel_group_); } -// Construct an "encodings" menu based on profile settings. -static MenuGtk* BuildEncodingsMenu(Profile* profile, - MenuGtk::Delegate* delegate) { - EncodingMenuController controller; - EncodingMenuController::EncodingMenuItemList items; - controller.GetEncodingMenuItems(profile, &items); - - MenuGtk* menu = new MenuGtk(delegate, false); - GSList* radio_group = NULL; - for (EncodingMenuController::EncodingMenuItemList::const_iterator i = - items.begin(); - i != items.end(); ++i) { - if (i == items.begin()) { - menu->AppendCheckMenuItemWithLabel(i->first, UTF16ToUTF8(i->second)); - } else if (i->first == 0) { - menu->AppendSeparator(); - } else { - GtkWidget* item = - gtk_radio_menu_item_new_with_label(radio_group, - UTF16ToUTF8(i->second).c_str()); - radio_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); - menu->AppendMenuItem(i->first, item); - } - } - return menu; -} - void BrowserToolbarGtk::Init(Profile* profile, GtkWindow* top_level_window) { // Make sure to tell the location bar the profile before calling its Init. @@ -222,8 +195,7 @@ void BrowserToolbarGtk::Init(Profile* profile, theme_provider_->GetRTLEnabledPixbufNamed(IDR_MENU_PAGE)); gtk_container_add(GTK_CONTAINER(page_menu), page_menu_image_); - encodings_menu_.reset(BuildEncodingsMenu(profile, this)); - page_menu_.reset(new MenuGtk(this, GetStandardPageMenu(encodings_menu_.get()), + page_menu_.reset(new MenuGtk(this, GetStandardPageMenu(profile_, this), accel_group_)); gtk_box_pack_start(GTK_BOX(menus_hbox_), page_menu, FALSE, FALSE, 0); diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index 74b2a48..b2f0590 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -189,7 +189,6 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, scoped_ptr<MenuGtk> page_menu_; scoped_ptr<MenuGtk> app_menu_; - scoped_ptr<MenuGtk> encodings_menu_; Browser* browser_; BrowserWindowGtk* window_; diff --git a/chrome/browser/gtk/standard_menus.cc b/chrome/browser/gtk/standard_menus.cc index 64e4309..c798fbbb 100644 --- a/chrome/browser/gtk/standard_menus.cc +++ b/chrome/browser/gtk/standard_menus.cc @@ -12,6 +12,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/encoding_menu_controller.h" +#include "chrome/browser/profile.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -107,7 +108,31 @@ struct MenuCreateMaterial standard_app_menu_materials[] = { } // namespace -const MenuCreateMaterial* GetStandardPageMenu(MenuGtk* encodings_menu) { +const MenuCreateMaterial* GetStandardPageMenu(Profile* profile, + MenuGtk::Delegate* delegate) { + EncodingMenuController controller; + EncodingMenuController::EncodingMenuItemList items; + controller.GetEncodingMenuItems(profile, &items); + + MenuGtk* encodings_menu = new MenuGtk(delegate, false); + GSList* radio_group = NULL; + for (EncodingMenuController::EncodingMenuItemList::const_iterator i = + items.begin(); + i != items.end(); ++i) { + if (i == items.begin()) { + encodings_menu->AppendCheckMenuItemWithLabel(i->first, + UTF16ToUTF8(i->second)); + } else if (i->first == 0) { + encodings_menu->AppendSeparator(); + } else { + GtkWidget* item = + gtk_radio_menu_item_new_with_label(radio_group, + UTF16ToUTF8(i->second).c_str()); + radio_group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item)); + encodings_menu->AppendMenuItem(i->first, item); + } + } + // Find the encoding menu and attach this menu. for (MenuCreateMaterial* entry = standard_page_menu_materials; entry->type != MENU_END; ++entry) { diff --git a/chrome/browser/gtk/standard_menus.h b/chrome/browser/gtk/standard_menus.h index c9298c3..15c3734 100644 --- a/chrome/browser/gtk/standard_menus.h +++ b/chrome/browser/gtk/standard_menus.h @@ -5,8 +5,9 @@ #ifndef CHROME_BROWSER_GTK_STANDARD_MENUS_H_ #define CHROME_BROWSER_GTK_STANDARD_MENUS_H_ +#include "chrome/browser/gtk/menu_gtk.h" + class Menu; -class MenuGtk; class Profile; enum MenuItemType { @@ -54,7 +55,9 @@ struct MenuCreateMaterial { }; // Returns the menu construction data structure for the page menu. -const MenuCreateMaterial* GetStandardPageMenu(MenuGtk* encodings_menu); +// The parameters are used to construct the encodings menu. +const MenuCreateMaterial* GetStandardPageMenu(Profile* profile, + MenuGtk::Delegate* delegate); // Returns the menu construction data structure for the app menu. const MenuCreateMaterial* GetStandardAppMenu(); |