I had sent a patch earlier that did this and works fine, but unfortunately
it seems as if some of my submissions are disappearing into a black hole.

Latest patch attached,
-- Elliot

? autom4te.cache
? obj
? t.py
Index: configure.in
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/configure.in,v
retrieving revision 1.46
diff -u -r1.46 configure.in
--- configure.in        2001/10/08 19:46:55     1.46
+++ configure.in        2001/10/10 14:59:14
@@ -46,7 +46,7 @@
   AC_MSG_RESULT(no)
 fi
 
-AM_PATH_GLIB_2_0(1.3.9,,[AC_MSG_ERROR(maybe you want the gtk-gnome-1-2 
branch?)],gobject)
+AM_PATH_GLIB_2_0(1.3.9,,[AC_MSG_ERROR(maybe you want the gtk-gnome-1-2 
+branch?)],gobject $extra_mods)
 PKG_CHECK_MODULES(PANGO, pango >= 0.20,,[AC_MSG_ERROR(maybe you want the 
gtk-gnome-1-2 branch?)])
 AC_SUBST(PANGO_CFLAGS)
 AC_SUBST(PANGO_LIBS)
Index: gobjectmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gobjectmodule.c,v
retrieving revision 1.63
diff -u -r1.63 gobjectmodule.c
--- gobjectmodule.c     2001/10/05 19:28:33     1.63
+++ gobjectmodule.c     2001/10/10 14:59:14
@@ -1,4 +1,6 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
+#include "config.h"
+
 #define _INSIDE_PYGOBJECT_
 #include "pygobject.h"
 
@@ -10,6 +12,8 @@
 staticforward PyTypeObject PyGObject_Type;
 static void pygobject_dealloc(PyGObject *self);
 static int  pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
+static void pyg_block_threads(void);
+static void pyg_unblock_threads(void);
 
 static void
 object_free(PyObject *op)
@@ -50,7 +54,7 @@
     char buf[80];
     const gchar *name = g_type_name(self->type);
 
-    g_snprintf(buf, sizeof(buf), "<GType %s>",
+    g_snprintf(buf, sizeof(buf), "<GType %s (%u)>",
               name?name:"invalid", self->type);
     return PyString_FromString(buf);
 }
@@ -221,9 +225,9 @@
 {
     PyObject *obj = (PyObject *)user_data;
 
-    /* PyGTK_BLOCK_THREADS */
+    pyg_block_threads();
     Py_DECREF(obj);
-    /* PyGTK_UNBLOCK_THREADS */
+    pyg_unblock_threads();
 }
 
 static void
@@ -487,8 +491,8 @@
     PyGBoxed *self;
     PyTypeObject *tp;
 
-    g_return_if_fail(boxed_type != 0);
-    g_return_if_fail(!copy_boxed || (copy_boxed && own_ref));
+    g_return_val_if_fail(boxed_type != 0, NULL);
+    g_return_val_if_fail(!copy_boxed || (copy_boxed && own_ref), NULL);
 
     if (!boxed) {
        Py_INCREF(Py_None);
@@ -639,6 +643,24 @@
        Py_DECREF(gtype);
     }
 
+    if(PyType_Check(obj)) {
+       PyTypeObject *tobj = (PyTypeObject *)obj;
+       if(tobj == &PyFloat_Type)
+           return G_TYPE_DOUBLE;
+       else if(tobj == &PyInt_Type)
+           return G_TYPE_INT;
+       else if(tobj == &PyLong_Type)
+           return G_TYPE_LONG;
+       else if(tobj == &PyString_Type)
+           return G_TYPE_STRING;
+       else if(tobj == &PyBaseObject_Type)
+           return PY_TYPE_OBJECT;
+       else if(tobj == &PyCObject_Type)
+           return G_TYPE_POINTER;
+       else if(tobj == Py_None->ob_type)
+           return G_TYPE_NONE;
+    }
+
     PyErr_Clear();
     PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
     return 0;
