Fix some Gtk::Menu memory leaks
A Gtk::manage()d widget will be deleted when its parent container is destroyed. Top-level context menus are not inside a container and hence need to be manually deallocated. The solution here is to use a shared Gtk::Menu pointer that is centrally de/re-allocated. This works because the GUI is single-threaded and at most one context menu is visible at a time.
This commit is contained in:
parent
12a415f077
commit
7b96fa1c5e
@ -287,6 +287,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
|
|||||||
, _was_dirty (false)
|
, _was_dirty (false)
|
||||||
, _mixer_on_top (false)
|
, _mixer_on_top (false)
|
||||||
, _initial_verbose_plugin_scan (false)
|
, _initial_verbose_plugin_scan (false)
|
||||||
|
, _shared_popup_menu (0)
|
||||||
, secondary_clock_spacer (0)
|
, secondary_clock_spacer (0)
|
||||||
, auto_input_button (ArdourButton::led_default_elements)
|
, auto_input_button (ArdourButton::led_default_elements)
|
||||||
, time_info_box (0)
|
, time_info_box (0)
|
||||||
@ -868,6 +869,7 @@ ARDOUR_UI::~ARDOUR_UI ()
|
|||||||
delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
|
delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
|
||||||
delete nsm; nsm = 0;
|
delete nsm; nsm = 0;
|
||||||
delete gui_object_state; gui_object_state = 0;
|
delete gui_object_state; gui_object_state = 0;
|
||||||
|
delete _shared_popup_menu ; _shared_popup_menu = 0;
|
||||||
delete main_window_visibility;
|
delete main_window_visibility;
|
||||||
FastMeter::flush_pattern_cache ();
|
FastMeter::flush_pattern_cache ();
|
||||||
ArdourFader::flush_pattern_cache ();
|
ArdourFader::flush_pattern_cache ();
|
||||||
@ -5433,7 +5435,7 @@ ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
|
|||||||
{
|
{
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
|
|
||||||
RadioMenuItem::Group group;
|
RadioMenuItem::Group group;
|
||||||
@ -6024,3 +6026,14 @@ ARDOUR_UI::monitor_mono ()
|
|||||||
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-mono");
|
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Monitor"), "monitor-mono");
|
||||||
_monitor->set_mono (tact->get_active());
|
_monitor->set_mono (tact->get_active());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gtk::Menu*
|
||||||
|
ARDOUR_UI::shared_popup_menu ()
|
||||||
|
{
|
||||||
|
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::shared_popup_menu, ignored);
|
||||||
|
|
||||||
|
assert (!_shared_popup_menu || !_shared_popup_menu->is_visible());
|
||||||
|
delete _shared_popup_menu;
|
||||||
|
_shared_popup_menu = new Gtk::Menu;
|
||||||
|
return _shared_popup_menu;
|
||||||
|
}
|
||||||
|
@ -228,6 +228,8 @@ public:
|
|||||||
PublicEditor& the_editor() { return *editor;}
|
PublicEditor& the_editor() { return *editor;}
|
||||||
Mixer_UI* the_mixer() { return mixer; }
|
Mixer_UI* the_mixer() { return mixer; }
|
||||||
|
|
||||||
|
Gtk::Menu* shared_popup_menu ();
|
||||||
|
|
||||||
void new_midi_tracer_window ();
|
void new_midi_tracer_window ();
|
||||||
void toggle_editing_space();
|
void toggle_editing_space();
|
||||||
void toggle_mixer_space();
|
void toggle_mixer_space();
|
||||||
@ -401,6 +403,8 @@ private:
|
|||||||
bool _mixer_on_top;
|
bool _mixer_on_top;
|
||||||
bool _initial_verbose_plugin_scan;
|
bool _initial_verbose_plugin_scan;
|
||||||
|
|
||||||
|
Gtk::Menu* _shared_popup_menu;
|
||||||
|
|
||||||
void hide_tabbable (ArdourWidgets::Tabbable*);
|
void hide_tabbable (ArdourWidgets::Tabbable*);
|
||||||
void detach_tabbable (ArdourWidgets::Tabbable*);
|
void detach_tabbable (ArdourWidgets::Tabbable*);
|
||||||
void attach_tabbable (ArdourWidgets::Tabbable*);
|
void attach_tabbable (ArdourWidgets::Tabbable*);
|
||||||
@ -555,8 +559,6 @@ private:
|
|||||||
|
|
||||||
void transport_rec_enable_blink (bool onoff);
|
void transport_rec_enable_blink (bool onoff);
|
||||||
|
|
||||||
Gtk::Menu* session_popup_menu;
|
|
||||||
|
|
||||||
/* menu bar and associated stuff */
|
/* menu bar and associated stuff */
|
||||||
|
|
||||||
Gtk::MenuBar* menu_bar;
|
Gtk::MenuBar* menu_bar;
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include "widgets/ardour_button.h"
|
#include "widgets/ardour_button.h"
|
||||||
#include "widgets/ardour_knob.h"
|
#include "widgets/ardour_knob.h"
|
||||||
|
|
||||||
|
#include "ardour_ui.h"
|
||||||
#include "automation_controller.h"
|
#include "automation_controller.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
#include "note_select_dialog.h"
|
#include "note_select_dialog.h"
|
||||||
@ -301,14 +303,14 @@ AutomationController::on_button_release(GdkEventButton* ev)
|
|||||||
|
|
||||||
const ARDOUR::ParameterDescriptor& desc = _controllable->desc();
|
const ARDOUR::ParameterDescriptor& desc = _controllable->desc();
|
||||||
if (desc.unit == ARDOUR::ParameterDescriptor::MIDI_NOTE) {
|
if (desc.unit == ARDOUR::ParameterDescriptor::MIDI_NOTE) {
|
||||||
Gtk::Menu* menu = manage(new Menu());
|
Gtk::Menu* menu = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = menu->items();
|
MenuList& items = menu->items();
|
||||||
items.push_back(MenuElem(_("Select Note..."),
|
items.push_back(MenuElem(_("Select Note..."),
|
||||||
sigc::mem_fun(*this, &AutomationController::run_note_select_dialog)));
|
sigc::mem_fun(*this, &AutomationController::run_note_select_dialog)));
|
||||||
menu->popup(1, ev->time);
|
menu->popup(1, ev->time);
|
||||||
return true;
|
return true;
|
||||||
} else if (desc.unit == ARDOUR::ParameterDescriptor::HZ) {
|
} else if (desc.unit == ARDOUR::ParameterDescriptor::HZ) {
|
||||||
Gtk::Menu* menu = manage(new Menu());
|
Gtk::Menu* menu = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = menu->items();
|
MenuList& items = menu->items();
|
||||||
items.push_back(MenuElem(_("Halve"),
|
items.push_back(MenuElem(_("Halve"),
|
||||||
sigc::bind(sigc::mem_fun(*this, &AutomationController::set_ratio),
|
sigc::bind(sigc::mem_fun(*this, &AutomationController::set_ratio),
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <gtkmm/menu.h>
|
#include <gtkmm/menu.h>
|
||||||
#include <gtkmm/menuitem.h>
|
#include <gtkmm/menuitem.h>
|
||||||
|
|
||||||
|
#include "ardour_ui.h"
|
||||||
#include "time_axis_view.h"
|
#include "time_axis_view.h"
|
||||||
#include "streamview.h"
|
#include "streamview.h"
|
||||||
#include "editor_summary.h"
|
#include "editor_summary.h"
|
||||||
@ -461,7 +462,7 @@ EditorSummary::on_button_press_event (GdkEventButton* ev)
|
|||||||
|
|
||||||
if (ev->button == 3) { // right-click: show the reset menu action
|
if (ev->button == 3) { // right-click: show the reset menu action
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
Gtk::Menu* m = manage (new Gtk::Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
items.push_back(MenuElem(_("Reset Summary to Extents"),
|
items.push_back(MenuElem(_("Reset Summary to Extents"),
|
||||||
sigc::mem_fun(*this, &EditorSummary::reset_to_extents)));
|
sigc::mem_fun(*this, &EditorSummary::reset_to_extents)));
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "widgets/tooltips.h"
|
#include "widgets/tooltips.h"
|
||||||
|
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
#include "ardour_ui.h"
|
||||||
#include "ardour_window.h"
|
#include "ardour_window.h"
|
||||||
#include "ui_config.h"
|
#include "ui_config.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -837,7 +838,7 @@ MeterStrip::popup_level_meter_menu (GdkEventButton* ev)
|
|||||||
{
|
{
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
|
|
||||||
RadioMenuItem::Group group;
|
RadioMenuItem::Group group;
|
||||||
@ -888,7 +889,7 @@ MeterStrip::popup_name_label_menu (GdkEventButton* ev)
|
|||||||
{
|
{
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
|
|
||||||
RadioMenuItem::Group group;
|
RadioMenuItem::Group group;
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
|
|
||||||
#include "widgets/tooltips.h"
|
#include "widgets/tooltips.h"
|
||||||
|
|
||||||
|
#include "ardour_ui.h"
|
||||||
#include "ardour_window.h"
|
#include "ardour_window.h"
|
||||||
#include "enums_convert.h"
|
#include "enums_convert.h"
|
||||||
#include "mixer_strip.h"
|
#include "mixer_strip.h"
|
||||||
@ -2520,7 +2521,7 @@ MixerStrip::popup_level_meter_menu (GdkEventButton* ev)
|
|||||||
{
|
{
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
|
|
||||||
RadioMenuItem::Group group;
|
RadioMenuItem::Group group;
|
||||||
|
@ -2874,7 +2874,7 @@ Mixer_UI::popup_note_context_menu (GdkEventButton *ev)
|
|||||||
{
|
{
|
||||||
using namespace Gtk::Menu_Helpers;
|
using namespace Gtk::Menu_Helpers;
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
|
|
||||||
if (_selection.axes.empty()) {
|
if (_selection.axes.empty()) {
|
||||||
|
@ -1062,7 +1062,7 @@ SessionDialog::recent_context_mennu (GdkEventButton *ev)
|
|||||||
Gtk::TreeModel::Path tpath = recent_session_model->get_path(iter);
|
Gtk::TreeModel::Path tpath = recent_session_model->get_path(iter);
|
||||||
const bool is_child = tpath.up () && tpath.up ();
|
const bool is_child = tpath.up () && tpath.up ();
|
||||||
|
|
||||||
Gtk::Menu* m = manage (new Menu);
|
Gtk::Menu* m = ARDOUR_UI::instance()->shared_popup_menu ();
|
||||||
MenuList& items = m->items ();
|
MenuList& items = m->items ();
|
||||||
items.push_back (MenuElem (s, sigc::bind (sigc::hide_return (sigc::ptr_fun (&PBD::open_folder)), s)));
|
items.push_back (MenuElem (s, sigc::bind (sigc::hide_return (sigc::ptr_fun (&PBD::open_folder)), s)));
|
||||||
if (!is_child) {
|
if (!is_child) {
|
||||||
|
@ -69,6 +69,7 @@ VisibilityGroup::button_press_event (GdkEventButton* ev)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* memory leak: Gtk::Menu* */
|
||||||
menu()->popup (1, ev->time);
|
menu()->popup (1, ev->time);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ public:
|
|||||||
boost::function<boost::optional<bool> ()> = 0
|
boost::function<boost::optional<bool> ()> = 0
|
||||||
);
|
);
|
||||||
|
|
||||||
Gtk::Menu* menu ();
|
|
||||||
Gtk::Widget* list_view ();
|
Gtk::Widget* list_view ();
|
||||||
bool button_press_event (GdkEventButton *);
|
bool button_press_event (GdkEventButton *);
|
||||||
void update ();
|
void update ();
|
||||||
@ -87,6 +86,8 @@ private:
|
|||||||
void update_list_view ();
|
void update_list_view ();
|
||||||
bool should_actually_be_visible (Member const &) const;
|
bool should_actually_be_visible (Member const &) const;
|
||||||
|
|
||||||
|
Gtk::Menu* menu ();
|
||||||
|
|
||||||
std::vector<Member> _members;
|
std::vector<Member> _members;
|
||||||
std::string _xml_property_name;
|
std::string _xml_property_name;
|
||||||
ModelColumns _model_columns;
|
ModelColumns _model_columns;
|
||||||
|
Loading…
Reference in New Issue
Block a user