diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-19 23:44:34 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-19 23:44:34 +0000 |
commit | 06416f79b380fe5378bc3fd305e89c762c8408ea (patch) | |
tree | b573c2d4c334f7ab19a68fecba3cb3fa499ada4a /chrome/browser | |
parent | aec3525822420bd1386af1a3cfd9fe3f6d0dbe90 (diff) | |
download | chromium_src-06416f79b380fe5378bc3fd305e89c762c8408ea.zip chromium_src-06416f79b380fe5378bc3fd305e89c762c8408ea.tar.gz chromium_src-06416f79b380fe5378bc3fd305e89c762c8408ea.tar.bz2 |
Handle non-composited WMs when rendering the dragged tab. Also moves rendering of the close button to TabRendererGtk (where it belongs).
Review URL: http://codereview.chromium.org/115543
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16437 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.cc | 69 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.h | 18 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_gtk.cc | 37 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_gtk.h | 13 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_renderer_gtk.cc | 120 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_renderer_gtk.h | 34 |
6 files changed, 184 insertions, 107 deletions
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc index 6caa70c0..699fdb7 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc @@ -7,6 +7,7 @@ #include <gdk/gdk.h> #include "app/gfx/canvas.h" +#include "app/gfx/gtk_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/gtk/tabs/tab_renderer_gtk.h" @@ -23,6 +24,11 @@ const float kScalingFactor = 0.5; const int kAnimateToBoundsDurationMs = 150; +bool IsScreenComposited() { + GdkScreen* screen = gdk_screen_get_default(); + return gdk_screen_is_composited(screen) == TRUE; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -43,7 +49,8 @@ DraggedTabGtk::DraggedTabGtk(TabContents* datasource, SetContainerColorMap(); gtk_widget_set_app_paintable(container_, TRUE); g_signal_connect(G_OBJECT(container_), "expose-event", - G_CALLBACK(OnExpose), this); + G_CALLBACK(OnExposeEvent), this); + gtk_widget_add_events(container_, GDK_STRUCTURE_MASK); gtk_container_add(GTK_CONTAINER(container_), renderer_->widget()); gtk_widget_show_all(container_); } @@ -140,6 +147,13 @@ int DraggedTabGtk::ScaleValue(int value) { return attached_ ? value : static_cast<int>(value * kScalingFactor); } +gfx::Rect DraggedTabGtk::bounds() const { + gint x, y, width, height; + gtk_window_get_position(GTK_WINDOW(container_), &x, &y); + gtk_window_get_size(GTK_WINDOW(container_), &width, &height); + return gfx::Rect(x, y, width, height); +} + void DraggedTabGtk::SetContainerColorMap() { GdkScreen* screen = gtk_widget_get_screen(container_); GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen); @@ -151,23 +165,58 @@ void DraggedTabGtk::SetContainerColorMap() { gtk_widget_set_colormap(container_, colormap); } -// static -gboolean DraggedTabGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, - DraggedTabGtk* dragged_tab) { - cairo_t* cairo_context = gdk_cairo_create(widget->window); +void DraggedTabGtk::SetContainerTransparency() { + cairo_t* cairo_context = gdk_cairo_create(container_->window); if (!cairo_context) - return FALSE; + return; // Make the background of the dragged tab window fully transparent. All of // the content of the window (child widgets) will be completely opaque. - gint width, height; - gtk_window_get_size(GTK_WINDOW(widget), &width, &height); - cairo_scale(cairo_context, static_cast<double>(width), - static_cast<double>(height)); + gfx::Size size = bounds().size(); + cairo_scale(cairo_context, static_cast<double>(size.width()), + static_cast<double>(size.height())); cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f); cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE); cairo_paint(cairo_context); cairo_destroy(cairo_context); +} + +void DraggedTabGtk::SetContainerShapeMask() { + // Render the tab as a bitmap. + SkBitmap tab = renderer_->PaintBitmap(); + GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&tab); + + // Create a 1bpp bitmap the size of |container_|. + gfx::Size size = bounds().size(); + GdkPixmap* pixmap = gdk_pixmap_new(NULL, size.width(), size.height(), 1); + cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(pixmap)); + + // Set the transparency. + cairo_set_source_rgba(cairo_context, 1, 1, 1, 0); + + // Blit the rendered bitmap into a pixmap. Any pixel set in the pixmap will + // be opaque in the container window. + cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE); + gdk_cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0); + cairo_paint(cairo_context); + cairo_destroy(cairo_context); + + // Set the shape mask. + gdk_window_shape_combine_mask(container_->window, pixmap, 0, 0); + g_object_unref(pixbuf); + g_object_unref(pixmap); +} + +// static +gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget, + GdkEventExpose* event, + DraggedTabGtk* dragged_tab) { + printf("OnExposeEvent\n"); + if (IsScreenComposited()) { + dragged_tab->SetContainerTransparency(); + } else { + dragged_tab->SetContainerShapeMask(); + } return FALSE; } diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h index 3a65b2d..cedce9d 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.h @@ -61,13 +61,25 @@ class DraggedTabGtk : public AnimationDelegate { // Utility for scaling a size by the current scaling factor. int ScaleValue(int value); + // Returns the bounds of the container window. + gfx::Rect bounds() const; + // Sets the color map of the container window to allow the window to be // transparent. void SetContainerColorMap(); - // expose-event handler that redraws the dragged tab. - static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* event, - DraggedTabGtk* dragged_tab); + // Sets full transparency for the container window. This is used if + // compositing is available for the screen. + void SetContainerTransparency(); + + // Sets the shape mask for the container window to emulate a transparent + // container window. This is used if compositing is not available for the + // screen. + void SetContainerShapeMask(); + + // expose-event handler that notifies when the tab needs to be redrawn. + static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event, + DraggedTabGtk* dragged_tab); // The window that contains the dragged tab or tab contents. GtkWidget* container_; diff --git a/chrome/browser/gtk/tabs/tab_gtk.cc b/chrome/browser/gtk/tabs/tab_gtk.cc index 4bc7b85..7981759 100644 --- a/chrome/browser/gtk/tabs/tab_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_gtk.cc @@ -7,7 +7,6 @@ #include "app/gfx/path.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" -#include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/menu_gtk.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -126,8 +125,6 @@ TabGtk::TabGtk(TabDelegate* delegate) GDK_LEAVE_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_container_add(GTK_CONTAINER(event_box_.get()), TabRendererGtk::widget()); gtk_widget_show_all(event_box_.get()); - - close_button_.reset(MakeCloseButton()); } TabGtk::~TabGtk() { @@ -260,31 +257,13 @@ void TabGtk::SetVisible(bool visible) const { } } -void TabGtk::CloseButtonResized(const gfx::Rect& bounds) { - if (!bounds.IsEmpty()) { - gtk_fixed_move(GTK_FIXED(TabRendererGtk::widget()), - close_button_.get()->widget(), bounds.x(), bounds.y()); - gtk_widget_show(close_button_.get()->widget()); - } else { - gtk_widget_hide(close_button_.get()->widget()); - } -} - -void TabGtk::Paint(GdkEventExpose* event) { - TabRendererGtk::Paint(event); - - gtk_container_propagate_expose(GTK_CONTAINER(TabRendererGtk::widget()), - close_button_.get()->widget(), event); +void TabGtk::CloseButtonClicked() { + delegate_->CloseTab(this); } /////////////////////////////////////////////////////////////////////////////// // TabGtk, private: -// static -void TabGtk::OnCloseButtonClicked(GtkWidget* widget, TabGtk* tab) { - tab->delegate_->CloseTab(tab); -} - void TabGtk::ShowContextMenu() { if (!menu_controller_.get()) menu_controller_.reset(new ContextMenuController(this)); @@ -296,15 +275,3 @@ void TabGtk::ContextMenuClosed() { delegate()->StopAllHighlighting(); menu_controller_.reset(); } - -CustomDrawButton* TabGtk::MakeCloseButton() { - CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE, - IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE); - - g_signal_connect(G_OBJECT(button->widget()), "clicked", - G_CALLBACK(OnCloseButtonClicked), this); - GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); - gtk_fixed_put(GTK_FIXED(TabRendererGtk::widget()), button->widget(), 0, 0); - - return button; -} diff --git a/chrome/browser/gtk/tabs/tab_gtk.h b/chrome/browser/gtk/tabs/tab_gtk.h index 044718f..df8dfe9 100644 --- a/chrome/browser/gtk/tabs/tab_gtk.h +++ b/chrome/browser/gtk/tabs/tab_gtk.h @@ -13,8 +13,6 @@ namespace gfx { class Path; } -class CustomDrawButton; - class TabGtk : public TabRendererGtk { public: // An interface implemented by an object that can help this Tab complete @@ -82,8 +80,7 @@ class TabGtk : public TabRendererGtk { virtual bool IsSelected() const; virtual bool IsVisible() const; virtual void SetVisible(bool visible) const; - virtual void CloseButtonResized(const gfx::Rect& bounds); - virtual void Paint(GdkEventExpose* event); + virtual void CloseButtonClicked(); // The callback that is called for every gdk event. We use it to inspect for // drag-motion events when the drag is outside of the source tab. @@ -126,17 +123,12 @@ class TabGtk : public TabRendererGtk { class ContextMenuController; friend class ContextMenuController; - // Handles the clicked signal for the close button. - static void OnCloseButtonClicked(GtkWidget* widget, TabGtk* tab); - // Shows the context menu. void ShowContextMenu(); // Invoked when the context menu closes. void ContextMenuClosed(); - CustomDrawButton* MakeCloseButton(); - // An instance of a delegate object that can perform various actions based on // user gestures. TabDelegate* delegate_; @@ -147,9 +139,6 @@ class TabGtk : public TabRendererGtk { // The context menu controller. scoped_ptr<ContextMenuController> menu_controller_; - // The close button. - scoped_ptr<CustomDrawButton> close_button_; - // The windowless widget used to collect input events for the tab. OwnedWidgetGtk event_box_; diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index 38cba8f..6bcc6fc 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -8,6 +8,7 @@ #include "app/resource_bundle.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_theme_provider.h" +#include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "grit/generated_resources.h" @@ -182,6 +183,7 @@ TabRendererGtk::TabRendererGtk() gtk_widget_set_app_paintable(tab_.get(), TRUE); g_signal_connect(G_OBJECT(tab_.get()), "expose-event", G_CALLBACK(OnExpose), this); + close_button_.reset(MakeCloseButton()); gtk_widget_show(tab_.get()); hover_animation_.reset(new SlideAnimation(this)); @@ -241,10 +243,6 @@ void TabRendererGtk::SetVisible(bool visible) const { } } -void TabRendererGtk::CloseButtonResized(const gfx::Rect& bounds) { - // Nothing to do. -} - void TabRendererGtk::ValidateLoadingAnimation(AnimationState animation_state) { loading_animation_.ValidateLoadingAnimation(animation_state); } @@ -371,11 +369,7 @@ void TabRendererGtk::ResetCrashedFavIcon() { should_display_crashed_favicon_ = false; } -void TabRendererGtk::Paint(GdkEventExpose* event) { - gfx::CanvasPaint canvas(event, false); - if (canvas.isEmpty()) - return; - +void TabRendererGtk::Paint(gfx::Canvas* canvas) { // Don't paint if we're narrower than we can render correctly. (This should // only happen during animations). if (width() < GetMinimumUnselectedSize().width()) @@ -390,42 +384,42 @@ void TabRendererGtk::Paint(GdkEventExpose* event) { show_close_button != showing_close_button_) Layout(); - PaintTabBackground(&canvas); + PaintTabBackground(canvas); if (show_icon) { if (loading_animation_.animation_state() != ANIMATION_NONE) { - PaintLoadingAnimation(&canvas); + PaintLoadingAnimation(canvas); } else { - canvas.save(); - canvas.ClipRectInt(0, 0, width(), height() - kFavIconTitleSpacing); + canvas->save(); + canvas->ClipRectInt(0, 0, width(), height() - kFavIconTitleSpacing); if (should_display_crashed_favicon_) { - canvas.DrawBitmapInt(*crashed_fav_icon, 0, 0, - crashed_fav_icon->width(), - crashed_fav_icon->height(), - favicon_bounds_.x(), - favicon_bounds_.y() + fav_icon_hiding_offset_, - kFavIconSize, kFavIconSize, - true); + canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0, + crashed_fav_icon->width(), + crashed_fav_icon->height(), + favicon_bounds_.x(), + favicon_bounds_.y() + fav_icon_hiding_offset_, + kFavIconSize, kFavIconSize, + true); } else { if (!data_.favicon.isNull()) { // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch // to using that class to render the favicon). - canvas.DrawBitmapInt(data_.favicon, 0, 0, - data_.favicon.width(), - data_.favicon.height(), - favicon_bounds_.x(), - favicon_bounds_.y() + fav_icon_hiding_offset_, - kFavIconSize, kFavIconSize, - true); + canvas->DrawBitmapInt(data_.favicon, 0, 0, + data_.favicon.width(), + data_.favicon.height(), + favicon_bounds_.x(), + favicon_bounds_.y() + fav_icon_hiding_offset_, + kFavIconSize, kFavIconSize, + true); } } - canvas.restore(); + canvas->restore(); } } if (show_download_icon) { - canvas.DrawBitmapInt(*download_icon_, - download_icon_bounds_.x(), download_icon_bounds_.y()); + canvas->DrawBitmapInt(*download_icon_, + download_icon_bounds_.x(), download_icon_bounds_.y()); } // Paint the Title. @@ -442,9 +436,15 @@ void TabRendererGtk::Paint(GdkEventExpose* event) { SkColor title_color = IsSelected() ? kSelectedTitleColor : kUnselectedTitleColor; - canvas.DrawStringInt(title, *title_font_, title_color, title_bounds_.x(), - title_bounds_.y(), title_bounds_.width(), - title_bounds_.height()); + canvas->DrawStringInt(title, *title_font_, title_color, title_bounds_.x(), + title_bounds_.y(), title_bounds_.width(), + title_bounds_.height()); +} + +SkBitmap TabRendererGtk::PaintBitmap() { + gfx::Canvas canvas(width(), height(), false); + Paint(&canvas); + return canvas.ExtractBitmap(); } void TabRendererGtk::SchedulePaint() { @@ -492,7 +492,7 @@ void TabRendererGtk::Layout() { close_button_bounds_.SetRect(0, 0, 0, 0); } - CloseButtonResized(close_button_bounds_); + MoveCloseButtonWidget(); // Size the Title text to fill the remaining space. int title_left = favicon_bounds_.right() + kFavIconTitleSpacing; @@ -520,7 +520,25 @@ void TabRendererGtk::Layout() { // TODO(jhawkins): Handle RTL layout. } -void TabRendererGtk::PaintTabBackground(gfx::CanvasPaint* canvas) { +void TabRendererGtk::MoveCloseButtonWidget() { + if (!close_button_bounds_.IsEmpty()) { + gtk_fixed_move(GTK_FIXED(tab_.get()), close_button_.get()->widget(), + close_button_bounds_.x(), close_button_bounds_.y()); + gtk_widget_show(close_button_.get()->widget()); + } else { + gtk_widget_hide(close_button_.get()->widget()); + } +} + +void TabRendererGtk::PaintTab(GdkEventExpose* event) { + gfx::CanvasPaint canvas(event, false); + if (canvas.isEmpty()) + return; + + Paint(&canvas); +} + +void TabRendererGtk::PaintTabBackground(gfx::Canvas* canvas) { if (IsSelected()) { // Sometimes detaching a tab quickly can result in the model reporting it // as not being selected, so is_drag_clone_ ensures that we always paint @@ -549,7 +567,7 @@ void TabRendererGtk::PaintTabBackground(gfx::CanvasPaint* canvas) { } } -void TabRendererGtk::PaintInactiveTabBackground(gfx::CanvasPaint* canvas) { +void TabRendererGtk::PaintInactiveTabBackground(gfx::Canvas* canvas) { bool is_otr = data_.off_the_record; // The tab image needs to be lined up with the background image @@ -600,7 +618,7 @@ void TabRendererGtk::PaintInactiveTabBackground(gfx::CanvasPaint* canvas) { bounds_.x() + width() - tab_inactive_.r_width, bounds_.y()); } -void TabRendererGtk::PaintActiveTabBackground(gfx::CanvasPaint* canvas) { +void TabRendererGtk::PaintActiveTabBackground(gfx::Canvas* canvas) { int offset = 1; SkBitmap* tab_bg = theme_provider_->GetBitmapNamed(IDR_THEME_TOOLBAR); @@ -636,7 +654,7 @@ void TabRendererGtk::PaintActiveTabBackground(gfx::CanvasPaint* canvas) { bounds_.x() + width() - tab_active_.r_width, bounds_.y()); } -void TabRendererGtk::PaintLoadingAnimation(gfx::CanvasPaint* canvas) { +void TabRendererGtk::PaintLoadingAnimation(gfx::Canvas* canvas) { const SkBitmap* frames = (loading_animation_.animation_state() == ANIMATION_WAITING) ? loading_animation_.waiting_animation_frames() : @@ -678,10 +696,34 @@ bool TabRendererGtk::ShouldShowCloseBox() const { return IsSelected() || IconCapacity() >= 3; } +CustomDrawButton* TabRendererGtk::MakeCloseButton() { + CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE, + IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE); + + g_signal_connect(G_OBJECT(button->widget()), "clicked", + G_CALLBACK(OnCloseButtonClicked), this); + GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); + gtk_fixed_put(GTK_FIXED(tab_.get()), button->widget(), 0, 0); + + return button; +} + +void TabRendererGtk::CloseButtonClicked() { + // Nothing to do. +} + +// static +void TabRendererGtk::OnCloseButtonClicked(GtkWidget* widget, + TabRendererGtk* tab) { + tab->CloseButtonClicked(); +} + // static gboolean TabRendererGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, TabRendererGtk* tab) { - tab->Paint(event); + tab->PaintTab(event); + gtk_container_propagate_expose(GTK_CONTAINER(tab->tab_.get()), + tab->close_button_.get()->widget(), event); return TRUE; } diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h index f93681d..b353049 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -20,6 +20,7 @@ namespace gfx { class Size; } // namespace gfx +class CustomDrawButton; class TabContents; class ThemeProvider; @@ -90,16 +91,19 @@ class TabRendererGtk : public AnimationDelegate { // Sets the visibility of the Tab. virtual void SetVisible(bool visible) const; - // Notifies subclasses that the close button has been resized to |bounds|. - virtual void CloseButtonResized(const gfx::Rect& bounds); - // Paints the tab into |canvas|. - virtual void Paint(GdkEventExpose* event); + virtual void Paint(gfx::Canvas* canvas); + + // Paints the tab into a SkBitmap. + virtual SkBitmap PaintBitmap(); // There is no PaintNow available, so the fastest we can do is schedule a // paint with the windowing system. virtual void SchedulePaint(); + // Notifies the Tab that the close button has been clicked. + virtual void CloseButtonClicked(); + // Advance the loading animation to the next frame, or hide the animation if // the tab isn't loading. void ValidateLoadingAnimation(AnimationState animation_state); @@ -190,14 +194,20 @@ class TabRendererGtk : public AnimationDelegate { // Generates the bounds for the interior items of the tab. void Layout(); + // Moves the close button widget within the GtkFixed container. + void MoveCloseButtonWidget(); + // Returns the largest of the favicon, title text, and the close button. static int GetContentHeight(); + // Paints the tab, minus the close button. + void PaintTab(GdkEventExpose* event); + // Paint various portions of the Tab - void PaintTabBackground(gfx::CanvasPaint* canvas); - void PaintInactiveTabBackground(gfx::CanvasPaint* canvas); - void PaintActiveTabBackground(gfx::CanvasPaint* canvas); - void PaintLoadingAnimation(gfx::CanvasPaint* canvas); + void PaintTabBackground(gfx::Canvas* canvas); + void PaintInactiveTabBackground(gfx::Canvas* canvas); + void PaintActiveTabBackground(gfx::Canvas* canvas); + void PaintLoadingAnimation(gfx::Canvas* canvas); // Returns the number of favicon-size elements that can fit in the tab's // current size. @@ -209,6 +219,11 @@ class TabRendererGtk : public AnimationDelegate { // Returns whether the Tab should display a close button. bool ShouldShowCloseBox() const; + CustomDrawButton* MakeCloseButton(); + + // Handles the clicked signal for the close button. + static void OnCloseButtonClicked(GtkWidget* widget, TabRendererGtk* tab); + // expose-event handler that redraws the tab. static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e, TabRendererGtk* tab); @@ -276,6 +291,9 @@ class TabRendererGtk : public AnimationDelegate { // still render the old theme for this tab. ThemeProvider* theme_provider_; + // The close button. + scoped_ptr<CustomDrawButton> close_button_; + DISALLOW_COPY_AND_ASSIGN(TabRendererGtk); }; |