@@ -891,15 +913,16 @@
     PyObject *swap_data; /* other object for gtk_signal_connect_object */
 };
 
-/* XXXX - must handle multithreadedness here */
 static void
 pyg_closure_destroy(gpointer data, GClosure *closure)
 {
     PyGClosure *pc = (PyGClosure *)closure;
 
+    pyg_block_threads();
     Py_DECREF(pc->callback);
     Py_XDECREF(pc->extra_args);
     Py_XDECREF(pc->swap_data);
+    pyg_unblock_threads();
 }
 
 /* XXXX - need to handle python thread context stuff */
@@ -915,6 +938,7 @@
     PyObject *params, *ret;
     guint i;
 
+    pyg_block_threads();
     /* construct Python tuple for the parameter values */
     params = PyTuple_New(n_param_values);
     for (i = 0; i < n_param_values; i++) {
@@ -929,7 +953,7 @@
            /* error condition */
            if (!item) {
                Py_DECREF(params);
-               /* XXXX - clean up if threading was used */
+               pyg_unblock_threads();
                return;
            }
            PyTuple_SetItem(params, i, item);
@@ -946,13 +970,13 @@
        /* XXXX - do fatal exceptions thing here */
        PyErr_Print();
        PyErr_Clear();
-       /* XXXX - clean up if threading was used */
+       pyg_unblock_threads();
        return;
     }
     if (return_value)
        pyg_value_from_pyobject(return_value, ret);
     Py_DECREF(ret);
-    /* XXXX - clean up if threading was used */
+    pyg_unblock_threads();
 }
 
 static GClosure *
@@ -966,10 +990,11 @@
     g_closure_set_marshal(closure, pyg_closure_marshal);
     Py_INCREF(callback);
     ((PyGClosure *)closure)->callback = callback;
-    if (extra_args) {
+    if (extra_args && extra_args != Py_None) {
        if (!PyTuple_Check(extra_args)) {
            PyObject *tmp = PyTuple_New(1);
            PySequence_SetItem(tmp, 0, extra_args);
+           Py_INCREF(extra_args);
            extra_args = tmp;
        } else {
             Py_INCREF(extra_args);
@@ -978,7 +1003,7 @@
     }
     if (swap_data) {
        Py_INCREF(swap_data);
-       ((PyGClosure *)closure)->swap_data;
+       ((PyGClosure *)closure)->swap_data = swap_data;
        closure->derivative_flag = TRUE;
     }
     return closure;
@@ -1013,6 +1038,7 @@
 
     g_return_if_fail(invocation_hint != NULL);
 
+    pyg_block_threads();
     /* get the object passed as the first argument to the closure */
     object = g_value_get_object(&param_values[0]);
     g_return_if_fail(object != NULL && G_IS_OBJECT(object));
@@ -1036,6 +1062,7 @@
     if (!method) {
        PyErr_Clear();
        Py_DECREF(object_wrapper);
+       pyg_unblock_threads();
        return;
     }
     Py_DECREF(object_wrapper);
@@ -1048,7 +1075,7 @@
        /* error condition */
        if (!item) {
            Py_DECREF(params);
-           /* XXXX - clean up if threading was used */
+           pyg_unblock_threads();
            return;
        }
        PyTuple_SetItem(params, i - 1, item);
@@ -1059,15 +1086,15 @@
        /* XXXX - do fatal exceptions thing here */
        PyErr_Print();
        PyErr_Clear();
-       /* XXXX - clean up if threading was used */
        Py_DECREF(method);
+       pyg_unblock_threads();
        return;
     }
     Py_DECREF(method);
     if (return_value)
        pyg_value_from_pyobject(return_value, ret);
     Py_DECREF(ret);
-    /* XXXX - clean up if threading was used */
+    pyg_unblock_threads();
 }
 
 static GClosure *
@@ -1112,7 +1139,9 @@
     PyObject_GC_UnTrack((PyObject *)self);
 
     if (self->inst_dict)
