15.5 Pointer Tracking

Summary: The
tracking-pointer
macro provides a general means for running code while following the position of a pointing device and monitoring for other input events. The programmer supplies code (the clauses in
body
) to be run upon the occurrence of any of the following types of events:

Motion of the pointer

Motion of the pointer over a presentation

Clicking or releasing a pointer button

Clicking or releasing a pointer button while the pointer is over a presentation

Keyboard event (typing a character)

The
stream
argument is not evaluated, and must be a symbol that is bound to an input sheet or stream. If
stream
is
t
,
*standard-output*
is used.
body
may have zero or more declarations as its first forms.

The
pointer
argument specifies a pointer to track. It defaults to the primary pointer for the sheet, (
port-pointer
stream
).

When
multiple-window
is
t
, the pointer will be tracked across multiple windows; when
nil
, it will be tracked only in the window corresponding to
stream
.

When the boolean
transformp
is
t
, then the coordinates supplied to the
:pointer-motion
clause will be in the "user" coordinate system rather than in stream coordinates; that is, the medium's transformation will be applied to the coordinates.

context-type
is used to specify the presentation type of presentations that will be "visible" to the tracking code for purposes of highlighting and for the
:presentation
,
:presentation-button-press
, and
:presentation-button-release
clauses. Supplying
context-type
is only useful when
sheet
is an output recording stream.
context-type
defaults to
t
, meaning that all presentations are visible.

When
highlight
is
t
,
tracking-pointer
will highlight applicable presentations as the pointer is positioned over them.
highlight
defaults to
t
when any of the
:presentation
,
:presentation-button-press
, or
:presentation-button-release
clauses is supplied; otherwise, it defaults to
nil
.

The body of
tracking-pointer
consists of a list of clauses. Each clause is of the form
(clause-keyword arglist . clause-body)
and defines a local function to be run upon occurrence of each type of event. The possible values for
clause-keyword
and the associated
arglist
are:

:pointer-motion
(
&key
window x y)
Defines a clause to run whenever the pointer moves. In the clause,
window
is bound to the window in which the motion occurred, and
x
and
y
to the coordinates of the pointer. (See the keyword argument
:transformp
for a description of the coordinate system in which
x
and
y
are expressed.)

:presentation
(
&key
presentation window x y)
Defines a clause to run whenever the pointer moves over a presentation of the desired type. (See the keyword argument
:context-type
for a description of how to specify the desired type.) In the clause,
presentation
is bound to the presentation,
window
to the window in which the motion occurred, and
x
and
y
to the coordinates of the pointer. (See the keyword argument
:transformp
for a description of the coordinate system in which
x
and
y
are expressed.)

When both
:presentation
and
:pointer-motion
clauses are provided, the two are mutually exclusive. The
:presentation
clause will run only if the pointer is over an applicable presentation; otherwise the
:pointer-motion
clause will run.

:pointer-button-press
(
&key
event x y)
Defines a clause to run whenever a pointer button is pressed. In the clause,
event
is bound to the pointer button press event. (The window and the coordinates of the pointer are part of
event
.)

x
and
y
are the transformed
x
and
y
positions of the pointer. These will be different from
pointer-event-x
and
pointer-event-y
if the user transformation is not the identity transformation.

:presentation-button-press
(
&key
presentation event x y)
Defines a clause to run whenever the pointer button is pressed while the pointer is over a presentation of the desired type. (See the keyword argument
:context-type
for a description of how to specify the desired type.) In the clause,
presentation
is bound to the presentation, and
event
to the pointer button press event. (The window and the stream coordinates of the pointer are part of
event
.)
x
and
y
are as for the
:pointer-button-press
clause.

When both
:presentation-button-press
and
:pointer-button-press
clauses are provided, the two clauses are mutually exclusive. The
:presentation-button-press
clause will run only if the pointer is over an applicable presentation; otherwise, the
:pointer-button-press
clause will run.

:pointer-button-release
(
&key
event x y)
Defines a clause to run whenever a pointer button is released. In the clause,
event
is bound to the pointer button release event. (The window and the coordinates of the pointer are part of
event
.)

x
and
y
are the transformed
x
and
y
positions of the pointer. These will be different from
pointer-event-x
and
pointer-event-y
if the user transformation is not the identity transformation.

:presentation-button-release
(
&key
presentation event x y)
Defines a clause to run whenever a pointer button is released while the pointer is over a presentation of the desired type. (See the keyword argument
:context-type
for a description of how to specify the desired type.) In the clause,
presentation
is bound to the presentation, and
event
to the pointer button release event. (The window and the stream coordinates of the pointer are part of
event
.)
x
and
y
are as for the
:pointer-button-release
clause.

