
@node Event Handling
@chapter Event Handling

Events are sent from the X server to the X client.  Most of the event
types deal with user input, but there are also event types used for
inter-client communication.

Most X applications are built around an event loop, where the client
waits for the server to send events.  The client responds to the events,
typically by doing one or more X requests.

@menu
* Getting Events::    Waiting for events.
* Selecting Events::  Selecting interesting events.
* Event Types::       Details on all event types.
* Sending Events::    Clients sending events to other clients.
@end menu


@node Getting Events
@section Getting Events

Events can be sent at any time, not necessarily when the client is ready
to recieve an event. Therefore they must be stored temporarily from that
they are read from the network until the client is ready to handle them.
Read but unhandled events are stored on an event queue in the Display
object.  There are two functions to access this queue:

@defmethod Display next_event ( )

Return the next event in the event queue.  If the event queue is empty,
block until an event is read from the network, and return that one.

@end defmethod

@defmethod Display pending_events ( )

Return the number of events which can be returned without blocking.

@end defmethod


A trivial event loop would simply loop infinitely, waiting for an
event and then handling it.  It could look like this:

@example
while 1:
   event = disp.next_event()
   handle_event(event)
@end example


However, most applications need more control, e.g. to simultaneously
handle a network connection or at regular intervals schedule timeouts.
The module @code{select} is often used for this.  @code{Display} objects
can be used with @code{select}, since they have the required
@code{fileno()} method.  When @code{select} indicates that a
@code{Display} object is ready for reading, that means that the server
has sent some data to the client.  That alone doesn't guarantee that an
entire event has arrived, so one must first use @code{pending_events()}
to make sure that @code{next_event()} will return without blocking.  A
simple event loop which waits for events or a one-second timeout looks
like this:

@example
while 1:
    # Wait for display to send something, or a timeout of one second
    readable, w, e = select.select([disp], [], [], 1)

    # if no files are ready to be read, it's an timeout
    if not readable:
        handle_timeout()

    # if display is readable, handle as many events as have been recieved
    elif disp in readable:
        i = disp.pending_events()
        while i > 0:
            event = disp.next_event()
            handle_event(event)
            i = i - 1

    # loop around to wait for more things to happen
@end example


@node Selecting Events
@section Selecting Events

To avoid flooding the clients with events in which they have no
interest, they must explicitly tell the server which events they are
interested in.  This is done by providing the @code{event_mask}
attribute when creating windows with @code{Window.create_window} or in
calls to @code{Window.change_attributes}.  The value of this attribute
is a mask of all types of events the client is interested in on that
particular window.  Whenever the server generates an event for a window
which matches the clients event mask on that window, the event will be
sent to the client.

The following table lists all event masks and the corresponding event
types and classes.  All event masks and types are integer constants
defined in the module @code{Xlib.X}.  Classes have the same name as the
event type, and are defined in @code{Xlib.protocol.event}.

@multitable {SubstructureRedirectMask} {VisibilityNotify} {Colormap changed or installed}

@item @strong{Mask} @tab @strong{Type and Class} @tab @strong{Generated when}

@item ButtonMotionMask @* Button1MotionMask @* Button2MotionMask @* Button3MotionMask @* Button4MotionMask @* Button5MotionMask
  @tab MotionNotify
  @tab Pointer moved with any or a certain button down

@item @tab @tab
  
@item ButtonPressMask	@tab ButtonPress
  @tab Pointer button pressed

@item ButtonReleaseMask	@tab ButtonRelease
  @tab Pointer button released

@item @tab @tab
  
@item ColormapChangeMask @tab ColormapNotify
  @tab Colormap changed or installed

@item @tab @tab
  
@item EnterWindowMask @tab EnterNotify
  @tab Pointer enters window

@item LeaveWindowMask @tab LeaveNotify
  @tab Pointer leaves window

@item @tab @tab
  
@item ExposureMask @tab Expose @* NoExpose
  @tab Window needs to be redrawn

@item @tab @tab
  
@item FocusChangeMask @tab FocusIn @* FocusOut
  @tab Focus changes

@item KeymapStateMask @tab KeymapNotify
  @tab After EnterNotify and FocusIn

@item @tab @tab
  
@item KeyPressMask @tab KeyPress
  @tab Key is pressed