-       Py_DECREF(self->inst_dict);
+       {
+           Py_DECREF(self->inst_dict);
+       }
     self->inst_dict = NULL;
 
     /* the following causes problems with subclassed types */
@@ -1330,7 +1359,7 @@
        PyErr_SetString(PyExc_TypeError, "second argument must be callable");
        return NULL;
     }
-    if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
+    if (!g_signal_parse_name(name, pyg_type_from_object((PyObject *)self),
                             &sigid, &detail, TRUE)) {
        PyErr_SetString(PyExc_TypeError, "unknown signal name");
        return NULL;
@@ -1553,13 +1582,16 @@
            return NULL;
        }
     }
-    if (query.return_type != G_TYPE_NONE)
+    if (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_INVALID)
        g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+    pyg_unblock_threads();
     g_signal_emitv(params, signal_id, detail, &ret);
+    pyg_block_threads();
     for (i = 0; i < query.n_params + 1; i++)
        g_value_unset(&params[i]);
     g_free(params);
-    if (query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE != G_TYPE_NONE) {
+    if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE
+       && (query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_INVALID) {
        py_ret = pyg_value_as_pyobject(&ret);
        g_value_unset(&ret);
     } else {
@@ -2263,7 +2295,6 @@
     g_type_class_unref(fclass);
 }
 
-
 /* ----------------- gobject module initialisation -------------- */
 
 static struct _PyGObject_Functions functions = {
@@ -2288,8 +2319,55 @@
 
   pyg_enum_add_constants,
   pyg_flags_add_constants,
+  pyg_block_threads,
+  pyg_unblock_threads,
+  NULL, /* gdk_threads_enter */
+  NULL /* gdk_threads_leave */
 };
 
+
+#ifdef ENABLE_PYGTK_THREADING
+static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT;
+static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT;
+#  define INITIAL_LOCK_COUNT 1
+#endif
+
+static void
+pyg_block_threads(void)
+{
+#ifdef ENABLE_PYGTK_THREADING
+    gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));
+    g_assert(functions.block_threads == pyg_block_threads);
+    if (counter == INITIAL_LOCK_COUNT) {
+       PyThreadState *_save;
+       _save = g_static_private_get(&pythreadstate_key);
+       if(functions.gdk_threads_leave)
+           functions.gdk_threads_leave();
+       Py_BLOCK_THREADS;
+    }                                                                     
+    counter--;
+    g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);
+#endif
+}
+
+static void
+pyg_unblock_threads(void)
+{
+#ifdef ENABLE_PYGTK_THREADING
+    gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));
+    g_assert(functions.unblock_threads == pyg_unblock_threads);
+    counter++;
+    if (counter == INITIAL_LOCK_COUNT) {
+       PyThreadState *_save;
+       Py_UNBLOCK_THREADS;
+       if(functions.gdk_threads_enter)
+           functions.gdk_threads_enter();
+       g_static_private_set(&pythreadstate_key, _save, NULL);
+    }
+    g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);
+#endif
+}
+
 DL_EXPORT(void)
 initgobject(void)
 {
@@ -2301,6 +2379,12 @@
     m = Py_InitModule("gobject", pygobject_functions);
     d = PyModule_GetDict(m);
 
+    /* initialise gthread if appropriate ... */
+#ifdef ENABLE_PYGTK_THREADING
+    /* it is required that this function be called to enable the thread
+     * safety functions */
+    g_thread_init(NULL);
+#endif
     g_type_init();
 
     PY_TYPE_OBJECT = g_boxed_type_register_static("PyObject",
Index: pango.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/pango.override,v
retrieving revision 1.6
diff -u -r1.6 pango.override
--- pango.override      2001/10/08 09:01:36     1.6
+++ pango.override      2001/10/10 14:59:14
@@ -1,8 +1,10 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include <pygobject.h>
+#define PANGO_ENABLE_BACKEND 1
 #include <pango/pango.h>
 
 %%
Index: pygobject.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/pygobject.h,v
retrieving revision 1.18
diff -u -r1.18 pygobject.h
--- pygobject.h 2001/09/28 23:43:46     1.18
+++ pygobject.h 2001/10/10 14:59:14
@@ -61,6 +61,10 @@
                                const gchar *strip_prefix);
     void (* flags_add_constants)(PyObject *module, GType flags_type,
                                 const gchar *strip_prefix);
+    void (* block_threads)(void);
+    void (* unblock_threads)(void);
+    void (* gdk_threads_enter)(void);
+    void (* gdk_threads_leave)(void);
 };
 
 #ifndef _INSIDE_PYGOBJECT_
