X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/clg/blobdiff_plain/3005806e61162b6f55a29bd7b40fcf2bcc8c35fc..5de2b5f6a587aff7590db74f3aa7eb622cd8904c:/glib/gcallback.lisp diff --git a/glib/gcallback.lisp b/glib/gcallback.lisp index 2d0d5a6..6d211f4 100644 --- a/glib/gcallback.lisp +++ b/glib/gcallback.lisp @@ -20,7 +20,7 @@ ;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -;; $Id: gcallback.lisp,v 1.28 2006-02-06 18:12:19 espen Exp $ +;; $Id: gcallback.lisp,v 1.32 2006-02-26 15:16:15 espen Exp $ (in-package "GLIB") @@ -29,27 +29,26 @@ (use-prefix "g") ;;;; Callback invokation +(deftype gclosure () 'pointer) +(register-type 'gclosure '|g_closure_get_type|) + (defun register-callback-function (function) (check-type function (or null symbol function)) (register-user-data function)) ;; Callback marshal for regular signal handlers -(defcallback closure-marshal (nil - (gclosure pointer) - (return-value gvalue) - (n-params unsigned-int) - (param-values pointer) - (invocation-hint pointer) - (callback-id unsigned-int)) +(define-callback closure-marshal nil + ((gclosure gclosure) (return-value gvalue) (n-params unsigned-int) + (param-values pointer) (invocation-hint pointer) + (callback-id unsigned-int)) (declare (ignore gclosure invocation-hint)) (callback-trampoline callback-id n-params param-values return-value)) ;; Callback function for emission hooks -(defcallback signal-emission-hook (nil - (invocation-hint pointer) - (n-params unsigned-int) - (param-values pointer) - (callback-id unsigned-int)) +(define-callback signal-emission-hook nil + ((invocation-hint pointer) (n-params unsigned-int) (param-values pointer) + (callback-id unsigned-int)) + (declare (ignore invocation-hint)) (callback-trampoline callback-id n-params param-values)) (defun callback-trampoline (callback-id n-params param-values &optional @@ -93,16 +92,16 @@ (defconstant +priority-low+ 300) (defbinding source-remove () boolean (tag unsigned-int)) -(defcallback source-callback-marshal (nil (callback-id unsigned-int)) +(define-callback source-callback-marshal nil ((callback-id unsigned-int)) (callback-trampoline callback-id 0 nil)) (defbinding (timeout-add "g_timeout_add_full") (interval function &optional (priority +priority-default+)) unsigned-int (priority int) (interval unsigned-int) - ((callback source-callback-marshal) pointer) + (source-callback-marshal callback) ((register-callback-function function) unsigned-long) - ((callback user-data-destroy-func) pointer)) + (user-data-destroy-callback callback)) (defun timeout-remove (timeout) (source-remove timeout)) @@ -110,9 +109,9 @@ (defun timeout-remove (timeout) (defbinding (idle-add "g_idle_add_full") (function &optional (priority +priority-default-idle+)) unsigned-int (priority int) - ((callback source-callback-marshal) pointer) + (source-callback-marshal callback) ((register-callback-function function) unsigned-long) - ((callback user-data-destroy-func) pointer)) + (user-data-destroy-callback callback)) (defun idle-remove (idle) (source-remove idle)) @@ -219,15 +218,13 @@ (defbinding %signal-chain-from-overridden () nil (args pointer) (return-value (or null gvalue))) -;; TODO: implement same semantics as CALL-NEXT-METHOD -(defun %call-next-handler (n-params types args defaults return-type) + +(defun %call-next-handler (n-params types args return-type) (let ((params (allocate-memory (* n-params +gvalue-size+)))) (loop - as tmp = args then (rest tmp) - for default in defaults + for arg in args for type in types for offset from 0 by +gvalue-size+ - as arg = (if tmp (car tmp) default) do (gvalue-init (sap+ params offset) type arg)) (unwind-protect @@ -253,15 +250,16 @@ (defmacro define-signal-handler (name ((object class) &rest args) &body body) until (eq arg '&rest) collect arg)) (rest (cadr (member '&rest args))) - (next (make-symbol "ARGS"))) + (next (make-symbol "ARGS")) + (default (make-symbol "DEFAULT"))) `(progn (signal-override-class-closure ',name ',class #'(lambda (,object ,@args) - (flet ((call-next-handler (&rest ,next) - (let ((defaults (list* ,object ,@vars ,rest))) + (let ((,default (list* ,object ,@vars ,rest))) + (flet ((call-next-handler (&rest ,next) (%call-next-handler - ,n-params ',types ,next defaults ',return-type)))) + ,n-params ',types (or ,next ,default) ',return-type)))) ,@body))) ',name))) @@ -284,9 +282,9 @@ (defbinding signal-add-emission-hook (type signal function &key (detail 0)) unsigned-int ((ensure-signal-id-from-type signal type) unsigned-int) (detail quark) - ((callback signal-emission-hook) pointer) + (signal-emission-hook callback) ((register-callback-function function) unsigned-int) - ((callback user-data-destroy-func) pointer)) + (user-data-destroy-callback callback)) (defbinding signal-remove-emission-hook (type signal hook-id) nil ((ensure-signal-id-from-type signal type) unsigned-int) @@ -323,20 +321,15 @@ (defbinding signal-handler-is-connected-p () boolean (instance ginstance) (handler-id unsigned-int)) -(deftype gclosure () 'pointer) -(register-type 'gclosure "GClosure") - (defbinding (callback-closure-new "clg_callback_closure_new") () gclosure (callback-id unsigned-int) - (callback pointer) - (destroy-notify pointer)) + (callback callback) + (destroy-notify callback)) (defun make-callback-closure (function) (let ((callback-id (register-callback-function function))) (values - (callback-closure-new - callback-id (callback closure-marshal) - (callback user-data-destroy-func)) + (callback-closure-new callback-id closure-marshal user-data-destroy-callback) callback-id))) (defgeneric compute-signal-function (gobject signal function object)) @@ -450,19 +443,41 @@ (defun signal-emit (object signal &rest args) ;;;; Convenient macros -(defmacro def-callback-marshal (name (return-type &rest args)) - (let ((names (loop - for arg in args - collect (if (atom arg) (gensym) (first arg)))) - (types (loop - for arg in args - collect (if (atom arg) arg (second arg))))) - `(defcallback ,name (,return-type ,@(mapcar #'list names types) - (callback-id unsigned-int)) - (invoke-callback callback-id ',return-type ,@names)))) +(defmacro define-callback-marshal (name return-type args &key (callback-id :last)) + (let* ((ignore ()) + (params ()) + (names (loop + for arg in args + collect (if (or + (eq arg :ignore) + (and (consp arg) (eq (first arg) :ignore))) + (let ((name (gensym "IGNORE"))) + (push name ignore) + name) + (let ((name (if (atom arg) + (gensym (string arg)) + (first arg)))) + (push name params) + name)))) + (types (loop + for arg in args + collect (cond + ((eq arg :ignore) 'pointer) + ((atom arg) arg) + (t (second arg)))))) + `(define-callback ,name ,return-type + ,(ecase callback-id + (:first `((callback-id unsigned-int) ,@(mapcar #'list names types))) + (:last `(,@(mapcar #'list names types) (callback-id unsigned-int)))) + (declare (ignore ,@ignore)) + (invoke-callback callback-id ',return-type ,@params)))) (defmacro with-callback-function ((id function) &body body) `(let ((,id (register-callback-function ,function))) (unwind-protect (progn ,@body) (destroy-user-data ,id)))) + +;; For backward compatibility +(defmacro def-callback-marshal (name (return-type &rest args)) + `(define-callback-marshal ,name ,return-type ,args))