x11

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

README

x11 — go-freedesktop

ci Go Reference License Go Coverage

The foundation every X11 client needs before it can say anything of its own — the wire codec, the .Xauthority parser, the connection-setup exchange, the anonymous shared-memory segment MIT-SHM attaches, and the unix-domain transport that hands the server a descriptor over SCM_RIGHTS.

Pure Go, CGO-free, standard library only. No Xlib, no XCB, no cgo — the wire format is encoded and decoded here, byte for byte, per the X11 protocol specification.

Scope — deliberately, the bytes and nothing above them

This package stops at the byte stream. It has no connection type, no event loop and no opinion about what a client does with a connection, because the two things clients do with one — pump events for a window, or pull frames for a capture — want genuinely different request/reply machines over the same socket. Forcing them to share one would make both worse. A consumer builds its own connection type over [Handshake]'s result.

in out
Encoder / Decoder — the wire codec, both byte orders, every read bounds-checked request/reply/event demultiplexing
LoadAuthCookie, ParseXauthority — MIT-MAGIC-COOKIE-1 from $XAUTHORITY window creation, mapping, properties
Handshake + Setup — the setup exchange and its full reply (formats, screens, depths, visuals) keysym / keyboard mapping
Monitors — the displays inside a screen, over RANDR 1.5 / XINERAMA, with their EDID model names the MIT-SHM, XFIXES, Present request encodings
Segment — an anonymous shared-memory region, mapped, for MIT-SHM mode setting, output configuration, xrandr's write side
WrapUnix / DialUnix — the unix transport, SCM_RIGHTS fd passing, readability waiting DISPLAY parsing and socket-path search
The one thing above the bytes: Monitors

An X screen is one coordinate space, and the physical displays are laid out inside it. Both consumers need that layout — a capture to grab the left-hand panel, a toolkit to put a window full-screen on the right one — and the answer does not depend on what the client is for, which is exactly what makes a second copy of it pure duplication.

So it lives here, and it does not need a connection type to do its job: it asks through Requester, two methods (Order, Request) that any request/reply machine already has.

mons, err := x11.Monitors(conn, setup.ScreenOf(0)) // conn is your own type
for _, m := range mons {
    fmt.Println(m.DisplayName(), m.Width, m.Height, m.X, m.Y, m.Primary)
}

Name is the connector RANDR reports (HDMI-1, DP-2); Model is the display's own product name read out of its EDID (VITURE Beast), which is the field to use when an application has to recognise a particular panel rather than a particular socket. DisplayName prefers the model and falls back to the connector. RANDR 1.5 is tried first, then XINERAMA, then the whole screen as a single nameless monitor — a server that offers neither still gets an answer, and the list is never empty.

Transport-agnostic on purpose

Handshake takes any io.ReadWriteCloser. In production that is a dialed unix socket; in a test it is one half of a net.Pipe driven by a scripted fake server. That is not a convenience — it is what lets the entire codec be tested on darwin and on windows, with no X server anywhere, so a protocol bug is caught on every platform rather than only on the one that can run an X server.

rw, err := x11.DialUnix("/tmp/.X11-unix/X0")
if err != nil {
    return err
}
name, data, err := x11.LoadAuthCookie(x11.AuthFilePath(), "", "0")
if err != nil {
    return err
}
setup, err := x11.Handshake(rw, binary.LittleEndian, name, data)
if err != nil {
    return err
}
// setup.Screens[0].RootVisualType() and setup.FormatFor(depth) are now
// everything you need to size and decode an image. Frame your own requests
// over rw from here.

Descriptor passing, and why it is here

MIT-SHM 1.2's AttachFd hands the X server a descriptor for a shared segment, so a full-screen image costs a ~40-byte request instead of megabytes down the socket. That needs two things that are not protocol: a segment (NewSegment — an unlinked file on a tmpfs, mapped MAP_SHARED, the portable equivalent of memfd_create) and a transport that can carry a descriptor (WrapUnix, whose result implements FDSender).

