+ (unless (gtk-init)
+ (error "Initialization of GTK+ failed."))
+ #+(or cmu sbcl)
+ (progn
+ (signal-connect (gdk:display-manager) 'display-opened
+ #'(lambda (display)
+ (let ((fd (gdk:display-connection-number display)))
+ (unless (< fd 0)
+ (let ((handler (add-fd-handler
+ (gdk:display-connection-number display)
+ :input #'main-iterate-all)))
+ (signal-connect display 'closed
+ #'(lambda (is-error-p)
+ (declare (ignore is-error-p))
+ (remove-fd-handler handler))))))))
+ (setq *periodic-polling-function* #'main-iterate-all)
+ (setq *max-event-to-sec* 0)
+ (setq *max-event-to-usec* *event-poll-interval*))
+ #+(and clisp readline)
+ ;; Readline will call the event hook at most ten times per second
+ (setf readline:event-hook #'main-iterate-all)
+ #+clisp
+ ;; When running in Slime we need to hook into the Swank server
+ ;; to handle events asynchronously
+ (if (find-package "SWANK")
+ (let ((read-from-emacs (symbol-function (find-symbol "READ-FROM-EMACS" "SWANK")))
+ (stream (funcall (find-symbol "CONNECTION.SOCKET-IO" "SWANK") (symbol-value (find-symbol "*EMACS-CONNECTION*" "SWANK")))))
+ (setf (symbol-function (find-symbol "READ-FROM-EMACS" "SWANK"))
+ #'(lambda ()
+ (loop
+ (case (socket:socket-status (cons stream :input) 0 *event-poll-interval*)
+ (:input (return (funcall read-from-emacs)))
+ (:eof (read-char stream))
+ (otherwise (main-iterate-all)))))))
+ #-readline(warn "Not running in Slime and Readline support is missing, so the Gtk main loop has to be invoked explicit."))
+
+ (gdk:display-open display)))
+
+
+#+sbcl
+(defun clg-init-with-threading (&optional display)
+ "Initializes the system and starts event handling"
+ (unless (gdk:display-get-default)
+ #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0")
+ (progn
+ #+sbcl(sb-int:set-floating-point-modes :traps nil)
+ #+cmu(ext:set-floating-point-modes :traps nil))
+
+ (gdk:gdk-init)
+ (gdk:threads-set-lock-functions)
+ (unless (gtk-init)
+ (error "Initialization of GTK+ failed."))
+ (sb-thread:make-thread
+ #'(lambda ()
+ (gdk:display-open display)
+ (gdk:with-global-lock (main)))
+ :name "gtk event loop")))
+
+
+;;; Generic functions
+
+(defgeneric add-to-radio-group (item1 item2))
+(defgeneric activate-radio-widget (item))
+(defgeneric (setf tool-item-tip-text) (tip-text tool-item))
+(defgeneric (setf tool-item-tip-private) (tip-private tool-item))
+
+
+
+;;; Misc
+
+(defbinding grab-add () nil
+ (widget widget))
+
+(defbinding grab-get-current () widget)
+
+(defbinding grab-remove () nil
+ (widget widget))
+
+(defbinding get-default-language () (copy-of pango:language))
+
+
+;;; About dialog
+
+#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0")
+(progn
+ (define-callback-marshal %about-dialog-activate-link-callback nil
+ (about-dialog (link string)))
+
+ (defbinding about-dialog-set-email-hook (function) nil
+ (%about-dialog-activate-link-callback callback)
+ ((register-callback-function function) unsigned-int)
+ (user-data-destroy-callback callback))
+
+ (defbinding about-dialog-set-url-hook (function) nil
+ (%about-dialog-activate-link-callback callback)
+ ((register-callback-function function) unsigned-int)
+ (user-data-destroy-callback callback)))