Package xgbutil

import "github.com/BurntSushi/xgbutil"
Overview
Index
Subdirectories

Overview ▾

Package xgbutil is a utility library designed to make common tasks with the X server easier. The central design choice that has driven development is to hide the complexity of X wherever possible but expose it when necessary.

For example, the xevent package provides an implementation of an X event loop that acts as a dispatcher to event handlers set up with the xevent, keybind and mousebind packages. At the same time, the event queue is exposed and can be modified using xevent.Peek and xevent.DequeueAt.

Sub-packages

The xgbutil package is considerably small, and only contains some type definitions and the initial setup for an X connection. Much of the functionality of xgbutil comes from its sub-packages. Each sub-package is appropriately documented.

Installation

xgbutil is go-gettable:

go get github.com/BurntSushi/xgbutil

Dependencies

XGB is the main dependency, and is required for all packages inside xgbutil.

graphics-go and freetype-go are also required if using the xgraphics package.

Quick Example

A quick example to demonstrate that xgbutil is working correctly:

go get github.com/BurntSushi/xgbutil/examples/window-name-sizes
GO/PATH/bin/window-name-sizes

The output will be a list of names of all top-level windows and their geometry including window manager decorations. (Assuming your window manager supports some basic EWMH properties.)

Examples

The examples directory contains a sizable number of examples demonstrating common tasks with X. They are intended to demonstrate a single thing each, although a few that require setup are necessarily long. Each example is heavily documented.

The examples directory should be your first stop when learning how to use xgbutil.

xgbutil is also used heavily throughout my window manager, Wingo. It may be useful reference material.

Wingo project page: https://github.com/BurntSushi/wingo

Thread Safety

While I am fairly confident that XGB is thread safe, I am only somewhat confident that xgbutil is thread safe. It simply has not been tested enough for my confidence to be higher.

Note that the xevent package's X event loop is not concurrent. Namely, designing a generally concurrent X event loop is extremely complex. Instead, the onus is on you, the user, to design concurrent callback functions if concurrency is desired.

Constants

const MaxReqSize = (1 << 16) * 4

The current maximum request size. I think we can expand this with BigReq, but it probably isn't worth it at the moment.

Variables

var Logger = log.New(os.Stderr, "[xgbutil] ", log.Lshortfile)

Logger is used through xgbutil when messages need to be emitted to stderr.

type Callback

type Callback interface {
    // Connect modifies XUtil's state to attach an event handler to a
    // particular event.
    Connect(xu *XUtil, win xproto.Window)

    // Run is exported for use in the xevent package but should not be
    // used by the user. (It is used to run the callback function in the
    // main event loop.)
    Run(xu *XUtil, ev interface{})
}

Callback is an interface that should be implemented by event callback functions. Namely, to assign a function to a particular event/window combination, simply define a function with type 'SomeEventFun' (pre-defined in xevent/callback.go), and call the 'Connect' method. The 'Run' method is used inside the Main event loop, and shouldn't be used by the user. Also, it is perfectly legitimate to connect to events that don't specify a window (like MappingNotify and KeymapNotify). In this case, simply use 'xgbutil.NoWindow' as the window id.

Example to respond to ConfigureNotify events on window 0x1

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(X, 0x1)

type CallbackHook

type CallbackHook interface {
    // Connect connects this hook to the main loop of the passed XUtil
    // instance.
    Connect(xu *XUtil)

    // Run is exported for use in the xevent package, but should not be
    // used by the user.  It should return true if it's ok to process
    // the event as usual, or false if it should be suppressed.
    Run(xu *XUtil, ev interface{}) bool
}

CallbackHook works similarly to the more general Callback, but it is for hooks into the main xevent loop. As such it does not get attached to a window.

type CallbackKey

type CallbackKey interface {
    // Connect modifies XUtil's state to attach an event handler to a
    // particular key press. If grab is true, connect will request a passive
    // grab.
    Connect(xu *XUtil, win xproto.Window, keyStr string, grab bool) error

    // Run is exported for use in the keybind package but should not be
    // used by the user. (It is used to run the callback function in the
    // main event loop.
    Run(xu *XUtil, ev interface{})
}

CallbackKey works similarly to the more general Callback, but it adds parameters specific to key bindings.

type CallbackMouse

