From psilord at cs.wisc.edu Wed Mar 2 03:59:12 2011 From: psilord at cs.wisc.edu (Peter Keller) Date: Tue, 1 Mar 2011 21:59:12 -0600 Subject: [cl-gtk2-devel] gtk_widget_destroy Message-ID: <20110302035912.GA11637@cs.wisc.edu> Hello, I noticed that gtk_widget_destroy() isn't in the cl-gtk2 bindings, so here is a piece of code one can stick into gtk.widget.lisp to support it: (defcfun gtk-widget-destroy :void (widget g-object)) (defun widget-destroy (widget) (gtk-widget-destroy widget)) (export 'widget-destroy) Instead of just exporting gtk-widget-destroy, I made it be symmetrical in exported symbol name to widget-show. I also have a question. Normally, when writing GTK in C, after gtk_main() finishes, one does some various cleanup and exit(). This causes all the windows to go away. However, suppose I have this type of code in Lisp which loads a hello-world style GUI that has a quit button made with glade: ;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun clicked-callback (w) (declare (ignore w)) (format t "Quitting~%") (gtk:gtk-main-quit)) (defun doit () (let ((builder (make-instance 'gtk:builder))) (gtk:builder-add-from-file builder "./hello.xml") (gtk:builder-connect-signals-simple builder `(("clicked_cb" ,#'clicked-callback))) (let ((top-level (gtk:builder-get-object builder "top_level"))) (gtk:widget-show top-level :all t) (gtk:gtk-main) (format t "After main. Shutting down.~%")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;; When I click the button. I get the output after the main function, but the actual toplevel doesn't disappear, presumably because I didn't actually exit the REPL. It just sits there with the depressed button and doesn't respond to events anymore. How can I remove all of the widgets after gtk-main is finished? There seems to be a chicken and egg problem... Thank you. -pete From andy128k at gmail.com Wed Mar 2 09:08:53 2011 From: andy128k at gmail.com (Andrey Kutejko) Date: Wed, 2 Mar 2011 11:08:53 +0200 Subject: [cl-gtk2-devel] gtk_widget_destroy In-Reply-To: <20110302035912.GA11637@cs.wisc.edu> References: <20110302035912.GA11637@cs.wisc.edu> Message-ID: Hello, 2011/3/2 Peter Keller : > Hello, > > I noticed that gtk_widget_destroy() isn't in the cl-gtk2 bindings, so here > is a piece of code one can stick into gtk.widget.lisp to support it: > > (defcfun gtk-widget-destroy :void > ?(widget g-object)) > > (defun widget-destroy (widget) > ? ?(gtk-widget-destroy widget)) > > (export 'widget-destroy) > > Instead of just exporting gtk-widget-destroy, I made it be symmetrical > in exported symbol name to widget-show. > There is no need to add gtk-widget-destroy to cl-gtk2. gtk:object-destroy already exists. > I also have a question. > > Normally, when writing GTK in C, after gtk_main() finishes, one does some > various cleanup and exit(). This causes all the windows to go away. > > However, suppose I have this type of code in Lisp which loads a > hello-world style GUI that has a quit button made with glade: > > ;;;;;;;;;;;;;;;;;;;;;;;;;;; > (defun clicked-callback (w) > ?(declare (ignore w)) > ?(format t "Quitting~%") > ?(gtk:gtk-main-quit)) > > (defun doit () > ?(let ((builder (make-instance 'gtk:builder))) > ? ?(gtk:builder-add-from-file builder "./hello.xml") > ? ?(gtk:builder-connect-signals-simple > ? ? builder `(("clicked_cb" ,#'clicked-callback))) > > ? ?(let ((top-level (gtk:builder-get-object builder "top_level"))) > > ? ? ?(gtk:widget-show top-level :all t) > > ? ? ?(gtk:gtk-main) > > ? ? ?(format t "After main. Shutting down.~%")))) > ;;;;;;;;;;;;;;;;;;;;;;;;;;; > > When I click the button. I get the output after the main function, > but the actual toplevel doesn't disappear, presumably because I didn't > actually exit the REPL. It just sits there with the depressed button and > doesn't respond to events anymore. How can I remove all of the widgets > after gtk-main is finished? There seems to be a chicken and egg problem... Try to invoke (gtk:object-destroy top-level) after main loop. > > Thank you. > > -pete > > > > _______________________________________________ > cl-gtk2-devel mailing list > cl-gtk2-devel at common-lisp.net > http://common-lisp.net/cgi-bin/mailman/listinfo/cl-gtk2-devel > From psilord at cs.wisc.edu Thu Mar 3 05:17:46 2011 From: psilord at cs.wisc.edu (Peter Keller) Date: Wed, 2 Mar 2011 23:17:46 -0600 Subject: [cl-gtk2-devel] gtk_widget_destroy In-Reply-To: References: <20110302035912.GA11637@cs.wisc.edu> Message-ID: <20110303051746.GA16260@cs.wisc.edu> On Wed, Mar 02, 2011 at 11:08:53AM +0200, Andrey Kutejko wrote: > There is no need to add gtk-widget-destroy to cl-gtk2. > gtk:object-destroy already exists. Fair enough. > > I also have a question. [snip] > > When I click the button. I get the output after the main function, > > but the actual toplevel doesn't disappear, presumably because I didn't > > actually exit the REPL. It just sits there with the depressed button and > > doesn't respond to events anymore. How can I remove all of the widgets > > after gtk-main is finished? There seems to be a chicken and egg problem... > > > Try to invoke (gtk:object-destroy top-level) after main loop. I tried this, but it doesn't change the behavior. Here is my sample code. The hello.xml is just a simple glade ui definition with a quit button to which I attach a function. (defun clicked-callback (w) (declare (ignore w)) (format t "Quitting~%") (gtk:gtk-main-quit)) (defun doit () (let ((builder (make-instance 'gtk:builder))) (gtk:builder-add-from-file builder "./hello.xml") (gtk:builder-connect-signals-simple builder `(("quit_button_clicked" ,#'clicked-callback))) (let ((top-level (gtk:builder-get-object builder "top_level"))) (gtk:widget-show top-level :all t) (gtk:gtk-main) (format t "After main. Shutting down.~%") (gtk:object-destroy top-level)))) Upon clicking the quit button, I get the output indicated "quitting" and "After main...", but the window stays shown and present with the depressed quit button and stops responding to any events. Thank you. -pete From kalyanov.dmitry at gmail.com Fri Mar 4 03:52:33 2011 From: kalyanov.dmitry at gmail.com (Kalyanov Dmitry) Date: Fri, 04 Mar 2011 06:52:33 +0300 Subject: [cl-gtk2-devel] gtk_widget_destroy In-Reply-To: <20110302035912.GA11637@cs.wisc.edu> References: <20110302035912.GA11637@cs.wisc.edu> Message-ID: <1299210753.3325.8.camel@dvk-laptop> Hello, > Normally, when writing GTK in C, after gtk_main() finishes, one does some > various cleanup and exit(). This causes all the windows to go away. Gtk+ does not do any cleanup on gtk_main_quit - it just ends its event loop. Windows are destroyed by X11 server beacuse socket is closed by the OS when process quits. To properly close all windows, you have to something like this: (gtk:within-main-loop (loop for w in (gtk:gtk-window-list-toplevels) do (gtk:object-destroy w))) You can use the gtk_quit_add_full function to register cleanup callback; but cl-gtk2 does not have bindings for it. You should also note that cl-gtk2 will use background thread for Gtk+ main event loop (if your lisp supports threads); (gtk:gtk-main) starts the background thread and returns. From psilord at cs.wisc.edu Fri Mar 4 08:38:49 2011 From: psilord at cs.wisc.edu (Peter Keller) Date: Fri, 4 Mar 2011 02:38:49 -0600 Subject: [cl-gtk2-devel] gtk_widget_destroy In-Reply-To: <1299210753.3325.8.camel@dvk-laptop> References: <20110302035912.GA11637@cs.wisc.edu> <1299210753.3325.8.camel@dvk-laptop> Message-ID: <20110304083848.GA13925@cs.wisc.edu> On Fri, Mar 04, 2011 at 06:52:33AM +0300, Kalyanov Dmitry wrote: > Gtk+ does not do any cleanup on gtk_main_quit - it just ends its event > loop. Windows are destroyed by X11 server beacuse socket is closed by > the OS when process quits. To properly close all windows, you have to > something like this: > > (gtk:within-main-loop (loop for w in (gtk:gtk-window-list-toplevels) do > (gtk:object-destroy w))) > > You can use the gtk_quit_add_full function to register cleanup callback; > but cl-gtk2 does not have bindings for it. > > You should also note that cl-gtk2 will use background thread for Gtk+ > main event loop (if your lisp supports threads); (gtk:gtk-main) starts > the background thread and returns. > What I ended up doing was this. It waits until the gtk main loop has exited by joining with it, then cleans up the top-level I created. This seems to work over and over again without corrupting SBCL or causing GTK to emit assertion failures. The lisp style of my test code is nasty and just makes me think I'm doing it wrong. (defun clicked-callback (w) (declare (ignore w)) (format t "Quitting~%") (gtk:gtk-main-quit)) (defun doit () (let (top-level) (gtk:within-main-loop (let ((builder (make-instance 'gtk:builder))) (gtk:builder-add-from-file builder "./hello.xml") (gtk:builder-connect-signals-simple builder `(("quit_button_clicked" ,#'clicked-callback))) (setf top-level (gtk:builder-get-object builder "top_level")) (format t "Created toplevel ~A~%" top-level) (gtk:widget-show top-level :all t))) (gtk:join-gtk-main) (gtk:within-main-loop (gtk:object-destroy top-level)))) I found that when I used your loop based toplevel closing code, I closed more toplevels than I created(!?!) even in a brand new SBCL image where I've run (doit) exactly once. It also put gtk into a bad state where gtk itself would emit assertion failures and eventually the SBCL image would corrupt itself and wedge. The draft manual has some pretty vague documentation in the GTK+ Main Loop section (like it states that gtk-main starts and waits in its own main loop until gtk-main-quit is called, but you say gtk-main starts the background thread and immediately returns, but in testing, the former seems to be what happens). The lisp-ish control forms around the gtk main loop idea are relatively confusing in the manual. Also, in the manual JOIN-MAIN-THREAD should be JOIN-GTK-MAIN. I would be interested in helping you expand your tutorial and manual if you have the time to answer (probably many) questions and help me understand things. Thank you. -pete