@setfilename ../info/events
@node Events, X11 Primitives, Buttons, top
@chapter Events

Epoch provides the ability to handle X window system events in Elisp.

@menu
* Event Basics::                Introduction to events
* Basic Event Handling::	Basic Event Handling
* Property Change Events::	Property Change Events
* Client Message Events::	Handling Client Messages
* Mouse Events::		Mouse Events
* Motion Events::		Motion Events
* On Event Handling::           One-shot handlers
@end menu

@node Event Basics, Basic Event Handling, Events, Events
@section Event Basics

@cindex event queue
@cindex event key
@cindex event value
@cindex event screen
@dfn{Events} are the mechanism the X window system uses to communicate
with client programs (such as Epoch). Certain types of X events, listed
below,  are stored into a queue, the @dfn{event-queue}. 
Whenever such an event is received by Epoch, it is stored
in the event-queue, and an @dfn{event-key} is inserted into the keyboard 
buffer. Whenever the keyboard is checked for keys, these event keys are read
and processed until there are none left or an actual key is encountered. 
For each of these event, the variable @code{epoch::event} is bound to the 
value of the event, and the event handler @code{epoch::event-handler} is 
called.  (@xref{Basic Event Handling} to learn more about that subject.)
Each event is returned as a vector of 3 elements.  The first is the
event type, the second is data associated with the event, and the third
is the screen on which the event occured.

@cindex event types
Epoch currently captures the events described in the following table:

@group
@table @code
@item Event
Data

@item focus
@code{t} for focus-in, @code{nil} for focus-out

@item property-change
@cindex property-change event
If @code{epoch::lazy-events} is @code{nil}, then a cons pair.  Car is
name of property (a string), cdr is new value of property. Otherwise,
the value is just the X-atom resource of the property.  
(@xref{Property Change Events})

@item map
@cindex map and unmap events
@code{t} for map, @code{nil} for unmap

@item move
@cindex move event
Cons pair:  x-position, y-position in pixels

@item resize
@cindex resize event
List of 3 elements: new width, new height, outer borderwidth

@item client-message
@cindex client message event
A triple of the form @code{(@var{TYPE} @var{FROM} . @var{DATA})}.  See
description of @code{epoch::send-client-message} below for an
explanation.  (@xref{Client Message Events}).

@item button
@cindex button event
A 5-tuple of form @code{(@var{Press/Release x-coord y-coord button
mod-state})}.  (@xref{Mouse Events})

@item motion
@cindex motion event
A triplet of the form @code{(@var{x-coord y-coord mod-state})}.
(@xref{Motion Events}).

@end table
@end group

@cindex asynchronous communication
To support asynchronous communication through events, Epoch
provides primitives to set and read X Properties (@xref{X Properties}), 
and a property event handler.  Primitives are also provided to send 
client messages.

Client messages are sent through the @code{epoch::send-client-message}
function and received through events of type @code{client-message}.

@defvar epoch::lazy-events
If this variable is non-@code{nil}, then the internal event code will do as
little work as possible. Primarily, property events will only report
the atom of the property changed, and leave it up to other code to
acquire the value if desired.  (@xref{Property Change Events})
@end defvar


@defvar epoch::mouse-events
If this variable is non-@code{nil}, then mouse events are placed into
the Epoch event queue instead of generating fake key strokes.
@end defvar


@node Basic Event Handling, Property Change Events, Event Basics, Events
@section Basic Event Handling
@cindex event handler errors

Events are handled by binding the variable @code{epoch::event-handler} to
a function of no arguments. Whenever an event is dispatched as described
above, if @code{epoch::event-handler} is non-@code{nil}, the value in it
is called as a no argument function. This function should then examine the
value of @code{epoch::event} and take appropriate action.

If any error occurs while the event handler is being executed, then the
behaviour depends on the value of the variable
@code{epoch::event-handler-abort}.  If this is @code{t}, then the
@code{event-handler} is aborted by resetting the variable to @code{nil}.
This action prevents runaway errors on every following event.  If the
variable @code{epoch::event-handler-abort} is @code{nil} then this
action is not taken.