@@ -89,6 +93,8 @@
 #define pyg_boxed_new              (_PyGObject_API->boxed_new)
 #define pyg_enum_add_constants     (_PyGObject_API->enum_add_constants)
 #define pyg_flags_add_constants    (_PyGObject_API->flags_add_constants)
+#define pyg_block_threads          (_PyGObject_API->block_threads)
+#define pyg_unblock_threads        (_PyGObject_API->unblock_threads)
 
 #define init_pygobject() { \
     PyObject *gobject = PyImport_ImportModule("gobject"); \
Index: codegen/codegen.py
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/codegen/codegen.py,v
retrieving revision 1.32
diff -u -r1.32 codegen.py
--- codegen/codegen.py  2001/10/08 09:01:37     1.32
+++ codegen/codegen.py  2001/10/10 14:59:15
@@ -781,6 +781,7 @@
 
 def write_source(parser, overrides, prefix, fp=FileOutput(sys.stdout)):
     fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
+    fp.write('#include "config.h"\n')
     fp.write('#include <Python.h>\n\n\n')
     fp.write(overrides.get_headers())
     fp.resetline()
Index: gtk/gdk.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gdk.override,v
retrieving revision 1.8
diff -u -r1.8 gdk.override
--- gtk/gdk.override    2001/10/08 09:01:38     1.8
+++ gtk/gdk.override    2001/10/10 14:59:15
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include "pygobject.h"
 #include <gtk/gtk.h>
Index: gtk/gtk.defs
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtk.defs,v
retrieving revision 1.71
diff -u -r1.71 gtk.defs
--- gtk/gtk.defs        2001/10/09 04:05:33     1.71
+++ gtk/gtk.defs        2001/10/10 14:59:15
@@ -4193,8 +4193,6 @@
   (return-type "GtkShadowType")
 )
 
-
-
 ;; From /opt/gtk2/include/gtk-2.0/gtk/gtkgamma.h
 
 (define-function gtk_gamma_curve_get_type
@@ -13226,8 +13224,12 @@
     '("GtkTreeIter*" "iter")
   )
 )
-
 
+(define-method clear
+  (of-object "GtkTreeStore")
+  (c-name "gtk_tree_store_clear")
+  (return-type "none")
+)
 
 ;; From /opt/gtk2/include/gtk-2.0/gtk/gtktreeview.h
 
@@ -13977,9 +13979,6 @@
 
 
 ;; From /opt/gtk2/include/gtk-2.0/gtk/gtktypeutils.h
-
-
-
 
 ;; From /opt/gtk2/include/gtk-2.0/gtk/gtkvbbox.h
 
Index: gtk/gtk.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtk.override,v
retrieving revision 1.65
diff -u -r1.65 gtk.override
--- gtk/gtk.override    2001/10/08 09:01:38     1.65
+++ gtk/gtk.override    2001/10/10 14:59:15
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include "pygobject.h"
 #include <gtk/gtk.h>
@@ -1324,6 +1325,45 @@
     }
 }
 %%