@item KeyReleaseMask @tab ReleasePress
  @tab Key is released

@item @tab @tab
  
@item PointerMotionMask @tab MotionNotify
  @tab Pointer is moved

@item @tab @tab
  
@item PropertyChangeMask @tab PropertyNotify
  @tab Window properties change

@item @tab @tab
    
@item StructureNotifyMask
  @tab CirculateNotify @*
  ConfigureNotify @*
  DestroyNotify @*
  GravityNotify @*
  MapNotify @*
  ReparentNotify @*
  UnmapNotify
  @tab Window structure changes

@item @tab @tab
    
@item SubstructureNotifyMask
  @tab CirculateNotify @*
  ConfigureNotify @*
  CreateNotify @*
  DestroyNotify @*
  GravityNotify @*
  MapNotify @*
  ReparentNotify @*
  UnmapNotify
  @tab Child window structure changes

@item @tab @tab
    
@item ResizeRedirectMask @tab ResizeRequest
  @tab Controlling window size change

@item @tab @tab
    
@item SubstructureRedirectMask
  @tab CirculateRequest @*
  ConfigureRequest @*
  MapRequest
  @tab Controlling changes to child windows

@item @tab @tab
    
@item VisibilityChangeMask @tab VisibilityNotify
  @tab Window is obscured or visible

@end multitable

There are also some event types which are always sent to the clients,
regardless of any event masks:

@multitable {@strong{Type and Class}} {Other client sends message}

@item @strong{Type and Class}	@tab @strong{Cut'n'pasting between windows}

@item ClientMessage @tab Other client sends message
@item @tab 
    
@item MappingMotify @tab Keyboard mapping changes
@item @tab 
    
@item SelectionClear @*
  SelectionNotify @*
  SelectionRequest
  @tab Cut'n'pasting between windows

@end multitable

    
@node Event Types
@section Event Types

This section describes all event types by listing their fields and basic
information on when they are generated.  All events are defined in the
module @code{Xlib.protocol.event}.  All event types have the following
two attributes:

@defivar Event type

Stores the X type code of this event.  Type codes are integers in the
range 2-127, and are defined with symbolic names in @code{Xlib.X}.  The
symbolic names are the same as the event class names, except for the
special event @code{AnyEvent}.

@end defivar

@defivar Event send_event

This attribute is normally 0, meaning that the event was generated by
the X server.  It is set to 1 if this event was instead sent from
another client.

@end defivar


Event object can be created by instantiating the corresponding event
class, providing all the attributes described for the event as keyword
arguments. 


@defvr Event KeyPress
@defvrx Event KeyRelease
@defvrx Event ButtonPress
@defvrx Event ButtonRelease
@defvrx Event MotionNotify

These events are generated when a key or a button logically changes
state, or when the pointer logically moves.  In the discussion below,
the @dfn{source window} is the window that the event occured in.  The
event may be generated on some other window than the source window, see
XKeyEvent(3X11) for details.  The same man page also describes
@code{MotionNotify}.

@defivar KeyButtonPointerEvent time
The server X time when this event was generated.
@end defivar

@defivar KeyButtonPointerEvent root
The root window which the source window is an inferior of.
@end defivar

@defivar KeyButtonPointerEvent window
The window the event is reported on.
@end defivar

@defivar KeyButtonPointerEvent same_screen
Set to 1 if @code{window} is on the same screen as @code{root}, 0
otherwise.
@end defivar

@defivar KeyButtonPointerEvent child
If the source window is an inferior of @code{window}, @code{child} is
set to the child of @code{window} that is the ancestor of (or is) the
source window.  Otherwise it is set to @code{X.NONE}.
@end defivar

@defivar KeyButtonPointerEvent root_x
@defivarx KeyButtonPointerEvent root_y
The pointer coordinates at the time of the event, relative to the root
window. 
@end defivar

@defivar KeyButtonPointerEvent event_x
@defivarx KeyButtonPointerEvent event_y
The pointer coordinates at the time of the event, relative to
@code{window}.  If @code{window} is not on the same screen as
@code{root}, these are set to 0.
@end defivar

@defivar KeyButtonPointerEvent state
The logical state of the button and modifier keys just before the event.
@end defivar

@defivar KeyButtonPointerEvent detail
For @code{KeyPress} and @code{KeyRelease}, this is the keycode of the
event key.

