CLIM mail archive
[Prev][Next][Index][Thread]
Re: double-clicking
#+ACL 4.2
#+clim-2.0
has anyone got a good version of a double-click method? I have one
that's weak, doesn't always behave properly.
I need to be able to dbl-click on a presentation to bring up its
editor-frame (much like the mac does stuff).
I need one with the next month.
thanks for any help!
-- clint
Well, thats what I wrote to hack this. Double clicks are
mapped to gestures with have the :hyper modifier key set,
as this was the best way I could think of to map this
into clim's gesture stuff.
This implementation defines a click to be a double-click if
a) it follows the last click within a short period of time
(i.e., within *Double-Click-Interval*)
b) the click is near the last click
(i.e., nearer than *Double-Click-Radius*)
c) the mouse button and modifiers are the same as with the
last click.
If all these conditions hold, the "hyper-modifer-state" is set.
Note that with this implementation the "two clicks" of a double-click lead to
two pointer-gestures. I.e., if you define a normal single-click gesture
as :select and a double-click gesture as :open, then
when you double-click on a presentation clim will see two gestures:
first a :select gesture and then the :open gesture.
I once had a lengthy discussion on this on the net (with some
misunderstandings), and I dont know how to circumvent this problem.
Moreover, it might not always be a problem e.g., when an object
must be selected before it can be opened (as it is on the mac).
Regards - Stefan B.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Double Clicks
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar *last-button-press-event-time* 0)
(defvar *last-button-press-event-x* 0)
(defvar *last-button-press-event-y* 0)
(defvar *last-button-press-event-button* nil)
(defvar *last-button-press-event-modifier-state* nil)
(defvar *last-button-press-was-double-click* nil)
(defparameter *Double-Click-Interval* (* 1 internal-time-units-per-second))
(defparameter *Double-Click-Radius* 2)
(defun mouse-still-down (stream &optional (start-time
*last-button-press-event-time*)
(wait-time *Double-Click-Interval*))
(let* ((pointer (stream-primary-pointer stream)))
(loop with wait-until = (+ start-time wait-time)
while (and (<= (get-internal-real-time) wait-until)
(/= (pointer-button-state pointer) 0))
finally (return (/= (pointer-button-state pointer) 0)))))
(defmethod clim:queue-event :before ((pane clim:clim-stream-pane)
(event clim:pointer-button-press-event))
(let ((x (pointer-event-x event))
(y (pointer-event-y event))
(button (pointer-event-button event))
(modifier-state (event-modifier-state event))
(radius *Double-Click-Radius*)
(-radius (- *Double-Click-Radius*))
(current-time (get-internal-real-time)))
(when
(setf *last-button-press-was-double-click*
(and (not *last-button-press-was-double-click*)
(eql button *last-button-press-event-button*)
(eql modifier-state *last-button-press-event-modifier-state*)
(<= (- current-time *last-button-press-event-time*) *Double-Click-Interval*)
(<= -radius (- x *last-button-press-event-x*) radius)
(<= -radius (- y *last-button-press-event-y*) radius)
))
(with-slots ((modifier-state clim-silica::modifier-state)) event
(setf modifier-state (logior modifier-state +hyper-key+))))
(setf *last-button-press-event-time* current-time
*last-button-press-event-x* x
*last-button-press-event-y* y
*last-button-press-event-button* button
*last-button-press-event-modifier-state* modifier-state)))
(defun double-click-p ()
*last-button-press-was-double-click*)
;;; example: the :open-gesture maps to a double-left-click
(define-gesture-name :open
:pointer-button
(:left :hyper))
;;; - Stefan Bernemann (berni@iml.fhg.de)
Main Index |
Thread Index