[mcclim-cvs] CVS update: mcclim/Backends/beagle/input/events.lisp
Duncan Rose
drose at common-lisp.net
Thu May 19 22:25:36 UTC 2005
Update of /project/mcclim/cvsroot/mcclim/Backends/beagle/input
In directory common-lisp.net:/tmp/cvs-serv24047/beagle/input
Modified Files:
events.lisp
Log Message:
Some refactoring of events.lisp; made an effort to trawl for
memory allocations and ensure they're freed appropriately.
Estimate this to be around 70-80% done. Seems to give
performance and stability benefits.
Date: Fri May 20 00:25:34 2005
Author: drose
Index: mcclim/Backends/beagle/input/events.lisp
diff -u mcclim/Backends/beagle/input/events.lisp:1.3 mcclim/Backends/beagle/input/events.lisp:1.4
--- mcclim/Backends/beagle/input/events.lisp:1.3 Tue May 17 22:12:37 2005
+++ mcclim/Backends/beagle/input/events.lisp Fri May 20 00:25:34 2005
@@ -28,7 +28,7 @@
#||
-$Id: events.lisp,v 1.3 2005/05/17 20:12:37 drose Exp $
+$Id: events.lisp,v 1.4 2005/05/19 22:25:34 drose Exp $
All these are copied pretty much from CLX/port.lisp
@@ -56,19 +56,19 @@
;;; The following parameters are *all* added for 'synthesize-pointer-motion-event' only.
(defparameter *-current-event-modifier-state-* 0
- "Contains the most recent modifier state for any ``real'' event. Reset whenever any
+ "Contains the most recent modifier state for any 'real' event. Reset whenever any
event (but not notification) is handled.")
(defparameter *-current-pointer-button-state-* 0
- "Contains the most recent pointer button state for any ``real'' event. Reset whenever
+ "Contains the most recent pointer button state for any 'real' event. Reset whenever
any pointer or button-press event is handled.")
(defparameter *-current-pointer-graft-xy-* nil
"Contains the (Cocoa) NSPoint foreign object (structure) representing the position of
-the mouse pointer in screen coordinates. Reset whenever a ``real'' pointer event
+the mouse pointer in screen coordinates. Reset whenever a 'real' pointer event
(mouse-move, mouse-drag, enter / exit or button press / release) is handled.")
(defparameter *-current-pointer-view-xy-* nil
"Contains the (Cocoa) NSPoint foreign object (structure) representing the position of
the mouse pointer in the coordinate system of the NSView it is currently over. Reset
-whenever a ``real'' pointer event (mouse-move, mouse-drag, enter / exit or button
+whenever a 'real' pointer event (mouse-move, mouse-drag, enter / exit or button
press / release) is handled.")
(defvar *keysym-hash-table*
@@ -104,17 +104,6 @@
;;; in cocoa (grab events and window hints), hopefully that won't matter to
;;; us (apart from the menus use grabbing I think)
-;;; All these parameters must be what CLX provides for the :handler argument
-;;; to the xlib:process-event method.
-
-;;; We don't actually need all this gubbins for Cocoa events. We just need a
-;;; method to convert from a Cocoa event to a CLIM event. As specified, this
-;;; would be quite a good fit. Unfortunately, McCLIM seems to have a whole
-;;; bunch of non-standard slots in the event objects (root-x, root-y etc.)
-;;; and the override-redirect-p, send-event-p, hint-p stuff in this method.
-
-;;; So we actually want to do this slightly differently.
-
;; From CLX/port.lisp
;; NOTE: Although it might be tempting to compress (consolidate)
@@ -136,31 +125,6 @@
;;
;;--GB
-;; XXX :button code -> :button (decode-x-button-code code)
-;; (declare (ignorable event-slots))
-;; (declare (special *cocoa-port*))
-;; (let ((sheet (and window
-;; (port-lookup-sheet port window))))
-;; (when sheet
-;; (:enter-notify
-;; (make-instance 'pointer-enter-event
-;; :pointer 0
-;; :button code :x x :y y
-;; :graft-x root-x
-;; :graft-y root-y
-;; :sheet sheet
-;; :modifier-state (cocoa-event-state-modifiers *cocoa-port* state)
-;; :timestamp time))
-;; (:leave-notify
-;; (make-instance 'pointer-exit-event ; No grab events in cocoa - may cause problems?
-;; :pointer 0
-;; :button code
-;; :x x :y y
-;; :graft-x root-x
-;; :graft-y root-y
-;; :sheet sheet
-;; :modifier-state (cocoa-event-state-modifiers *cocoa-port* state)
-;; :timestamp time))
(defparameter *mcclim-event-queue* nil)
@@ -176,7 +140,8 @@
(setf *mcclim-event-queue* (nconc *mcclim-event-queue* (list clim-event)))
(ccl:signal-semaphore (beagle-port-event-semaphore *beagle-port*)))))
-(defmethod add-notification-to-queue (window notification &optional origin-x origin-y width height)
+(defmethod add-notification-to-queue (window notification
+ &optional origin-x origin-y width height)
"Adds an event to the dynamically scoped *mcclim-event-queue* queue, after conversion from
a Cocoa notification MACPTR to a CLIM event. This method signals the port event semaphore
when a notification is added to the queue."
@@ -224,14 +189,16 @@
;; Can we make use of the other modifier states set by cocoa? Some of
;; them might be useful...
-;;; Every key on the keyboard has a physical "key-code". a and A share the same key code, since the
-;;; same key is pressed (0 in this case). We can't make use of the key-code with any confidence since
-;;; they're at a very low-level. We have to use the 'characters method (or 'characters-ignoring-modifiers)
-;;; to pull the actual keys out of the event. Then we need to map these to McCLIM key names. *sigh*
-
-;;; We could use 'characters if we were going through the full Cocoa key-handling path; and we might
-;;; be able to make use of this anyway, but for now just use 'characters-ignoring-modifiers and compare
-;;; what we get with those values known from Cocoa for function keys etc.
+;;; Every key on the keyboard has a physical "key-code". a and A share the same key
+;;; code, since the same key is pressed (0 in this case). We can't make use of the
+;;; key-code with any confidence since they're at a very low-level. We have to use
+;;; the 'characters method (or 'characters-ignoring-modifiers) to pull the actual
+;;; keys out of the event. Then we need to map these to McCLIM key names. *sigh*
+
+;;; We could use 'characters if we were going through the full Cocoa key-handling
+;;; path; and we might be able to make use of this anyway, but for now just use
+;;; 'characters-ignoring-modifiers and compare what we get with those values known
+;;; from Cocoa for function keys etc.
(defun beagle-key-event-to-key-name (event)
;; This falls over when the function keys, the arrow keys, the num-lock key (and others)
;; are pressed; I guess we don't want to be doing this!
@@ -240,6 +207,7 @@
;;; (format *terminal-io* "returning key-name: ~A~%" key-name)
key-name))
+;;; ::TODO:: - make these masks parameters so the user can configure them?
(defun beagle-modifier-to-modifier-state (flags)
(declare (special *-current-event-modifier-state-*))
(let ((mods 0))
@@ -262,6 +230,9 @@
;;; NSHelpKeyMask
;;; NSNumericKeyPadKeyMask (key on numeric pad was pressed)
;;; NSFunctionKeyMask (function key was pressed)
+
+ ;; ::TODO:: return from setf is the value set, so don't need
+ ;; the final line below.
(setf *-current-event-modifier-state-* mods)
mods))
@@ -295,14 +266,104 @@
;; I'm not sure this is the best way with dealing with the timestamp...
+(defun notification-type (notification)
+"Enumerates all the Cocoa notifications Beagle takes an interest in. These
+are all NSWindow delegate notifications."
+ (let ((name (send notification 'name)))
+ (cond ((send name :is-equal-to-string #@"NSWindowDidBecomeKeyNotification")
+ :became-key)
+ ((send name :is-equal-to-string #@"NSWindowDidExposeNotification")
+ :did-expose)
+ ((send name :is-equal-to-string #@"NSWindowDidResizeNotification")
+ :did-resize)
+ ((send name :is-equal-to-string #@"NSWindowWillCloseNotification")
+ :will-close)
+ (t :unknown))))
+
+(defun event-type (event)
+"Enumerates all the Cocoa events Beagle takes an interest in. Returns two
+values; the first is the TYPE of event (mouse-up, mouse-move) and the
+second is the button pressed at the time of the event. The latter value
+will be NIL if no button was involved in the event (or if the event is
+not a mouse event)."
+ (let ((event-type (send event 'type)))
+ (cond ((equal #$NSLeftMouseUp event-type)
+ (values :mouse-up :left))
+ ((equal #$NSRightMouseUp event-type)
+ (values :mouse-up :right))
+ ((equal #$NSOtherMouseUp event-type)
+ (values :mouse-up :other))
+ ((equal #$NSLeftMouseDown event-type)
+ (values :mouse-down :left))
+ ((equal #$NSRightMouseDown event-type)
+ (values :mouse-down :right))
+ ((equal #$NSOtherMouseDown event-type)
+ (values :mouse-down :other))
+ ((equal #$NSScrollWheel event-type)
+ (values :scroll-wheel nil))
+ ((equal #$NSKeyDown event-type)
+ (values :key-down nil))
+ ((equal #$NSKeyUp event-type)
+ (values :key-up nil))
+ ((equal #$NSMouseMoved event-type)
+ (values :mouse-moved nil))
+ ((equal #$NSLeftMouseDragged event-type)
+ (values :mouse-moved :left))
+ ((equal #$NSRightMouseDragged event-type)
+ (values :mouse-moved :right))
+ ((equal #$NSOtherMouseDragged event-type)
+ (values :mouse-moved :other))
+ ((equal #$NSMouseEntered event-type)
+ ;; Not really a mouse event...
+ (values :mouse-enter nil))
+ ((equal #$NSMouseExited event-type)
+ ;; Not really a mouse event...
+ (values :mouse-exit nil))
+ ((equal #$NSFlagsChanged event-type)
+ (values :flags-changed nil))
+ (t (values :unknown nil)))))
+
+
+;;; Record current pointer position + button state so we can 'synthesize' a motion
+;;; event at will... this feels like a hack. Is it really necessary?
+(defun set-hacky-graft/view-xy (graft-xy view-xy)
+ (declare (special *-current-pointer-graft-xy-*
+ *-current-pointer-view-xy-*))
+
+ ;; Need to free memory assigned via 'make-record'. There's no nice way to do
+ ;; this :-(
+
+ (unless (or (null *-current-pointer-graft-xy-*)
+ (eql (%null-ptr) *-current-pointer-graft-xy-*))
+ (#_free *-current-pointer-graft-xy-*))
+
+ (unless (or (null *-current-pointer-view-xy-*)
+ (eql (%null-ptr) *-current-pointer-view-xy-*))
+ (#_free *-current-pointer-view-xy-*))
+
+ (setf *-current-pointer-graft-xy-* (ccl::make-record :<NSP>oint
+ :x (pref graft-xy :<NSP>oint.x)
+ :y (pref graft-xy :<NSP>oint.y)))
+ (setf *-current-pointer-view-xy-* (ccl::make-record :<NSP>oint
+ :x (pref view-xy :<NSP>oint.x)
+ :y (pref view-xy :<NSP>oint.y))))
+
+
+(defun set-hacky-button-state (state)
+ (declare (special *-current-pointer-button-state*-))
+ (setf *-current-pointer-button-state*- state))
+
+
(let ((timestamp 0))
(defun beagle-notification-to-clim-event (window notification &optional origin-x origin-y width height)
(declare (special *beagle-port*))
(let ((return-event nil)
- (sheet (%beagle-port-lookup-sheet-for-view *beagle-port* (send window 'content-view))))
+ (sheet (%beagle-port-lookup-sheet-for-view *beagle-port* (send window 'content-view)))
+ (n-type (notification-type notification)))
;; We don't get exposure notifications when the window has a (Cocoa) backing store.
+ ;; Use 'ecase' for this, like in medium-draw-text?
(cond
- ((send (send notification 'name) :is-equal-to-string #@"NSWindowDidBecomeKeyNotification")
+ ((eq :became-key n-type)
(setf return-event nil)
(when (send window 'is-visible) ; only do if window is on-screen...
(let* ((content-view (send window 'content-view))
@@ -313,7 +374,7 @@
(focus (climi::keyboard-input-focus frame)))
(unless (null target-sheet)
(setf (port-keyboard-input-focus *beagle-port*) focus)))))
- ((send (send notification 'name) :is-equal-to-string #@"NSWindowDidExposeNotification")
+ ((eq :did-expose n-type)
(setf return-event
(make-instance 'window-repaint-event :timestamp (incf timestamp)
:sheet sheet
@@ -321,273 +382,255 @@
;; seem to be a way to specify a region... coord
;; system?
:region (make-rectangle* origin-x origin-y width height))))
- ((send (send notification 'name) :is-equal-to-string #@"NSWindowDidResizeNotification")
+ ((eq :did-resize n-type)
(setf return-event (make-instance 'window-configuration-event :sheet sheet
:x origin-x ; coord system?
:y origin-y
:width width
:height height)))
- ((send (send notification 'name) :is-equal-to-string #@"NSWindowWillCloseNotification")
+ ((eq :will-close n-type)
(setf return-event (make-instance 'window-destroy-event :sheet sheet)))
- ;; TODO: this logic is the same as the previous version, but
- ;; is it correct? it means that if we get a
- ;; notification that we don't recognize, we ignore it
+ ;; Ignore notifications in which we're uninterested.
(t nil))
return-event))
(defun beagle-event-to-clim-event (mirror event)
- (declare (special *-current-pointer-button-state-*
- *-current-pointer-view-xy-*
- *-current-pointer-graft-xy-*))
+ (declare (special *-current-pointer-button-state-*))
+
(let ((window (send event 'window))
- (return-event event)
- ;; Can't do this here any more - it breaks NSFlagsChanged event handling :-(
-;;; (modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags)))
- (event-type (send event 'type)))
- (when (or (equal #$NSLeftMouseUp event-type)
- (equal #$NSLeftMouseDown event-type)
- (equal #$NSRightMouseUp event-type)
- (equal #$NSRightMouseDown event-type)
- (equal #$NSOtherMouseUp event-type)
- (equal #$NSOtherMouseDown event-type))
- (slet ((location-in-window-point (send event 'location-in-window))
- (window-bounds (send (send window 'content-view) 'bounds)))
- (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
- (pref location-in-window-point :<NSP>oint.y)))
-
- ;;; *SUSPECT* this will leak; gc won't collect heap-allocated store from make-record will it?
- (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
- :from-view (send window 'content-view)))
- (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
-
- (setf *-current-pointer-graft-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-screen-point :<NSP>oint.x)
- :y (pref location-in-screen-point :<NSP>oint.y)))
- (setf *-current-pointer-view-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)))
- (setf return-event
- (make-instance (if (or (equal #$NSLeftMouseUp event-type)
- (equal #$NSRightMouseUp event-type)
- (equal #$NSOtherMouseUp event-type))
- 'pointer-button-release-event
- 'pointer-button-press-event)
- :pointer 0
- :button (cond ((or (equal event-type #$NSLeftMouseUp)
- (equal event-type #$NSLeftMouseDown))
- (setf *-current-pointer-button-state-* +pointer-left-button+)
- +pointer-left-button+)
- ((or (equal event-type #$NSRightMouseUp)
- (equal event-type #$NSRightMouseDown))
- (setf *-current-pointer-button-state-* +pointer-right-button+)
- +pointer-right-button+)
- (t
- (setf *-current-pointer-button-state-* +pointer-middle-button+)
- +pointer-middle-button+))
- ;; x and y are in window coordinates. They need converting to screen
- ;; coordinates. Can do this with
- ;; [window convertBaseToScreen:location-in-window].x or .y.
- ;; They probably need coercing too :-(
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)
- :graft-x (pref location-in-screen-point :<NSP>oint.x)
- :graft-y (pref location-in-screen-point :<NSP>oint.y)
- :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
- :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- ;; Timestamp from Cocoa looks like 12345.7 - CLIM wants integer no
- ;; bigger than a fixnum, so it gets a fixnum. Hope Cocoa doesn't
- ;; send non-unique timestamps.
- ;; NSTimeInterval is a double typedef
- :timestamp (incf timestamp))))))
- ;; (coerce (* 10 (pref timestamp :<NST>ime<I>nterval)) 'fixnum))))))
-
- (when (equal #$NSScrollWheel event-type)
- (setf return-event (make-instance 'pointer-button-press-event
- :pointer 0
- ;; The 'amount' of scroll can be specified in Cocoa by a
- ;; larger or smaller delta in either X, Y or Z directions.
- ;; We ignore this, and always pass up or down and let
- ;; CLIM set the amount. Could do better with scroll wheel
- ;; events, CLIM also ignores X and Z deltas...
- :button (if (plusp (send event 'delta-y))
+ (return-event event))
+ (multiple-value-bind (event-type button)
+ (event-type event)
+ (when (or (eq :mouse-up event-type)
+ (eq :mouse-down event-type))
+ (slet ((location-in-window-point (send event 'location-in-window))
+ (window-bounds (send (send window 'content-view) 'bounds)))
+ (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
+ (pref location-in-window-point :<NSP>oint.y)))
+
+ (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
+ :from-view (send window 'content-view)))
+ (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
+
+ ;; Only want this for 'synthesize-point-motion-event'
+ (set-hacky-graft/view-xy location-in-screen-point
+ location-in-view-point)
+
+ (setf return-event
+ (make-instance (if (eq :mouse-up event-type)
+ 'pointer-button-release-event
+ 'pointer-button-press-event)
+ :pointer 0
+ :button (cond ((eq :left button)
+ (set-hacky-button-state +pointer-left-button+)
+ +pointer-left-button+)
+ ((eq :right button)
+ (set-hacky-button-state +pointer-right-button+)
+ +pointer-right-button+)
+ (t
+ (set-hacky-button-state +pointer-middle-button+)
+ +pointer-middle-button+))
+ ;; x and y are in window coordinates. They need converting to screen
+ ;; coordinates. Can do this with
+ ;; [window convertBaseToScreen:location-in-window].x or .y.
+ ;; They probably need coercing too :-(
+ :x (pref location-in-view-point :<NSP>oint.x)
+ :y (pref location-in-view-point :<NSP>oint.y)
+ :graft-x (pref location-in-screen-point :<NSP>oint.x)
+ :graft-y (pref location-in-screen-point :<NSP>oint.y)
+ :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
+ :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
+ ;; Timestamp from Cocoa looks like 12345.7 - CLIM wants integer no
+ ;; bigger than a fixnum, so it gets a fixnum. Hope Cocoa doesn't
+ ;; send non-unique timestamps.
+ ;; NSTimeInterval is a double typedef
+ :timestamp (incf timestamp))))))
+
+ (when (eq :scroll-wheel event-type)
+ (setf return-event (make-instance 'pointer-button-press-event
+ :pointer 0
+ ;; The 'amount' of scroll can be specified in Cocoa by a
+ ;; larger or smaller delta in either X, Y or Z directions.
+ ;; We ignore this, and always pass up or down and let
+ ;; CLIM set the amount. Could do better with scroll wheel
+ ;; events, CLIM also ignores X and Z deltas...
+ :button (if (plusp (send event 'delta-y))
+ (progn
+ (set-hacky-button-state +pointer-wheel-up+)
+ +pointer-wheel-up+)
(progn
- (setf *-current-pointer-button-state-* +pointer-wheel-up+)
- +pointer-wheel-up+)
- (progn
- (setf *-current-pointer-button-state-* +pointer-wheel-down+)
- +pointer-wheel-down+))
- ;; Surely scroll-wheel events do not need x, y coords? input.lisp
- ;; does a 'call-next-method' after handling the scroll but won't
- ;; that then get passed as a 'proper' button press? Best pass these
- ;; as values we're unlikely to ever get clicked.
- :x 0
- :y 0
- :graft-x 0
- :graft-y 0
- :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
- :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- ;; Timestamp from Cocoa looks like 12345.7 - CLIM wants integer no
- ;; bigger than a fixnum, so it gets a fixnum. Hope Cocoa doesn't
- ;; send non-unique timestamps.
- ;; NSTimeInterval is a double typedef
- :timestamp (incf timestamp))))
+ (set-hacky-button-state +pointer-wheel-down+)
+ +pointer-wheel-down+))
+ ;; Surely scroll-wheel events do not need x, y coords? input.lisp
+ ;; does a 'call-next-method' after handling the scroll but won't
+ ;; that then get passed as a 'proper' button press? Best pass these
+ ;; as values we're unlikely to ever get clicked.
+ :x 0
+ :y 0
+ :graft-x 0
+ :graft-y 0
+ :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
+ :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
+ ;; Timestamp from Cocoa looks like 12345.7 - CLIM wants integer at least
+ ;; as big as a fixnum, so it gets a fixnum. Hope Cocoa doesn't
+ ;; send non-unique timestamps.
+ ;; NSTimeInterval is a double typedef
+ :timestamp (incf timestamp))))
- ;; Keyname should probably be the #$NSF1FunctionKey, #$NSUpArrowFunctionKey etc as defined in the docs
- ;; for NSEvent (these are permitted to be implementation defined - not sure if that's the back end
- ;; implementation or the McCLIM implementation!), apart from the "standard" keys which should be symbols
- ;; in the keyword package (presumably :a :b :c etc.?)
+ ;; Keyname should probably be the #$NSF1FunctionKey, #$NSUpArrowFunctionKey etc as defined in the docs
+ ;; for NSEvent (these are permitted to be implementation defined - not sure if that's the back end
+ ;; implementation or the McCLIM implementation!), apart from the "standard" keys which should be symbols
+ ;; in the keyword package (presumably :a :b :c etc.?)
- ;; ::FIXME:: WILL ONLY WORK FOR "STANDARD" KEYS!!!
+ ;; ::FIXME:: WILL ONLY WORK FOR "STANDARD" KEYS!!!
- (when (or (equal #$NSKeyDown event-type)
- (equal #$NSKeyUp event-type))
- (let ((keyname (beagle-key-event-to-key-name event)))
-;;; (format *terminal-io* "In event-build with keyname: ~A (characterp = ~A)~%" keyname (characterp keyname))
- (setf return-event (make-instance (if (equal #$NSKeyDown event-type)
- 'key-press-event
- 'key-release-event)
- :key-name keyname
- ;; not needed by spec - should change implementation?
- :key-character (and (characterp keyname) keyname)
- :x 0 ; Not needed for key events?
- :y 0 ; Not needed for key events?
- :graft-x 0 ; Not needed for key events?
- :graft-y 0 ; Not needed for key events?
- ;; Irrespective of where the key event happened, send it
- ;; to the sheet that has key-focus for the port.
- :sheet (beagle-port-key-focus *beagle-port*)
- :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- :timestamp (incf timestamp)))))
- (when (or (equal #$NSMouseMoved event-type)
- (equal #$NSLeftMouseDragged event-type)
- (equal #$NSRightMouseDragged event-type)
- (equal #$NSOtherMouseDragged event-type))
- (slet ((location-in-window-point (send event 'location-in-window))
- (window-bounds (send (send window 'content-view) 'bounds)))
- ;; Because the location in window is *not* flipped, we need to flip it... (note: we flip by the size
- ;; of the window's content view, otherwise we end up out by the size of the window title bar).
- ;; *SUSPECT* this will leak; gc won't collect heap-allocated store from make-record will it?
- (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
- (pref location-in-window-point :<NSP>oint.y)))
- (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
- :from-view (send window 'content-view)))
- (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
-
- (setf *-current-pointer-graft-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-screen-point :<NSP>oint.x)
- :y (pref location-in-screen-point :<NSP>oint.y)))
- (setf *-current-pointer-view-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)))
- (setf return-event
- (make-instance 'pointer-motion-event
- :pointer 0
- :button (cond ((equal event-type #$NSMouseMoved)
- (setf *-current-pointer-button-state-* 0)
- 0)
- ((equal event-type #$NSLeftMouseDragged)
- (setf *-current-pointer-button-state-* +pointer-left-button+)
- +pointer-left-button+)
- ((equal event-type #$NSRightMouseDragged)
- (setf *-current-pointer-button-state-* +pointer-right-button+)
- +pointer-right-button+)
- (t
- (setf *-current-pointer-button-state-* +pointer-middle-button+)
- +pointer-middle-button+))
- ;; It looks like McCLIM diverges from the spec again in relation
- ;; to events (I wonder who is responsible? 8-) and expects :x and
- ;; :y to be relative to the MIRROR in which the events occur.
- ;; :x (pref location-in-screen-point :<NSP>oint.x)
- ;; :y (pref location-in-screen-point :<NSP>oint.y)
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)
- ;; Even though graft-x, graft-y is *not in the spec* we need to populate
- ;; them because there's code in McCLIM/gadgets.lisp that makes direct
- ;; use of the graft-x/y slot values. Naughty. So how does this differ
- ;; from :x and :y which are supposedly in native coordinates? Methinks
- ;; that the event hierarchy and associated code in McCLIM should perhaps
- ;; be revisited... currently it appears that these are *only* used to support
- ;; pointer-motion-events. Strange. It doesn't seem to make any difference what
- ;; gets set here! Suspect we're not invoking the callback because we're not
- ;; passing the correct sheet...?
+ (when (or (eq :key-down event-type)
+ (eq :key-up event-type))
+ (let ((keyname (beagle-key-event-to-key-name event)))
+ (setf return-event (make-instance (if (eq :key-down event-type)
+ 'key-press-event
+ 'key-release-event)
+ :key-name keyname
+ ;; not needed by spec - should change implementation?
+ :key-character (and (characterp keyname) keyname)
+ :x 0 ; Not needed for key events?
+ :y 0 ; Not needed for key events?
+ :graft-x 0 ; Not needed for key events?
+ :graft-y 0 ; Not needed for key events?
+ ;; Irrespective of where the key event happened, send it
+ ;; to the sheet that has key-focus for the port.
+ :sheet (beagle-port-key-focus *beagle-port*)
+ :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
+ :timestamp (incf timestamp)))))
+
+ (when (eq :mouse-moved event-type)
+ (slet ((location-in-window-point (send event 'location-in-window))
+ (window-bounds (send (send window 'content-view) 'bounds)))
+ ;; Because the location in window is *not* flipped, we need to flip it... (note: we flip by the size
+ ;; of the window's content view, otherwise we end up out by the size of the window title bar).
+ (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
+ (pref location-in-window-point :<NSP>oint.y)))
+ (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
+ :from-view (send window 'content-view)))
+ (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
+
+ (set-hacky-graft/view-xy location-in-screen-point
+ location-in-view-point)
+
+ (setf return-event
+ (make-instance 'pointer-motion-event
+ :pointer 0
+ :button (cond ((null button)
+ (set-hacky-button-state 0)
+ 0)
+ ((eq :left button)
+ (set-hacky-button-state +pointer-left-button+)
+ +pointer-left-button+)
+ ((eq :right button)
+ (set-hacky-button-state +pointer-right-button+)
+ +pointer-right-button+)
+ (t
+ (set-hacky-button-state +pointer-middle-button+)
+ +pointer-middle-button+))
+ ;; It looks like McCLIM diverges from the spec again in relation
+ ;; to events (I wonder who is responsible? 8-) and expects :x and
+ ;; :y to be relative to the MIRROR in which the events occur.
+ ;; :x (pref location-in-screen-point :<NSP>oint.x)
+ ;; :y (pref location-in-screen-point :<NSP>oint.y)
+ :x (pref location-in-view-point :<NSP>oint.x)
+ :y (pref location-in-view-point :<NSP>oint.y)
+ ;; Even though graft-x, graft-y is *not in the spec* we need to populate
+ ;; them because there's code in McCLIM/gadgets.lisp that makes direct
+ ;; use of the graft-x/y slot values. Naughty. So how does this differ
+ ;; from :x and :y which are supposedly in native coordinates? Methinks
+ ;; that the event hierarchy and associated code in McCLIM should perhaps
+ ;; be revisited... currently it appears that these are *only* used to support
+ ;; pointer-motion-events. Strange. It doesn't seem to make any difference what
+ ;; gets set here! Suspect we're not invoking the callback because we're not
+ ;; passing the correct sheet...?
;;; :graft-x (pref location-in-view-point :<NSP>oint.x) ;0
;;; :graft-y (pref location-in-view-point :<NSP>oint.y) ;0
- :graft-x (pref location-in-screen-point :<NSP>oint.x) ;0
- :graft-y (pref location-in-screen-point :<NSP>oint.y) ;0
- ;; This is probably wrong too; the NSWindow receives and propogates mouse
- ;; moved events, but we need to translate them into an appropriate view.
- ;; Not sure quite how we do that, but I think we need to... we're ok for
- ;; key down / up, we keep track of the "key view". Do we also need to keep
- ;; track of what interactors we have? I suspect not. We just need to traverse
- ;; the NSView hierarchy (or sheet hierarchy, whichever is easiest) until we
- ;; find the "youngest" view (or sheet) over which the event occurred; this
- ;; is the sheet that should handle the event.
- :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
+ :graft-x (pref location-in-screen-point :<NSP>oint.x) ;0
+ :graft-y (pref location-in-screen-point :<NSP>oint.y) ;0
+ ;; This is probably wrong too; the NSWindow receives and propogates mouse
+ ;; moved events, but we need to translate them into an appropriate view.
+ ;; Not sure quite how we do that, but I think we need to... we're ok for
+ ;; key down / up, we keep track of the "key view". Do we also need to keep
+ ;; track of what interactors we have? I suspect not. We just need to traverse
+ ;; the NSView hierarchy (or sheet hierarchy, whichever is easiest) until we
+ ;; find the "youngest" view (or sheet) over which the event occurred; this
+ ;; is the sheet that should handle the event.
+ :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
+ :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
+ :timestamp (incf timestamp))))))
+
+ (when (or (eq :mouse-enter event-type)
+ (eq :mouse-exit event-type))
+ #+nil
+ (let ((view-sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)))
+ (when (typep view-sheet 'clim:push-button-pane)
+ (format *debug-io* "Got ~a event on sheet ~a~%"
+ event-type view-sheet)))
+ (slet ((location-in-window-point (send event 'location-in-window))
+ (window-bounds (send (send window 'content-view) 'bounds)))
+ ;; Because the location in window is *not* flipped, we need to flip it...
+ ;; (note: we flip by the size of the window's content view, otherwise we
+ ;; end up out by the size of the window title bar).
+
+ ;; Is this where things are going wrong with PUSH-BUTTON-PANE buttons?
+ ;; Could be... whatever, I think this is a little dodgy...
+ (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
+ (pref location-in-window-point :<NSP>oint.y)))
+ (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
+ :from-view (send window 'content-view)))
+ (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
+
+ (set-hacky-graft/view-xy location-in-screen-point
+ location-in-view-point)
+
+ ;; This event does not provide button state, but we can use *-current-pointer-button-state-*
+ ;; to populate button state in the CLIM event. Obviously, we do not need to update this value
+ ;; (*-current-pointer-button-state-*) for enter / exit events...
+ (setf return-event
+ (make-instance (if (eq :mouse-enter event-type)
+ 'pointer-enter-event
+ 'pointer-exit-event)
+ :pointer 0
+ :button *-current-pointer-button-state-*
+ :x (pref location-in-view-point :<NSP>oint.x)
+ :y (pref location-in-view-point :<NSP>oint.y)
+ :graft-x (pref location-in-screen-point :<NSP>oint.x) ;0
+ :graft-y (pref location-in-screen-point :<NSP>oint.y) ;0
+ :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
+ :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
+ :timestamp (incf timestamp))))))
+
+ ;; We need to maintain the modifier flags state constantly to be able to
+ ;; implement this; suggest a slot in beagle-port?
+ (when (eq :flags-changed event-type)
+ ;; Use the 'old' 'modifiers' in conjunction with the new 'modifier-state'
+ ;; to work out if this is a key up or a key down...
+ (setf return-event
+ (destructuring-bind (event-class key)
+ (current-mods-map-to-key (send event 'modifier-flags))
+ (make-instance event-class
+ :key-name key
+ :key-character nil
+ :x 0
+ :y 0
+ :graft-x 0
+ :graft-y 0
+ ;; Irrespective of where the key event happened, send it
+ ;; to the sheet that has key-focus for the port.
+ :sheet (beagle-port-key-focus *beagle-port*)
:modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- :timestamp (incf timestamp))))))
- (when (or (equal #$NSMouseEntered event-type)
- (equal #$NSMouseExited event-type))
-;;; (format *debug-io* "Got mouse entered / exited event for mirror ~S~%" mirror)
- (slet ((location-in-window-point (send event 'location-in-window))
- (window-bounds (send (send window 'content-view) 'bounds)))
- ;; Because the location in window is *not* flipped, we need to flip it... (note: we flip by the size
- ;; of the window's content view, otherwise we end up out by the size of the window title bar).
- (setf (pref location-in-window-point :<NSP>oint.y) (- (pref window-bounds :<NSR>ect.size.height)
- (pref location-in-window-point :<NSP>oint.y)))
- (slet ((location-in-view-point (send mirror :convert-point location-in-window-point
- :from-view (send window 'content-view)))
- (location-in-screen-point (send window :convert-base-to-screen location-in-window-point)))
-
- (setf *-current-pointer-graft-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-screen-point :<NSP>oint.x)
- :y (pref location-in-screen-point :<NSP>oint.y)))
- (setf *-current-pointer-view-xy-* (ccl::make-record :<NSP>oint
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)))
- ;; This event does not provide button state, but we can use *-current-pointer-button-state-*
- ;; to populate button state in the CLIM event. Obviously, we do not need to update this value
- ;; (*-current-pointer-button-state-*) for enter / exit events...
- (setf return-event
- (make-instance (if (equal #$NSMouseEntered event-type)
- 'pointer-enter-event
- 'pointer-exit-event)
- :pointer 0
- :button *-current-pointer-button-state-*
- :x (pref location-in-view-point :<NSP>oint.x)
- :y (pref location-in-view-point :<NSP>oint.y)
- :graft-x (pref location-in-screen-point :<NSP>oint.x) ;0
- :graft-y (pref location-in-screen-point :<NSP>oint.y) ;0
- :sheet (%beagle-port-lookup-sheet-for-view *beagle-port* mirror)
- :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- :timestamp (incf timestamp))))))
-
- ;; We need to maintain the modifier flags state constantly to be able to
- ;; implement this; suggest a slot in beagle-port?
- (when (equal #$NSFlagsChanged event-type)
-;;; (format *debug-io* "In event-build (flags changed)~%")
- ;; Use the 'old' 'modifiers' in conjunction with the new 'modifier-state'
- ;; to work out if this is a key up or a key down...
- (setf return-event
- (destructuring-bind (event-class key)
- (current-mods-map-to-key (send event 'modifier-flags))
- (make-instance event-class
- :key-name key
- :key-character nil
- :x 0
- :y 0
- :graft-x 0
- :graft-y 0
- ;; Irrespective of where the key event happened, send it
- ;; to the sheet that has key-focus for the port.
- :sheet (beagle-port-key-focus *beagle-port*)
- :modifier-state (beagle-modifier-to-modifier-state (send event 'modifier-flags))
- :timestamp (incf timestamp)))))
+ :timestamp (incf timestamp)))))
- ;; #$NSHelpRequested- wonder if we can convert this into "user pressed help key" key event?
- ;; Then could pull up docs (or could do if there were any!)
- ;; #$NSCursorUpdate
+ ;; #$NSHelpRequested- wonder if we can convert this into "user pressed help key" key event?
+ ;; Then could pull up docs (or could do if there were any!)
+ ;; #$NSCursorUpdate
- return-event))
+ return-event)))
;;; This has been added to McCLIM and the CLX back end; I'm not sure what it's supposed
;;; to be for. Never mind, add it anyway. defgeneric is in stream-input.lisp
More information about the Mcclim-cvs
mailing list