For @code{ButtonPress} and @code{ButtonRelease}, this is the button of
the event.

For @code{MotionNotify}, this is either @code{X.NotifyNormal} or
@code{X.NotifyHint}.
@end defivar

@end defvr



@defvr Event EnterNotify
@defvrx Event LeaveNotify

If pointer motion or window hierarchy change causes the pointer to be in
another window than before, these events are generated instead of
a @code{MotionNotify} event.

The semantics are quite complex, see XCrossingEvent(3X11) for details.

@defivar EnterLeaveEvent time
The server X time when this event was generated.
@end defivar

@defivar EnterLeaveEvent root
The root window of the pointer at the end of this event.
@end defivar

@defivar EnterLeaveEvent window
The window the event is reported for.
@end defivar

@defivar EnterLeaveEvent child
In a @code{LeaveNotify} event, if a child of @code{window} contains the
initial pointer position, this is set to that child window.
In a @code{EnterNotify} event, if a child of @code{window} contains the
final pointer position, this is set to that child window.
Otherwise this is set to @code{X.NONE}.
@end defivar

@defivar EnterLeaveEvent root_x
@defivarx EnterLeaveEvent root_y
The final pointer position relative to @code{root}.
@end defivar

@defivar EnterLeaveEvent event_x
@defivarx EnterLeaveEvent event_y
The final pointer position relative to @code{window}.
@end defivar

@defivar EnterLeaveEvent state
The modifier and button state at the time of the event.
@end defivar

@defivar EnterLeaveEvent mode
One of @code{X.NotifyNormal}, @code{X.NotifyGrab} or
@code{X.NotifyUngrab}. 
@end defivar

@defivar EnterLeaveEvent detail
One of @code{X.NotifyAncestor}, @code{X.NotifyVirtual},
@code{X.NotifyInferior}, @code{X.NotifyNonlinear}, or
@code{X.NotifyNonlinearVirtual}.
@end defivar

@defivar EnterLeaveEvent flags
If bit 0 is set, @code{window} is the focus window or an inferior of it.
If bit 1 is set, @code{window} is on the same screen as @code{root}.
@end defivar

@end defvr

    
@defvr Event FocusIn
@defvrx Event FocusOut

These events are generated when the focus changes.  This is also very
complex events, see XFocusChangeEvent(3X11) for details.

@defivar FocusEvent window
The window the event is generated for.
@end defivar

@defivar FocusEvent mode
One of @code{X.NotifyNormal}, @code{X.NotifyWhileGrabbed},
@code{X.NotifyGrab}, or @code{X.NotifyUngrab}.
@end defivar

@defivar FocusEvent detail
One of @code{X.NotifyAncestor}, @code{X.NotifyVirtual},
@code{X.NotifyInferior}, @code{X.NotifyNonlinear}, 
@code{X.NotifyNonlinearVirtual}, @code{X.NotifyPointer},
@code{X.NotifyPointerRoot}, or @code{X.NONE}.
@end defivar

@end defvr


@defvr Event KeymapNotify

This event is generated immediately after every @code{EnterNotify} and
@code{FocusIn}.

@defivar KeymapNotify data
A list of 31 eight-bit integers, as returned by query_keymap.
@end defivar

@end defvr


@defvr Event Expose

This event is generated when regions of a window has to be redrawn.  The
regions are decomposed into a set of rectangles, and an @code{Expose}
event is generated for each rectangle.

@defivar Expose window
The window containing regions to redraw.
@end defivar

@defivar Expose x
@defivarx Expose y
@defivarx Expose width
@defivarx Expose height
The coordinates of the rectangle to redraw.
@end defivar

@defivar Expose count
At least this many more @code{Expose} events will immediately follow for
this window.  If this is the last event, @code{count} is set to 0.

This allows a simple application to ignore all @code{Expose} events
with a non-zero @code{count}, and then redraw the entire window when the
zero event is received.
@end defivar

@end defvr

@defvr Event GraphicsExpose
@defvrx Event NoExpose

These events may be generated for drawables when a graphics context with
@code{graphics_exposures} selected is used.  See
XGraphicsExposeEvent(3X11) for details.

Both events have these attributes:

@defivar GraphicsExpose drawable
The drawable of the event.
@end defivar

