Jim Bushnell | 3 Dec 01:17 2007
Picon
Picon

Mac OSX problems

On SBCL under OSX 10.5.0.1 (Leopard), I get an error about missing libgobject-2.0.so when running the test.

Looking at past postings to this list, I note that others have had similar problems. I tried changing the definition of %load-foreign-library to always return t, but this didn't help. I am brand-new to cells-gtk and SBCL and MacOSX (but not to Lisp), and I don't know what else to try.

I used the cells-gtk-2006-06-30.tgz version of cells-gtk, and I can't find one more recent.

I would appreciate any help.

Jim Bushnell

<div>On SBCL under OSX 10.5.0.1 (Leopard), I get an error about missing libgobject-2.0.so when running the test.<div><br class="webkit-block-placeholder"></div>
<div>Looking at past postings to this list, I note that others have had similar problems. I tried changing the definition of %load-foreign-library to always return t, but this didn't help. I am brand-new to cells-gtk and SBCL and MacOSX (but not to Lisp), and I don't know what else to try.</div>
<div><br class="webkit-block-placeholder"></div>
<div>I used the&nbsp;<a href="http://common-lisp.net/project/cells-gtk/files/cells-gtk-2006-06-30.tgz">cells-gtk-2006-06-30.tgz</a>&nbsp;version of cells-gtk, and I can't find one more recent.</div>
<div><br class="webkit-block-placeholder"></div>
<div>I would appreciate any help.</div>
<div><br class="webkit-block-placeholder"></div>
<div>Jim Bushnell</div>
<div><br class="webkit-block-placeholder"></div>
</div>
Peter Hildebrandt | 3 Dec 12:50 2007
Picon

start-app and multithreading?


I've been trying for a while to launch a gtk application in a distinct
thread (using sbcl):

