summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-05 22:27:26 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-05 22:27:26 +0000
commitfcbbd1fdf87fee30fca225b5bfb2ae7d52227058 (patch)
tree29f70359c1a5b1474c758f31b82567ca9936c57c
parentaaa70a4e4256fc2c96ce550b773ff00e5cd99e30 (diff)
downloadchromium_src-fcbbd1fdf87fee30fca225b5bfb2ae7d52227058.zip
chromium_src-fcbbd1fdf87fee30fca225b5bfb2ae7d52227058.tar.gz
chromium_src-fcbbd1fdf87fee30fca225b5bfb2ae7d52227058.tar.bz2
Change the visual appearance of panel on GTK per new UI design.
In order not to add more panel specific stuff to BrowserTitlebar, I decided to put all titlebar painting and handling logic in PanelBrowserTitlebarGtk. This is also needed for the ongoing effort to strip out the BrowserWindow dependency from panel implementation. I also moved throbber logic out of BrowserTitlebar into a separate class so that the code can be shared between BrowserTitlebar and PanelBrowserTitlebarGtk. BUG=none TEST=existing tests Review URL: https://chromiumcodereview.appspot.com/10483010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140636 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/gtk/browser_titlebar.cc102
-rw-r--r--chrome/browser/ui/gtk/browser_titlebar.h120
-rw-r--r--chrome/browser/ui/gtk/browser_titlebar_base.h50
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc8
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.h49
-rw-r--r--chrome/browser/ui/gtk/titlebar_throb_animation.cc71
-rw-r--r--chrome/browser/ui/gtk/titlebar_throb_animation.h37
-rw-r--r--chrome/browser/ui/panels/detached_panel_browsertest.cc8
-rw-r--r--chrome/browser/ui/panels/native_panel.h8
-rw-r--r--chrome/browser/ui/panels/panel_browser_titlebar_gtk.cc353
-rw-r--r--chrome/browser/ui/panels/panel_browser_titlebar_gtk.h102
-rw-r--r--chrome/browser/ui/panels/panel_browser_view.cc11
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_cocoa.mm11
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_gtk.cc234
-rw-r--r--chrome/browser/ui/panels/panel_browser_window_gtk.h23
-rw-r--r--chrome/browser/ui/panels/panel_browsertest.cc31
-rw-r--r--chrome/browser/ui/panels/panel_constants.h7
-rw-r--r--chrome/chrome_browser.gypi7
18 files changed, 748 insertions, 484 deletions
diff --git a/chrome/browser/ui/gtk/browser_titlebar.cc b/chrome/browser/ui/gtk/browser_titlebar.cc
index 06596f1..cea3903 100644
--- a/chrome/browser/ui/gtk/browser_titlebar.cc
+++ b/chrome/browser/ui/gtk/browser_titlebar.cc
@@ -56,7 +56,6 @@
#include "ui/base/x/active_window_watcher_x.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/skbitmap_operations.h"
using content::WebContents;
@@ -477,10 +476,10 @@ GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
titlebar_right_buttons_vbox_;
GtkWidget* top_padding = gtk_fixed_new();
- gtk_widget_set_size_request(top_padding, -1, GetButtonOuterPadding());
+ 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, GetButtonSpacing());
+ GtkWidget* buttons_hbox = gtk_hbox_new(FALSE, kButtonSpacing);
gtk_box_pack_start(GTK_BOX(vbox), buttons_hbox, FALSE, FALSE, 0);
if (left_side) {
@@ -494,14 +493,6 @@ GtkWidget* BrowserTitlebar::GetButtonHBox(bool left_side) {
return buttons_hbox;
}
-int BrowserTitlebar::GetButtonOuterPadding() const {
- return kButtonOuterPadding;
-}
-
-int BrowserTitlebar::GetButtonSpacing() const {
- return kButtonSpacing;
-}
-
CustomDrawButton* BrowserTitlebar::CreateTitlebarButton(
const std::string& button_name, bool left_side) {
int normal_image_id;
@@ -707,10 +698,10 @@ void BrowserTitlebar::UpdateTitlebarAlignment() {
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 += GetButtonOuterPadding();
- close_button_req.height += GetButtonOuterPadding();
- minimize_button_req.height += GetButtonOuterPadding();
- restore_button_req.height += GetButtonOuterPadding();
+ 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_)
@@ -837,17 +828,6 @@ void BrowserTitlebar::UpdateAvatar() {
avatar_button_->set_menu_arrow_location(arrow_location);
}
-void BrowserTitlebar::ShowFaviconMenu(GdkEventButton* event) {
- 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);
-}
-
void BrowserTitlebar::MaximizeButtonClicked() {
GdkEvent* event = gtk_get_current_event();
if (event->button.button == 1) {
@@ -915,10 +895,6 @@ gboolean BrowserTitlebar::OnScroll(GtkWidget* widget, GdkEventScroll* event) {
}
void BrowserTitlebar::OnButtonClicked(GtkWidget* button) {
- HandleButtonClick(button);
-}
-
-void BrowserTitlebar::HandleButtonClick(GtkWidget* button) {
if (close_button_.get() && close_button_->widget() == button) {
browser_window_->Close();
} else if (restore_button_.get() && restore_button_->widget() == button) {
@@ -935,7 +911,15 @@ gboolean BrowserTitlebar::OnFaviconMenuButtonPressed(GtkWidget* widget,
if (event->button != 1)
return FALSE;
- ShowFaviconMenu(event);
+ 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;
}
@@ -1053,60 +1037,16 @@ bool BrowserTitlebar::IsOffTheRecord() {
return browser_window_->browser()->profile()->IsOffTheRecord();
}
-///////////////////////////////////////////////////////////////////////////////
-// BrowserTitlebar::Throbber implementation
-// TODO(tc): Handle anti-clockwise spinning when waiting for a connection.
-
-// We don't bother to clean up these or the pixbufs they contain when we exit.
-static std::vector<GdkPixbuf*>* g_throbber_frames = NULL;
-static std::vector<GdkPixbuf*>* g_throbber_waiting_frames = NULL;
-
-// Load |resource_id| from the ResourceBundle and split it into a series of
-// square GdkPixbufs that get stored in |frames|.
-static void MakeThrobberFrames(int resource_id,
- std::vector<GdkPixbuf*>* frames) {
- ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance();
- SkBitmap* frame_strip = rb.GetBitmapNamed(resource_id);
-
- // Each frame of the animation is a square, so we use the height as the
- // frame size.
- int frame_size = frame_strip->height();
- size_t num_frames = frame_strip->width() / frame_size;
-
- // Make a separate GdkPixbuf for each frame of the animation.
- for (size_t i = 0; i < num_frames; ++i) {
- SkBitmap frame = SkBitmapOperations::CreateTiledBitmap(*frame_strip,
- i * frame_size, 0, frame_size, frame_size);
- frames->push_back(gfx::GdkPixbufFromSkBitmap(frame));
- }
+GtkWidget* BrowserTitlebar::widget() const {
+ return container_;
}
-GdkPixbuf* BrowserTitlebar::Throbber::GetNextFrame(bool is_waiting) {
- Throbber::InitFrames();
- if (is_waiting) {
- return (*g_throbber_waiting_frames)[current_waiting_frame_++ %
- g_throbber_waiting_frames->size()];
- } else {
- return (*g_throbber_frames)[current_frame_++ % g_throbber_frames->size()];
- }
-}
-
-void BrowserTitlebar::Throbber::Reset() {
- current_frame_ = 0;
- current_waiting_frame_ = 0;
+void BrowserTitlebar::set_window(GtkWindow* window) {
+ window_ = window;
}
-// static
-void BrowserTitlebar::Throbber::InitFrames() {
- if (g_throbber_frames)
- return;
-
- // We load the light version of the throbber since it'll be in the titlebar.
- g_throbber_frames = new std::vector<GdkPixbuf*>;
- MakeThrobberFrames(IDR_THROBBER_LIGHT, g_throbber_frames);
-
- g_throbber_waiting_frames = new std::vector<GdkPixbuf*>;
- MakeThrobberFrames(IDR_THROBBER_WAITING_LIGHT, g_throbber_waiting_frames);
+AvatarMenuButtonGtk* BrowserTitlebar::avatar_button() const {
+ return avatar_button_.get();
}
BrowserTitlebar::ContextMenuModel::ContextMenuModel(
diff --git a/chrome/browser/ui/gtk/browser_titlebar.h b/chrome/browser/ui/gtk/browser_titlebar.h
index 0ed05f0..2ffeb88 100644
--- a/chrome/browser/ui/gtk/browser_titlebar.h
+++ b/chrome/browser/ui/gtk/browser_titlebar.h
@@ -16,6 +16,8 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/ui/gtk/browser_titlebar_base.h"
+#include "chrome/browser/ui/gtk/titlebar_throb_animation.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/base/gtk/gtk_signal.h"
@@ -33,7 +35,8 @@ namespace content {
class WebContents;
}
-class BrowserTitlebar : public content::NotificationObserver,
+class BrowserTitlebar : public BrowserTitlebarBase,
+ public content::NotificationObserver,
public ui::ActiveWindowWatcherXObserver,
public ui::SimpleMenuModel::Delegate {
public:
@@ -44,71 +47,36 @@ class BrowserTitlebar : public content::NotificationObserver,
BrowserTitlebar(BrowserWindowGtk* browser_window, GtkWindow* window);
virtual ~BrowserTitlebar();
- // Updates the theme supplied background color and image.
- virtual void UpdateButtonBackground(CustomDrawButton* button);
-
- // Updates the title and icon when in app or popup/panel mode (no tabstrip).
- virtual void UpdateTitleAndIcon();
-
- GtkWidget* widget() {
- return container_;
- }
-
- void set_window(GtkWindow* window) { window_ = window; }
-
- // Build the titlebar, the space above the tab strip, and (maybe) the min,
- // max, close buttons. |container_| is the gtk container that we put the
- // widget into.
- void Init();
-
// Builds the buttons based on the metacity |button_string|.
void BuildButtons(const std::string& button_string);
- // Update the appearance of the title bar based on whether we're showing a
- // custom frame or not. If |use_custom_frame| is true, we show an extra
- // tall titlebar and the min/max/close buttons.
- void UpdateCustomFrame(bool use_custom_frame);
-
- // Called by the browser asking us to update the loading throbber.
- // |web_contents| is the tab that is associated with the window throbber.
- // |web_contents| can be null.
- void UpdateThrobber(content::WebContents* web_contents);
+ // Overriden from BrowserTitlebarBase.
+ virtual void Init() OVERRIDE;
+ virtual void UpdateTitleAndIcon() OVERRIDE;
+ virtual void UpdateCustomFrame(bool use_custom_frame) OVERRIDE;
+ virtual void UpdateThrobber(content::WebContents* web_contents) OVERRIDE;
+ virtual void ShowContextMenu(GdkEventButton* event) OVERRIDE;
+ virtual GtkWidget* widget() const OVERRIDE;
+ virtual void set_window(GtkWindow* window) OVERRIDE;
+ virtual AvatarMenuButtonGtk* avatar_button() const OVERRIDE;
- // On Windows, right clicking in the titlebar background brings up the system
- // menu. There's no such thing on linux, so we just show the menu items we
- // add to the menu.
- void ShowContextMenu(GdkEventButton* event);
-
- AvatarMenuButtonGtk* avatar_button() { return avatar_button_.get(); }
+ private:
+ class ContextMenuModel : public ui::SimpleMenuModel {
+ public:
+ explicit ContextMenuModel(ui::SimpleMenuModel::Delegate* delegate);
+ };
- protected:
// Builds the button as denoted by |button_token|. Returns true if the button
// is created successfully.
- virtual bool BuildButton(const std::string& button_token, bool left_side);
+ bool BuildButton(const std::string& button_token, bool left_side);
// Retrieves the 3 image ids (IDR_) and a tooltip id (IDS) for the purpose of
// painting a CustomDraw button.
- virtual void GetButtonResources(const std::string& button_name,
- int* normal_image_id,
- int* pressed_image_id,
- int* hover_image_id,
- int* tooltip_id) const;
-
- // Returns the spacing around outside of titlebar buttons.
- virtual int GetButtonOuterPadding() const;
-
- // Returns the spacing between buttons of the titlebar.
- virtual int GetButtonSpacing() const;
-
- // Called when a button is clicked.
- virtual void HandleButtonClick(GtkWidget* button);
-
- // Show the menu that the user gets from left-clicking the favicon.
- virtual void ShowFaviconMenu(GdkEventButton* event);
-
- // Updates the color of the title bar. Called whenever we have a state
- // change in the window.
- virtual void UpdateTextColor();
+ void GetButtonResources(const std::string& button_name,
+ int* normal_image_id,
+ int* pressed_image_id,
+ int* hover_image_id,
+ int* tooltip_id) const;
// Constructs a CustomDraw button given button name and left or right side of
// the titlebar where the button is placed.
@@ -121,40 +89,12 @@ class BrowserTitlebar : public content::NotificationObserver,
// settings to get absolutely horrid combinations of buttons on both sides.
GtkWidget* GetButtonHBox(bool left_side);
- CustomDrawButton* minimize_button() const { return minimize_button_.get(); }
- CustomDrawButton* maximize_button() const { return maximize_button_.get(); }
- CustomDrawButton* restore_button() const { return restore_button_.get(); }
- CustomDrawButton* close_button() const { return close_button_.get(); }
- GtkWidget* app_mode_title() const { return app_mode_title_; }
-
- GtkThemeService* theme_service() const { return theme_service_; }
-
- private:
- // A helper class to keep track of which frame of the throbber animation
- // we're showing.
- class Throbber {
- public:
- Throbber() : current_frame_(0), current_waiting_frame_(0) {}
-
- // Get the next frame in the animation. The image is owned by the throbber
- // so the caller doesn't need to unref. |is_waiting| is true if we're
- // still waiting for a response.
- GdkPixbuf* GetNextFrame(bool is_waiting);
-
- // Reset back to the first frame.
- void Reset();
- private:
- // Make sure the frames are loaded.
- static void InitFrames();
-
- int current_frame_;
- int current_waiting_frame_;
- };
+ // Updates the theme supplied background color and image.
+ void UpdateButtonBackground(CustomDrawButton* button);
- class ContextMenuModel : public ui::SimpleMenuModel {
- public:
- explicit ContextMenuModel(ui::SimpleMenuModel::Delegate* delegate);
- };
+ // Updates the color of the title bar. Called whenever we have a state
+ // change in the window.
+ void UpdateTextColor();
// Update the titlebar spacing based on the custom frame and maximized state.
void UpdateTitlebarAlignment();
@@ -287,7 +227,7 @@ class BrowserTitlebar : public content::NotificationObserver,
scoped_ptr<PopupPageMenuModel> favicon_menu_model_;
// The throbber used when the window is in app mode or popup window mode.
- Throbber throbber_;
+ TitlebarThrobAnimation throbber_;
// The avatar button.
scoped_ptr<AvatarMenuButtonGtk> avatar_button_;
diff --git a/chrome/browser/ui/gtk/browser_titlebar_base.h b/chrome/browser/ui/gtk/browser_titlebar_base.h
new file mode 100644
index 0000000..f8c8843
--- /dev/null
+++ b/chrome/browser/ui/gtk/browser_titlebar_base.h
@@ -0,0 +1,50 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_BASE_H_
+#define CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_BASE_H_
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "base/compiler_specific.h"
+
+class AvatarMenuButtonGtk;
+
+namespace content {
+class WebContents;
+}
+
+class BrowserTitlebarBase {
+ public:
+ virtual ~BrowserTitlebarBase() { }
+
+ // Build the titlebar, the space above the tab strip, and (maybe) the min,
+ // max, close buttons.
+ virtual void Init() = 0;
+
+ // Updates the title and icon when in app or popup/panel mode (no tabstrip).
+ virtual void UpdateTitleAndIcon() = 0;
+
+ // Update the appearance of the title bar based on whether we're showing a
+ // custom frame or not. If |use_custom_frame| is true, we show an extra
+ // tall titlebar and the min/max/close buttons.
+ virtual void UpdateCustomFrame(bool use_custom_frame) = 0;
+
+ // Called by the browser asking us to update the loading throbber.
+ // |web_contents| is the tab that is associated with the window throbber.
+ // |web_contents| can be null.
+ virtual void UpdateThrobber(content::WebContents* web_contents) = 0;
+
+ // On Windows, right clicking in the titlebar background brings up the system
+ // menu. There's no such thing on linux, so we just show the menu items we
+ // add to the menu.
+ virtual void ShowContextMenu(GdkEventButton* event) = 0;
+
+ virtual GtkWidget* widget() const = 0;
+ virtual void set_window(GtkWindow* window) = 0;
+ virtual AvatarMenuButtonGtk* avatar_button() const = 0;
+};
+
+#endif // CHROME_BROWSER_UI_GTK_BROWSER_TITLEBAR_BASE_H_
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index 76e5af1..3a1c75f 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -437,7 +437,11 @@ void BrowserWindowGtk::Init() {
gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
GdkEventExpose* event) {
TRACE_EVENT0("ui::gtk", "BrowserWindowGtk::OnCustomFrameExpose");
+ DrawFrame(widget, event);
+ return FALSE; // Allow subwidgets to paint.
+}
+void BrowserWindowGtk::DrawFrame(GtkWidget* widget, GdkEventExpose* event) {
// Draw the default background.
cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
gdk_cairo_rectangle(cr, &event->area);
@@ -455,8 +459,6 @@ gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget,
if (UseCustomFrame() && !IsMaximized())
DrawCustomFrameBorder(widget);
-
- return FALSE; // Allow subwidgets to paint.
}
void BrowserWindowGtk::DrawCustomFrameBorder(GtkWidget* widget) {
@@ -2476,7 +2478,7 @@ bool BrowserWindowGtk::UsingCustomPopupFrame() const {
return !theme_provider->UsingNativeTheme() && browser()->is_type_popup();
}
-BrowserTitlebar* BrowserWindowGtk::CreateBrowserTitlebar() {
+BrowserTitlebarBase* BrowserWindowGtk::CreateBrowserTitlebar() {
return new BrowserTitlebar(this, window_);
}
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
index 7a89a51..b16b4a7 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.h
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -27,7 +27,7 @@
class BookmarkBarGtk;
class Browser;
-class BrowserTitlebar;
+class BrowserTitlebarBase;
class BrowserToolbarGtk;
class DownloadShelfGtk;
class ExtensionKeybindingRegistryGtk;
@@ -61,11 +61,6 @@ class BrowserWindowGtk : public BrowserWindow,
// functions during initialization.
virtual void Init();
- // Returns whether to draw the content drop shadow on the sides and bottom
- // of the browser window. When false, we still draw a shadow on the top of
- // the toolbar (under the tab strip), but do not round the top corners.
- virtual bool ShouldDrawContentDropShadow() const;
-
// Overridden from BrowserWindow:
virtual void Show() OVERRIDE;
virtual void ShowInactive() OVERRIDE;
@@ -217,6 +212,11 @@ class BrowserWindowGtk : public BrowserWindow,
// onbeforeunload handler that prevents us from closing.
bool CanClose() const;
+ // Returns whether to draw the content drop shadow on the sides and bottom
+ // of the browser window. When false, we still draw a shadow on the top of
+ // the toolbar (under the tab strip), but do not round the top corners.
+ bool ShouldDrawContentDropShadow() const;
+
bool ShouldShowWindowIcon() const;
// Add the find bar widget to the window hierarchy.
@@ -238,7 +238,7 @@ class BrowserWindowGtk : public BrowserWindow,
GtkWindow* window() const { return window_; }
- BrowserTitlebar* titlebar() const { return titlebar_.get(); }
+ BrowserTitlebarBase* titlebar() const { return titlebar_.get(); }
GtkWidget* titlebar_widget() const;
@@ -263,8 +263,8 @@ class BrowserWindowGtk : public BrowserWindow,
protected:
virtual void DestroyBrowser() OVERRIDE;
- // Returns an instance of |BrowserTitlebar| to be used for this window.
- virtual BrowserTitlebar* CreateBrowserTitlebar();
+ // Returns an instance of |BrowserTitlebarBase| to be used for this window.
+ virtual BrowserTitlebarBase* CreateBrowserTitlebar();
// Checks to see if the mouse pointer at |x|, |y| is over the border of the
// custom frame (a spot that should trigger a window resize). Returns true if
@@ -276,8 +276,8 @@ class BrowserWindowGtk : public BrowserWindow,
// returned.
virtual GdkRegion* GetWindowShape(int width, int height) const;
- // Draws the border, including resizable corners, for the custom frame.
- virtual void DrawCustomFrameBorder(GtkWidget* widget);
+ // Draws the frame, including background, border and drop shadow.
+ virtual void DrawFrame(GtkWidget* widget, GdkEventExpose* event);
virtual bool HandleTitleBarLeftMousePress(GdkEventButton* event,
guint32 last_click_time,
@@ -298,21 +298,9 @@ class BrowserWindowGtk : public BrowserWindow,
// Returns |true| if we should use the custom frame.
virtual bool UseCustomFrame() const;
- // Whether we should draw the tab background instead of the theme_frame
- // background because this window is a popup.
- virtual bool UsingCustomPopupFrame() const;
-
// Called when the window size changed.
virtual void OnSizeChanged(int width, int height);
- // Draws the normal custom frame using theme_frame.
- virtual void DrawCustomFrame(cairo_t* cr, GtkWidget* widget,
- GdkEventExpose* event);
-
- // Draws the tab image as the frame so we can write legible text.
- virtual void DrawPopupFrame(cairo_t* cr, GtkWidget* widget,
- GdkEventExpose* event);
-
// 'focus-in-event' handler.
virtual void HandleFocusIn(GtkWidget* widget, GdkEventFocus* event);
@@ -362,6 +350,19 @@ class BrowserWindowGtk : public BrowserWindow,
// ctrl-l, etc.).
void ConnectAccelerators();
+ // Whether we should draw the tab background instead of the theme_frame
+ // background because this window is a popup.
+ bool UsingCustomPopupFrame() const;
+
+ // Draws the normal custom frame using theme_frame.
+ void DrawCustomFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
+
+ // Draws the tab image as the frame so we can write legible text.
+ void DrawPopupFrame(cairo_t* cr, GtkWidget* widget, GdkEventExpose* event);
+
+ // Draws the border, including resizable corners, for the custom frame.
+ void DrawCustomFrameBorder(GtkWidget* widget);
+
// Change whether we're showing the custom blue frame.
// Must be called once at startup.
// Triggers relayout of the content.
@@ -488,7 +489,7 @@ class BrowserWindowGtk : public BrowserWindow,
scoped_ptr<GlobalMenuBar> global_menu_bar_;
// The container for the titlebar + tab strip.
- scoped_ptr<BrowserTitlebar> titlebar_;
+ scoped_ptr<BrowserTitlebarBase> titlebar_;
// The object that manages all of the widgets in the toolbar.
scoped_ptr<BrowserToolbarGtk> toolbar_;
diff --git a/chrome/browser/ui/gtk/titlebar_throb_animation.cc b/chrome/browser/ui/gtk/titlebar_throb_animation.cc
new file mode 100644
index 0000000..4b90974
--- /dev/null
+++ b/chrome/browser/ui/gtk/titlebar_throb_animation.cc
@@ -0,0 +1,71 @@
+// 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/titlebar_throb_animation.h"
+#include "grit/theme_resources.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/skbitmap_operations.h"
+
+namespace {
+
+// We don't bother to clean up these or the pixbufs they contain when we exit.
+std::vector<GdkPixbuf*>* g_throbber_frames = NULL;
+std::vector<GdkPixbuf*>* g_throbber_waiting_frames = NULL;
+
+// Load |resource_id| from the ResourceBundle and split it into a series of
+// square GdkPixbufs that get stored in |frames|.
+void MakeThrobberFrames(int resource_id, std::vector<GdkPixbuf*>* frames) {
+ ui::ResourceBundle &rb = ui::ResourceBundle::GetSharedInstance();
+ SkBitmap* frame_strip = rb.GetBitmapNamed(resource_id);
+
+ // Each frame of the animation is a square, so we use the height as the
+ // frame size.
+ int frame_size = frame_strip->height();
+ size_t num_frames = frame_strip->width() / frame_size;
+
+ // Make a separate GdkPixbuf for each frame of the animation.
+ for (size_t i = 0; i < num_frames; ++i) {
+ SkBitmap frame = SkBitmapOperations::CreateTiledBitmap(*frame_strip,
+ i * frame_size, 0, frame_size, frame_size);
+ frames->push_back(gfx::GdkPixbufFromSkBitmap(frame));
+ }
+}
+
+} // namespace
+
+// TODO(tc): Handle anti-clockwise spinning when waiting for a connection.
+
+TitlebarThrobAnimation::TitlebarThrobAnimation()
+ : current_frame_(0),
+ current_waiting_frame_(0) {
+}
+
+GdkPixbuf* TitlebarThrobAnimation::GetNextFrame(bool is_waiting) {
+ InitFrames();
+ if (is_waiting) {
+ return (*g_throbber_waiting_frames)[current_waiting_frame_++ %
+ g_throbber_waiting_frames->size()];
+ } else {
+ return (*g_throbber_frames)[current_frame_++ % g_throbber_frames->size()];
+ }
+}
+
+void TitlebarThrobAnimation::Reset() {
+ current_frame_ = 0;
+ current_waiting_frame_ = 0;
+}
+
+// static
+void TitlebarThrobAnimation::InitFrames() {
+ if (g_throbber_frames)
+ return;
+
+ // We load the light version of the throbber since it'll be in the titlebar.
+ g_throbber_frames = new std::vector<GdkPixbuf*>;
+ MakeThrobberFrames(IDR_THROBBER_LIGHT, g_throbber_frames);
+
+ g_throbber_waiting_frames = new std::vector<GdkPixbuf*>;
+ MakeThrobberFrames(IDR_THROBBER_WAITING_LIGHT, g_throbber_waiting_frames);
+}
diff --git a/chrome/browser/ui/gtk/titlebar_throb_animation.h b/chrome/browser/ui/gtk/titlebar_throb_animation.h
new file mode 100644
index 0000000..8540d02
--- /dev/null
+++ b/chrome/browser/ui/gtk/titlebar_throb_animation.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef CHROME_BROWSER_UI_GTK_TITLEBAR_THROB_ANIMATION_H_
+#define CHROME_BROWSER_UI_GTK_TITLEBAR_THROB_ANIMATION_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ui/gfx/gtk_util.h"
+
+// A helper class to keep track of which frame of the throbber animation
+// we're showing.
+class TitlebarThrobAnimation {
+ public:
+ TitlebarThrobAnimation();
+
+ // Get the next frame in the animation. The image is owned by the throbber
+ // so the caller doesn't need to unref. |is_waiting| is true if we're
+ // still waiting for a response.
+ GdkPixbuf* GetNextFrame(bool is_waiting);
+
+ // Reset back to the first frame.
+ void Reset();
+
+ private:
+ // Make sure the frames are loaded.
+ static void InitFrames();
+
+ int current_frame_;
+ int current_waiting_frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(TitlebarThrobAnimation);
+};
+
+#endif // CHROME_BROWSER_UI_GTK_TITLEBAR_THROB_ANIMATION_H_
diff --git a/chrome/browser/ui/panels/detached_panel_browsertest.cc b/chrome/browser/ui/panels/detached_panel_browsertest.cc
index e84d269..feec61f 100644
--- a/chrome/browser/ui/panels/detached_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/detached_panel_browsertest.cc
@@ -25,11 +25,9 @@ IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, CheckDetachedPanelProperties) {
EXPECT_FALSE(panel->always_on_top());
- EXPECT_TRUE(panel_testing->IsButtonVisible(NativePanelTesting::CLOSE_BUTTON));
- EXPECT_FALSE(panel_testing->IsButtonVisible(
- NativePanelTesting::MINIMIZE_BUTTON));
- EXPECT_FALSE(panel_testing->IsButtonVisible(
- NativePanelTesting::RESTORE_BUTTON));
+ EXPECT_TRUE(panel_testing->IsButtonVisible(panel::CLOSE_BUTTON));
+ EXPECT_FALSE(panel_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+ EXPECT_FALSE(panel_testing->IsButtonVisible(panel::RESTORE_BUTTON));
EXPECT_EQ(panel::RESIZABLE_ALL_SIDES, panel->CanResizeByMouse());
diff --git a/chrome/browser/ui/panels/native_panel.h b/chrome/browser/ui/panels/native_panel.h
index 61d1ff9..527fbba 100644
--- a/chrome/browser/ui/panels/native_panel.h
+++ b/chrome/browser/ui/panels/native_panel.h
@@ -101,12 +101,6 @@ class NativePanel {
// native panel used only by test automation.
class NativePanelTesting {
public:
- enum TitlebarButtonType {
- CLOSE_BUTTON,
- MINIMIZE_BUTTON,
- RESTORE_BUTTON
- };
-
static NativePanelTesting* Create(NativePanel* native_panel);
virtual ~NativePanelTesting() {}
@@ -136,7 +130,7 @@ class NativePanelTesting {
virtual bool IsWindowSizeKnown() const = 0;
virtual bool IsAnimatingBounds() const = 0;
- virtual bool IsButtonVisible(TitlebarButtonType button_type) const = 0;
+ virtual bool IsButtonVisible(panel::TitlebarButtonType button_type) const = 0;
};
#endif // CHROME_BROWSER_UI_PANELS_NATIVE_PANEL_H_
diff --git a/chrome/browser/ui/panels/panel_browser_titlebar_gtk.cc b/chrome/browser/ui/panels/panel_browser_titlebar_gtk.cc
index 83b8e20..1962037 100644
--- a/chrome/browser/ui/panels/panel_browser_titlebar_gtk.cc
+++ b/chrome/browser/ui/panels/panel_browser_titlebar_gtk.cc
@@ -9,149 +9,270 @@
#include "chrome/browser/ui/gtk/custom_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
+#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_window_gtk.h"
+#include "chrome/common/chrome_notification_types.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 "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/gtk/gtk_compat.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/skia_utils_gtk.h"
namespace {
-// Spacing between buttons of panel's titlebar.
-const int kPanelButtonSpacing = 7;
-
-// Spacing around outside of panel's titlebar buttons.
-const int kPanelButtonOuterPadding = 7;
+// Padding around the titlebar.
+const int kPanelTitlebarPaddingTop = 7;
+const int kPanelTitlebarPaddingBottom = 7;
+const int kPanelTitlebarPaddingLeft = 4;
+const int kPanelTitlebarPaddingRight = 9;
-// Markup for painting title as bold.
-const char* const kTitleMarkupPrefix = "<span font_weight='bold'>";
-const char* const kTitleMarkupSuffix = "</span>";
+// Spacing between buttons of panel's titlebar.
+const int kPanelButtonSpacing = 9;
-// Colors used to draw title in attention mode.
-const SkColor kAttentionTitleTextDefaultColor = SK_ColorWHITE;
+// Spacing between the icon and the title text.
+const int kPanelIconTitleSpacing = 9;
-// Alpha value used in drawing inactive titlebar under non-default theme.
-const U8CPU kInactiveAlphaBlending = 0x80;
+// Color used to draw title text under default theme.
+const SkColor kTitleTextDefaultColor = SkColorSetRGB(0xf9, 0xf9, 0xf9);
-SkColor BlendSkColorWithAlpha(SkColor fg_color, SkColor bg_color, U8CPU alpha) {
- if (alpha == 255)
- return fg_color;
- double fg_ratio = alpha / 255.0;
- double bg_ratio = 1.0 - fg_ratio;
- return SkColorSetRGB(
- (SkColorGetR(fg_color) * fg_ratio + SkColorGetR(bg_color) * bg_ratio),
- (SkColorGetG(fg_color) * fg_ratio + SkColorGetG(bg_color) * bg_ratio),
- (SkColorGetB(fg_color) * fg_ratio + SkColorGetB(bg_color) * bg_ratio));
-}
+// Markup used to paint the title with the desired font.
+const char* const kTitleMarkupPrefix = "<span face='Arial' size='11264'>";
+const char* const kTitleMarkupSuffix = "</span>";
} // namespace
PanelBrowserTitlebarGtk::PanelBrowserTitlebarGtk(
PanelBrowserWindowGtk* browser_window, GtkWindow* window)
- : BrowserTitlebar(browser_window, window),
- browser_window_(browser_window) {
+ : browser_window_(browser_window),
+ window_(window),
+ container_(NULL),
+ titlebar_right_buttons_vbox_(NULL),
+ titlebar_right_buttons_hbox_(NULL),
+ icon_(NULL),
+ title_(NULL),
+ theme_service_(NULL) {
}
PanelBrowserTitlebarGtk::~PanelBrowserTitlebarGtk() {
}
+void PanelBrowserTitlebarGtk::Init() {
+ container_ = gtk_event_box_new();
+ gtk_widget_set_name(container_, "chrome-panel-titlebar");
+ gtk_event_box_set_visible_window(GTK_EVENT_BOX(container_), FALSE);
+
+ // We use an alignment to control the titlebar paddings.
+ GtkWidget* container_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0);
+ gtk_container_add(GTK_CONTAINER(container_), container_alignment);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(container_alignment),
+ kPanelTitlebarPaddingTop,
+ kPanelTitlebarPaddingBottom,
+ kPanelTitlebarPaddingLeft,
+ kPanelTitlebarPaddingRight);
+
+ // Add a container box.
+ GtkWidget* container_hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(container_alignment), container_hbox);
+
+ g_signal_connect(window_, "window-state-event",
+ G_CALLBACK(OnWindowStateChangedThunk), this);
+
+ // Add minimize/restore and close buttons. Panel buttons are always placed
+ // on the right part of the titlebar.
+ titlebar_right_buttons_vbox_ = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(container_hbox), titlebar_right_buttons_vbox_,
+ FALSE, FALSE, 0);
+ BuildButtons();
+
+ // Add hbox for holding icon and title.
+ GtkWidget* icon_title_hbox = gtk_hbox_new(FALSE, kPanelIconTitleSpacing);
+ gtk_box_pack_start(GTK_BOX(container_hbox), icon_title_hbox, TRUE, TRUE, 0);
+
+ // Add icon. We use the app logo as a placeholder image so the title doesn't
+ // jump around.
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ icon_ = gtk_image_new_from_pixbuf(rb.GetNativeImageNamed(
+ IDR_PRODUCT_LOGO_16, ui::ResourceBundle::RTL_ENABLED).ToGdkPixbuf());
+ g_object_set_data(G_OBJECT(icon_), "left-align-popup",
+ reinterpret_cast<void*>(true));
+ gtk_box_pack_start(GTK_BOX(icon_title_hbox), icon_, FALSE, FALSE, 0);
+
+ // Add title.
+ title_ = gtk_label_new(NULL);
+ gtk_label_set_ellipsize(GTK_LABEL(title_), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment(GTK_MISC(title_), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(icon_title_hbox), title_, TRUE, TRUE, 0);
+
+ UpdateTitleAndIcon();
+
+ theme_service_ = GtkThemeService::GetFrom(
+ browser_window_->panel()->profile());
+ registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
+ content::Source<ThemeService>(theme_service_));
+ theme_service_->InitThemesFor(this);
+
+ gtk_widget_show_all(container_);
+}
+
SkColor PanelBrowserTitlebarGtk::GetTextColor() const {
- PanelBrowserWindowGtk::PaintState paint_state =
- browser_window_->GetPaintState();
- if (paint_state == PanelBrowserWindowGtk::PAINT_FOR_ATTENTION)
- return kAttentionTitleTextDefaultColor;
+ if (browser_window_->UsingDefaultTheme())
+ return kTitleTextDefaultColor;
+ return theme_service_->GetColor(browser_window_->paint_state() ==
+ PanelBrowserWindowGtk::PAINT_AS_ACTIVE ?
+ ThemeService::COLOR_TAB_TEXT :
+ ThemeService::COLOR_BACKGROUND_TAB_TEXT);
+}
- return paint_state == PanelBrowserWindowGtk::PAINT_AS_ACTIVE ?
- theme_service()->GetColor(ThemeService::COLOR_TAB_TEXT) :
- BlendSkColorWithAlpha(
- theme_service()->GetColor(ThemeService::COLOR_BACKGROUND_TAB_TEXT),
- theme_service()->GetColor(ThemeService::COLOR_TOOLBAR),
- kInactiveAlphaBlending);
+void PanelBrowserTitlebarGtk::BuildButtons() {
+ minimize_button_.reset(CreateButton(panel::MINIMIZE_BUTTON));
+ restore_button_.reset(CreateButton(panel::RESTORE_BUTTON));
+ close_button_.reset(CreateButton(panel::CLOSE_BUTTON));
+
+ // We control visibility of minimize and restore buttons.
+ gtk_widget_set_no_show_all(minimize_button_->widget(), TRUE);
+ gtk_widget_set_no_show_all(restore_button_->widget(), TRUE);
+
+ // Now show the correct widgets in the two hierarchies.
+ UpdateMinimizeRestoreButtonVisibility();
}
-void PanelBrowserTitlebarGtk::UpdateButtonBackground(CustomDrawButton* button) {
- // Don't need to update background since we're using transparent background.
+CustomDrawButton* PanelBrowserTitlebarGtk::CreateButton(
+ panel::TitlebarButtonType button_type) {
+ int normal_image_id;
+ int pressed_image_id;
+ int hover_image_id;
+ int tooltip_id;
+ GetButtonResources(button_type, &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);
+
+ std::string localized_tooltip = l10n_util::GetStringUTF8(tooltip_id);
+ gtk_widget_set_tooltip_text(button->widget(),
+ localized_tooltip.c_str());
+
+ GtkWidget* box = GetButtonHBox();
+ gtk_box_pack_start(GTK_BOX(box), button->widget(), FALSE, FALSE, 0);
+ return button;
}
-void PanelBrowserTitlebarGtk::UpdateTitleAndIcon() {
- DCHECK(app_mode_title());
+void PanelBrowserTitlebarGtk::GetButtonResources(
+ panel::TitlebarButtonType button_type,
+ int* normal_image_id,
+ int* pressed_image_id,
+ int* hover_image_id,
+ int* tooltip_id) const {
+ switch (button_type) {
+ case panel::CLOSE_BUTTON:
+ *normal_image_id = IDR_PANEL_CLOSE;
+ *pressed_image_id = IDR_PANEL_CLOSE_C;
+ *hover_image_id = IDR_PANEL_CLOSE_H;
+ *tooltip_id = IDS_PANEL_CLOSE_TOOLTIP;
+ break;
+ case panel::MINIMIZE_BUTTON:
+ *normal_image_id = IDR_PANEL_MINIMIZE;
+ *pressed_image_id = IDR_PANEL_MINIMIZE_C;
+ *hover_image_id = IDR_PANEL_MINIMIZE_H;
+ *tooltip_id = IDS_PANEL_MINIMIZE_TOOLTIP;
+ break;
+ case panel::RESTORE_BUTTON:
+ *normal_image_id = IDR_PANEL_RESTORE;
+ *pressed_image_id = IDR_PANEL_RESTORE_C;
+ *hover_image_id = IDR_PANEL_RESTORE_H;
+ *tooltip_id = IDS_PANEL_RESTORE_TOOLTIP;
+ break;
+ }
+}
- std::string title = UTF16ToUTF8(browser_window_->panel()->GetWindowTitle());
+GtkWidget* PanelBrowserTitlebarGtk::GetButtonHBox() {
+ if (!titlebar_right_buttons_hbox_) {
+ // We put the minimize/restore/close buttons in a vbox so they are top
+ // aligned (up to padding) and don't vertically stretch.
+ titlebar_right_buttons_hbox_ = gtk_hbox_new(FALSE, kPanelButtonSpacing);
+ gtk_box_pack_start(GTK_BOX(titlebar_right_buttons_vbox_),
+ titlebar_right_buttons_hbox_, FALSE, FALSE, 0);
+ }
- // Add the markup to show the title as bold.
- gchar* escaped_title = g_markup_escape_text(title.c_str(), -1);
- gchar* title_with_markup = g_strconcat(kTitleMarkupPrefix,
- escaped_title,
- kTitleMarkupSuffix,
- NULL);
- gtk_label_set_markup(GTK_LABEL(app_mode_title()), title_with_markup);
- g_free(escaped_title);
- g_free(title_with_markup);
+ return titlebar_right_buttons_hbox_;
}
-bool PanelBrowserTitlebarGtk::BuildButton(const std::string& button_token,
- bool left_side) {
- // Panel only shows close and minimize/restore buttons.
- if (button_token != "close" && button_token != "minimize")
- return false;
-
- if (!BrowserTitlebar::BuildButton(button_token, left_side))
- return false;
+void PanelBrowserTitlebarGtk::UpdateCustomFrame(bool use_custom_frame) {
+ // Nothing to do.
+}
- if (button_token == "minimize") {
- // Create unminimze button, used to expand the minimized panel.
- unminimize_button_.reset(CreateTitlebarButton("unminimize", left_side));
+void PanelBrowserTitlebarGtk::UpdateTitleAndIcon() {
+ std::string title_text =
+ UTF16ToUTF8(browser_window_->panel()->GetWindowTitle());
+
+ // Add the markup to show the title in the desired font.
+ gchar* escaped_title_text = g_markup_escape_text(title_text.c_str(), -1);
+ gchar* title_text_with_markup = g_strconcat(kTitleMarkupPrefix,
+ escaped_title_text,
+ kTitleMarkupSuffix,
+ NULL);
+ gtk_label_set_markup(GTK_LABEL(title_), title_text_with_markup);
+ g_free(escaped_title_text);
+ g_free(title_text_with_markup);
+}
- // We control visibility of minimize and unminimize buttons.
- gtk_widget_set_no_show_all(minimize_button()->widget(), TRUE);
- gtk_widget_set_no_show_all(unminimize_button_->widget(), TRUE);
- }
- return true;
-}
-
-void PanelBrowserTitlebarGtk::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_PANEL_CLOSE;
- *pressed_image_id = 0;
- *hover_image_id = IDR_PANEL_CLOSE_H;
- *tooltip_id = IDS_PANEL_CLOSE_TOOLTIP;
- } else if (button_name == "minimize") {
- *normal_image_id = IDR_PANEL_MINIMIZE;
- *pressed_image_id = 0;
- *hover_image_id = IDR_PANEL_MINIMIZE_H;
- *tooltip_id = IDS_PANEL_MINIMIZE_TOOLTIP;
- } else if (button_name == "unminimize") {
- *normal_image_id = IDR_PANEL_RESTORE;
- *pressed_image_id = 0;
- *hover_image_id = IDR_PANEL_RESTORE_H;
- *tooltip_id = IDS_PANEL_RESTORE_TOOLTIP;
+void PanelBrowserTitlebarGtk::UpdateThrobber(
+ content::WebContents* web_contents) {
+ if (web_contents && web_contents->IsLoading()) {
+ GdkPixbuf* icon_pixbuf =
+ throbber_.GetNextFrame(web_contents->IsWaitingForResponse());
+ gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), icon_pixbuf);
+ } else {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+
+ SkBitmap icon = browser_window_->panel()->GetCurrentPageIcon();
+ if (icon.empty()) {
+ // Fallback to the Chromium icon if the page has no icon.
+ gtk_image_set_from_pixbuf(GTK_IMAGE(icon_),
+ rb.GetNativeImageNamed(IDR_PRODUCT_LOGO_16).ToGdkPixbuf());
+ } else {
+ GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(icon);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(icon_), icon_pixbuf);
+ g_object_unref(icon_pixbuf);
+ }
+
+ throbber_.Reset();
}
}
-int PanelBrowserTitlebarGtk::GetButtonOuterPadding() const {
- return kPanelButtonOuterPadding;
+void PanelBrowserTitlebarGtk::ShowContextMenu(GdkEventButton* event) {
+ // Panel does not show any context menu.
}
-int PanelBrowserTitlebarGtk::GetButtonSpacing() const {
- return kPanelButtonSpacing;
+void PanelBrowserTitlebarGtk::UpdateTextColor() {
+ GdkColor text_color = gfx::SkColorToGdkColor(GetTextColor());
+ gtk_util::SetLabelColor(title_, &text_color);
}
void PanelBrowserTitlebarGtk::UpdateMinimizeRestoreButtonVisibility() {
- if (!unminimize_button_.get() || !minimize_button())
- return;
-
Panel* panel = browser_window_->panel();
- gtk_widget_set_visible(minimize_button()->widget(), panel->CanMinimize());
- gtk_widget_set_visible(unminimize_button_->widget(), panel->CanRestore());
+ gtk_widget_set_visible(minimize_button_->widget(), panel->CanMinimize());
+ gtk_widget_set_visible(restore_button_->widget(), panel->CanRestore());
}
-void PanelBrowserTitlebarGtk::HandleButtonClick(GtkWidget* button) {
- if (close_button() && close_button()->widget() == button) {
+gboolean PanelBrowserTitlebarGtk::OnWindowStateChanged(
+ GtkWindow* window, GdkEventWindowState* event) {
+ UpdateTextColor();
+ return FALSE;
+}
+
+void PanelBrowserTitlebarGtk::OnButtonClicked(GtkWidget* button) {
+ if (close_button_->widget() == button) {
browser_window_->panel()->Close();
return;
}
@@ -159,12 +280,11 @@ void PanelBrowserTitlebarGtk::HandleButtonClick(GtkWidget* button) {
GdkEvent* event = gtk_get_current_event();
DCHECK(event && event->type == GDK_BUTTON_RELEASE);
- if (minimize_button() && minimize_button()->widget() == button) {
+ if (minimize_button_->widget() == button) {
browser_window_->panel()->OnMinimizeButtonClicked(
(event->button.state & GDK_CONTROL_MASK) ?
panel::APPLY_TO_ALL : panel::NO_MODIFIER);
- } else if (unminimize_button_.get() &&
- unminimize_button_->widget() == button) {
+ } else if (restore_button_->widget() == button) {
browser_window_->panel()->OnRestoreButtonClicked(
(event->button.state & GDK_CONTROL_MASK) ?
panel::APPLY_TO_ALL : panel::NO_MODIFIER);
@@ -173,15 +293,17 @@ void PanelBrowserTitlebarGtk::HandleButtonClick(GtkWidget* button) {
gdk_event_free(event);
}
-void PanelBrowserTitlebarGtk::ShowFaviconMenu(GdkEventButton* event) {
- // Favicon menu is not supported in panels.
-}
-
-void PanelBrowserTitlebarGtk::UpdateTextColor() {
- DCHECK(app_mode_title());
-
- GdkColor text_color = gfx::SkColorToGdkColor(GetTextColor());
- gtk_util::SetLabelColor(app_mode_title(), &text_color);
+void PanelBrowserTitlebarGtk::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_BROWSER_THEME_CHANGED:
+ UpdateTextColor();
+ break;
+ default:
+ NOTREACHED();
+ }
}
void PanelBrowserTitlebarGtk::SendEnterNotifyToCloseButtonIfUnderMouse() {
@@ -224,3 +346,16 @@ void PanelBrowserTitlebarGtk::SendEnterNotifyToCloseButtonIfUnderMouse() {
"enter-notify-event", event,
&return_value);
}
+
+GtkWidget* PanelBrowserTitlebarGtk::widget() const {
+ return container_;
+}
+
+void PanelBrowserTitlebarGtk::set_window(GtkWindow* window) {
+ window_ = window;
+}
+
+AvatarMenuButtonGtk* PanelBrowserTitlebarGtk::avatar_button() const {
+ // Not supported in panel.
+ return NULL;
+}
diff --git a/chrome/browser/ui/panels/panel_browser_titlebar_gtk.h b/chrome/browser/ui/panels/panel_browser_titlebar_gtk.h
index feaa725..954d762 100644
--- a/chrome/browser/ui/panels/panel_browser_titlebar_gtk.h
+++ b/chrome/browser/ui/panels/panel_browser_titlebar_gtk.h
@@ -5,17 +5,34 @@
#ifndef CHROME_BROWSER_UI_PANELS_PANEL_BROWSER_TITLEBAR_GTK_H_
#define CHROME_BROWSER_UI_PANELS_PANEL_BROWSER_TITLEBAR_GTK_H_
-#include "chrome/browser/ui/gtk/browser_titlebar.h"
+#include <gtk/gtk.h>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/gtk/browser_titlebar_base.h"
+#include "chrome/browser/ui/gtk/titlebar_throb_animation.h"
+#include "chrome/browser/ui/panels/panel_constants.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "ui/base/gtk/gtk_signal.h"
#include "ui/gfx/skia_util.h"
+class CustomDrawButton;
+class GtkThemeService;
class PanelBrowserWindowGtk;
-class PanelBrowserTitlebarGtk : public BrowserTitlebar {
+namespace content {
+class WebContents;
+}
+
+class PanelBrowserTitlebarGtk : public BrowserTitlebarBase,
+ public content::NotificationObserver {
public:
PanelBrowserTitlebarGtk(PanelBrowserWindowGtk* browser_window,
GtkWindow* window);
virtual ~PanelBrowserTitlebarGtk();
+ void UpdateTextColor();
void UpdateMinimizeRestoreButtonVisibility();
// When a panel appears in the same position as the one of the panel being
@@ -30,41 +47,72 @@ class PanelBrowserTitlebarGtk : public BrowserTitlebar {
// https://bugzilla.gnome.org/show_bug.cgi?id=667841
void SendEnterNotifyToCloseButtonIfUnderMouse();
- // Overridden from BrowserTitlebar:
- virtual void UpdateButtonBackground(CustomDrawButton* button) OVERRIDE;
+ // Overriden from BrowserTitlebarBase.
+ virtual void Init() OVERRIDE;
virtual void UpdateTitleAndIcon() OVERRIDE;
- virtual void UpdateTextColor() OVERRIDE;
-
- protected:
- // Overridden from BrowserTitlebar:
- virtual bool BuildButton(const std::string& button_token,
- bool left_side) OVERRIDE;
- virtual void GetButtonResources(const std::string& button_name,
- int* normal_image_id,
- int* pressed_image_id,
- int* hover_image_id,
- int* tooltip_id) const OVERRIDE;
- virtual int GetButtonOuterPadding() const OVERRIDE;
- virtual int GetButtonSpacing() const OVERRIDE;
- virtual void HandleButtonClick(GtkWidget* button) OVERRIDE;
- virtual void ShowFaviconMenu(GdkEventButton* event) OVERRIDE;
+ virtual void UpdateCustomFrame(bool use_custom_frame) OVERRIDE;
+ virtual void UpdateThrobber(content::WebContents* web_contents) OVERRIDE;
+ virtual void ShowContextMenu(GdkEventButton* event) OVERRIDE;
+ virtual GtkWidget* widget() const OVERRIDE;
+ virtual void set_window(GtkWindow* window) OVERRIDE;
+ virtual AvatarMenuButtonGtk* avatar_button() const OVERRIDE;
private:
friend class NativePanelTestingGtk;
- CustomDrawButton* unminimize_button() const {
- return unminimize_button_.get();
- }
+ // Overridden from content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ void BuildButtons();
+ CustomDrawButton* CreateButton(panel::TitlebarButtonType button_type);
+ void GetButtonResources(panel::TitlebarButtonType button_type,
+ int* normal_image_id,
+ int* pressed_image_id,
+ int* hover_image_id,
+ int* tooltip_id) const;
+ GtkWidget* GetButtonHBox();
+
+ // Callback for changes to window state. This includes minimizing/restoring
+ // the window.
+ CHROMEG_CALLBACK_1(PanelBrowserTitlebarGtk, gboolean, OnWindowStateChanged,
+ GtkWindow*, GdkEventWindowState*);
+
+ // Callback for minimize/restore/close buttons.
+ CHROMEGTK_CALLBACK_0(PanelBrowserTitlebarGtk, void, OnButtonClicked);
+
+ CustomDrawButton* close_button() const { return close_button_.get(); }
+ CustomDrawButton* minimize_button() const { return minimize_button_.get(); }
+ CustomDrawButton* restore_button() const { return restore_button_.get(); }
SkColor GetTextColor() const;
+ // Pointers to the browser window that owns us and its GtkWindow.
PanelBrowserWindowGtk* browser_window_;
+ GtkWindow* window_;
+
+ // The container widget the holds the hbox which contains the whole titlebar.
+ GtkWidget* container_;
+
+ // VBoxes that holds the minimize/restore/close buttons box.
+ GtkWidget* titlebar_right_buttons_vbox_;
+
+ // HBoxes that contains the actual min/max/close buttons.
+ GtkWidget* titlebar_right_buttons_hbox_;
+
+ // The icon and page title.
+ GtkWidget* icon_;
+ GtkWidget* title_;
+
+ // The buttons.
+ scoped_ptr<CustomDrawButton> close_button_;
+ scoped_ptr<CustomDrawButton> minimize_button_;
+ scoped_ptr<CustomDrawButton> restore_button_;
- // All other buttons, including close and minimize buttons, are defined in
- // the base class BrowserTitlebar. This is indeed our restore button. But
- // we name it differently to avoid the confusion with restore_button defined
- // in the base class and used for unmaximize purpose.
- scoped_ptr<CustomDrawButton> unminimize_button_;
+ TitlebarThrobAnimation throbber_;
+ GtkThemeService* theme_service_;
+ content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(PanelBrowserTitlebarGtk);
};
diff --git a/chrome/browser/ui/panels/panel_browser_view.cc b/chrome/browser/ui/panels/panel_browser_view.cc
index e063b96..5d0631b 100644
--- a/chrome/browser/ui/panels/panel_browser_view.cc
+++ b/chrome/browser/ui/panels/panel_browser_view.cc
@@ -630,7 +630,8 @@ class NativePanelTestingWin : public NativePanelTesting {
virtual bool VerifyActiveState(bool is_active) OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
- virtual bool IsButtonVisible(TitlebarButtonType button_type) const OVERRIDE;
+ virtual bool IsButtonVisible(
+ panel::TitlebarButtonType button_type) const OVERRIDE;
PanelBrowserView* panel_browser_view_;
};
@@ -690,15 +691,15 @@ bool NativePanelTestingWin::IsAnimatingBounds() const {
}
bool NativePanelTestingWin::IsButtonVisible(
- TitlebarButtonType button_type) const {
+ panel::TitlebarButtonType button_type) const {
PanelBrowserFrameView* frame_view = panel_browser_view_->GetFrameView();
switch (button_type) {
- case CLOSE_BUTTON:
+ case panel::CLOSE_BUTTON:
return frame_view->close_button_->visible();
- case MINIMIZE_BUTTON:
+ case panel::MINIMIZE_BUTTON:
return frame_view->minimize_button_->visible();
- case RESTORE_BUTTON:
+ case panel::RESTORE_BUTTON:
return frame_view->restore_button_->visible();
default:
NOTREACHED();
diff --git a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
index e9ceeed..0483825 100644
--- a/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
+++ b/chrome/browser/ui/panels/panel_browser_window_cocoa.mm
@@ -364,7 +364,8 @@ class NativePanelTestingCocoa : public NativePanelTesting {
virtual bool VerifyActiveState(bool is_active) OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
- virtual bool IsButtonVisible(TitlebarButtonType button_type) const OVERRIDE;
+ virtual bool IsButtonVisible(
+ panel::TitlebarButtonType button_type) const OVERRIDE;
private:
PanelTitlebarViewCocoa* titlebar() const;
@@ -438,13 +439,13 @@ bool NativePanelTestingCocoa::IsAnimatingBounds() const {
}
bool NativePanelTestingCocoa::IsButtonVisible(
- TitlebarButtonType button_type) const {
+ panel::TitlebarButtonType button_type) const {
switch (button_type) {
- case CLOSE_BUTTON:
+ case panel::CLOSE_BUTTON:
return ![[titlebar() closeButton] isHidden];
- case MINIMIZE_BUTTON:
+ case panel::MINIMIZE_BUTTON:
return ![[titlebar() minimizeButton] isHidden];
- case RESTORE_BUTTON:
+ case panel::RESTORE_BUTTON:
return ![[titlebar() restoreButton] isHidden];
default:
NOTREACHED();
diff --git a/chrome/browser/ui/panels/panel_browser_window_gtk.cc b/chrome/browser/ui/panels/panel_browser_window_gtk.cc
index ca21de9..dd74253 100644
--- a/chrome/browser/ui/panels/panel_browser_window_gtk.cc
+++ b/chrome/browser/ui/panels/panel_browser_window_gtk.cc
@@ -11,10 +11,10 @@
#include "chrome/browser/ui/gtk/browser_titlebar.h"
#include "chrome/browser/ui/gtk/custom_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
-#include "chrome/browser/ui/gtk/nine_box.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_bounds_animation.h"
#include "chrome/browser/ui/panels/panel_browser_titlebar_gtk.h"
+#include "chrome/browser/ui/panels/panel_constants.h"
#include "chrome/browser/ui/panels/panel_drag_gtk.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel_strip.h"
@@ -23,49 +23,61 @@
#include "content/public/browser/notification_service.h"
#include "grit/theme_resources_standard.h"
#include "grit/ui_resources.h"
-#include "third_party/skia/include/core/SkShader.h"
+#include "ui/base/gtk/gtk_compat.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/cairo_cached_surface.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/skia_util.h"
using content::NativeWebKeyboardEvent;
using content::WebContents;
namespace {
-// Colors used to draw titlebar and frame for drawing attention under default
-// theme. It is also used in non-default theme since attention color is not
-// defined in the theme.
-const SkColor kAttentionBackgroundColorStart = SkColorSetRGB(0xff, 0xab, 0x57);
-const SkColor kAttentionBackgroundColorEnd = SkColorSetRGB(0xe6, 0x9a, 0x4e);
+// Colors used to draw frame background under default theme.
+const SkColor kActiveBackgroundDefaultColor = SkColorSetRGB(0x3a, 0x3c, 0x3c);
+const SkColor kInactiveBackgroundDefaultColor = SkColorSetRGB(0x7a, 0x7c, 0x7c);
+const SkColor kAttentionBackgroundDefaultColor =
+ SkColorSetRGB(0xff, 0xab, 0x57);
+const SkColor kMinimizeBackgroundDefaultColor = SkColorSetRGB(0xf5, 0xf4, 0xf0);
+const SkColor kMinimizeBorderDefaultColor = SkColorSetRGB(0xc9, 0xc9, 0xc9);
+
+// Color used to draw the divider line between the titlebar and the client area.
+const SkColor kDividerColor = SkColorSetRGB(0x5a, 0x5c, 0x5c);
// Set minimium width for window really small.
const int kMinWindowWidth = 26;
-gfx::Image* CreateGradientImage(SkColor start_color, SkColor end_color) {
- // Though the height of titlebar, used for creating gradient, cannot be
- // pre-determined, we use a reasonably bigger value that is obtained from
- // the experimentation and should work for most cases.
- const int gradient_size = 32;
- SkShader* shader = gfx::CreateGradientShader(
- 0, gradient_size, start_color, end_color);
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setAntiAlias(true);
- paint.setShader(shader);
- shader->unref();
- gfx::Canvas canvas(gfx::Size(1, gradient_size), true);
- canvas.DrawRect(gfx::Rect(0, 0, 1, gradient_size), paint);
+gfx::Image* CreateImageForColor(SkColor color) {
+ gfx::Canvas canvas(gfx::Size(1, 1), true);
+ canvas.DrawColor(color);
return new gfx::Image(canvas.ExtractBitmap());
}
-gfx::Image* GetAttentionBackgroundImage() {
+const gfx::Image* GetActiveBackgroundDefaultImage() {
static gfx::Image* image = NULL;
- if (!image) {
- image = CreateGradientImage(kAttentionBackgroundColorStart,
- kAttentionBackgroundColorEnd);
- }
+ if (!image)
+ image = CreateImageForColor(kActiveBackgroundDefaultColor);
+ return image;
+}
+
+const gfx::Image* GetInactiveBackgroundDefaultImage() {
+ static gfx::Image* image = NULL;
+ if (!image)
+ image = CreateImageForColor(kInactiveBackgroundDefaultColor);
+ return image;
+}
+
+const gfx::Image* GetAttentionBackgroundDefaultImage() {
+ static gfx::Image* image = NULL;
+ if (!image)
+ image = CreateImageForColor(kAttentionBackgroundDefaultColor);
+ return image;
+}
+
+const gfx::Image* GetMinimizeBackgroundDefaultImage() {
+ static gfx::Image* image = NULL;
+ if (!image)
+ image = CreateImageForColor(kMinimizeBackgroundDefaultColor);
return image;
}
@@ -85,6 +97,7 @@ PanelBrowserWindowGtk::PanelBrowserWindowGtk(Browser* browser,
: BrowserWindowGtk(browser),
panel_(panel),
bounds_(bounds),
+ paint_state_(PAINT_AS_INACTIVE),
is_drawing_attention_(false) {
}
@@ -116,11 +129,7 @@ void PanelBrowserWindowGtk::Init() {
content::Source<GtkWindow>(window()));
}
-bool PanelBrowserWindowGtk::ShouldDrawContentDropShadow() const {
- return !panel_->IsMinimized();
-}
-
-BrowserTitlebar* PanelBrowserWindowGtk::CreateBrowserTitlebar() {
+BrowserTitlebarBase* PanelBrowserWindowGtk::CreateBrowserTitlebar() {
return new PanelBrowserTitlebarGtk(this, window());
}
@@ -128,10 +137,13 @@ PanelBrowserTitlebarGtk* PanelBrowserWindowGtk::GetPanelTitlebar() const {
return static_cast<PanelBrowserTitlebarGtk*>(titlebar());
}
-PanelBrowserWindowGtk::PaintState PanelBrowserWindowGtk::GetPaintState() const {
- if (is_drawing_attention_)
- return PAINT_FOR_ATTENTION;
- return IsActive() ? PAINT_AS_ACTIVE : PAINT_AS_INACTIVE;
+bool PanelBrowserWindowGtk::UsingDefaultTheme() const {
+ // No theme is provided for attention painting.
+ if (paint_state_ == PAINT_FOR_ATTENTION)
+ return true;
+
+ GtkThemeService* theme_provider = GtkThemeService::GetFrom(panel_->profile());
+ return theme_provider->UsingDefaultTheme();
}
bool PanelBrowserWindowGtk::GetWindowEdge(int x, int y, GdkWindowEdge* edge) {
@@ -171,20 +183,70 @@ GdkRegion* PanelBrowserWindowGtk::GetWindowShape(int width, int height) const {
return mask;
}
-void PanelBrowserWindowGtk::DrawCustomFrameBorder(GtkWidget* widget) {
- static NineBox* custom_frame_border = NULL;
- if (!custom_frame_border) {
- custom_frame_border = new NineBox(IDR_WINDOW_TOP_LEFT_CORNER,
- IDR_WINDOW_TOP_CENTER,
- IDR_WINDOW_TOP_RIGHT_CORNER,
- IDR_WINDOW_LEFT_SIDE,
- 0,
- IDR_WINDOW_RIGHT_SIDE,
- IDR_PANEL_BOTTOM_LEFT_CORNER,
- IDR_WINDOW_BOTTOM_CENTER,
- IDR_PANEL_BOTTOM_RIGHT_CORNER);
+bool PanelBrowserWindowGtk::UseCustomFrame() const {
+ // We always use custom frame for panels.
+ return true;
+}
+
+void PanelBrowserWindowGtk::DrawFrame(GtkWidget* widget,
+ GdkEventExpose* event) {
+ cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
+ gdk_cairo_rectangle(cr, &event->area);
+ cairo_clip(cr);
+
+ // Update the painting state.
+ int window_height = gdk_window_get_height(gtk_widget_get_window(widget));
+ if (is_drawing_attention_)
+ paint_state_ = PAINT_FOR_ATTENTION;
+ else if (window_height <= panel::kMinimizedPanelHeight)
+ paint_state_ = PAINT_AS_MINIMIZED;
+ else if (IsActive())
+ paint_state_ = PAINT_AS_ACTIVE;
+ else
+ paint_state_ = PAINT_AS_INACTIVE;
+
+ // Draw the background.
+ gfx::CairoCachedSurface* surface = GetFrameBackground()->ToCairo();
+ surface->SetSource(cr, widget, 0, 0);
+ cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
+ cairo_rectangle(cr, event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_fill(cr);
+
+ // Draw the divider only if we're showing more than titlebar.
+ if (window_height > panel::kTitlebarHeight) {
+ cairo_set_source_rgb(cr,
+ SkColorGetR(kDividerColor) / 255.0,
+ SkColorGetG(kDividerColor) / 255.0,
+ SkColorGetB(kDividerColor) / 255.0);
+ cairo_rectangle(cr, 0, panel::kTitlebarHeight - 1, bounds_.width(), 1);
+ cairo_fill(cr);
}
- custom_frame_border->RenderToWidget(widget);
+
+ // Draw the border for the minimized panel only.
+ if (paint_state_ == PAINT_AS_MINIMIZED) {
+ cairo_move_to(cr, 0, 3);
+ cairo_line_to(cr, 1, 2);
+ cairo_line_to(cr, 1, 1);
+ cairo_line_to(cr, 2, 1);
+ cairo_line_to(cr, 3, 0);
+ cairo_line_to(cr, event->area.width - 3, 0);
+ cairo_line_to(cr, event->area.width - 2, 1);
+ cairo_line_to(cr, event->area.width - 1, 1);
+ cairo_line_to(cr, event->area.width - 1, 2);
+ cairo_line_to(cr, event->area.width - 1, 3);
+ cairo_line_to(cr, event->area.width - 1, event->area.height - 1);
+ cairo_line_to(cr, 0, event->area.height - 1);
+ cairo_close_path(cr);
+ cairo_set_source_rgb(cr,
+ SkColorGetR(kMinimizeBorderDefaultColor) / 255.0,
+ SkColorGetG(kMinimizeBorderDefaultColor) / 255.0,
+ SkColorGetB(kMinimizeBorderDefaultColor) / 255.0);
+ cairo_set_line_width(cr, 1.0);
+ cairo_stroke(cr);
+ }
+
+ cairo_destroy(cr);
}
void PanelBrowserWindowGtk::EnsureDragHelperCreated() {
@@ -270,51 +332,31 @@ void PanelBrowserWindowGtk::OnSizeChanged(int width, int height) {
content::NotificationService::NoDetails());
}
-bool PanelBrowserWindowGtk::UseCustomFrame() const {
- // We always use custom frame for panels.
- return true;
-}
-
-bool PanelBrowserWindowGtk::UsingCustomPopupFrame() const {
- // We do not draw custom popup frame.
- return false;
-}
-
-void PanelBrowserWindowGtk::DrawPopupFrame(cairo_t* cr,
- GtkWidget* widget,
- GdkEventExpose* event) {
- NOTREACHED();
+const gfx::Image* PanelBrowserWindowGtk::GetFrameBackground() const {
+ return UsingDefaultTheme() ?
+ GetDefaultFrameBackground() : GetThemedFrameBackground();
}
-const gfx::Image* PanelBrowserWindowGtk::GetThemeFrameImage() const {
- PaintState paint_state = GetPaintState();
- if (paint_state == PAINT_FOR_ATTENTION)
- return GetAttentionBackgroundImage();
-
- GtkThemeService* theme_provider = GtkThemeService::GetFrom(
- GetPanelBrowser()->profile());
- if (theme_provider->UsingDefaultTheme()) {
- // We choose to use the window frame theme to paint panels for the default
- // theme. This is because the default tab theme does not work well for the
- // user to recognize active and inactive panels.
- return theme_provider->GetImageNamed(paint_state == PAINT_AS_ACTIVE ?
- IDR_THEME_FRAME : IDR_THEME_FRAME_INACTIVE);
+const gfx::Image* PanelBrowserWindowGtk::GetDefaultFrameBackground() const {
+ switch (paint_state_) {
+ case PAINT_AS_INACTIVE:
+ return GetInactiveBackgroundDefaultImage();
+ case PAINT_AS_ACTIVE:
+ return GetActiveBackgroundDefaultImage();
+ case PAINT_AS_MINIMIZED:
+ return GetMinimizeBackgroundDefaultImage();
+ case PAINT_FOR_ATTENTION:
+ return GetAttentionBackgroundDefaultImage();
+ default:
+ NOTREACHED();
+ return GetInactiveBackgroundDefaultImage();
}
-
- return theme_provider->GetImageNamed(paint_state == PAINT_AS_ACTIVE ?
- IDR_THEME_TOOLBAR : IDR_THEME_TAB_BACKGROUND);
}
-void PanelBrowserWindowGtk::DrawCustomFrame(cairo_t* cr,
- GtkWidget* widget,
- GdkEventExpose* event) {
- gfx::CairoCachedSurface* surface = GetThemeFrameImage()->ToCairo();
-
- surface->SetSource(cr, widget, 0, 0);
- cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
- cairo_rectangle(cr, event->area.x, event->area.y,
- event->area.width, event->area.height);
- cairo_fill(cr);
+const gfx::Image* PanelBrowserWindowGtk::GetThemedFrameBackground() const {
+ GtkThemeService* theme_provider = GtkThemeService::GetFrom(panel_->profile());
+ return theme_provider->GetImageNamed(paint_state_ == PAINT_AS_ACTIVE ?
+ IDR_THEME_TOOLBAR : IDR_THEME_TAB_BACKGROUND);
}
void PanelBrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
@@ -324,6 +366,7 @@ void PanelBrowserWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
if (!window() || was_active == is_active) // State didn't change.
return;
+ GetPanelTitlebar()->UpdateTextColor();
panel_->OnActiveStateChanged(is_active);
}
@@ -600,7 +643,8 @@ class NativePanelTestingGtk : public NativePanelTesting {
virtual void WaitForWindowCreationToComplete() const OVERRIDE;
virtual bool IsWindowSizeKnown() const OVERRIDE;
virtual bool IsAnimatingBounds() const OVERRIDE;
- virtual bool IsButtonVisible(TitlebarButtonType button_type) const OVERRIDE;
+ virtual bool IsButtonVisible(
+ panel::TitlebarButtonType button_type) const OVERRIDE;
PanelBrowserWindowGtk* panel_browser_window_gtk_;
};
@@ -703,19 +747,19 @@ bool NativePanelTestingGtk::IsAnimatingBounds() const {
}
bool NativePanelTestingGtk::IsButtonVisible(
- TitlebarButtonType button_type) const {
+ panel::TitlebarButtonType button_type) const {
PanelBrowserTitlebarGtk* titlebar =
panel_browser_window_gtk_->GetPanelTitlebar();
CustomDrawButton* button;
switch (button_type) {
- case CLOSE_BUTTON:
+ case panel::CLOSE_BUTTON:
button = titlebar->close_button();
break;
- case MINIMIZE_BUTTON:
+ case panel::MINIMIZE_BUTTON:
button = titlebar->minimize_button();
break;
- case RESTORE_BUTTON:
- button = titlebar->unminimize_button();
+ case panel::RESTORE_BUTTON:
+ button = titlebar->restore_button();
break;
default:
NOTREACHED();
diff --git a/chrome/browser/ui/panels/panel_browser_window_gtk.h b/chrome/browser/ui/panels/panel_browser_window_gtk.h
index 911259b..d19089c 100644
--- a/chrome/browser/ui/panels/panel_browser_window_gtk.h
+++ b/chrome/browser/ui/panels/panel_browser_window_gtk.h
@@ -28,6 +28,7 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
enum PaintState {
PAINT_AS_ACTIVE,
PAINT_AS_INACTIVE,
+ PAINT_AS_MINIMIZED,
PAINT_FOR_ATTENTION
};
@@ -37,7 +38,6 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
// BrowserWindowGtk override
virtual void Init() OVERRIDE;
- virtual bool ShouldDrawContentDropShadow() const OVERRIDE;
// BrowserWindow overrides
virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
@@ -47,16 +47,16 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- PaintState GetPaintState() const;
+ bool UsingDefaultTheme() const;
Panel* panel() const { return panel_.get(); }
+ PaintState paint_state() const { return paint_state_; }
protected:
// BrowserWindowGtk overrides
- virtual BrowserTitlebar* CreateBrowserTitlebar() OVERRIDE;
+ virtual BrowserTitlebarBase* CreateBrowserTitlebar() OVERRIDE;
virtual bool GetWindowEdge(int x, int y, GdkWindowEdge* edge) OVERRIDE;
virtual GdkRegion* GetWindowShape(int width, int height) const OVERRIDE;
- virtual void DrawCustomFrameBorder(GtkWidget* widget) OVERRIDE;
virtual bool HandleTitleBarLeftMousePress(
GdkEventButton* event,
guint32 last_click_time,
@@ -68,12 +68,8 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
virtual void SaveWindowPosition() OVERRIDE;
virtual void SetGeometryHints() OVERRIDE;
virtual bool UseCustomFrame() const OVERRIDE;
- virtual bool UsingCustomPopupFrame() const OVERRIDE;
+ virtual void DrawFrame(GtkWidget* widget, GdkEventExpose* event) OVERRIDE;
virtual void OnSizeChanged(int width, int height) OVERRIDE;
- virtual void DrawCustomFrame(cairo_t* cr, GtkWidget* widget,
- GdkEventExpose* event) OVERRIDE;
- virtual void DrawPopupFrame(cairo_t* cr, GtkWidget* widget,
- GdkEventExpose* event) OVERRIDE;
virtual void ActiveWindowChanged(GdkWindow* active_window) OVERRIDE;
// Overridden from NativePanel:
@@ -138,8 +134,10 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
PanelBrowserTitlebarGtk* GetPanelTitlebar() const;
- // Returns the theme image to paint the frame.
- const gfx::Image* GetThemeFrameImage() const;
+ // Returns the image to paint the frame.
+ const gfx::Image* GetFrameBackground() const;
+ const gfx::Image* GetDefaultFrameBackground() const;
+ const gfx::Image* GetThemedFrameBackground() const;
CHROMEGTK_CALLBACK_1(PanelBrowserWindowGtk, gboolean,
OnTitlebarButtonReleaseEvent, GdkEventButton*);
@@ -152,6 +150,9 @@ class PanelBrowserWindowGtk : public BrowserWindowGtk,
// Size of window frame. Empty until the window has been allocated and sized.
gfx::Size frame_size_;
+ // Indicates different painting state, active, drawing attention or else.
+ PaintState paint_state_;
+
// Indicates that the panel is currently drawing attention.
bool is_drawing_attention_;
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index 0ac8e14..0595764 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -291,26 +291,17 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CheckDockedPanelProperties) {
EXPECT_TRUE(panel2->always_on_top());
EXPECT_TRUE(panel3->always_on_top());
- EXPECT_TRUE(panel1_testing->IsButtonVisible(
- NativePanelTesting::CLOSE_BUTTON));
- EXPECT_TRUE(panel2_testing->IsButtonVisible(
- NativePanelTesting::CLOSE_BUTTON));
- EXPECT_TRUE(panel3_testing->IsButtonVisible(
- NativePanelTesting::CLOSE_BUTTON));
-
- EXPECT_TRUE(panel1_testing->IsButtonVisible(
- NativePanelTesting::MINIMIZE_BUTTON));
- EXPECT_FALSE(panel2_testing->IsButtonVisible(
- NativePanelTesting::MINIMIZE_BUTTON));
- EXPECT_FALSE(panel3_testing->IsButtonVisible(
- NativePanelTesting::MINIMIZE_BUTTON));
-
- EXPECT_FALSE(panel1_testing->IsButtonVisible(
- NativePanelTesting::RESTORE_BUTTON));
- EXPECT_TRUE(panel2_testing->IsButtonVisible(
- NativePanelTesting::RESTORE_BUTTON));
- EXPECT_TRUE(panel3_testing->IsButtonVisible(
- NativePanelTesting::RESTORE_BUTTON));
+ EXPECT_TRUE(panel1_testing->IsButtonVisible(panel::CLOSE_BUTTON));
+ EXPECT_TRUE(panel2_testing->IsButtonVisible(panel::CLOSE_BUTTON));
+ EXPECT_TRUE(panel3_testing->IsButtonVisible(panel::CLOSE_BUTTON));
+
+ EXPECT_TRUE(panel1_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+ EXPECT_FALSE(panel2_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+ EXPECT_FALSE(panel3_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
+
+ EXPECT_FALSE(panel1_testing->IsButtonVisible(panel::RESTORE_BUTTON));
+ EXPECT_TRUE(panel2_testing->IsButtonVisible(panel::RESTORE_BUTTON));
+ EXPECT_TRUE(panel3_testing->IsButtonVisible(panel::RESTORE_BUTTON));
EXPECT_EQ(panel::RESIZABLE_ALL_SIDES_EXCEPT_BOTTOM,
panel1->CanResizeByMouse());
diff --git a/chrome/browser/ui/panels/panel_constants.h b/chrome/browser/ui/panels/panel_constants.h
index f51b7b5..d805c69 100644
--- a/chrome/browser/ui/panels/panel_constants.h
+++ b/chrome/browser/ui/panels/panel_constants.h
@@ -25,6 +25,13 @@ static const int kMinimizedPanelHeight = 4;
// The height in pixels of the titlebar.
static const int kTitlebarHeight = 32;
+// Different types of buttons that can be shown on panel's titlebar.
+enum TitlebarButtonType {
+ CLOSE_BUTTON,
+ MINIMIZE_BUTTON,
+ RESTORE_BUTTON
+};
+
// Different platforms use different modifier keys to change the behavior
// of a mouse click. This enum captures the meaning of the modifier rather
// than the actual modifier key to generalize across platforms.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index ebe7c97..59e0ffb 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2892,6 +2892,7 @@
'browser/ui/gtk/browser_actions_toolbar_gtk.h',
'browser/ui/gtk/browser_titlebar.cc',
'browser/ui/gtk/browser_titlebar.h',
+ 'browser/ui/gtk/browser_titlebar_base.h',
'browser/ui/gtk/browser_toolbar_gtk.cc',
'browser/ui/gtk/browser_toolbar_gtk.h',
'browser/ui/gtk/browser_window_gtk.cc',
@@ -3092,6 +3093,8 @@
'browser/ui/gtk/task_manager_gtk.h',
'browser/ui/gtk/throbber_gtk.cc',
'browser/ui/gtk/throbber_gtk.h',
+ 'browser/ui/gtk/titlebar_throb_animation.cc',
+ 'browser/ui/gtk/titlebar_throb_animation.h',
'browser/ui/gtk/unity_service.cc',
'browser/ui/gtk/unity_service.h',
'browser/ui/gtk/update_recommended_dialog.cc',
@@ -3155,10 +3158,10 @@
'browser/ui/panels/panel_bounds_animation.h',
'browser/ui/panels/panel_browser_frame_view.cc',
'browser/ui/panels/panel_browser_frame_view.h',
- 'browser/ui/panels/panel_browser_view.cc',
- 'browser/ui/panels/panel_browser_view.h',
'browser/ui/panels/panel_browser_titlebar_gtk.cc',
'browser/ui/panels/panel_browser_titlebar_gtk.h',
+ 'browser/ui/panels/panel_browser_view.cc',
+ 'browser/ui/panels/panel_browser_view.h',
'browser/ui/panels/panel_browser_window.cc',
'browser/ui/panels/panel_browser_window.h',
'browser/ui/panels/panel_browser_window_cocoa.h',