summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Henstridge <james@daa.com.au>2002-01-07 10:46:32 +0000
committerJames Henstridge <jamesh@src.gnome.org>2002-01-07 10:46:32 +0000
commit1bc78a422c4127c3d18cf21d1f28a16469d215b9 (patch)
tree3090f188ed51906be9532d6ce19a4b6ab73d6fe9
parent22ddb79502701fc47318ae05e3a7f5e085b9fa68 (diff)
downloadpygtk-1bc78a422c4127c3d18cf21d1f28a16469d215b9.tar.gz
add overriden implementation that allows threads while waiting, so some
2002-01-07 James Henstridge <james@daa.com.au> * gtk/gdk.override (_wrap_gdk_threads_enter): add overriden implementation that allows threads while waiting, so some other thread has a chance to give up the gdk lock. * gtk/gtkmodule.c (functions): remove stuff. * gtk/pygtk-private.h: remove definitions here as well. * gtk/pygtk.h (_PyGtk_FunctionStruct): remove destroy notify and thread block stuff. * gtk/gtkobject-support.c: remove pygtk_destroy_notify. * gtk/gtk.override (pygtk_tree_foreach_marshal): move this function here from gtkobject-support.c, and don't bother blocking threads. (_wrap_gtk_tree_selection_selected_foreach): same here -- don't need to unblock threads. (pygtk_tree_selection_marshal): move this function here from gtkobject-support.c. Convert to use pyg_block_threads. (_wrap_gtk_dialog_run): add overriden implementation that unblocks threads. (_wrap_gtk_main): use pyg_block_threads (_wrap_gtk_main_iteration): same. (_wrap_gtk_item_factory_create_items): same here. (_wrap_gtk_menu_popup): same here. (_wrap_gtk_clist_set_row_data): use pyg_destroy_notify (_wrap_gtk_timeout_add): same here. (_wrap_gtk_idle_add): same here. (_wrap_gtk_quit_add): same here. (_wrap_gtk_input_add_full): same here. (_wrap_gtk_ctree_node_set_row_data): same here. * gtk/gtkobject-support.c: remove PyGTK_BLOCK_THREADS and PyGTK_UNBLOCK_THREADS macros. (pygtk_destroy_notify): use pyg_block_threads. (pygtk_custom_destroy_notify): same. (pygtk_handler_marshal): same. (pygtk_input_marshal): same. * gtk/gdk.override (_wrap_gdk_threads_init): register gdk lock based recursive threads block/unblock functions. If threading was disabled at compile time, then this function will error out. * gtk/gdk.defs (threads_enter, threads_leave, threads_leave): add functions. * gobjectmodule.c (functions): add destroy_notify here as well. * pygobject.h: add destroy_notify to the PyGObject_Functions vtable.
-rw-r--r--ChangeLog52
-rw-r--r--gobject/gobjectmodule.c9
-rw-r--r--gobject/pygobject.h3
-rw-r--r--gobjectmodule.c9
-rw-r--r--gtk/gdk.defs16
-rw-r--r--gtk/gdk.override97
-rw-r--r--gtk/gtk.override110
-rw-r--r--gtk/gtkmodule.c7
-rw-r--r--gtk/gtkobject-support.c151
-rw-r--r--gtk/pygtk-private.h16
-rw-r--r--gtk/pygtk.h11
-rw-r--r--pygobject.h3
12 files changed, 283 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index 6aed478f..6407fac9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,57 @@
2002-01-07 James Henstridge <james@daa.com.au>
+ * gtk/gdk.override (_wrap_gdk_threads_enter): add overriden
+ implementation that allows threads while waiting, so some other
+ thread has a chance to give up the gdk lock.
+
+ * gtk/gtkmodule.c (functions): remove stuff.
+
+ * gtk/pygtk-private.h: remove definitions here as well.
+
+ * gtk/pygtk.h (_PyGtk_FunctionStruct): remove destroy notify and
+ thread block stuff.
+
+ * gtk/gtkobject-support.c: remove pygtk_destroy_notify.
+
+ * gtk/gtk.override (pygtk_tree_foreach_marshal): move this
+ function here from gtkobject-support.c, and don't bother blocking
+ threads.
+ (_wrap_gtk_tree_selection_selected_foreach): same here -- don't
+ need to unblock threads.
+ (pygtk_tree_selection_marshal): move this function here from
+ gtkobject-support.c. Convert to use pyg_block_threads.
+ (_wrap_gtk_dialog_run): add overriden implementation that unblocks
+ threads.
+ (_wrap_gtk_main): use pyg_block_threads
+ (_wrap_gtk_main_iteration): same.
+ (_wrap_gtk_item_factory_create_items): same here.
+ (_wrap_gtk_menu_popup): same here.
+ (_wrap_gtk_clist_set_row_data): use pyg_destroy_notify
+ (_wrap_gtk_timeout_add): same here.
+ (_wrap_gtk_idle_add): same here.
+ (_wrap_gtk_quit_add): same here.
+ (_wrap_gtk_input_add_full): same here.
+ (_wrap_gtk_ctree_node_set_row_data): same here.
+
+ * gtk/gtkobject-support.c: remove PyGTK_BLOCK_THREADS and
+ PyGTK_UNBLOCK_THREADS macros.
+ (pygtk_destroy_notify): use pyg_block_threads.
+ (pygtk_custom_destroy_notify): same.
+ (pygtk_handler_marshal): same.
+ (pygtk_input_marshal): same.
+
+ * gtk/gdk.override (_wrap_gdk_threads_init): register gdk lock
+ based recursive threads block/unblock functions. If threading was
+ disabled at compile time, then this function will error out.
+
+ * gtk/gdk.defs (threads_enter, threads_leave, threads_leave): add
+ functions.
+
+ * gobjectmodule.c (functions): add destroy_notify here as well.
+
+ * pygobject.h: add destroy_notify to the PyGObject_Functions
+ vtable.
+
* gobjectmodule.c (pyg_set_thread_block_funcs): handler for
registering thread block/unblock funcs.
(pygobject_destroy_notify): block threads during DECREF call.
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index 1e61fd2b..39fba99f 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -250,7 +250,7 @@ pyg_param_spec_new(GParamSpec *pspec)
/* -------------- class <-> wrapper manipulation --------------- */
static void
-pygobject_destroy_notify(gpointer user_data)
+pyg_destroy_notify(gpointer user_data)
{
PyObject *obj = (PyObject *)user_data;
@@ -1228,7 +1228,7 @@ pygobject_dealloc(PyGObject *self)
Py_INCREF(self); /* grab a reference on the wrapper */
self->hasref = TRUE;
g_object_set_qdata_full(obj, pygobject_ownedref_key,
- self, pygobject_destroy_notify);
+ self, pyg_destroy_notify);
g_object_unref(obj);
/* we ref the type, so subtype_dealloc() doesn't kill off our
@@ -1441,7 +1441,7 @@ pygobject_set_data(PyGObject *self, PyObject *args)
return NULL;
quark = g_quark_from_string(key);
Py_INCREF(data);
- g_object_set_qdata_full(self->obj, quark, data, pygobject_destroy_notify);
+ g_object_set_qdata_full(self->obj, quark, data, pyg_destroy_notify);
Py_INCREF(Py_None);
return Py_None;
}
@@ -3002,7 +3002,10 @@ static struct _PyGObject_Functions functions = {
pygobject_register_wrapper,
pygobject_lookup_class,
pygobject_new,
+
pyg_closure_new,
+ pyg_destroy_notify,
+
pyg_type_from_object,
pyg_type_wrapper_new,
pyg_enum_get_value,
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index 8fa45424..9918dd30 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -37,8 +37,10 @@ struct _PyGObject_Functions {
void (* register_wrapper)(PyObject *self);
PyTypeObject *(* lookup_class)(GType type);
PyObject *(* newgobj)(GObject *obj);
+
GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args,
PyObject *swap_data);
+ GDestroyNotify destroy_notify;
GType (* type_from_object)(PyObject *obj);
PyObject *(* type_wrapper_new)(GType type);
@@ -91,6 +93,7 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pygobject_lookup_class (_PyGObject_API->lookup_class)
#define pygobject_new (_PyGObject_API->newgobj)
#define pyg_closure_new (_PyGObject_API->closure_new)
+#define pyg_destroy_notify (_PyGObject_API->destroy_notify)
#define pyg_type_from_object (_PyGObject_API->type_from_object)
#define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new)
#define pyg_enum_get_value (_PyGObject_API->enum_get_value)
diff --git a/gobjectmodule.c b/gobjectmodule.c
index 1e61fd2b..39fba99f 100644
--- a/gobjectmodule.c
+++ b/gobjectmodule.c
@@ -250,7 +250,7 @@ pyg_param_spec_new(GParamSpec *pspec)
/* -------------- class <-> wrapper manipulation --------------- */
static void
-pygobject_destroy_notify(gpointer user_data)
+pyg_destroy_notify(gpointer user_data)
{
PyObject *obj = (PyObject *)user_data;
@@ -1228,7 +1228,7 @@ pygobject_dealloc(PyGObject *self)
Py_INCREF(self); /* grab a reference on the wrapper */
self->hasref = TRUE;
g_object_set_qdata_full(obj, pygobject_ownedref_key,
- self, pygobject_destroy_notify);
+ self, pyg_destroy_notify);
g_object_unref(obj);
/* we ref the type, so subtype_dealloc() doesn't kill off our
@@ -1441,7 +1441,7 @@ pygobject_set_data(PyGObject *self, PyObject *args)
return NULL;
quark = g_quark_from_string(key);
Py_INCREF(data);
- g_object_set_qdata_full(self->obj, quark, data, pygobject_destroy_notify);
+ g_object_set_qdata_full(self->obj, quark, data, pyg_destroy_notify);
Py_INCREF(Py_None);
return Py_None;
}
@@ -3002,7 +3002,10 @@ static struct _PyGObject_Functions functions = {
pygobject_register_wrapper,
pygobject_lookup_class,
pygobject_new,
+
pyg_closure_new,
+ pyg_destroy_notify,
+
pyg_type_from_object,
pyg_type_wrapper_new,
pyg_enum_get_value,
diff --git a/gtk/gdk.defs b/gtk/gdk.defs
index 8a01cf6e..c9628226 100644
--- a/gtk/gdk.defs
+++ b/gtk/gdk.defs
@@ -42,6 +42,22 @@
)
)
+(define-function threads_enter
+ (c-name "gdk_threads_enter")
+ (return-type "none")
+)
+
+(define-function threads_leave
+ (c-name "gdk_threads_leave")
+ (return-type "none")
+)
+
+(define-function threads_init
+ (c-name "gdk_threads_init")
+ (return-type "none")
+)
+
+
;; From /opt/gtk2/include/gtk-2.0/gdk/gdkcolor.h
(define-function gdk_colormap_get_type
diff --git a/gtk/gdk.override b/gtk/gdk.override
index 7746d056..cc90548f 100644
--- a/gtk/gdk.override
+++ b/gtk/gdk.override
@@ -1,6 +1,10 @@
/* -*- Mode: C; c-basic-offset: 4 -*- */
%%
headers
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#define NO_IMPORT_PYGOBJECT
#include "pygobject.h"
#include <gtk/gtk.h>
@@ -18,6 +22,99 @@ import pango.Layout as PyPangoLayout_Type
ignore-glob
*_get_type
%%
+override gdk_threads_init noargs
+
+/* block/unblock threads implementations using GDK lock to handle
+ * recursion (as in 1.2 version). Here is the comments about it from
+ * the 1.2 version of pygtk:*/
+
+/* 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;
+#define INITIAL_LOCK_COUNT 1
+
+static void
+pygdk_block_threads (void)
+{
+ 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);
+}
+static void
+pyg_unblock_threads (void)
+{
+ 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
+
+static PyObject *
+_wrap_gdk_threads_init(PyObject *self)
+{
+#ifdef ENABLE_PYGTK_THREADING
+ /* register gdk thread block/unblock routines with gobjectmodule */
+ pyg_set_thread_block_funcs (pygdk_block_threads, pygdk_unblock_threads);
+
+ gdk_threads_init();
+
+ Py_INCREF(Py_None);
+ return Py_None;
+#else
+ PyErr_SetString(PyExc_RuntimeError,
+ "pygtk threading disabled at compile time");
+ return NULL;
+#endif
+}
+%%
+override gdk_threads_enter noargs
+static PyObject *
+_wrap_gdk_threads_enter(PyObject *self)
+{
+ /* must allow threads while acquiring lock, or no other python
+ * code will execute while we wait! */
+ Py_BEGIN_ALLOW_THREADS;
+ gdk_threads_enter();
+ Py_END_ALLOW_THREADS;
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+%%
override gdk_draw_polygon kwargs
static PyObject *
_wrap_gdk_draw_polygon(PyGObject *self, PyObject *args, PyObject *kwargs)
diff --git a/gtk/gtk.override b/gtk/gtk.override
index 1599184b..eb2a0511 100644
--- a/gtk/gtk.override
+++ b/gtk/gtk.override
@@ -675,7 +675,7 @@ _wrap_gtk_clist_set_row_data(PyGObject *self, PyObject *args,
return NULL;
Py_INCREF(data);
gtk_clist_set_row_data_full(GTK_CLIST(self->obj), row, data,
- (GtkDestroyNotify)pygtk_destroy_notify);
+ (GtkDestroyNotify)pyg_destroy_notify);
Py_INCREF(Py_None);
return Py_None;
}
@@ -1518,6 +1518,26 @@ _wrap_gtk_tree_selection_get_selected(PyGObject *self)
}
%%
override gtk_tree_selection_selected_foreach
+static void
+pygtk_tree_foreach_marshal(GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ PyGtkCustomNotify *cunote = data;
+ PyObject *pypath, *retobj;
+
+ g_assert(cunote->func);
+
+ 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);
+}
static PyObject *
_wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args)
{
@@ -1530,16 +1550,53 @@ _wrap_gtk_tree_selection_selected_foreach(PyGObject *self, PyObject *args)
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 gboolean
+pygtk_tree_selection_marshal(GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *path,
+ gboolean path_currently_selected,
+ gpointer data)
+{
+ gboolean retval = FALSE;
+ PyGtkCustomNotify *cunote = data;
+ PyObject *pypath, *retobj;
+
+ pyg_block_threads();
+
+ g_assert(cunote->func);
+
+ 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;
+}
static PyObject *
_wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args)
{
@@ -1551,8 +1608,10 @@ _wrap_gtk_tree_selection_set_select_function(PyGObject *self, PyObject *args)
return NULL;
cunote = g_new0(PyGtkCustomNotify, 1);
- Py_XINCREF(cunote->func = pyfunc);
- Py_XINCREF(cunote->data = pyarg);
+ cunote->func = pyfunc;
+ cunote->data = pyarg;
+ Py_INCREF(cunote->func);
+ Py_XINCREF(cunote->data);
gtk_tree_selection_set_select_function(GTK_TREE_SELECTION(self->obj),
pygtk_tree_selection_marshal,
cunote,
@@ -1850,9 +1909,9 @@ override gtk_main noargs
static PyObject *
_wrap_gtk_main(PyObject *self)
{
- pygtk_unblock_threads();
+ pyg_unblock_threads();
gtk_main();
- pygtk_block_threads();
+ pyg_block_threads();
if (PyErr_Occurred())
return NULL;
Py_INCREF(Py_None);
@@ -1869,9 +1928,9 @@ _wrap_gtk_main_iteration(PyObject *self, PyObject *args, PyObject *kwargs)
if(!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:main_iteration", kwlist,
&block))
return NULL;
- pygtk_unblock_threads();
+ pyg_unblock_threads();
ret = gtk_main_iteration_do(block);
- pygtk_block_threads();
+ pyg_block_threads();
return PyInt_FromLong(ret);
}
%%
@@ -1907,8 +1966,8 @@ _wrap_gtk_timeout_add(PyObject *self, PyObject *args)
if (data == NULL)
return NULL;
return PyInt_FromLong(gtk_timeout_add_full(interval, NULL,
- (GtkCallbackMarshal)pygtk_handler_marshal,
- data, (GtkDestroyNotify)pygtk_destroy_notify));
+ (GtkCallbackMarshal)pygtk_handler_marshal,
+ data, (GtkDestroyNotify)pyg_destroy_notify));
}
%%
override gtk_idle_add
@@ -1943,7 +2002,7 @@ _wrap_gtk_idle_add(PyObject *self, PyObject *args)
return NULL;
return PyInt_FromLong(gtk_idle_add_full(GTK_PRIORITY_DEFAULT, NULL,
(GtkCallbackMarshal)pygtk_handler_marshal,
- data, (GtkDestroyNotify)pygtk_destroy_notify));
+ data, (GtkDestroyNotify)pyg_destroy_notify));
}
%%
override gtk_quit_add
@@ -1979,7 +2038,7 @@ _wrap_gtk_quit_add(PyObject *self, PyObject *args)
return NULL;
return PyInt_FromLong(gtk_quit_add_full(main_level, NULL,
(GtkCallbackMarshal)pygtk_handler_marshal,
- data, (GtkDestroyNotify)pygtk_destroy_notify));
+ data, (GtkDestroyNotify)pyg_destroy_notify));
}
%%
override gtk_input_add_full kwargs
@@ -2007,7 +2066,7 @@ _wrap_gtk_input_add_full(PyObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(callback);
return PyInt_FromLong(gtk_input_add_full(source, condition, NULL,
(GtkCallbackMarshal)pygtk_input_marshal, callback,
- (GtkDestroyNotify)pygtk_destroy_notify));
+ (GtkDestroyNotify)pyg_destroy_notify));
}
%%
override gtk_editable_insert_text kwargs
@@ -2033,7 +2092,7 @@ pygtk_item_factory_cb(PyObject *callback, guint action, GtkWidget *widget)
{
PyObject *ret;
- pygtk_block_threads();
+ pyg_block_threads();
ret = PyObject_CallFunction(callback, "iO", action,
pygobject_new((GObject *)widget));
if (ret == NULL) {
@@ -2041,7 +2100,7 @@ pygtk_item_factory_cb(PyObject *callback, guint action, GtkWidget *widget)
PyErr_Clear();
} else
Py_DECREF(ret);
- pygtk_unblock_threads();
+ pyg_unblock_threads();
}
static PyObject *
_wrap_gtk_item_factory_create_items(PyGObject *self, PyObject *args,
@@ -2109,7 +2168,7 @@ pygtk_menu_position(GtkMenu *menu, int *x, int *y, PyObject *func)
{
PyObject *ret;
- pygtk_block_threads();
+ pyg_block_threads();
ret = PyObject_CallFunction(func, "Oii", pygobject_new((GObject *)menu),
*x, *y);
if (ret == NULL || !PyArg_ParseTuple(ret, "ii", x, y)) {
@@ -2121,7 +2180,7 @@ pygtk_menu_position(GtkMenu *menu, int *x, int *y, PyObject *func)
} else {
Py_DECREF(ret);
}
- pygtk_unblock_threads();
+ pyg_unblock_threads();
}
static PyObject *
_wrap_gtk_menu_popup(PyGObject *self, PyObject *args, PyObject *kwargs)
@@ -2885,7 +2944,7 @@ _wrap_gtk_ctree_node_set_row_data(PyGObject *self, PyObject *args,
Py_INCREF(data);
gtk_ctree_node_set_row_data_full(GTK_CTREE(self->obj),
pyg_boxed_get(node, GtkCTreeNode), data,
- (GtkDestroyNotify)pygtk_destroy_notify);
+ (GtkDestroyNotify)pyg_destroy_notify);
Py_INCREF(Py_None);
return Py_None;
}
@@ -4136,6 +4195,19 @@ _wrap_gtk_dialog_new_with_buttons(PyGObject *self, PyObject *args,
return 0;
}
%%
+override gtk_dialog_run noargs
+static PyObject *
+_wrap_gtk_dialog_run(PyGObject *self)
+{
+ gint retval;
+
+ pyg_unblock_threads();
+ retval = gtk_dialog_run(GTK_DIALOG(self->obj));
+ pyg_block_threads();
+
+ return PyInt_FromLong(retval);
+}
+%%
override gtk_message_dialog_new kwargs
static int
_wrap_gtk_message_dialog_new(PyGObject *self, PyObject *args, PyObject *kwargs)
diff --git a/gtk/gtkmodule.c b/gtk/gtkmodule.c
index 96facdf3..cf2aee64 100644
--- a/gtk/gtkmodule.c
+++ b/gtk/gtkmodule.c
@@ -3,6 +3,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+
/* include this first, before NO_IMPORT_PYGOBJECT is defined */
#include <pygobject.h>
#include "pygtk-private.h"
@@ -18,12 +19,6 @@ extern PyMethodDef pygdk_functions[];
static struct _PyGtk_FunctionStruct functions = {
VERSION,
- FALSE,
-
- pygtk_block_threads,
- pygtk_unblock_threads,
-
- pygtk_destroy_notify,
&PyGdkAtom_Type, PyGdkAtom_New,
};
diff --git a/gtk/gtkobject-support.c b/gtk/gtkobject-support.c
index 286d7da6..41571d59 100644
--- a/gtk/gtkobject-support.c
+++ b/gtk/gtkobject-support.c
@@ -5,89 +5,17 @@
#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
-pygtk_destroy_notify(gpointer user_data)
-{
- PyObject *obj = (PyObject *)user_data;
-
- PyGTK_BLOCK_THREADS
- Py_DECREF(obj);
- PyGTK_UNBLOCK_THREADS
-}
-
-void
pygtk_custom_destroy_notify(gpointer user_data)
{
PyGtkCustomNotify *cunote = user_data;
- PyGTK_BLOCK_THREADS
+ pyg_block_threads();
Py_XDECREF(cunote->func);
Py_XDECREF(cunote->data);
- PyGTK_UNBLOCK_THREADS
+ pyg_unblock_threads();
g_free(cunote);
}
@@ -97,7 +25,7 @@ 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),
@@ -108,15 +36,15 @@ pygtk_handler_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args)
PyErr_Print();
PyErr_Clear();
*GTK_RETLOC_BOOL(args[0]) = FALSE;
- PyGTK_UNBLOCK_THREADS
- return;
+ pyg_unblock_threads();
+ return;
}
if (ret == Py_None || (PyInt_Check(ret) && PyInt_AsLong(ret) == 0))
*GTK_RETLOC_BOOL(args[0]) = FALSE;
else
*GTK_RETLOC_BOOL(args[0]) = TRUE;
Py_DECREF(ret);
- PyGTK_UNBLOCK_THREADS
+ pyg_unblock_threads();
}
/* callback for input handlers */
@@ -125,7 +53,7 @@ pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args)
{
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);
@@ -135,70 +63,7 @@ pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args)
PyErr_Clear();
} else
Py_DECREF(ret);
- PyGTK_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);
-
- PyGTK_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);
-
- PyGTK_UNBLOCK_THREADS
+ pyg_unblock_threads();
}
-gboolean
-pygtk_tree_selection_marshal(GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- gpointer data)
-{
- gboolean retval = FALSE;
- PyGtkCustomNotify *cunote = data;
- PyObject *pypath, *retobj;
-
- g_assert(cunote->func);
-
- PyGTK_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);
- }
-
- PyGTK_UNBLOCK_THREADS
-
- return retval;
-}
diff --git a/gtk/pygtk-private.h b/gtk/pygtk-private.h
index 12c58c3b..27e6edb8 100644
--- a/gtk/pygtk-private.h
+++ b/gtk/pygtk-private.h
@@ -22,12 +22,6 @@ extern PyTypeObject PyGdkAtom_Type;
/* 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);
void pygtk_input_marshal(gpointer a, PyObject *func, int nargs, GtkArg *args);
@@ -43,14 +37,4 @@ typedef struct {
void pygtk_custom_destroy_notify(gpointer user_data);
-gboolean pygtk_tree_selection_marshal(GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currenly_selected,
- gpointer data);
-void pygtk_tree_foreach_marshal(GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data);
-
#endif
diff --git a/gtk/pygtk.h b/gtk/pygtk.h
index 602b7f0a..e34dc174 100644
--- a/gtk/pygtk.h
+++ b/gtk/pygtk.h
@@ -9,12 +9,6 @@
struct _PyGtk_FunctionStruct {
char *pygtkVersion;
- gboolean fatalExceptions;
-
- void (* block_threads)(void);
- void (* unblock_threads)(void);
-
- GtkDestroyNotify destroy_notify;
PyTypeObject *gdkAtom_type;
PyObject *(* gdkAtom_new)(GdkAtom atom);
@@ -52,11 +46,6 @@ struct _PyGtk_FunctionStruct *_PyGtk_API;
/* type objects */
#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 */
#define PYGTK_VERSION (_PyGtk_API->pygtkVersion)
diff --git a/pygobject.h b/pygobject.h
index 8fa45424..9918dd30 100644
--- a/pygobject.h
+++ b/pygobject.h
@@ -37,8 +37,10 @@ struct _PyGObject_Functions {
void (* register_wrapper)(PyObject *self);
PyTypeObject *(* lookup_class)(GType type);
PyObject *(* newgobj)(GObject *obj);
+
GClosure *(* closure_new)(PyObject *callback, PyObject *extra_args,
PyObject *swap_data);
+ GDestroyNotify destroy_notify;
GType (* type_from_object)(PyObject *obj);
PyObject *(* type_wrapper_new)(GType type);
@@ -91,6 +93,7 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pygobject_lookup_class (_PyGObject_API->lookup_class)
#define pygobject_new (_PyGObject_API->newgobj)
#define pyg_closure_new (_PyGObject_API->closure_new)
+#define pyg_destroy_notify (_PyGObject_API->destroy_notify)
#define pyg_type_from_object (_PyGObject_API->type_from_object)
#define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new)
#define pyg_enum_get_value (_PyGObject_API->enum_get_value)