Which MIT-SHM requests a client then sends over them is the client's business and lives in the client: a capture asks the server to write into the segment, a window writes into it and asks the server to read.

Off Linux there is no segment to make: NewSegment reports ErrNoSharedMemory, and everything above it still builds and still passes.

Platforms

linux (amd64, arm64, riscv64, loong64, ppc64le, s390x) everything, against real syscalls
darwin, freebsd, other unix codec + xauth + setup + the unix transport; no shared memory
windows, js/wasm codec + xauth + setup; DialUnix reports ErrNoTransport

Both wire orders are exercised, and the big-endian path is executed on real big-endian (s390x under qemu) rather than merely compiled.

Tests & coverage

100% of statements, on Linux, darwin and windows, with no exemptions. Every line is either pure protocol arithmetic or a syscall behind a package variable a test can fail on purpose — so a number below 100 means a branch nobody has tested, not a platform getting in the way. The gate is .github/coverage-gate.sh and it runs on all three.

go test -coverprofile=cover.out ./... && ./.github/coverage-gate.sh cover.out

Consumers

License

BSD-3-Clause. See LICENSE.

Documentation

Overview

Package x11 is a from-scratch, pure-Go (CGO-free, no non-stdlib dependency) implementation of the pieces of the X Window System protocol, version 11.0, that every X client needs before it can say anything of its own: the wire encoder and decoder, the .Xauthority parser, the connection-setup exchange and its reply, the anonymous shared-memory segment MIT-SHM attaches, and the unix-domain transport that hands the server a descriptor over SCM_RIGHTS.

It deliberately stops there. It has no connection type, no event loop and no opinion about what a client does with a connection: a screen capture and a window toolkit want very different request/reply machines on top of the same bytes, and this package is the bytes. A consumer builds its own connection type over Handshake's result.

The one exception is Monitors, which enumerates the displays laid out inside an X screen over RANDR and XINERAMA. It is here because the answer does not depend on what the client is FOR — a capture and a toolkit want the same rectangles — and it does not need a connection type to give it: it asks through Requester, two methods any request/reply machine already has.

Everything above the socket is transport-agnostic: Handshake takes any io.ReadWriteCloser, so the whole codec is exercisable in-process over a net.Pipe against a scripted fake server. That is what lets the wire format be tested to 100% on darwin and on windows, with no X server anywhere — a protocol bug is caught on every platform, not only on the one that can run an X server.

Index

Constants

View Source
const (
	RandrName    = "RANDR"
	XineramaName = "XINERAMA"
)

Extension names, as QueryExtension spells them.

View Source
const (
	VisualStaticGray  = 0
	VisualGrayScale   = 1
	VisualStaticColor = 2
	VisualPseudoColor = 3
	VisualTrueColor   = 4
	VisualDirectColor = 5
)

Visual classes. Only TrueColor and DirectColor decompose a pixel through the masks; the palette classes would need the colormap read back, which no display built this millennium presents.

View Source
const (
	ImageOrderLSB = 0
	ImageOrderMSB = 1
)

Image byte-order values reported by Setup.ImageByteOrder.

View Source
const (
	OrderLSB = 'l'
	OrderMSB = 'B'
)

The two byte-order sentinels sent as the first byte of the setup request: 'l' little-endian (LSB first), 'B' big-endian (MSB first).

View Source
const (
	FamilyInternet  = 0
	FamilyLocal     = 256
	FamilyWild      = 65535
	FamilyInternet6 = 6
)

Xauthority address families (X11/Xauth.h). Lengths in the file are always big-endian, independent of the machine.

View Source
const AtomNone = 0

AtomNone is the atom that names nothing (X11/Xatom.h).

View Source
const AuthMITCookie = "MIT-MAGIC-COOKIE-1"

AuthMITCookie is the MIT-MAGIC-COOKIE-1 authorization protocol name sent in the setup request when a matching cookie is found in the authority file.

Variables