+override gtk_tree_selection_selected_foreach
+static PyObject *
+_wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args)
+{
+  PyObject *pyfunc, *pyarg = NULL;
+  PyGtkCustomNotify cunote;
+
+  if(!PyArg_ParseTuple(args, "O|O:GtkTreeSelection.selected_foreach", &pyfunc, 
+&pyarg))
+    return NULL;
+
+  cunote.func = pyfunc;
+  cunote.data = pyarg;
+  pygtk_unblock_threads();
+  gtk_tree_selection_selected_foreach(GTK_TREE_SELECTION(self->obj), 
+pygtk_tree_foreach_marshal, &cunote);
+  pygtk_block_threads();
+
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+%%
+override gtk_tree_selection_set_select_function
+static PyObject *
+_wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args)
+{
+  PyObject *pyfunc, *pyarg = NULL;
+  PyGtkCustomNotify *cunote;
+
+  if(!PyArg_ParseTuple(args, "O|O:GtkTreeSelection.set_select_function", &pyfunc, 
+&pyarg))
+    return NULL;
+
+  cunote = g_new0(PyGtkCustomNotify, 1);
+  Py_XINCREF(cunote->func = pyfunc);
+  Py_XINCREF(cunote->data = pyarg);
+  gtk_tree_selection_set_select_function(GTK_TREE_SELECTION(self->obj), 
+pygtk_tree_selection_marshal, cunote,
+                                        pygtk_custom_destroy_notify);
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+%%
 override gtk_tree_selection_get_selected
 static PyObject *
 _wrap_gtk_tree_selection_get_selected(PyGObject *self, PyObject *args)
@@ -3937,6 +3977,24 @@
     gtk_object_sink(GTK_OBJECT(self->obj));
     pygobject_register_wrapper((PyObject *)self);
     return 0;
+}
+%%
+override gtk_dialog_run
+
+static PyObject *
+_wrap_gtk_dialog_run(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { NULL };
+    gint retval;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":GtkDialog.run", kwlist))
+        return NULL;
+
+    pyg_unblock_threads();
+    retval = gtk_dialog_run(GTK_DIALOG(self->obj));
+    pyg_block_threads();
+
+    return PyInt_FromLong(retval);
 }
 %%
 override gtk_message_dialog_new kwargs
Index: gtk/gtkgl.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkgl.override,v
retrieving revision 1.2
diff -u -r1.2 gtkgl.override
--- gtk/gtkgl.override  2000/06/26 14:14:48     1.2
+++ gtk/gtkgl.override  2001/10/10 14:59:15
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGTK
 #include "pygtk.h"
 
Index: gtk/gtkmodule.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkmodule.c,v
retrieving revision 1.22
diff -u -r1.22 gtkmodule.c
--- gtk/gtkmodule.c     2001/09/27 16:22:45     1.22
+++ gtk/gtkmodule.c     2001/10/10 14:59:15
@@ -20,9 +20,6 @@
     VERSION,
     FALSE,
 
-    pygtk_block_threads,
-    pygtk_unblock_threads,
-
     pygtk_destroy_notify,
 
     &PyGdkAtom_Type,  PyGdkAtom_New,
@@ -35,17 +32,12 @@
     PyObject *av;
     int argc, i;
     char **argv;
+    GSList *stock_ids, *cur;
+    char buf[128];
 
     /* initialise gobject */
     init_pygobject();
 
-    /* initialise gthread if appropriate ... */
-#ifdef ENABLE_PYGTK_THREADING
-    /* it is required that this function be called to enable the thread
-     * safety functions */
-    g_thread_init(NULL);
-#endif
-
     /* set the default python encoding to utf-8 */
     PyUnicode_SetDefaultEncoding("utf-8");
 
@@ -83,6 +75,37 @@
     PyDict_SetItemString(d, "_PyGtk_API",
                         PyCObject_FromVoidPtr(&functions, NULL));
 