When both
:presentation-button-release
and
:pointer-button-release
clauses are provided, the two clauses are mutually exclusive. The
:presentation-button-release
clause will run only if the pointer is over an applicable presentation; otherwise, the
:pointer-button-release
clause will run.

:keyboard
(
&key
gesture)
Defines a clause to run whenever a character is typed on the keyboard. In the clause,
gesture
is bound to the keyboard gesture corresponding to the character typed.

Summary: Enters an interaction mode in which the user moves the pointer and
output-record
"follows" the pointer by being dragged on the output recording stream
stream
. By default, the dragging is accomplished by erasing the output record from its previous position and redrawing at the new position.
output-record
remains in the output history of
stream
at its final position.

The returned values are the final
x
and
y
positions of the pointer, and the delta-x and delta-y position of the mouse with respect to the origin of the object at the time it was originally selected by the pointer.

The boolean
repaint
controls the appearance of the windows as the pointer is dragged. If
repaint
is
t
(the default), displayed contents of windows are not disturbed as the output record is dragged over them (that is, those regions of the screen are repainted). If it is
nil
, then no repainting is done as the output record is dragged.

erase
identifies a function that will be called to erase the output record as it is dragged. It must be a function of two arguments, the output record to erase and the stream; it has dynamic extent. The default is
erase-output-record
.

feedback
allows the programmer to identify a "feedback" function of seven arguments: the output record, the stream, the initial
x
and
y
position of the pointer, the current
x
and
y
position of the pointer, and a drawing argument (either
:erase
or
:draw
). It has dynamic extent. The default is
nil
, meaning that the feedback behavior will be for the output record to track the pointer. (The
feedback
argument is used when the programmer desires more complex feedback behavior, such as drawing a "rubber band" line as the user moves the mouse.) Note that if
feedback
is supplied,
erase
is ignored.

If the boolean
finish-on-release
is
nil
(the default),
drag-output-record
is exited when the user presses a pointer button. When it is
t
,
drag-output-record
is exited when the user releases the pointer button currently being held down.

Summary: This macro is used by functions that want to move output records in an interactive fashion in a CLIM window. The body of the macro invocation contains code to draw a CLIM graphic. The resulting graphic tracks mouse motion in the window until the mouse button is pressed (or released, depending on the options).

body
is evaluated inside of
with-output-to-output-record
to produce an output record for the stream
stream
, and then invokes
drag-output-record
on the record in order to drag the output. The output record is not inserted into
stream
's output history.

The returned values are the final
x
and
y
positions of the pointer, and the delta-x and delta-y position of the mouse with respect to the origin of the object at the time it was originally selected by the pointer.

The
stream
argument is not evaluated, and must be a symbol that is bound to an output recording stream stream. If
stream
is
t
(the default),
*standard-output*
is used.
body
may have zero or more declarations as its first forms.

Summary: This function is used to place a rubber-band line. The input is the end points of a rubber-band line on the stream
stream
(which defaults to
*standard-input*
) via the pointer
pointer
.

If
start-x
and
start-y
are provided, the start point of the line is at (
start-x,start-y
). Otherwise, the start point of the line is selected by pressing a button on the pointer.

The
pointer
argument specifies a pointer from which to take input. It defaults to (
port-pointer
stream
).

When the boolean
multiple-window
argument is
t
, input can be taken from a window other than the default window. However, input cannot be taken from more than one window at the same time. For instance, you cannot press the pointer button in one window to begin the line and release it in another window to indicate the end point of the line; the press and release must happen in the same window.

When the boolean
finish-on-release
is
t
, pointer-place-rubber-band-line* is exited when the user releases the pointer button currently being held down. When it is
nil
, pointer-place-rubber-band-line* is exited when the user presses a pointer button.

pointer-place-rubber-band-line*
returns five values: the start X and Y of the line, the end X and Y of the line, and the window on which the line was drawn. The final value is useful only when
multiple-window
is
t
.

pointer-input-rectangle*[Function]

Arguments:
&key
left top right bottom stream pointer multiple-window finish-on-release

Summary: This function is used to input a rectangle via the pointer
pointer
. The input is the corners of a rectangle on the stream
stream
, which defaults to
*standard-input*
.

If
left
and
top
are provided, the upper left corner of the rectangle will be placed at (
left,top
). If
right
and
bottom
are provided, the lower right corner of the rectangle will be placed at (
right,bottom
). Otherwise, the upper left corner of the rectangle is selected by pressing a button on the pointer.

pointer
,
multiple-window
, and
finish-on-release
are as for
pointer-place-rubber-band-line*
.

pointer-input-rectangle*
returns five values: the left, top, right, and bottom corners of the rectangle, and the window on which the rectangle was drawn. The final value is useful only when
multiple-window
is true.