Destroy timeouts on Widget deletion.

Timeouts would tick, even after the parent Widget is long gone causing
use-after-free bugs.
This commit is contained in:
scorpion-26 2024-03-15 19:33:19 +01:00
parent 6fc09324ab
commit 4fdc81d949
2 changed files with 14 additions and 3 deletions

View file

@ -49,7 +49,12 @@ Widget::~Widget()
{
if (m_Widget)
{
LOG("Destroy widget and its children");
// LOG("Destroy widget and its children");
for (guint timeout : m_Timeouts)
{
g_source_remove(timeout);
}
m_Timeouts.clear();
m_Childs.clear();
gtk_widget_destroy(m_Widget);
}
@ -178,7 +183,8 @@ void Widget::ApplyPropertiesToWidget()
// Apply style
auto style = gtk_widget_get_style_context(m_Widget);
gtk_style_context_add_class(style, m_CssClass.c_str());
for (auto& cssClass : m_AdditionalClasses) {
for (auto& cssClass : m_AdditionalClasses)
{
gtk_style_context_add_class(style, cssClass.c_str());
}

View file

@ -135,6 +135,7 @@ public:
{
TimerCallback<TWidget> timeoutFn;
Widget* thisWidget;
guint id;
};
TimerPayload* payload = new TimerPayload();
payload->thisWidget = this;
@ -145,6 +146,7 @@ public:
TimerResult result = payload->timeoutFn(*(TWidget*)payload->thisWidget);
if (result == TimerResult::Delete)
{
payload->thisWidget->m_Timeouts.erase(payload->id);
delete payload;
return false;
}
@ -157,7 +159,8 @@ public:
return;
}
}
g_timeout_add(timeoutMS, +fn, payload);
payload->id = g_timeout_add(timeoutMS, +fn, payload);
m_Timeouts.insert(payload->id);
}
GtkWidget* Get() { return m_Widget; };
@ -182,6 +185,8 @@ protected:
Transform m_VerticalTransform; // Y
Callback<Widget> m_OnCreate;
std::unordered_set<guint> m_Timeouts;
};
class Box : public Widget