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 = &gtype_oop_value_table;
   G_TYPE_OOP = g_type_register_static (G_TYPE_BOXED, "OOP", &gtype_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

Reply via email to