I am working with SBCL for Linux on an AMD64 machine.
Function ANIMTEST instantiates an LTK window with a CANVAS widget. Two items, BARRIER and FOLLOWER, live in the canvas. Both spin continuously, with BARRIER at the center of the canvas and FOLLOWER intended to follow the mouse, which is not working as intended. My first attempt (see comment) resulted in absolute screen coordinates of the mouse being interpreted as relative coordinates within the canvas with no account of the offset between the two. After searching through ltk.lisp and docs, I found SCREEN-MOUSE-X/Y (Second Attempt, see comment). I feel like I am using SCREEN-MOUSE-X & -Y according to the documentation, but why is it not working?
= Note =
The file that contains ANIMTEST and the packages that support it load and run with no errors.
Functions I have defined (UCTK-BEAM, etc.) are tested and run fine.
(defun animtest ()
"Test a spinning figure in LTK"
(with-ltk ()
(let* ((cnvs (make-instance 'canvas :width 400 :height 400))
(barrier (uctk-beam 200 200 40 20))
(follower (uctk-beam 0 40 40 20))
(slp-time 50) ; in ms
(bar-theta 0)
(fol-theta 0))
(labels ((update ()
(draw barrier nil)
(draw follower nil)
(incf bar-theta (/ pi 15))
(incf fol-theta (/ pi 15))
(geo:set-theta barrier bar-theta)
(geo:set-theta follower fol-theta)
(geo:set-center follower
;== FIRST ATTEMPT ==
(cons (screen-mouse-x cnvs)
(screen-mouse-y cnvs)))
; == SECOND ATTEMPT ==
;(cons (canvasx cnvs (screen-mouse-x cnvs))
; (canvasy cnvs (screen-mouse-y cnvs))))
(after slp-time #'update)))
(pack cnvs :fill :both :expand 1)
(update)))))
Thanks in advance!
To grab the mouse position in a canvas widget, I don’t call the
screen-mouse functions, but rather bind the motion and button press
events. The callback gets passed the event structure which contains
the slots event-x and event-y which are canvas coordinates. Not only
are you getting the right values directly this way, but also it is
more efficient, as you don’t have to poll the mouse position – you get
updates automatically when it changes. In your case you could either
choose to update the barrier on mouse-move or alternatively, just
store the mouse coordinates in a variable you read inside your update
loop.