From f62c8c664d9e7419e4af2ca39b1767ddbb8fc709 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 20 Jul 2017 23:41:18 +0200 Subject: [PATCH] Fix crash when renaming track to an invalid name If the "Sorry I cannot do that" dialog is displayed from FloatingTextEntry::use_text(), the entry is still visible and accepts [focus] events. Also the dialog returns focus and multiple idle_delete_self() will be called for an Entry that's already being deleted. --- gtk2_ardour/floating_text_entry.cc | 46 +++++++++++++++++++++++------- gtk2_ardour/floating_text_entry.h | 1 + 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/gtk2_ardour/floating_text_entry.cc b/gtk2_ardour/floating_text_entry.cc index 29be2ef774..3dc74fe796 100644 --- a/gtk2_ardour/floating_text_entry.cc +++ b/gtk2_ardour/floating_text_entry.cc @@ -87,7 +87,8 @@ FloatingTextEntry::entry_focus_out (GdkEventFocus* ev) entry.remove_modal_grab (); if (entry_changed) { - use_text (entry.get_text (), 0); + disconect_signals (); + use_text (entry.get_text (), 0); /* EMIT SIGNAL */ } idle_delete_self (); @@ -108,7 +109,8 @@ FloatingTextEntry::button_press (GdkEventButton* ev) Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::ptr_fun (gtk_main_do_event), gdk_event_copy ((GdkEvent*) ev)), false)); if (entry_changed) { - use_text (entry.get_text (), 0); + disconect_signals (); + use_text (entry.get_text (), 0); /* EMIT SIGNAL */ } idle_delete_self (); @@ -119,6 +121,7 @@ FloatingTextEntry::button_press (GdkEventButton* ev) void FloatingTextEntry::activated () { + disconect_signals (); use_text (entry.get_text(), 0); // EMIT SIGNAL idle_delete_self (); } @@ -151,11 +154,13 @@ FloatingTextEntry::key_release (GdkEventKey* ev) * generates a different ev->keyval, rather than setting * ev->state. */ + disconect_signals (); use_text (entry.get_text(), -1); // EMIT SIGNAL, move to prev idle_delete_self (); return true; case GDK_Tab: + disconect_signals (); use_text (entry.get_text(), 1); // EMIT SIGNAL, move to next idle_delete_self (); return true; @@ -173,19 +178,40 @@ FloatingTextEntry::on_hide () entry.remove_modal_grab (); /* No hide button is shown (no decoration on the window), - so being hidden is equivalent to the Escape key or any other - method of cancelling the edit. - */ - - idle_delete_self (); + * so being hidden is equivalent to the Escape key or any other + * method of cancelling the edit. + * + * This is also used during disconect_signals() before calling + * use_text (). see note below. + * + * If signals are already disconnected, idle-delete must be + * in progress already. + */ + if (!_connections.empty ()) { + idle_delete_self (); + } Gtk::Window::on_hide (); } +void +FloatingTextEntry::disconect_signals () +{ + for (std::list::iterator i = _connections.begin(); i != _connections.end(); ++i) { + i->disconnect (); + } + /* the entry is floating on-top, emitting use_text() + * may result in another dialog being shown (cannot rename track) + * which would + * - be stacked below the floating text entry + * - return focus to the entry when closedA + * so we hide the entry here. + */ + hide (); +} + void FloatingTextEntry::idle_delete_self () { - for (std::list::iterator i = _connections.begin(); i != _connections.end(); ++i) { - i->disconnect (); - } + disconect_signals (); delete_when_idle (this); } diff --git a/gtk2_ardour/floating_text_entry.h b/gtk2_ardour/floating_text_entry.h index d70185a8a6..f52447de16 100644 --- a/gtk2_ardour/floating_text_entry.h +++ b/gtk2_ardour/floating_text_entry.h @@ -50,6 +50,7 @@ private: void changed (); void populate_popup (Gtk::Menu*); void idle_delete_self (); + void disconect_signals (); std::list _connections;