12.2 Receiving input from the user

The CAPI supports receiving input from the user through the use of an
input model
, which is a mapping of events to the callbacks that should be run when they occur. The input model is specified by the initarg :input-model.

When the event callback is called, it gets passed the output-pane and the
x
and
y
integer coordinates of the mouse pointer at the time of the event. A few events also pass additional information as necessary; for example, keyboard events also pass the key that was pressed.

For example, we can create a very simple drawing pane by adding a callback to draw a point whenever the left button is dragged across the pane. This is done as follows:

(contain

(make-instance

'output-pane

:input-model '(((:motion :button-1)

gp:draw-point))))

Figure 12.3 An interactive output pane

The input model above seems quite complicated, but it is just a list of event to callback mappings, where each one of these mappings is a list containing an event specification and a callback. An event specification is also a list containing keywords specifying the type of event required.

12.2.1 Detailed description of the input model

The input model provides a means to get callbacks on mouse, keyboard and touch gestures in an output-pane. An
input-model
is a list of mappings from gesture to callback, where each mapping is a list

(
gesture
callback
.
extra-callback-args
)

gesture
specifies the type of gesture, which can be Gesture Spec, character, button, modifier change, key, command, cursor motion or multi-touch. These are described in the following sections. User input is processed as described in Processing user input.

Note:
it is recommended you follow the style guidelines and conventions of the platform you are targeting when mapping gestures to callbacks.

12.2.1.1 Gesture Spec mappings

In a Gesture Spec mapping,
gesture
can be simply the keyword :gesture-spec, which matches any keyboard input. For specific mappings,
gesture
is a list

(:gesture-spec
data
[modifier]*
)

in which
data
is a character object or an integer between 0 and char-code-limit (interpreted as the character object obtained by code-char), or a keyword naming a function key, and each
modifier
is one of the keywords :shift, :control and :meta. Note that the modifier :meta is received only when the keys style is :emacs (see interface-keys-style).

Also
data
can be a string which is interpreted as a Gesture Spec as if by sys:coerce-to-gesture-spec. See the
LispWorks User Guide and Reference Manual
for a description of this and other functions for manipulating Gesture Spec objects.

12.2.1.2 Character mappings

In a character mapping,
gesture
can be simply the keyword :character, which matches any character input. For specific mappings,
gesture
can be a list containing a single character object
char
, or a list

(
char
)

Note:
where input would match both a Gesture Spec mapping and a character mapping, the Gesture Spec mapping takes precedence.

Note:
in LispWorks 7.0 and later versions the cl:character type does not support the bits attribute. To represent keyboard input with modifier keys, see Gesture Spec mappings.

12.2.1.3 Button mappings

In a button mapping,
gesture
should be list

(
button
action
[modifiers]*
)

where
button
is one of :button-1, :button-2 or :button-3 denoting the mouse buttons.
action
is one of :press, :release, :second-press, :third-press, :nth-press and :motion, and each
modifier
is one of the keywords :shift, :control, :meta and :hyper. The :meta modifier will be the Alt key on most keyboards. On Cocoa, the :hyper modifier is interpreted as the Command key for button and motion gestures. On Windows, the :hyper modifier is currently never generated, so gesture mappings using it will never be invoked.:third-press and :nth-press are supported only on Cocoa and Motif.

Button mappings with
action:nth-press are matched on the nth button click made in quick succession, but only when there is not a more specific match with :press, :second-press or :third-press. The callback for :nth-press receives an extra argument which is the count of clicks.

12.2.1.4 Modifier change mappings

In a modifier change mapping,
gesture
is :modifier-change, which generates a callback whenever the state of a modifier (Control, Shift and Meta key, Command on Cocoa, and Caps Lock) changes.

The
callback
is called with the output pane,
x
and
y
, an integer
mods
, followed by
extra-callback-args
if any.
mods
is calculated as a logior of sys:gesture-*-bit values. The bits that that may be set in
mods
are:

sys:gesture-spec-shift-bit

sys:gesture-spec-control-bit

sys:gesture-spec-meta-bit

sys:gesture-spec-hyper-bit

sys:gesture-spec-caps-lock-bit

Note that sys:gesture-spec-hyper-bit is set when Command is pressed.

Note that for Caps Lock, the callback is generated when the state of the Caps Lock changes, not when the Caps Lock key is pressed or released.

The pane gets the callback only when it has the focus. If the pane receives the focus and the state of the modifiers is different from what it was the last time the pane had the focus, a callback is generated at that time. That means that tracking the state using the callback is reliable while the pane has the focus, but not while the pane does not have the focus.

12.2.1.5 Key mappings

Key mappings are intended for detecting low-level keyboard input. In a key mapping,
gesture
should be a list

(:key [
keyname]
action [
modifiers]*)

where the optional
keyname
is a character naming a key (no modifiers) or one of the valid Gesture Spec keywords,
action
is one of :press or :release and each modifier is one of the keywords :shift, :control and :meta. The callback will receive a Gesture Spec object, with its data set to an integer ASCII code or a keyword representing the primary item on the key and its modifiers representing the set of modifiers pressed. The :meta modifier will be the Alt key on most keyboards. On Cocoa, the :hyper modifier is interpreted as the Command key for :key input.

12.2.1.6 Motion mappings

In a motion mapping,
gesture
can either be defined in terms of dragging a button (in which case it is defined as a button gesture with
action:motion), or it can be defined for motions while no button is down by just specifying the keyword :motion with no additional arguments.

12.2.1.7 Command mappings

In a command mapping, gesture should be a command which is defined using define-command, and provides an alias for a gesture. The following commands are predefined:

