diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-29 18:30:39 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-29 18:30:39 +0000 |
commit | 3171a5f58cc8ddc33eeef2d597fc80a8b214d3cc (patch) | |
tree | 1b07fa92b5540f56c1e8a98f7be7882f10e4deef | |
parent | 94d2135c70fc622226a72fd970ed1d3dd0428b6d (diff) | |
download | chromium_src-3171a5f58cc8ddc33eeef2d597fc80a8b214d3cc.zip chromium_src-3171a5f58cc8ddc33eeef2d597fc80a8b214d3cc.tar.gz chromium_src-3171a5f58cc8ddc33eeef2d597fc80a8b214d3cc.tar.bz2 |
GTK: more signal handler foolproofing.
BUG=40735
TEST=manual clicking about, trybots
Review URL: http://codereview.chromium.org/1783010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45966 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/browser_actions_toolbar_gtk.cc | 47 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_actions_toolbar_gtk.h | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc | 33 | ||||
-rw-r--r-- | chrome/browser/gtk/fullscreen_exit_bubble_gtk.h | 12 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_theme_provider.cc | 13 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_theme_provider.h | 3 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_bar_helper.cc | 27 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_bar_helper.h | 30 | ||||
-rw-r--r-- | chrome/browser/gtk/options/content_page_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/browser/gtk/rounded_window.cc | 19 |
10 files changed, 80 insertions, 110 deletions
diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index 3eb7e98..0ea880c 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -100,13 +100,13 @@ class BrowserActionButton : public NotificationObserver, ImageLoadingTracker::DONT_CACHE); } - g_signal_connect(button_.get(), "button-press-event", + signals_.Connect(button_.get(), "button-press-event", G_CALLBACK(OnButtonPress), this); - g_signal_connect(button_.get(), "clicked", + signals_.Connect(button_.get(), "clicked", G_CALLBACK(OnClicked), this); - g_signal_connect_after(button_.get(), "expose-event", - G_CALLBACK(OnExposeEvent), this); - g_signal_connect(button_.get(), "drag-begin", + signals_.ConnectAfter(button_.get(), "expose-event", + G_CALLBACK(OnExposeEvent), this); + signals_.Connect(button_.get(), "drag-begin", G_CALLBACK(&OnDragBegin), this); registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, @@ -318,6 +318,7 @@ class BrowserActionButton : public NotificationObserver, // Same as |default_icon_|, but stored as SkBitmap. SkBitmap default_skbitmap_; + GtkSignalRegistrar signals_; NotificationRegistrar registrar_; // The context menu view and model for this extension action. @@ -352,19 +353,19 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) GtkWidget* gripper = gtk_button_new(); GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS); gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK); - g_signal_connect(gripper, "motion-notify-event", + signals_.Connect(gripper, "motion-notify-event", G_CALLBACK(OnGripperMotionNotifyThunk), this); - g_signal_connect(gripper, "expose-event", + signals_.Connect(gripper, "expose-event", G_CALLBACK(OnGripperExposeThunk), this); - g_signal_connect(gripper, "enter-notify-event", + signals_.Connect(gripper, "enter-notify-event", G_CALLBACK(OnGripperEnterNotifyThunk), this); - g_signal_connect(gripper, "leave-notify-event", + signals_.Connect(gripper, "leave-notify-event", G_CALLBACK(OnGripperLeaveNotifyThunk), this); - g_signal_connect(gripper, "button-release-event", + signals_.Connect(gripper, "button-release-event", G_CALLBACK(OnGripperButtonReleaseThunk), this); - g_signal_connect(gripper, "button-press-event", + signals_.Connect(gripper, "button-press-event", G_CALLBACK(OnGripperButtonPressThunk), this); - g_signal_connect(overflow_button_.widget(), "button-press-event", + signals_.Connect(overflow_button_.widget(), "button-press-event", G_CALLBACK(OnOverflowButtonPressThunk), this); gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0); @@ -384,19 +385,13 @@ BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) // We want to connect to "set-focus" on the toplevel window; we have to wait // until we are added to a toplevel window to do so. - g_signal_connect(widget(), "hierarchy-changed", + signals_.Connect(widget(), "hierarchy-changed", G_CALLBACK(OnHierarchyChangedThunk), this); ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); } BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { - GtkWidget* toplevel = gtk_widget_get_toplevel(widget()); - if (toplevel) { - g_signal_handlers_disconnect_by_func( - toplevel, reinterpret_cast<gpointer>(OnSetFocusThunk), this); - } - if (model_) model_->RemoveObserver(this); button_hbox_.Destroy(); @@ -423,7 +418,7 @@ void BrowserActionsToolbarGtk::SetupDrags() { gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, GDK_ACTION_MOVE); - g_signal_connect(button_hbox_.get(), "drag-motion", + signals_.Connect(button_hbox_.get(), "drag-motion", G_CALLBACK(OnDragMotionThunk), this); } @@ -463,16 +458,16 @@ void BrowserActionsToolbarGtk::CreateButtonForExtension(Extension* extension, gtk_drag_source_set(button->widget(), GDK_BUTTON1_MASK, &drag_target, 1, GDK_ACTION_MOVE); // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. - g_signal_connect(button->widget(), "drag-end", + signals_.Connect(button->widget(), "drag-end", G_CALLBACK(&OnDragEndThunk), this); - g_signal_connect(button->widget(), "drag-failed", + signals_.Connect(button->widget(), "drag-failed", G_CALLBACK(&OnDragFailedThunk), this); // Any time a browser action button is shown or hidden we have to update // the chevron state. - g_signal_connect(button->widget(), "show", + signals_.Connect(button->widget(), "show", G_CALLBACK(&OnButtonShowOrHideThunk), this); - g_signal_connect(button->widget(), "hide", + signals_.Connect(button->widget(), "hide", G_CALLBACK(&OnButtonShowOrHideThunk), this); gtk_widget_show(button->widget()); @@ -712,7 +707,7 @@ void BrowserActionsToolbarGtk::OnHierarchyChanged( if (!GTK_WIDGET_TOPLEVEL(toplevel)) return; - g_signal_connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); + signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); } void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget, @@ -826,7 +821,7 @@ gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress( // TODO(estade): set the menu item's tooltip. } - g_signal_connect(overflow_menu_->widget(), "button-press-event", + signals_.Connect(overflow_menu_->widget(), "button-press-event", G_CALLBACK(OnOverflowMenuButtonPressThunk), this); gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(overflow), diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/gtk/browser_actions_toolbar_gtk.h index 88faba7..5de4ffb 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.h @@ -184,6 +184,8 @@ class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer, // This is the width we were at when we started animating. int start_width_; + GtkSignalRegistrar signals_; + ScopedRunnableMethodFactory<BrowserActionsToolbarGtk> method_factory_; DISALLOW_COPY_AND_ASSIGN(BrowserActionsToolbarGtk); diff --git a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc index fb93241..848cb59 100644 --- a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc +++ b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.cc @@ -35,15 +35,6 @@ FullscreenExitBubbleGtk::FullscreenExitBubbleGtk( } FullscreenExitBubbleGtk::~FullscreenExitBubbleGtk() { - // If the user exits the browser while in fullscreen mode, we may already - // have been removed from the widget hierarchy. - GtkWidget* parent = gtk_widget_get_parent(widget()); - if (parent) { - DCHECK_EQ(GTK_WIDGET(container_), parent); - g_signal_handlers_disconnect_by_func(parent, - reinterpret_cast<gpointer>(OnSetFloatingPosition), this); - gtk_container_remove(GTK_CONTAINER(parent), widget()); - } } void FullscreenExitBubbleGtk::InitWidgets() { @@ -61,7 +52,7 @@ void FullscreenExitBubbleGtk::InitWidgets() { exit_text_utf8.c_str()); gtk_chrome_link_button_set_use_gtk_theme(GTK_CHROME_LINK_BUTTON(link), FALSE); - g_signal_connect(link, "clicked", G_CALLBACK(OnLinkClicked), this); + signals_.Connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this); GtkWidget* container = gtk_util::CreateGtkBorderBin(link, &gfx::kGdkBlack, kPaddingPixels, kPaddingPixels, kPaddingPixels, kPaddingPixels); @@ -83,38 +74,34 @@ void FullscreenExitBubbleGtk::InitWidgets() { gtk_floating_container_add_floating(GTK_FLOATING_CONTAINER(container_), widget()); - g_signal_connect(container_, "set-floating-position", - G_CALLBACK(OnSetFloatingPosition), this); + signals_.Connect(container_, "set-floating-position", + G_CALLBACK(OnSetFloatingPositionThunk), this); } void FullscreenExitBubbleGtk::Hide() { slide_widget_->Close(); } -// static void FullscreenExitBubbleGtk::OnSetFloatingPosition( - GtkFloatingContainer* floating_container, GtkAllocation* allocation, - FullscreenExitBubbleGtk* bubble) { + GtkWidget* floating_container, + GtkAllocation* allocation) { GtkRequisition bubble_size; - gtk_widget_size_request(bubble->widget(), &bubble_size); + gtk_widget_size_request(widget(), &bubble_size); // Position the bubble at the top center of the screen. GValue value = { 0, }; g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, (allocation->width - bubble_size.width) / 2); gtk_container_child_set_property(GTK_CONTAINER(floating_container), - bubble->widget(), "x", &value); + widget(), "x", &value); g_value_set_int(&value, 0); gtk_container_child_set_property(GTK_CONTAINER(floating_container), - bubble->widget(), "y", &value); + widget(), "y", &value); g_value_unset(&value); } -// static -void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link, - FullscreenExitBubbleGtk* bubble) { - GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel( - bubble->widget())); +void FullscreenExitBubbleGtk::OnLinkClicked(GtkWidget* link) { + GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(widget())); gtk_window_unfullscreen(window); } diff --git a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h index 44b3ac0..0b9c90e 100644 --- a/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h +++ b/chrome/browser/gtk/fullscreen_exit_bubble_gtk.h @@ -7,6 +7,7 @@ #include <gtk/gtk.h> +#include "app/gtk_signal.h" #include "base/timer.h" #include "chrome/browser/gtk/slide_animator_gtk.h" @@ -30,12 +31,9 @@ class FullscreenExitBubbleGtk { // Hide the exit bubble. void Hide(); - static void OnSetFloatingPosition(GtkFloatingContainer* floating_container, - GtkAllocation* allocation, - FullscreenExitBubbleGtk* bubble); - - static void OnLinkClicked(GtkWidget* link, - FullscreenExitBubbleGtk* bubble); + CHROMEGTK_CALLBACK_1(FullscreenExitBubbleGtk, void, OnSetFloatingPosition, + GtkAllocation*); + CHROMEGTK_CALLBACK_0(FullscreenExitBubbleGtk, void, OnLinkClicked); // A pointer to the floating container that is our parent. GtkFloatingContainer* container_; @@ -45,6 +43,8 @@ class FullscreenExitBubbleGtk { // The timer that does the initial hiding of the exit bubble. base::OneShotTimer<FullscreenExitBubbleGtk> initial_delay_; + + GtkSignalRegistrar signals_; }; #endif // CHROME_BROWSER_GTK_FULLSCREEN_EXIT_BUBBLE_GTK_H_ diff --git a/chrome/browser/gtk/gtk_theme_provider.cc b/chrome/browser/gtk/gtk_theme_provider.cc index be3c358c..66fa0e5 100644 --- a/chrome/browser/gtk/gtk_theme_provider.cc +++ b/chrome/browser/gtk/gtk_theme_provider.cc @@ -145,7 +145,7 @@ GtkThemeProvider::GtkThemeProvider() // Only realized widgets receive style-set notifications, which we need to // broadcast new theme images and colors. gtk_widget_realize(fake_frame_); - g_signal_connect(fake_frame_, "style-set", G_CALLBACK(&OnStyleSet), this); + signals_.Connect(fake_frame_, "style-set", G_CALLBACK(&OnStyleSet), this); } GtkThemeProvider::~GtkThemeProvider() { @@ -158,13 +158,6 @@ GtkThemeProvider::~GtkThemeProvider() { // We have to call this because FreePlatformCached() in ~BrowserThemeProvider // doesn't call the right virutal FreePlatformCaches. FreePlatformCaches(); - - // Disconnect from the destroy signal of any redisual widgets in - // |chrome_buttons_|. - for (std::vector<GtkWidget*>::iterator it = chrome_buttons_.begin(); - it != chrome_buttons_.end(); ++it) { - gtk_signal_disconnect_by_data(GTK_OBJECT(*it), this); - } } void GtkThemeProvider::Init(Profile* profile) { @@ -249,7 +242,7 @@ GtkWidget* GtkThemeProvider::BuildChromeButton() { gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(button), use_gtk_); chrome_buttons_.push_back(button); - g_signal_connect(button, "destroy", G_CALLBACK(OnDestroyChromeButtonThunk), + signals_.Connect(button, "destroy", G_CALLBACK(OnDestroyChromeButtonThunk), this); return button; } @@ -261,7 +254,7 @@ GtkWidget* GtkThemeProvider::CreateToolbarSeparator() { kSeparatorPadding, kSeparatorPadding, kSeparatorPadding, 0); gtk_container_add(GTK_CONTAINER(alignment), separator); - g_signal_connect(separator, "expose-event", + signals_.Connect(separator, "expose-event", G_CALLBACK(OnSeparatorExposeThunk), this); return alignment; } diff --git a/chrome/browser/gtk/gtk_theme_provider.h b/chrome/browser/gtk/gtk_theme_provider.h index 40522b6..3c7b752 100644 --- a/chrome/browser/gtk/gtk_theme_provider.h +++ b/chrome/browser/gtk/gtk_theme_provider.h @@ -192,6 +192,9 @@ class GtkThemeProvider : public BrowserThemeProvider, // them of theme changes. std::vector<GtkWidget*> chrome_buttons_; + // Tracks all the signals we have connected to on various widgets. + GtkSignalRegistrar signals_; + // Tints and colors calculated by LoadGtkValues() that are given to the // caller while |use_gtk_| is true. ColorMap colors_; diff --git a/chrome/browser/gtk/menu_bar_helper.cc b/chrome/browser/gtk/menu_bar_helper.cc index 54fa555..d5d42ae 100644 --- a/chrome/browser/gtk/menu_bar_helper.cc +++ b/chrome/browser/gtk/menu_bar_helper.cc @@ -79,16 +79,19 @@ void MenuBarHelper::MenuStartedShowing(GtkWidget* button, GtkWidget* menu) { DCHECK(GTK_IS_MENU(menu)); button_showing_menu_ = button; showing_menu_ = menu; - g_signal_connect(menu, "motion-notify-event", - G_CALLBACK(OnMenuMotionNotifyThunk), this); - g_signal_connect(menu, "hide", - G_CALLBACK(OnMenuHiddenThunk), this); - g_signal_connect(menu, "move-current", - G_CALLBACK(OnMenuMoveCurrentThunk), this); + + signal_handlers_.reset(new GtkSignalRegistrar()); + signal_handlers_->Connect(menu, "motion-notify-event", + G_CALLBACK(OnMenuMotionNotifyThunk), this); + signal_handlers_->Connect(menu, "hide", + G_CALLBACK(OnMenuHiddenThunk), this); + signal_handlers_->Connect(menu, "move-current", + G_CALLBACK(OnMenuMoveCurrentThunk), this); gtk_container_foreach(GTK_CONTAINER(menu), PopulateSubmenus, &submenus_); + for (size_t i = 0; i < submenus_.size(); ++i) { - g_signal_connect(submenus_[i], "motion-notify-event", - G_CALLBACK(OnMenuMotionNotifyThunk), this); + signal_handlers_->Connect(submenus_[i], "motion-notify-event", + G_CALLBACK(OnMenuMotionNotifyThunk), this); } } @@ -138,14 +141,8 @@ gboolean MenuBarHelper::OnMenuMotionNotify(GtkWidget* menu, void MenuBarHelper::OnMenuHidden(GtkWidget* menu) { DCHECK_EQ(showing_menu_, menu); - int matched = g_signal_handlers_disconnect_matched(showing_menu_, - G_SIGNAL_MATCH_DATA, 0, NULL, NULL, NULL, this); - DCHECK_EQ(3, matched); - for (size_t i = 0; i < submenus_.size(); ++i) { - g_signal_handlers_disconnect_by_func(submenus_[i], - reinterpret_cast<gpointer>(OnMenuMotionNotifyThunk), this); - } + signal_handlers_.reset(); showing_menu_ = NULL; button_showing_menu_ = NULL; submenus_.clear(); diff --git a/chrome/browser/gtk/menu_bar_helper.h b/chrome/browser/gtk/menu_bar_helper.h index 9b6448c..05d6819 100644 --- a/chrome/browser/gtk/menu_bar_helper.h +++ b/chrome/browser/gtk/menu_bar_helper.h @@ -13,6 +13,9 @@ #include <vector> +#include "app/gtk_signal.h" +#include "base/scoped_ptr.h" + class MenuBarHelper { public: class Delegate { @@ -43,24 +46,11 @@ class MenuBarHelper { void Clear(); private: - static gboolean OnMenuMotionNotifyThunk(GtkWidget* menu, - GdkEventMotion* motion, - MenuBarHelper* helper) { - return helper->OnMenuMotionNotify(menu, motion); - } - gboolean OnMenuMotionNotify(GtkWidget* menu, GdkEventMotion* motion); - - static void OnMenuHiddenThunk(GtkWidget* menu, MenuBarHelper* helper) { - helper->OnMenuHidden(menu); - } - void OnMenuHidden(GtkWidget* menu); - - static void OnMenuMoveCurrentThunk(GtkWidget* menu, - GtkMenuDirectionType dir, - MenuBarHelper* helper) { - helper->OnMenuMoveCurrent(menu, dir); - } - void OnMenuMoveCurrent(GtkWidget* menu, GtkMenuDirectionType dir); + CHROMEGTK_CALLBACK_1(MenuBarHelper, gboolean, OnMenuMotionNotify, + GdkEventMotion*); + CHROMEGTK_CALLBACK_0(MenuBarHelper, void, OnMenuHidden); + CHROMEGTK_CALLBACK_1(MenuBarHelper, void, OnMenuMoveCurrent, + GtkMenuDirectionType); // The buttons for which we pop up menus. We do not own these, or even add // refs to them. @@ -76,6 +66,10 @@ class MenuBarHelper { // of them. std::vector<GtkWidget*> submenus_; + // Signal handlers that are attached only between the "show" and "hide" events + // for the menu. + scoped_ptr<GtkSignalRegistrar> signal_handlers_; + Delegate* delegate_; }; diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc index 22a635e..3b92201 100644 --- a/chrome/browser/gtk/options/content_page_gtk.cc +++ b/chrome/browser/gtk/options/content_page_gtk.cc @@ -45,8 +45,8 @@ void OnLabelAllocate(GtkWidget* label, GtkAllocation* allocation) { // Disconnect ourselves. Repeatedly resizing based on allocation causes // the dialog to become unshrinkable. - g_signal_handlers_disconnect_by_func(label, (void*)OnLabelAllocate, - NULL); + g_signal_handlers_disconnect_by_func( + label, reinterpret_cast<gpointer>(OnLabelAllocate), NULL); } // Set the label to use a request size equal to its initial allocation diff --git a/chrome/browser/gtk/rounded_window.cc b/chrome/browser/gtk/rounded_window.cc index 52bedc9..c223425 100644 --- a/chrome/browser/gtk/rounded_window.cc +++ b/chrome/browser/gtk/rounded_window.cc @@ -7,6 +7,7 @@ #include <gtk/gtk.h> #include <math.h> +#include "app/gtk_signal.h" #include "base/i18n/rtl.h" #include "chrome/browser/gtk/gtk_util.h" @@ -36,6 +37,9 @@ struct RoundedWindowData { // Which sides of the window should have an internal border? int drawn_borders; + + // Keeps track of attached signal handlers. + GtkSignalRegistrar signals; }; // Callback from GTK to release allocated memory. @@ -256,11 +260,12 @@ void ActAsRoundedWindow( DCHECK(!g_object_get_data(G_OBJECT(widget), kRoundedData)); gtk_widget_set_app_paintable(widget, TRUE); - g_signal_connect(widget, "expose-event", - G_CALLBACK(OnRoundedWindowExpose), NULL); - g_signal_connect(widget, "style-set", G_CALLBACK(OnStyleSet), NULL); RoundedWindowData* data = new RoundedWindowData; + data->signals.Connect(widget, "expose-event", + G_CALLBACK(OnRoundedWindowExpose), NULL); + data->signals.Connect(widget, "style-set", G_CALLBACK(OnStyleSet), NULL); + data->expected_width = -1; data->expected_height = -1; @@ -275,13 +280,7 @@ void ActAsRoundedWindow( } void StopActingAsRoundedWindow(GtkWidget* widget) { - g_signal_handlers_disconnect_by_func(widget, - reinterpret_cast<gpointer>(OnRoundedWindowExpose), NULL); - g_signal_handlers_disconnect_by_func(widget, - reinterpret_cast<gpointer>(OnStyleSet), NULL); - - delete static_cast<RoundedWindowData*>( - g_object_steal_data(G_OBJECT(widget), kRoundedData)); + g_object_set_data(G_OBJECT(widget), kRoundedData, NULL); if (GTK_WIDGET_REALIZED(widget)) gdk_window_shape_combine_mask(widget->window, NULL, 0, 0); |