/*
Package xevent provides an event handler interface for attaching callback
functions to X events, and an implementation of an X event loop.

The X event loop

One of the biggest conveniences offered by xgbutil is its event handler system.
That is, the ability to attach an arbitrary callback function to any X event.
In order for such things to work, xgbutil needs to control the main X event
loop and act as a dispatcher for all event handlers created by you.

To run the X event loop, use xevent.Main or xevent.MainPing. The former
runs a normal event loop in the current goroutine and processes events. The
latter runs the event loop in a new goroutine and returns a pingBefore and
a pingAfter channel. The pingBefore channel is sent a benign value right before
an event is dequeued, and the pingAfter channel is sent a benign value right
after after all callbacks for that event have finished execution. These
synchronization points in the main event loop can be combined with a 'select'
statement to process data from other input sources. An example of this is given
in the documentation for the MainPing function. A complete example called
multiple-source-event-loop can also be found in the examples directory of the
xgbutil package.

To quit the main event loop, you may use xevent.Quit, but there is nothing
inherently wrong with stopping dead using os.Exit. xevent.Quit is provided for
your convenience should you need to run any clean-up code after the main event
loop returns.

The X event queue

xgbutil's event queue contains values that are either events or errors. (Never
both and never neither.) Namely, errors are received in the event loop from
unchecked requests. (Errors generated by checked requests are guaranteed to be
returned to the caller and are never received in the event loop.) Also, a
default error handler function can be set with xevent.ErrorHandlerSet.

To this end, xgbutil's event queue can be inspected. This is advantageous when
information about what events will be processed in the future could be helpful
(i.e., if there is an UnmapNotify event waiting to be processed.) The event
queue can also be manipulated to facilitate event compression. (Two events that
are common candidates for compression are ConfigureNotify and MotionNotify.)

Detach events

Whenever a window can no longer receive events (i.e., when it is destroyed),
all event handlers related to that window should be detached. (If this is
omitted, then Go's garbage collector will not be able to reuse memory occupied
by the now-unused event handlers for that window.) Moreover, its possible that
a window id can be reused after it has been discarded, which could result in
odd behavior in your application.

To detach a window from all event handlers in the xevent package, use
xevent.Detach. If you're also using the keybind and mousebind packages, you'll
need to call keybind.Detach and mousebind.Detach too. So to detach your window
from all possible event handlers in xgbutil, use something like:

	xevent.Detach(XUtilValue, your-window-id)
	keybind.Detach(XUtilValue, your-window-id)
	mousebind.Detach(XUtilValue, your-window-id)

Quick example

A small example that shows how to respond to ConfigureNotify events sent to
your-window-id.

	xevent.ConfigureNotifyFun(
		func(X *xgbutil.XUtil, e xevent.ConfigureNotifyEvent) {
			fmt.Printf("(%d, %d) %dx%d\n", e.X, e.Y, e.Width, e.Height)
		}).Connect(XUtilValue, your-window-id)

More examples

The xevent package is used in several of the examples in the examples directory
in the xgbutil package.
*/
package xevent
