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

Unified Diff: chrome/browser/ui/gtk/browser_titlebar.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_titlebar.cc
diff --git a/chrome/browser/ui/gtk/browser_titlebar.cc b/chrome/browser/ui/gtk/browser_titlebar.cc
deleted file mode 100644
index 171735fde2b0bd8a1fec2d1ee6029a4f7b587f35..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/gtk/browser_titlebar.cc
+++ /dev/null
@@ -1,1107 +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_titlebar.h"
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/i18n/rtl.h"
-#include "base/memory/singleton.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/avatar_menu.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_info_cache.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/gtk/accelerators_gtk.h"
-#include "chrome/browser/ui/gtk/avatar_menu_bubble_gtk.h"
-#include "chrome/browser/ui/gtk/avatar_menu_button_gtk.h"
-#include "chrome/browser/ui/gtk/browser_window_gtk.h"
-#include "chrome/browser/ui/gtk/custom_button.h"
-#if defined(USE_GCONF)
-#include "chrome/browser/ui/gtk/gconf_titlebar_listener.h"
-#endif
-#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#include "chrome/browser/ui/gtk/gtk_util.h"
-#include "chrome/browser/ui/gtk/menu_gtk.h"
-#include "chrome/browser/ui/gtk/nine_box.h"
-#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
-#include "chrome/browser/ui/gtk/unity_service.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
-#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/web_contents.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#include "ui/base/gtk/gtk_hig_constants.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/x/active_window_watcher_x.h"
-#include "ui/gfx/image/image.h"
-
-using content::WebContents;
-
-namespace {
-
-// The space above the titlebars.
-const int kTitlebarHeight = 14;
-
-// The thickness in pixels of the tab border.
-const int kTabOuterThickness = 1;
-
-// Amount to offset the tab images relative to the background.
-const int kNormalVerticalOffset = kTitlebarHeight + kTabOuterThickness;
-
-// A linux specific menu item for toggling window decorations.
-const int kShowWindowDecorationsCommand = 200;
-
-const int kAvatarBottomSpacing = 1;
-// There are 2 px on each side of the avatar (between the frame border and
-// it on the left, and between it and the tabstrip on the right).
-const int kAvatarSideSpacing = 2;
-
-// There is a 4px gap between the icon and the title text.
-const int kIconTitleSpacing = 4;
-
-// Padding around the icon when in app mode or popup mode.
-const int kAppModePaddingTop = 5;
-const int kAppModePaddingBottom = 4;
-const int kAppModePaddingLeft = 2;
-
-// The left padding of the tab strip. In Views, the tab strip has a left
-// margin of FrameBorderThickness + kClientEdgeThickness. This offset is to
-// account for kClientEdgeThickness.
-const int kTabStripLeftPadding = 1;
-
-// Spacing between buttons of the titlebar.
-const int kButtonSpacing = 2;
-
-// Spacing around outside of titlebar buttons.
-const int kButtonOuterPadding = 2;
-
-// Spacing between tabstrip and window control buttons (when the window is
-// maximized).
-const int kMaximizedTabstripPadding = 16;
-
-gboolean OnMouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
- BrowserWindowGtk* browser_window) {
- // Reset to the default mouse cursor.
- browser_window->ResetCustomFrameCursor();
- return TRUE;
-}
-
-// Converts a GdkColor to a color_utils::HSL.
-color_utils::HSL GdkColorToHSL(const GdkColor* color) {
- color_utils::HSL hsl;
- color_utils::SkColorToHSL(SkColorSetRGB(color->red >> 8,
- color->green >> 8,
- color->blue >> 8), &hsl);
- return hsl;
-}
-
-// Returns either |one| or |two| based on which has a greater difference in
-// luminosity.
-GdkColor PickLuminosityContrastingColor(const GdkColor* base,
- const GdkColor* one,
- const GdkColor* two) {
- // Convert all GdkColors to color_utils::HSLs.
- color_utils::HSL baseHSL = GdkColorToHSL(base);
- color_utils::HSL oneHSL = GdkColorToHSL(one);
- color_utils::HSL twoHSL = GdkColorToHSL(two);
- double one_difference = fabs(baseHSL.l - oneHSL.l);
- double two_difference = fabs(baseHSL.l - twoHSL.l);
-
- // Be biased towards the first color presented.
- if (two_difference > one_difference + 0.1)
- return *two;
- else
- return *one;
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// PopupPageMenuModel
-
-// A menu model that builds the contents of the menu shown for popups (when the
-// user clicks on the favicon) and all of its submenus.
-class PopupPageMenuModel : public ui::SimpleMenuModel {
- public:
- PopupPageMenuModel(ui::SimpleMenuModel::Delegate* delegate, Browser* browser);
- virtual ~PopupPageMenuModel() { }
-
- private:
- void Build();
-
- // Models for submenus referenced by this model. SimpleMenuModel only uses
- // weak references so these must be kept for the lifetime of the top-level
- // model.
- scoped_ptr<ZoomMenuModel> zoom_menu_model_;
- scoped_ptr<EncodingMenuModel> encoding_menu_model_;
- Browser* browser_; // weak
-
- DISALLOW_COPY_AND_ASSIGN(PopupPageMenuModel);
-};
-
-PopupPageMenuModel::PopupPageMenuModel(
- ui::SimpleMenuModel::Delegate* delegate,
- Browser* browser)
- : ui::SimpleMenuModel(delegate), browser_(browser) {
- Build();
-}
-
-void PopupPageMenuModel::Build() {
- AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
- AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
- AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(IDC_CUT, IDS_CUT);
- AddItemWithStringId(IDC_COPY, IDS_COPY);
- AddItemWithStringId(IDC_PASTE, IDS_PASTE);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(IDC_FIND, IDS_FIND);
- AddItemWithStringId(IDC_PRINT, IDS_PRINT);
- zoom_menu_model_.reset(new ZoomMenuModel(delegate()));
- AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU, zoom_menu_model_.get());
-
- encoding_menu_model_.reset(new EncodingMenuModel(browser_));
- AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
- encoding_menu_model_.get());
-
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// BrowserTitlebar
-
-// static
-const char BrowserTitlebar::kDefaultButtonString[] = ":minimize,maximize,close";
-
-BrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window,
- GtkWindow* window)
- : browser_window_(browser_window),
- window_(window),
- container_(NULL),
- container_hbox_(NULL),
- titlebar_left_buttons_vbox_(NULL),
- titlebar_right_buttons_vbox_(NULL),
- titlebar_left_buttons_hbox_(NULL),
- titlebar_right_buttons_hbox_(NULL),
- titlebar_left_avatar_frame_(NULL),
- titlebar_right_avatar_frame_(NULL),
- titlebar_left_label_frame_(NULL),
- titlebar_right_label_frame_(NULL),
- avatar_(NULL),
- avatar_label_(NULL),
- avatar_label_bg_(NULL),
- top_padding_left_(NULL),
- top_padding_right_(NULL),
- titlebar_alignment_(NULL),
- app_mode_favicon_(NULL),
- app_mode_title_(NULL),
- using_custom_frame_(false),
- window_has_focus_(false),
- display_avatar_on_left_(false),
- theme_service_(NULL) {
-}
-
-void BrowserTitlebar::Init() {
- // The widget hierarchy is shown below.
- //
- // +- EventBox (container_) ------------------------------------------------+
- // +- HBox (container_hbox_) -----------------------------------------------+
- // |+ VBox ---++- Algn. -++- Alignment --------------++- Algn. -++ VBox ---+|
- // || titlebar||titlebar || (titlebar_alignment_) ||titlebar || titlebar||
- // || left ||left || ||right || right ||
- // || button ||spy || ||spy || button ||
- // || vbox ||frame ||+- TabStripGtk ---------+||frame || vbox ||
- // || || || tab tab tabclose ||| || ||
- // || || ||+------------------------+|| || ||
- // |+---------++---------++--------------------------++---------++---------+|
- // +------------------------------------------------------------------------+
- //
- // There are two vboxes on either side of |container_hbox_| because when the
- // desktop is GNOME, the button placement is configurable based on a metacity
- // gconf key. We can't just have one vbox and move it back and forth because
- // the gconf language allows you to place buttons on both sides of the
- // window. This being Linux, I'm sure there's a bunch of people who have
- // already configured their window manager to do so and we don't want to get
- // confused when that happens. The actual contents of these vboxes are lazily
- // generated so they don't interfere with alignment when everything is
- // stuffed in the other box.
- //
- // Each vbox has the following hierarchy if it contains buttons:
- //
- // +- VBox (titlebar_{l,r}_buttons_vbox_) ---------+
- // |+- Fixed (top_padding_{l,r}_) ----------------+|
- // ||+- HBox (titlebar_{l,r}_buttons_hbox_ ------+||
- // ||| (buttons of a configurable layout) |||
- // ||+-------------------------------------------+||
- // |+---------------------------------------------+|
- // +-----------------------------------------------+
- //
- // The two spy alignments are only allocated if this window is an incognito
- // window. Only one of them holds the spy image.
- //
- // If we're a popup window or in app mode, we don't display the spy guy or
- // the tab strip. Instead, put an hbox in titlebar_alignment_ in place of
- // the tab strip.
- // +- Alignment (titlebar_alignment_) -----------------------------------+
- // |+ HBox -------------------------------------------------------------+|
- // ||+- TabStripGtk -++- Image ----------------++- Label --------------+||
- // ||| hidden ++ (app_mode_favicon_) || (app_mode_title_) |||
- // ||| || favicon || page title |||
- // ||+---------------++------------------------++----------------------+||
- // |+-------------------------------------------------------------------+|
- // +---------------------------------------------------------------------+
- container_hbox_ = gtk_hbox_new(FALSE, 0);
-
- container_ = gtk_event_box_new();
- gtk_widget_set_name(container_, "chrome-browser-titlebar");
- gtk_event_box_set_visible_window(GTK_EVENT_BOX(container_), FALSE);
- gtk_container_add(GTK_CONTAINER(container_), container_hbox_);
-
- g_signal_connect(container_, "scroll-event", G_CALLBACK(OnScrollThunk), this);
-
- g_signal_connect(window_, "window-state-event",
- G_CALLBACK(OnWindowStateChangedThunk), this);
-
- // Allocate the two button boxes on the left and right parts of the bar. These
- // are always allocated, but only displayed in incognito mode or when using
- // multiple profiles.
- titlebar_left_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_buttons_vbox_,
- FALSE, FALSE, 0);
- titlebar_left_avatar_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
- gtk_widget_set_no_show_all(titlebar_left_avatar_frame_, TRUE);
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_left_avatar_frame_), 0,
- kAvatarBottomSpacing, kAvatarSideSpacing, kAvatarSideSpacing);
- gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_avatar_frame_,
- FALSE, FALSE, 0);
-
- titlebar_left_label_frame_ = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
- gtk_widget_set_no_show_all(titlebar_left_label_frame_, TRUE);
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_left_label_frame_), 0,
- kAvatarBottomSpacing, kAvatarSideSpacing, kAvatarSideSpacing);
- gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_label_frame_,
- FALSE, FALSE, 0);
-
- titlebar_right_avatar_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
- gtk_widget_set_no_show_all(titlebar_right_avatar_frame_, TRUE);
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_right_avatar_frame_), 0,
- kAvatarBottomSpacing, kAvatarSideSpacing, kAvatarSideSpacing);
- gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_avatar_frame_,
- FALSE, FALSE, 0);
-
- titlebar_right_label_frame_ = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
- gtk_widget_set_no_show_all(titlebar_right_label_frame_, TRUE);
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_right_label_frame_), 0,
- kAvatarBottomSpacing, kAvatarSideSpacing, kAvatarSideSpacing);
- gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_label_frame_,
- FALSE, FALSE, 0);
-
- titlebar_right_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_buttons_vbox_,
- FALSE, FALSE, 0);
-
- // Create the Avatar button and listen for notifications. It must always be
- // created because a new profile can be added at any time.
- avatar_button_.reset(new AvatarMenuButtonGtk(browser_window_->browser()));
-
- registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
- content::NotificationService::AllSources());
-
-#if defined(USE_GCONF)
- // Either read the gconf database and register for updates (on GNOME), or use
- // the default value (anywhere else).
- GConfTitlebarListener::GetInstance()->SetTitlebarButtons(this);
-#else
- BuildButtons(kDefaultButtonString);
-#endif
-
- UpdateAvatar();
-
- // We use an alignment to control the titlebar height.
- titlebar_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
- if (browser_window_->browser()->is_type_tabbed()) {
- gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
- TRUE, 0);
-
- // Put the tab strip in the titlebar.
- gtk_container_add(GTK_CONTAINER(titlebar_alignment_),
- browser_window_->tabstrip()->widget());
- } else {
- // App mode specific widgets.
- gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
- TRUE, 0);
- GtkWidget* app_mode_hbox = gtk_hbox_new(FALSE, kIconTitleSpacing);
- gtk_container_add(GTK_CONTAINER(titlebar_alignment_), app_mode_hbox);
-
- // Put the tab strip in the hbox even though we don't show it. Sometimes
- // we need the position of the tab strip so make sure it's in our widget
- // hierarchy.
- 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(OnFaviconMenuButtonPressedThunk), 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.
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- app_mode_favicon_ = gtk_image_new_from_pixbuf(rb.GetNativeImageNamed(
- IDR_PRODUCT_LOGO_16, ui::ResourceBundle::RTL_ENABLED).ToGdkPixbuf());
- 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);
- gtk_misc_set_alignment(GTK_MISC(app_mode_title_), 0.0, 0.5);
- gtk_box_pack_start(GTK_BOX(app_mode_hbox), app_mode_title_, TRUE, TRUE,
- 0);
-
- UpdateTitleAndIcon();
- }
-
- theme_service_ = GtkThemeService::GetFrom(
- browser_window_->browser()->profile());
- registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
- content::Source<ThemeService>(theme_service_));
- theme_service_->InitThemesFor(this);
-
- gtk_widget_show_all(container_);
-
- ui::ActiveWindowWatcherX::AddObserver(this);
-}
-
-BrowserTitlebar::~BrowserTitlebar() {
- ui::ActiveWindowWatcherX::RemoveObserver(this);
-#if defined(USE_GCONF)
- GConfTitlebarListener::GetInstance()->RemoveObserver(this);
-#endif
-}
-
-void BrowserTitlebar::BuildButtons(const std::string& button_string) {
- // Clear out all previous data.
- close_button_.reset();
- restore_button_.reset();
- maximize_button_.reset();
- minimize_button_.reset();
- gtk_util::RemoveAllChildren(titlebar_left_buttons_vbox_);
- gtk_util::RemoveAllChildren(titlebar_right_buttons_vbox_);
- titlebar_left_buttons_hbox_ = NULL;
- titlebar_right_buttons_hbox_ = NULL;
- top_padding_left_ = NULL;
- top_padding_right_ = NULL;
-
- bool left_side = true;
- base::StringTokenizer tokenizer(button_string, ":,");
- tokenizer.set_options(base::StringTokenizer::RETURN_DELIMS);
- int left_count = 0;
- int right_count = 0;
- while (tokenizer.GetNext()) {
- if (tokenizer.token_is_delim()) {
- if (*tokenizer.token_begin() == ':')
- left_side = false;
- } else {
- base::StringPiece token = tokenizer.token_piece();
- if (BuildButton(token.as_string(), left_side))
- (left_side ? left_count : right_count)++;
- }
- }
-
- // If we are in incognito mode, add the spy guy to either the end of the left
- // or the beginning of the right depending on which side has fewer buttons.
- display_avatar_on_left_ = right_count > left_count;
-
- // Now show the correct widgets in the two hierarchies.
- if (using_custom_frame_) {
- gtk_widget_show_all(titlebar_left_buttons_vbox_);
- gtk_widget_show_all(titlebar_right_buttons_vbox_);
- }
- UpdateMaximizeRestoreVisibility();
-}
-
-bool BrowserTitlebar::BuildButton(const std::string& button_token,
- bool left_side) {
- if (button_token == "minimize") {
- minimize_button_.reset(CreateTitlebarButton("minimize", left_side));
-
- gtk_widget_size_request(minimize_button_->widget(),
- &minimize_button_req_);
- return true;
- } else if (button_token == "maximize") {
- restore_button_.reset(CreateTitlebarButton("unmaximize", left_side));
- maximize_button_.reset(CreateTitlebarButton("maximize", left_side));
-
- gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(),
- true, true, true);
- gtk_widget_size_request(restore_button_->widget(),
- &restore_button_req_);
- return true;
- } else if (button_token == "close") {
- close_button_.reset(CreateTitlebarButton("close", left_side));
- close_button_->set_flipped(left_side);
-
- gtk_widget_size_request(close_button_->widget(), &close_button_req_);
- return true;
- }
- // Ignore any other values like "pin" since we don't have images for
- // those.
- return false;
-}
-
-GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
- if (left_side && titlebar_left_buttons_hbox_)
- return titlebar_left_buttons_hbox_;
- else if (!left_side && titlebar_right_buttons_hbox_)
- return titlebar_right_buttons_hbox_;
-
- // We put the min/max/restore/close buttons in a vbox so they are top aligned
- // (up to padding) and don't vertically stretch.
- GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ :
- titlebar_right_buttons_vbox_;
-
- GtkWidget* top_padding = gtk_fixed_new();
- gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding);
- gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0);
-
- GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing);
- gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0);
-
- if (left_side) {
- titlebar_left_buttons_hbox_ = buttons_hbox;
- top_padding_left_ = top_padding;
- } else {
- titlebar_right_buttons_hbox_ = buttons_hbox;
- top_padding_right_ = top_padding;
- }
-
- return buttons_hbox;
-}
-
-CustomDrawButton* BrowserTitlebar::CreateTitlebarButton(
- const std::string& button_name, bool left_side) {
- int normal_image_id;
- int pressed_image_id;
- int hover_image_id;
- int tooltip_id;
- GetButtonResources(button_name, &normal_image_id, &pressed_image_id,
- &hover_image_id, &tooltip_id);
-
- CustomDrawButton* button = new CustomDrawButton(normal_image_id,
- pressed_image_id,
- hover_image_id,
- 0);
- gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK);
- g_signal_connect(button->widget(), "clicked",
- G_CALLBACK(OnButtonClickedThunk), this);
- g_signal_connect(button->widget(), "motion-notify-event",
- G_CALLBACK(OnMouseMoveEvent), browser_window_);
-
- std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip_id);
- gtk_widget_set_tooltip_text(button->widget(),
- localized_tooltip.c_str());
-
- GtkWidget* box = GetButtonHBox(left_side);
- gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0);
- return button;
-}
-
-void BrowserTitlebar::GetButtonResources(const std::string& button_name,
- int* normal_image_id,
- int* pressed_image_id,
- int* hover_image_id,
- int* tooltip_id) const {
- if (button_name == "close") {
- *normal_image_id = IDR_CLOSE;
- *pressed_image_id = IDR_CLOSE_P;
- *hover_image_id = IDR_CLOSE_H;
- *tooltip_id = IDS_XPFRAME_CLOSE_TOOLTIP;
- } else if (button_name == "minimize") {
- *normal_image_id = IDR_MINIMIZE;
- *pressed_image_id = IDR_MINIMIZE_P;
- *hover_image_id = IDR_MINIMIZE_H;
- *tooltip_id = IDS_XPFRAME_MINIMIZE_TOOLTIP;
- } else if (button_name == "maximize") {
- *normal_image_id = IDR_MAXIMIZE;
- *pressed_image_id = IDR_MAXIMIZE_P;
- *hover_image_id = IDR_MAXIMIZE_H;
- *tooltip_id = IDS_XPFRAME_MAXIMIZE_TOOLTIP;
- } else if (button_name == "unmaximize") {
- *normal_image_id = IDR_RESTORE;
- *pressed_image_id = IDR_RESTORE_P;
- *hover_image_id = IDR_RESTORE_H;
- *tooltip_id = IDS_XPFRAME_RESTORE_TOOLTIP;
- }
-}
-
-void BrowserTitlebar::UpdateButtonBackground(CustomDrawButton* button) {
- SkColor color = theme_service_->GetColor(
- ThemeProperties::COLOR_BUTTON_BACKGROUND);
- SkBitmap background = theme_service_->GetImageNamed(
- IDR_THEME_WINDOW_CONTROL_BACKGROUND).AsBitmap();
-
- // TODO(erg): For now, we just use a completely black mask and we can get
- // away with this in the short term because our buttons are rectangles. We
- // should get Glen to make properly hinted masks that match our min/max/close
- // buttons (which have some odd alpha blending around the
- // edges). http://crbug.com/103661
- SkBitmap mask;
- mask.setConfig(SkBitmap::kARGB_8888_Config,
- button->SurfaceWidth(), button->SurfaceHeight(), 0);
- mask.allocPixels();
- mask.eraseColor(SK_ColorBLACK);
-
- button->SetBackground(color, background, mask);
-}
-
-void BrowserTitlebar::UpdateCustomFrame(bool use_custom_frame) {
- using_custom_frame_ = use_custom_frame;
- if (!use_custom_frame ||
- (browser_window_->IsMaximized() && unity::IsRunning())) {
- if (titlebar_left_buttons_vbox_)
- gtk_widget_hide(titlebar_left_buttons_vbox_);
- if (titlebar_right_buttons_vbox_)
- gtk_widget_hide(titlebar_right_buttons_vbox_);
- } else {
- if (titlebar_left_buttons_vbox_)
- gtk_widget_show_all(titlebar_left_buttons_vbox_);
- if (titlebar_right_buttons_vbox_)
- gtk_widget_show_all(titlebar_right_buttons_vbox_);
- }
- UpdateTitlebarAlignment();
- UpdateMaximizeRestoreVisibility();
-}
-
-void BrowserTitlebar::UpdateTitleAndIcon() {
- if (!app_mode_title_)
- return;
-
- // Get the page title and elide it to the available space.
- base::string16 title =
- browser_window_->browser()->GetWindowTitleForCurrentTab();
- gtk_label_set_text(GTK_LABEL(app_mode_title_),
- base::UTF16ToUTF8(title).c_str());
-
- if (browser_window_->browser()->is_app()) {
- switch (browser_window_->browser()->type()) {
- case Browser::TYPE_POPUP: {
- // Update the system app icon. We don't need to update the icon in the
- // top left of the custom frame, that will get updated when the
- // throbber is updated.
- Profile* profile = browser_window_->browser()->profile();
- gfx::Image icon = browser_window_->browser()->GetCurrentPageIcon();
- if (icon.IsEmpty()) {
- gtk_util::SetWindowIcon(window_, profile);
- } else {
- gtk_util::SetWindowIcon(window_, profile, icon.ToGdkPixbuf());
- }
- break;
- }
- case Browser::TYPE_TABBED: {
- NOTREACHED() << "We should never have a tabbed app window.";
- break;
- }
- }
- }
-}
-
-void BrowserTitlebar::UpdateThrobber(WebContents* web_contents) {
- DCHECK(app_mode_favicon_);
-
- if (web_contents && web_contents->IsLoading()) {
- GdkPixbuf* icon_pixbuf =
- throbber_.GetNextFrame(web_contents->IsWaitingForResponse());
- gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
- } else {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-
- // Note: we want to exclude the application popup/panel window.
- if ((browser_window_->browser()->is_app() &&
- !browser_window_->browser()->is_type_tabbed()) ||
- browser_window_->browser()->is_type_popup()) {
- gfx::Image icon = browser_window_->browser()->GetCurrentPageIcon();
- if (icon.IsEmpty()) {
- // Fallback to the Chromium icon if the page has no icon.
- gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
- rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_16).ToGdkPixbuf());
- } else {
- gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
- icon.ToGdkPixbuf());
- }
- } else {
- gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
- rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_16).ToGdkPixbuf());
- }
- throbber_.Reset();
- }
-}
-
-void BrowserTitlebar::UpdateTitlebarAlignment() {
- if (browser_window_->browser()->is_type_tabbed()) {
- int top_padding = 0;
- int side_padding = 0;
- int vertical_offset = kNormalVerticalOffset;
-
- if (using_custom_frame_) {
- if (!browser_window_->IsMaximized()) {
- top_padding = kTitlebarHeight;
- } else if (using_custom_frame_ && browser_window_->IsMaximized()) {
- vertical_offset = 0;
- if (!unity::IsRunning())
- side_padding = kMaximizedTabstripPadding;
- }
- }
-
- int right_padding = 0;
- int left_padding = kTabStripLeftPadding;
- if (titlebar_right_buttons_hbox_)
- right_padding = side_padding;
- if (titlebar_left_buttons_hbox_)
- left_padding = side_padding;
-
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
- top_padding, 0,
- left_padding, right_padding);
- browser_window_->tabstrip()->SetVerticalOffset(vertical_offset);
- } else {
- if (using_custom_frame_ && !browser_window_->IsFullscreen()) {
- gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
- kAppModePaddingTop, kAppModePaddingBottom, kAppModePaddingLeft, 0);
- gtk_widget_show(titlebar_alignment_);
- } else {
- gtk_widget_hide(titlebar_alignment_);
- }
- }
-
- // Resize the buttons so that the clickable area extends all the way to the
- // edge of the browser window.
- GtkRequisition close_button_req = close_button_req_;
- GtkRequisition minimize_button_req = minimize_button_req_;
- GtkRequisition restore_button_req = restore_button_req_;
- if (using_custom_frame_ && browser_window_->IsMaximized()) {
- close_button_req.width += kButtonOuterPadding;
- close_button_req.height += kButtonOuterPadding;
- minimize_button_req.height += kButtonOuterPadding;
- restore_button_req.height += kButtonOuterPadding;
- if (top_padding_left_)
- gtk_widget_hide(top_padding_left_);
- if (top_padding_right_)
- gtk_widget_hide(top_padding_right_);
- } else {
- if (top_padding_left_)
- gtk_widget_show(top_padding_left_);
- if (top_padding_right_)
- gtk_widget_show(top_padding_right_);
- }
- if (close_button_.get()) {
- gtk_widget_set_size_request(close_button_->widget(),
- close_button_req.width,
- close_button_req.height);
- }
- if (minimize_button_.get()) {
- gtk_widget_set_size_request(minimize_button_->widget(),
- minimize_button_req.width,
- minimize_button_req.height);
- }
- if (maximize_button_.get()) {
- gtk_widget_set_size_request(restore_button_->widget(),
- restore_button_req.width,
- restore_button_req.height);
- }
-}
-
-void BrowserTitlebar::UpdateTextColor() {
- if (!app_mode_title_)
- return;
-
- if (theme_service_ && theme_service_->UsingNativeTheme()) {
- // We don't really have any good options here.
- //
- // Colors from window manager themes aren't exposed in GTK; the window
- // manager is a separate component and when there is information sharing
- // (in the case of metacity), it's one way where the window manager reads
- // data from the GTK theme (which allows us to do a decent job with
- // picking the frame color).
- //
- // We probably won't match in the majority of cases, but we can at the
- // very least make things legible. The default metacity and xfwm themes
- // on ubuntu have white text hardcoded. Determine whether black or white
- // has more luminosity contrast and then set that color as the text
- // color.
- GdkColor frame_color;
- if (window_has_focus_) {
- frame_color = theme_service_->GetGdkColor(
- ThemeProperties::COLOR_FRAME);
- } else {
- frame_color = theme_service_->GetGdkColor(
- ThemeProperties::COLOR_FRAME_INACTIVE);
- }
- GdkColor text_color = PickLuminosityContrastingColor(
- &frame_color, &ui::kGdkWhite, &ui::kGdkBlack);
- gtk_util::SetLabelColor(app_mode_title_, &text_color);
- } else {
- gtk_util::SetLabelColor(app_mode_title_, &ui::kGdkWhite);
- }
-}
-
-void BrowserTitlebar::UpdateAvatarLabel() {
- if (theme_service_ && avatar_label_) {
- GdkColor text_color =
- theme_service_->GetGdkColor(ThemeProperties::COLOR_MANAGED_USER_LABEL);
- GdkColor label_background = theme_service_->GetGdkColor(
- ThemeProperties::COLOR_MANAGED_USER_LABEL_BACKGROUND);
- gtk_util::SetLabelColor(avatar_label_, &text_color);
- gtk_widget_modify_bg(
- GTK_WIDGET(avatar_label_bg_), GTK_STATE_NORMAL, &label_background);
- char* markup = g_markup_printf_escaped(
- "<span size='small'>%s</span>",
- l10n_util::GetStringUTF8(IDS_MANAGED_USER_AVATAR_LABEL).c_str());
- gtk_label_set_markup(GTK_LABEL(avatar_label_), markup);
- g_free(markup);
- }
-}
-
-void BrowserTitlebar::UpdateAvatar() {
- // Remove previous state.
- gtk_util::RemoveAllChildren(titlebar_left_avatar_frame_);
- gtk_util::RemoveAllChildren(titlebar_right_avatar_frame_);
- gtk_util::RemoveAllChildren(titlebar_left_label_frame_);
- gtk_util::RemoveAllChildren(titlebar_right_label_frame_);
-
- if (!ShouldDisplayAvatar())
- return;
-
- if (!avatar_) {
- if (IsOffTheRecord()) {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- gfx::Image avatar_image =
- rb.GetNativeImageNamed(IDR_OTR_ICON, ui::ResourceBundle::RTL_ENABLED);
- avatar_ = gtk_image_new_from_pixbuf(avatar_image.ToGdkPixbuf());
- gtk_misc_set_alignment(GTK_MISC(avatar_), 0.0, 1.0);
- gtk_widget_set_size_request(avatar_, -1, 0);
- } else {
- // Use a clickable avatar.
- avatar_ = avatar_button_->widget();
- }
- }
-
- gtk_widget_show_all(avatar_);
-
- Profile* profile = browser_window_->browser()->profile();
- if (profile->IsManaged()) {
- avatar_label_ = gtk_label_new(NULL);
- gtk_misc_set_padding(GTK_MISC(avatar_label_), 10, 2);
- avatar_label_bg_ = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(avatar_label_bg_), avatar_label_);
- g_signal_connect(avatar_label_bg_, "button-press-event",
- G_CALLBACK(OnAvatarLabelButtonPressedThunk), this);
- UpdateAvatarLabel();
- gtk_widget_show(avatar_label_bg_);
- gtk_widget_show(avatar_label_);
- if (display_avatar_on_left_) {
- gtk_container_add(GTK_CONTAINER(titlebar_left_label_frame_),
- avatar_label_bg_);
- gtk_widget_show(titlebar_left_label_frame_);
- gtk_widget_hide(titlebar_right_label_frame_);
- } else {
- gtk_container_add(GTK_CONTAINER(titlebar_right_label_frame_),
- avatar_label_bg_);
- gtk_widget_show(titlebar_right_label_frame_);
- gtk_widget_hide(titlebar_left_label_frame_);
- }
- }
-
- if (display_avatar_on_left_) {
- gtk_container_add(GTK_CONTAINER(titlebar_left_avatar_frame_), avatar_);
- gtk_widget_show(titlebar_left_avatar_frame_);
- gtk_widget_hide(titlebar_right_avatar_frame_);
- } else {
- gtk_container_add(GTK_CONTAINER(titlebar_right_avatar_frame_), avatar_);
- gtk_widget_show(titlebar_right_avatar_frame_);
- gtk_widget_hide(titlebar_left_avatar_frame_);
- }
-
- if (IsOffTheRecord())
- return;
-
- bool is_gaia_picture = false;
- gfx::Image avatar;
- ProfileInfoCache& cache =
- g_browser_process->profile_manager()->GetProfileInfoCache();
- size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
- if (index == std::string::npos)
- return;
-
- is_gaia_picture =
- cache.IsUsingGAIAPictureOfProfileAtIndex(index) &&
- cache.GetGAIAPictureOfProfileAtIndex(index);
- avatar = cache.GetAvatarIconOfProfileAtIndex(index);
- avatar_button_->SetIcon(avatar, is_gaia_picture);
- avatar_button_->set_menu_frame_style(display_avatar_on_left_ ?
- BubbleGtk::ANCHOR_TOP_LEFT : BubbleGtk::ANCHOR_TOP_RIGHT);
-}
-
-void BrowserTitlebar::MaximizeButtonClicked() {
- GdkEvent* event = gtk_get_current_event();
- if (event->button.button == 1) {
- gtk_window_maximize(window_);
- } else {
- GtkWidget* widget = GTK_WIDGET(window_);
- GdkScreen* screen = gtk_widget_get_screen(widget);
- gint monitor = gdk_screen_get_monitor_at_window(
- screen, gtk_widget_get_window(widget));
- GdkRectangle screen_rect;
- gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
-
- gint x, y;
- gtk_window_get_position(window_, &x, &y);
-
- GtkAllocation allocation;
- gtk_widget_get_allocation(widget, &allocation);
- gint width = allocation.width;
- gint height = allocation.height;
-
- if (event->button.button == 3) {
- x = 0;
- width = screen_rect.width;
- } else if (event->button.button == 2) {
- y = 0;
- height = screen_rect.height;
- }
-
- browser_window_->SetBounds(gfx::Rect(x, y, width, height));
- }
- gdk_event_free(event);
-}
-
-void BrowserTitlebar::UpdateMaximizeRestoreVisibility() {
- if (maximize_button_.get()) {
- if (browser_window_->IsMaximized()) {
- gtk_widget_hide(maximize_button_->widget());
- gtk_widget_show(restore_button_->widget());
- } else {
- gtk_widget_hide(restore_button_->widget());
- gtk_widget_show(maximize_button_->widget());
- }
- }
-}
-
-gboolean BrowserTitlebar::OnWindowStateChanged(GtkWindow* window,
- GdkEventWindowState* event) {
- UpdateMaximizeRestoreVisibility();
- UpdateTitlebarAlignment();
- UpdateTextColor();
- return FALSE;
-}
-
-gboolean BrowserTitlebar::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
- Browser* browser = browser_window_->browser();
- int index = browser->tab_strip_model()->active_index();
- if (event->direction == GDK_SCROLL_LEFT ||
- event->direction == GDK_SCROLL_UP) {
- if (index != 0)
- chrome::SelectPreviousTab(browser);
- } else if (index + 1 < browser->tab_strip_model()->count()) {
- chrome::SelectNextTab(browser);
- }
- return TRUE;
-}
-
-void BrowserTitlebar::OnButtonClicked(GtkWidget* button) {
- if (close_button_.get() && close_button_->widget() == button) {
- browser_window_->Close();
- } else if (restore_button_.get() && restore_button_->widget() == button) {
- browser_window_->UnMaximize();
- } else if (maximize_button_.get() && maximize_button_->widget() == button) {
- MaximizeButtonClicked();
- } else if (minimize_button_.get() && minimize_button_->widget() == button) {
- gtk_window_iconify(window_);
- }
-}
-
-gboolean BrowserTitlebar::OnFaviconMenuButtonPressed(GtkWidget* widget,
- GdkEventButton* event) {
- if (event->button != 1)
- return FALSE;
-
- if (!favicon_menu_model_.get()) {
- favicon_menu_model_.reset(
- new PopupPageMenuModel(this, browser_window_->browser()));
-
- favicon_menu_.reset(new MenuGtk(NULL, favicon_menu_model_.get()));
- }
-
- favicon_menu_->PopupForWidget(app_mode_favicon_, event->button, event->time);
-
- return TRUE;
-}
-
-gboolean BrowserTitlebar::OnAvatarLabelButtonPressed(GtkWidget* widget,
- GdkEventButton* event) {
- if (event->button != 1)
- return FALSE;
-
- // Show the avatar menu bubble with the upward arrow at the x position where
- // the user has clicked.
- gfx::Rect rect = gtk_util::WidgetBounds(widget);
- rect.set_x(event->x);
- rect.set_width(0);
- new AvatarMenuBubbleGtk(
- browser_window_->browser(), widget, BubbleGtk::ANCHOR_TOP_RIGHT, &rect);
- return TRUE;
-}
-
-void BrowserTitlebar::ShowContextMenu(GdkEventButton* event) {
- if (!context_menu_.get()) {
- context_menu_model_.reset(new ContextMenuModel(this));
- context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get()));
- }
-
- context_menu_->PopupAsContext(gfx::Point(event->x_root, event->y_root),
- event->time);
-}
-
-bool BrowserTitlebar::IsCommandIdEnabled(int command_id) const {
- if (command_id == kShowWindowDecorationsCommand)
- return true;
-
- return chrome::IsCommandEnabled(browser_window_->browser(), command_id);
-}
-
-bool BrowserTitlebar::IsCommandIdChecked(int command_id) const {
- if (command_id == kShowWindowDecorationsCommand) {
- PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
- return !prefs->GetBoolean(prefs::kUseCustomChromeFrame);
- }
-
- EncodingMenuController controller;
- if (controller.DoesCommandBelongToEncodingMenu(command_id)) {
- WebContents* web_contents =
- browser_window_->browser()->tab_strip_model()->GetActiveWebContents();
- if (web_contents) {
- return controller.IsItemChecked(browser_window_->browser()->profile(),
- web_contents->GetEncoding(),
- command_id);
- }
- return false;
- }
-
- NOTREACHED();
- return false;
-}
-
-void BrowserTitlebar::ExecuteCommand(int command_id, int event_flags) {
- if (command_id == kShowWindowDecorationsCommand) {
- PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
- prefs->SetBoolean(prefs::kUseCustomChromeFrame,
- !prefs->GetBoolean(prefs::kUseCustomChromeFrame));
- return;
- }
-
- chrome::ExecuteCommand(browser_window_->browser(), command_id);
-}
-
-bool BrowserTitlebar::GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* out_accelerator) {
- const ui::Accelerator* accelerator =
- AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
- command_id);
- if (!accelerator)
- return false;
- *out_accelerator = *accelerator;
- return true;
-}
-
-void BrowserTitlebar::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: {
- UpdateTextColor();
- UpdateAvatarLabel();
-
- if (minimize_button_.get())
- UpdateButtonBackground(minimize_button_.get());
- if (maximize_button_.get())
- UpdateButtonBackground(maximize_button_.get());
- if (restore_button_.get())
- UpdateButtonBackground(restore_button_.get());
- if (close_button_.get())
- UpdateButtonBackground(close_button_.get());
- break;
- }
-
- case chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED:
- if (!IsOffTheRecord())
- UpdateAvatar();
- break;
-
- default:
- NOTREACHED();
- }
-}
-
-void BrowserTitlebar::ActiveWindowChanged(GdkWindow* active_window) {
- // Can be called during shutdown; BrowserWindowGtk will set our |window_|
- // to NULL during that time.
- if (!window_)
- return;
-
- window_has_focus_ =
- gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
- UpdateTextColor();
-}
-
-bool BrowserTitlebar::ShouldDisplayAvatar() {
- if (IsOffTheRecord())
- return true;
-
- if (!browser_window_->browser()->is_type_tabbed())
- return false;
-
- return AvatarMenu::ShouldShowAvatarMenu();
-}
-
-bool BrowserTitlebar::IsOffTheRecord() {
- return browser_window_->browser()->profile()->IsOffTheRecord();
-}
-
-BrowserTitlebar::ContextMenuModel::ContextMenuModel(
- ui::SimpleMenuModel::Delegate* delegate)
- : SimpleMenuModel(delegate) {
- AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB);
- AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddCheckItemWithStringId(kShowWindowDecorationsCommand,
- IDS_SHOW_WINDOW_DECORATIONS_MENU);
-}

Powered by Google App Engine
This is Rietveld 408576698