:post-menu

(:button-3 :release) on Microsoft Windows.

(:button-3 :press) on Motif.

(:button-1 :press :control) on Mac OS X.

:control-post-menu

(:button-3 :press :control) on Microsoft Windows, Motif and Mac OS X.

:keyboard-post-menu

(:gesture-spec :f10 :shift) on Microsoft Windows, Motif and Mac OS X.

12.2.1.8 Touch mappings

On Cocoa and Windows
input-model
can contain mappings for multi-touch gestures from devices that can generate them (trackpad or touchscreen). These include zoom, rotate, pan, swipe (Cocoa only), two finger tap (Windows only), press and tap (Windows only), and beginning and end of sequences of gestures.

In a touch mapping
gesture
should be of the form:

(:touch
multi-touch-keyword
)

where
multi-touch-keyword
specifies the type of gesture as listed below. For all multi-touch gestures the callback receives as arguments the
pane
, and the
x
and
y
of the event. There are also an additional one or two arguments for each specific gesture. The extra arguments are always relative to the previous state, so each event can be interpreted on each own. Use
extra-callback-args
if any are added in the end.

multi-touch-keyword
should be one of:

:zoom

The callback receives an extra argument which is the zoom factor.

:rotate

The callback receives an extra argument which is the angle to rotate, anti-clockwise in radians.

:pan

The callback receives two extra arguments, the
delta-x
and
delta-y
, which are the amount to scroll in the
x
and
y
directions.

:swipe

The callback receives an extra argument which is one of the keywords :left, :right, :up or :down.

:swipe is supported only on Cocoa.

:two-finger-tap

The callback receives an extra argument which is the distance between the fingers.

:two-finger-tap is supported only on Windows.

:press-and-tap

The callback receives two extra arguments, which are the
delta-x
and
delta-y
of the tapping finger from the resting finger.

:press-and-tap is supported only on Windows.

:begin-end

The callback receives an extra argument
begin-p
which is a boolean, t for beginning of a sequence of events and nil for end. The beginning and end of sequences are determined by the underlying device implementation, which tries to identify what the user regards as a single operation.

12.2.1.9 Notes about touch mappings

Because the callbacks receive relative values, you do not need the :begin-end events to interpret them. These events are useful when you want to do things which correspond to user operations, for example recording a state for undo or committing a change.

They are also useful if you want to restrict the type of events that are processed inside each operation. For example, your pane may have a flag that the callbacks check and set which is used to allow only one kind of gesture to have an effect in each sequence.

The
x
and
y
coordinates are the coordinates which should be used as the center of operation. On Windows, you can track the
x
and
y
in :zoom and :rotate events, and do panning while rotating or zooming.

On Cocoa, a sequence of events (starting and ending with :begin-end events) can contain either :zoom and :rotate events or :pan events, but not a mixture of :pan and :rotate or :zoom. On Windows all these three types of events can be mixed in principle.

:swipe events (Cocoa only) are three finger brushing. :swipe events are always on their own, and are not enclosed in pairs of :begin-end callbacks.

On Cocoa, pan should generally act as a scrolling gesture, so normally you should not need to use it.

12.2.1.10 Processing user input

When user input matches a gesture
gesture
, the
callback
is called with the gesture callback arguments followed by any user-supplied
extra-callback-args
.

The gesture callback arguments contain three standard arguments, and for some gestures there is a fourth argument. The standard three arguments are:

output-pane
x
y

where (
x
,
y
) is the cursor position.

The following gestures have a fourth argument:

:gesture-spec

:key

A gesture-spec representing the user input.

:character

character

A character representing the user input.

:modifier-change

An integer specifying the modifiers as logior of sys:gesture-spec-*-bit.

Button with :nth-press

An integer which is the number of clicks.

Note:
mouse gestures with :press, :second-press, :third-press and :nth-press actions can each be expected to be followed by a :release action.

Note:
In some circumstances :motion events can be received even when the output-pane does not have the input focus. See window style :motion-events-without-focus under interface for details.

input-model
can be set before the pane is displayed, but changes after that are ignored.

In particular, cl:initialize-instance is the natural place for subclasses to modify the existing
input-model
, using the output-pane accessor output-pane-input-model. Note that since the mappings are processed in order, prepending to an existing
input-model
overrides it when there are clashes, while appending affects only gestures for which the original
input-model
did not have a match..

12.2.2 Commands - aliases

It is possible to define aliases for gestures (called "commands"), which is mapping between a gesture and a command (a unique Lisp object, typically a keyword). The command then can be used as the
gesture
in an
input-model
. That allows changing the actual user gesture to invoke the callbacks that are associated with the command in input models of many panes, without having to change the actual input model specifications.

A command is defined using define-command, which defines the mapping, and can also specify on which library it is applicable and a translator to change the arguments that are passed to the callback.

12.2.3 Native input method

The input that CAPI sees may be pre-processed by a native input method. Native input methods are part of the underlying GUI system which allow the user to enter characters that do not appear on the keyboard. On GTK+ you can control whether the native input method is used by the output-pane initarg :use-native-input-method, and you can specify the default by set-default-use-native-input-method.

12.2.4 Composition of characters

Composition of characters is done by the underlying window system, which combines several keystrokes to one character (or more rarely, to several characters) , and is used to input characters that are not available on the keyboard. output-pane has a callback, :composition-callback, which is called when composition starts and ends, and also if the pane is supposed to display the input, it is called to tell it what to display.

Inside the callback call for starting composition, the function set-composition-placement where relative to the composition should, which tells the system where to put any window that it popups to interact the user. For example, editor-pane uses this to set the placement at the position of the cursor.