Skip to content

Commit

Permalink
Merge pull request #327 from mcorino/develop
Browse files Browse the repository at this point in the history
fix potential problems with cloning async method call events and impr…
  • Loading branch information
mcorino authored Nov 17, 2024
2 parents 4d85bda + aa1a75c commit 0c8b5f6
Show file tree
Hide file tree
Showing 9 changed files with 511 additions and 367 deletions.
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

0 comments on commit 0c8b5f6

Please sign in to comment.