+;;;; Super class for all classes in the GObject type hierarchy
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (defclass gobject (ginstance)
+ ()
+ (:metaclass gobject-class)
+ (:alien-name "GObject")))
+
+(defmethod print-object ((instance gobject) stream)
+ (print-unreadable-object (instance stream :type t :identity nil)
+ (if (slot-boundp instance 'location)
+ (format stream "at 0x~X" (sap-int (proxy-location instance)))
+ (write-string "(destroyed)" stream))))
+
+
+(defmethod initialize-instance ((object gobject) &rest initargs)
+ ;; Extract initargs which we should pass directly to the GObeject
+ ;; constructor
+ (let* ((slotds (class-slots (class-of object)))
+ (args (loop
+ as tmp = initargs then (cddr tmp) while tmp
+ as key = (first tmp)
+ as value = (second tmp)
+ as slotd = (find-if
+ #'(lambda (slotd)
+ (member key (slot-definition-initargs slotd)))
+ slotds)
+ when (and (typep slotd 'effective-property-slot-definition)
+ (slot-value slotd 'construct))
+ collect (progn
+ (remf initargs key)
+ (list
+ (slot-definition-pname slotd)
+ (slot-definition-type slotd)
+ value)))))
+ (if args
+ (let* ((string-size (size-of 'string))
+ (string-writer (writer-function 'string))
+ (string-destroy (destroy-function 'string))
+ (params (allocate-memory
+ (* (length args) (+ string-size +gvalue-size+)))))
+ (loop
+ for (pname type value) in args
+ as tmp = params then (sap+ tmp (+ string-size +gvalue-size+))
+ do (funcall string-writer pname tmp)
+ (gvalue-init (sap+ tmp string-size) type value))
+ (unwind-protect
+ (setf
+ (slot-value object 'location)
+ (%gobject-newv (type-number-of object) (length args) params))
+ (loop
+ repeat (length args)
+ as tmp = params then (sap+ tmp (+ string-size +gvalue-size+))
+ do (funcall string-destroy tmp)
+ (gvalue-unset (sap+ tmp string-size)))
+ (deallocate-memory params)))
+ (setf
+ (slot-value object 'location)
+ (%gobject-new (type-number-of object)))))
+
+ (%object-weak-ref object)
+ (apply #'call-next-method object initargs))
+
+
+(defmethod initialize-instance :around ((object gobject) &rest initargs)
+ (declare (ignore initargs))
+ (call-next-method)
+ (%object-weak-ref object))
+
+
+(defcallback weak-notify (nil (data int) (location pointer))
+ (let ((object (find-cached-instance location)))
+ (when object
+;; (warn "~A being finalized by the GObject system while still in existence in lisp" object)
+ (slot-makunbound object 'location)
+ (remove-cached-instance location))))
+
+(defbinding %object-weak-ref (object) nil
+ (object gobject)
+ ((callback weak-notify) pointer)
+ (0 unsigned-int))
+
+(defbinding (%gobject-new "g_object_new") () pointer
+ (type type-number)
+ (nil null))
+
+(defbinding (%gobject-newv "g_object_newv") () pointer
+ (type type-number)
+ (n-parameters unsigned-int)
+ (params pointer))
+
+
+
+;;;; Property stuff