172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_titlebar.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gdk/gdkkeysyms.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_piece.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_tokenizer.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/app/chrome_command_ids.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/accelerators_gtk.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/browser_window_gtk.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/custom_button.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(USE_GCONF)
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gconf_titlebar_listener.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/menu_gtk.h"
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/nine_box.h"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h"
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/toolbar/wrench_menu_model.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h"
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h"
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The space above the titlebars.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitlebarHeight = 14;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The thickness in pixels of the tab border.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTabOuterThickness = 1;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Amount to offset the tab images relative to the background.
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kNormalVerticalOffset = kTitlebarHeight + kTabOuterThickness;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A linux specific menu item for toggling window decorations.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kShowWindowDecorationsCommand = 200;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kOTRBottomSpacing = 1;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There are 2 px on each side of the OTR avatar (between the frame border and
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// it on the left, and between it and the tabstrip on the right).
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kOTRSideSpacing = 2;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The thickness of the custom frame border; we need it here to enlarge the
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// close button whent the custom frame border isn't showing but the custom
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// titlebar is showing.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kFrameBorderThickness = 4;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is a 4px gap between the icon and the title text.
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kIconTitleSpacing = 4;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Padding around the icon when in app mode or popup mode.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kAppModePaddingTop = 5;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kAppModePaddingBottom = 4;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kAppModePaddingLeft = 2;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The left padding of the tab strip.  In Views, the tab strip has a left
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// margin of FrameBorderThickness + kClientEdgeThickness.  This offset is to
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// account for kClientEdgeThickness.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTabStripLeftPadding = 1;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Spacing between buttons of the titlebar.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kButtonSpacing = 2;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Spacing around outside of titlebar buttons.
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kButtonOuterPadding = 2;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Spacing between tabstrip and window control buttons (when the window is
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// maximized).
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMaximizedTabstripPadding = 16;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean OnMouseMoveEvent(GtkWidget* widget, GdkEventMotion* event,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          BrowserWindowGtk* browser_window) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset to the default mouse cursor.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_window->ResetCustomFrameCursor();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkPixbuf* GetOTRAvatar() {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static GdkPixbuf* otr_avatar = NULL;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!otr_avatar) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    otr_avatar = rb.GetRTLEnabledPixbufNamed(IDR_OTR_ICON);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return otr_avatar;
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts a GdkColor to a color_utils::HSL.
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochcolor_utils::HSL GdkColorToHSL(const GdkColor* color) {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::HSL hsl;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::SkColorToHSL(SkColorSetRGB(color->red >> 8,
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          color->green >> 8,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          color->blue >> 8), &hsl);
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return hsl;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns either |one| or |two| based on which has a greater difference in
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// luminosity.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkColor PickLuminosityContrastingColor(const GdkColor* base,
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const GdkColor* one,
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const GdkColor* two) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Convert all GdkColors to color_utils::HSLs.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::HSL baseHSL = GdkColorToHSL(base);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::HSL oneHSL = GdkColorToHSL(one);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  color_utils::HSL twoHSL = GdkColorToHSL(two);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double one_difference = fabs(baseHSL.l - oneHSL.l);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double two_difference = fabs(baseHSL.l - twoHSL.l);
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Be biased towards the first color presented.
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (two_difference > one_difference + 0.1)
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *two;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *one;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// PopupPageMenuModel
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A menu model that builds the contents of the menu shown for popups (when the
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// user clicks on the favicon) and all of its submenus.
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass PopupPageMenuModel : public ui::SimpleMenuModel {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  explicit PopupPageMenuModel(ui::SimpleMenuModel::Delegate* delegate,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              Browser* browser);
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~PopupPageMenuModel() { }
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Build();
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Models for submenus referenced by this model. SimpleMenuModel only uses
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // weak references so these must be kept for the lifetime of the top-level
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // model.
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ZoomMenuModel> zoom_menu_model_;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<EncodingMenuModel> encoding_menu_model_;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser_;  // weak
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(PopupPageMenuModel);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPopupPageMenuModel::PopupPageMenuModel(
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ui::SimpleMenuModel::Delegate* delegate,
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* browser)
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : ui::SimpleMenuModel(delegate), browser_(browser) {
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Build();
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PopupPageMenuModel::Build() {
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD);
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSeparator();
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB);
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AddItemWithStringId(IDC_COPY_URL, IDS_APP_MENU_COPY_URL);
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSeparator();
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_CUT, IDS_CUT);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_COPY, IDS_COPY);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_PASTE, IDS_PASTE);
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSeparator();
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_FIND, IDS_FIND);
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_PRINT, IDS_PRINT);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  zoom_menu_model_.reset(new ZoomMenuModel(delegate()));
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU, zoom_menu_model_.get());
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  encoding_menu_model_.reset(new EncodingMenuModel(browser_));
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU,
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         encoding_menu_model_.get());
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AddSeparator();
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserTitlebar
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// static
1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst char BrowserTitlebar::kDefaultButtonString[] = ":minimize,maximize,close";
2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserTitlebar::BrowserTitlebar(BrowserWindowGtk* browser_window,
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 GtkWindow* window)
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : browser_window_(browser_window),
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      window_(window),
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      titlebar_left_buttons_vbox_(NULL),
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      titlebar_right_buttons_vbox_(NULL),
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      titlebar_left_buttons_hbox_(NULL),
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      titlebar_right_buttons_hbox_(NULL),
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      titlebar_left_spy_frame_(NULL),
210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      titlebar_right_spy_frame_(NULL),
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_padding_left_(NULL),
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      top_padding_right_(NULL),
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      app_mode_favicon_(NULL),
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      app_mode_title_(NULL),
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      using_custom_frame_(false),
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      window_has_focus_(false),
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      theme_service_(NULL) {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Init();
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::Init() {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The widget hierarchy is shown below.
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // +- EventBox (container_) ------------------------------------------------+
225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // +- HBox (container_hbox_) -----------------------------------------------+
226513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // |+ VBox ---++- Algn. -++- Alignment --------------++- Algn. -++ VBox ---+|
227513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // || titlebar||titlebar ||   (titlebar_alignment_)  ||titlebar || titlebar||
228513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // || left    ||left     ||                          ||right    || right   ||
229513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // || button  ||spy      ||                          ||spy      || button  ||
230513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // || vbox    ||frame    ||+- TabStripGtk  ---------+||frame    || vbox    ||
231513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // ||         ||         || tab   tab   tabclose    |||         ||         ||
232513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // ||         ||         ||+------------------------+||         ||         ||
233513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // |+---------++---------++--------------------------++---------++---------+|
234513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // +------------------------------------------------------------------------+
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // There are two vboxes on either side of |container_hbox_| because when the
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // desktop is GNOME, the button placement is configurable based on a metacity
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // gconf key. We can't just have one vbox and move it back and forth because
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the gconf language allows you to place buttons on both sides of the
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window.  This being Linux, I'm sure there's a bunch of people who have
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // already configured their window manager to do so and we don't want to get
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // confused when that happens. The actual contents of these vboxes are lazily
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // generated so they don't interfere with alignment when everything is
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // stuffed in the other box.
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Each vbox has the contains the following hierarchy if it contains buttons:
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +- VBox (titlebar_{l,r}_buttons_vbox_) ---------+
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+- Fixed (top_padding_{l,r}_) ----------------+|
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+- HBox (titlebar_{l,r}_buttons_hbox_ ------+||
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||| (buttons of a configurable layout)        |||
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+-------------------------------------------+||
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+---------------------------------------------+|
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +-----------------------------------------------+
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // The two spy alignments are only allocated if this window is an incognito
257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // window. Only one of them holds the spy image.
258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  //
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If we're a popup window or in app mode, we don't display the spy guy or
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the tab strip.  Instead, put an hbox in titlebar_alignment_ in place of
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the tab strip.
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +- Alignment (titlebar_alignment_) -----------------------------------+
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+ HBox -------------------------------------------------------------+|
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+- TabStripGtk -++- Image ----------------++- Label --------------+||
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||| hidden        ++    (app_mode_favicon_) ||    (app_mode_title_) |||
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |||               ||  favicon               ||  page title          |||
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+---------------++------------------------++----------------------+||
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+-------------------------------------------------------------------+|
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +---------------------------------------------------------------------+
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_hbox_ = gtk_hbox_new(FALSE, 0);
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  container_ = gtk_event_box_new();
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_name(container_, "chrome-browser-titlebar");
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_event_box_set_visible_window(GTK_EVENT_BOX(container_), FALSE);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_container_add(GTK_CONTAINER(container_), container_hbox_);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(container_, "scroll-event", G_CALLBACK(OnScrollThunk), this);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(window_, "window-state-event",
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnWindowStateChangedThunk), this);
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Allocate the two button boxes on the left and right parts of the bar, and
283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // spyguy frames in case of incognito mode.
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_left_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_buttons_vbox_,
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     FALSE, FALSE, 0);
287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    titlebar_left_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_widget_set_no_show_all(titlebar_left_spy_frame_, TRUE);
291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_left_spy_frame_), 0,
292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_left_spy_frame_,
294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                       FALSE, FALSE, 0);
295513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
296513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    titlebar_right_spy_frame_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_widget_set_no_show_all(titlebar_right_spy_frame_, TRUE);
298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_right_spy_frame_), 0,
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        kOTRBottomSpacing, kOTRSideSpacing, kOTRSideSpacing);
300513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_spy_frame_,
301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                     FALSE, FALSE, 0);
302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_right_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_end(GTK_BOX(container_hbox_), titlebar_right_buttons_vbox_,
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   FALSE, FALSE, 0);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(USE_GCONF)
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Either read the gconf database and register for updates (on GNOME), or use
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the default value (anywhere else).
31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  GConfTitlebarListener::GetInstance()->SetTitlebarButtons(this);
3114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
3124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BuildButtons(kDefaultButtonString);
3134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use an alignment to control the titlebar height.
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_alignment_ = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       TRUE, 0);
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Put the tab strip in the titlebar.
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_add(GTK_CONTAINER(titlebar_alignment_),
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      browser_window_->tabstrip()->widget());
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // App mode specific widgets.
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(container_hbox_), titlebar_alignment_, TRUE,
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       TRUE, 0);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* app_mode_hbox = gtk_hbox_new(FALSE, kIconTitleSpacing);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_add(GTK_CONTAINER(titlebar_alignment_), app_mode_hbox);
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Put the tab strip in the hbox even though we don't show it.  Sometimes
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // we need the position of the tab strip so make sure it's in our widget
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // hierarchy.
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(app_mode_hbox),
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser_window_->tabstrip()->widget(), FALSE, FALSE, 0);
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* favicon_event_box = gtk_event_box_new();
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_event_box_set_visible_window(GTK_EVENT_BOX(favicon_event_box), FALSE);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_signal_connect(favicon_event_box, "button-press-event",
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     G_CALLBACK(OnButtonPressedThunk), this);
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(app_mode_hbox), favicon_event_box, FALSE,
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       FALSE, 0);
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We use the app logo as a placeholder image so the title doesn't jump
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // around.
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    app_mode_favicon_ = gtk_image_new_from_pixbuf(
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rb.GetRTLEnabledPixbufNamed(IDR_PRODUCT_LOGO_16));
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_object_set_data(G_OBJECT(app_mode_favicon_), "left-align-popup",
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      reinterpret_cast<void*>(true));
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_add(GTK_CONTAINER(favicon_event_box), app_mode_favicon_);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    app_mode_title_ = gtk_label_new(NULL);
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_label_set_ellipsize(GTK_LABEL(app_mode_title_), PANGO_ELLIPSIZE_END);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_misc_set_alignment(GTK_MISC(app_mode_title_), 0.0, 0.5);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(app_mode_hbox), app_mode_title_, TRUE, TRUE,
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       0);
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Register with the theme provider to set the |app_mode_title_| label
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // color.
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    theme_service_ = GtkThemeService::GetFrom(
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser_window_->browser()->profile());
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    theme_service_->InitThemesFor(this);
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UpdateTitleAndIcon();
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(container_);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::ActiveWindowWatcherX::AddObserver(this);
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserTitlebar::~BrowserTitlebar() {
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::ActiveWindowWatcherX::RemoveObserver(this);
3754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(USE_GCONF)
37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  GConfTitlebarListener::GetInstance()->RemoveObserver(this);
3774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::BuildButtons(const std::string& button_string) {
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Clear out all previous data.
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  close_button_.reset();
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  restore_button_.reset();
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  maximize_button_.reset();
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  minimize_button_.reset();
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::RemoveAllChildren(titlebar_left_buttons_vbox_);
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::RemoveAllChildren(titlebar_right_buttons_vbox_);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_left_buttons_hbox_ = NULL;
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  titlebar_right_buttons_hbox_ = NULL;
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top_padding_left_ = NULL;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  top_padding_right_ = NULL;
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool left_side = true;
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StringTokenizer tokenizer(button_string, ":,");
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
396513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int left_count = 0;
397513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  int right_count = 0;
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (tokenizer.GetNext()) {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (tokenizer.token_is_delim()) {
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (*tokenizer.token_begin() == ':')
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        left_side = false;
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::StringPiece token = tokenizer.token_piece();
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (token == "minimize") {
405513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        (left_side ? left_count : right_count)++;
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkWidget* parent_box = GetButtonHBox(left_side);
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        minimize_button_.reset(
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            BuildTitlebarButton(IDR_MINIMIZE, IDR_MINIMIZE_P,
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDR_MINIMIZE_H, parent_box,
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDS_XPFRAME_MINIMIZE_TOOLTIP));
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_widget_size_request(minimize_button_->widget(),
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                &minimize_button_req_);
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (token == "maximize") {
415513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        (left_side ? left_count : right_count)++;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkWidget* parent_box = GetButtonHBox(left_side);
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        restore_button_.reset(
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            BuildTitlebarButton(IDR_RESTORE, IDR_RESTORE_P,
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDR_RESTORE_H, parent_box,
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDS_XPFRAME_RESTORE_TOOLTIP));
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        maximize_button_.reset(
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            BuildTitlebarButton(IDR_MAXIMIZE, IDR_MAXIMIZE_P,
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDR_MAXIMIZE_H, parent_box,
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDS_XPFRAME_MAXIMIZE_TOOLTIP));
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_util::SetButtonClickableByMouseButtons(maximize_button_->widget(),
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                   true, true, true);
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_widget_size_request(restore_button_->widget(),
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                &restore_button_req_);
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (token == "close") {
431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        (left_side ? left_count : right_count)++;
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GtkWidget* parent_box = GetButtonHBox(left_side);
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        close_button_.reset(
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            BuildTitlebarButton(IDR_CLOSE, IDR_CLOSE_P,
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDR_CLOSE_H, parent_box,
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                IDS_XPFRAME_CLOSE_TOOLTIP));
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        close_button_->set_flipped(left_side);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_widget_size_request(close_button_->widget(), &close_button_req_);
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Ignore any other values like "pin" since we don't have images for
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // those.
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
446513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // If we are in incognito mode, add the spy guy to either the end of the left
447513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // or the beginning of the right depending on which side has fewer buttons.
448513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (browser_window_->browser()->profile()->IsOffTheRecord() &&
449513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
450513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    GtkWidget* spy_guy = gtk_image_new_from_pixbuf(GetOTRAvatar());
451513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_misc_set_alignment(GTK_MISC(spy_guy), 0.0, 1.0);
452513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_widget_set_size_request(spy_guy, -1, 0);
453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_widget_show(spy_guy);
454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
455513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    // Remove previous state.
456513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_util::RemoveAllChildren(titlebar_left_spy_frame_);
457513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_util::RemoveAllChildren(titlebar_right_spy_frame_);
458513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
459513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    if (right_count > left_count) {
460513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_container_add(GTK_CONTAINER(titlebar_left_spy_frame_), spy_guy);
461513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_widget_show(titlebar_left_spy_frame_);
462513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_widget_hide(titlebar_right_spy_frame_);
463513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    } else {
464513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_container_add(GTK_CONTAINER(titlebar_right_spy_frame_), spy_guy);
465513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_widget_show(titlebar_right_spy_frame_);
466513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      gtk_widget_hide(titlebar_left_spy_frame_);
467513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    }
468513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
469513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now show the correct widgets in the two hierarchies.
471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (using_custom_frame_) {
472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    gtk_widget_show_all(titlebar_left_buttons_vbox_);
473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    gtk_widget_show_all(titlebar_right_buttons_vbox_);
474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateMaximizeRestoreVisibility();
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (left_side && titlebar_left_buttons_hbox_)
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return titlebar_left_buttons_hbox_;
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else if (!left_side && titlebar_right_buttons_hbox_)
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return titlebar_right_buttons_hbox_;
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We put the min/max/restore/close buttons in a vbox so they are top aligned
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (up to padding) and don't vertically stretch.
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* vbox = left_side ? titlebar_left_buttons_vbox_ :
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    titlebar_right_buttons_vbox_;
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* top_padding = gtk_fixed_new();
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(top_padding, -1, kButtonOuterPadding);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(vbox), top_padding, FALSE, FALSE, 0);
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (left_side) {
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    titlebar_left_buttons_hbox_ = buttons_hbox;
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    top_padding_left_ = top_padding;
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    titlebar_right_buttons_hbox_ = buttons_hbox;
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    top_padding_right_ = top_padding;
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return buttons_hbox;
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawButton* BrowserTitlebar::BuildTitlebarButton(int image,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int image_pressed, int image_hot, GtkWidget* box, int tooltip) {
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CustomDrawButton* button = new CustomDrawButton(image, image_pressed,
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  image_hot, 0);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_add_events(GTK_WIDGET(button->widget()), GDK_POINTER_MOTION_MASK);
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(button->widget(), "clicked",
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnButtonClickedThunk), this);
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(button->widget(), "motion-notify-event",
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnMouseMoveEvent), browser_window_);
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_tooltip_text(button->widget(),
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              localized_tooltip.c_str());
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0);
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return button;
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateCustomFrame(bool use_custom_frame) {
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  using_custom_frame_ = use_custom_frame;
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_custom_frame) {
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_left_buttons_vbox_)
527201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      gtk_widget_show_all(titlebar_left_buttons_vbox_);
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_right_buttons_vbox_)
529201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      gtk_widget_show_all(titlebar_right_buttons_vbox_);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_left_buttons_vbox_)
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(titlebar_left_buttons_vbox_);
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_right_buttons_vbox_)
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(titlebar_right_buttons_vbox_);
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateTitlebarAlignment();
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateTitleAndIcon() {
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!app_mode_title_)
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get the page title and elide it to the available space.
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 title = browser_window_->browser()->GetWindowTitleForCurrentTab();
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_label_set_text(GTK_LABEL(app_mode_title_), UTF16ToUTF8(title).c_str());
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // because we want to exclude Browser::TYPE_APP_POPUP.
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_window_->browser()->type() == Browser::TYPE_APP ||
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Update the system app icon.  We don't need to update the icon in the top
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // left of the custom frame, that will get updated when the throbber is
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // updated.
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (icon.empty()) {
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_util::SetWindowIcon(window_);
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_window_set_icon(window_, icon_pixbuf);
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_object_unref(icon_pixbuf);
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateThrobber(TabContents* tab_contents) {
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(app_mode_favicon_);
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_contents && tab_contents->is_loading()) {
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkPixbuf* icon_pixbuf =
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        throbber_.GetNextFrame(tab_contents->waiting_for_response());
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Note: this isn't browser_window_->browser()->type() & Browser::TYPE_APP
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // because we want to exclude Browser::TYPE_APP_POPUP.
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (browser_window_->browser()->type() == Browser::TYPE_APP ||
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser_window_->browser()->type() == Browser::TYPE_APP_PANEL) {
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkBitmap icon = browser_window_->browser()->GetCurrentPageIcon();
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (icon.empty()) {
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Fallback to the Chromium icon if the page has no icon.
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(&icon);
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_), icon_pixbuf);
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_object_unref(icon_pixbuf);
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_image_set_from_pixbuf(GTK_IMAGE(app_mode_favicon_),
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          rb.GetPixbufNamed(IDR_PRODUCT_LOGO_16));
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    throbber_.Reset();
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateTitlebarAlignment() {
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (browser_window_->browser()->type() == Browser::TYPE_NORMAL) {
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int top_padding = 0;
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int side_padding = 0;
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int vertical_offset = kNormalVerticalOffset;
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (using_custom_frame_) {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!browser_window_->IsMaximized()) {
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        top_padding = kTitlebarHeight;
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else if (using_custom_frame_ && browser_window_->IsMaximized()) {
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        vertical_offset = 0;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        side_padding = kMaximizedTabstripPadding;
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int right_padding = 0;
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int left_padding = kTabStripLeftPadding;
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_right_buttons_hbox_)
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      right_padding = side_padding;
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (titlebar_left_buttons_hbox_)
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      left_padding = side_padding;
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              top_padding, 0,
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              left_padding, right_padding);
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_window_->tabstrip()->SetVerticalOffset(vertical_offset);
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (using_custom_frame_ && !browser_window_->IsFullscreen()) {
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_alignment_set_padding(GTK_ALIGNMENT(titlebar_alignment_),
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          kAppModePaddingTop, kAppModePaddingBottom, kAppModePaddingLeft, 0);
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_show(titlebar_alignment_);
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(titlebar_alignment_);
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Resize the buttons so that the clickable area extends all the way to the
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // edge of the browser window.
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition close_button_req = close_button_req_;
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition minimize_button_req = minimize_button_req_;
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkRequisition restore_button_req = restore_button_req_;
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (using_custom_frame_ && browser_window_->IsMaximized()) {
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button_req.width += kButtonOuterPadding;
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    close_button_req.height += kButtonOuterPadding;
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    minimize_button_req.height += kButtonOuterPadding;
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    restore_button_req.height += kButtonOuterPadding;
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (top_padding_left_)
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(top_padding_left_);
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (top_padding_right_)
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(top_padding_right_);
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (top_padding_left_)
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_show(top_padding_left_);
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (top_padding_right_)
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_show(top_padding_right_);
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (close_button_.get()) {
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(close_button_->widget(),
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                close_button_req.width,
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                close_button_req.height);
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (minimize_button_.get()) {
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(minimize_button_->widget(),
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                minimize_button_req.width,
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                minimize_button_req.height);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (maximize_button_.get()) {
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(restore_button_->widget(),
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                restore_button_req.width,
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                restore_button_req.height);
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateTextColor() {
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!app_mode_title_)
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (theme_service_ && theme_service_->UseGtkTheme()) {
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We don't really have any good options here.
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Colors from window manager themes aren't exposed in GTK; the window
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // manager is a separate component and when there is information sharing
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // (in the case of metacity), it's one way where the window manager reads
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // data from the GTK theme (which allows us to do a decent job with
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // picking the frame color).
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    //
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We probably won't match in the majority of cases, but we can at the
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // very least make things legible. The default metacity and xfwm themes
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // on ubuntu have white text hardcoded. Determine whether black or white
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // has more luminosity contrast and then set that color as the text
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // color.
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkColor frame_color;
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (window_has_focus_) {
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      frame_color = theme_service_->GetGdkColor(
691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ThemeService::COLOR_FRAME);
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      frame_color = theme_service_->GetGdkColor(
694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          ThemeService::COLOR_FRAME_INACTIVE);
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkColor text_color = PickLuminosityContrastingColor(
697513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        &frame_color, &gtk_util::kGdkWhite, &gtk_util::kGdkBlack);
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_util::SetLabelColor(app_mode_title_, &text_color);
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
700513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    gtk_util::SetLabelColor(app_mode_title_, &gtk_util::kGdkWhite);
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::ShowFaviconMenu(GdkEventButton* event) {
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!favicon_menu_model_.get()) {
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicon_menu_model_.reset(
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new PopupPageMenuModel(this, browser_window_->browser()));
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicon_menu_.reset(new MenuGtk(NULL, favicon_menu_model_.get()));
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  favicon_menu_->PopupForWidget(app_mode_favicon_, event->button, event->time);
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::MaximizeButtonClicked() {
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEvent* event = gtk_get_current_event();
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->button.button == 1) {
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_maximize(window_);
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* widget = GTK_WIDGET(window_);
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkScreen* screen = gtk_widget_get_screen(widget);
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint monitor = gdk_screen_get_monitor_at_window(screen, widget->window);
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GdkRectangle screen_rect;
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gdk_screen_get_monitor_geometry(screen, monitor, &screen_rect);
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint x, y;
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_get_position(window_, &x, &y);
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint width = widget->allocation.width;
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gint height = widget->allocation.height;
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (event->button.button == 3) {
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      x = 0;
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      width = screen_rect.width;
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (event->button.button == 2) {
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      y = 0;
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      height = screen_rect.height;
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_window_->SetBounds(gfx::Rect(x, y, width, height));
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_event_free(event);
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::UpdateMaximizeRestoreVisibility() {
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (maximize_button_.get()) {
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (browser_window_->IsMaximized()) {
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(maximize_button_->widget());
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_show(restore_button_->widget());
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_hide(restore_button_->widget());
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_show(maximize_button_->widget());
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserTitlebar::OnWindowStateChanged(GtkWindow* window,
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               GdkEventWindowState* event) {
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateMaximizeRestoreVisibility();
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateTitlebarAlignment();
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateTextColor();
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return FALSE;
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserTitlebar::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabStripModel* tabstrip_model = browser_window_->browser()->tabstrip_model();
766ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int index = tabstrip_model->active_index();
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->direction == GDK_SCROLL_LEFT ||
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      event->direction == GDK_SCROLL_UP) {
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (index != 0)
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tabstrip_model->SelectPreviousTab();
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (index + 1 < tabstrip_model->count()) {
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tabstrip_model->SelectNextTab();
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::OnButtonClicked(GtkWidget* button) {
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (close_button_.get() && close_button_->widget() == button) {
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_window_->Close();
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (restore_button_.get() && restore_button_->widget() == button) {
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_window_->UnMaximize();
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (maximize_button_.get() && maximize_button_->widget() == button) {
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MaximizeButtonClicked();
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (minimize_button_.get() && minimize_button_->widget() == button) {
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_window_iconify(window_);
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BrowserTitlebar::OnButtonPressed(GtkWidget* widget,
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          GdkEventButton* event) {
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (event->button != 1)
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return FALSE;
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowFaviconMenu(event);
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BrowserTitlebar::ShowContextMenu(GdkEventButton* event) {
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!context_menu_.get()) {
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context_menu_model_.reset(new ContextMenuModel(this));
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context_menu_.reset(new MenuGtk(NULL, context_menu_model_.get()));
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  context_menu_->PopupAsContext(gfx::Point(event->x_root, event->y_root),
80672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                event->time);
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserTitlebar::IsCommandIdEnabled(int command_id) const {
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (command_id == kShowWindowDecorationsCommand)
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return browser_window_->browser()->command_updater()->
814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IsCommandEnabled(command_id);
815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserTitlebar::IsCommandIdChecked(int command_id) const {
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (command_id == kShowWindowDecorationsCommand) {
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return !prefs->GetBoolean(prefs::kUseCustomChromeFrame);
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EncodingMenuController controller;
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (controller.DoesCommandBelongToEncodingMenu(command_id)) {
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabContents* tab_contents =
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser_window_->browser()->GetSelectedTabContents();
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (tab_contents) {
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return controller.IsItemChecked(browser_window_->browser()->profile(),
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      tab_contents->encoding(),
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      command_id);
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NOTREACHED();
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::ExecuteCommand(int command_id) {
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (command_id == kShowWindowDecorationsCommand) {
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    PrefService* prefs = browser_window_->browser()->profile()->GetPrefs();
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    prefs->SetBoolean(prefs::kUseCustomChromeFrame,
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  !prefs->GetBoolean(prefs::kUseCustomChromeFrame));
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_window_->browser()->ExecuteCommand(command_id);
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserTitlebar::GetAcceleratorForCommandId(
85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int command_id, ui::Accelerator* accelerator) {
85272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const ui::AcceleratorGtk* accelerator_gtk =
85321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      AcceleratorsGtk::GetInstance()->GetPrimaryAcceleratorForCommand(
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          command_id);
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (accelerator_gtk)
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *accelerator = *accelerator_gtk;
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return accelerator_gtk;
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::Observe(NotificationType type,
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              const NotificationSource& source,
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              const NotificationDetails& details) {
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type.value) {
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::BROWSER_THEME_CHANGED:
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UpdateTextColor();
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::ActiveWindowChanged(GdkWindow* active_window) {
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Can be called during shutdown; BrowserWindowGtk will set our |window_|
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to NULL during that time.
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window_)
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  window_has_focus_ = GTK_WIDGET(window_)->window == active_window;
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateTextColor();
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BrowserTitlebar::Throbber implementation
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(tc): Handle anti-clockwise spinning when waiting for a connection.
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We don't bother to clean up these or the pixbufs they contain when we exit.
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::vector<GdkPixbuf*>* g_throbber_frames = NULL;
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::vector<GdkPixbuf*>* g_throbber_waiting_frames = NULL;
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Load |resource_id| from the ResourceBundle and split it into a series of
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// square GdkPixbufs that get stored in |frames|.
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void MakeThrobberFrames(int resource_id,
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               std::vector<GdkPixbuf*>* frames) {
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ResourceBundle &rb = ResourceBundle::GetSharedInstance();
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap* frame_strip = rb.GetBitmapNamed(resource_id);
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Each frame of the animation is a square, so we use the height as the
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // frame size.
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int frame_size = frame_strip->height();
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t num_frames = frame_strip->width() / frame_size;
902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a separate GdkPixbuf for each frame of the animation.
904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < num_frames; ++i) {
905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkBitmap frame = SkBitmapOperations::CreateTiledBitmap(*frame_strip,
906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        i * frame_size, 0, frame_size, frame_size);
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    frames->push_back(gfx::GdkPixbufFromSkBitmap(&frame));
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGdkPixbuf* BrowserTitlebar::Throbber::GetNextFrame(bool is_waiting) {
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Throbber::InitFrames();
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (is_waiting) {
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (*g_throbber_waiting_frames)[current_waiting_frame_++ %
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_throbber_waiting_frames->size()];
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return (*g_throbber_frames)[current_frame_++ % g_throbber_frames->size()];
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::Throbber::Reset() {
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_frame_ = 0;
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  current_waiting_frame_ = 0;
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserTitlebar::Throbber::InitFrames() {
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (g_throbber_frames)
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We load the light version of the throbber since it'll be in the titlebar.
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_throbber_frames = new std::vector<GdkPixbuf*>;
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MakeThrobberFrames(IDR_THROBBER_LIGHT, g_throbber_frames);
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_throbber_waiting_frames = new std::vector<GdkPixbuf*>;
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MakeThrobberFrames(IDR_THROBBER_WAITING_LIGHT, g_throbber_waiting_frames);
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserTitlebar::ContextMenuModel::ContextMenuModel(
94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ui::SimpleMenuModel::Delegate* delegate)
941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : SimpleMenuModel(delegate) {
942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_NEW_TAB, IDS_TAB_CXMENU_NEWTAB);
943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSeparator();
945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddSeparator();
947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddCheckItemWithStringId(kShowWindowDecorationsCommand,
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           IDS_SHOW_WINDOW_DECORATIONS_MENU);
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
950