@defivar GraphicsExpose major_event
@defivarx GraphicsExpose minor_event
The major and minor number of the request that generated this event.
For the core protocol @code{major_event} is always 62 (CopyArea) or 63
(CopyPlane), and @code{minor_event} is always 0.
@end defivar

GraphicsExpose have these additional attributes:

@defivar GraphicsExpose x
@defivarx GraphicsExpose y
@defivarx GraphicsExpose width
@defivarx GraphicsExpose height
The coordinates of the event region.
@end defivar

@defivar GraphicsExpose count
At least this many more @code{GraphicsExposure} events follows.  The
last one has @code{count} set to 0.
@end defivar

@end defvr


@defvr Event VisibilityNotify

These events are generated when the visibility of a viewable window is
changed.  See XVisibilityNotifyEvent(3X11).

@defivar VisibiltyNotify window
The window of the event.
@end defivar

@defivar VisibiltyNotify state
One of @code{X.VisibilityUnobscured},
@code{X.VisibilityPartiallyObscured}, or @code{X.VisibilityFullyObscured}.
@end defivar

@end defvr


@defvr Event CreateNotify

This event is generated when a window is created.
@code{X.SubstructureNotifyMask} must be selected on the parent of the
new window to receive this event.

@defivar CreateNotify parent
The parent of the new window.
@end defivar

@defivar CreateNotify window
The new window.
@end defivar

@defivar CreateNotify x
@defivarx CreateNotify y
@defivarx CreateNotify width
@defivarx CreateNotify height
@defivarx CreateNotify border_width
@defivarx CreateNotify override
These values are fetched from the @code{create_window} call.
@end defivar

@end defvr


@defvr Event DestroyNotify

This event is generated when a window is destroyed.

@defivar DestroyNotify event
The window that the event is generated for.
@end defivar

@defivar DestroyNotify window
The window that was destroyed.
@end defivar

@end defvr


@defvr Event UnmapNotify

This event is generated when a window is unmapped.

@defivar UnmapNotify event
The window that the event is generated for.
@end defivar

@defivar UnmapNotify window
The window that was unmapped.
@end defivar

@defivar Event from_configure
This is true if @code{window} was unmapped because its parent was
resized and @code{window} had win-gravity @code{X.UnmapGravity}.
@end defivar

@end defvr


@defvr Event MapNotify

This event is generated when a window is mapped.

@defivar MapNotify event
The window that the event is generated for.
@end defivar

@defivar MapNotify window
The window that was mapped.
@end defivar

@defivar Event override
This is set from the corresponding window attribute.
@end defivar
@end defvr


@defvr Event MapRequest

This event is reported to the client that has set
@code{X.SubstructureRedirectMask} on a window, and an unmapped child of
that window attempts to be mapped by some other client, unless the child
has override-redirect set.

@defivar MapRequest parent
The parent window.
@end defivar

@defivar MapRequest window
The child window that attempts to be mapped.
@end defivar

@end defvr


@defvr Event ReparentNotify

This event is reported to clients selecting
@code{X.SubstructureNotifyMask} on either the old or the new parent and
to clients selecting @code{X.StructureNotifyMask} on the reparented
window.

@defivar ReparentNotify event
The window the event is generated for.
@end defivar

@defivar ReparentNotify window
The reparented window.
@end defivar

@defivar ReparentNotify parent
The new parent window.
@end defivar

@defivar ReparentNotify x
@defivarx ReparentNotify y
The coordinates of the upper-left outer corner of @code{window} in
@code{parent}. 
@end defivar

@defivar ReparentNotify override
This is set from the corresponding attribute on @code{window}.
@end defivar

@end defvr


@defvr Event ConfigureNotify

This event is generated when a configure request actually changes the
state of the window.

@defivar ConfigureNotify event
The window that the event is generated for.
@end defivar

@defivar ConfigureNotify window
The window that has been changed.
@end defivar

@defivar ConfigureNotify x
@defivarx ConfigureNotify y
@defivarx ConfigureNotify width
@defivarx ConfigureNotify height
@defivarx ConfigureNotify border_width
The new coordinate and geometry of @code{window}.
@end defivar

@defivar ConfigureNotify above_sibling
This is @code{X.NONE} if this window is at the bottom of the window
stack.  Otherwise it is the sibling window that @code{window} is
immediately above.
@end defivar

