diff --git a/ext/fox16/FXRuby.cpp b/ext/fox16/FXRuby.cpp
index 81bb2f1eb00c124a108b04dbcb122a85117a3c17..ad7feb07f8b3cfa168d798063222b263c7448aba 100644
--- a/ext/fox16/FXRuby.cpp
+++ b/ext/fox16/FXRuby.cpp
@@ -85,11 +85,15 @@ static st_table * FXRuby_Objects;
  * struct. It identifies the Ruby instance associated with a C++ object.
  * It also indicates whether this is merely a "borrowed" reference to
  * some C++ object (i.e. it's not one we need to destroy later).
+ *
+ * in_gc is set for FXWindows that are in garbage collection and must
+ * not call ruby code anymore.
  */
 
 struct FXRubyObjDesc {
   VALUE obj;
   bool borrowed;
+  bool in_gc;
   };
 
 
@@ -110,6 +114,7 @@ VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
       obj=SWIG_Ruby_NewPointerObj(ptr,ty,1);
       desc->obj=obj;
       desc->borrowed=true;
+      desc->in_gc=false;
       st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t>(desc));
       return obj;
       }
@@ -140,6 +145,25 @@ bool FXRbIsBorrowed(void* ptr){
     }
   }
 
+bool FXRbSetInGC(const void* ptr, bool enabled){
+  FXASSERT(ptr!=0);
+  FXRubyObjDesc *desc;
+  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
+    desc->in_gc=enabled;
+    return enabled;
+    }
+  return false;
+  }
+
+bool FXRbIsInGC(const void* ptr){
+  FXASSERT(ptr!=0);
+  FXRubyObjDesc *desc;
+  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
+    return desc->in_gc;
+    }
+  return false;
+  }
+
 
 /**
  * FXRbConvertPtr() is just a wrapper around SWIG_Ruby_ConvertPtr().
@@ -211,6 +235,7 @@ void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
   if(FXMALLOC(&desc,FXRubyObjDesc,1)){
     desc->obj=rubyObj;
     desc->borrowed=false;
+    desc->in_gc=false;
     st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t>(desc));
     }
   else{
@@ -1301,6 +1326,7 @@ void FXRbRange2LoHi(VALUE range,FXdouble& lo,FXdouble& hi){
 void FXRbCallVoidMethod(FXObject* recv, ID func) {
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
+  FXASSERT(!FXRbIsInGC(recv));
   rb_funcall(obj,func,0,NULL);
   }
 
diff --git a/ext/fox16/include/FXRbWindow.h b/ext/fox16/include/FXRbWindow.h
index 78099a9a7b98f4198a34b72d30d8a6ea7f28ae3b..1e702339ef67992f0793d8bf106002cdb32b506c 100644
--- a/ext/fox16/include/FXRbWindow.h
+++ b/ext/fox16/include/FXRbWindow.h
@@ -149,7 +149,7 @@ inline void klass ## _dropDisable(klass* self){ \
     FXRbCallVoidMethod(this,rb_intern("killFocus")); \
     } \
   void cls::changeFocus(FXWindow* child){ \
-    FXRbCallVoidMethod(this,rb_intern("changeFocus"),child); \
+    if(!FXRbIsInGC(this)) FXRbCallVoidMethod(this,rb_intern("changeFocus"),child); \
     } \
   void cls::setDefault(FXbool enable){ \
     FXRbCallVoidMethod(this,rb_intern("setDefault"),enable); \
@@ -173,7 +173,7 @@ inline void klass ## _dropDisable(klass* self){ \
     FXRbCallVoidMethod(this,rb_intern("position"),x,y,w,h); \
     } \
   void cls::recalc(){ \
-    FXRbCallVoidMethod(this,rb_intern("recalc")); \
+    if(!FXRbIsInGC(this)) FXRbCallVoidMethod(this,rb_intern("recalc")); \
     } \
   void cls::reparent(FXWindow* father,FXWindow* other){ \
     FXRbCallVoidMethod(this,rb_intern("reparent"),father,other); \
diff --git a/ext/fox16/include/FXRuby.h b/ext/fox16/include/FXRuby.h
index 1a1bd0e1c690a586fdcd3b411720070514351e30..49bb58e2a961195ab946349df2fa5e6792c68023 100644
--- a/ext/fox16/include/FXRuby.h
+++ b/ext/fox16/include/FXRuby.h
@@ -73,6 +73,8 @@ VALUE showHelper(VALUE self, int argc, VALUE *argv, TYPE *p, swig_type_info *typ
 // Wrapper around SWIG_Ruby_NewPointerObj()
 VALUE FXRbNewPointerObj(void *ptr, swig_type_info *typeinfo);
 bool FXRbIsBorrowed(void* ptr);
+bool FXRbSetInGC(const void* ptr, bool enabled);
+bool FXRbIsInGC(const void* ptr);
 
 // Wrapper around SWIG_TypeQuery()
 swig_type_info *FXRbTypeQuery(const char *name);
@@ -322,6 +324,7 @@ template<class TYPE>
 void FXRbCallVoidMethod(FXObject* recv,ID func, TYPE& arg){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
+  FXASSERT(!FXRbIsInGC(recv));
   rb_funcall(obj,func,1,to_ruby(arg));
   }
 
@@ -336,6 +339,7 @@ template<class TYPE>
 void FXRbCallVoidMethod(const FXObject* recv, ID func, TYPE& arg){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
+  FXASSERT(!FXRbIsInGC(recv));
   rb_funcall(obj,func,1,to_ruby(arg));
   }
 
diff --git a/ext/fox16/markfuncs.cpp b/ext/fox16/markfuncs.cpp
index 825a8c76ea1e3d6d6cb3cddd5728b3eee22c0957..87b75f609b137391bde31498760f16a99d2aeb12 100644
--- a/ext/fox16/markfuncs.cpp
+++ b/ext/fox16/markfuncs.cpp
@@ -53,6 +53,11 @@ void FXRbObject::markfunc(FXObject* obj){
   FXTRACE((100,"%s::markfunc(%p)\n",obj?obj->getClassName():"FXRbObject",obj));
   }
 
+static void FXRbSetInGCRecursive(FXWindow *window, bool enabled){
+  FXRbSetInGC( window, true );
+  if(window->getParent()) FXRbSetInGCRecursive( window->getParent(), enabled );
+  }
+
 
 void FXRbObject::freefunc(FXObject* self){
   if(self!=0){
@@ -66,6 +71,17 @@ void FXRbObject::freefunc(FXObject* self){
     FXASSERT(classname!=0);
     FXASSERT(strlen(classname)>3);
     if(classname[0]=='F' && classname[1]=='X' && classname[2]=='R' && classname[3]=='b'){
+      // FXWindow destructor calls recalc() and changeFocus() of it's parent window.
+      // Since these methods are routed back to Ruby code, but calling Ruby code from
+      // GC isn't a good idea, we mark the parent window as "in_gc", so that it will
+      // ignore recalc() and changeFocus() calls completely.
+      // The parent window should also be scheduled to be free'd. In the other case,
+      // the child window would have been marked as used.
+      if(self->isMemberOf(FXMETACLASS(FXWindow))){
+        if(FXWindow *parent = dynamic_cast<FXWindow*>(self)->getParent()){
+          FXRbSetInGCRecursive( parent, true );
+          }
+        }
       delete self;
       }
     else{