type CallbackMouse interface {
    // Connect modifies XUtil's state to attach an event handler to a
    // particular button press.
    // If sync is true, the grab will be synchronous. (This will require a
    // call to xproto.AllowEvents in response, otherwise no further events
    // will be processed and your program will lock.)
    // If grab is true, connect will request a passive grab.
    Connect(xu *XUtil, win xproto.Window, buttonStr string,
        sync bool, grab bool) error

    // Run is exported for use in the mousebind package but should not be
    // used by the user. (It is used to run the callback function in the
    // main event loop.)
    Run(xu *XUtil, ev interface{})
}

CallbackMouse works similarly to the more general Callback, but it adds parameters specific to mouse bindings.

type ErrorHandlerFun

type ErrorHandlerFun func(err xgb.Error)

ErrorHandlerFun is the type of function required to handle errors that come in through the main event loop. For example, to set a new error handler, use:

xevent.ErrorHandlerSet(xgbutil.ErrorHandlerFun(
	func(err xgb.Error) {
		// do something with err
	}))

type EventOrError

type EventOrError struct {
    Event xgb.Event
    Err   xgb.Error
}

EventOrError is a struct that contains either an event value or an error value. It is an error to contain both. Containing neither indicates an error too. This is exported for use in the xevent package. You shouldn't have any direct contact with values of this type, unless you need to inspect the queue directly with xevent.Peek.

type KeyKey

type KeyKey struct {
    Evtype int
    Win    xproto.Window
    Mod    uint16
    Code   xproto.Keycode
}

KeyKey is the type of the key in the map of keybindings. It essentially represents the tuple (event type, window id, modifier, keycode). It is exported for use in the keybind package. It should not be used.

type KeyString

type KeyString struct {
    Str      string
    Callback CallbackKey
    Evtype   int
    Win      xproto.Window
    Grab     bool
}

KeyString is the type of a key binding string used to connect to particular key combinations. A list of all such key strings is maintained in order to rebind keys when the keyboard mapping has been changed.

type KeyboardMapping

type KeyboardMapping struct {
    *xproto.GetKeyboardMappingReply
}

KeyboardMapping embeds a keyboard mapping reply from XGB. It should be retrieved using keybind.KeyMapGet, if necessary. xgbutil tries quite hard to absolve you from ever having to use this. A keyboard mapping is a table that maps keycodes to one or more keysyms.

type ModifierMapping

type ModifierMapping struct {
    *xproto.GetModifierMappingReply
}

ModifierMapping embeds a modifier mapping reply from XGB. It should be retrieved using keybind.ModMapGet, if necessary. xgbutil tries quite hard to absolve you from ever having to use this. A modifier mapping is a table that maps modifiers to one or more keycodes.

type MouseDragBeginFun

type MouseDragBeginFun func(xu *XUtil, rootX, rootY,
    eventX, eventY int) (bool, xproto.Cursor)

MouseDragBeginFun is the kind of function used to initialize a drag. The difference between this and MouseDragFun is that the begin function returns a bool (of whether or not to cancel the drag) and an X resource identifier corresponding to a cursor.

type MouseDragFun

type MouseDragFun func(xu *XUtil, rootX, rootY, eventX, eventY int)

MouseDragFun is the kind of function used on each dragging step and at the end of a drag.

type MouseKey

type MouseKey struct {
    Evtype int
    Win    xproto.Window
    Mod    uint16
    Button xproto.Button
}

MouseKey is the type of the key in the map of mouse bindings. It essentially represents the tuple (event type, window id, modifier, button). It is exported for use in the mousebind package. It should not be used.

type XUtil

