From jcbushnell2 at comcast.net Mon Dec 3 00:17:02 2007 From: jcbushnell2 at comcast.net (Jim Bushnell) Date: Sun, 2 Dec 2007 17:17:02 -0700 Subject: [cells-gtk-devel] Mac OSX problems Message-ID: <38A0EFD2-4874-4C17-B0DD-53517FDDE242@comcast.net> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter.hildebrandt at gmail.com Mon Dec 3 11:50:29 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Mon, 03 Dec 2007 12:50:29 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: References: Message-ID: 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 From peter.denno at nist.gov Mon Dec 3 12:29:59 2007 From: peter.denno at nist.gov (Peter Denno) Date: Mon, 3 Dec 2007 07:29:59 -0500 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: References: Message-ID: <200712030729.59998.peter.denno@nist.gov> 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 From peter.hildebrandt at gmail.com Tue Dec 4 14:57:10 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 04 Dec 2007 15:57:10 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <200712030729.59998.peter.denno@nist.gov> References: <200712030729.59998.peter.denno@nist.gov> Message-ID: 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 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 > From peter.denno at nist.gov Tue Dec 4 16:10:58 2007 From: peter.denno at nist.gov (Peter Denno) Date: Tue, 4 Dec 2007 11:10:58 -0500 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: References: <200712030729.59998.peter.denno@nist.gov> Message-ID: <200712041110.58495.peter.denno@nist.gov> 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 > > > 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 From peter.denno at nist.gov Tue Dec 4 16:57:47 2007 From: peter.denno at nist.gov (Peter Denno) Date: Tue, 4 Dec 2007 11:57:47 -0500 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <475581BA.3080402@optonline.net> References: <200712041110.58495.peter.denno@nist.gov> <475581BA.3080402@optonline.net> Message-ID: <200712041157.48110.peter.denno@nist.gov> 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 #'fail #'kids :do #'(lambda (k) (push k ))) at any point, and 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 From peter.hildebrandt at gmail.com Tue Dec 4 17:45:59 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 04 Dec 2007 18:45:59 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <200712041110.58495.peter.denno@nist.gov> References: <200712030729.59998.peter.denno@nist.gov> <200712041110.58495.peter.denno@nist.gov> Message-ID: 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 From peter.hildebrandt at gmail.com Tue Dec 4 18:09:17 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 04 Dec 2007 19:09:17 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <200712041157.48110.peter.denno@nist.gov> References: <200712041110.58495.peter.denno@nist.gov> <475581BA.3080402@optonline.net> <200712041157.48110.peter.denno@nist.gov> Message-ID: Kenny and Peter, thanks for your response. On Tue, 04 Dec 2007 17:57:47 +0100, Peter Denno 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 #'fail #'kids :do #'(lambda (k) > (push k ))) > > at any point, and 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 > From peter.denno at nist.gov Tue Dec 4 19:05:11 2007 From: peter.denno at nist.gov (Peter Denno) Date: Tue, 4 Dec 2007 14:05:11 -0500 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: References: <200712041157.48110.peter.denno@nist.gov> Message-ID: <200712041405.12064.peter.denno@nist.gov> 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 > > > 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 #'fail #'kids :do #'(lambda (k) > > (push k ))) > > > > at any point, and 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 From peter.hildebrandt at gmail.com Tue Dec 4 21:26:34 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 04 Dec 2007 22:26:34 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <200712041405.12064.peter.denno@nist.gov> References: <200712041157.48110.peter.denno@nist.gov> <200712041405.12064.peter.denno@nist.gov> Message-ID: On Tue, 04 Dec 2007 20:05:11 +0100, Peter Denno 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 From BlogBlaster at common-lisp.net Wed Dec 5 22:09:36 2007 From: BlogBlaster at common-lisp.net (BlogBlaster at common-lisp.net) Date: 05 Dec 2007 14:09:36 -0800 Subject: [cells-gtk-devel] Blast your ad to millions of blogs Message-ID: <20071205140934.CFBB0F09E501C207@from.header.has.no.domain> An HTML attachment was scrubbed... URL: -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: Unsubscribe email.txt URL: From peter.hildebrandt at gmail.com Thu Dec 6 12:15:20 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Thu, 06 Dec 2007 13:15:20 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <4755D927.9010401@optonline.net> References: <200712041157.48110.peter.denno@nist.gov> <200712041405.12064.peter.denno@nist.gov> <4755D927.9010401@optonline.net> Message-ID: On Tue, 04 Dec 2007 23:48:07 +0100, Ken Tilton wrote: > I just glanced at the GTk doc and did not see anything that would > support such a safety net, so you are probably on the right track > rolling one into Cells-Gtk. One might check with the GTk mailing list to > see if we are missing something. Basically the Prime Directive in these > GUI wrapper deals is to use the C library wherever possible. Thanks for the hint. Indeed there is a way to do this with GTK. Actually, there is two: The good people at gtk-app-devel-list at gnome.org pointed me to gtk_quit_add [1] and gtk_quit_add_destroy [2]. The former registers a callback which is called once gtk-main quits, while the latter simply schedules a window for destruction upon quitting the main app (as I learned, this was discussed on the GTK mailing list in February 1999 [3]). http://mail.gnome.org/archives/gtk-list/1999-February/msg00577.html [1] http://library.gnome.org/devel/gtk/2.12/gtk-General.html#gtk-quit-add [2] http://library.gnome.org/devel/gtk/2.12/gtk-General.html#gtk-quit-add-destroy [3] http://mail.gnome.org/archives/gtk-list/1999-February/msg00577.html I assume what we want is the former, that is code it along these lines - upon creation of a window we register a callback to dispose of the window once the app is closed (either md-awaken :after or make-instance :after -- which one is more appropriate? I'd go with the former, since this is the point in time where the window actually shows up on the screen) - in the callback we finally call not-to-be on self to properly dispose of the 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? >>> >>> Anyone? >> It'd like to hear some comments, too. > > It's a toss-up. The above has a slight "backdoor" feel to it, but that > might be the right way to go. It is definitely a hack. That's why I'm discussing this issue with you guys before publishing a patch. > Some background: Cells is all about making sure everything gets done and > in the right order when things change. But because the Cells engine is > ordering operations, interesting code is almost compelled to play within > the Cells framework, or it misses out on vital action (does not learn > about change) or at best runs at the wrong time. I think I understand. > If you creat a class called gtk-application and hang windows off that as > kids of an instance of that, then you can just not-to-be that instance > and have all windows tended to. Use of this instance gets enforced > simply by having the md-awaken method merely enforce that with a helpful > error message telling the developer the right way to make a window (push > a new instance onto the kids of a gtk-application instance. Well, the problem is that gtk-app is derived from window, hence its kids are the widgets to be displayed within it. As I mentioned before, I'd like to maintain compatibility, thus I'd rather leave this as it is. My suggestion: We introduce a new class, gtk-application, which so far does nothing but keep track of all windows opened by the app in its kids slots. Since not-to-be will remove them properly (and will be called either by the user or through the callback), we do not have to keep track of that. All that's left to do is register new instances -- which I'd do within the md-awaken method, so that instances are registered with the application object at the same time the callback is registered. > Of course some renegade developer might start leaking gtk-app instances, > but the sense I have here is that you just want to be able to work > freely, not fend off deliberate incompetence and sabotage. True. All I want is play freely at the repl, sleep quietly, and not worry about left-over instances, forgotten destroy calls etc. I.e. when I make-instance an object, the GC is eventually gonna get rid of it for me -- and so should cells-gtk. > With a gtk-app family, other bits of the application can then be aware > of the coming and going of windows. Perhaps like PhotoShop you have a > menu for open windows. That sort of thing. So be it. In the current model, this bookkeeping is independent of the destruction of windows, however, since we handle this with the gtk callback. > Otoh, the above slightly backdoor scheme is a lot simpler, and it may > even be superior/the only way to go. As I have said elsewhere, at the > boundary with the wrapped C library things can get ugly, you might > /need/ to step out of the Cells constraints a little. (And I hasten to > add you are not all that far outside the Cells system with the above.) > > Me, I would err on the side of using the gtk-app instance by default to > get other benefits (eg, a windows menu for some app) and fall back onto > managing windows outside Cells as usage persuades me that the gtk-app > approach will not hunt. I'll put together the model as described above and mail out a patch later today, so you guys can have a look at it. > >> >>>> 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. > > If the engine was running, I just hope it was the valve covers PD > pulled. :) Well ... I turned over the crank shaft with a big lever while the head were off (kinda like calling functions from the repl, isn't it?) ;) Peter > kt From peter.hildebrandt at gmail.com Sun Dec 9 15:19:34 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Sun, 09 Dec 2007 16:19:34 +0100 Subject: [cells-gtk-devel] start-app and multithreading? In-Reply-To: <47581763.9020903@optonline.net> References: <200712041157.48110.peter.denno@nist.gov> <200712041405.12064.peter.denno@nist.gov> <4755D927.9010401@optonline.net> <47581763.9020903@optonline.net> Message-ID: On Thu, 06 Dec 2007 16:38:11 +0100, Ken Tilton wrote: > Peter Hildebrandt wrote: >> On Tue, 04 Dec 2007 23:48:07 +0100, Ken Tilton >> wrote: >> >>> I just glanced at the GTk doc and did not see anything that would >>> support such a safety net, so you are probably on the right track >>> rolling one into Cells-Gtk. One might check with the GTk mailing list >>> to see if we are missing something. Basically the Prime Directive in >>> these GUI wrapper deals is to use the C library wherever possible. >> Thanks for the hint. Indeed there is a way to do this with GTK. >> Actually, there is two: The good people at >> gtk-app-devel-list at gnome.org pointed me to gtk_quit_add [1] and >> gtk_quit_add_destroy [2]. > > Cool. They are part of my patch to cells-gtk I just mailed out. >> The former registers a callback which is called once gtk-main quits, >> while the latter simply schedules a window for destruction upon >> quitting the main app (as I learned, this was discussed on the GTK >> mailing list in February 1999 [3]). >> http://mail.gnome.org/archives/gtk-list/1999-February/msg00577.html >> [1] >> http://library.gnome.org/devel/gtk/2.12/gtk-General.html#gtk-quit-add >> [2] >> http://library.gnome.org/devel/gtk/2.12/gtk-General.html#gtk-quit-add-destroy >> [3] http://mail.gnome.org/archives/gtk-list/1999-February/msg00577.html >> I assume what we want is the former, that is code it along these lines >> - upon creation of a window we register a callback to dispose of the >> window once the app is closed (either md-awaken :after or >> make-instance :after -- which one is more appropriate? I'd go with >> the former, since this is the point in time where the window actually >> shows up on the screen) > > I think we want to register the callback as soon as possible so we do > not miss any action the GTk side -- I am imagining a sequence where > something goes wrong during window instantiation and GTk snuffs a window > while we are still going about building it from the Lisp side. Of course > Gtk would complain about continued attempts to build a snuffed window, > but things might go more neatly if we avoid that by getting the callback > set up ASAP. Yep, it's part of make-instance ((self window)) now. > In the latest Cells (not yet pulled into Cells-GTk) there is an > elaborate scheme for handling such matters -- wherever messages get > prepped for Gtk they would get enqueued, not actually sent. Then Cells > allows the application to specify a custom handler for this queue, which > handler can sort the messages so they happen in just the right order. In > this case we would tag the creation message with :win-make and tag the > callback registration with :win-quit-cb-register and sort them to run > back to back. And in case anyone is thinking ahead, I believe there is > enough state information on the Lisp side to handle gracefully "snuff" > notifications that come in during window creation. Well, of course that'd be a great project. That would put us in a position to handle threading properly by wrapping the execution of the command queue win with-gdk-threads and thus be truly thread-safe in gdk terms. Right now we ignore this issue more or less since it does not seem to be a problem. (At least I haven't seen anything bad happen despite of some rigorous testing on test-gtk). Maybe after all lisp does not really process stuff from the repl while in a C callback? > >> - in the callback we finally call not-to-be on self to properly >> dispose of the 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? >>>>> >>>>> >>>>> Anyone? >>>> >>>> It'd like to hear some comments, too. >>> >>> >>> It's a toss-up. The above has a slight "backdoor" feel to it, but >>> that might be the right way to go. >> It is definitely a hack. > > :) I did not mean anything disparaging by "backdoor". Indeed, we are at > the very boundary between C and Lisp "Gtks" where we might very much > /want/ to step out of the Cells machinery (but so far it looks like we > can stay within, if only because Cells does allow one to play with > md-awaken and not-to-be and get a c little closer to the action when > needed). Well, actually it turned out that this way I might be messing with cells too much. The mapcar #'not-to-be appears to be somewhat radical compared to a modest (not-to-be self) in the gtk-quit callback. >> That's why I'm discussing this issue with you guys before publishing >> a patch. >> >>> Some background: Cells is all about making sure everything gets done >>> and in the right order when things change. But because the Cells >>> engine is ordering operations, interesting code is almost compelled >>> to play within the Cells framework, or it misses out on vital action >>> (does not learn about change) or at best runs at the wrong time. >> I think I understand. >> >>> If you creat a class called gtk-application and hang windows off that >>> as kids of an instance of that, then you can just not-to-be that >>> instance and have all windows tended to. Use of this instance gets >>> enforced simply by having the md-awaken method merely enforce that >>> with a helpful error message telling the developer the right way to >>> make a window (push a new instance onto the kids of a gtk-application >>> instance. >> Well, the problem is that gtk-app is derived from window, hence its >> kids are the widgets to be displayed within it. As I mentioned >> before, I'd like to maintain compatibility, thus I'd rather leave this >> as it is. My suggestion: >> We introduce a new class, gtk-application, which so far does nothing >> but keep track of all windows opened by the app in its kids slots. > > That is what I meant by gtk-app, which I did not know existed. Now we have a global variable *system*, and every window pushes itself open creation into the kids of *system*. There is a function called (open-windows) that returns those kids which currently have a gtk representation. (It appears I am not capable of removing a window from the kids of *system* without causing some cells havoc). Still a hack, but closer to the Right Thing. And once I figure it out, I can change it all internally wihtout modifying the interface. > Is this the Windows model where a window (or the prime window) is the > same as an application? I grew up developing on the mac where one could > close all the windows and still have the app and its menu bar available. Thanks for pointing that out. Indeed I had the windowsy idea of a main window being equivalent to the app in mind (which seems to match the gtk philosophy). Of course there is no point why a GUI toolkit should dictate this view. The version I mailed out earlier today allows you work either way. - Have a main app thread that is independent of any specific window and close it down at its on discretion (maybe a menu command or the like) - Have a main window, closing which will result in closing all the other windows. My current version supports only one app per image in the later model, whereas you can run several applications of the former kind within the same lisp image. >> Since not-to-be will remove them properly (and will be called either >> by the user or through the callback), we do not have to keep track of >> that. All that's left to do is register new instances -- which I'd do >> within the md-awaken method, so that instances are registered with the >> application object at the same time the callback is registered. > > That would work. I do not mean to confuse things -- I think registering > for quits is still The Right Way meaning that is how windows would get > managed, but I might /still/ have gtk-application to support things like > my imagined menu of windows, drag/drop between windows, etc etc. Yep, this is how it is done now. gtk-quit closes windows if you want that, and (open-windows) gives you a list of all open instances of window (or its subclass gtk-app). > Anyway, sounds like you are doing pretty good sorting this out, just > throwing thoughts over the wall. Thanks! Regards, Peter > cheers, ken From peter.hildebrandt at gmail.com Tue Dec 11 11:52:55 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 11 Dec 2007 12:52:55 +0100 Subject: [cells-gtk-devel] Re: Multithreading patch In-Reply-To: <200712100845.38022.peter.denno@nist.gov> References: <200712100845.38022.peter.denno@nist.gov> Message-ID: On Mon 10 Dec 2007 14:45:37 +0100, Peter Denno wrote: > On Sunday 09 December 2007 09:58, Peter Hildebrandt wrote: >> Here it is, finally. Multithreading for cells-gtk on sbcl/linux. > > Hi Peter, > > I'll try this out and get back to you, hopefully today, while your > mind is still in this stuff. I think I finally got multiple calls to (init-gtk) straight (so far multiple initializations have been an issue, since cells-gtk-init destroys state vital to open application windows). Here's a patch for gtk-app.lisp that does three things - handle mutiple calls to init-gtk gracefully [1] - add a key parameter :close-all-windows to init-gtk (which closes all open windows cleanly by signalling gtk-main-quit [2]) - move the bookkeeping section beneath around to remove the warning about *system* being undefined The patch is incremental to the previous one I mailed out. Peter ------ [1] The solution was to separate loading the gtk librbaries from resetting cells-gtk, along these lines: - load libs if necessary - use lib func to check whether threading is initialized - if not, init threading, cells, gtk [2] Yep, this works now. The trick is, you can use (gtk-main-quit) to exit a gtk-main loop that is *running* in a different thread, and this will cleanly close all open windows. However, it seems you cannot use it to cleanup a *stale* instance that was left due to a signal/condition > >> I built the patch against the current cvs (which is different from >> the tar.gz linked on the website, which is different from the >> asdf-install version). Applications will work just as they used to >> (a littler better, hopefully, see below). >> >> To run an application in the background, just use the new >> >> (start-win 'app-class initargs) >> >> which starts your application window in the background and returns >> right to the repl. The return value is the freshly created >> instance of app-class. That's it. >> >> To reset cells-gtk, there is the new (init-gtk), which closes all >> open windows before calling cells-gtk-init, and also takes care of >> threading. >> >> A couple details: >> >> - To simulate the idea of a "main window" (thanks Kenny for >> pointing out that this is not something "natural") gtk-app now has >> the slot terminate-on-exit -- if this is set to true, all open >> windows will be closed when this is closed >> >> - Calls from the repl can be wrapped in (with-gdk-threads ...), in >> theory this is the right thing to do. In practice I have not seen >> anything bad happening, when I didn't. >> >> - You can start the gtk thread manually by calling (start-gtk-main) >> >> - The gtk thread can be terminated by calling (stop-gtk-main). In >> order to use gtk again, you will have to restart lisp. >> >> Here's a silly example of interactive UI development: >> >> ;; make a package >> (defpackage :cgtk-user (:use :cl :cgtk :cells)) >> (in-package :cgtk-user) >> >> ;; start a blank app >> (start-win 'gtk-app :title (c-in "My App") :kids (c-in nil)) ; it >> appears >> >> ;; bind it to a variable >> (defparameter *app* *) >> >> ;; change its title >> (setf (title *app*) "Application") ; the title changes >> >> ;; create a vbox to take the our widgets >> (push (mk-vbox :kids (c-in nil)) (kids *app*)) >> (defparameter *vbox* (first *)) >> >> ;; make a button >> (push (mk-button :label "Click me" :on-clicked (callback (w e d) >> (print 'you-clicked-me))) (kids *vbox*)) ; it shows up >> >> ;; make a counter >> (push (mk-button :label (c-in "Me too") :on-clicked (let ((count >> 0)) (callback (w e d) (print (incf count))))) (kids *vbox*)) >> >> ;; relabel that button >> >> (setf (label (first *)) "Counter") >> >> ;; kill your window >> (not-to-be *app*) >> >> >> Some technical details: >> >> - The way gtk-app used to handle restarts resulted in effect in a >> mutual recursion: Closing a window resulted in signaling quit, >> which led to transfer of control out of gtk-main into lisp, which >> then exited, leaving the gtk-main task waiting for a return (that >> would never come). Each time you ran an application, that stack >> would build up. >> >> The previous way to unwind that stack upon exit, like >> >> (loop for i below (gtk-main-level) do (gtk-main-quit)) ;; I >> had this one somehow >> >> or >> >> (loop while (> (gtk-main-level) 0) do (gtk-main-quit)) ;; from >> cvs, results for me in endless loop, since gtk-main-level won't >> reduce for me by calling gtk-main-quit like this >> >> does not do the trick, since gtk-main-quit only workd as expected >> when called from within a gtk-main initiated callback, not after >> control has been violently transfered out of gtk-main by a signal. >> In effect, I found there seems to be no way to resume an open >> instance of gtk-main once a lisp callback has used error or signal >> to uncleanly jump out of it. I believe that this could be the >> reason why the termination code in gtk-app.lisp included several >> fixes for different lisps. >> >> I rewrote gtk-app completely so that now in effect one instance of >> gtk-main runs continously. When an application with >> :terminate-on-close is closed, gtk-main-quit is signalled through >> gtk, gtk-main thus cleanly left, through gtk-quit callbacks open >> windows are closed, and gtk-main is called again. This way no call >> stack piles up. In the normal case there should be no callstack >> building up this way. You can check with (gtk-main-level). >> >> Only errors in callbacks still lead to recursive re-entries. >> Therefore I left the current termination code in place, though my >> changes should make this the exception rather than the normal case. >> >> If someone figures out how to reenter gtk-main after a callback >> signaled an error, I'd be very excited to learn. >> >> - I added an additional error handler that catches lisp errors. >> Thus, if a callback raises a lisp error, this is caught within the >> thread running gtk-main and a message box is displayed. The user >> has the option to resignal the error (results in invoking the >> debugger) or to "recklessly continue" (which works fine as long as >> the callback has not caused inconsistent state). This is helpful >> if (like me) you deal with user input and you prototype does not >> handle typos well ;) >> >> - cells-gtk has a major leak due to the nature it synchronized clos >> with gtk objects: Upon creation, each clos object in cells-gtk is >> registered in *gtk-objects* along with the pointer to its gtk >> equivalent. However, this entry is not removed when the >> gtk-instance is freed. When subsequently new objects are created, >> gtk may well reuse this space, causing cells-gtk to signal an error >> like "new object has pointer x, but this is already known as >> such-and-such". Curiously, it is usually only *gtk-objects* which >> holds a reference to an obsolete object. For instance, running >> test-gtk allocates some 330 objects in *gtk-objects*, about 100 of >> which are not freed, when the app is closed. >> >> The right way to solve this would be to hook into the >> on-delete-event signal of the widget object -- unfortunately it >> seems this is not called every time gtk deletes a widget. I >> introduced some additional cleanup code in cells-gtk, thus covering >> about 70% of leftover widgets. >> >> For the rest, I believe the right thing is to trust gtk when in >> doubt -- thus I modified the gtk-objects registry to forget about >> the old object if gtk has given the pointer to a new one. (It used >> to throw an error and break gtk. I had it signal a warning in the >> beginning, but I came to believe that this cannot be the right way >> to deal with it; it would entail writing C-style memory management, >> carefully keeping track of objects and manually freeing them. >> Ewww.) >> >> This hasn't been a problem so far since it seems most cells-gtk >> apps just call cells-gtk-init before launching their app, thus >> wiping *gtk-objects* (and along with that all gtk state). Not >> exactly dynamic ;). >> >> For an example where the problem arises, consider the following >> slot def: >> >> (caption-widgets :initform (c? (loop for caption in captions >> collecting (mk-label :text caption)))) >> >> Once you got to somehow free all the old labels everytime you >> create new ones, things get -- ehh -- ugly. >> >> It looks like what we see here is the due penalty for using a >> C-library for doing our window management. Maybe one day CLIM will >> be fast and sleek. >> >> - For every new window, upon creation a gtk-quit callback is >> registered, closing that window once gtk-main-quit is called from >> within a callback. You force this to happen by setting >> terminate-on-close to t in a gtk-app window. >> >> - I moved some initialization from start-app to an own function, >> init-gtk. >> >> - To prevent double initialization of glib's threading faacility >> via g-thread-init, there is a global variable in gtk-app.lisp. >> This works fine, until you recompile this file. So I figured why >> keep track of state when glib can do this for us? It turns out >> there is a macro in glib for this purpose. Since it's a macro (not >> a function), I added a respective function to gtk-adds.c. A >> dependency on glib-2.0 is introduced, since threading is a glib >> feature, not gtk (this should be uncritical -- linux systems >> without glib are -- errr -- rare). I added the corresponding stuff >> to Makefile. Thus, when you compile cells-gtk with #+libcellsgtk, >> it will use this function. Otherwise there is a flag variable in a >> closure around (init-gtk). >> >> - The threading code is currently SBCL specific. However, I >> singled out the needed primitives in four macro definitions, >> therefore it should be easy to add the respective calls for other >> implementations: >> >> >> (defmacro thread-current () >> #+sbcl `(identity sb-thread:*current-thread*) >> ) >> >> (defmacro thread-make (thread-fn name) >> (declare (ignorable name)) >> #+sbcl `(sb-thread:make-thread ,thread-fn :name ,name) >> ) >> >> (defmacro thread-kill (thread) >> #+sbcl `(sb-thread:terminate-thread ,thread) >> ) >> >> (defmacro thread-yield () >> #+sbcl `(sb-thread:thread-yield) >> ) >> >> - My changes will compile and run just fine without sbcl. >> Everything should work normally, you just won't be able to use >> (start-win). >> >> That's all I can think of right now. Let me if clarifications are >> needed. >> >> Regards, >> Peter > -------------- next part -------------- A non-text attachment was scrubbed... Name: cells-gtk-threading-2.patch Type: application/octet-stream Size: 2536 bytes Desc: not available URL: From peter.hildebrandt at gmail.com Tue Dec 11 15:51:55 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Tue, 11 Dec 2007 16:51:55 +0100 Subject: [cells-gtk-devel] Re: Multithreading patch In-Reply-To: References: Message-ID: Here it is, finally. Multithreading for cells-gtk on sbcl/linux. http://www.washbear-network.de/peterblog/wp-content/uploads/2007/12/cells-gtk-threading-2.patch (since it's too big for the list, I revived my blog and put stuff there. Check it out if you like: ) I built the patch against the current cvs (which is different from the tar.gz linked on the website, which is different from the asdf-install version). Applications will work just as they used to (a littler better, hopefully, see below). To run an application in the background, just use the new (start-win 'app-class initargs) which starts your application window in the background and returns right to the repl. The return value is the freshly created instance of app-class. That's it. To initialize cells-gtk, there is the new (init-gtk). It is threadsafe and makes sure that no important state is destroyed. That is, you can call it while other windows are open in the background. Don't do this with cells-gtk-init. You will need to call init-gtk before you do anything to cells-gtk (it loads foreign libraries). start-win takes care of that for you. A couple details: - To simulate the idea of a "main window" (thanks Kenny for pointing out that this is not something "natural") gtk-app now has the slot terminate-on-exit -- if this is set to true, all open windows will be closed when this is closed. - (open-windows) gives you a list of, well, open windows - You can close all windows by (close-all-windows) or (init-gtk :close-all-windows t) - Calls from the repl can be wrapped in (with-gdk-threads ...), in theory this is the right thing to do. In practice it mostly works if you don't. However, every now and then I broke my gdk this way and had to restart lisp. In a real app, always wrap calls that might affect your window in (with-gdk-threads ...). Multithreading and gtk is tricky. Calls have to wrapped in the macro *exactly once* -- do it more than once, and you get a deadlock. Do it less than once, and gtk might fail with an Xlib asynchronity. For now, wrap everything at the highest level in with-gdk-threads, except for start-win. - You can start the gtk thread manually by calling (start-gtk-main). start-win does that for you. - The gtk thread can be terminated by calling (stop-gtk-main). In order to use gtk again, you will have to restart lisp. Normally this is utterly useless. You might want it if you ship your app as a save-lisp-and-die image. Maybe. Here's a silly example of interactive UI development: ;; make a package (defpackage :cgtk-user (:use :cl :cgtk :cells)) (in-package :cgtk-user) ;; start a blank app (start-win 'gtk-app :title (c-in "My App") :kids (c-in nil)) ; it appears ;; bind it to a variable (defparameter *app* *) ;; change its title (setf (title *app*) "Application") ; the title changes ;; create a vbox to take the our widgets (push (mk-vbox :kids (c-in nil)) (kids *app*)) (defparameter *vbox* (first *)) ;; make a button (push (mk-button :label "Click me" :on-clicked (callback (w e d) (print 'you-clicked-me))) (kids *vbox*)) ; it shows up ;; make a counter (push (mk-button :label (c-in "Me too") :on-clicked (let ((count 0)) (callback (w e d) (print (incf count))))) (kids *vbox*)) ;; relabel that button (setf (label (first *)) "Counter") ;; close all windows (close-all-windows) That's all I can think of right now. Let me if clarifications are needed. Regards, Peter Some technical details: - The way gtk-app used to handle restarts resulted in effect in a mutual recursion: Closing a window resulted in signaling quit, which led to transfer of control out of gtk-main into lisp, which then exited, leaving the gtk-main task waiting for a return (that would never come). Each time you ran an application, that stack would build up. The previous way to unwind that stack upon exit, like (loop for i below (gtk-main-level) do (gtk-main-quit)) ;; I had this one somehow or (loop while (> (gtk-main-level) 0) do (gtk-main-quit)) ;; from cvs, results for me in endless loop, since gtk-main-level won't reduce for me by calling gtk-main-quit like this This does not do the trick, since gtk-main-quit only works as expected for active gtk-main loops, not for stale ones (which you get after transferring control out of them by means of a signal or error). In effect, I found no way to resume an open instance of gtk-main once a lisp callback has used error or signal to uncleanly jump out of it. I believe that this could be the reason why the termination code in gtk-app.lisp needs several workarounds for different lisps: something's not kosher here. I rewrote gtk-app completely so that now in effect one instance of gtk-main runs continously. When an application with :terminate-on-close is closed, gtk-main-quit is invoked while gtk-main is still running, gtk-main thus cleanly left. Through gtk-quit callbacks open windows are closed, and gtk-main is called again. This way no call stack piles up. In the normal case there should be no callstack building up this way. You can check with (gtk-main-level). Only errors in callbacks still lead to recursive re-entries. Therefore I left the current termination code in place, though my changes should make this the exception rather than the normal case. If someone figures out how to re-enter gtk-main after a callback signaled an error, I'd be very excited to learn. - I added an additional error handler that catches lisp errors. Thus, if a callback raises a lisp error, this is caught within the thread running gtk-main and a message box is displayed. The user has the option to resignal the error (results in invoking the debugger) or to "recklessly continue" (which works fine as long as the callback has not caused inconsistent state). This is helpful if (like me) you deal with user input and you prototype does not handle typos well - cells-gtk has a major leak due to the nature it synchronized clos with gtk objects: Upon creation, each clos object in cells-gtk is registered in *gtk-objects* along with the pointer to its gtk equivalent. However, this entry is not removed when the gtk-instance is freed. When subsequently new objects are created, gtk may well reuse this space, causing cells-gtk to signal an error like "new object has pointer x, but this is already known as such-and-such". Curiously, it is usually only *gtk-objects* which holds a reference to an obsolete object. For instance, running test-gtk allocates some 330 objects in *gtk-objects*, about 100 of which are not freed, when the app is closed. The right way to solve this would be to hook into the on-delete-event signal of the widget object -- unfortunately it seems this is not called every time gtk deletes a widget. I introduced some additional cleanup code in cells-gtk, thus covering about 70% of leftover widgets. For the rest, I believe the right thing is to trust gtk when in doubt -- thus I modified the gtk-objects registry to forget about the old object if gtk has given the pointer to a new one. (It used to throw an error and break gtk. I had it signal a warning in the beginning, but I came to believe that this cannot be the right way to deal with it; it would entail writing C-style memory management, carefully keeping track of objects and manually freeing them. Ewww.) This hasn't been a problem so far since it seems most cells-gtk apps just call cells-gtk-init before launching their app, thus wiping *gtk-objects* (and along with that all gtk state). Not exactly dynamic ;). For an example where the problem arises, consider the following slot def: (caption-widgets :initform (c? (loop for caption in captions collecting (mk-label :text caption)))) Once you got to somehow free all the old labels everytime you create new ones, things get -- ehh -- ugly. It looks like what we see here is the due penalty for using a C-library for doing our window management. Maybe one day CLIM will be fast and sleek. - For every new window, upon creation a gtk-quit callback is registered, closing that window once gtk-main-quit is called from within a callback. You force this to happen by setting terminate-on-close to t in a gtk-app window. - I moved some initialization from start-app to an own function, init-gtk. This one also takes care of multiple initialization. - To prevent double initialization of glib's threading faacility via g-thread-init, there is a global variable in gtk-app.lisp. This works fine, until you recompile this file. So I figured why keep track of state when glib can do this for us? It turns out there is a macro in glib for this purpose. Since it's a macro (not a function), I added a respective function to gtk-adds.c. A dependency on glib-2.0 is introduced, since threading is a glib feature, not gtk (this should be uncritical -- linux systems without glib are -- errr -- rare). I added the corresponding stuff to Makefile. Thus, when you compile cells-gtk with #+libcellsgtk, it will use this function. Otherwise there is a flag variable in a closure around (init-gtk). - On the same note, init-gtk checks whether the libs have beeen loaded by calling a function (gtk-main-level) from within a handler-case. If this fails, we know they haven't been loaded. I prefer to tap into exiting state information over duplicating it. - The threading code is currently SBCL specific. However, I singled out the needed primitives in four macro definitions, therefore it should be easy to add the respective calls for other implementations: (defmacro thread-current () #+sbcl `(identity sb-thread:*current-thread*) ) (defmacro thread-make (thread-fn name) (declare (ignorable name)) #+sbcl `(sb-thread:make-thread ,thread-fn :name ,name) ) (defmacro thread-kill (thread) #+sbcl `(sb-thread:terminate-thread ,thread) ) (defmacro thread-yield () #+sbcl `(sb-thread:thread-yield) ) - My changes will compile and run just fine without sbcl. Everything should work normally, you just won't be able to use the threading functions like start-win and close-all-windows. From peter.hildebrandt at gmail.com Wed Dec 12 01:35:44 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Wed, 12 Dec 2007 02:35:44 +0100 Subject: [cells-gtk-devel] Multithreading patch, v2 In-Reply-To: <200712110953.10777.peter.denno@nist.gov> References: <200712110953.10777.peter.denno@nist.gov> Message-ID: Here's a new version of my patch http://www.washbear-network.de/peterblog/wp-content/uploads/2007/12/cells-gtk-threading-121207.patch Again, it builds against the CVS version. I did quite a bit of testing and I would call it "stable" for my purposes. I'd appreciate if you guys could try to break it and let me know if you succeeded. This patch includes an answer to the question of thread safety. In short, it wraps every call to gdk/gtk in a thread-safe lock (with-gdk-threads ...), thus creating thread safety at the lowest level while at the same time not blocking longer than necessary. Cheers, Peter ----- The longer story (in case anyone is interested): First and foremost, I modified with-gdk-threads to simulate a recursive lock, that is, if you call with-gdk-threads from within a with-gdk-thread, nothing bad happens (i.e. no dead lock). Additionally, since we know that all callbacks from gtk-main are from within a lock, everything from the gtk-main thread gets a free pass (the overhead boils down to a pointer comparisson). This enables us to use with-gdk-threads generously. In other words, every call to a gtk/gdk library function is now automatically wrapped and can thus be used from any thread. At least with test-gtk, there seems to be hardly any performance penalty, and it makes it ultimately easy to deal with threading -- just ignore it. Additionally I fixed start-gtk-main. Now in case it has forgotton the handle of the gtk-main thread, it checks the environment and reconnects if it finds one. This way, a running cells-gtk even survives complete package recompilations etc. Here's another bit of sample code for the repl: Hello World, interactive style: ;; fire up a hello world window (start-win 'gtk-app :title "Hello World" :kids (c-in nil)) ;; create a little playground (defparameter vbox (first (push (mk-vbox :kids (c-in nil)) (kids *)))) ;; make a label (push (mk-label :text (c-in "Heyho!")) (kids vbox)) ;; have some fun (push (mk-button :label "Click me!" :on-clicked (callback (w e d) (print :hello-world))) (kids vbox)) ;; now something exciting (push (mk-label :text (c-in "") :md-name :counter) (kids vbox)) (push (mk-button :label "Count" :on-clicked (let ((c 0)) (callback (w e d) (setf (text (fm-other :counter)) (format nil "~r" (incf c)))))) (kids vbox)) From peter.hildebrandt at gmail.com Wed Dec 12 03:21:46 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Wed, 12 Dec 2007 04:21:46 +0100 Subject: [cells-gtk-devel] Re: [cells-devel] Something like a def-family-observer? In-Reply-To: <475F3BE6.9040206@optonline.net> References: <475EED1B.6000504@optonline.net> <475F3BE6.9040206@optonline.net> Message-ID: > > OK, I understand. You are right, we want the tree-view to update > automatically as the model changes, by which I mean either the > population of the model or the value of a displayed slot of a node of > the model, and normally this is how my GUIs work. It should be easy to > get this in cells-gtk. Thanks for the reassuring words. Sounds like we're in for some fun :-) > I may have to build Cells-gtk. Possibly you have missed some existing > mechanism in cells-gtk, so I have CCed that list. Or possibly the Well, I got editing "cells" in the treeview through the gui to work in cells-gtk (which was not supported so far). Thanks to that excercise I know the tree-view code in cells-gtk pretty much inside out. I don't think I missed something. > cells-gtk tree-view got implemented with a static model in mind and it > is merely time to break that assumption. No big deal, assuming GTk's API > has the chops (which I wager it does). You're exactly right. Cells-gtk is only prepared to deal with fully replacing the lisp side of the model. All the code for rebuilding the model on the gtk-side is triggered from the def-c-observer on the roots slot. So either you have something simple like a list there (and everytime you change it the observer rebuilds the whole model), or you have something complex like a family (and it only gets rebuilt when you setf that slot) The GTK trieview OTOH is built on top of a dynamic model. There is all the bits and pieces to do pretty much anything with that model. I've used this tutorial so far: http://scentric.net/tutorial/treeview-tutorial.html The API is here: http://library.gnome.org/devel/gtk/2.11/GtkTreeStore.html > A question is how much work gets done on the Lisp side. Do we end up > with one Lisp widget instance for each observed row? Better yet, for > each field of each row? ie, the lisp tree-view runs down the model > rooted in "roots" looking for kids of kids and then... Not at this point. The current cells-gtk has nothing more fine grained than the tree-store/tree-model whatever they call it. The rows and fields are all assembled "on the fly". But -- this is what I had in mind. > hmmm, maybe not, and it looks like I better build Cells-gtk. Keep in mind that it needs the "cells_2.0" branch. This is not in CVS but part of the release on the website. Also, at least for me (SBCL/linux) there was a bug in gtk-app.lisp, resulting in a crash when closing an application. Line 124 reads (loop while (> (gtk-main-level) 0) do (gtk-main-quit)) but should be (dotimes (i (gtk-main-level)) (gtk-main-quit)) > Normally what I do is mirror each thingy on the C side with a thingy on > Lisp side, so there would be tree-view and then tree-view-row and maybe > tree-view-row-field (or tree-view-cell in spreadsheet-ese). To make > things super-flexible, I then make those types parameterizable, so I can > make a custom tree-view-cell (by subclassing tree-view-cell) and then > specify to tree-view that it should use that subclass as it is > traversing my data model building up the Lisp tree-view. Sounds great. So I am not the only dreamer out here :) > At this point, of course, on the Lisp side anyway I can "see" cells-wise > everything that is happening, including tree insertion/deletions and > changes to slot values of model nodes. The next question is how to tell > GTk. Exactly, that is what I had in mind when I outlined that "tto" strategy. Have generic model embody the functionality of observing lisp and updating C, and then subclass it for the various cases. As a side effect this will make handling user input a lot nicer: The bits linking the clos slots to the tree-view cells might know about the inverse function and thus propagate a setf back, i.e. User changes something => tree-view widget sends setf to the corresponding connector => connector setf's the corresponding slot in the observed model => that gets propagated into the connector => the connector tells GTK about the change > Does Gtk give us the granularity to operate on the tree view, ie, does > it allow us to say "remove this row" or change this field of this row to > show this new value ("My child")? I think you said yes to this in your > prior note. Yes, it does (see pointers above). > If so, the next question is if we have done the FFI for those bits of > the API. :) Mostly, I'd say. cells-gtk/gtk-ffi has append/insert functions and most of the path/iter stuff to locate items. A function for setting values is also there. What's left is removing stuff. Shouldn't be too hard. > I'll stop here since I am just collecting info, but rest assured this is > normal stuff and if the GTk API offers the hooks we should have no > problem getting information to flow from the lisp side to Gtk, using the > ideas hinted at above. Cool. I'm looking forward to it. Cheers, Peter > kt > > > >> So I came up with the idea to make the interface to the tree-view a >> tree of cells, so that in effect for every box that is displayed in >> the treeview there is a dependent cell in the treeview (Instead of one >> cell connecting to the kids of the root). >> One way to do this would be to have an observer object >> (defmodel tto () ((obs :accessor obs :initarg :obs) >> (corresponding-point-in-gtk)) >> (def-c-output obs ((self tto)) >> (call-gtk-and-set corresponding-point-in-gtk new-value)) >> Then we would make six of these, two per node (name and age) when >> roots is assigned: >> (def-c-output roots ((self tree-view)) >> (mapcar (lambda (nd) (make-instance 'tto :obs (c? (md-name nd)) >> :corresponding... ...)) (roots self)) >> ;; of course we'll have to recurse into the kids and the names of >> the accessors >> ;; are supplied somewhere to the treeview etc. >> Additionally we'd have some sort of structure observer that listens on >> the kids of every node (here three for three nodes) and reacts to >> changes by adding/deleting rows to the tree-view. Additionally it'd >> have to create/remove tto's to listen to the slots of new nodes or >> stop listening to removed nodes. >> Another option would be what I dubbed the "family-observer": Some >> piece of magic that gets notified when any slot in a model or any of >> its decendents gets modified. The notification would idealy include >> the modified node, the modified slot, the new-value and a path from >> the root to the node (could be a closure, (lambda (n) (nth 2 (nth 3 >> (nth 0 (kids n] => (lambda root) is the modified node, or just a list >> '(0 3 2)). That family observer could then take this >> notification/message and do the appropriate action. >> I do not understand cells enough to judge whether this would even be >> possible. So maybe there is something, some instance where all state >> changes get passed through, that could filter out the ones going to >> root or its descendents, maybe not. >> Well, I hope it's clearer now what I wish to do. >> In reply to your comments: >> On Tue, 11 Dec 2007 21:03:39 +0100, Ken Tilton >> wrote: >> >>> More below, just retro-inserting notes: normally in /my/ work the >>> parent slot is not even a Cell, but I /have/ done that a couple of >>> times on certain subclasses of Family and it did work. >> Yeah, thanks for pointing that out. I got that confused from time to >> time and was wondering why a (c? parent) does not learn about (kids >> parent). >> >>> Confused: The kids slot is a Cell, so any rule anywhere (on slots not >>> just the ascendants) that references (kids ) will get >>> kicked off whent that changes. More below on this. >> I was wondering whether there would be a way to kick of that rule >> when something deeper down in the tree gets modified (see above, the >> family observer) >> >>>> If you have seen my ton of mails on the cells-gtk-devel list, you >>>> know I'm doing some GUI work with cells-gtk at the moment. I ran >>>> into the following issue: cells-gtk can use a family tree as a >>>> natural representation of the contents of a tree-view. However, >>>> when I change the items in that family tree, cells-gtk currently >>>> has no way of updating the C data structure correspondingly. >>> >>> >>> This sentence seems crucial and puzzles me some. What precisely is >>> meant by "when I change the items in that family tree"? Do you mean >>> reorgamize the tree by moving kids between parents? >> Maybe this, maybe changing a cell slot on a node in the tree, maybe >> adding kids, maybe removing them. In effect I want to keep the >> projection of the tree onto the tree-view consistent with the tree. >> >>> As for "update the C data structure correspondingly", well, /what/ C >>> data structure, this is the first I have heard of it. Do you mean the >>> C struct implementing the tree view, or a C struct one might be >>> "inspecting" by mapping its hierarchy to a tree of widgets? >> The gtk tree-view displays an internal data structure, consisting of >> rows of "cells". rows can have children. Whenever we want to put >> some lisp structure in the treeview, we have to traverse it and build >> the corresponding gtk stuff. >> >>> Let me clarify a couple of things first. btw, I do not even have >>> Cells-Gtk installed anywhere so I may have to do that if things get >>> too complicated. >> I hope it won't come that far :) I really appreciate your help, esp. >> given you won't even use cells-gtk. >> >>> First of all, my models normally do not have the parent slot as a >>> Cell at all, meaning I do not move things from one parent to another. >>> But! There have been times when I did that and it did seem to work, >>> so let's keep that in mind going forward. >> Probably we won't have to. I believe this one comes out of a >> misunderstanding -- or am I not getting it? >> >>> Second, without looking I am almost certain the kids slot of the >>> family class already does let applications react to changes to kids, >>> so I am not clear on why TTO is necessary (unless we are talking >>> about also needing the parent to be a Cell, which as I said might >>> Just Work if we put our minds to it). >> This confuses me. "the kids slot of the family class already does >> let applications react to changes to kids" -- what exactly do you mean >> by that? Adding/removing kids? Changes to the kids themselves (setf >> (md-name (first (kids root))) "Joe")? >> To me it looks like neither happens. >> (defparameter root (make-instance 'node :md-name "Root" :kids (c-in >> nil))) >> => ROOT >> (defparameter tview (make-instance 'tree-view :roots (c? (kids root)))) >> => TVIEW >> (push (make-instance 'node :md-name "child") (kids root)) >> => (child) >> ====> Nothing >> (roots tview) >> => ("roots have changed" (child)) >> => (child) >> (i.e. the def-c-observer only gets called once I query the slot) >> >>> Third, I'd like to understand the functionality better. Is the goal >>> to manipulate a tree on the C side via a [Cells-]Gtk tree view? Or >>> just dynamically restucture a treeview? This is the same question as >>> above where I ask about what is meant by "update the C data >>> structure"? >> The goal is >> I modify lisp stuff >> ==> the GTK tree model stuff ("C data structure") gets updated >> ==> The treeview reflects my changes to the lisp stuff >> It looks like I got myself into quite a mess here ... >> Cheers, >> Peter >> > From peter.hildebrandt at gmail.com Wed Dec 12 03:21:46 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Wed, 12 Dec 2007 04:21:46 +0100 Subject: [cells-gtk-devel] Re: [cells-devel] Something like a def-family-observer? In-Reply-To: <475F3BE6.9040206@optonline.net> References: <475EED1B.6000504@optonline.net> <475F3BE6.9040206@optonline.net> Message-ID: > > OK, I understand. You are right, we want the tree-view to update > automatically as the model changes, by which I mean either the > population of the model or the value of a displayed slot of a node of > the model, and normally this is how my GUIs work. It should be easy to > get this in cells-gtk. Thanks for the reassuring words. Sounds like we're in for some fun :-) > I may have to build Cells-gtk. Possibly you have missed some existing > mechanism in cells-gtk, so I have CCed that list. Or possibly the Well, I got editing "cells" in the treeview through the gui to work in cells-gtk (which was not supported so far). Thanks to that excercise I know the tree-view code in cells-gtk pretty much inside out. I don't think I missed something. > cells-gtk tree-view got implemented with a static model in mind and it > is merely time to break that assumption. No big deal, assuming GTk's API > has the chops (which I wager it does). You're exactly right. Cells-gtk is only prepared to deal with fully replacing the lisp side of the model. All the code for rebuilding the model on the gtk-side is triggered from the def-c-observer on the roots slot. So either you have something simple like a list there (and everytime you change it the observer rebuilds the whole model), or you have something complex like a family (and it only gets rebuilt when you setf that slot) The GTK trieview OTOH is built on top of a dynamic model. There is all the bits and pieces to do pretty much anything with that model. I've used this tutorial so far: http://scentric.net/tutorial/treeview-tutorial.html The API is here: http://library.gnome.org/devel/gtk/2.11/GtkTreeStore.html > A question is how much work gets done on the Lisp side. Do we end up > with one Lisp widget instance for each observed row? Better yet, for > each field of each row? ie, the lisp tree-view runs down the model > rooted in "roots" looking for kids of kids and then... Not at this point. The current cells-gtk has nothing more fine grained than the tree-store/tree-model whatever they call it. The rows and fields are all assembled "on the fly". But -- this is what I had in mind. > hmmm, maybe not, and it looks like I better build Cells-gtk. Keep in mind that it needs the "cells_2.0" branch. This is not in CVS but part of the release on the website. Also, at least for me (SBCL/linux) there was a bug in gtk-app.lisp, resulting in a crash when closing an application. Line 124 reads (loop while (> (gtk-main-level) 0) do (gtk-main-quit)) but should be (dotimes (i (gtk-main-level)) (gtk-main-quit)) > Normally what I do is mirror each thingy on the C side with a thingy on > Lisp side, so there would be tree-view and then tree-view-row and maybe > tree-view-row-field (or tree-view-cell in spreadsheet-ese). To make > things super-flexible, I then make those types parameterizable, so I can > make a custom tree-view-cell (by subclassing tree-view-cell) and then > specify to tree-view that it should use that subclass as it is > traversing my data model building up the Lisp tree-view. Sounds great. So I am not the only dreamer out here :) > At this point, of course, on the Lisp side anyway I can "see" cells-wise > everything that is happening, including tree insertion/deletions and > changes to slot values of model nodes. The next question is how to tell > GTk. Exactly, that is what I had in mind when I outlined that "tto" strategy. Have generic model embody the functionality of observing lisp and updating C, and then subclass it for the various cases. As a side effect this will make handling user input a lot nicer: The bits linking the clos slots to the tree-view cells might know about the inverse function and thus propagate a setf back, i.e. User changes something => tree-view widget sends setf to the corresponding connector => connector setf's the corresponding slot in the observed model => that gets propagated into the connector => the connector tells GTK about the change > Does Gtk give us the granularity to operate on the tree view, ie, does > it allow us to say "remove this row" or change this field of this row to > show this new value ("My child")? I think you said yes to this in your > prior note. Yes, it does (see pointers above). > If so, the next question is if we have done the FFI for those bits of > the API. :) Mostly, I'd say. cells-gtk/gtk-ffi has append/insert functions and most of the path/iter stuff to locate items. A function for setting values is also there. What's left is removing stuff. Shouldn't be too hard. > I'll stop here since I am just collecting info, but rest assured this is > normal stuff and if the GTk API offers the hooks we should have no > problem getting information to flow from the lisp side to Gtk, using the > ideas hinted at above. Cool. I'm looking forward to it. Cheers, Peter > kt > > > >> So I came up with the idea to make the interface to the tree-view a >> tree of cells, so that in effect for every box that is displayed in >> the treeview there is a dependent cell in the treeview (Instead of one >> cell connecting to the kids of the root). >> One way to do this would be to have an observer object >> (defmodel tto () ((obs :accessor obs :initarg :obs) >> (corresponding-point-in-gtk)) >> (def-c-output obs ((self tto)) >> (call-gtk-and-set corresponding-point-in-gtk new-value)) >> Then we would make six of these, two per node (name and age) when >> roots is assigned: >> (def-c-output roots ((self tree-view)) >> (mapcar (lambda (nd) (make-instance 'tto :obs (c? (md-name nd)) >> :corresponding... ...)) (roots self)) >> ;; of course we'll have to recurse into the kids and the names of >> the accessors >> ;; are supplied somewhere to the treeview etc. >> Additionally we'd have some sort of structure observer that listens on >> the kids of every node (here three for three nodes) and reacts to >> changes by adding/deleting rows to the tree-view. Additionally it'd >> have to create/remove tto's to listen to the slots of new nodes or >> stop listening to removed nodes. >> Another option would be what I dubbed the "family-observer": Some >> piece of magic that gets notified when any slot in a model or any of >> its decendents gets modified. The notification would idealy include >> the modified node, the modified slot, the new-value and a path from >> the root to the node (could be a closure, (lambda (n) (nth 2 (nth 3 >> (nth 0 (kids n] => (lambda root) is the modified node, or just a list >> '(0 3 2)). That family observer could then take this >> notification/message and do the appropriate action. >> I do not understand cells enough to judge whether this would even be >> possible. So maybe there is something, some instance where all state >> changes get passed through, that could filter out the ones going to >> root or its descendents, maybe not. >> Well, I hope it's clearer now what I wish to do. >> In reply to your comments: >> On Tue, 11 Dec 2007 21:03:39 +0100, Ken Tilton >> wrote: >> >>> More below, just retro-inserting notes: normally in /my/ work the >>> parent slot is not even a Cell, but I /have/ done that a couple of >>> times on certain subclasses of Family and it did work. >> Yeah, thanks for pointing that out. I got that confused from time to >> time and was wondering why a (c? parent) does not learn about (kids >> parent). >> >>> Confused: The kids slot is a Cell, so any rule anywhere (on slots not >>> just the ascendants) that references (kids ) will get >>> kicked off whent that changes. More below on this. >> I was wondering whether there would be a way to kick of that rule >> when something deeper down in the tree gets modified (see above, the >> family observer) >> >>>> If you have seen my ton of mails on the cells-gtk-devel list, you >>>> know I'm doing some GUI work with cells-gtk at the moment. I ran >>>> into the following issue: cells-gtk can use a family tree as a >>>> natural representation of the contents of a tree-view. However, >>>> when I change the items in that family tree, cells-gtk currently >>>> has no way of updating the C data structure correspondingly. >>> >>> >>> This sentence seems crucial and puzzles me some. What precisely is >>> meant by "when I change the items in that family tree"? Do you mean >>> reorgamize the tree by moving kids between parents? >> Maybe this, maybe changing a cell slot on a node in the tree, maybe >> adding kids, maybe removing them. In effect I want to keep the >> projection of the tree onto the tree-view consistent with the tree. >> >>> As for "update the C data structure correspondingly", well, /what/ C >>> data structure, this is the first I have heard of it. Do you mean the >>> C struct implementing the tree view, or a C struct one might be >>> "inspecting" by mapping its hierarchy to a tree of widgets? >> The gtk tree-view displays an internal data structure, consisting of >> rows of "cells". rows can have children. Whenever we want to put >> some lisp structure in the treeview, we have to traverse it and build >> the corresponding gtk stuff. >> >>> Let me clarify a couple of things first. btw, I do not even have >>> Cells-Gtk installed anywhere so I may have to do that if things get >>> too complicated. >> I hope it won't come that far :) I really appreciate your help, esp. >> given you won't even use cells-gtk. >> >>> First of all, my models normally do not have the parent slot as a >>> Cell at all, meaning I do not move things from one parent to another. >>> But! There have been times when I did that and it did seem to work, >>> so let's keep that in mind going forward. >> Probably we won't have to. I believe this one comes out of a >> misunderstanding -- or am I not getting it? >> >>> Second, without looking I am almost certain the kids slot of the >>> family class already does let applications react to changes to kids, >>> so I am not clear on why TTO is necessary (unless we are talking >>> about also needing the parent to be a Cell, which as I said might >>> Just Work if we put our minds to it). >> This confuses me. "the kids slot of the family class already does >> let applications react to changes to kids" -- what exactly do you mean >> by that? Adding/removing kids? Changes to the kids themselves (setf >> (md-name (first (kids root))) "Joe")? >> To me it looks like neither happens. >> (defparameter root (make-instance 'node :md-name "Root" :kids (c-in >> nil))) >> => ROOT >> (defparameter tview (make-instance 'tree-view :roots (c? (kids root)))) >> => TVIEW >> (push (make-instance 'node :md-name "child") (kids root)) >> => (child) >> ====> Nothing >> (roots tview) >> => ("roots have changed" (child)) >> => (child) >> (i.e. the def-c-observer only gets called once I query the slot) >> >>> Third, I'd like to understand the functionality better. Is the goal >>> to manipulate a tree on the C side via a [Cells-]Gtk tree view? Or >>> just dynamically restucture a treeview? This is the same question as >>> above where I ask about what is meant by "update the C data >>> structure"? >> The goal is >> I modify lisp stuff >> ==> the GTK tree model stuff ("C data structure") gets updated >> ==> The treeview reflects my changes to the lisp stuff >> It looks like I got myself into quite a mess here ... >> Cheers, >> Peter >> > From peter.hildebrandt at gmail.com Wed Dec 12 10:09:12 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Wed, 12 Dec 2007 11:09:12 +0100 Subject: [cells-gtk-devel] Re: [cells-devel] Something like a def-family-observer? In-Reply-To: <475F462A.6080306@optonline.net> References: <475EED1B.6000504@optonline.net> <475F462A.6080306@optonline.net> Message-ID: On Wed, 12 Dec 2007 03:23:38 +0100, Ken Tilton wrote: > A cursory glance at the GTk doc itself does not show things like > insert/delete row or set cell value. Can you steer me to those? the API: http://library.gnome.org/devel/gtk/2.11/GtkTreeStore.html or more readable: http://scentric.net/tutorial/treeview-tutorial.html The treestore/liststore is the "underlying C data structure" I was talking about in my first email. In GTK-speak, a treestore/liststore implements the tree-model interface, which is used by the tree-view widget. And all I want is a treebox ;) Good night (its 430AM over here), Peter > If they do not exist, it may well be that the Gtk tree view widget > itself was designed with a static model in mind, in which case, yes, you > are in for some fun milking what API it does offer. And, again /if/ this > is the case, I recommend checking with the Gtk list to see if something > has been missed and how they handle what seems like a pretty common > requirment. > > kt From peter.hildebrandt at gmail.com Wed Dec 12 15:20:48 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Wed, 12 Dec 2007 16:20:48 +0100 Subject: [cells-gtk-devel] Re: [cells-devel] Something like a def-family-observer? In-Reply-To: <475FF1EA.6070105@optonline.net> References: <475F68B9.8060500@optonline.net> <475FD39A.5030504@optonline.net> <475FF1EA.6070105@optonline.net> Message-ID: On Wed, 12 Dec 2007 15:36:26 +0100, Ken Tilton wrote: > Ken Tilton wrote: >> Ken Tilton wrote: >> >>> Peter Hildebrandt wrote: >>> >>> OK, now that I am up to speed, let's go back to your original query. >>> >>>> >>>> Say, I have a model M that depends on the structure of a family >>>> tree. One of M's slots is therefore depending on the root of the >>>> family tree: (c? root). However, I want M to know about changes in >>>> the family tree, like, say, when a child or grandchild is added. >>>> Apparently cells (at least the cells_2.0 branch required by >>>> cells-gtk) does not broadcast change messages to the parents of a >>>> node (which I guess is the right thing in 99% of the cases). >>>> >>>> What's the best way to deal with that? >>>> >>>> (i) Is there some mechanism for this purpose present in cells? Or >>>> (ii) Do I roll my own special case solution? Or >>>> (iii) Is it worthwhile to build some general purpose solution to >>>> this problem? >>>> >>>> My approach towards (ii) (I haven't coded anything yet, waiting for >>>> you comments) would be something like building an observer tree each >>>> node of which observes one node in the family tree. Something like >>>> this: >>>> - Design a tiny tree observer model ("tto"?), suited to observing >>>> one family node >>>> (defmodel tty (family) (observed observed-kids reports-to)) >>>> >>>> - Every tto knows about the parent model (M from above) and does the >>>> right thing when it sees a change (say, call a closure) >>>> - If the observed nodes has kids, it instantiates tto kids of its own >>>> to match the kids of the observed tree >>>> (def-c-output observed ((self tto)) >>>> (make-tto :observed (c? new-value) :observed-kids (c? (kids >>>> new-value))) >>>> (setf (kids self) (mapcar (lambda (kid) (make-tto :observed (c? >>>> kid) :observed-kids (c? (kids kid)))) (kids new-value) >>>> ...) >>>> (def-c-output observed-kids ((self tto)) >>>> ...) >>>> >>>> - Changing the root slot in M results in the instantiation of a tto >>>> for the root >>>> >>>> I guess that would work ... but I feel there must be a more elegant >>>> solution. >> Roughly (cuz of rough recall of Cells2): >> (defmodel family-observer (family) >> ;; we'll use the "md-value" slot for the observed >> () >> (:default-initargs >> :kids (c? (the-kids >> (bwhen (o (^md-value self)) ;; not sure why not >> (loop for k in (^kids o) collecting >> (let ((this-k k)) ;; loop is weird >> (make-instance 'family-observer >> :md-value this-k))))))) >> That handles rows in/out. > > Left unsaid was that you need an observer specialized on family-observer > to relay changes to the Gtk side. Ah, I get it. Would the following do the trick? (def-c-observer kids ((self f-o)) (mapcar #'gtk-forget-about-and delete-that-row old-value) (mapcar #'not-to-be old-value)) ;; would i need that? Help with this one is really appreciated, because I feel I have never quite understood how to handle making instances in a cells slot properly (I how to clean up properly). > >> As for individual values, well, I guess you generalize the handling of >> kids so it is just another slot-value. Changes to kids add/remove rows, >> changes to other things set values within a row. >> You know you need the kids handled, so what you might build that in >> and then have some macrology write the defmodel for custom subclasses >> of f-o: >> (def-family-observer my-tree () slot-1 slot-2) > > Left unsaid is that def-family-observer expands into: > > (defmodel my-tree (family-observer) > > (:default-initargs > :slot-1 (c? (slot-1 (md-value self))) > :slot-2 )) > > ...and observers for slot-1 and slot-2 specialized on my-tree to relay > changes to gtk. Cool. Gotta love lisp, macros, and cells. I wonder how many lines of C that would make. As to the current status, I'm messing with CFFI to get some more bookkeeping deferred to the GTK side. Once you get started there's a function of everything :) Peter > kt From peter.hildebrandt at gmail.com Thu Dec 20 19:33:34 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Thu, 20 Dec 2007 20:33:34 +0100 Subject: [cells-gtk-devel] Patch for "cells-tree-view" (the result of the family-observer discussion) Message-ID: I wrote a patch to add editable cells to the tree-view widgets. It adds editing to the existing treebox/listbox, and moreover it provides the new cells-tree-view, which keeps a tree-view in sync with a cells family tree. Thanks go to Kenny Tilton for his suggestions. Since my previous patch (adding threading to cells-gtk) is still pending (Peter?), I created threee flavors: (1) cummulative: cgtk-all-071220.patch adds both the cells-tree-view and threading to a current CVS checkout. http://www.washbear-network.de/peterblog/wp-content/uploads/2007/12/cgtk-all-071220.patch (2) differential: cgtk-tree-view-from-threading-071220.patch adds the cells-tree-view to a cells-gtk already patched with my threading functionality. http://www.washbear-network.de/peterblog/wp-content/uploads/2007/12/cgtk-tree-view-from-threading-071220.patch (3) stand alone: cgtk-tree-view-only-071220.patch adds the cells-tree-view only to a current CVS checkout, in case you don?t want threading. http://www.washbear-network.de/peterblog/wp-content/uploads/2007/12/cgtk-tree-view-only-071220.patch The patch adds a new tab Cells-Tree-View to the Tree-view page in cells-gtk, which demonstrates the functionality. The code is in test-gtk/test-tree-view.lisp Details about the implementation and application can be found here: http://www.washbear-network.de/peterblog/2007/12/20/a-cells-tree-view-for-cells-gtk/ I have done a fair amount of testing, but bug reports are very welcome. Peter From peter.hildebrandt at gmail.com Thu Dec 20 23:05:44 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Fri, 21 Dec 2007 00:05:44 +0100 Subject: [cells-gtk-devel] Re: [cells-devel] Patch for "cells-tree-view" (the result of the family-observer discussion) In-Reply-To: <476AD666.3000100@optonline.net> References: <476AD666.3000100@optonline.net> Message-ID: On Thu, 20 Dec 2007 21:53:58 +0100, Ken Tilton wrote: > Peter Hildebrandt wrote: >> I wrote a patch to add editable cells to the tree-view widgets. It >> adds editing to the existing treebox/listbox, and moreover it provides >> the new cells-tree-view, which keeps a tree-view in sync with a cells >> family tree. > > Wow, you have been busy. Congrats on pulling this off. Thanks :-) Your suggestions definitely got me on the right track there. The hairy part in the end was to get the hooks into the right places so that gtk is called at the right moment. It turned out :default-initargs is the best place to construct gtk objects, and the latter part of an :around method for not-to-be is where it should be destroyed. I did quite a bit of stress testing (the threading part helps here, I can just run a few loops from the repl, consing family trees together and ripping them apart and watch gtk trying to catch up), and could not manage to break it. This makes me wonder once more what GUI toolkits people really use. Since it's so easy, does everyone just roll their own (like you, for that matter)? Or is there some good standard library out there that I have missed in my search? Or do Franz and Allegro offer superior toolkits with their products? Or is it just that most people use lisp for stuff that does not require GUIs (i.e. (academic) command line tools/web apps)? Maybe I'll kick off another one of these threads on cll (the last one is almost two years old, I think). Anyway, Happy Holidays everyone, Peter > kt From peter.denno at nist.gov Thu Dec 20 23:16:16 2007 From: peter.denno at nist.gov (Peter Denno) Date: Thu, 20 Dec 2007 18:16:16 -0500 Subject: [cells-gtk-devel] Patch for "cells-tree-view" (the result of the family-observer discussion) In-Reply-To: References: Message-ID: <200712201816.16953.peter.denno@nist.gov> On Thursday 20 December 2007 14:33, Peter Hildebrandt wrote: > Since my previous patch (adding threading to cells-gtk) is still > pending ? (Peter?), I'm still buried in work. Seeing what great work you are doing, perhaps you would like CVS access to the repository. -- Best regards, - Peter From peter.hildebrandt at gmail.com Fri Dec 21 00:32:44 2007 From: peter.hildebrandt at gmail.com (Peter Hildebrandt) Date: Fri, 21 Dec 2007 01:32:44 +0100 Subject: [cells-gtk-devel] Patch for "cells-tree-view" (the result of the family-observer discussion) In-Reply-To: <200712201816.16953.peter.denno@nist.gov> References: <200712201816.16953.peter.denno@nist.gov> Message-ID: On Fri, 21 Dec 2007 00:16:16 +0100, Peter Denno wrote: > On Thursday 20 December 2007 14:33, Peter Hildebrandt wrote: >> Since my previous patch (adding threading to cells-gtk) is still >> pending ? (Peter?), > > I'm still buried in work. Seeing what great work you are doing, > perhaps you would like CVS access to the repository. That'd be great, I feel honored :) Best, Peter From akopa.gmane.poster at gmail.com Sun Dec 30 19:32:21 2007 From: akopa.gmane.poster at gmail.com (Matthew D. Swank) Date: Sun, 30 Dec 2007 13:32:21 -0600 Subject: [cells-gtk-devel] Re: trivial patches References: <200606200834.59797.peter.denno@nist.gov> Message-ID: On Tue, 20 Jun 2006 08:34:59 -0400, Peter Denno wrote: > On Tuesday 20 June 2006 05:43, Andras Simon wrote: >> Hi Peter, >> >> Would you commit these? Thanks, > > Hi Andras, > > Sure, I will if you'd like. But didn't you get CVS access? > >> >> Andras Could I resubmit 4 patches from July? or did I also get commit access? Matt -- "You do not really understand something unless you can explain it to your grandmother." -- Albert Einstein. From peter.denno at nist.gov Mon Dec 31 17:30:29 2007 From: peter.denno at nist.gov (Peter Denno) Date: Mon, 31 Dec 2007 12:30:29 -0500 Subject: [cells-gtk-devel] Re: trivial patches Message-ID: <200712311230.29695.peter.denno@nist.gov> On Sunday 30 December 2007 02:32:21 pm Matthew D. Swank wrote: > On Tue, 20 Jun 2006 08:34:59 -0400, Peter Denno wrote: > > On Tuesday 20 June 2006 05:43, Andras Simon wrote: > >> Hi Peter, > >> > >> Would you commit these? Thanks, > > > > Hi Andras, > > > > Sure, I will if you'd like. But didn't you get CVS access? > > > >> Andras > > Could I resubmit 4 patches from July? or did I also get commit > access? I'm pretty sure these have been committed, but for the next few days I don't have access to the computer that has my old email on it, so I can't look back at what this is about. What are these changes? > > Matt -- Best regards, Peter