(sb-thread:make-thread (lambda () (cells-gtk-init) (start-app 'my-app)))

The thread appears to runs fine up to the point where (gtk-main) is
called, however no window is ever being displayed.

The objective is to launch a GUI in the background, then return back to
the REPL (with the GUI still runnning in the background), and modifying
the underlying data structures directly, while the GUI visualizes the
results.  For another app I have this up and running with cl-glut, but
here I'd like to have (cells-)gtk for various reasons.

Did anybody ever encounter this issue, or has any ideas how to work around
it?

Help is highly appreciated,

Peter

Peter Denno | 3 Dec 13:29 2007

Re: start-app and multithreading?

On Monday 03 December 2007 06:50, Peter Hildebrandt wrote:
> I've been trying for a while to launch a gtk application in a
> distinct thread (using sbcl):
>
> (sb-thread:make-thread (lambda () (cells-gtk-init) (start-app
> 'my-app)))
>
> The thread appears to runs fine up to the point where (gtk-main) is
> called, however no window is ever being displayed.

I ran in to this problem. I don't think I resolved it. It may well be 
the case that I still don't understand restarts completely. The code 
to look at is probably start-app in gtk-app.lisp.

If you typically run under slime, just for experimentation, try 
running from a command prompt instead.

>
>
> The objective is to launch a GUI in the background, then return
> back to the REPL (with the GUI still runnning in the background),
> and modifying the underlying data structures directly, while the
> GUI visualizes the results.  For another app I have this up and
> running with cl-glut, but here I'd like to have (cells-)gtk for
> various reasons.
>
> Did anybody ever encounter this issue, or has any ideas how to work
> around it?
>
> Help is highly appreciated,
>
> Peter
>
>
> _______________________________________________
> cells-gtk-devel site list
> cells-gtk-devel <at> common-lisp.net
> http://common-lisp.net/mailman/listinfo/cells-gtk-devel

--

-- 
Best regards,
  - Peter
Peter Hildebrandt | 4 Dec 15:57 2007
Picon

Re: start-app and multithreading?


Peter,

thanks for your reply.  I've made some progress, but before suggesting a  
patch I'd like to verify a few internals.

The GTK/GDK doc says, that you're fine as long as you use gdk/gtk only in  
callback functions such as on-click-handlers.  These callbacks are  
apparently run within the lock we supply for gtk-main.  However in   
"Idles, timeouts, and input functions" [1] you'd need to sorround calls to  
gtk/gdk with the equivalent of with-gdk-threads.

[1] http://www.gnu.org/software/guile-gnome/docs/gdk/html/Threads.html

Now I have poked around the code for a while, and did not find any of  
those.  Does cells-gtk use "Idles, timeouts, and input functions"?  If  
yes, where?

My second question:  Is there somewhere a list of all windows that have  
been created using to-be?  Or will I have to hack my own using :after  
methods?  (for details why I need this, see below)

To give you an idea where things are going, here's a short write-up of the  
status quo.  Test-gtk works perfectly.  If you have loaded test-gtk and  
changed into the package,

(start-app-in-thread 'test-gtk)

starts the sample app and returns right away to the REPL.

A typical example how this facility would be used is along these lines:

;; create a hello-world app
(defmodel app (gtk-app)
   ((label :accessor label :initform (c-in "") :initarg :label))
   (:default-initargs
     :title "TestApp"
     :kids (list
	   (mk-label :text (c? (label (upper self)))))))

;; run the app
(start-app-in-thread 'app)

;; modify a slot in the app instance and watch cells(-gtk) propagate the  
change
(setf (label (gtk-current-app)) "Hallo Welt")

Once the app is running, you can create further windows

(to-be (mk-window :title "a window"))

and also instances of the application

(to-be (make-instance 'app))

I love interactive programming :-)

Three limitations apply:

(1) To maintain compatibility with start-app's behavior, the window  
started by start-app-in-thread serves as the applications main window --  
gtk-main will exit, when this one is closed.  The application (or the  
developer at the REPL) has to make sure all windows created by to-be are  
closed using not-to-be before the main window exits.  If he doesn't, they  
will remain inactive, until a new application is started.  (This is where  
a list of all open windows would come in handy, the solution being only a  
mapcar away)

(2) If start-app-in-thread is called while an application is still  
running, it will schedule the request and return immediately.  The new  
application is opened once the previous one is closed.  This limitation  
appears to be necessary to prevent hassle with applications that are not  
thread-safe and thus do not like being execute several times within the  
same lisp process.  If you really want to run your application in  
parallel, use (to-be (make-instance 'app)) or (make-be 'app).

(3) For technical reasons, you CANNOT use start-app and  
start-app-in-thread from the same lisp session (i.e., if you have used  
one, you will have to RESTART your lisp session before you can use the  
other)

In other words, (start-app-in-thread) behaves just like (start-app), the  
only difference being, that it returns immediately, running gtk in the  
background.

Comments are welcome.  If this behavior seems to be ok, I will factor out  
the relevant changes against the current cvs version and provide a patch  
for testing.

Here's a little write up of the technical details involved.

The major issue appears to be that GTK expects gtk-main to be called only  
once for every given process.  If it is called repeatedly, gtk plays along  
nicely, if the call comes from the same thread as before, otherwise it  
does not signal an error, but simply discards any screen output.

Interestingly, g-thread-init and gdk-thread-init may well be called from a  
different thread.  However, once gtk-main has been called, our process is  
doomed to use the same thread for subsequent calls to gtk-main.  I did not  
find this behavior documented anywhere, but I have come to believe that it  
simply reflects the C programming style of compile-link-run -- hence it  
did not occur to anyone that this might be a problem.

As long as you run gtk-main directly from your lisp session, it is not a  
problem either, since it is always the same caller as well. However, once  
you try to spawn a thread every time you launch gtk-main, things  
inevitably break.

Therefore, my code creates one thread dedicated to running gtk-main.  This  
thread is fired up the first time start-app-in-thread is called and should  
remain alive throughout the lisp session.  Subsequent calls to  
start-app-in-thread use a mutex to communicate start-app requests to the  
running thread.

Regards,
Peter

On Mon, 03 Dec 2007 13:29:59 +0100, Peter Denno <peter.denno <at> nist.gov>  
wrote:

> On Monday 03 December 2007 06:50, Peter Hildebrandt wrote:
>> I've been trying for a while to launch a gtk application in a
>> distinct thread (using sbcl):
>>
>> (sb-thread:make-thread (lambda () (cells-gtk-init) (start-app
>> 'my-app)))
>>
>> The thread appears to runs fine up to the point where (gtk-main) is
>> called, however no window is ever being displayed.
>
> I ran in to this problem. I don't think I resolved it. It may well be
> the case that I still don't understand restarts completely. The code
> to look at is probably start-app in gtk-app.lisp.
>
> If you typically run under slime, just for experimentation, try
> running from a command prompt instead.
>
>>
>>
>> The objective is to launch a GUI in the background, then return
>> back to the REPL (with the GUI still runnning in the background),
>> and modifying the underlying data structures directly, while the
>> GUI visualizes the results.  For another app I have this up and
>> running with cl-glut, but here I'd like to have (cells-)gtk for
>> various reasons.
>>
>> Did anybody ever encounter this issue, or has any ideas how to work
>> around it?
>>
>> Help is highly appreciated,
>>
>> Peter
>>
>>
>> _______________________________________________
>> cells-gtk-devel site list
>> cells-gtk-devel <at> common-lisp.net
>> http://common-lisp.net/mailman/listinfo/cells-gtk-devel
>

Peter Denno | 4 Dec 17:10 2007

Re: start-app and multithreading?

On Tuesday 04 December 2007 09:57, Peter Hildebrandt wrote:
> Peter,
>
> thanks for your reply.  I've made some progress, but before
> suggesting a patch I'd like to verify a few internals.
>
> The GTK/GDK doc says, that you're fine as long as you use gdk/gtk
> only in callback functions such as on-click-handlers.  These
> callbacks are apparently run within the lock we supply for
> gtk-main.  However in "Idles, timeouts, and input functions" [1]
> you'd need to sorround calls to gtk/gdk with the equivalent of
> with-gdk-threads.

I see that the entire main loop in gtk-app is surrounded in 
with-gdk-threads, but nothing on a finer grain. Is this the problem?

> [1]
> http://www.gnu.org/software/guile-gnome/docs/gdk/html/Threads.html

I recall reading this page after struggling with the behavior in the 
Win32 port of my program. 

It has been about a year since I've worked with cells-gtk (Not that I 
don't like it, or have given up on it.  I'm just busy with some 
server stuff and hunchentoot). 

> Now I have poked around the code for a while, and did not find any
> of those.  Does cells-gtk use "Idles, timeouts, and input
> functions"?  If yes, where?

I did a quick tutorial at
http://www.gtk.org/tutorial1.2/gtk_tut-17.html

fgrep timeout `find . -name \*.lisp` ...

widgets.lisp timeout-add. This is used in test-gtk/test-display... In 
fact I have noted that this test doesn't work in some lisps! I don't 
see in my notes where though.

Under lispworks, gtk-app does a process-wait-with-timeout. 

Grep on idle and input doesn't show anything. 

>
> My second question:  Is there somewhere a list of all windows that
> have been created using to-be?  Or will I have to hack my own using
> :after methods?  (for details why I need this, see below)

Maybe Kenny Tilton could answer that one.
>
>
> To give you an idea where things are going, here's a short write-up
> of the status quo.  Test-gtk works perfectly.  

Including the pulse behavior in test-display?

> If you have loaded 
> test-gtk and changed into the package,
>
> (start-app-in-thread 'test-gtk)
>
> starts the sample app and returns right away to the REPL.
>
> A typical example how this facility would be used is along these
> lines:
>
> ;; create a hello-world app
> (defmodel app (gtk-app)
>    ((label :accessor label :initform (c-in "") :initarg :label))
>    (:default-initargs
>
>      :title "TestApp"
>      :kids (list
>
> 	   (mk-label :text (c? (label (upper self)))))))
>
> ;; run the app
> (start-app-in-thread 'app)
>
> ;; modify a slot in the app instance and watch cells(-gtk)
> propagate the change
> (setf (label (gtk-current-app)) "Hallo Welt")
>
> Once the app is running, you can create further windows
>
> (to-be (mk-window :title "a window"))
>
> and also instances of the application
>
> (to-be (make-instance 'app))
>
> I love interactive programming :-)
>
> Three limitations apply:
>
> (1) To maintain compatibility with start-app's behavior, the window
> started by start-app-in-thread serves as the applications main
> window -- gtk-main will exit, when this one is closed.  The
> application (or the developer at the REPL) has to make sure all
> windows created by to-be are closed using not-to-be before the main
> window exits.  If he doesn't, they will remain inactive, until a
> new application is started.  (This is where a list of all open
> windows would come in handy, the solution being only a mapcar away)

This may resolve the problem I've seen where I'd have to restart lisp 
to get cells-gtk unstuck after breaking (e.g. in debugger) and 
quitting. That would be marvelous!

>
> (2) If start-app-in-thread is called while an application is still
> running, it will schedule the request and return immediately.  The
> new application is opened once the previous one is closed.  This
> limitation appears to be necessary to prevent hassle with
> applications that are not thread-safe and thus do not like being
> execute several times within the same lisp process.  If you really
> want to run your application in parallel, use (to-be (make-instance
> 'app)) or (make-be 'app).
>
> (3) For technical reasons, you CANNOT use start-app and
> start-app-in-thread from the same lisp session (i.e., if you have
> used one, you will have to RESTART your lisp session before you can
> use the other)
>
> In other words, (start-app-in-thread) behaves just like
> (start-app), the only difference being, that it returns
> immediately, running gtk in the background.
>
> Comments are welcome.  If this behavior seems to be ok, I will
> factor out the relevant changes against the current cvs version and
> provide a patch for testing.

This could be a patch that might really improve matters. Go for it!
>
>
> Here's a little write up of the technical details involved.
>
> The major issue appears to be that GTK expects gtk-main to be
> called only once for every given process.  If it is called
> repeatedly, gtk plays along nicely, if the call comes from the same
> thread as before, otherwise it does not signal an error, but simply
> discards any screen output.
>
> Interestingly, g-thread-init and gdk-thread-init may well be called
> from a different thread.  However, once gtk-main has been called,
> our process is doomed to use the same thread for subsequent calls
> to gtk-main.  I did not find this behavior documented anywhere, but
> I have come to believe that it simply reflects the C programming
> style of compile-link-run -- hence it did not occur to anyone that
> this might be a problem.
>
> As long as you run gtk-main directly from your lisp session, it is
> not a problem either, since it is always the same caller as well.
> However, once you try to spawn a thread every time you launch
> gtk-main, things inevitably break.
>
> Therefore, my code creates one thread dedicated to running
> gtk-main.  This thread is fired up the first time
> start-app-in-thread is called and should remain alive throughout
> the lisp session.  Subsequent calls to start-app-in-thread use a
> mutex to communicate start-app requests to the running thread.
>
> Regards,
> Peter
>
>
> On Mon, 03 Dec 2007 13:29:59 +0100, Peter Denno
> <peter.denno <at> nist.gov>
>
> wrote:
> > On Monday 03 December 2007 06:50, Peter Hildebrandt wrote:
> >> I've been trying for a while to launch a gtk application in a
> >> distinct thread (using sbcl):
> >>
> >> (sb-thread:make-thread (lambda () (cells-gtk-init) (start-app
> >> 'my-app)))
> >>
> >> The thread appears to runs fine up to the point where (gtk-main)
> >> is called, however no window is ever being displayed.
> >
> > I ran in to this problem. I don't think I resolved it. It may
> > well be the case that I still don't understand restarts
> > completely. The code to look at is probably start-app in
> > gtk-app.lisp.
> >
> > If you typically run under slime, just for experimentation, try
> > running from a command prompt instead.
> >
> >> The objective is to launch a GUI in the background, then return
> >> back to the REPL (with the GUI still runnning in the
> >> background), and modifying the underlying data structures
> >> directly, while the GUI visualizes the results.  For another app
> >> I have this up and running with cl-glut, but here I'd like to
> >> have (cells-)gtk for various reasons.
> >>
> >> Did anybody ever encounter this issue, or has any ideas how to
> >> work around it?
> >>
> >> Help is highly appreciated,
> >>
> >> Peter
> >>
> >>
> >> _______________________________________________
> >> cells-gtk-devel site list
> >> cells-gtk-devel <at> common-lisp.net
> >> http://common-lisp.net/mailman/listinfo/cells-gtk-devel

--

-- 
Best regards,
  - Peter
Peter Denno | 4 Dec 17:57 2007

Re: start-app and multithreading?


I think Kenny intended to send this note to the whole cells-gtk-devel 
list. 

I've added my two cents below also.

On Tuesday 04 December 2007 11:35, you wrote:
> Peter Denno wrote:
> > On Tuesday 04 December 2007 09:57, Peter Hildebrandt wrote:
> >>Peter,
> >>
> >>thanks for your reply.  I've made some progress, but before
> >>suggesting a patch I'd like to verify a few internals.
> >>
> >>The GTK/GDK doc says, that you're fine as long as you use gdk/gtk
> >>only in callback functions such as on-click-handlers.  These
> >>callbacks are apparently run within the lock we supply for
> >>gtk-main.  However in "Idles, timeouts, and input functions" [1]
> >>you'd need to sorround calls to gtk/gdk with the equivalent of
> >>with-gdk-threads.
> >
> > I see that the entire main loop in gtk-app is surrounded in
> > with-gdk-threads, but nothing on a finer grain. Is this the
> > problem?
> >
> >>[1]
> >>http://www.gnu.org/software/guile-gnome/docs/gdk/html/Threads.htm
> >>l
> >
> > I recall reading this page after struggling with the behavior in
> > the Win32 port of my program.
> >
> > It has been about a year since I've worked with cells-gtk (Not
> > that I don't like it, or have given up on it.  I'm just busy with
> > some server stuff and hunchentoot).
> >
> >>Now I have poked around the code for a while, and did not find
> >> any of those.  Does cells-gtk use "Idles, timeouts, and input
> >> functions"?  If yes, where?
> >
> > I did a quick tutorial at
> > http://www.gtk.org/tutorial1.2/gtk_tut-17.html
> >
> > fgrep timeout `find . -name \*.lisp` ...
> >
> > widgets.lisp timeout-add. This is used in
> > test-gtk/test-display... In fact I have noted that this test
> > doesn't work in some lisps! I don't see in my notes where though.
> >
> > Under lispworks, gtk-app does a process-wait-with-timeout.
> >
> > Grep on idle and input doesn't show anything.
> >
> >>My second question:  Is there somewhere a list of all windows
> >> that have been created using to-be?  Or will I have to hack my
> >> own using
> >>
> >>:after methods?  (for details why I need this, see below)
> >
> > Maybe Kenny Tilton could answer that one.
>
> I usually structure my applications with a "system" instance at the
> top, system being a family subclass, each child being a window. Or
> I go further and have system be a tree of applications of windows.
> That sort of thing. If I was doing a network app I would extend
> that to model a bigger world. Anyway, then new windows are made at
> the repl with:
>
>    (push (my-new-window) (kids *sys*))
>
> Where I have bound the system instance to *sys*.

Come to think of it you could call,

(depth-first-search <root-window> #'fail #'kids :do #'(lambda (k)  
(push k <whatever>)))

at any point, and <whatever> would contain the list of all widgets 
found through navigating the kids slot.

#'depth-first-search and #'fail are in pod-utils. It is part of the 
distribution.

>
> The other way I have been known to get to all windows is to use
> some hook offered by the windowing API, but I do not know if GTk
> offers such a beast.
>
> As for the rest, yes, many times I have wrestled with the different
> world view held by the C developer to get to the point where I can
> do iterative development in Lisp calling a C windowing library that
> expects to get a fresh process with each run. Obviously a
> make/break deal for us Lispniks, and it can indeed require detailed
> analysis of the internals of the target platform, especially at the
> edges where we are creating and disposing of windows. It took me
> more than a few hours to sort out the various sequences of
> messages/events arising during the various ways a window can be
> closed, such as by the user clicking the close box vs the
> application initiating a close in response to alt-F4 vs etc etc
>
> So you all are on the right track, don't get discouraged, use as
> much duct tape as you need to get to interactive development. And
> to be honest, if certain nasty combinations arise and force a
> complete bounce of my Lisp once a day I just get on with it. :)
>
> kt

--

-- 
Best regards,
  - Peter
Peter Hildebrandt | 4 Dec 18:45 2007
Picon

Re: start-app and multithreading?


Peter,

thanks for your pointers.  Just to clarify things, I am working with the  
latest SBCL on linux (ubuntu 7.10, gtk 2.2) mostly from slime.  I do not  
have other environments around for testing.

> I see that the entire main loop in gtk-app is surrounded in
> with-gdk-threads, but nothing on a finer grain. Is this the problem?

Actually from what I understand this is perfectly fine (and most C sample  
code on the net seems to do the same).  During normal use, the thread will  
spend its time within gtk-main, and gtk-main apparently releases the lock  
on idle and reacquires it when calling a callback.  So this is fine.

> It has been about a year since I've worked with cells-gtk (Not that I
> don't like it, or have given up on it.  I'm just busy with some
> server stuff and hunchentoot).

That's good to hear.  Especially now that threading appears to work (at  
least with SBCL in linux), it makes a great development environment for  
local GUI apps.  Just another example:

;; first create an empty window
(make-be 'window :title "Some Window" :kids (c-in nil))
;; the window shows up and is empty

;; next make a button and see what happens
(setf (kids *) (list (mk-button :label "click me" :on-clicked (callback (w  
e d) (print 'clicked)))))

;; for extra points: click on it

>> Now I have poked around the code for a while, and did not find any
>> of those.  Does cells-gtk use "Idles, timeouts, and input
>> functions"?  If yes, where?
>
> I did a quick tutorial at
> http://www.gtk.org/tutorial1.2/gtk_tut-17.html

Thanks, now I understand a little better what this is all about anyway.

> widgets.lisp timeout-add.

(defun timeout-add (milliseconds function)
...
                 (let ((r (with-gdk-threads
			  (funcall function))))
...

... and interestingly timeout-add actually uses with-gdk-threads ...

> This is used in test-gtk/test-display... In
> fact I have noted that this test doesn't work in some lisps! I don't
> see in my notes where though.

... and this one works perfectly in its thread for me in SBCL/linux.

> Under lispworks, gtk-app does a process-wait-with-timeout.

That should not hurt, though, since there is no callback, and thus no gtk  
access.

> Grep on idle and input doesn't show anything.

>> My second question:  Is there somewhere a list of all windows that
>> have been created using to-be?  Or will I have to hack my own using
>> :after methods?  (for details why I need this, see below)
>
> Maybe Kenny Tilton could answer that one.

 From what I can see the cells code does not keep book of the instances of  
a particular kind.  Come to think of it, I don't know why it should. (I  
see a count-it macro, but I guess this is for performance monitoring)

I included an :after method for md-awaken and a :before mtehod for  
not-to-be, specialising on window.  Now all windows created after  
start-app-in-thread are terminated when the main window is closed.

>> of the status quo.  Test-gtk works perfectly.
> Including the pulse behavior in test-display?

As mentioned above, yes it does.

>> Three limitations apply:
>>
>> (1) To maintain compatibility with start-app's behavior, the window
>> started by start-app-in-thread serves as the applications main
>> window -- gtk-main will exit, when this one is closed.  The
>> application (or the developer at the REPL) has to make sure all
>> windows created by to-be are closed using not-to-be before the main
>> window exits.  If he doesn't, they will remain inactive, until a
>> new application is started.  (This is where a list of all open
>> windows would come in handy, the solution being only a mapcar away)
>
> This may resolve the problem I've seen where I'd have to restart lisp
> to get cells-gtk unstuck after breaking (e.g. in debugger) and
> quitting. That would be marvelous!

Indeed.  This sounds exactly like the problem I had to work around here.   
I included a handler for general Lisp errors, which shows the error in a  
message box and allows you to shutdown your app cleanly or just continue  
in the main loop.  This is nice if for instance you setf a slot to an atom  
while your prog expects a list or the like.  Just correct it and click yes  
to go on as if nothing ever happened.

Regards,
Peter
Peter Hildebrandt | 4 Dec 19:09 2007
Picon

Re: start-app and multithreading?


Kenny and Peter,

thanks for your response.

On Tue, 04 Dec 2007 17:57:47 +0100, Peter Denno <peter.denno <at> nist.gov>  
wrote:

>> I usually structure my applications with a "system" instance at the
>> top, system being a family subclass, each child being a window. Or
>> I go further and have system be a tree of applications of windows.
>> That sort of thing. If I was doing a network app I would extend
>> that to model a bigger world. Anyway, then new windows are made at
>> the repl with:
>>
>>    (push (my-new-window) (kids *sys*))
>>
>> Where I have bound the system instance to *sys*.

Sounds extremely reasonable.  I guess that's what I will do in my  
application.

> Come to think of it you could call,
>
> (depth-first-search <root-window> #'fail #'kids :do #'(lambda (k)
> (push k <whatever>)))
>
> at any point, and <whatever> would contain the list of all widgets
> found through navigating the kids slot.
>
> #'depth-first-search and #'fail are in pod-utils. It is part of the
> distribution.

I wonder whether this is really what one wants in a gui toolkit.   
Cells-gtk should simply find all windows and get rid of them, s.t. no  
inactive ones remain.  The approach above would miss windows which are  
created by plainly using (make-be 'window).

Is there anything wrong with hooking into md-awaken/not-to-be?  I put the  
following in my code:

(let ((open-windows nil))
   (defmethod md-awaken :after ((self window))
     (pushnew self open-windows))
   (defmethod not-to-be :before ((self window))
     (setf open-windows (delete self open-windows )))
   (defun not-to-be-all ()
     (mapcar #'not-to-be open-windows)
     (setf open-windows nil)))

where not-to-be-all is called when the user closes the main window.   
Appears to be working perfectly.  Am I missing something?

Checked creating a dozen windows, closing some with Alt-F4, some with  
menu-close, some with the close box, and having the main app (test-gtk,  
surprise, surprise) take the rest down with it.

>> The other way I have been known to get to all windows is to use
>> some hook offered by the windowing API, but I do not know if GTk
>> offers such a beast.

I'll keep that one in mind, in case the former approach fails.

>> As for the rest, yes, many times I have wrestled with the different
>> world view held by the C developer to get to the point where I can
>> do iterative development in Lisp calling a C windowing library that
>> expects to get a fresh process with each run. Obviously a
>> make/break deal for us Lispniks, and it can indeed require detailed
>> analysis of the internals of the target platform, especially at the
>> edges where we are creating and disposing of windows. It took me
>> more than a few hours to sort out the various sequences of
>> messages/events arising during the various ways a window can be
>> closed, such as by the user clicking the close box vs the
>> application initiating a close in response to alt-F4 vs etc etc
>> So you all are on the right track, don't get discouraged, use as
>> much duct tape as you need to get to interactive development.

Glad to hear that I'm not alone.  Actually it is strange anyone would give  
up and settle for any other type of UI development.  This is so much fun,  
like I'm not merely poking around in the internals of my application while  
it is running, I can watch even watch it react.  Kinda like when I pulled  
those cylinder heads on my 1962 Cadillac a couple years ago.

>> And
>> to be honest, if certain nasty combinations arise and force a
>> complete bounce of my Lisp once a day I just get on with it. :)
:)

Regards,
Peter

>> kt
>

Peter Denno | 4 Dec 20:05 2007

Re: start-app and multithreading?

On Tuesday 04 December 2007 13:09, Peter Hildebrandt wrote:
> Kenny and Peter,
>
> thanks for your response.
>
> On Tue, 04 Dec 2007 17:57:47 +0100, Peter Denno
> <peter.denno <at> nist.gov>
>
> wrote:
> >> I usually structure my applications with a "system" instance at
> >> the top, system being a family subclass, each child being a
> >> window. Or I go further and have system be a tree of
> >> applications of windows. That sort of thing. If I was doing a
> >> network app I would extend that to model a bigger world. Anyway,
> >> then new windows are made at the repl with:
> >>
> >>    (push (my-new-window) (kids *sys*))
> >>
> >> Where I have bound the system instance to *sys*.
>
> Sounds extremely reasonable.  I guess that's what I will do in my
> application.
>
> > Come to think of it you could call,
> >
> > (depth-first-search <root-window> #'fail #'kids :do #'(lambda (k)
> > (push k <whatever>)))
> >
> > at any point, and <whatever> would contain the list of all
> > widgets found through navigating the kids slot.
> >
> > #'depth-first-search and #'fail are in pod-utils. It is part of
> > the distribution.
>
> I wonder whether this is really what one wants in a gui toolkit.
> Cells-gtk should simply find all windows

I'm not sure what you mean by "find all windows" but if you mean find 
all widgets starting at some parent, where by parent I mean the 
relationship specified by the kid slot, I see no reason not to do the 
above.

> and get rid of them, s.t. 
> no inactive ones remain.  The approach above would miss windows
> which are created by plainly using (make-be 'window).

Not sure why you'd want to do that, but then I've been away from this 
code for too long.

>
> Is there anything wrong with hooking into md-awaken/not-to-be?  I
> put the following in my code:
>
> (let ((open-windows nil))
>    (defmethod md-awaken :after ((self window))
>      (pushnew self open-windows))
>    (defmethod not-to-be :before ((self window))
>      (setf open-windows (delete self open-windows )))
>    (defun not-to-be-all ()
>      (mapcar #'not-to-be open-windows)
>      (setf open-windows nil)))
>
> where not-to-be-all is called when the user closes the main window.
> Appears to be working perfectly.  Am I missing something?

Looks OK to me, but I might not be the best person to ask, at this 
point.

Anyone?

>
> Checked creating a dozen windows, closing some with Alt-F4, some
> with menu-close, some with the close box, and having the main app
> (test-gtk, surprise, surprise) take the rest down with it.
>
> >> The other way I have been known to get to all windows is to use
> >> some hook offered by the windowing API, but I do not know if GTk
> >> offers such a beast.
>
> I'll keep that one in mind, in case the former approach fails.
>
> >> As for the rest, yes, many times I have wrestled with the
> >> different world view held by the C developer to get to the point
> >> where I can do iterative development in Lisp calling a C
> >> windowing library that expects to get a fresh process with each
> >> run. Obviously a make/break deal for us Lispniks, and it can
> >> indeed require detailed analysis of the internals of the target
> >> platform, especially at the edges where we are creating and
> >> disposing of windows. It took me more than a few hours to sort
> >> out the various sequences of messages/events arising during the
> >> various ways a window can be closed, such as by the user
> >> clicking the close box vs the application initiating a close in
> >> response to alt-F4 vs etc etc So you all are on the right track,
> >> don't get discouraged, use as much duct tape as you need to get
> >> to interactive development.
>
> Glad to hear that I'm not alone.  Actually it is strange anyone
> would give up and settle for any other type of UI development. 
> This is so much fun, like I'm not merely poking around in the
> internals of my application while it is running, I can watch even
> watch it react.  Kinda like when I pulled those cylinder heads on
> my 1962 Cadillac a couple years ago.

I'm with ya there. I always wondered whether others who hacked code 
with enthusiasm did this sort of thing too.

>
> >> And
> >> to be honest, if certain nasty combinations arise and force a
> >> complete bounce of my Lisp once a day I just get on with it. :)
> :
> :)
>
> Regards,
> Peter
>
> >> kt

--

-- 
Best regards,
  - Peter
Peter Hildebrandt | 4 Dec 22:26 2007
Picon

Re: start-app and multithreading?

On Tue, 04 Dec 2007 20:05:11 +0100, Peter Denno <peter.denno <at> nist.gov>  
wrote:
>> I wonder whether this is really what one wants in a gui toolkit.
>> Cells-gtk should simply find all windows
>
> I'm not sure what you mean by "find all windows" but if you mean find
> all widgets starting at some parent, where by parent I mean the
> relationship specified by the kid slot, I see no reason not to do the
> above.

Sorry, I am afraid I've caused a misunderstanding here.  There are two  
separate issues

(1) An application should somehow keep track of the windows it creates and  
make sure they get closed properly, unsaved data stored, etc.  This can  
nicely be done using a family tree as Kenny described, and some tree  
search (like the one you mentioned) would do the trick.

(2) However, if the programmer for some reason fails to do that (or if I  
have been just playing around at the repl, creating random windows to try  
things out), the should be some sort of safety net within the gui toolkit  
to make sure that closing the main application window does the logical  
thing, namely not leave unreactive, greyed out windows behind -- which is  
what happens once gtk-main closes down.  Therefore by "all" I mean all  
windows created after start-app-in-thread was called.

I wanted to imitate the behavior of start-app, which closes down its gtk  
communication when the main window is closed.  And even if the programmer  
forgets about closing some window he might have opened, the toolkit should  
take care.

Currently the line of events is

start-app-in-thread
   cells-gtk-init
   make-instance application
   enter gtk-main
...
open and close what ever other windows you'd like
...
until the application window is closed (either by the user or by not-to-be)
   gtk-main exits
   all windows which are still open (and would become dead) are closed
   gtk is cleanly left, but with the option for re-entry

...

start-app-in-thread again
etc.

Another approach would be to keep gtk-main running until all windows in  
the current lisp session are closed.  However, it would require some more  
investigation to see when and how gtk-main would need to be restarted to  
simulate a continous running gui.  One problem I ran into already is that  
an app like test-gtk needs cells-gtk-init to run before it can be  
relaunched -- which would take down other stuff open at the time.

>> and get rid of them, s.t.
>> no inactive ones remain.  The approach above would miss windows
>> which are created by plainly using (make-be 'window).
>
> Not sure why you'd want to do that, but then I've been away from this
> code for too long.

Just to try stuff out from the repl; make a window, push some kids in  
there, change options, see what happens.

>
>>
>> Is there anything wrong with hooking into md-awaken/not-to-be?  I
>> put the following in my code:
>>
>> (let ((open-windows nil))
>>    (defmethod md-awaken :after ((self window))
>>      (pushnew self open-windows))
>>    (defmethod not-to-be :before ((self window))
>>      (setf open-windows (delete self open-windows )))
>>    (defun not-to-be-all ()
>>      (mapcar #'not-to-be open-windows)
>>      (setf open-windows nil)))
>>
>> where not-to-be-all is called when the user closes the main window.
>> Appears to be working perfectly.  Am I missing something?
>
> Looks OK to me, but I might not be the best person to ask, at this
> point.
>
> Anyone?

It'd like to hear some comments, too.

>> Glad to hear that I'm not alone.  Actually it is strange anyone
>> would give up and settle for any other type of UI development.
>> This is so much fun, like I'm not merely poking around in the
>> internals of my application while it is running, I can watch even
>> watch it react.  Kinda like when I pulled those cylinder heads on
>> my 1962 Cadillac a couple years ago.
>
> I'm with ya there. I always wondered whether others who hacked code
> with enthusiasm did this sort of thing too.

Like peeling apart the internals of a running system or like working on  
the internals of mechanical engines?

Regards,
Peter


Gmane