Documentation ¶
Overview ¶
Package XGB provides the X Go Binding, which is a low-level API to communicate with the core X protocol and many of the X extensions.
It is *very* closely modeled on XCB, so that experience with XCB (or xpyb) is easily translatable to XGB. That is, it uses the same cookie/reply model and is thread safe. There are otherwise no major differences (in the API).
Most uses of XGB typically fall under the realm of window manager and GUI kit development, but other applications (like pagers, panels, tilers, etc.) may also require XGB. Moreover, it is a near certainty that if you need to work with X, xgbutil will be of great use to you as well: https://github.com/jezek/xgbutil
Example ¶
This is an extremely terse example that demonstrates how to connect to X, create a window, listen to StructureNotify events and Key{Press,Release} events, map the window, and print out all events received. An example with accompanying documentation can be found in examples/create-window.
package main import ( "fmt" "github.com/jezek/xgb" "github.com/jezek/xgb/xproto" ) func main() { X, err := xgb.NewConn() if err != nil { fmt.Println(err) return } wid, _ := xproto.NewWindowId(X) screen := xproto.Setup(X).DefaultScreen(X) xproto.CreateWindow(X, screen.RootDepth, wid, screen.Root, 0, 0, 500, 500, 0, xproto.WindowClassInputOutput, screen.RootVisual, xproto.CwBackPixel | xproto.CwEventMask, []uint32{ // values must be in the order defined by the protocol 0xffffffff, xproto.EventMaskStructureNotify | xproto.EventMaskKeyPress | xproto.EventMaskKeyRelease}) xproto.MapWindow(X, wid) for { ev, xerr := X.WaitForEvent() if ev == nil && xerr == nil { fmt.Println("Both event and error are nil. Exiting...") return } if ev != nil { fmt.Printf("Event: %s\n", ev) } if xerr != nil { fmt.Printf("Error: %s\n", xerr) } } }
Xinerama Example ¶
This is another small example that shows how to query Xinerama for geometry information of each active head. Accompanying documentation for this example can be found in examples/xinerama.
package main import ( "fmt" "log" "github.com/jezek/xgb" "github.com/jezek/xgb/xinerama" ) func main() { X, err := xgb.NewConn() if err != nil { log.Fatal(err) } // Initialize the Xinerama extension. // The appropriate 'Init' function must be run for *every* // extension before any of its requests can be used. err = xinerama.Init(X) if err != nil { log.Fatal(err) } reply, err := xinerama.QueryScreens(X).Reply() if err != nil { log.Fatal(err) } fmt.Printf("Number of heads: %d\n", reply.Number) for i, screen := range reply.ScreenInfo { fmt.Printf("%d :: X: %d, Y: %d, Width: %d, Height: %d\n", i, screen.XOrg, screen.YOrg, screen.Width, screen.Height) } }
Parallelism ¶
XGB can benefit greatly from parallelism due to its concurrent design. For evidence of this claim, please see the benchmarks in xproto/xproto_test.go.
Tests ¶
xproto/xproto_test.go contains a number of contrived tests that stress particular corners of XGB that I presume could be problem areas. Namely: requests with no replies, requests with replies, checked errors, unchecked errors, sequence number wrapping, cookie buffer flushing (i.e., forcing a round trip every N requests made that don't have a reply), getting/setting properties and creating a window and listening to StructureNotify events.
Code Generator ¶
Both XCB and xpyb use the same Python module (xcbgen) for a code generator. XGB (before this fork) used the same code generator as well, but in my attempt to add support for more extensions, I found the code generator extremely difficult to work with. Therefore, I re-wrote the code generator in Go. It can be found in its own sub-package, xgbgen, of xgb. My design of xgbgen includes a rough consideration that it could be used for other languages.
What works ¶
I am reasonably confident that the core X protocol is in full working form. I've also tested the Xinerama and RandR extensions sparingly. Many of the other existing extensions have Go source generated (and are compilable) and are included in this package, but I am currently unsure of their status. They *should* work.
What does not work ¶
XKB is the only extension that intentionally does not work, although I suspect that GLX also does not work (however, there is Go source code for GLX that compiles, unlike XKB). I don't currently have any intention of getting XKB working, due to its complexity and my current mental incapacity to test it.
Index ¶
- Variables
- func Errorf(format string, v ...interface{}) error
- func Get16(buf []byte) uint16
- func Get32(buf []byte) uint32
- func Get64(buf []byte) uint64
- func Pad(n int) int
- func PopCount(mask0 int) int
- func Put16(buf []byte, v uint16)
- func Put32(buf []byte, v uint32)
- func Put64(buf []byte, v uint64)
- func Sprintf(format string, v ...interface{}) string
- func StringsJoin(ss []string, sep string) string
- type Conn
- type Cookie
- type Error
- type Event
- type NewErrorFun
- type NewEventFun
Constants ¶
This section is empty.
Variables ¶
var ( // Where to log error-messages. Defaults to stderr. // To disable logging, just set this to log.New(ioutil.Discard, "", 0) Logger = log.New(os.Stderr, "XGB: ", log.Lshortfile) )
var NewErrorFuncs = make(map[int]NewErrorFun)
NewErrorFuncs is a map from error numbers to functions that create the corresponding error. It should not be used. It is exported for use in the extension sub-packages.
var NewEventFuncs = make(map[int]NewEventFun)
NewEventFuncs is a map from event numbers to functions that create the corresponding event. It should not be used. It is exported for use in the extension sub-packages.
var NewExtErrorFuncs = make(map[string]map[int]NewErrorFun)
NewExtErrorFuncs is a temporary map that stores error constructor functions for each extension. When an extension is initialized, each error for that extension is added to the 'NewErrorFuncs' map. It should not be used. It is exported for use in the extension sub-packages.
var NewExtEventFuncs = make(map[string]map[int]NewEventFun)
NewExtEventFuncs is a temporary map that stores event constructor functions for each extension. When an extension is initialized, each event for that extension is added to the 'NewEventFuncs' map. It should not be used. It is exported for use in the extension sub-packages.
Functions ¶
func Errorf ¶
Errorf is just a wrapper for fmt.Errorf. Exists for the same reason that 'stringsJoin' and 'sprintf' exists.
func StringsJoin ¶
StringsJoin is an alias to strings.Join. It allows us to avoid having to import 'strings' in each of the generated Go files.
Types ¶
type Conn ¶
type Conn struct { DisplayNumber int DefaultScreen int SetupBytes []byte // ExtLock is a lock used whenever new extensions are initialized. // It should not be used. It is exported for use in the extension // sub-packages. ExtLock sync.RWMutex // Extensions is a map from extension name to major opcode. It should // not be used. It is exported for use in the extension sub-packages. Extensions map[string]byte // contains filtered or unexported fields }
A Conn represents a connection to an X server.
func NewConn ¶
NewConn creates a new connection instance. It initializes locks, data structures, and performs the initial handshake. (The code for the handshake has been relegated to conn.go.) It is up to user to close connection with Close() method to finish all unfinished requests and clean up spawned goroutines. If the connection unexpectedly closes itself and WaitForEvent() returns "nil, nil", everything is cleaned by that moment, but nothing bad happens if you call Close() after.
func NewConnDisplay ¶
NewConnDisplay is just like NewConn (see closing instructions), but allows a specific DISPLAY string to be used. If 'display' is empty it will be taken from os.Getenv("DISPLAY").
Examples:
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 NewConnNet ¶
NewConnNet is just like NewConn (see closing instructions), but allows a specific net.Conn to be used.
func (*Conn) Close ¶
func (c *Conn) Close()
Close gracefully closes the connection to the X server. When everything is cleaned up, the WaitForEvent method will return (nil, nil)
func (*Conn) NewCookie ¶
NewCookie creates a new cookie with the correct channels initialized depending upon the values of 'checked' and 'reply'. Together, there are four different kinds of cookies. (See more detailed comments in the function for more info on those.) Note that a sequence number is not set until just before the request corresponding to this cookie is sent over the wire.
Unless you're building requests from bytes by hand, this method should not be used.
func (*Conn) NewId ¶
NewId generates a new unused ID for use with requests like CreateWindow. If no new ids can be generated, the id returned is 0 and error is non-nil. This shouldn't be used directly, and is exported for use in the extension sub-packages. If you need identifiers, use the appropriate constructor. e.g., For a window id, use xproto.NewWindowId. For a new pixmap id, use xproto.NewPixmapId. And so on. Returns (0, io.EOF) when the connection is closed.
func (*Conn) NewRequest ¶
NewRequest takes the bytes and a cookie of a particular request, constructs a request type, and sends it over the Conn.reqChan channel. Note that the sequence number is added to the cookie after it is sent over the request channel, but before it is sent to X.
Note that you may safely use NewRequest to send arbitrary byte requests to X. The resulting cookie can be used just like any normal cookie and abides by the same rules, except that for replies, you'll get back the raw byte data. This may be useful for performance critical sections where every allocation counts, since all X requests in XGB allocate a new byte slice. In contrast, NewRequest allocates one small request struct and nothing else. (Except when the cookie buffer is full and has to be flushed.)
If you're using NewRequest manually, you'll need to use NewCookie to create a new cookie.
In all likelihood, you should be able to copy and paste with some minor edits the generated code for the request you want to issue.
func (*Conn) PollForEvent ¶
PollForEvent returns the next event from the server if one is available in the internal queue without blocking. Note that unlike WaitForEvent, both Event and Error could be nil. Indeed, they are both nil when the event queue is empty.
func (*Conn) Sync ¶
func (c *Conn) Sync()
Sync sends a round trip request and waits for the response. This forces all pending cookies to be dealt with. You actually shouldn't need to use this like you might with Xlib. Namely, buffers are automatically flushed using Go's channels and round trip requests are forced where appropriate automatically.
func (*Conn) WaitForEvent ¶
WaitForEvent returns the next event from the server. It will block until an event is available. WaitForEvent returns either an Event or an Error. (Returning both is a bug.) Note than an Error here is an X error and not an XGB error. That is, X errors are sometimes completely expected (and you may want to ignore them in some cases).
If both the event and error are nil, then the connection has been closed.
type Cookie ¶
type Cookie struct { Sequence uint16 // contains filtered or unexported fields }
Cookie is the internal representation of a cookie, where one is generated for *every* request sent by XGB. 'cookie' is most frequently used by embedding it into a more specific kind of cookie, i.e., 'GetInputFocusCookie'.
func (Cookie) Check ¶
Check is used for checked requests that have no replies. It is a mechanism by which to report "success" or "error" in a synchronous fashion. (Therefore, unchecked requests without replies cannot use this method.) If the request causes an error, it is sent to this cookie's errorChan. If the request was successful, there is no response from the server. Thus, pingChan is sent a value when the *next* reply is read. If no more replies are being processed, we force a round trip request with GetInputFocus. Returns io.EOF error when the connection is closed.
Unless you're building requests from bytes by hand, this method should not be used.
type Error ¶
Error is an interface that can contain any of the errors returned by the server. Use a type assertion switch to extract the Error structs.
type Event ¶
Event is an interface that can contain any of the events returned by the server. Use a type assertion switch to extract the Event structs.
type NewErrorFun ¶
NewErrorFun is the type of function use to construct errors from raw bytes. It should not be used. It is exported for use in the extension sub-packages.
type NewEventFun ¶
NewEventFun is the type of function use to construct events from raw bytes. It should not be used. It is exported for use in the extension sub-packages.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package bigreq is the X client API for the BIG-REQUESTS extension.
|
Package bigreq is the X client API for the BIG-REQUESTS extension. |
Package composite is the X client API for the Composite extension.
|
Package composite is the X client API for the Composite extension. |
Package damage is the X client API for the DAMAGE extension.
|
Package damage is the X client API for the DAMAGE extension. |
Package dpms is the X client API for the DPMS extension.
|
Package dpms is the X client API for the DPMS extension. |
Package dri2 is the X client API for the DRI2 extension.
|
Package dri2 is the X client API for the DRI2 extension. |
Package examples contains a few different use cases of XGB, like creating a window, reading properties, and querying for information about multiple heads using the Xinerama or RandR extensions.
|
Package examples contains a few different use cases of XGB, like creating a window, reading properties, and querying for information about multiple heads using the Xinerama or RandR extensions. |
create-window
Example create-window shows how to create a window, map it, resize it, and listen to structure and key events (i.e., when the window is resized by the window manager, or when key presses/releases are made when the window has focus).
|
Example create-window shows how to create a window, map it, resize it, and listen to structure and key events (i.e., when the window is resized by the window manager, or when key presses/releases are made when the window has focus). |
get-active-window
Example get-active-window reads the _NET_ACTIVE_WINDOW property of the root window and uses the result (a window id) to get the name of the window.
|
Example get-active-window reads the _NET_ACTIVE_WINDOW property of the root window and uses the result (a window id) to get the name of the window. |
randr
Example randr uses the randr protocol to get information about the active heads.
|
Example randr uses the randr protocol to get information about the active heads. |
shapes
The shapes example shows how to draw basic shapes into a window.
|
The shapes example shows how to draw basic shapes into a window. |
xinerama
Example xinerama shows how to query the geometry of all active heads.
|
Example xinerama shows how to query the geometry of all active heads. |
Package ge is the X client API for the Generic Event Extension extension.
|
Package ge is the X client API for the Generic Event Extension extension. |
Package glx is the X client API for the GLX extension.
|
Package glx is the X client API for the GLX extension. |
Package randr is the X client API for the RANDR extension.
|
Package randr is the X client API for the RANDR extension. |
Package record is the X client API for the RECORD extension.
|
Package record is the X client API for the RECORD extension. |
Package render is the X client API for the RENDER extension.
|
Package render is the X client API for the RENDER extension. |
Package res is the X client API for the X-Resource extension.
|
Package res is the X client API for the X-Resource extension. |
Package screensaver is the X client API for the MIT-SCREEN-SAVER extension.
|
Package screensaver is the X client API for the MIT-SCREEN-SAVER extension. |
Package shape is the X client API for the SHAPE extension.
|
Package shape is the X client API for the SHAPE extension. |
Package shm is the X client API for the MIT-SHM extension.
|
Package shm is the X client API for the MIT-SHM extension. |
Package xcmisc is the X client API for the XC-MISC extension.
|
Package xcmisc is the X client API for the XC-MISC extension. |
Package xevie is the X client API for the XEVIE extension.
|
Package xevie is the X client API for the XEVIE extension. |
Package xf86dri is the X client API for the XFree86-DRI extension.
|
Package xf86dri is the X client API for the XFree86-DRI extension. |
Package xf86vidmode is the X client API for the XFree86-VidModeExtension extension.
|
Package xf86vidmode is the X client API for the XFree86-VidModeExtension extension. |
Package xfixes is the X client API for the XFIXES extension.
|
Package xfixes is the X client API for the XFIXES extension. |
Package xinerama is the X client API for the XINERAMA extension.
|
Package xinerama is the X client API for the XINERAMA extension. |
Package xprint is the X client API for the XpExtension extension.
|
Package xprint is the X client API for the XpExtension extension. |
Package xproto is the X client API for the extension.
|
Package xproto is the X client API for the extension. |
Package xselinux is the X client API for the SELinux extension.
|
Package xselinux is the X client API for the SELinux extension. |
Package xtest is the X client API for the XTEST extension.
|
Package xtest is the X client API for the XTEST extension. |
Package xv is the X client API for the XVideo extension.
|
Package xv is the X client API for the XVideo extension. |
Package xvmc is the X client API for the XVideo-MotionCompensation extension.
|
Package xvmc is the X client API for the XVideo-MotionCompensation extension. |