diff options
-rw-r--r-- | tools/valgrind/memcheck/suppressions.txt | 9 | ||||
-rw-r--r-- | views/controls/menu/native_menu_gtk.cc | 33 | ||||
-rw-r--r-- | views/controls/menu/native_menu_gtk.h | 11 |
3 files changed, 34 insertions, 19 deletions
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index f055b00..22c1ae88 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt @@ -2250,12 +2250,3 @@ fun:ChromeMain fun:main } -{ - bug_33475 - Memcheck:Leak - fun:_Znw* - ... - fun:_ZN5views13NativeMenuGtk7RebuildEv - fun:_ZN5views5Menu27RebuildEv - fun:_ZN5views5Menu2C1EPN5menus9MenuModelE -} diff --git a/views/controls/menu/native_menu_gtk.cc b/views/controls/menu/native_menu_gtk.cc index 1335b85..2bc1fbc 100644 --- a/views/controls/menu/native_menu_gtk.cc +++ b/views/controls/menu/native_menu_gtk.cc @@ -62,18 +62,23 @@ namespace views { //////////////////////////////////////////////////////////////////////////////// // NativeMenuGtk, public: -NativeMenuGtk::NativeMenuGtk(menus::MenuModel* model) +NativeMenuGtk::NativeMenuGtk(Menu2* menu) : parent_(NULL), - model_(model), + model_(menu->model()), menu_(NULL), menu_shown_(false), suppress_activate_signal_(false), activated_menu_(NULL), - activated_index_(-1) { + activated_index_(-1), + host_menu_(menu) { } NativeMenuGtk::~NativeMenuGtk() { - gtk_widget_destroy(menu_); + if (menu_) { + // Don't call MenuDestroyed because menu2 has already been destroyed. + g_signal_handler_disconnect(menu_, destroy_handler_id_); + gtk_widget_destroy(menu_); + } } //////////////////////////////////////////////////////////////////////////////// @@ -207,9 +212,6 @@ GtkWidget* NativeMenuGtk::AddMenuItemAt(int index, } if (type == menus::MenuModel::TYPE_SUBMENU) { - // TODO(beng): we're leaking these objects right now... consider some other - // arrangement. - // See http://crbug.com/33475. Menu2* submenu = new Menu2(model_->GetSubmenuModelAt(index)); static_cast<NativeMenuGtk*>(submenu->wrapper_.get())->set_parent(this); g_object_set_data(G_OBJECT(menu_item), "submenu", submenu); @@ -232,9 +234,13 @@ GtkWidget* NativeMenuGtk::AddMenuItemAt(int index, } void NativeMenuGtk::ResetMenu() { - if (menu_) + if (menu_) { + g_signal_handler_disconnect(menu_, destroy_handler_id_); gtk_widget_destroy(menu_); + } menu_ = gtk_menu_new(); + destroy_handler_id_ = g_signal_connect( + menu_, "destroy", G_CALLBACK(NativeMenuGtk::MenuDestroyed), host_menu_); } void NativeMenuGtk::UpdateMenuItemState(GtkWidget* menu_item) { @@ -336,12 +342,21 @@ void NativeMenuGtk::Activate() { } } +// static +void NativeMenuGtk::MenuDestroyed(GtkWidget* widget, Menu2* menu2) { + NativeMenuGtk* native_menu = + static_cast<NativeMenuGtk*>(menu2->wrapper_.get()); + // The native gtk widget has already been destroyed. + native_menu->menu_ = NULL; + delete menu2; +} + //////////////////////////////////////////////////////////////////////////////// // MenuWrapper, public: // static MenuWrapper* MenuWrapper::CreateWrapper(Menu2* menu) { - return new NativeMenuGtk(menu->model()); + return new NativeMenuGtk(menu); } } // namespace views diff --git a/views/controls/menu/native_menu_gtk.h b/views/controls/menu/native_menu_gtk.h index b2aceff..af7e9b61 100644 --- a/views/controls/menu/native_menu_gtk.h +++ b/views/controls/menu/native_menu_gtk.h @@ -19,7 +19,7 @@ namespace views { // TODO(beng): rename to MenuGtk once the old class is dead. class NativeMenuGtk : public MenuWrapper { public: - explicit NativeMenuGtk(menus::MenuModel* model); + explicit NativeMenuGtk(Menu2* menu); virtual ~NativeMenuGtk(); // Overridden from MenuWrapper: @@ -61,6 +61,10 @@ class NativeMenuGtk : public MenuWrapper { // Notifies the model the user selected an item. void Activate(); + // A callback to delete menu2 object when the native widget is + // destroyed first. + static void MenuDestroyed(GtkWidget* widget, Menu2* menu2); + // If we're a submenu, this is the parent. NativeMenuGtk* parent_; @@ -85,6 +89,11 @@ class NativeMenuGtk : public MenuWrapper { // user selects and not the root. int activated_index_; + // A eference to the hosting menu2 object and signal handler id + // used to delete the menu2 when its native menu gtk is destroyed first. + Menu2* host_menu_; + gulong destroy_handler_id_; + DISALLOW_COPY_AND_ASSIGN(NativeMenuGtk); }; |