This section is empty.

Functions

func AuthFilePath

func AuthFilePath() string

AuthFilePath returns the authority file to consult: $XAUTHORITY if set, otherwise $HOME/.Xauthority, otherwise "".

func DialUnix

func DialUnix(path string) (io.ReadWriteCloser, error)

DialUnix connects to the X server's unix-domain socket at path and returns it wrapped by WrapUnix.

func EDIDModelName added in v0.2.0

func EDIDModelName(edid []byte) string

EDIDModelName returns the display product name carried by a base EDID block — the string a user recognises, "DELL U2720Q" rather than "DP-2" — or "" if the blob is not an EDID or carries no name descriptor.

The name is a 13-byte field terminated by a line feed and padded with spaces, so both the terminator and the padding are trimmed. Only the base block is read: the name descriptor is required to be there, and an extension block cannot move it.

func EncodeAuthEntry

func EncodeAuthEntry(e AuthEntry) []byte

EncodeAuthEntry serializes an AuthEntry back to the Xauthority file format. It is the exact inverse of ParseXauthority, and is exported because the only honest way to test a client against a cookie is to write one: a test builds the fixture with this, and a round-trip through the parser proves the two agree.

func LoadAuthCookie

func LoadAuthCookie(authFile, host, display string) (name string, data []byte, err error)

LoadAuthCookie resolves the MIT-MAGIC-COOKIE-1 for (host, display) from the given authority file. A missing file, or no match, is not an error: it returns an empty name and data so the caller falls back to an unauthenticated setup, exactly as Xlib does. host defaults to the machine hostname when empty.

func Pad4

func Pad4(n int) int

Pad4 returns n rounded up to the next multiple of four. X11 pads every variable-length field to a four-byte boundary.

func Padding

func Padding(n int) int

Padding returns the number of pad bytes needed after n data bytes.

func ReadFull

func ReadFull(r io.Reader, b []byte) error

ReadFull reads exactly len(b) bytes or returns the first error. It is kept here so the codec's callers have one spelling of "read a whole packet".

func TrimNul

func TrimNul(b []byte) string

TrimNul returns b up to its first NUL, as a string. X11 zero-pads several text fields (a vendor string, a refusal reason, a format-8 property) and states their length separately or not at all.

func WrapUnix

func WrapUnix(c *net.UnixConn) io.ReadWriteCloser

WrapUnix wraps a dialed *net.UnixConn as an fd-passing transport for Handshake. The result implements FDSender and Waiter.

Types

type AuthEntry

type AuthEntry struct {
	Family  uint16
	Address []byte
	Number  string // display number as ASCII; "" is a wildcard
	Name    string // authorization protocol name
	Data    []byte // the cookie
}

AuthEntry is one record parsed from an Xauthority file.

func ParseXauthority

func ParseXauthority(r io.Reader) ([]AuthEntry, error)

ParseXauthority reads every entry from an Xauthority stream. The file is a flat sequence of records, each a big-endian-length-prefixed family/address/number/name/data quintuple.

type ByteOrder

type ByteOrder = binary.ByteOrder

ByteOrder is the wire byte order negotiated at connection setup. X11 lets the client pick; the server then speaks the client's order for the session.

func OrderFor

func OrderFor(sentinel byte) (ByteOrder, bool)

OrderFor maps a byte-order sentinel to its binary.ByteOrder. The bool reports whether the sentinel was recognised.

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder reads a fixed-order byte slice. Every read is bounds-checked; once the Decoder is not OK it stays that way, so a truncated buffer degrades to a clean error at the call site rather than a panic.

func NewDecoder

func NewDecoder(order ByteOrder, b []byte) *Decoder

NewDecoder wraps b for reading in the given order.

func (*Decoder) Get8

func (d *Decoder) Get8() byte

Get8 reads one byte.

func (*Decoder) Get16

func (d *Decoder) Get16() uint16

Get16 reads a 16-bit value in the decoder's order.

func (*Decoder) Get16s