In order to make event handling easier, a standard set of event handling
functions are provided.  These provide a (somewhat) widget-like interface to
events.  Selected parts of the interface can be replaced without change to the
underlying internals.   Event handling is organized hierarchially -- the top
level handler invokes other handlers to dispatch the final handling
routines.  The following description is from the top down.

The basic event handler maintains an internal alist to associate event
types with event handlers.  An @dfn{event type} is the symbolic name
corresponding to a class of X events.  An @dfn{event handler} is an elisp
function that may be called when an event occurs.

For each event type, a stack of event handlers is kept, and when an
event of that type occurs, the function at the top of the stack is
called with arguments showed below.  This allows you to change the event 
handler behaviour in a restorable way.  Each basic event type must be 
installed before any events will be dispatched for it; this allows 
events to be globally disabled and reenabled.  Currently the Epoch elisp files
(@pxref{Packages}) install all supported events.  

When the basic handler runs, @code{epoch::event-handler-abort} is initially
set to @code{t}.  It then watches for errors during the dispatch of an event,
which are detected by checking @code{epoch::event-handler} after
returning from the dispatch.  If @code{epoch::event-handler} has been
set to @code{nil}, an error is presumed to have occured, and
@code{ignore-event} is called on that event.  This provides improvements
over the built-in system, in that only a particular type of event is
ignored (others continue to dispatch), and service can be restored with
a simple @code{(resume-event @var{event})}, independent of the actual
names of the handlers.  This also means that handlers can now be anonymous,
i.e.  @code{push-event} can be passed a @code{lambda} expression instead
of the symbol name of a function.

Event handler functions should be defined as follows:

@example
(defun my-event-handler (@var{event-type} @var{value} @var{screen})
  "@var{event-type} is the type of the event.  @var{value} is the value of
the event, and @var{screen} is the screen which received the event.
Handlers can call the event handling interface routines, so that a
one-shot handler (which pops itself) can be set up."
  )
@end example

The following functions and variables form the interface to the event
handling system.


@defvar epoch::event-handler
Variable that contains @code{nil} or a function to be called when there
are pending property change events. The handler should use the variable
@code{epoch::event} to retrieve the current event.  If 
@code{epoch::event-handler} has been set to @code{nil} after an event has been
dispatched, an error is presumed to have occured (see above).
@end defvar

@defvar epoch::event
Just before the event handler in @code{epoch::event-handler} is called, this
variable is bound to the value of the event that caused the handler call.
It is a vector of size three, consisting of the event type, the event value,
and the screen where the event occurred.
@end defvar

@defvar epoch::event-handler-abort
If this variable is non-@code{nil}, then if an error occurs while the
event handler is running, @code{epoch::event-handler} is set to @code{nil}.
This prevents an error in some part of the event handler code from causing
Epoch to lock up with excessive errors.
@end defvar

@defun epoch::get-event
@cindex internal event queue
All events are stored in an internal event queue. This primitive returns the
oldest event in the event queue as an Elisp vector of size three. The
zeroth element is the type of the event, the first element is the value
of the event, and the second element is the screen on which the event
occurred. @b{OBSOLETE}
@end defun

@defun install-event event
This puts @var{event} into the handler alist.  @var{event} can be anything,
but unless it is @code{eq} to an event type, it will never be dispatched;
instead it will be ignored.
@end defun

@defun remove-event event
Removes @var{event} from the handler alist.  All handlers associated with it
are lost.
@end defun

@defun push-event event handler
Installs @var{handler} for @var{event}.  Handlers are installed in a stack,
and the handler at the top of the stack is dispatched for the event.
@end defun

@defun pop-event event
Removes and returns the top level handler for @var{event}.
@end defun

@defun ignore-event event
Pushes a marker onto the handler stack for @var{event} so that the event is
not dispatched.
@end defun

@defun resume-event event
@cindex event inhibition
Pops the ignore marker from the top of the handler stack for @var{event}.
Note that these two functions are different from  @code{remove-event} and
@code{install-event} in that these allow temporary, transparent inhibition of
events in a local area, while the latter have global effects.
@end defun