+    stock_ids = gtk_stock_list_ids();
+    strcpy(buf, "STOCK_");
+    for(cur = stock_ids; cur; cur = stock_ids)
+      {
+       char *ctmp;
+       PyObject *obj;
+       int i;
+
+       ctmp = cur->data;
+       if(strncmp(ctmp, "gtk-", 4))
+         continue;
+       ctmp += 4;
+
+       strcpy(buf + sizeof("STOCK"), ctmp);
+       ctmp = buf + sizeof("STOCK");
+       for(i = 0; ctmp[i]; i++)
+         {
+           if(ctmp[i] == '-')
+             ctmp[i] = '_';
+           else if(ctmp[i] >= 'a' && ctmp[i] <= 'z')
+             ctmp[i] -= 'a'-'A';
+         }
+
+       obj = PyString_FromString(cur->data);
+       PyDict_SetItemString(d, buf, obj);
+       Py_DECREF(obj);
+       g_free(cur->data);
+       stock_ids = cur->next;
+       g_slist_free_1(cur);
+      }
+
     /* namespace all the gdk stuff in gtk.gdk ... */
     m = Py_InitModule("gtk.gdk", pygdk_functions);
     d = PyModule_GetDict(m);
@@ -93,4 +116,6 @@
     if (PyErr_Occurred())
        Py_FatalError("can't initialise module _gtk");
 
+    _PyGObject_API->gdk_threads_enter = gdk_threads_enter;
+    _PyGObject_API->gdk_threads_leave = gdk_threads_leave;
 }
Index: gtk/gtkobject-support.c
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/gtkobject-support.c,v
retrieving revision 1.12
diff -u -r1.12 gtkobject-support.c
--- gtk/gtkobject-support.c     2001/06/25 03:27:27     1.12
+++ gtk/gtkobject-support.c     2001/10/10 14:59:15
@@ -5,68 +5,6 @@
 
 #include "pygtk-private.h"
 
-/* ----------------- Thread stuff -------------------- */
-/* The threading hacks are based on ones supplied by Duncan Grisby
- * of AT&T Labs Cambridge.  Since then they have been modified a bit. */
-
-/* The threading code has been enhanced to be a little better with multiple
- * threads accessing GTK+.  Here are some notes on the changes by
- * Paul Fisher:
- *
- * If threading is enabled, we create a recursive version of Python's
- * global interpreter mutex using TSD.  This scheme makes it possible,
- * although rather hackish, for any thread to make a call into PyGTK,
- * as long as the GDK lock is held (that is, Python code is wrapped
- * around a threads_{enter,leave} pair).
- *
- * A viable alternative would be to wrap each and every GTK call, at
- * the Python/C level, with Py_{BEGIN,END}_ALLOW_THREADS.  However,
- * given the nature of Python threading, this option is not
- * particularly appealing.
- */
-
-
-#ifdef ENABLE_PYGTK_THREADING
-static GStaticPrivate pythreadstate_key = G_STATIC_PRIVATE_INIT;
-static GStaticPrivate counter_key = G_STATIC_PRIVATE_INIT;
-
-/* The global Python lock will be grabbed by Python when entering a
- * Python/C function; thus, the initial lock count will always be one.
- */
-#  define INITIAL_LOCK_COUNT 1
-#  define PyGTK_BLOCK_THREADS                                              \
-   {                                                                       \
-     gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));   \
-     if (counter == -INITIAL_LOCK_COUNT) {                                 \
-       PyThreadState *_save;                                               \
-       _save = g_static_private_get(&pythreadstate_key);                   \
-       Py_BLOCK_THREADS;                                                   \
-     }                                                                     \
-     counter++;                                                            \
-     g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);   \
-   }
-
-#  define PyGTK_UNBLOCK_THREADS                                            \
-   {                                                                       \
-     gint counter = GPOINTER_TO_INT(g_static_private_get(&counter_key));   \
-     counter--;                                                            \
-     if (counter == -INITIAL_LOCK_COUNT) {                                 \
-       PyThreadState *_save;                                               \
-       Py_UNBLOCK_THREADS;                                                 \
-       g_static_private_set(&pythreadstate_key, _save, NULL);              \
-     }                                                                     \
-     g_static_private_set(&counter_key, GINT_TO_POINTER(counter), NULL);   \
-   }
-
-
-#else /* !WITH_THREADS */
-#  define PyGTK_BLOCK_THREADS
-#  define PyGTK_UNBLOCK_THREADS
-#endif
-
-void pygtk_block_threads(void) { PyGTK_BLOCK_THREADS }
-void pygtk_unblock_threads(void) { PyGTK_UNBLOCK_THREADS }
-
 /* ------------------- object support */
 
 void