type XUtil struct {

    // Quit can be set to true, and the main event loop will finish processing
    // the current event, and gracefully quit afterwards.
    // This is exported for use in the xevent package. Please us xevent.Quit
    // to set this value.
    Quit bool // when true, the main event loop will stop gracefully

    // Atoms is a cache of atom names to resource identifiers. This minimizes
    // round trips to the X server, since atom identifiers never change.
    // It is exported for use in the xprop package. It should not be used.
    Atoms    map[string]xproto.Atom
    AtomsLck *sync.RWMutex

    // AtomNames is a cache just like 'atoms', but in the reverse direction.
    // It is exported for use in the xprop package. It should not be used.
    AtomNames    map[xproto.Atom]string
    AtomNamesLck *sync.RWMutex

    // Evqueue is the queue that stores the results of xgb.WaitForEvent.
    // Namely, each value is either an Event *or* an Error.
    // It is exported for use in the xevent package. Do not use it.
    // If you need to interact with the event queue, please use the functions
    // available in the xevent package: Dequeue, DequeueAt, QueueEmpty
    // and QueuePeek.
    Evqueue    []EventOrError
    EvqueueLck *sync.RWMutex

    // Callbacks is a map of event numbers to a map of window identifiers
    // to callback functions.
    // This is the data structure that stores all callback functions, where
    // a callback function is always attached to a (event, window) tuple.
    // It is exported for use in the xevent package. Do not use it.
    Callbacks    map[int]map[xproto.Window][]Callback
    CallbacksLck *sync.RWMutex

    // Hooks are called by the XEvent main loop before processing the event
    // itself. These are meant for instances when it's not possible / easy
    // to use the normal Hook system. You should not modify this yourself.
    Hooks    []CallbackHook
    HooksLck *sync.RWMutex

    // Keymap corresponds to xgbutil's current conception of the keyboard
    // mapping. It is automatically kept up-to-date if xgbutil's event loop
    // is used.
    // It is exported for use in the keybind package. It should not be
    // accessed directly. Instead, use keybind.KeyMapGet.
    Keymap *KeyboardMapping

    // Modmap corresponds to xgbutil's current conception of the modifier key
    // mapping. It is automatically kept up-to-date if xgbutil's event loop
    // is used.
    // It is exported for use in the keybind package. It should not be
    // accessed directly. Instead, use keybind.ModMapGet.
    Modmap *ModifierMapping

    // KeyRedirect corresponds to a window identifier that, when set,
    // automatically receives *all* keyboard events. This is a sort-of
    // synthetic grab and is helpful in avoiding race conditions.
    // It is exported for use in the xevent and keybind packages. Do not use
    // it directly. To redirect key events, please use xevent.RedirectKeyEvents.
    KeyRedirect xproto.Window

    // Keybinds is the data structure storing all callbacks for key bindings.
    // This is extremely similar to the general notion of event callbacks,
    // but adds extra support to make handling key bindings easier. (Like
    // specifying human readable key sequences to bind to.)
    // KeyBindKey is a struct representing the 4-tuple
    // (event-type, window-id, modifiers, keycode).
    // It is exported for use in the keybind package. Do not access it directly.
    Keybinds    map[KeyKey][]CallbackKey
    KeybindsLck *sync.RWMutex

    // Keygrabs is a frequency count of the number of callbacks associated
    // with a particular KeyBindKey. This is necessary because we can only
    // grab a particular key *once*, but we may want to attach several callbacks
    // to a single keypress.
    // It is exported for use in the keybind package. Do not access it directly.
    Keygrabs map[KeyKey]int

    // Keystrings is a list of all key strings used to connect keybindings.
    // They are used to rebuild key grabs when the keyboard mapping is updated.
    // It is exported for use in the keybind package. Do not access it directly.
    Keystrings []KeyString

    // Mousebinds is the data structure storing all callbacks for mouse
    // bindings.This is extremely similar to the general notion of event
    // callbacks,but adds extra support to make handling mouse bindings easier.
    // (Like specifying human readable mouse sequences to bind to.)
    // MouseBindKey is a struct representing the 4-tuple
    // (event-type, window-id, modifiers, button).
    // It is exported for use in the mousebind package. Do not use it.
    Mousebinds    map[MouseKey][]CallbackMouse
    MousebindsLck *sync.RWMutex

    // Mousegrabs is a frequency count of the number of callbacks associated
    // with a particular MouseBindKey. This is necessary because we can only
    // grab a particular mouse button *once*, but we may want to attach
    // several callbacks to a single button press.
    // It is exported for use in the mousebind package. Do not use it.
    Mousegrabs map[MouseKey]int

    // InMouseDrag is true if a drag is currently in progress.
    // It is exported for use in the mousebind package. Do not use it.
    InMouseDrag bool

    // MouseDragStep is the function executed for each step (i.e., pointer
    // movement) in the current mouse drag. Note that this is nil when a drag
    // is not in progress.
    // It is exported for use in the mousebind package. Do not use it.
    MouseDragStepFun MouseDragFun

    // MouseDragEnd is the function executed at the end of the current
    // mouse drag. This is nil when a drag is not in progress.
    // It is exported for use in the mousebind package. Do not use it.
    MouseDragEndFun MouseDragFun

    // ErrorHandler is the function that handles errors *in the event loop*.
    // By default, it simply emits them to stderr.
    // It is exported for use in the xevent package. To set the default error
    // handler, please use xevent.ErrorHandlerSet.
    ErrorHandler ErrorHandlerFun
    // contains filtered or unexported fields
}