@defun display-event-status
@kindex C-Z e
Print the current event handler status into a buffer and display it in a
window on the current screen.  Normally bound to @kbd{C-z e}.  The
status keys are @kbd{H} for being handled, @kbd{I} for ignored, and
@kbd{U} for uninstalled.  If a number follows the letter, that is the
depth of the handlers or ignore markers.
@end defun


@node Property Change Events, Client Message Events, Basic Event Handling, Events
@section Property Change Events
@cindex property-change events
@cindex property X-agom

The Epoch elisp files set up a handler for the @code{property-change}
event which then dispatches based on the property, in a manner analagous
to the basic event handling.  This property event handler uses @dfn{lazy
events} (see @code{epoch::lazy-events} in @xref{Basic Event Handling}.)
This means that a property change event has a value of just the X-atom
resource corresponding to the property that changed.

@quotation
Implementation note: Property events are passed as lazy events to save
the expense of unneeded round-trip server requests.  With non-lazy
events, all property events would involve 2 round-trip requests, one for
the atom and another for the value.  However, most property events are
not handled, and so such information is simply thrown away.  With this
system, only those property events that are actually dispatched invoke
this expense, and in many cases the name of the property is unnecessary.
(If the handler function is attached to only one property, then it
implicitly knows the property name value.)  The primitive @code{equal} has
been extened to provide comparisons for X-Resources @xref{X Resources}.
@end quotation

Each installed property is stored as the X-atom resource and a stack of
handlers.  If the top entry is a function, then it is called with the
same parameters as for basic event handling.  (The event type will
always be @code{property-change}, but this allows a consistent handler
interface for all handler functions.)  If the property is not in the 
alist, or the top entry is not a function, the property change is ignored.

In contrast to basic event handling, if the property is not installed,
pushing the property handler will install it.  The inhibition of
handling for certain properties is not as useful as for events.  Since
the number of possible property events is far larger than the number of
possible event types, the extra hassle of having to seperately install
properties was judged to be too much.  The @code{install-property} and
@code{remove-property} should be used seldom, if at all, and are provided
primarily for conformity with basic event handling.

Property change handler functions should be of the same form as the
general event handlers.  Note that the value of the property change is
passed as an X-atom.  If the value of the property is desired, the
function @code{get-property} can be used.  If the name of the
property is needed, use @code{unintern-atom}.

@cindex menus
One way that property change events can be used is to send messages to
and receive messages from the window manager.  We use this facility
extensively to display menus to the user, change window names and
decorations, etc.  X properties are manipulated and accessed through the
@code{epoch::set-property} and @code{epoch::get-property} functions
(@pxref{X Properties}).

Epoch maintains two properties on the screens automatically.  These are
@code{EPOCH_SCREEN_ID}, which is an integer that is the screen ID, and
@code{EPOCH_CURRENT}, which is a string, either ``yes'' if that screen is
the current edit screen, ``no'' if it is not, or ``minibuf'' if it is
the minibuffer.

The following functions are the interface to the property event
handling system.

@defun install-property property
This puts @var{property} into the handler alist.  @var{property} should be
the name of an X Property (i.e. a string or X Atom).
@end defun

@defun remove-property property
Removes @var{property} from the handler alist.  All handlers associated with it
are lost.
@end defun

@defun push-property property handler
Installs @var{handler} for @var{property}.  Handlers are installed in a stack,
and the handler at the top of the stack is dispatched for the property.
If the property is not already in the handler list, it is added.
@end defun

@defun pop-property property
Removes and returns the top level handler for @var{property}.
@end defun

@defun ignore-property property
Pushes a marker onto the handler stack for @var{property} so that the
property is not dispatched.
@end defun

@defun resume-property property
Pops the ignore marker from the top of the handler stack for @var{property}.
@end defun

@node Client Message Events, Mouse Events, Property Change Events, Events
@section Client Message Events

The Epoch elisp files set up a handler for the @code{client-message}
event which then dispatches based on the message type.  Each installed
property is stored as the X-atom resource and a stack of handlers.  If
the top entry is a function, then it is called, with the same parameters
as for basic event handling.  If the message type is not in the alist,
or the top entry is not a function, the message is ignored.

The value of a client message is a list of ( @var{type} @var{source} .
@var{data} ) where @var{type} is the message type X-atom resource,
@var{source} is an X-window resource specifying the source window, and
@var{data} is the data field of the message converted to Elisp data in
the same manner as X property values (@pxref{X Properties}). To send
client mesages, @pxref{Client Messages}.

If the message type is not installed, pushing a handler will install it.
@code{install-message} and @code{remove-message} should be used seldom, if
at all, and are provided primarily for conformity with basic event
handling.

The following functions are the interface to the client message event
handling system.

@defun install-message message 
This puts @var{message} into the handler alist.  @var{message} should be 
either a string or X Atom.
@end defun

@defun remove-message message
Removes @var{message} from the handler alist.  All handlers associated with it
are lost.
@end defun

@defun push-message message handler
Installs @var{handler} for @var{message}.  Handlers are installed in a stack,
and the handler at the top of the stack is dispatched for the message.
If the message is not already in the handler list, it is added.
@end defun

@defun pop-message message
Removes and returns the top level handler for @var{message}.
@end defun

@defun ignore-message message
Pushes an ignore marker onto the handler stack for @var{message} so that the
message is not dispatched.
@end defun

@defun resume-message message
Pops the ignore marker from the top of the handler stack for @var{message}.
@end defun

@node Mouse Events, Motion Events, Client Message Events, Events
@section Mouse Events
@cindex mouse events
@cindex button events

Mouse events go into the event queue with event type @code{button} 
(which have nothing to do with epoch buttons) and event
value the 5-tuple @code{(@var{press/release} @var{x-coord} @var{y-coord}
@var{button} @var{mod-state})}.  @var{press/release} indicates if the
event was a button press or release; the coordinates are character
coordinates within the screen; @var{button} indicates which button; and
the @var{mod-state} is a bitmask indicating the state of the button modifiers.

@cindex keyboard queue
@b{Note:} Mouse events are only received on the keyboard queue
when @code{epoch::mouse-events} is @code{nil}. This is the default
value, but the Epoch Elisp files set it to @code{t}.

The Epoch Elisp files install a handler for the @code{button} events,
which in turn dispatches functions for each different mouse event.

Mouse event dispatching uses two tables, one global and the other local to 
each buffer.  When a mouse event is dispatched, the local table is checked 
first.  If the table is missing or the entry is @code{nil}, then the 
global table is used.  If a function is found, then it is dispatched.  
The mouse event handler should be defined as follows:

@example
(defun my-mouse-handler (@var{mouse-data})
  "@var{mouse-data} is a list of @code{( @var{point} @var{buffer} @var{window} @var{screen} )}.  
These all refer to the character location
at which the button on the mouse was pressed or released.  Note that at
the time the handler is called,  @i{no} change to point, current buffer,
current window or current screen has been made.  It is entirely up to the
handler how much to change such information.")
@end example

When specifying a particular mouse event, both the mouse button and keyboard
@dfn{modifier} states must be specified, e.g. the middle button with Control.
These values are specified as numbers, but for ease of programming, constants
are defined for them, listed below.

These are the predefined constants for specifying the mouse button:
@table @code
@item Name	
Value

@item mouse-left	
0
@item mouse-middle	
1
@item mouse-right	
2
@end table

These are the predefined constants for specifying the keyboard modifier state.
Names without a trailing @code{-up} signify the down button event.
@table @code
@item Name
Value

@item mouse-down
0
@item mouse-up
1
@item mouse-shift
2
@item mouse-shift-up
3
@item mouse-control
4
@item mouse-control-up
5
@item mouse-control-shift
6
@item mouse-control-shift-up
7
@item mouse-meta
8
@item mouse-meta-up
9
@item mouse-meta-shift
10
@item mouse-meta-shift-up
11
@item mouse-meta-control
12
@item mouse-meta-control-up
13
@item mouse-meta-control-shift
14
@item mouse-meta-control-shift-up
15
@end table

@b{Note:} This version of the mouse handling code is very different from
the previous version, whose main advantage was that it was the same as
regular Emacs.  In that version, the passed argument was a list of the
form @code{(@var{X} @var{Y} @var{screen})} of the mouse event.  This
data was not particularly useful, and had to be converted into more
useful data by actually setting point with the @code{x-mouse-set-point}
call.  A look through the mouse handling code indicated that, in fact, 
every function went ahead and did this in order to calculate the point.

The following functions are modeled after keymaps.

@defun create-mouse-map &optional source-map
Creates a mouse map for use in dispatching.  If @var{source-map} is 
non-@code{nil}, then the contents of that map are copied into the new map.
@end defun

@defun copy-mouse-map source-map dest-map
Copies a mouse map from @var{source-map} to @var{dest-map}.
@end defun

@defun use-local-mouse-map mouse-map &optional buffer
Sets @var{mouse-map} to be the local mouse map in @var{buffer}.
@end defun

@defun kill-local-mouse-map &optional buffer
Removes the local mouse map from @var{buffer}.
@end defun

@defun define-mouse mouse-map button modifier function
Sets the entry in @var{mouse-map} for the mouse @var{button} with
@var{modifier} to be @var{function}.  @var{button} should be one of the
mouse button constants, and @var{modifier} should be one of the button
modifiers.
@end defun

@defun local-set-mouse button modifier function
Sets the entry in the local mouse map for @var{button} and @var{modifier}
to @var{function}.
@end defun

@defun global-set-mouse button modifier function
Sets the entry in the global mouse map for @var{button} and @var{modifier}
to @var{function}.
@end defun

@defun mouse::set-point mouse-data
Sets the point to the value specified in @var{mouse-data}, which should be
the same form as the list passed to mouse handler functions, (@code{point} 
@code{buffer} @code{window} @code{screen})
@end defun

@defun epoch::coords-to-point x y screen
Converts a character (@var{x}, @var{y}) location on a given @var{screen} into a list of the form @code{(point buffer window screen)} or @code{nil} if the location is not on the @var{screen}.
@end defun

@defun mouse::convert-xy-screen xy screen
Converts an (X Y) character position list @var{xy} and a @var{screen}
into a list of @code{(point buffer window screen)} without changing the
current buffer, window, or screen. OBSOLETE - use @code{epoch::coords-to-point}
@end defun


@node Motion Events, On Event Handling , Mouse Events, Events
@section Motion Events
@cindex motion events

Epoch allows the user to receive motion events, which occur when the mouse
moves.  By default this feature is turned off.  It can be enabled in a 
number of ways:

@itemize @bullet
@item  
using command line option @code{-motion}:  makes motion events appear
for all screens.

@item  
using @code{*motion} in resources:  makes motion events appear for
all screens.

@item  
using @code{motion} in the property alist; @code{t} turns on motion
events at screen creation time, @code{nil} disables them.

@item  
using primitive @code{epoch::set-motion-hints}: turns motion events
on or off by screen.

@end itemize

Note that motion events go into the event-queue but must be specifically 
solicited by functions rather than being automatically provided.  
Each time you execute a function affecting the mouse, 
(for example @code{epoch::query-pointer}), the next motion event 
(if any) is sent to the primitive.  This prevents motion events from coming so 
fast that Epoch would thrash to death.

The relevent primitives are:

@defun epoch::motion-hints-p &optional screen
Returns @code{t} or @code{nil} for @var{screen} (default: current screen)
depending if motion events are enabled or disabled for that screen.
@end defun

@defun epoch::set-motion-hints flag &optional screen
Flag must be @code{t} or @code{nil}; enables or disables motion hints for
@var{screen} (default: current screen).
@end defun

@node On Event Handling , , Motion Events, Events
@section On Event Handling
@cindex on event handling
@cindex one-shot event handlers

As part of the standard event handling, a facility to install one-shot
handlers for events on particular screens is provided. After the action
function has been called for the particular event, it is removed.

@defun on-map-do screen action
On the next map event for @var{screen}, call @var{action} with a single
argument that is the screen of the event.
@end defun

@defun on-unmap-do screen action
On the next unmap event for @var{screen}, call @var{action} with a
single argument that is the screen of the event. 
@end defun

@defun on-move-do screen action
On the next move event for @var{screen}, call @var{action} with 2
arguments, the screen and the move event value.
@end defun

@defun on-resize-do screen action
On the next resize event for @var{screen}, call @var{action} with 2
arguments, the screen and the resize event value.
@end defun