func (d *Decoder) Get16s() int16

Get16s reads a signed 16-bit value, which is how X11 states coordinates.

func (*Decoder) Get32

func (d *Decoder) Get32() uint32

Get32 reads a 32-bit value in the decoder's order.

func (*Decoder) GetBytes

func (d *Decoder) GetBytes(n int) []byte

GetBytes returns the next n bytes (a copy) and advances.

func (*Decoder) GetString

func (d *Decoder) GetString(n int) string

GetString reads an n-byte string and skips its four-byte padding.

func (*Decoder) OK

func (d *Decoder) OK() bool

OK reports whether every read so far stayed inside the buffer. A parser checks it once, at the end, rather than after every field.

func (*Decoder) Order

func (d *Decoder) Order() ByteOrder

Order returns the byte order the Decoder reads in.

func (*Decoder) Skip

func (d *Decoder) Skip(n int)

Skip advances over n bytes, going not-OK rather than past the end.

type Depth

type Depth struct {
	Depth   uint8
	Visuals []VisualType
}

Depth groups the visuals available at a given colour depth.

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder builds a request body in a chosen byte order. Every multi-byte integer goes through the negotiated ByteOrder, so the same code emits a correct little- or big-endian stream.

func NewEncoder

func NewEncoder(order ByteOrder) *Encoder

NewEncoder starts an Encoder in the given order.

func (*Encoder) Bytes

func (e *Encoder) Bytes() []byte

Bytes returns the bytes written so far. The slice aliases the Encoder's own buffer, so a caller that keeps it past the next write must copy it.

func (*Encoder) Order

func (e *Encoder) Order() ByteOrder

Order returns the byte order the Encoder writes in.

func (*Encoder) Pad

func (e *Encoder) Pad(n int)

Pad appends the padding that follows n written bytes.

func (*Encoder) Put8

func (e *Encoder) Put8(v byte)

Put8 appends one byte.

func (*Encoder) Put16

func (e *Encoder) Put16(v uint16)

Put16 appends a 16-bit value in the negotiated order.

func (*Encoder) Put32

func (e *Encoder) Put32(v uint32)

Put32 appends a 32-bit value in the negotiated order.

func (*Encoder) PutBytes

func (e *Encoder) PutBytes(b []byte)

PutBytes appends raw bytes verbatim (no padding).

func (*Encoder) PutString

func (e *Encoder) PutString(s string)

PutString appends s then pads to a four-byte boundary with zero bytes.

func (*Encoder) Skip

func (e *Encoder) Skip(n int)

Skip appends n zero bytes (for "unused" fixed fields).

type FDSender

type FDSender interface {
	// SendFD writes one already-framed request with fd attached as a single
	// SCM_RIGHTS control message.
	SendFD(msg []byte, fd int) error
}

FDSender is implemented by a transport that can pass a file descriptor alongside a request over the same socket (a unix-domain stream, via SCM_RIGHTS). The transport WrapUnix returns implements it; an in-process net.Pipe used by a test does not, so a client's MIT-SHM fd-passing path degrades to the plain socket path when it is absent.

It is an interface rather than a concrete type because that is what keeps the connection above it transport-agnostic: a client type-asserts on this and never on a socket.

type Format

type Format struct {
	Depth       uint8
	BitsPerPix  uint8
	ScanlinePad uint8
}

Format is one entry of the server's pixmap-format list: for a given colour depth it fixes the bits-per-pixel and the scanline padding a ZPixmap image of that depth uses on the wire. It is what turns a width into a STRIDE.

func (Format) Stride

func (f Format) Stride(width int) int

Stride is the number of BYTES one scanline of a width-pixel ZPixmap image occupies in this format: the pixel bits rounded up to the format's scanline pad. It is not width*BitsPerPix/8 in general, which is exactly why an image must carry it rather than assume it.

type Monitor added in v0.2.0

