chiark / gitweb /
7d72ff611846ec49ca9286d965c9539e1daf097c
[clg] / glib / gcallback.lisp
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
18 ;; $Id: gcallback.lisp,v 1.3 2001-05-11 16:08:52 espen Exp $
19
20 (in-package "GLIB")
21
22 (use-prefix "g")
23
24
25 ;;;; Closures
26
27 (deftype gclosure () 'pointer)
28
29 (defbinding lisp-callback-closure-new () gclosure
30   (callback-id unsigned-int))
31
32
33
34 ;;;; Callback mechanism
35
36 (defun register-callback-function (function)
37   (check-type function (or null symbol function))
38   (lisp-callback-closure-new (register-user-data function)))
39
40 (defun callback-trampoline (callback-id params return-value)
41   (let* ((return-type (unless (null-pointer-p return-value)
42                         (type-from-number (gvalue-type return-value))))
43          (args nil)
44          (callback-function (find-user-data callback-id)))
45
46     (destructuring-bind (nparams . param-values) params
47       (dotimes (n nparams)
48         (push (gvalue-get (sap+ param-values (* n +gvalue-size+))) args)))
49
50     (labels ((invoke-callback ()
51                (restart-case
52                    (unwind-protect
53                        (let ((result (apply callback-function args)))
54                          (when return-type
55                            (gvalue-set return-value result))))
56                 
57                  (continue nil :report "Return from callback function"
58                   (when return-type
59                     (format
60                      *query-io*
61                      "Enter return value of type ~S: "
62                      return-type)
63                     (force-output *query-io*)
64                     (gvalue-set return-value (eval (read *query-io*)))))
65                  (re-invoke nil :report "Re-invoke callback function"
66                   (invoke-callback)))))
67       (invoke-callback))))
68
69 (defun after-gc-hook ()
70   (setf
71    (extern-alien "callback_trampoline" system-area-pointer)
72    (make-pointer (kernel:get-lisp-obj-address #'callback-trampoline))
73    (extern-alien "destroy_user_data" system-area-pointer)
74    (make-pointer (kernel:get-lisp-obj-address #'destroy-user-data))))
75
76 (pushnew 'after-gc-hook ext:*after-gc-hooks*)
77 (after-gc-hook)
78
79
80
81 ;;;; Signals
82
83 (defun signal-name-to-string (name)
84   (substitute #\_ #\- (string-downcase (string name))))
85
86 (defbinding signal-lookup (name itype) unsigned-int
87   ((signal-name-to-string name) string)
88   (itype type-number))
89
90 (defbinding signal-name () string
91   (signal-id unsigned-int))
92
93 (defun ensure-signal-id (signal-id instance)
94   (etypecase signal-id
95     (integer signal-id)
96     (string (signal-lookup signal-id (type-number-of instance)))
97     (symbol (signal-lookup signal-id (type-number-of instance)))))
98   
99 (defbinding signal-stop-emission (instance signal-id) nil
100   (instance ginstance)
101   ((ensure-signal-id signal-id instance) unsigned-int))
102
103 ; (defbinding (signal-add-emisson-hook "g_signal_add_emission_hook_full")
104 ;     () unsigned-int
105 ;   (signal-id unsigned-int)
106 ;   (closure gclosure))
107
108 ; (defbinding signal-remove-emisson-hook () nil
109 ;   (signal-id unsigned-int)
110 ;   (hook-id unsigned-int))
111
112 (defbinding (signal-has-handler-pending-p "g_signal_has_handler_pending")
113     (instance signal-id &key detail blocked) boolean
114   (instance ginstance)
115   ((ensure-signal-id signal-id instance) unsigned-int)
116   ((or detail 0) quark)
117   (blocked boolean))
118     
119 (defbinding (signal-connect-closure "g_signal_connect_closure_by_id")
120     (instance signal-id closure &key detail after) unsigned-int
121   (instance ginstance)
122   ((ensure-signal-id signal-id instance) unsigned-int)
123   ((or detail 0) quark)
124   (closure gclosure)
125   (after boolean))
126
127 (defbinding signal-handler-block () nil
128   (instance ginstance)
129   (handler unsigned-int))
130
131 (defbinding signal-handler-unblock () nil
132   (instance ginstance)
133   (handler unsigned-int))
134
135 (defbinding signal-handler-disconnect () nil
136   (instance ginstance)
137   (handler unsigned-int))
138
139
140 (defun signal-connect (instance signal function &key after object)
141   (let ((callback
142          (cond
143           ((or (eq object t) (eq object instance)) function)
144           ((not object)
145            #'(lambda (&rest args) (apply function (cdr args))))
146           (t
147            #'(lambda (&rest args) (apply function object (rest args)))))))
148     
149     (signal-connect-closure
150      instance signal (register-callback-function callback) :after after)))