X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/clg/blobdiff_plain/18b84c8043e09adb90c047fd5dfe6860e26b27e8..80c00d73e8060c5a7cb8944e20c1412646e0796e:/gtk/gtk.lisp diff --git a/gtk/gtk.lisp b/gtk/gtk.lisp index f054449..01f6ff3 100644 --- a/gtk/gtk.lisp +++ b/gtk/gtk.lisp @@ -1,5 +1,5 @@ ;; Common Lisp bindings for GTK+ v2.x -;; Copyright 1999-2005 Espen S. Johnsen +;; Copyright 1999-2006 Espen S. Johnsen ;; ;; Permission is hereby granted, free of charge, to any person obtaining ;; a copy of this software and associated documentation files (the @@ -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: gtk.lisp,v 1.61 2006-04-25 13:37:29 espen Exp $ +;; $Id: gtk.lisp,v 1.72 2007-06-04 19:03:12 espen Exp $ (in-package "GTK") @@ -45,38 +45,82 @@ (defun gtk-version () (format nil "Gtk+ v~A.~A.~A" major minor micro)))) (defun clg-version () - "clg 0.92.1") + "clg 0.93") -;;;; Initalization +;;;; Initalization and display handling (defbinding (gtk-init "gtk_parse_args") () boolean "Initializes the library without opening the display." (nil null) (nil null)) +(defparameter *event-poll-interval* 10000) + (defun clg-init (&optional display) - "Initializes the system and starts the event handling" + "Initializes the system and starts event handling" #+sbcl(when (and (find-package "SWANK") (eq (symbol-value (find-symbol "*COMMUNICATION-STYLE*" "SWANK")) :spawn)) (error "When running clg in Slime the communication style :spawn can not be used. See the README file and for more information.")) (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) (unless (gtk-init) (error "Initialization of GTK+ failed.")) - (prog1 - (gdk:display-open display) - (add-fd-handler (gdk:display-connection-number) :input #'main-iterate-all) + #?(or (pkg-config:featurep :cmu) (and (pkg-config:featurep :sbcl) (not (pkg-config:sbcl>= 1 0 6)))) + (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* 1000)))) + (setq *max-event-to-usec* *event-poll-interval*)) + #?(pkg-config:sbcl>= 1 0 6) + (warn "Periodic polling functionality has been removed from SERVE-EVENT in SBCL 1.0.6. An explicit gtk main loop has to be invoked.") + #+(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 the event handling" + "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) @@ -112,7 +156,7 @@ (defbinding get-default-language () (copy-of pango:language)) ;;; About dialog -#+gtk2.6 +#?(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))) @@ -146,7 +190,7 @@ (defun accel-group-connect (group accelerator function &optional flags) (defbinding accel-group-connect-by-path (group path function) nil (group accel-group) (path string) - ((make-callback-closure function) gclosure :return)) + ((make-callback-closure function) gclosure :in/return)) (defbinding %accel-group-disconnect (group gclosure) boolean (group accel-group) @@ -247,7 +291,7 @@ (defbinding accelerator-name () string (key unsigned-int) (modifiers gdk:modifier-type)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding accelerator-get-label () string (key unsigned-int) (modifiers gdk:modifier-type)) @@ -273,8 +317,6 @@ (defbinding accel-label-refetch () boolean ;;; Accel map -(defbinding (accel-map-init "_gtk_accel_map_init") () nil) - (defbinding %accel-map-add-entry () nil (path string) (key unsigned-int) @@ -286,7 +328,7 @@ (defun accel-map-add-entry (path accelerator) (defbinding %accel-map-lookup-entry () boolean (path string) - ((make-instance 'accel-key) accel-key :return)) + ((make-instance 'accel-key) accel-key :in/return)) (defun accel-map-lookup-entry (path) (multiple-value-bind (found-p accel-key) (%accel-map-lookup-entry path) @@ -407,11 +449,11 @@ (defun (setf bin-child) (child bin) (container-add bin child) child) -(defmethod compute-signal-function ((bin bin) signal function object) +(defmethod compute-signal-function ((bin bin) signal function object args) (declare (ignore signal)) (if (eq object :child) - #'(lambda (&rest args) - (apply function (bin-child bin) (rest args))) + #'(lambda (&rest emission-args) + (apply function (bin-child bin) (nconc (rest emission-args) args))) (call-next-method))) @@ -463,7 +505,8 @@ (defbinding box-set-child-packing () nil (defmethod initialize-instance ((button button) &rest initargs &key stock) (if stock - (apply #'call-next-method button :label stock :use-stock t initargs) + (apply #'call-next-method button + :label stock :use-stock t :use-underline t initargs) (call-next-method))) @@ -577,7 +620,7 @@ (defbinding combo-box-prepend-text () nil (combo-box combo-box) (text string)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding combo-box-get-active-text () string (combo-box combo-box)) @@ -601,7 +644,7 @@ (defmethod initialize-instance ((combo-box-entry combo-box-entry) &key model) (defmethod shared-initialize ((dialog dialog) names &rest initargs &key button buttons) - (declare (ignore button buttons)) + (declare (ignore names button buttons)) (prog1 (call-next-method) (initial-apply-add dialog #'dialog-add-button initargs :button :buttons))) @@ -611,7 +654,7 @@ (defun dialog-response-id (dialog response &optional create-p error-p) "Returns a numeric response id" (if (typep response 'response-type) (response-type-to-int response) - (let ((responses (object-data dialog 'responses))) + (let ((responses (user-data dialog 'responses))) (cond ((and responses (position response responses :test #'equal))) (create-p @@ -621,7 +664,7 @@ (defun dialog-response-id (dialog response &optional create-p error-p) (1- (length responses))) (t (setf - (object-data dialog 'responses) + (user-data dialog 'responses) (make-array 1 :adjustable t :fill-pointer t :initial-element response)) 0))) @@ -632,7 +675,7 @@ (defun dialog-find-response (dialog id) "Finds a symbolic response given a numeric id" (if (< id 0) (int-to-response-type id) - (aref (object-data dialog 'responses) id))) + (aref (user-data dialog 'responses) id))) (defmethod compute-signal-id ((dialog dialog) signal) @@ -640,8 +683,8 @@ (defmethod compute-signal-id ((dialog dialog) signal) (ensure-signal-id 'response dialog) (call-next-method))) -(defmethod compute-signal-function ((dialog dialog) signal function object) - (declare (ignore function object)) +(defmethod compute-signal-function ((dialog dialog) signal function object args) + (declare (ignore function object args)) (let ((callback (call-next-method)) (id (dialog-response-id dialog signal))) (if id @@ -712,11 +755,11 @@ (defbinding dialog-set-response-sensitive (dialog response sensitive) nil ((dialog-response-id dialog response nil t) int) (sensitive boolean)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding alternative-dialog-button-order-p (&optional screen) boolean (screen (or null gdk:screen))) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding (dialog-set-alternative-button-order "gtk_dialog_set_alternative_button_order_from_array") (dialog new-order) nil @@ -727,7 +770,7 @@ (defbinding (dialog-set-alternative-button-order new-order) (vector int))) -#+gtk2.8 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0") (progn (defbinding %dialog-get-response-for-widget () int (dialog dialog) @@ -751,6 +794,12 @@ (defmethod (setf container-children) (children (dialog dialog)) (setf (container-children (dialog-vbox dialog)) children)) +;;; Drawing Area + +(defun drawing-area-scroll (drawing-area dx dy) + (gdk:window-scroll (widget-window drawing-area) dx dy)) + + ;;; Entry (defbinding entry-get-layout-offsets () nil @@ -781,7 +830,7 @@ (defbinding entry-completion-set-match-func (completion function) nil (defbinding entry-completion-complete () nil (completion entry-completion)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding entry-completion-insert-prefix () nil (completion entry-completion)) @@ -893,8 +942,10 @@ (defmethod initialize-instance ((file-filter file-filter) &rest initargs (prog1 (call-next-method) (when pixbuf-formats - #-gtk2.6(warn "Initarg :PIXBUF-FORMATS not supportet in this version of Gtk") - #+gtk2.6(file-filter-add-pixbuf-formats file-filter)) + #?-(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") + (warn "Initarg :PIXBUF-FORMATS not supportet in this version of Gtk") + #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") + (file-filter-add-pixbuf-formats file-filter)) (initial-add file-filter #'file-filter-add-mime-type initargs :mime-type :mime-types) (initial-add file-filter #'file-filter-add-pattern @@ -909,7 +960,7 @@ (defbinding file-filter-add-pattern () nil (filter file-filter) (pattern string)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding file-filter-add-pixbuf-formats () nil (filter file-filter)) @@ -961,7 +1012,7 @@ (defun create-image-widget (source &optional mask) ((or list vector) (make-instance 'image :pixmap source)) (gdk:pixmap (make-instance 'image :pixmap source :mask mask)))) -#+gtk2.8 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0") (defbinding image-clear () nil (image image)) @@ -1036,6 +1087,8 @@ (defun %add-activate-callback (widget signal function object after) (defmethod activate-radio-widget ((button radio-button)) (signal-emit button 'clicked)) +(defgeneric add-activate-callback (action function &key object after)) + (defmethod add-activate-callback ((button radio-button) function &key object after) (%add-activate-callback button 'clicked function object after)) @@ -1107,7 +1160,7 @@ (defbinding menu-item-toggle-size-allocate () nil ;;; Menu tool button -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding menu-tool-button-set-arrow-tooltip () nil (menu-tool-button menu-tool-button) (tooltips tooltips) @@ -1122,12 +1175,13 @@ (defmethod allocate-foreign ((dialog message-dialog) &key (message-type :info) (%message-dialog-new transient-parent flags message-type buttons)) -(defmethod shared-initialize ((dialog message-dialog) names - &key text #+gtk 2.6 secondary-text) +(defmethod shared-initialize ((dialog message-dialog) names &key text + #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") + secondary-text) (declare (ignore names)) (when text (message-dialog-set-markup dialog text)) - #+gtk2.6 + #?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (when secondary-text (message-dialog-format-secondary-markup dialog secondary-text)) (call-next-method)) @@ -1144,12 +1198,12 @@ (defbinding message-dialog-set-markup () nil (message-dialog message-dialog) (markup string)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding message-dialog-format-secondary-text () nil (message-dialog message-dialog) (text string)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding message-dialog-format-secondary-markup () nil (message-dialog message-dialog) (markup string)) @@ -1233,7 +1287,7 @@ (defmethod print-object ((window window) stream) (not (zerop (length (window-title window))))) (print-unreadable-object (window stream :type t :identity nil) (format stream "~S at 0x~X" - (window-title window) (sap-int (foreign-location window)))) + (window-title window) (pointer-address (foreign-location window)))) (call-next-method))) (defbinding window-set-wmclass () nil @@ -1322,11 +1376,11 @@ (defbinding window-propagate-key-event () boolean (window window) (event gdk:key-event)) -#-gtk2.8 +#?-(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0") (defbinding window-present () nil (window window)) -#+gtk2.8 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0") (progn (defbinding %window-present () nil (window window)) @@ -1449,10 +1503,14 @@ (defun (setf window-default-icon-list) (icons) (defbinding %window-set-default-icon () nil (icons (glist gdk:pixbuf))) +(defgeneric (setf window-default-icon) (icon)) + (defmethod (setf window-default-icon) ((icon gdk:pixbuf)) (%window-set-default-icon icon) icon) +(defgeneric (setf window-group) (group window)) + (defmethod (setf window-group) ((group window-group) (window window)) (window-group-add-window group window) group) @@ -1582,21 +1640,21 @@ (defun %ensure-notebook-child (notebook position) (t (notebook-get-nth-page notebook position)))) (defbinding (notebook-insert "gtk_notebook_insert_page_menu") - (notebook position child tab-label &optional menu-label) nil + (notebook position child &optional tab-label menu-label) nil (notebook notebook) (child widget) ((if (stringp tab-label) (make-instance 'label :label tab-label) - tab-label) widget) + tab-label) (or null widget)) ((if (stringp menu-label) (make-instance 'label :label menu-label) menu-label) (or null widget)) ((%ensure-notebook-position notebook position) position)) -(defun notebook-append (notebook child tab-label &optional menu-label) +(defun notebook-append (notebook child &optional tab-label menu-label) (notebook-insert notebook :last child tab-label menu-label)) -(defun notebook-prepend (notebook child tab-label &optional menu-label) +(defun notebook-prepend (notebook child &optional tab-label menu-label) (notebook-insert notebook :first child tab-label menu-label)) (defbinding notebook-remove-page (notebook page) nil @@ -1640,7 +1698,7 @@ (defun %notebook-current-page (notebook) (notebook-get-nth-page notebook (notebook-current-page-num notebook)))) (defun (setf notebook-current-page) (page notebook) - (setf (notebook-current-page notebook) (notebook-page-num notebook page))) + (setf (notebook-current-page-num notebook) (notebook-page-num notebook page))) (defbinding (notebook-tab-label "gtk_notebook_get_tab_label") (notebook page) widget @@ -1856,7 +1914,7 @@ (defun (setf menu-active) (menu child) child) (define-callback %menu-detach-callback nil ((widget widget) (menu menu)) - (funcall (object-data menu 'detach-func) widget menu)) + (funcall (user-data menu 'detach-func) widget menu)) (defbinding %menu-attach-to-widget (menu widget) nil (menu menu) @@ -1864,13 +1922,13 @@ (defbinding %menu-attach-to-widget (menu widget) nil (%menu-detach-callback callback)) (defun menu-attach-to-widget (menu widget function) - (setf (object-data menu 'detach-func) function) + (setf (user-data menu 'detach-func) function) (%menu-attach-to-widget menu widget)) (defbinding menu-detach () nil (menu menu)) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding menu-get-for-attach-widget () (copy-of (glist widget)) (widget widget)) @@ -1938,12 +1996,16 @@ (defbinding %table-set-col-spacings () nil (table table) (spacing unsigned-int)) -(defun (setf table-col-spacing) (spacing table &optional col) - (if col - (%table-set-col-spacing table col spacing) +(defun (setf table-column-spacing) (spacing table &optional column) + (if column + (%table-set-col-spacing table column spacing) (%table-set-col-spacings table spacing)) spacing) +(defun (setf table-col-spacing) (spacing table &optional col) + (warn "TABLE-COL-SPACING is deprecatet, use TABLE-COLUMN-SPACING instead") + (setf (table-column-spacing table col) spacing)) + (defbinding %table-get-col-spacing () unsigned-int (table table) (col unsigned-int)) @@ -1951,11 +2013,15 @@ (defbinding %table-get-col-spacing () unsigned-int (defbinding %table-get-default-col-spacing () unsigned-int (table table)) -(defun table-col-spacing (table &optional col) - (if col - (%table-get-col-spacing table col) +(defun table-column-spacing (table &optional column) + (if column + (%table-get-col-spacing table column) (%table-get-default-col-spacing table))) +(defun table-col-spacing (table &optional col) + (warn "TABLE-COL-SPACING is deprecatet, use TABLE-COLUMN-SPACING instead") + (table-column-spacing table col)) + ;;; Toolbar @@ -2055,7 +2121,7 @@ (defun (setf tool-item-proxy-menu-item) (menu-item menu-item-id tool-item) (%tool-item-set-proxy-menu-item menu-item-id tool-item menu-item) menu-item) -#+gtk2.6 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.6.0") (defbinding tool-item-rebuild-menu () nil (tool-item tool-item)) @@ -2076,7 +2142,7 @@ (defbinding editable-insert-text (editable text &optional (position 0)) nil (editable editable) (text string) ((length text) int) - (position position :in-out)) + (position position :in/out)) (defun editable-append-text (editable text) (editable-insert-text editable text nil)) @@ -2251,12 +2317,6 @@ (defbinding %stock-item-copy () pointer (defbinding %stock-item-free () nil (location pointer)) -(defmethod reference-foreign ((class (eql (find-class 'stock-item))) location) - (%stock-item-copy location)) - -(defmethod unreference-foreign ((class (eql (find-class 'stock-item))) location) - (%stock-item-free location)) - (defbinding stock-add (stock-item) nil (stock-item stock-item) (1 unsigned-int)) @@ -2268,11 +2328,11 @@ (defbinding %stock-lookup () boolean (location pointer)) (defun stock-lookup (stock-id) - (with-allocated-memory (stock-item (foreign-size (find-class 'stock-item))) + (with-memory (stock-item (foreign-size (find-class 'stock-item))) (when (%stock-lookup stock-id stock-item) (ensure-proxy-instance 'stock-item (%stock-item-copy stock-item))))) -#+gtk2.8 +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.8.0") (progn (define-callback-marshal %stock-translate-callback string ((path string))) @@ -2379,3 +2439,17 @@ (defbinding %plug-new () pointer (defmethod allocate-foreign ((plug plug) &key id) (%plug-new (or id 0))) + + +;;;; New stuff in Gtk+ 2.10 + +;;; Link button + +#?(pkg-exists-p "gtk+-2.0" :atleast-version "2.10.0") +(progn + (define-callback-marshal %link-button-uri-callback nil (link-button (link string))) + + (defbinding link-button-set-uri-hook (function) pointer + (%link-button-uri-callback callback) + ((register-callback-function function) unsigned-int) + (user-data-destroy-callback callback)))