type Monitor struct {
	// Name is the RANDR monitor name, which is normally the CONNECTOR —
	// "HDMI-1", "DP-2", "eDP-1". It is stable and it is what xrandr prints,
	// but it does not say what is plugged in. It is "" from XINERAMA, which
	// carries no names at all.
	Name string
	// Model is the display's own product name, read out of its EDID: "VITURE
	// Beast", "DELL U2720Q". It is what a user recognises, and the only field
	// that can tell two identical connectors apart by what is on the end of
	// them — so an application that identifies a headset by name wants this
	// one. It is "" when the output publishes no EDID (a virtual server such
	// as Xvfb, or a driver that does not export the property).
	Model string
	// NameAtom is the atom Name was resolved from, kept because a caller that
	// re-queries can compare atoms without a round trip.
	NameAtom uint32
	// Primary marks the monitor the desktop treats as its origin.
	Primary bool
	// Automatic marks a monitor RANDR synthesised from the outputs rather than
	// one configured by hand with `xrandr --setmonitor`.
	Automatic bool
	// X, Y, Width, Height are the monitor's rectangle inside the screen's
	// coordinate space, top-left origin, Y growing downwards.
	X, Y          int16
	Width, Height uint16
	// WidthMM, HeightMM are the physical size, which is what a DPI is computed
	// from. Both are 0 on a display that reports none.
	WidthMM  uint32
	HeightMM uint32
	// Outputs are the RANDR output ids driving this monitor. Empty from
	// XINERAMA and from the whole-screen fallback.
	Outputs []uint32
}

Monitor is one physical output's rectangle inside an X screen.

func Monitors added in v0.2.0

func Monitors(r Requester, sc *Screen) ([]Monitor, error)

Monitors lists the monitors of screen sc, trying RANDR 1.5 first — with the displays' own model names filled in where they publish an EDID — then XINERAMA, and falling back to the whole screen as a single nameless monitor.

It never returns an empty list without an error: a screen always has at least itself. An extension that is absent, that refuses, or that answers nothing is not an error either; it just means the next way of asking gets a turn. The one error is a screen that does not exist.

func (Monitor) DisplayName added in v0.2.0

func (m Monitor) DisplayName() string

DisplayName is the best human-readable name for the monitor: the EDID model when the display published one, the connector otherwise. It is what to show a user choosing an output.

func (Monitor) String added in v0.2.0

func (m Monitor) String() string

String renders the monitor for logs.

type Randr added in v0.2.0

type Randr struct {
	VerMajor uint32
	VerMinor uint32
	// contains filtered or unexported fields
}

Randr is a queried RANDR handle: the extension's major opcode plus the version the server agreed to speak.

func QueryRandr added in v0.2.0

func QueryRandr(r Requester) (*Randr, error)

QueryRandr queries RANDR and negotiates version 1.5, which is the one that carries RRGetMonitors. It returns (nil, nil) when the server has no RANDR, because "the server does not offer it" is an answer, not a failure.

func (*Randr) GetMonitors added in v0.2.0

func (rr *Randr) GetMonitors(root uint32) ([]Monitor, error)

GetMonitors lists the monitors of the screen rooted at root. Names are resolved from their atoms, so a monitor comes back as "HDMI-1" rather than as a number; models are NOT read here, because that costs one round trip per output and a caller that only wants rectangles should not pay for it. Use Randr.ResolveModels or Monitors for those.

func (*Randr) HasMonitors added in v0.2.0

func (rr *Randr) HasMonitors() bool

HasMonitors reports whether the negotiated version carries RRGetMonitors, which arrived in RANDR 1.5.

func (*Randr) OutputProperty added in v0.2.0

func (rr *Randr) OutputProperty(output, property uint32, maxWords uint32) (format byte, value []byte, err error)

OutputProperty reads up to maxWords 32-bit words of a RANDR output property. A property the output does not have comes back with format 0 and no value, which is not an error.

func (*Randr) ResolveModels added in v0.2.0

func (rr *Randr) ResolveModels(mons []Monitor) error

