Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix potential problems with cloning async method call events and impr… #327

Merged
merged 8 commits into from
Nov 17, 2024
18 changes: 9 additions & 9 deletions ext/wxruby3/include/wxRubyApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@ class wxRubyApp : public wxApp
else if (rb_obj_is_kind_of(rb_obj, wxRuby_GetDefaultEventClass()) )
rb_gc_mark(rb_obj);
}
else if (TYPE(rb_obj) == T_ARRAY )
{
VALUE proc = rb_ary_entry(rb_obj, 0);
if (rb_obj_is_kind_of(proc, rb_cProc) || rb_obj_is_kind_of(proc, rb_cMethod))
{
// keep the async call alive
rb_gc_mark(rb_obj);
}
}
// else if (TYPE(rb_obj) == T_ARRAY )
// {
// VALUE proc = rb_ary_entry(rb_obj, 0);
// if (rb_obj_is_kind_of(proc, rb_cProc) || rb_obj_is_kind_of(proc, rb_cMethod))
// {
// // keep the async call alive
// rb_gc_mark(rb_obj);
// }
// }
}

// Implements GC protection across wxRuby. Always called because
Expand Down
28 changes: 17 additions & 11 deletions ext/wxruby3/swig/mark_free_impl.i
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ WXRUBY_EXPORT void GC_mark_wxWindow(void *ptr)
std::wcout << "* GC_mark_wxWindow - found sizer" << std::endl;
#endif
VALUE rb_sizer = SWIG_RubyInstanceFor(wx_sizer);
if ( rb_sizer != Qnil )
if ( rb_sizer != Qnil )
GC_mark_SizerBelongingToWindow(wx_sizer, rb_sizer);
}

Expand All @@ -235,22 +235,28 @@ WXRUBY_EXPORT void GC_mark_wxWindow(void *ptr)
std::wcout << "* GC_mark_wxWindow - found caret" << std::endl;
#endif
VALUE rb_caret = SWIG_RubyInstanceFor(wx_caret);
rb_gc_mark(rb_caret);
rb_gc_mark(rb_caret);
}

#ifdef __WXRB_DEBUG__
if (wxRuby_TraceLevel()>2)
std::wcout << "* GC_mark_wxWindow - getting droptarget" << std::endl;
#endif
wxDropTarget* wx_droptarget = wx_win->GetDropTarget();
if ( wx_droptarget )
static WXWidget WXWidget_NULL {};

// be careful; getting drop target may require fully created window (default ctors do not call Create())
if (wx_win->GetHandle() != WXWidget_NULL)
{
#ifdef __WXRB_DEBUG__
if (wxRuby_TraceLevel()>2)
std::wcout << "* GC_mark_wxWindow - found droptarget" << std::endl;
std::wcout << "* GC_mark_wxWindow - getting droptarget" << std::endl;
#endif
VALUE rb_droptarget = SWIG_RubyInstanceFor(wx_droptarget);
rb_gc_mark(rb_droptarget);
wxDropTarget* wx_droptarget = wx_win->GetDropTarget();
if ( wx_droptarget )
{
#ifdef __WXRB_DEBUG__
if (wxRuby_TraceLevel()>2)
std::wcout << "* GC_mark_wxWindow - found droptarget" << std::endl;
#endif
VALUE rb_droptarget = SWIG_RubyInstanceFor(wx_droptarget);
rb_gc_mark(rb_droptarget);
}
}

#ifdef __WXRB_DEBUG__
Expand Down
42 changes: 30 additions & 12 deletions ext/wxruby3/swig/wx.i
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ WXRUBY_EXPORT VALUE wxRuby_WrapWxObjectInRuby(wxObject *wx_obj)
// generated on the C++ side.
// Cached reference to EvtHandler evt_type_id -> ruby_event_class map
static VALUE Evt_Type_Map = NULL;
static VALUE WxRuby_cAsyncProcCallEvent = Qnil;