An XUtil represents the state of xgbutil. It keeps track of the current X connection, the root window, event callbacks, key/mouse bindings, etc. Regrettably, many of the members are exported, even though they should not be used directly by the user. They are exported for use in sub-packages. (Namely, xevent, keybind and mousebind.) In fact, there should *never* be a reason to access any members of an XUtil value directly. Any interaction with an XUtil value should be through its methods.

func NewConn

func NewConn() (*XUtil, error)

NewConn connects to the X server using the DISPLAY environment variable and creates a new XUtil. Most environments have the DISPLAY environment variable set, so this is probably what you want to use to connect to X.

func NewConnDisplay

func NewConnDisplay(display string) (*XUtil, error)

NewConnDisplay connects to the X server and creates a new XUtil. If 'display' is empty, the DISPLAY environment variable is used. Otherwise there are several different display formats supported:

NewConn(":1") -> net.Dial("unix", "", "/tmp/.X11-unix/X1")
NewConn("/tmp/launch-12/:0") -> net.Dial("unix", "", "/tmp/launch-12/:0")
NewConn("hostname:2.1") -> net.Dial("tcp", "", "hostname:6002")
NewConn("tcp/hostname:1.0") -> net.Dial("tcp", "", "hostname:6001")

func (*XUtil) Conn

func (xu *XUtil) Conn() *xgb.Conn

Conn returns the xgb connection object.

func (*XUtil) Dummy

func (xu *XUtil) Dummy() xproto.Window

Dummy gets the id of the dummy window.

func (*XUtil) ExtInitialized

func (xu *XUtil) ExtInitialized(extName string) bool

ExtInitialized returns true if an extension has been initialized. This is useful for determining whether an extension is available or not.

func (*XUtil) GC

func (xu *XUtil) GC() xproto.Gcontext

GC gets a general purpose graphics context that is typically used to simply paint images.

func (*XUtil) Grab

func (xu *XUtil) Grab()

Grabs the server. Everything becomes synchronous.

func (*XUtil) RootWin

func (xu *XUtil) RootWin() xproto.Window

RootWin returns the current root window.

func (*XUtil) RootWinSet

func (xu *XUtil) RootWinSet(root xproto.Window)

RootWinSet will change the current root window to the one provided. N.B. This probably shouldn't be used unless you're desperately trying to support multiple X screens. (This is *not* the same as Xinerama/RandR or TwinView. All of those have a single root window.)

func (*XUtil) Screen

func (xu *XUtil) Screen() *xproto.ScreenInfo

Screen returns the default screen

func (*XUtil) Setup

func (xu *XUtil) Setup() *xproto.SetupInfo

Setup returns the setup information retrieved during connection time.

func (*XUtil) Sync

func (xu *XUtil) Sync()

Sync forces XGB to catch up with all events/requests and synchronize. This is done by issuing a benign round trip request to X.

func (*XUtil) TimeGet

func (xu *XUtil) TimeGet() xproto.Timestamp

TimeGet gets the most recent time seen by an event.

func (*XUtil) TimeSet

func (xu *XUtil) TimeSet(t xproto.Timestamp)

TimeSet sets the most recent time seen by an event.

func (*XUtil) Ungrab

func (xu *XUtil) Ungrab()

Ungrabs the server.

Subdirectories

Name      Synopsis
..
ewmh      Package ewmh provides a comprehensive API to get and set properties specified by the EWMH spec, as well as perform actions specified by the EWMH spec.
gopher      Package gopher contains a single image of the Go gopher.
icccm      Package icccm provides an API for a portion of the ICCCM, namely, getters and setters for many of the properties specified in the ICCCM.
keybind      Package keybind provides an easy to use interface to assign callback functions to human readable key sequences.
motif      Package motif has a few functions to allow easy access to Motif related properties.
mousebind      Package mousebind provides an easy to use interface to assign callback functions to human readable button sequences.
xcursor      Package xcursor provides a small interface for using cursors that are predefined in the X 'cursor' font.
xevent      Package xevent provides an event handler interface for attaching callback functions to X events, and an implementation of an X event loop.
xgraphics      Package xgraphics defines an X image type and provides convenience functions for reading and writing X pixmaps and bitmaps.
xinerama      Package xinerama provides a convenience function to retrieve the geometry of all active heads sorted in order from left to right and then top to bottom.
xprop      Package xprop provides a cache for interning atoms and helper functions for dealing with GetProperty and ChangeProperty X requests.
xrect      Package xrect defines a Rect interface and an XRect type implementing the Rect interface for working with X rectangles.
xwindow      Package xwindow defines a window type that provides easy access to common window operations while hiding many of the more obscure X parameters.