ResolveModels fills in the Model of each monitor from its outputs' EDID.

It is best-effort by construction: an output with no EDID property, a server that refuses the request, and a blob that is not an EDID all leave Model empty rather than failing the enumeration — the rectangles are still right, and a caller that wanted them should not lose them because a display declines to introduce itself. It reports an error only when the EDID atom itself cannot be looked up, which means the connection is in trouble.

type Requester added in v0.2.0

type Requester interface {
	// Order returns the byte order negotiated at connection setup.
	Order() ByteOrder
	// Request sends one request and returns its reply. op names the request
	// for error messages; opcode is the major opcode — a core one, or an
	// extension's as QueryExtension reported it; data is the byte the protocol
	// packs into the request header. body must already be 4-byte padded.
	//
	// The reply is the 32-byte fixed part followed by whatever additional data
	// the request carries, as one slice. An error reply comes back as an
	// error, not as a packet.
	Request(op string, opcode, data byte, body []byte) ([]byte, error)
}

Requester is what the monitor enumeration needs of a connection, and all it needs: the negotiated byte order, and the ability to send a request and be handed its reply.

This package deliberately owns no connection type (see the package comment), because a capture loop and an event pump want genuinely different request/reply machines over the same socket. Both of them can satisfy this, though, and that is what lets one enumeration serve both.

type Screen

type Screen struct {
	Root          uint32
	DefaultColmap uint32
	WhitePixel    uint32
	BlackPixel    uint32
	Width         uint16
	Height        uint16
	WidthMM       uint16
	HeightMM      uint16
	RootVisual    uint32
	RootDepth     uint8
	Depths        []Depth
}

Screen is one root screen: its root window, size, root visual and the allowed depths (each carrying its visuals).

func (*Screen) DepthOfVisual

func (sc *Screen) DepthOfVisual(id uint32) (uint8, bool)

DepthOfVisual returns the colour depth the given visual lives at, and whether it was found.

func (*Screen) FindVisual

func (sc *Screen) FindVisual(id uint32) (VisualType, bool)

FindVisual returns the VisualType with the given id on screen sc, and whether it was found.

func (*Screen) RootVisualType

func (sc *Screen) RootVisualType() VisualType

RootVisualType returns the screen's root visual descriptor, falling back to a synthesized 24-bit TrueColor BGRX visual if the root visual id is somehow absent from the depth list (defensive; real servers always list it).

type Segment

type Segment struct {
	Seg  uint32
	FD   int
	Data []byte
	// contains filtered or unexported fields
}

Segment is a mapped anonymous shared-memory region backing a MIT-SHM attachment: Data is the pixel store both peers see, FD is the descriptor handed to the X server by the extension's AttachFd request, and Seg is the resource id the server knows it by.

It is the memory, not the protocol. Which AttachFd/PutImage/GetImage requests a client sends over it is the client's business — a capture asks the server to WRITE into the segment, a window writes into it and asks the server to read — and those requests live in the consumer, not here.

The lifecycle is portable; the shared-memory syscalls themselves sit behind createAnonFile/mmapRegion/munmapRegion/closeFD, which are provided per platform. Off Linux there is no X server to attach to, so createAnonFile reports [ErrNoSharedMemory] and no segment is ever created.

func NewSegment

func NewSegment(seg uint32, size int) (*Segment, error)

NewSegment allocates and maps a shared-memory segment of size bytes and assigns it the resource id seg. The caller registers it with the server via the MIT-SHM AttachFd request and frees it with Segment.Close.

func (*Segment) Close

func (s *Segment) Close() error

Close unmaps the region and closes its descriptor, returning the first error (both steps are attempted regardless). It is idempotent, so a deferred Close after an explicit one is harmless.

func (*Segment) Size

func (s *Segment) Size() int

Size returns the segment's byte length.

type Setup