@defivar ConfigureNotify override
This is set from the corresponding attribute on @code{window}.
@end defivar

@end defvr


@defvr Event ConfigureRequest

This event is reported to the client that has set
@code{X.SubstructureRedirectMask} on the parent of a window that another
client attempts to configure, unless the window has override-redirect
set.

@defivar ConfigureRequest parent
The parent of the window being configured.
@end defivar

@defivar ConfigureRequest window
The window being configured.
@end defivar

@defivar ConfigureRequest value_mask
A bitmask indicating which values that the caller tries to change.
@end defivar

@defivar ConfigureRequest x
@defivarx ConfigureRequest y
@defivarx ConfigureRequest width
@defivarx ConfigureRequest height
@defivarx ConfigureRequest border_width
The window geometry in the configure call.  If @code{X.CWX},
@code{X.CWY}, @code{X.CWWidth}, @code{X.CWHeight}, or
@code{X.CWBorderWidth} is set in @code{value_mask}, the corresponding
attributes contains the new value as given in the configure call,
otherwise the current value is used.
@end defivar

@defivar ConfigureRequest stack_mode
If @code{X.CWStackMode} is set in @code{value_mask}, this is the stack
mode specified in the configure call, one of @code{X.Above},
@code{X.Below}, @code{X.TopIf}, @code{X.BottomIf}, or
@code{X.Opposite}.  If the flag is not set, this is set to
@code{X.Above}.
@end defivar

@defivar ConfigureRequest sibling
If @code{X.CWSibling} is set in @code{value_mask}, this is the sibling
window specified in the configure call.  If the flag is not set, this is
set to @code{X.NONE}.
@end defivar

@end defvr


@defvr Event GravityNotify

This event is generated when a window is moved because its parent's size
has changed.

@defivar GravityNotify event
The window the event is generated for.
@end defivar

@defivar GravityNotify window
The window that moved.
@end defivar

@defivar GravityNotify x
@defivarx GravityNotify y
The new coordinates of the upper-left outer corner of @code{window}.
@end defivar

@end defvr

    
@defvr Event ResizeRequest

This is reported to the client selecting @code{X.ResizeRedirectMask} on
a window, and another client attempts to resize it. 

@defivar ResizeRedirect window
The window that was attempted to be resized.
@end defivar

@defivar ResizeRedirect width
@defivarx ResizeRedirect height
The requested size of the window, excluding the border.
@end defivar

@end defvr


@defvr Event CirculateNotify

This event is generated when a window is restacked caused by a circulate
call.

@defivar Event event
The window the event is reported on.
@end defivar

@defivar Event window
The window that has been restacked.
@end defivar

@defivar Event place
Either @code{X.PlaceOnTop} or @code{X.PlaceOnBottom}.
@end defivar

@end defvr


@defvr Event CirculateRequest

This event is reported to the client that has set
@code{X.SubstructureRedirectMask} on the parent of a window that needs
to be restacked as a result of a circulate call on the parent.

@defivar CirculateRequest parent
The parent window.
@end defivar

@defivar CirculateRequest window
The window that should be restacked.
@end defivar

@defivar CirculateRequest place
Where @code{window} should be placed, either @code{X.PlaceOnTop} or
@code{X.PlaceOnBottom}. 
@end defivar

@end defvr


@defvr Event PropertyNotify

This event is generated when a property on a window is changed.


@defivar Event window
The window which the property is or was set on.
@end defivar

@defivar Event atom
The atom identifying the property.
@end defivar

@defivar Event time
The server X time when the property was changed.
@end defivar

@defivar Event state
What was changed, either @code{X.PropertyNewValue} or
@code{X.PropertyDelete}.
@end defivar

@end defvr


@defvr Event SelectionClear

This event is reported to the owner of a selection when it has gotten a
new owner.

@defivar SelectionClear window
The owner window of the selection.
@end defivar

@defivar SelectionClear atom
The selection atom.
@end defivar

@defivar SelectionClear time
The server X time when the selection was last changed.
@end defivar

@end defvr


@defvr Event SelectionRequest

This event is reported to the owner of a selection when a client
requests it by calling convert_selection.

@defivar SelectionRequest owner
The owner window of the selection.
@end defivar

@defivar SelectionRequest requestor
@defivarx SelectionRequest selection
@defivarx SelectionRequest target
@defivarx SelectionRequest property
@defivarx SelectionRequest time
These attributes are fetched from the convert_selection call.
@end defivar

@end defvr


@defvr Event SelectionNotify

This event is generated by the server if there are no owner of a
selection when convert_selection is called.  If there is an owner, it
should send this event to the requestor when the selection has been
converted. 

@defivar SelectionNotify requestor
@defivarx SelectionNotify selection
@defivarx SelectionNotify target
@defivarx SelectionNotify property
@defivarx SelectionNotify time
See XSelectionEvent(3X11).
@end defivar

@end defvr


@defvr Event ColormapNotify

This event is generated when the colormap attribute of a window is set,
or when a window's colormap is installed or uninstalled.

@defivar ColormapNotify window
The affected window.
@end defivar

@defivar ColormapNotify colormap
The colormap of the window, or @code{X.NONE}.
@end defivar

@defivar ColormapNotify new
Set to 1 if the colormap attribute has been set, 0 when the
colormap is installed or uninstalled.
@end defivar

@defivar ColormapNotify state
Indicates whether the colormap is installed or not, either
@code{X.ColormapInstalled} or @code{X.ColormapUninstalled}.
@end defivar

@end defvr


@defvr Event MappingNotify

This event is sent to all clients, without any event mask having to be
set.  It is sent when the keyboard or pointer mapping is changed.

@defivar MappingNotify request
The mapping that has changed, one of @code{X.MappingModifier},
@code{X.MappingKeyboard} or @code{X.Pointer}.
@end defivar

@defivar MappingNotify first_keycode
@defivarx MappingNotify count
If the keyboard mapping has changed, this is the range of modified
keycodes.
@end defivar

@end defvr


@defvr Event ClientMessage

This event is only generated by clients using send_event.  

@defivar ClientMessage window
The destination window of the event.
@end defivar

@defivar ClientMessage client_type
The type of message, an atom.
@end defivar

@defivar ClientMessage data
The message data as a tuple: @code{(format, mdata)}

Format must be one of 8, 16, or 32.  mdata must either be a string of
exactly 20 characters, or a list of exactly 20, 10 or 5 integers
depending of the format.
@end defivar

@end defvr


@defvr Event AnyEvent

This event is represents an event the Xlib does not recognise.  These
should never be returned by @code{Display.next_event()}, but they might
be useful for sending special events to other clients.

@defivar AnyEvent detail
An eight-bit integer.
@end defivar

@defivar AnyEvent data
A string of exactly 28 characters.
@end defivar

@end defvr


@node Sending Events
@section Sending Events

Clients can send events to each other.  Most often these are
general-purpose @code{ClientMessage} events, but any event type can be
sent.

To send an event, an event object must be created.  This is done by
instantiating an event class, providing values to all its fields as
keyword parameters.  The event is then sent with the @code{send_event()}
method:

@defmethod Window send_event ( event, event_mask = 0, propagate = 0, @w{onerror = None )}

Send @var{event} to this window.

If @var{event_mask} is 0, the event is sent to the client that created
the window.  Otherwise the event is sent to every client selecting any
of the event types in @var{event_mask}.

If no clients have selected any of the event types and @var{propagate}
is true, the X server will search for an ancestor of this window on
which some client has selected any of the event types.  For details, see
XSendEvent(3X11).

@end defmethod

@defmethod Display send_event ( destination, event, @w{event_mask = 0,} @w{propagate = 0,} @w{onerror = None )}

Send @var{event} to @var{destination}, which can either be a
@code{Window} object or a constant:  If @code{X.PointerWindow} is
specified, send the event to the window the pointer is in. If
@code{X.InputFocus} is specified and the focus window contains the
pointer, send the event to the window that the pointer is in.
Otherwise, send the event to the focus window.

@end defmethod


As an example, this creates and sends a @code{ClientMessage} event of
the client specific type @code{HELLO_WORLD} (an atom), to the window
@code{dest} and with the 8-bitformat value @code{"G'day, mate"} (which
must be exactly twenty bytes):

@example
cm_event = Xlib.protocol.event.ClientMessage(
    window = dest,
    client_type = HELLO_WORLD,
    data = (8, "G'day mate\0\0\0\0\0\0\0\0\0\0"))

dest.send_event(cm_event)
@end example