@@ -74,19 +12,30 @@
 {
     PyObject *obj = (PyObject *)user_data;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
     Py_DECREF(obj);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
 }
 
+void
+pygtk_custom_destroy_notify(gpointer user_data)
+{
+  PyGtkCustomNotify *cunote = user_data;
 
+  pyg_block_threads();
+  Py_XDECREF(cunote->func);
+  Py_XDECREF(cunote->data);
+  pyg_unblock_threads();
+  g_free(cunote);
+}
+
 /* used for timeout and idle functions */
 void
 pygtk_handler_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args)
 {
     PyObject *ret;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
 
     if (PyTuple_Check(func))
        ret = PyObject_CallObject(PyTuple_GetItem(func, 0),
@@ -101,7 +50,7 @@
            PyErr_Clear();
        }
        *GTK_RETLOC_BOOL(args[0]) = FALSE;
-       PyGTK_UNBLOCK_THREADS
+       pyg_unblock_threads();
            return;
     }
     if (ret == Py_None || (PyInt_Check(ret) && PyInt_AsLong(ret) == 0))
@@ -109,7 +58,7 @@
     else
        *GTK_RETLOC_BOOL(args[0]) = TRUE;
     Py_DECREF(ret);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
 }
 
 /* callback for input handlers */
@@ -118,7 +67,7 @@
 {
     PyObject *tuple, *ret;
 
-    PyGTK_BLOCK_THREADS
+    pyg_block_threads();
     tuple = Py_BuildValue("(ii)", GTK_VALUE_INT(args[0]),
                          GTK_VALUE_FLAGS(args[1]));
     ret = PyObject_CallObject(func, tuple);
@@ -132,8 +81,67 @@
        }
     } else
        Py_DECREF(ret);
-    PyGTK_UNBLOCK_THREADS
+    pyg_unblock_threads();
+}
+
+void
+pygtk_tree_foreach_marshal(GtkTreeModel *model,
+                          GtkTreePath *path,
+                          GtkTreeIter *iter,
+                          gpointer data)
+{
+  PyGtkCustomNotify *cunote = data;
+  PyObject *pypath, *retobj;
+
+  g_assert(cunote->func);
+
+  pyg_block_threads();
+
+  pypath = pygtk_tree_path_to_pyobject(path);
+  if(cunote->data)
+    retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, cunote->data);
+  else
+    retobj = PyEval_CallFunction(cunote->func, "(O)", pypath);
+  Py_DECREF(pypath);
+  Py_XDECREF(retobj);
+
+  pyg_unblock_threads();
 }
 
+gboolean
+pygtk_tree_selection_marshal(GtkTreeSelection  *selection,
+                            GtkTreeModel      *model,
+                            GtkTreePath       *path,
+                            gpointer           data)
+{
+  gboolean retval = FALSE;
+  PyGtkCustomNotify *cunote = data;
+  PyObject *pypath, *retobj;
+
+  g_assert(cunote->func);
+
+  pyg_block_threads();
+
+  pypath = pygtk_tree_path_to_pyobject(path);
+  if(cunote->data)
+    retobj = PyEval_CallFunction(cunote->func, "(OO)", pypath, cunote->data);
+  else
+    retobj = PyEval_CallFunction(cunote->func, "(O)", pypath);
+  Py_DECREF(pypath);
+  if(retobj)
+    {
+      if(retobj == Py_None);
+      else if(PyInt_Check(retobj))
+       retval = PyInt_AsLong(retobj) && TRUE;
+      else if(PyLong_Check(retobj))
+       retval = PyLong_AsLongLong(retobj) && TRUE;
+      else if(PyString_Check(retobj))
+       retval = PyString_GET_SIZE(retobj) && TRUE;
+
+      Py_DECREF(retobj);
+    }
 
+  pyg_unblock_threads();
 
+  return retval;
+}
Index: gtk/libglade.override
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/libglade.override,v
retrieving revision 1.9
diff -u -r1.9 libglade.override
--- gtk/libglade.override       2001/10/08 09:01:38     1.9
+++ gtk/libglade.override       2001/10/10 14:59:15
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4 -*- */
 %%
 headers
+#include "config.h"
 #define NO_IMPORT_PYGOBJECT
 #include <pygobject.h>
 #include <glade/glade.h>
Index: gtk/pygtk-private.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/pygtk-private.h,v
retrieving revision 1.18
diff -u -r1.18 pygtk-private.h
--- gtk/pygtk-private.h 2001/09/27 16:22:45     1.18
+++ gtk/pygtk-private.h 2001/10/10 14:59:15
@@ -22,10 +22,6 @@
 /* constructors for PyObject wrappers ... */
 PyObject *PyGdkAtom_New(GdkAtom atom);
 
-/* miscelaneous functions */
-void pygtk_block_threads(void);
-void pygtk_unblock_threads(void);
-
 void pygtk_destroy_notify(gpointer data);
 
 void pygtk_handler_marshal(gpointer a, PyObject *func, int nargs,GtkArg *args);
@@ -36,5 +32,20 @@
 GtkTreePath *pygtk_tree_path_from_pyobject(PyObject *object);
 
 static gboolean PyGtk_FatalExceptions = FALSE;
+
+typedef struct {
+  PyObject *func, *data;
+} PyGtkCustomNotify;
+
+void pygtk_custom_destroy_notify(gpointer user_data);
+
+gboolean pygtk_tree_selection_marshal(GtkTreeSelection  *selection,
+                                     GtkTreeModel      *model,
+                                     GtkTreePath       *path,
+                                     gpointer           data);
+void pygtk_tree_foreach_marshal(GtkTreeModel *model,
+                               GtkTreePath *path,
+                               GtkTreeIter *iter,
+                               gpointer data);
 
 #endif
Index: gtk/pygtk.h
===================================================================
RCS file: /cvs/gnome/gnome-python/pygtk/gtk/pygtk.h,v
retrieving revision 1.20
diff -u -r1.20 pygtk.h
--- gtk/pygtk.h 2001/09/28 23:43:47     1.20
+++ gtk/pygtk.h 2001/10/10 14:59:15
@@ -11,9 +11,6 @@
     char *pygtkVersion;
     gboolean fatalExceptions;
 
-    void (* block_threads)(void);
-    void (* unblock_threads)(void);
-
     GtkDestroyNotify destroy_notify;
 
     PyTypeObject *gdkAtom_type;
@@ -30,6 +27,9 @@
 /* routines to get the C object value out of the PyObject wrapper */
 #define PyGdkAtom_Get(v) (((PyGdkAtom_Object *)(v))->atom)
 
+#define pygtk_block_threads pyg_block_threads
+#define pygtk_unblock_threads pyg_unblock_threads
+
 /* this section is dependent on whether we are being included from gtkmodule.c
  * or not.  A similar source level interface should be provided in both
  * instances. */
@@ -53,8 +53,6 @@
 #define PyGdkAtom_New          (_PyGtk_API->gdkAtom_new)
 
 /* miscelaneous other functions */
-#define pygtk_block_threads (_PyGtk_API->block_threads)
-#define pygtk_unblock_threads (_PyGtk_API->unblock_threads)
 #define pygtk_destroy_notify (_PyGtk_API->destroy_notify)
 
 /* some variables */

Reply via email to