type Setup struct {
	ProtoMajor     uint16
	ProtoMinor     uint16
	Release        uint32
	ResourceIDBase uint32
	ResourceIDMask uint32
	Vendor         string
	MaxRequestLen  uint16 // in 4-byte units
	ImageByteOrder uint8  // 0 = LSBFirst, 1 = MSBFirst
	BitmapBitOrder uint8
	BitmapUnit     uint8
	BitmapPad      uint8
	MinKeycode     uint8
	MaxKeycode     uint8
	Formats        []Format
	Screens        []Screen
}

Setup is the parsed server connection-setup reply: everything a client needs to allocate resource IDs, pick a visual, size images correctly and map keycodes.

func Handshake

func Handshake(rw io.ReadWriteCloser, order ByteOrder, authName string, authData []byte) (*Setup, error)

Handshake runs the client connection setup over rw: it sends the byte-order sentinel, protocol 11.0 and the authorization name and data, then reads and parses the server's reply. order selects the wire byte order; both are valid and the server adopts the client's choice for the whole session.

It returns only the parsed Setup. Framing requests and demultiplexing replies, errors and events is the caller's business, and the two things a client does with a connection — pump events, or push frames — want different machines over the same socket. What is common is everything up to this point, which is what this function is.

On return, rw is positioned exactly at the first byte the server sends after the setup reply, so the caller can start reading packets immediately. On error rw is left as it is: the caller closes it.

func (*Setup) FormatFor

func (s *Setup) FormatFor(depth uint8) (Format, bool)

FormatFor returns the pixmap Format matching depth, and whether one exists. It is what sizes each pixel and pads each scanline of an image at that depth.

func (*Setup) ScreenOf

func (s *Setup) ScreenOf(i int) *Screen

ScreenOf returns screen i, or nil when i names no screen.

func (*Setup) ScreenOfRoot

func (s *Setup) ScreenOfRoot(root uint32) (int, bool)

ScreenOfRoot returns the index of the screen whose root window is root, and whether one matched.

type SetupError

type SetupError struct {
	Reason       string
	Authenticate bool // the server asked for further authentication
}

SetupError is the connection-setup refusal: the server would not talk to us at all. Reason is the server's own wording, which for a missing or wrong cookie is "No protocol specified" or "Authorization required".

func (*SetupError) Error

func (e *SetupError) Error() string

Error renders the refusal.

type VisualType

type VisualType struct {
	ID          uint32
	Class       uint8
	BitsPerRGB  uint8
	ColormapEnt uint16
	RedMask     uint32
	GreenMask   uint32
	BlueMask    uint32
}

VisualType describes a visual: its class and the RGB channel masks a TrueColor or DirectColor visual packs a pixel with. The masks are what convert a pixel to or from any other layout.

func (VisualType) Direct

func (v VisualType) Direct() bool

Direct reports whether the visual's pixels decompose through its masks.

type Waiter

type Waiter interface {
	// WaitReadable reports whether the server sent anything within d. An
	// implementation must not consume a partial packet: see the note on the
	// unix transport for why a read deadline is not a substitute.
	WaitReadable(d time.Duration) bool
}

Waiter is implemented by a transport that can say whether the server sent anything, without reading a whole packet. The transport WrapUnix returns implements it.

It exists because parts of the X11 protocol have no timeout of their own — a selection paste asks whoever owns the clipboard and waits for an event that arrives only if that owner is alive and still answering. A client that cannot bound that wait freezes.

type Xinerama added in v0.2.0

type Xinerama struct {
	VerMajor uint16
	VerMinor uint16
	// contains filtered or unexported fields
}

Xinerama is a queried XINERAMA handle.

func QueryXinerama added in v0.2.0

func QueryXinerama(r Requester) (*Xinerama, error)

QueryXinerama queries XINERAMA. It returns (nil, nil) when the server has none.

func (*Xinerama) QueryScreens added in v0.2.0

func (x *Xinerama) QueryScreens() ([]Monitor, error)

QueryScreens lists the Xinerama screens, which are the same rectangles RANDR would call monitors, without names.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL