From: Dmitry Kalyanov Date: Fri, 3 Apr 2009 08:36:13 +0000 (+0400) Subject: Improved gtk threading: added with-* macros, functions to call gtk-main X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=500d18cd286348c598c6644a31f7cd7867b37f98;p=cl-gtk2.git Improved gtk threading: added with-* macros, functions to call gtk-main --- diff --git a/gtk/gtk.asd b/gtk/gtk.asd index 5615e85..8479ea0 100644 --- a/gtk/gtk.asd +++ b/gtk/gtk.asd @@ -54,4 +54,4 @@ (:file "gtk.dialog.example") (:file "gtk.demo")) - :depends-on (:glib :cffi :gdk :anaphora)) \ No newline at end of file + :depends-on (:glib :cffi :gdk :anaphora :bordeaux-threads)) \ No newline at end of file diff --git a/gtk/gtk.demo.lisp b/gtk/gtk.demo.lisp index f517183..4cf8f71 100644 --- a/gtk/gtk.demo.lisp +++ b/gtk/gtk.demo.lisp @@ -33,7 +33,7 @@ x y) (g-signal-connect window "destroy" (lambda (widget) (release widget) - (gtk-main-quit))) + (leave-gtk-main))) (g-signal-connect window "motion-notify-event" (lambda (widget event) (release widget) (setf x (event-motion-x event) @@ -58,7 +58,7 @@ (widget-queue-draw window))) (widget-show window) (push :pointer-motion-mask (gdk-window-events (widget-window window))) - (gtk-main) + (ensure-gtk-main) (release window))) (defun test-entry () @@ -79,7 +79,7 @@ (box-pack-start box w) (container-add w text-view)) (container-add window box) - (g-signal-connect window "destroy" (lambda (widget) (release widget) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (widget) (release widget) (leave-gtk-main))) (g-signal-connect window "delete-event" (lambda (widget event) (declare (ignore event)) (release widget) @@ -96,7 +96,7 @@ (g-signal-connect button-insert "clicked" (lambda (button) (release button) (editable-insert-text entry "hello" 2))) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun table-packing () (using* ((window (make-instance 'gtk-window :type :toplevel :title "Table packing" :border-width 20)) @@ -108,10 +108,10 @@ (table-attach table button-1 0 1 0 1) (table-attach table button-2 1 2 0 1) (table-attach table button-q 0 2 1 2) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (g-signal-connect button-q "clicked" (lambda (b) (release b) (object-destroy window))) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-pixbuf () (using* ((window (make-instance 'gtk-window :title "Test pixbuf" :request-width 600 :request-height 240)) @@ -120,21 +120,21 @@ (vbox-1 (make-instance 'v-box))) (container-add window vbox) (box-pack-start vbox (make-instance 'label :text "Placing bg image" :font "Times New Roman Italic 10" :color "#00f" :request-height 40)) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (box-pack-start vbox eventbox) (container-add eventbox vbox-1) (box-pack-start vbox-1 (make-instance 'label :text "This is the eventbox")) (box-pack-start vbox-1 (make-instance 'label :text "The green ball is the bg")) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-image () (using*((window (make-instance 'gtk-window :title "Test images")) (image (make-instance 'image :icon-name "applications-development" :icon-size 6))) (container-add window image) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-progress-bar () (using* ((window (make-instance 'gtk-window :title "Test progress bar")) @@ -143,7 +143,7 @@ (button-pulse (make-instance 'button :label "Pulse")) (button-set (make-instance 'button :label "Set")) (entry (make-instance 'entry))) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (container-add window v-box) (box-pack-start v-box p-bar) (box-pack-start v-box button-pulse) @@ -154,7 +154,7 @@ (setf (progress-bar-fraction p-bar) (coerce (read-from-string (entry-text entry)) 'real)))) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-status-bar () (using* ((window (make-instance 'gtk-window :title "Text status bar")) @@ -169,7 +169,7 @@ (set-status-icon-tooltip icon "An icon from lisp program") (g-signal-connect window "destroy" (lambda (w) (release w) #+ (or) (setf (status-icon-visible icon) nil) - (gtk-main-quit))) + (leave-gtk-main))) (g-signal-connect button-push "clicked" (lambda (b) (release b) (status-bar-push status-bar "lisp-prog" (entry-text entry)))) (g-signal-connect button-pop "clicked" (lambda (b) (release b) (status-bar-pop status-bar "lisp-prog"))) (g-signal-connect icon "activate" (lambda (i) (release i) @@ -185,15 +185,15 @@ (box-pack-start v-box status-bar :expand nil) (widget-show window) (setf (status-icon-screen icon) (gtk-window-screen window)) - (gtk-main))) + (ensure-gtk-main))) (defun test-scale-button () (using* ((window (make-instance 'gtk-window :type :toplevel :title "Testing scale button")) (button (make-instance 'scale-button :icons (list "media-seek-backward" "media-seek-forward" "media-playback-stop" "media-playback-start") :adjustment (make-instance 'adjustment :lower -40 :upper 50 :value 20)))) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (container-add window button) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-text-view () (using* ((window (make-instance 'gtk-window :type :toplevel :title "Testing text view" :width-request 400 :height-request 300)) @@ -204,7 +204,7 @@ (v (make-instance 'text-view :buffer buffer :wrap-mode :word)) (box (make-instance 'v-box)) (scrolled (make-instance 'scrolled-window :hscrollbar-policy :automatic :vscrollbar-policy :automatic))) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (g-signal-connect button "clicked" (lambda (b) (release b) (using* ((i1 (make-instance 'text-iter)) @@ -248,21 +248,21 @@ (box-pack-start box bold-btn :expand nil) (box-pack-start box scrolled) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun demo-code-editor () (using* ((window (make-instance 'gtk-window :type :toplevel :title "Code editor" :width-request 400 :height-request 400 :window-position :center)) (scrolled (make-instance 'scrolled-window :hscrollbar-policy :automatic :vscrollbar-policy :automatic)) (buffer (make-instance 'text-buffer)) (view (make-instance 'text-view :buffer buffer))) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (container-add window scrolled) (container-add scrolled view) (widget-show window) (g-signal-connect buffer "insert-text" (lambda (buffer location text len) (using* ((buffer buffer) (location location)) (format t "~A~%" (list buffer location text len))))) - (gtk-main))) + (ensure-gtk-main))) (defstruct tvi title value) @@ -286,7 +286,7 @@ (store-add-item model (make-tvi :title "Saturday" :value 6)) (store-add-item model (make-tvi :title "Sunday" :value 7)) (setf (tree-view-model tv) model (tree-view-tooltip-column tv) 0) - (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (gtk-main-quit))) + (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (leave-gtk-main))) (gobject:g-signal-connect button "clicked" (lambda (b) (gobject:release b) (store-add-item model (make-tvi :title (entry-text title-entry) :value (or (parse-integer (entry-text value-entry) @@ -317,7 +317,7 @@ (print (tree-view-column-tree-view column)) (print (tree-view-column-cell-renderers column))) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-combo-box () (let* ((window (make-instance 'gtk-window :type :toplevel :title "Treeview (list)")) @@ -337,7 +337,7 @@ (store-add-item model (make-tvi :title "Friday" :value 5)) (store-add-item model (make-tvi :title "Saturday" :value 6)) (store-add-item model (make-tvi :title "Sunday" :value 7)) - (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (gtk-main-quit))) + (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (leave-gtk-main))) (gobject:g-signal-connect button "clicked" (lambda (b) (gobject:release b) (store-add-item model (make-tvi :title (entry-text title-entry) :value (or (parse-integer (entry-text value-entry) @@ -359,7 +359,7 @@ (cell-layout-pack-start combo-box renderer :expand nil) (cell-layout-add-attribute combo-box renderer "text" 1)) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-ui-manager () (let* ((window (make-instance 'gtk-window :type :toplevel :title "UI Manager" :default-width 200 :default-height 100 :window-position :center)) @@ -378,7 +378,7 @@ ") - (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (gtk-main-quit))) + (gobject:g-signal-connect window "destroy" (lambda (w) (gobject:release w) (leave-gtk-main))) (iter (with fn = (lambda (action) (when print-confirmation (format t "Action ~A with name ~A activated~%" action (action-name action))))) (with action-group = (make-instance 'action-group :name "Actions")) (finally (let ((a (make-instance 'toggle-action :name "print-confirm" :label "Print" :stock-id "gtk-print-report" :active t))) @@ -395,32 +395,32 @@ (awhen (ui-manager-widget ui-manager "/toolbar1") (container-add window it)) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-color-button () (let ((window (make-instance 'gtk-window :title "Color button" :type :toplevel :window-position :center :width-request 100 :height-request 100)) (button (make-instance 'color-button :title "Color button"))) - (g-signal-connect window "destroy" (lambda (w) (release w) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (release w) (leave-gtk-main))) (g-signal-connect button "color-set" (lambda (b) (release b) (format t "Chose color ~A~%" (color-button-color button)))) (container-add window button) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-color-selection () (let ((window (make-instance 'gtk-window :title "Color selection" :type :toplevel :window-position :center)) (selection (make-instance 'color-selection :has-opacity-control t))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect selection "color-changed" (lambda (s) (declare (ignore s)) (unless (color-selection-adjusting-p selection) (format t "color: ~A~%" (color-selection-current-color selection))))) (container-add window selection) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-file-chooser () (let ((window (make-instance 'gtk-window :title "file chooser" :type :toplevel :window-position :center :default-width 100 :default-height 100)) (v-box (make-instance 'v-box)) (button (make-instance 'file-chooser-button :action :open)) (b (make-instance 'button :label "Choose for save" :stock-id "gtk-save"))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect button "file-set" (lambda (b) (declare (ignore b)) (format t "File set: ~A~%" (file-chooser-filename button)))) (g-signal-connect b "clicked" (lambda (b) (declare (ignore b)) @@ -434,24 +434,24 @@ (box-pack-start v-box button) (box-pack-start v-box b) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-font-chooser () (let ((window (make-instance 'gtk-window :title "fonts" :type :toplevel :window-position :center :default-width 100 :default-height 100)) (v-box (make-instance 'v-box)) (button (make-instance 'font-button :title "Choose font" :font-name "Sans 10"))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect button "font-set" (lambda (b) (declare (ignore b)) (format t "Chose font ~A~%" (font-button-font-name button)))) (container-add window v-box) (box-pack-start v-box button) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-notebook () (let ((window (make-instance 'gtk-window :title "Notebook" :type :toplevel :window-position :center :default-width 100 :default-height 100)) (expander (make-instance 'expander :expanded t :label "notebook")) (notebook (make-instance 'notebook :enable-popup t))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (iter (for i from 0 to 5) (for page = (make-instance 'label :label (format nil "Label for page ~A" i))) (for tab-label = (make-instance 'label :label (format nil "Tab ~A" i))) @@ -464,7 +464,7 @@ (container-add window expander) (container-add expander notebook) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun calendar-detail (calendar year month day) (declare (ignore calendar year month)) @@ -474,25 +474,25 @@ (defun test-calendar () (let ((window (make-instance 'gtk-window :title "Calendar" :type :toplevel :window-position :center :default-width 100 :default-height 100)) (calendar (make-instance 'calendar :detail-function #'calendar-detail))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect calendar "day-selected" (lambda (c) (declare (ignore c)) (format t "selected: year ~A month ~A day ~A~%" (calendar-year calendar) (calendar-month calendar) (calendar-day calendar)))) (container-add window calendar) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-box-child-property () (let ((window (make-instance 'gtk-window :title "Text box child property" :type :toplevel :window-position :center :width-request 200 :height-request 200)) (box (make-instance 'h-box)) (button (make-instance 'toggle-button :active t :label "Expand"))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect button "toggled" (lambda (b) (declare (ignore b)) (setf (box-child-expand box button) (toggle-button-active button)))) (container-add window box) (box-pack-start box button) (widget-show window) - (gtk-main))) + (ensure-gtk-main))) (defun test-builder () (let ((builder (make-instance 'builder))) @@ -521,10 +521,10 @@ :logo-icon-name "gtk-apply"))) (dialog-run d) (object-destroy d))))))) - (g-signal-connect (builder-get-object builder "window1") "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect (builder-get-object builder "window1") "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (status-bar-push (builder-get-object builder "statusbar1") "times" "0 times") (widget-show (builder-get-object builder "window1")) - (gtk-main))) + (ensure-gtk-main))) (defun read-text-file (file-name) (with-output-to-string (str) @@ -626,7 +626,7 @@ ("about" ,#'about) ("quit" ,#'quit) ("eval" ,#'cb-eval))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (g-signal-connect (text-view-buffer text-view) "changed" (lambda (b) (declare (ignore b)) (setf modified-p t) (set-properties))) (widget-show window) - (gtk-main)))) \ No newline at end of file + (ensure-gtk-main)))) \ No newline at end of file diff --git a/gtk/gtk.dialog.example.lisp b/gtk/gtk.dialog.example.lisp index 8432480..6a1288b 100644 --- a/gtk/gtk.dialog.example.lisp +++ b/gtk/gtk.dialog.example.lisp @@ -3,9 +3,8 @@ (defun test-dialog () (let ((window (make-instance 'gtk-window :type :toplevel :title "Testing dialogs")) (v-box (make-instance 'v-box))) - (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (gtk-main-quit))) + (g-signal-connect window "destroy" (lambda (w) (declare (ignore w)) (leave-gtk-main))) (container-add window v-box) - (let ((button (make-instance 'button :label "Dialog 1"))) (box-pack-start v-box button) (g-signal-connect button "clicked" (lambda (b) (declare (ignore b)) @@ -29,4 +28,4 @@ (object-destroy dialog))))) (widget-show window) - (gtk-main))) \ No newline at end of file + (ensure-gtk-main))) \ No newline at end of file diff --git a/gtk/gtk.high-level.lisp b/gtk/gtk.high-level.lisp index a4f6fa9..4fd2edc 100644 --- a/gtk/gtk.high-level.lisp +++ b/gtk/gtk.high-level.lisp @@ -119,8 +119,10 @@ (defun test-progress () (with-progress-bar ("Snowball" 4) - (iter (repeat 4) - (with-progress-bar-action + (loop + repeat 4 + do (with-progress-bar-action (with-progress-bar ("Texts" 10) - (iter (repeat 10) - (with-progress-bar-action (sleep 1)))))))) \ No newline at end of file + (loop + repeat 10 + do (with-progress-bar-action (sleep 1)))))))) \ No newline at end of file diff --git a/gtk/gtk.main_loop_events.lisp b/gtk/gtk.main_loop_events.lisp index 6c7376a..a98262c 100644 --- a/gtk/gtk.main_loop_events.lisp +++ b/gtk/gtk.main_loop_events.lisp @@ -27,6 +27,26 @@ (defcfun gtk-main :void) +#+thread-support +(defun ensure-gtk-main () + (unless (find "gtk main thread" (bt:all-threads) :test 'string= :key 'bt:thread-name) + (bt:make-thread (lambda () (gtk:gtk-main)) :name "gtk main thread"))) + +#-thread-support +(defun ensure-gtk-main () + (gtk-main)) + +(export 'ensure-gtk-main) + +#+thread-support +(defun leave-gtk-main ()) ;noop on multithreading + +#-thread-support +(defun leave-gtk-main () + (gtk-main-quit)) + +(export 'leave-gtk-main) + (defcfun gtk-main-level :uint) (defcfun gtk-main-quit :void) diff --git a/gtk/gtk.misc.lisp b/gtk/gtk.misc.lisp index 81dd06d..fbfaa77 100644 --- a/gtk/gtk.misc.lisp +++ b/gtk/gtk.misc.lisp @@ -19,11 +19,26 @@ (g-idle-add-full priority (callback call-from-main-loop-callback) (allocate-stable-pointer function) - (callback stable-pointer-free-destroy-notify-callback))) + (callback stable-pointer-free-destroy-notify-callback)) + (ensure-gtk-main)) (export 'call-from-gtk-main-loop) (defmacro within-main-loop (&body body) `(call-from-gtk-main-loop (lambda () ,@body))) -(export 'within-main-loop) \ No newline at end of file +(export 'within-main-loop) + +#+thread-support +(defmacro with-main-loop (&body body) + `(progn + (ensure-gtk-main) + (within-main-loop ,@body))) + +#-thread-support +(defmacro with-main-loop (&body body) + `(progn + ,@body + (gtk-main))) + +(export 'with-main-loop) \ No newline at end of file