#ifdef __WXRB_DEBUG__
WXRUBY_EXPORT VALUE wxRuby_WrapWxEventInRuby(void* rcvr, wxEvent *wx_event)
Expand All @@ -240,17 +241,31 @@ WXRUBY_EXPORT VALUE wxRuby_WrapWxEventInRuby(wxEvent *wx_event)
std::wcout << "* wxRuby_WrapWxEventInRuby(rcvr=" << rcvr << ", " << wx_event << ":{" << wx_event->GetEventType() << "@" << wx_event->GetEventObject() << "})" << std::endl;
#endif

// Then, look up the event type in this hash (MUCH faster than calling
// EvtHandler.evt_class_for_type method)
VALUE rb_event_type_id = INT2NUM( wx_event->GetEventType() );
VALUE rb_event_class = rb_hash_aref(Evt_Type_Map, rb_event_type_id);

// Check we have a valid class; warn and map to default Wx::Event if not
if ( NIL_P(rb_event_class) )
VALUE rb_event_type_id = INT2NUM(wx_event->GetEventType());
VALUE rb_event_class = Qnil;
// wxEVT_ASYNC_METHOD_CALL is a special case which has no Ruby class mapping registered
if (wx_event->GetEventType() == wxEVT_ASYNC_METHOD_CALL)
{
rb_event_class = wxRuby_GetDefaultEventClass ();
wxString class_name( wx_event->GetClassInfo()->GetClassName() );
rb_warning("Unmapped event type %i (%s)", wx_event->GetEventType(), (const char *)class_name.mb_str());
if (WxRuby_cAsyncProcCallEvent == Qnil)
{
WxRuby_cAsyncProcCallEvent = rb_eval_string("Wx::AsyncProcCallEvent");
}
rb_event_class = WxRuby_cAsyncProcCallEvent;
}
else
{
// Then, look up the event type in this hash (MUCH faster than calling
// EvtHandler.evt_class_for_type method)
rb_event_type_id = INT2NUM( wx_event->GetEventType());
rb_event_class = rb_hash_aref(Evt_Type_Map, rb_event_type_id);

// Check we have a valid class; warn and map to default Wx::Event if not
if (NIL_P(rb_event_class))
{
rb_event_class = wxRuby_GetDefaultEventClass ();
wxString class_name( wx_event->GetClassInfo()->GetClassName() );
rb_warning("Unmapped event type %i (%s)", wx_event->GetEventType(), (const char *)class_name.mb_str());
}
}

// Now, see if we have a tracked instance of this object already
Expand All @@ -264,7 +279,7 @@ WXRUBY_EXPORT VALUE wxRuby_WrapWxEventInRuby(wxEvent *wx_event)
// really the right thing, and not some stale reference.
if ( rb_event != Qnil )
{
if ( rb_obj_is_kind_of(rb_event, rb_event_class ) )
if (rb_obj_is_kind_of(rb_event, rb_event_class))
return rb_event; // OK
else
SWIG_RubyRemoveTracking((void *)wx_event); // Remove stale ref
Expand All @@ -275,7 +290,10 @@ WXRUBY_EXPORT VALUE wxRuby_WrapWxEventInRuby(wxEvent *wx_event)
rb_event = Data_Wrap_Struct(rb_event_class, 0, 0, 0);
DATA_PTR(rb_event) = wx_event;
// do not forget to mark the instance with the mangled swig type name
swig_type_info* type = wxRuby_GetSwigTypeForClass(rb_event_class);
// (as there is no swig_type for the Wx::AsyncProcCallEvent class use it's base Wx::Event)
swig_type_info* type = wx_event->GetEventType() == wxEVT_ASYNC_METHOD_CALL ?
wxRuby_GetSwigTypeForClass(wxRuby_GetDefaultEventClass()) :
wxRuby_GetSwigTypeForClass(rb_event_class);
rb_iv_set(rb_event, "@__swigtype__", rb_str_new2(type->name));

#if __WXRB_DEBUG__
Expand Down
Loading
Loading