chiark / gitweb /
Small change to %DEFBINDING
[clg] / glib / gcallback.lisp
CommitLineData
c9819f3e 1;; Common Lisp bindings for GTK+ v2.0
2;; Copyright (C) 2000 Espen S. Johnsen <esj@stud.cs.uit.no>
3;;
4;; This library is free software; you can redistribute it and/or
5;; modify it under the terms of the GNU Lesser General Public
6;; License as published by the Free Software Foundation; either
7;; version 2 of the License, or (at your option) any later version.
8;;
9;; This library is distributed in the hope that it will be useful,
10;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12;; Lesser General Public License for more details.
13;;
14;; You should have received a copy of the GNU Lesser General Public
15;; License along with this library; if not, write to the Free Software
16;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
0f2fb864 18;; $Id: gcallback.lisp,v 1.16 2004/12/05 13:54:10 espen Exp $
c9819f3e 19
20(in-package "GLIB")
21
22(use-prefix "g")
23
24
831668e8 25;;;; Callback mechanism
c9819f3e 26
27(deftype gclosure () 'pointer)
28
831668e8 29(defbinding (callback-closure-new "clg_callback_closure_new") () gclosure
30 (callback-id unsigned-int)
31 (callback pointer)
32 (destroy-notify pointer))
c9819f3e 33
60cfb912 34(defun register-callback-function (function)
35 (check-type function (or null symbol function))
36 (register-user-data function))
c9819f3e 37
7bde5a67 38(defcallback closure-callback-marshal (nil
39 (gclosure pointer)
40 (return-value gvalue)
41 (n-params unsigned-int)
42 (param-values pointer)
43 (invocation-hint pointer)
44 (callback-id unsigned-int))
831668e8 45 (callback-trampoline callback-id n-params param-values return-value))
c9819f3e 46
7bde5a67 47(defcallback %destroy-user-data (nil (id unsigned-int))
48 (destroy-user-data id))
831668e8 49
50(defun make-callback-closure (function)
51 (callback-closure-new
52 (register-callback-function function)
53 (callback closure-callback-marshal) (callback %destroy-user-data)))
c9819f3e 54
c9819f3e 55
831668e8 56(defun callback-trampoline (callback-id n-params param-values return-value)
c9819f3e 57 (let* ((return-type (unless (null-pointer-p return-value)
60cfb912 58 (gvalue-type return-value)))
831668e8 59 (args (loop
60 for n from 0 below n-params
61 collect (gvalue-get (sap+ param-values (* n +gvalue-size+))))))
62 (let ((result (apply #'invoke-callback callback-id return-type args)))
63 (when return-type
64 (gvalue-set return-value result)))))
65
66
7bde5a67 67(defun invoke-callback (callback-id return-type &rest args)
831668e8 68 (restart-case
69 (apply (find-user-data callback-id) args)
70 (continue nil :report "Return from callback function"
7bde5a67 71 (when return-type
72 (format *query-io* "Enter return value of type ~S: " return-type)
831668e8 73 (force-output *query-io*)
74 (eval (read *query-io*))))
75 (re-invoke nil :report "Re-invoke callback function"
7bde5a67 76 (apply #'invoke-callback callback-id return-type args))))
c9819f3e 77
c9819f3e 78
60cfb912 79;;;; Timeouts and idle functions
80
0f2fb864 81(defconstant +priority-high+ -100)
82(defconstant +priority-default+ 0)
83(defconstant +priority-high-idle+ 100)
84(defconstant +priority-default-idle+ 200)
85(defconstant +priority-low+ 300)
86
87(defbinding source-remove () boolean
88 (tag unsigned-int))
89
7bde5a67 90(defcallback source-callback-marshal (nil (callback-id unsigned-int))
831668e8 91 (callback-trampoline callback-id 0 nil (make-pointer 0)))
60cfb912 92
93(defbinding (timeout-add "g_timeout_add_full")
0f2fb864 94 (interval function &optional (priority +priority-default+)) unsigned-int
60cfb912 95 (priority int)
96 (interval unsigned-int)
0f2fb864 97 ((callback source-callback-marshal) pointer)
60cfb912 98 ((register-callback-function function) unsigned-long)
831668e8 99 ((callback %destroy-user-data) pointer))
60cfb912 100
0f2fb864 101(defun timeout-remove (timeout)
102 (source-remove timeout))
103
60cfb912 104(defbinding (idle-add "g_idle_add_full")
0f2fb864 105 (function &optional (priority +priority-default-idle+)) unsigned-int
60cfb912 106 (priority int)
0f2fb864 107 ((callback source-callback-marshal) pointer)
60cfb912 108 ((register-callback-function function) unsigned-long)
831668e8 109 ((callback %destroy-user-data) pointer))
60cfb912 110
0f2fb864 111(defun idle-remove (idle)
112 (source-remove idle))
60cfb912 113
c9819f3e 114
115;;;; Signals
116
3f4249c7 117(defbinding signal-lookup (name itype) unsigned-int
c9819f3e 118 ((signal-name-to-string name) string)
119 (itype type-number))
120
3f4249c7 121(defbinding signal-name () string
c9819f3e 122 (signal-id unsigned-int))
123
7eec806d 124(defun ensure-signal-id (signal-id instance)
c9819f3e 125 (etypecase signal-id
126 (integer signal-id)
127 (string (signal-lookup signal-id (type-number-of instance)))
128 (symbol (signal-lookup signal-id (type-number-of instance)))))
129
3f4249c7 130(defbinding signal-stop-emission (instance signal-id) nil
c9819f3e 131 (instance ginstance)
7eec806d 132 ((ensure-signal-id signal-id instance) unsigned-int))
c9819f3e 133
3f4249c7 134; (defbinding (signal-add-emisson-hook "g_signal_add_emission_hook_full")
c9819f3e 135; () unsigned-int
136; (signal-id unsigned-int)
137; (closure gclosure))
138
3f4249c7 139; (defbinding signal-remove-emisson-hook () nil
c9819f3e 140; (signal-id unsigned-int)
141; (hook-id unsigned-int))
142
3f4249c7 143(defbinding (signal-has-handler-pending-p "g_signal_has_handler_pending")
c9819f3e 144 (instance signal-id &key detail blocked) boolean
145 (instance ginstance)
7eec806d 146 ((ensure-signal-id signal-id instance) unsigned-int)
c9819f3e 147 ((or detail 0) quark)
148 (blocked boolean))
149
3f4249c7 150(defbinding (signal-connect-closure "g_signal_connect_closure_by_id")
c9819f3e 151 (instance signal-id closure &key detail after) unsigned-int
152 (instance ginstance)
7eec806d 153 ((ensure-signal-id signal-id instance) unsigned-int)
c9819f3e 154 ((or detail 0) quark)
155 (closure gclosure)
156 (after boolean))
157
3f4249c7 158(defbinding signal-handler-block () nil
c9819f3e 159 (instance ginstance)
160 (handler unsigned-int))
161
3f4249c7 162(defbinding signal-handler-unblock () nil
c9819f3e 163 (instance ginstance)
164 (handler unsigned-int))
165
3f4249c7 166(defbinding signal-handler-disconnect () nil
c9819f3e 167 (instance ginstance)
168 (handler unsigned-int))
169
170
6d00d707 171(defmethod signal-connect ((gobject gobject) signal function &key after object)
935a783c 172"Connects a callback function to a signal for a particular object. If :OBJECT
173 is T, the object connected to is passed as the first argument to the callback
174 function, or if :OBJECT is any other non NIL value, it is passed as the first
175 argument instead. If :AFTER is non NIL, the handler will be called after the
0f2fb864 176 default handler for the signal."
ff378415 177 (when function
178 (let ((callback-id
179 (make-callback-closure
180 (cond
181 ((or (eq object t) (eq object gobject)) function)
182 ((not object)
183 #'(lambda (&rest args) (apply function (cdr args))))
184 (t
185 #'(lambda (&rest args) (apply function object (rest args))))))))
186 (signal-connect-closure gobject signal callback-id :after after))))
dd181a20 187
188
189;;; Message logging
190
191;; TODO: define and signal conditions based on log-level
831668e8 192;(defun log-handler (domain log-level message)
6baf860c 193(def-callback log-handler (c-call:void (domain c-call:c-string)
194 (log-level c-call:int)
195 (message c-call:c-string))
dd181a20 196 (error "~A: ~A" domain message))
197
831668e8 198(setf (extern-alien "log_handler" system-area-pointer) (callback log-handler))
11e1e57c 199
200
201;;;; Convenient macros
202
203(defmacro def-callback-marshal (name (return-type &rest args))
204 (let ((names (loop
205 for arg in args
206 collect (if (atom arg) (gensym) (first arg))))
207 (types (loop
208 for arg in args
209 collect (if (atom arg) arg (second arg)))))
210 `(defcallback ,name (,return-type ,@(mapcar #'list names types)
211 (callback-id unsigned-int))
212 (invoke-callback callback-id ',return-type ,@names))))
213
214(defmacro with-callback-function ((id function) &body body)
215 `(let ((,id (register-callback-function ,function)))
216 (unwind-protect
217 (progn ,@body)
218 (destroy-user-data ,id))))
219
220