Update of /project/cells/cvsroot/cells-gtk3/cells-gtk
In directory clnet:/tmp/cvs-serv13587/cells-gtk
Modified Files:
buttons.lisp cairo-drawing-area.lisp cells-gtk.asd
drawing-area.lisp gl-drawing-area.lisp gtk-app.lisp
packages.lisp widgets.lisp
Log Message:
Added OpenGL drawing area
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/buttons.lisp 2008/04/13 10:59:16 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/buttons.lisp 2008/04/14 16:43:41 1.2
@@ -81,7 +81,7 @@
(def-widget radio-button (check-button)
() () ()
- :new-tail (c? (and (upper self box)
+ :new-tail (c_1 (and (upper self box)
(not (eql (first (kids (fm-parent self))) self))
'-from-widget))
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/cairo-drawing-area.lisp 2008/04/13 10:59:16 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/cairo-drawing-area.lisp 2008/04/14 16:43:41 1.2
@@ -216,19 +216,6 @@
(deb "done."))
-;;;; -----------------------------------------------------------
-;;;; redraw method (called to trigger a refresh)
-;;;; -----------------------------------------------------------
-
-;;; a handler if redraw called on nil
-(defmethod redraw (self))
-
-(defmethod redraw ((self cairo-drawing-area))
- "Queues a redraw with GTK. This is called whenever a primitve is modified"
- (trc nil "queue redraw" self)
- (gtk-ffi:gtk-widget-queue-draw (widget-id self)))
-
-
(defobserver prims ((self cairo-drawing-area))
(redraw self))
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/cells-gtk.asd 2008/04/13 10:59:16 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/cells-gtk.asd 2008/04/14 16:43:42 1.2
@@ -17,7 +17,7 @@
(pushnew :cells-gtk-cairo *features*)
;;; drawing-area widget using OpenGL (requires libgtkglext1)
-;(pushnew :cells-gtk-opengl *features*)
+(pushnew :cells-gtk-opengl *features*)
(asdf:defsystem :cells-gtk
:name "cells-gtk"
@@ -27,7 +27,10 @@
:gtk-ffi
:ph-maths
#+cells-gtk-cairo :cl-cairo2
- #+cells-gtk-threads :bordeaux-threads)
+ #+cells-gtk-threads :bordeaux-threads
+ #+cells-gtk-opengl :cl-opengl
+ #+cells-gtk-opengl :cl-glu
+ #+cells-gtk-opengl :cl-glut)
:serial t
:components
((:file "packages")
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/drawing-area.lisp 2008/04/13 10:59:17 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/drawing-area.lisp 2008/04/14 16:43:42 1.2
@@ -123,10 +123,26 @@
(declare (ignore rest))
(let ((widget (id self)))
(trc "registering handlers for" widget)
- (gtk-widget-add-events widget 772) ; 512 + 256 + 4 button_press, release, motion
- (gtk-signal-connect-swap widget "button-press-event" (cffi:get-callback 'drawing-button-handler) :data widget)
- (gtk-signal-connect-swap widget "button-release-event" (cffi:get-callback 'drawing-button-handler) :data widget)
- (gtk-signal-connect-swap widget "motion-notify-event" (cffi:get-callback 'drawing-pointer-motion-handler) :data widget)
- (gtk-signal-connect-swap widget "expose-event" (cffi:get-callback 'drawing-expose-handler) :data widget)))
+ (gtk-widget-add-events widget 772) ; 512 + 256 + 4 button_press, release, motion
+ (gtk-signal-connect-swap widget "button-press-event" (cffi:get-callback 'drawing-button-handler) :data widget)
+ (gtk-signal-connect-swap widget "button-release-event" (cffi:get-callback 'drawing-button-handler) :data widget)
+ (gtk-signal-connect-swap widget "motion-notify-event" (cffi:get-callback 'drawing-pointer-motion-handler) :data widget)
+ (gtk-signal-connect-swap widget "expose-event" (cffi:get-callback 'drawing-expose-handler) :data widget)))
+
+
+;;;
+;;; redraw method (called to trigger a refresh)
+;;;
+
+;;; a handler if redraw called on nil
+(export! redraw)
+
+(defmethod redraw (self))
+
+(defmethod redraw ((self drawing-area))
+ "Queues a redraw with GTK."
+ (trc nil "queue redraw" self)
+ (gtk-widget-queue-draw (id self)))
+
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/gl-drawing-area.lisp 2008/04/13 10:59:17 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/gl-drawing-area.lisp 2008/04/14 16:43:42 1.2
@@ -2,9 +2,112 @@
(in-package :cgtk)
+(defvar *gl-config* nil)
+
;;;
;;; gl drawing area
;;;
+;;;
+;;; OpenGL interaction
+;;;
+
+(defun get-gl-config ()
+ (let ((cfg (gdk-gl-config-new-by-mode '(:gdk-gl-mode-rgba :gdk-gl-mode-depth :gdk-gl-mode-double))))
+ (if (cffi-sys:null-pointer-p cfg)
+ (let ((cfg (gdk-gl-config-new-by-mode '(:gdk-gl-mode-rgba :gdk-gl-mode-depth :gdk-gl-mode-double))))
+ (warn "No double buffered visual found. Trying single-buffered.")
+ (if (cffi-sys:null-pointer-p cfg)
+ (error "No OpenGL capable visual found.")
+ cfg))
+ cfg)))
+
+(defun gl-init ()
+ (gtk-gl-init +c-null+ +c-null+)
+ (setf *gl-config* (get-gl-config)))
+
+
+(defmacro with-gl-context ((widget &key (swap-buffers-p t)) &rest body)
+ (with-gensyms (drawable context swap-p w wid)
+ `(let ((,swap-p ,swap-buffers-p)
+ (,w ,widget))
+ (let ((,wid (id ,w)))
+ (let ((,context (gtk-widget-get-gl-context ,wid))
+ (,drawable (gtk-widget-get-gl-window ,wid)))
+ (if (gdk-gl-drawable-gl-begin ,drawable ,context)
+ (progn
+ ,@body
+ (when ,swap-p
+ (when (gdk-gl-drawable-is-double-buffered ,drawable)
+ (trc "swapping buffers")
+ (gdk-gl-drawable-swap-buffers ,drawable)))
+ (gdk-gl-drawable-gl-end ,drawable))
+ (trc "gl-begin failed" ,w ,drawable ,context)))))))
+
+;;;
+;;; Event handling
+;;;
+
+(defun %gl-draw (self)
+ (bwhen (draw-fn (draw self))
+ (with-gl-context (self)
+ (funcall draw-fn self))))
+
+(cffi:defcallback realize-handler :void ((widget :pointer) (data :pointer))
+ (declare (ignore data))
+ (let ((self (gtk-object-find widget)))
+ (trc "gl realize" self widget (id self))
+ (bwhen (init-fn (init self))
+ (with-gl-context (self)
+ (funcall init-fn self)))
+ (trc "done gl realize" self)))
+
+
+(defun %resize (self)
+ (let ((width (allocated-width self))
+ (height (allocated-height self)))
+ (when (and (plusp width) (plusp height))
+ (trc "%resize to" width height)
+ (with-gl-context (self)
+ (gl:viewport 0 0 width height)
+ (bwhen (resize-fn (resize self))
+ (funcall resize-fn self))))))
+
+;;;
+;;; Widget
+;;;
+
(defmodel gl-drawing-area (drawing-area)
- ())
\ No newline at end of file
+ ((draw :accessor draw :initarg :draw :cell nil :initform nil)
+ (init :accessor init :initarg :init :cell nil :initform nil)
+ (resize :accessor resize :initarg :resize :cell nil :initform nil))
+ (:default-initargs
+ :on-draw #'%gl-draw))
+
+(defmethod initialize-instance :after ((self gl-drawing-area) &rest initargs)
+ (declare (ignore initargs))
+ (trc "registering handlers for" self)
+ (gtk-signal-connect-swap (id self) "realize" (cffi:get-callback 'realize-handler) :data (id self))
+ (trc "set gl capability" self)
+ (gtk-widget-set-gl-capability (id self) *gl-config* +c-null+ t :gdk-gl-rgba-type))
+
+(defobserver allocated-width ((self gl-drawing-area))
+ (%resize self))
+
+(defobserver allocated-height ((self gl-drawing-area))
+ (%resize self))
+
+
+;;;
+;;; supporting macros
+;;;
+
+(export! with-matrix-mode)
+
+(defmacro with-matrix-mode ((mode) &body body)
+ `(progn
+ (gl:matrix-mode ,mode)
+ (gl:load-identity)
+ ,@body
+ (gl:matrix-mode :modelview)
+ (gl:load-identity)))
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/gtk-app.lisp 2008/04/13 11:34:24 1.2
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/gtk-app.lisp 2008/04/14 16:43:42 1.3
@@ -127,28 +127,6 @@
(with-trc (gtk-quit-remove (slot-value self 'cb-quit-id))))
;;;
-;;; callback table
-;;;
-
-(defvar *gtk-global-callbacks* nil)
-
-(defun gtk-reset ()
- (cells-reset)
- (gtk-objects-init)
- (setf *gtk-global-callbacks*
- (make-array 128 :adjustable t :fill-pointer 0)))
-
-(defun gtk-global-callback-register (callback)
- (vector-push-extend callback *gtk-global-callbacks* 16))
-
-(defun gtk-global-callback-funcall (n)
- (trc nil "gtk-global-callback-funcall >" n
- *gtk-global-callbacks*
- (when n (aref *gtk-global-callbacks* n)))
- (funcall (aref *gtk-global-callbacks* n)))
-
-
-;;;
;;; Helper functions convering the life cycle of an application
;;;
@@ -184,6 +162,7 @@
(gdk-threads-init)
(assert (gtk-init-check +c-null+ +c-null+))
(gtk-init +c-null+ +c-null+)
+ #+cells-gtk-opengl (gl-init)
(gtk-reset)
#-libcellsgtk (setf threading-initialized t)))))
@@ -349,6 +328,5 @@
('no (error "Cannot mix start-win and start-app in one lisp session. Use start-app or restart lisp"))
(t (setf *using-thread* 'yes)))
(start-gtk-main)
- (apply #'show-win app-class initargs)
- 0))
+ (apply #'show-win app-class initargs)))
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/packages.lisp 2008/04/13 10:59:17 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/packages.lisp 2008/04/14 16:43:42 1.2
@@ -44,11 +44,15 @@
#:cells-tree-node
#:cells-tree-store
#:cells-gtk-init
+
#:title
#:icon
#:tooltips
#:tooltips-enable
#:tooltips-delay
+ #:allocated-width
+ #:allocated-height
+
#:start-app
#:start-win
#:stop-gtk-main
@@ -142,4 +146,9 @@
#:on-dragged ; (on-dragged [widget] [button] [primitive] [start-pos] [end-pos])
#:hover ; the primitive the mouse is currently over
#:dragging ; the primitive currently being dragged
+
+ #:gl-drawing-area
+ #:with-gl-context
+ #:init
+ #:draw
))
--- /project/cells/cvsroot/cells-gtk3/cells-gtk/widgets.lisp 2008/04/13 10:59:17 1.1
+++ /project/cells/cvsroot/cells-gtk3/cells-gtk/widgets.lisp 2008/04/14 16:43:44 1.2
@@ -24,9 +24,9 @@
(def-gtk-class-name :accessor def-gtk-class-name :initarg :def-gtk-class-name :initform nil)
(new-function-name :accessor new-function-name :initarg :new-function-name
:initform (c_1 (intern (format nil "GTK-~a-NEW~a"
- (def-gtk-class-name self)
- (or (new-tail self) ""))
- :gtk-ffi)))
+ (def-gtk-class-name self)
+ (or (new-tail self) ""))
+ :gtk-ffi)))
(new-args :accessor new-args :initarg :new-args :initform nil)
(new-tail :accessor new-tail :initarg :new-tail :initform nil)
(id :initarg :id :accessor id
@@ -36,6 +36,7 @@
(let ((id (apply (symbol-function (new-function-name self))
(new-args self))))
(gtk-object-store id self)
+ (gtk-signal-connect-swap id "configure-event" (cffi:get-callback 'reshape-widget-handler) :data id)
id))))
(callbacks :cell nil :accessor callbacks
@@ -47,14 +48,19 @@
;; --------- provide id-to-clos lookup ------
-(defvar *gtk-objects* nil)
+;;;
+;;; gtk object registry
+;;;
+(defvar *gtk-objects* nil)
(defvar *widgets* nil)
(defun gtk-objects-init ()
(setf *gtk-objects* (make-hash-table :size 100 :rehash-size 100)
*widgets* (make-hash-table :test #'equal)))
+;;; id lookup
+
(defun gtk-object-store (gtk-id gtk-object &aux (hash-id (cffi:pointer-address gtk-id)))
(unless *gtk-objects*
(gtk-objects-init))
@@ -88,10 +94,11 @@
(gtk-report-error gtk-object-id-error "gtk.object.find ID not found ~a" hash-id))
clos-widget)))
+;;; name lookup
+
(defun find-widget (name &optional default)
(gethash name *widgets* default))
-
(defmacro with-widget ((widget name &optional alternative) &body body)
`(bif (,widget (find-widget ,name))
(progn ,@body)
@@ -104,12 +111,13 @@
(progn ,@body)
,alternative))))
-(defun widget-value (name default &key (accessor 'value))
+(defun widget-value (name &optional default (accessor 'value))
(with-widget-value (val name :accessor accessor :alternative default)
val))
-
-
+;;;
+;;; callbacks
+;;;
;; ----- fake callbackable closures ------------
@@ -121,8 +129,6 @@
(defun callback-recover (self callback-key)
(cdr (assoc callback-key (callbacks self))))
-; ------------------------------------------
-
;;;
;;; callback table
;;;
@@ -145,7 +151,6 @@
(funcall (aref *gtk-global-callbacks* n)))
-
(defmethod configure ((self gtk-object) gtk-function value)
(apply gtk-function
(id self)
@@ -321,15 +326,36 @@
(x-pad :accessor x-pad :initarg :x-pad :initform (c? (padding? self)))
(y-pad :accessor y-pad :initarg :y-pad :initform (c? (padding? self)))
(width :accessor width :initarg :width :initform nil)
- (height :accessor height :initarg :height :initform nil))
+ (height :accessor height :initarg :height :initform nil)
+ (allocated-width :accessor allocated-width :initform (c-in 0))
+ (allocated-height :accessor allocated-height :initform (c-in 0))
+ )
()
(focus show hide delete-event destroy-event)
;; this is called unless the user overwrites this routine
:on-delete-event (c-in #'(lambda (self widget event data)
(declare (ignore widget event data))
+ (trc "on-delete")
(gtk-object-forget (id self) self)
0)))
+#+libcellsgtk
+(cffi:defcallback reshape-widget-handler :int ((widget :pointer) (event :pointer) (data :pointer))
+ (declare (ignore data event))
+ (bwhen (self (gtk-object-find widget))
+ (let ((new-width (gtk-adds-widget-width widget))
+ (new-height (gtk-adds-widget-height widget)))
+ (trc "reshape widget to new size" self widget new-width new-height)
+ (with-integrity (:change :adjust-widget-size)
+ (setf (allocated-width self) new-width
+ (allocated-height self) new-height))))
+ 0)
+
+(defmethod initialize-instance :after ((self widget) &rest initargs)
+ (declare (ignore initargs))
+ #+libcellsgtk-
+ )
+
(defmethod focus ((self widget))
(gtk-widget-grab-focus (id self)))