On Friday 12 February 2010 11:55:36 am Paolo Bonzini wrote:
> On 02/12/2010 10:59 AM, Gwenael Casaccio wrote:
> > On Thursday 11 February 2010 11:39:38 am Paolo Bonzini wrote:
> >>> Right now that works well (for example I can launch iLiad without any
> >>>
> >>> problem) I should fix the gtk_dialog_run because this function launch
> >>> an inner loop outside the same thread that the main gtk_loop; the two
> >>> loops are locked :D.
> >>
> >> I think it should not be hard to rewrite gtk_dialog_run in Smalltalk,
> >> see
> >>
> >> http://www.google.com/codesearch/p?hl=en#ErvFMsc8kPE/pub/GNOME/sources/g
> >> tk+ /2.6/gtk+-2.6.9.tar.gz|z8d-VbwUHqs/gtk+-2.6.9/gtk/gtkdialog.c
> >>
> >> around line 900.
> >
> > Normally a simple
> > run [
> >
> > self showAll
> >
> > ]
> >
> > That should be enough ^^
>
> When it is, the caller should have said "showAll". "Run" is blocking.
>
> Paolo
Hi,
you'll find as an attached file the first release of the new gtk event loop.
Gwen
diff --git a/packages/gtk/GtkImpl.st b/packages/gtk/GtkImpl.st
index 6a2d2fc..e3d86b6 100644
--- a/packages/gtk/GtkImpl.st
+++ b/packages/gtk/GtkImpl.st
@@ -487,24 +487,79 @@ GtkTextBuffer extend [
+CStruct subclass: SmalltalkClosure [
+ <category: 'GTK'>
+
+ <declaration: #( (#receiver #smalltalk)
+ (#selector #smalltalk)
+ (#data (#ptr #smalltalk))
+ (#widget #smalltalk)
+ (#n_params #int)
+ (#mutex #uLong)
+ (#status #int))>
+]
+
Gtk class extend [
+ | eventSem |
+
+ events [
+ <category: 'primitive'>
+
+ <cCall: 'gstGtkEvents' returning: #{SmalltalkClosure} args: #()>
+ ]
+
+ result: anObject mutex: aMutex [
+ <category: 'primitive'>
+
+ <cCall: 'gstGtkResult' returning: #void args: #(#smalltalk #uLong)>
+ ]
+
+ eventSemaphore: aSemaphore [
+ <category: 'primitive'>
+
+ <cCall: 'gstGtkEventSemaphore' returning: #void args: #(#smalltalk)>
+ ]
+
+ handleInnerEvent [
+
+ | event |
+ event := GTK.Gtk events.
+ event ifNotNil: [ | args |
+ args := Array new: event n_params value.
+ 1 to: args size do: [ :i | args at: i put: (event data value at: i - 1) ].
+ [ ^ (event receiver value perform: event selector value withArguments: args) ] on: Exception do: [ :exception |
+ Behavior debuggerClass open ] ]
+ ]
+
+ insideLoop [
+
+ | event |
+ eventSem wait.
+ event := GTK.Gtk events.
+ event ifNotNil: [ | args |
+ args := Array new: event n_params value.
+ 1 to: args size do: [ :i | args at: i put: (event data value at: i - 1) ].
+ [ GTK.Gtk result: (event receiver value perform: event selector value withArguments: args) mutex: event mutex value ] on: Exception do: [ :exception |
+ event status value: 0.
+ Behavior debuggerClass open.
+ GTK.Gtk result: nil mutex: event mutex value ] ]
+ ]
+
main [
"Main loop implementation. Same as gtk_main, but it lets Smalltalk
processes run. Like gtk_main, it is ended with Gtk>>#mainQuit."
<category: 'event loop'>
- | sem |
- sem := Semaphore new.
- "This call is asynchronous, so it leaves us waiting on the #wait call just
- below. Our loop starts as soon as the next bytecode is executed,
- because sem is asynchronously signalled by my_gtk_main."
- GTK.Gtk main: sem.
- sem wait.
-
- [GTK.Gtk mainIterationDo: false.
- GTK.Gtk shouldQuit]
- whileFalse: [Processor yield]
+
+ eventSem:= Semaphore new.
+ GTK.Gtk eventSemaphore: eventSem.
+
+ Processor yield.
+
+ GTK.Gtk mainLoop.
+ [ self insideLoop.
+ true ] whileTrue: [ "DOES NOT WORK :::::: Processor yield" ]
]
]
@@ -1071,6 +1126,15 @@ GTK.GtkTreeView extend [
]
]
+GTK.GtkDialog extend [
+
+ " TODO : add a block to evaluate after the execution of the dialog "
+ run [
+ self showAll
+ ]
+
+]
+
"Finish initialization. This will be done upon #returnFromSnapshot on
subsequent image loads."
diff --git a/packages/gtk/MoreFuncs.st b/packages/gtk/MoreFuncs.st
index a07ae29..d16210d 100644
--- a/packages/gtk/MoreFuncs.st
+++ b/packages/gtk/MoreFuncs.st
@@ -12,9 +12,9 @@ Gtk class extend [
]
- main: aSemaphore [
+ mainLoop [
<category: 'C call-outs'>
- <asyncCCall: 'gstGtkMain' args: #(#smalltalk )>
+ <asyncCCall: 'gstGtkMain' args: #()>
]
diff --git a/packages/gtk/gst-gtk.c b/packages/gtk/gst-gtk.c
index 45f6edf..dff089f 100644
--- a/packages/gtk/gst-gtk.c
+++ b/packages/gtk/gst-gtk.c
@@ -55,6 +55,8 @@
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
+#include <pthread.h>
+
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <glib-object.h>
@@ -70,6 +72,22 @@
#include "gst-gtk.h"
#include "placer.h"
+static GThread *main_thread = NULL;
+static OOP result = NULL;
+static OOP event_sem = NULL;
+
+typedef struct SmalltalkClosureStruct {
+ OOP receiver;
+ OOP selector;
+ OOP *data;
+ OOP widget;
+ int n_params;
+ GMutex *mutex;
+ int status
+} SmalltalkClosureStruct;
+
+static SmalltalkClosureStruct *event;
+
typedef struct SmalltalkClosure
{
GClosure closure;
@@ -133,7 +151,7 @@ static const GTypeValueTable gtype_oop_value_table = {
static GType G_TYPE_OOP;
/* Start the main event loop and then signal OOP. */
-static void my_gtk_main (OOP semaphore);
+static void my_gtk_main ();
/* Wait in the main event loop until there are no pending events. */
static void my_gtk_main_iteration ();
@@ -557,9 +575,9 @@ invoke_smalltalk_closure (GClosure *closure,
gpointer marshal_data)
{
SmalltalkClosure *stc = (SmalltalkClosure *) closure;
- OOP *args = alloca (sizeof (OOP) * stc->n_params);
+ OOP *args = malloc (sizeof (OOP) * stc->n_params);
- OOP resultOOP;
+ OOP resultOOP = NULL;
int i;
/* Less parameters than the event has, discard the ones in excess. */
@@ -587,8 +605,9 @@ invoke_smalltalk_closure (GClosure *closure,
{
if (stc->n_params > n_param_values + 1)
args[i++] = stc->widget;
- if (stc->n_params > n_param_values)
+ if (stc->n_params > n_param_values) {
args[i++] = stc->data;
+ }
}
else
{
@@ -596,7 +615,35 @@ invoke_smalltalk_closure (GClosure *closure,
args[i++] = stc->widget;
}
- resultOOP = _gst_vm_proxy->nvmsgSend (stc->receiver, stc->selector, args, i);
+ event = malloc (sizeof (*event));
+
+ event->receiver = stc->receiver;
+ event->selector = stc->selector;
+ event->data = args;
+ event->widget = stc->widget;
+ event->n_params = stc->n_params;
+ event->mutex = NULL;
+ event->status = 1;
+
+ if (g_thread_self () != main_thread) {
+ event->mutex = g_mutex_new ();
+ g_mutex_lock (event->mutex);
+
+ _gst_vm_proxy->syncSignal (event_sem, true);
+ _gst_vm_proxy->wakeUp ();
+
+ g_mutex_lock (event->mutex);
+
+ // Smalltalk event handling raises an exception launch an inner
+ // event loop
+ //
+ if (event->status == 0)
+ gtk_main ();
+ } else {
+ // We are not in the threaded loop !!!
+ //
+ resultOOP = _gst_vm_proxy->evalExpr ("GTK.Gtk handleInnerEvent");
+ }
/* FIXME Need to init return_value's type? */
if (return_value)
@@ -717,12 +764,20 @@ connect_accel_group_no_user_data (OOP accel_group,
is delivered, SEMAPHORE is unblocked and the real event loop
takes place in the semaphore process. */
-void
-my_gtk_main (OOP semaphore)
+gpointer
+loop (gpointer semaphore)
{
- _gst_vm_proxy->registerOOP (semaphore);
- _gst_vm_proxy->asyncSignalAndUnregister (semaphore);
+ gdk_threads_enter ();
gtk_main ();
+ gdk_threads_leave ();
+
+ return NULL;
+}
+
+void
+my_gtk_main ()
+{
+ g_thread_create (loop, NULL, false, NULL);
}
void
@@ -996,6 +1051,26 @@ gst_gtk_initialized ()
return initialized;
}
+SmalltalkClosureStruct *
+gstGtkEvents ()
+{
+ return event;
+}
+
+void
+set_event_semaphore (OOP semaphore)
+{
+ event_sem = semaphore;
+ _gst_vm_proxy->registerOOP (semaphore);
+}
+
+void
+set_result (OOP anObject, GMutex *mutex)
+{
+ result = anObject;
+ g_mutex_unlock (mutex);
+}
+
void
gst_initModule (proxy)
VMProxy *proxy;
@@ -1005,8 +1080,10 @@ gst_initModule (proxy)
gchar **argv = argvArray;
initialized = gtk_init_check (&argc, &argv);
- if (initialized && !g_thread_supported ())
+ if (initialized && !g_thread_supported ()) {
g_thread_init (NULL);
+ gdk_threads_init ();
+ }
q_gst_object = g_quark_from_string ("gst_object");
g_type_init ();
@@ -1029,6 +1106,8 @@ gst_initModule (proxy)
gtype_oop_info.value_table = >ype_oop_value_table;
G_TYPE_OOP = g_type_register_static (G_TYPE_BOXED, "OOP", >ype_oop_info, 0);
+ main_thread = g_thread_self ();
+
_gst_vm_proxy = proxy;
_gst_vm_proxy->defineCFunc ("gtkInitialized", gst_gtk_initialized);
_gst_vm_proxy->defineCFunc ("gstTypeOOP", gst_type_oop);
@@ -1063,6 +1142,9 @@ gst_initModule (proxy)
_gst_vm_proxy->defineCFunc ("gstGtkWidgetGetAllocation", widget_get_allocation);
_gst_vm_proxy->defineCFunc ("gstGtkDialogGetVBox", dialog_get_vbox);
_gst_vm_proxy->defineCFunc ("gstGtkDialogGetActionArea", dialog_get_action_area);
+ _gst_vm_proxy->defineCFunc ("gstGtkEvents", gstGtkEvents);
+ _gst_vm_proxy->defineCFunc ("gstGtkEventSemaphore", set_event_semaphore);
+ _gst_vm_proxy->defineCFunc ("gstGtkResult", set_result);
_gst_vm_proxy->defineCFunc ("gtk_placer_get_type", gtk_placer_get_type);
_gst_vm_proxy->defineCFunc ("gtk_placer_new", gtk_placer_new);
diff --git a/packages/visualgst/GtkTextWidget.st b/packages/visualgst/GtkTextWidget.st
index 368ed4f..431d2f9 100644
--- a/packages/visualgst/GtkTextWidget.st
+++ b/packages/visualgst/GtkTextWidget.st
@@ -16,7 +16,7 @@ GTK.GtkTextView subclass: GtkTextWidget [
connectSignals [
<category: 'initialization'>
- self
+ "self
connectSignal: 'paste-clipboard' to: self selector: #paste userData: nil;
connectSignal: 'cut-clipboard' to: self selector: #cut userData: nil.
@@ -24,7 +24,7 @@ GTK.GtkTextView subclass: GtkTextWidget [
connectSignal: 'begin-user-action' to: self selector: #'beginUserAction' userData: nil;
connectSignal: 'end-user-action' to: self selector: #'endUserAction' userData: nil;
connectSignal: 'insert-text' to: self selector: #'insert:at:text:size:' userData: nil;
- connectSignal: 'delete-range' to: self selector: #'delete:from:to:' userData: nil
+ connectSignal: 'delete-range' to: self selector: #'delete:from:to:' userData: nil"
]
initialize [
diff --git a/packages/visualgst/VisualGST.st b/packages/visualgst/VisualGST.st
index b232e27..6dca5f6 100644
--- a/packages/visualgst/VisualGST.st
+++ b/packages/visualgst/VisualGST.st
@@ -166,7 +166,8 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.';
addButton: 'Save image' responseId: 1;
runBlockingAndDo: [ :dlg :res |
res = 0 ifTrue: [ self class exit ].
- res = 1 ifTrue: [ self saveImage.
+ res = 1 ifTrue: [ 'ici' printNl.
+ self saveImage.
self class exit ].
dlg destroy ].
]
@@ -210,6 +211,8 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.';
"ObjectMemory>>#snapshot breaks hard links due to
http://bugzilla.kernel.org/show_bug.cgi?id=9138, so we have to
check the permission of the directory rather than the file."
+ stderr nextPutAll: 'ici'; flush.
+ self saveImageAs.
imageName asFile parent isWriteable ifFalse: [ ^ self saveImageAs ].
self saveImage: [ ObjectMemory snapshot: imageName ]
]
@@ -218,10 +221,7 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.';
<category: 'file events'>
(GTK.GtkFileChooserDialog save: 'Save image as...' parent: window)
- runNonBlockingAndDo: [ :dlg :res |
- imageName := dlg getFilename.
- dlg destroy.
- res = GTK.Gtk gtkResponseAccept ifTrue: [ self saveImage: [ ObjectMemory snapshot: imageName ] ] ]
+ run
]
saveImage: aBlock [
@@ -262,6 +262,7 @@ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.';
initialize [
<category: 'initialization'>
+ stderr nextPutAll: 'initialize'.
super initialize.
saved := false.
imageName := File image asString.
diff --git a/packages/visualgst/package.xml b/packages/visualgst/package.xml
index dbd9c5a..10927ef 100644
--- a/packages/visualgst/package.xml
+++ b/packages/visualgst/package.xml
@@ -337,6 +337,12 @@
<file>Icons/NUnit.Running.png</file>
<file>Icons/NUnit.SuccessAndFailed.png</file>
<file>Icons/NUnit.Success.png</file>
- <start>VisualGST.VisualGST open.
- GTK.Gtk main</start>
+ <start>
+ | a |
+ VisualGST.VisualGST open.
+ [ GTK.Gtk main ] fork.
+ a := Semaphore new.
+ a wait.
+ 'byebye' printNl.
+ </start>
</package>
diff --git a/snprintfv/snprintfv/filament.h b/snprintfv/snprintfv/filament.h
index 4a91eb6..8a7ce6c 100644
--- a/snprintfv/snprintfv/filament.h
+++ b/snprintfv/snprintfv/filament.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/filament.in"
+#line 1 "./filament.in"
/* -*- Mode: C -*- */
/* filament.h --- a bit like a string but different =)O|
@@ -118,7 +118,7 @@ extern char * fildelete (Filament *fil);
extern void _fil_extend (Filament *fil, size_t len, boolean copy);
-#line 61 "../../../snprintfv/snprintfv/filament.in"
+#line 61 "./filament.in"
/* Save the overhead of a function call in the great majority of cases. */
#define fil_maybe_extend(fil, len, copy) \
diff --git a/snprintfv/snprintfv/filament.stamp b/snprintfv/snprintfv/filament.stamp
deleted file mode 100644
index 9788f70..0000000
--- a/snprintfv/snprintfv/filament.stamp
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/snprintfv/snprintfv/printf.h b/snprintfv/snprintfv/printf.h
index 49a2e9f..1437dd5 100644
--- a/snprintfv/snprintfv/printf.h
+++ b/snprintfv/snprintfv/printf.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/printf.in"
+#line 1 "./printf.in"
/* -*- Mode: C -*- */
/* printf.in --- printf clone for argv arrays
@@ -266,7 +266,7 @@ enum
} \
} SNV_STMT_END
-#line 269 "../../../snprintfv/snprintfv/printf.in"
+#line 269 "./printf.in"
/**
* printf_generic_info:
* @pinfo: the current state information for the format
@@ -302,7 +302,7 @@ extern int printf_generic_info (struct printf_info *const pinfo, size_t n, int *
extern int printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args);
-#line 270 "../../../snprintfv/snprintfv/printf.in"
+#line 270 "./printf.in"
/**
* register_printf_function:
* @spec: the character which will trigger @func, cast to an unsigned int.
@@ -789,7 +789,7 @@ extern int snv_vasprintf (char **result, const char *format, va_list ap);
extern int snv_asprintfv (char **result, const char *format, snv_constpointer const args[]);
-#line 271 "../../../snprintfv/snprintfv/printf.in"
+#line 271 "./printf.in"
/* If you don't want to use snprintfv functions for *all* of your string
formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
diff --git a/snprintfv/snprintfv/printf.stamp b/snprintfv/snprintfv/printf.stamp
deleted file mode 100644
index 9788f70..0000000
--- a/snprintfv/snprintfv/printf.stamp
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/snprintfv/snprintfv/stream.h b/snprintfv/snprintfv/stream.h
index 496bd33..0bebce1 100644
--- a/snprintfv/snprintfv/stream.h
+++ b/snprintfv/snprintfv/stream.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/stream.in"
+#line 1 "./stream.in"
/* -*- Mode: C -*- */
/* stream.h --- customizable stream routines
@@ -180,7 +180,7 @@ extern int stream_puts (char *s, STREAM *stream);
extern int stream_get (STREAM *stream);
-#line 88 "../../../snprintfv/snprintfv/stream.in"
+#line 88 "./stream.in"
#ifdef __cplusplus
#if 0
/* This brace is so that emacs can still indent properly: */
diff --git a/snprintfv/snprintfv/stream.stamp b/snprintfv/snprintfv/stream.stamp
deleted file mode 100644
index 9788f70..0000000
--- a/snprintfv/snprintfv/stream.stamp
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
_______________________________________________
help-smalltalk mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-smalltalk