detached f8d04d7

Merge 582be8898a7ccc047433fa09a66bdcefe4ffeb8e into ba4ad521151d3500de111a037937f8e1dd3922d2

commit
f8d04d7aa74c29121d9f1ea4b438f519b8c49577
author
ermite · · 2026-10-22 06:28 UTC
merge of
ba4ad52 + 582be88 · diff against the first parent
signature
unsigned
60 files · +9337 -1
A bigreq/requests_generated.go +21 -0
@@ -0,0 +1,21 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package bigreq
3+
4+import "bnema.dev/xturbo"
5+
6+func Enable(b *xturbo.Buf) xturbo.Seq {
7+ if b.Ext == nil {
8+ b.Fail(xturbo.ErrExtMissing)
9+ return 0
10+ }
11+ major := b.Ext.Major(xturbo.ExtBigRequests)
12+ if major == 0 {
13+ b.Fail(xturbo.ErrExtMissing)
14+ return 0
15+ }
16+ p, seq := b.Request(major, 0, 0)
17+ if p == nil {
18+ return 0
19+ }
20+ return seq
21+}
A bigreq/sizes_test.go +11 -0
@@ -0,0 +1,11 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package bigreq
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("reply Enable fixed size = %d", got)
9+ }
10+
11+}
A bigreq/types_generated.go +2 -0
@@ -0,0 +1,2 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package bigreq
A buf.go +92 -0
@@ -0,0 +1,92 @@
1+package xturbo
2+
3+import (
4+ "encoding/binary"
5+ "errors"
6+)
7+
8+// Seq identifies a request; zero is invalid.
9+type Seq uint64
10+
11+var (
12+ ErrRequestTooLarge = errors.New("xturbo: request too large")
13+ ErrExtMissing = errors.New("xturbo: extension missing")
14+ ErrBadLength = errors.New("xturbo: bad length")
15+ ErrSeqOverflow = errors.New("xturbo: sequence overflow")
16+)
17+
18+// Buf is the caller-owned request encoder. The transport will own flushing and
19+// acknowledgment in Phase 3. It is not safe for concurrent use.
20+type Buf struct {
21+ Ext *ExtTable
22+ b []byte
23+ flushed int
24+ next, acked Seq
25+ maxReq uint32
26+ err error
27+}
28+
29+func NewBuf(size int) *Buf {
30+ if size <= 0 {
31+ size = 64 << 10
32+ }
33+ return &Buf{b: make([]byte, 0, size), next: 1, maxReq: 262140}
34+}
35+func (b *Buf) Fail(err error) {
36+ if b.err == nil {
37+ b.err = err
38+ }
39+}
40+func (b *Buf) Err() error { return b.err }
41+func (b *Buf) Reset() { b.b = b.b[:0]; b.flushed = 0 }
42+func (b *Buf) Bytes() []byte { return b.b[b.flushed:] }
43+func (b *Buf) Len() int { return len(b.b) - b.flushed }
44+func (b *Buf) Next() Seq { return b.next }
45+
46+// Request reserves a zeroed, four-byte-aligned body after the wire header.
47+// BIG-REQUESTS enablement is transport-owned; maxReq starts at the core limit.
48+func (b *Buf) Request(major, data uint8, body int) ([]byte, Seq) {
49+ if b.err != nil {
50+ return nil, 0
51+ }
52+ if body < 0 || body&3 != 0 {
53+ b.Fail(ErrBadLength)
54+ return nil, 0
55+ }
56+ if uint64(body)+4 > uint64(b.maxReq) {
57+ b.Fail(ErrRequestTooLarge)
58+ return nil, 0
59+ }
60+ if b.next-b.acked >= 0xffff {
61+ b.Fail(ErrSeqOverflow)
62+ return nil, 0
63+ }
64+ header := 4
65+ if (body+4)/4 > 0xffff {
66+ header = 8
67+ }
68+ total := body + header
69+ start := len(b.b)
70+ if total > cap(b.b)-start {
71+ capacity := cap(b.b) * 2
72+ if capacity < start+total {
73+ capacity = start + total
74+ }
75+ grown := make([]byte, start, capacity)
76+ copy(grown, b.b)
77+ b.b = grown
78+ }
79+ b.b = b.b[:start+total]
80+ p := b.b[start:]
81+ clear(p)
82+ p[0] = major
83+ p[1] = data
84+ if header == 4 {
85+ binary.LittleEndian.PutUint16(p[2:], uint16(total/4))
86+ } else {
87+ binary.LittleEndian.PutUint32(p[4:], uint32(total/4))
88+ }
89+ seq := b.next
90+ b.next++
91+ return p[header:], seq
92+}
A buf_test.go +69 -0
@@ -0,0 +1,69 @@
1+package xturbo
2+
3+import (
4+ "bytes"
5+ "encoding/binary"
6+ "errors"
7+ "testing"
8+)
9+
10+func TestBufRequest(t *testing.T) {
11+ b := NewBuf(4)
12+ p, seq := b.Request(8, 2, 4)
13+ if seq != 1 || len(p) != 4 || !bytes.Equal(b.Bytes(), []byte{8, 2, 2, 0, 0, 0, 0, 0}) {
14+ t.Fatalf("%x %d", b.Bytes(), seq)
15+ }
16+ p[0] = 255
17+ b.Reset()
18+ p, seq = b.Request(14, 0, 4)
19+ if seq != 2 || p[0] != 0 || b.Next() != 3 || b.Len() != 8 {
20+ t.Fatal("reset sequence/zeroing")
21+ }
22+ first := errors.New("first")
23+ b.Fail(first)
24+ b.Fail(ErrBadLength)
25+ p, seq = b.Request(1, 0, 0)
26+ if p != nil || seq != 0 || b.Err() != first {
27+ t.Fatal("sticky error")
28+ }
29+}
30+func TestBufLimits(t *testing.T) {
31+ for _, body := range []int{-1, 1, 262140} {
32+ b := NewBuf(0)
33+ p, s := b.Request(1, 0, body)
34+ if p != nil || s != 0 || b.Err() == nil || b.Len() != 0 {
35+ t.Fatal(body)
36+ }
37+ }
38+ b := NewBuf(0)
39+ b.next = 0xffff
40+ if p, s := b.Request(1, 0, 0); p != nil || s != 0 || b.Err() != ErrSeqOverflow {
41+ t.Fatal("overflow")
42+ }
43+ b = NewBuf(0)
44+ b.maxReq = 1 << 20
45+ p, s := b.Request(1, 0, 262140)
46+ if s != 1 || len(p) != 262140 || binary.LittleEndian.Uint16(b.Bytes()[2:]) != 0 || binary.LittleEndian.Uint32(b.Bytes()[4:]) != 65537 {
47+ t.Fatal("BIG-REQUESTS header")
48+ }
49+}
50+func TestAllocBufRequest(t *testing.T) {
51+ for _, body := range []int{4, 65536} {
52+ b := NewBuf(128 << 10)
53+ if n := testing.AllocsPerRun(1000, func() { b.Reset(); b.Request(1, 0, body) }); n != 0 {
54+ t.Fatal(n)
55+ }
56+ if b.Err() != nil {
57+ t.Fatal(b.Err())
58+ }
59+ }
60+}
61+func BenchmarkBufRequest(b *testing.B) {
62+ buf := NewBuf(0)
63+ b.ReportAllocs()
64+ for b.Loop() {
65+ buf.Reset()
66+ buf.acked = buf.next
67+ buf.Request(1, 0, 4)
68+ }
69+}
A cmd/xtgen/emit.go +252 -0
@@ -0,0 +1,252 @@
1+package main
2+
3+import (
4+ "bytes"
5+ "embed"
6+ "fmt"
7+ "go/format"
8+ "os"
9+ "path/filepath"
10+ "sort"
11+ "strings"
12+ "text/template"
13+)
14+
15+//go:embed templates/*.tmpl
16+var templates embed.FS
17+
18+func writeTemplate(path, name string, data any) error {
19+ t, err := template.ParseFS(templates, "templates/"+name+".tmpl")
20+ if err != nil {
21+ return err
22+ }
23+ var b bytes.Buffer
24+ if err = t.Execute(&b, data); err != nil {
25+ return err
26+ }
27+ code, err := format.Source(b.Bytes())
28+ if err != nil {
29+ return fmt.Errorf("format %s: %w\n%s", path, err, b.String())
30+ }
31+ if err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {
32+ return err
33+ }
34+ return os.WriteFile(path, code, 0644)
35+}
36+func putScalar(t *Type, src, dst string) string {
37+ if t.Base == "bool" {
38+ if t.Size == 1 {
39+ return fmt.Sprintf("if %s { %s[0]=1 } else { %s[0]=0 };", src, dst, dst)
40+ }
41+ return fmt.Sprintf("if %s { binary.LittleEndian.PutUint32(%s,1) } else { binary.LittleEndian.PutUint32(%s,0) };", src, dst, dst)
42+ }
43+ if t.Size == 1 {
44+ return fmt.Sprintf("%s[0]=byte(%s);", dst, src)
45+ }
46+ return fmt.Sprintf("binary.LittleEndian.PutUint%d(%s,uint%d(%s));", 8*t.Size, dst, 8*t.Size, src)
47+}
48+func getScalar(t *Type, goType, src string) string {
49+ value := src + "[0]"
50+ if t.Size > 1 {
51+ value = fmt.Sprintf("binary.LittleEndian.Uint%d(%s)", 8*t.Size, src)
52+ }
53+ if t.Base == "bool" {
54+ return "(" + value + "!=0)"
55+ }
56+ return goType + "(" + value + ")"
57+}
58+func isScalar(t *Type) bool { return t.Base != "" }
59+func typeDecl(t *Type) (string, error) {
60+ if isScalar(t) {
61+ return fmt.Sprintf("type %s %s", t.GoType, t.Base), nil
62+ }
63+ var b strings.Builder
64+ if t.Kind == "union" {
65+ fmt.Fprintf(&b, "type %s struct { raw []byte }; const %sSize=%d;\n", t.GoType, t.GoType, t.Size)
66+ fmt.Fprintf(&b, "func Get%s(p []byte) %s { return %s{raw:p[:%d]} };\n", t.GoType, t.GoType, t.GoType, t.Size)
67+ fmt.Fprintf(&b, "func (v %s) Put(p []byte) { copy(p[:%d],v.raw) };\n", t.GoType, t.Size)
68+ for _, f := range t.Fields {
69+ if f.Kind == "pad" {
70+ continue
71+ }
72+ if f.Kind == "list" {
73+ fmt.Fprintf(&b, "func (v %s) %s() (out %s) { for i:=range out { out[i]=%s }; return };\n", t.GoType, f.Name, f.GoType, getScalar(f.Type, qualified(t.Module, f.Type.Module, f.Type.GoType), fmt.Sprintf("v.raw[i*%d:]", f.Type.Size)))
74+ } else {
75+ fmt.Fprintf(&b, "func (v %s) %s() %s { return %s };\n", t.GoType, f.Name, f.GoType, getScalar(f.Type, f.GoType, "v.raw"))
76+ }
77+ }
78+ return b.String(), nil
79+ }
80+ fmt.Fprintf(&b, "type %s struct {\n", t.GoType)
81+ for _, f := range t.Fields {
82+ if f.Kind != "pad" {
83+ name := f.Name
84+ if name == "Size" || name == "Put" {
85+ name += "_"
86+ }
87+ fmt.Fprintf(&b, "%s %s\n", name, f.GoType)
88+ }
89+ }
90+ b.WriteString("}\n")
91+ fmt.Fprintf(&b, "const %sSize=%d;\n", t.GoType, t.Size)
92+ if t.Variable {
93+ fmt.Fprintf(&b, "func (v %s) Size() int { off:=0;", t.GoType)
94+ for _, f := range t.Fields {
95+ name := f.Name
96+ if name == "Size" || name == "Put" {
97+ name += "_"
98+ }
99+ if f.Align > 0 {
100+ fmt.Fprintf(&b, "off=(off+%d)&^%d;", f.Align-1, f.Align-1)
101+ } else if f.Kind == "list" && f.Count == 0 {
102+ if f.Type.Variable {
103+ fmt.Fprintf(&b, "for i:=range v.%s { off+=v.%s[i].Size() };", name, name)
104+ } else {
105+ fmt.Fprintf(&b, "off+=len(v.%s)*%d;", name, f.Type.Size)
106+ }
107+ } else {
108+ fmt.Fprintf(&b, "off+=%d;", f.Size)
109+ }
110+ }
111+ b.WriteString("return off };\n")
112+ }
113+ fmt.Fprintf(&b, "func (v %s) Put(p []byte) { ", t.GoType)
114+ if t.Variable {
115+ b.WriteString("off:=0;")
116+ } else {
117+ fmt.Fprintf(&b, "clear(p[:%d]);", t.Size)
118+ }
119+ for _, f := range t.Fields {
120+ name := f.Name
121+ if name == "Size" || name == "Put" {
122+ name += "_"
123+ }
124+ off := fmt.Sprint(f.Off)
125+ if t.Variable {
126+ off = "off"
127+ }
128+ if f.Kind == "pad" {
129+ if t.Variable {
130+ if f.Align > 0 {
131+ fmt.Fprintf(&b, "{ next:=(off+%d)&^%d; clear(p[off:next]); off=next };", f.Align-1, f.Align-1)
132+ } else {
133+ fmt.Fprintf(&b, "clear(p[off:off+%d]); off+=%d;", f.Size, f.Size)
134+ }
135+ }
136+ continue
137+ }
138+ src := "v." + name
139+ dst := "p[" + off + ":]"
140+ if f.Kind == "list" {
141+ fmt.Fprintf(&b, "for i:=range %s {", src)
142+ item := src + "[i]"
143+ target := fmt.Sprintf("p[%s+i*%d:]", off, f.Type.Size)
144+ if f.Type.Variable {
145+ target = "p[off:]"
146+ }
147+ if isScalar(f.Type) {
148+ b.WriteString(putScalar(f.Type, item, target))
149+ } else {
150+ fmt.Fprintf(&b, "%s.Put(%s);", item, target)
151+ }
152+ if f.Type.Variable {
153+ fmt.Fprintf(&b, "off+=%s.Size();", item)
154+ }
155+ b.WriteString("};")
156+ if t.Variable && !f.Type.Variable {
157+ fmt.Fprintf(&b, "off+=len(%s)*%d;", src, f.Type.Size)
158+ }
159+ } else {
160+ if isScalar(f.Type) {
161+ b.WriteString(putScalar(f.Type, src, dst))
162+ } else {
163+ fmt.Fprintf(&b, "%s.Put(%s);", src, dst)
164+ }
165+ if t.Variable {
166+ fmt.Fprintf(&b, "off+=%d;", f.Size)
167+ }
168+ }
169+ }
170+ b.WriteString("}\n")
171+ if !t.Variable {
172+ fmt.Fprintf(&b, "func Get%s(p []byte) (v %s) { _=p[%d];", t.GoType, t.GoType, t.Size-1)
173+ for _, f := range t.Fields {
174+ if f.Kind == "pad" {
175+ continue
176+ }
177+ dst := "v." + f.Name
178+ src := fmt.Sprintf("p[%d:]", f.Off)
179+ if f.Kind == "list" {
180+ fmt.Fprintf(&b, "for i:=range %s { %s[i]=%s };", dst, dst, getScalar(f.Type, qualified(t.Module, f.Type.Module, f.Type.GoType), fmt.Sprintf("p[%d+i*%d:]", f.Off, f.Type.Size)))
181+ } else if isScalar(f.Type) {
182+ fmt.Fprintf(&b, "%s=%s;", dst, getScalar(f.Type, f.GoType, src))
183+ } else {
184+ fmt.Fprintf(&b, "%s=%s(%s);", dst, qualified(t.Module, f.Type.Module, "Get"+f.Type.GoType), src)
185+ }
186+ }
187+ b.WriteString("return };\n")
188+ }
189+ return b.String(), nil
190+}
191+func importsFor(m *Module, decls string) string {
192+ paths := map[string]string{"binary.": "encoding/binary", "bits.": "math/bits"}
193+ for _, dep := range m.Imports {
194+ paths[dep.Pkg+"."] = "bnema.dev/xturbo/" + dep.Pkg
195+ }
196+ var imports []string
197+ for prefix, path := range paths {
198+ if strings.Contains(decls, prefix) {
199+ imports = append(imports, fmt.Sprintf("import %q", path))
200+ }
201+ }
202+ sort.Strings(imports)
203+ return strings.Join(imports, "\n")
204+}
205+func emitTypes(modules []*Module) error {
206+ for _, m := range modules {
207+ for _, t := range m.Types {
208+ decl, err := typeDecl(t)
209+ if err != nil {
210+ return err
211+ }
212+ m.Decls = append(m.Decls, decl)
213+ }
214+ for _, e := range m.Enums {
215+ var b strings.Builder
216+ if !e.Existing {
217+ fmt.Fprintf(&b, "type %s %s;\n", e.Name, e.Base)
218+ }
219+ for _, item := range e.Items {
220+ fmt.Fprintf(&b, "const %s %s = %d;\n", item.Name, e.Name, item.Value)
221+ }
222+ m.Decls = append(m.Decls, b.String())
223+ }
224+ imp := importsFor(m, strings.Join(m.Decls, "\n"))
225+ m.Decls = append([]string{imp}, m.Decls...)
226+ if err := writeTemplate(filepath.Join(m.Pkg, "types_generated.go"), "types", m); err != nil {
227+ return err
228+ }
229+ for _, t := range m.Types {
230+ if t.Kind == "struct" || t.Kind == "union" {
231+ m.SizeChecks = append(m.SizeChecks, fmt.Sprintf("if %sSize != %d { t.Errorf(%q, %sSize) }", t.GoType, t.Size, t.GoType+" fixed prefix = %d", t.GoType))
232+ }
233+ }
234+ if err := packetSizeChecks(m); err != nil {
235+ return err
236+ }
237+ if err := writeTemplate(filepath.Join(m.Pkg, "sizes_test.go"), "sizes", m); err != nil {
238+ return err
239+ }
240+ }
241+ var extensions []*Module
242+ for _, m := range modules {
243+ if m.ExtName != "" {
244+ extensions = append(extensions, m)
245+ }
246+ }
247+ return writeTemplate("ext_generated.go", "ext", extensions)
248+}
249+
250+func sizeCheck(name string, got, want int) string {
251+ return fmt.Sprintf("if got:= %d; got != %d { t.Errorf(%q,got) }", got, want, name+" fixed size = %d")
252+}
A cmd/xtgen/expr.go +43 -0
@@ -0,0 +1,43 @@
1+package main
2+
3+import "fmt"
4+
5+// renderExpr centralizes expression lowering; callers supply parameter, owned
6+// field, or getter references. No expression decisions are left to templates.
7+func renderExpr(n *Node, ref func(string) string, m *Module) (string, error) {
8+ if n == nil {
9+ return "", nil
10+ }
11+ switch n.Kind {
12+ case "value":
13+ return n.Text, nil
14+ case "fieldref":
15+ return ref(n.Text), nil
16+ case "enumref":
17+ e, owner := findEnum(m, n.Attr["ref"])
18+ if e == nil {
19+ return "", n.fail("unknown enum %s", n.Attr["ref"])
20+ }
21+ return "int(" + qualified(m, owner, e.Name+goName(n.Text)) + ")", nil
22+ case "op", "unop", "popcount":
23+ var parts []string
24+ for _, c := range n.Children {
25+ s, err := renderExpr(c, ref, m)
26+ if err != nil {
27+ return "", err
28+ }
29+ parts = append(parts, s)
30+ }
31+ if n.Kind == "popcount" {
32+ return "bits.OnesCount(uint(" + parts[0] + "))", nil
33+ }
34+ if n.Kind == "unop" {
35+ return "(^" + parts[0] + ")", nil
36+ }
37+ if len(parts) != 2 {
38+ return "", n.fail("invalid binary expression")
39+ }
40+ return "(" + parts[0] + " " + n.Attr["op"] + " " + parts[1] + ")", nil
41+ }
42+ return "", fmt.Errorf("%s:%d: unsupported expression %s", n.File, n.Line, n.Kind)
43+}
A cmd/xtgen/ir.go +39 -0
@@ -0,0 +1,39 @@
1+package main
2+
3+// Type is a resolved wire type. Size is the fixed prefix, not Go's memory size.
4+type Type struct {
5+ Name, GoType, Base, Kind string
6+ Size int
7+ Variable bool
8+ Node *Node
9+ Module *Module
10+ Fields []Field
11+ Resolving, Resolved bool
12+}
13+type Field struct {
14+ Name, Param, GoType, Kind string
15+ Off, Size, Count, Align int
16+ Type *Type
17+ Node *Node
18+ Expr *Node
19+}
20+type Enum struct {
21+ Name, Base string
22+ Existing bool
23+ Items []EnumItem
24+ Node *Node
25+}
26+type EnumItem struct {
27+ Name string
28+ Value int64
29+}
30+type Module struct {
31+ Pkg, Header, XName, ExtName string
32+ Root *Node
33+ Imports []*Module
34+ Types []*Type
35+ Enums []Enum
36+ Symbols map[string]*Type
37+ Names map[string]*Node
38+ Decls, SizeChecks []string
39+}
A cmd/xtgen/layout.go +103 -0
@@ -0,0 +1,103 @@
1+package main
2+
3+import "strconv"
4+
5+// packetFixed computes the minimum complete packet size. The first XML byte
6+// occupies byte 1; the implicit sequence/length header follows that byte.
7+func packetFixed(m *Module, n *Node, reply bool) (int, error) {
8+ off := 1
9+ if n.Attr["no-sequence-number"] == "true" {
10+ off = 1
11+ }
12+ for _, f := range n.Children {
13+ if f.Kind == "doc" {
14+ continue
15+ }
16+ size := 0
17+ switch f.Kind {
18+ case "pad":
19+ if a := f.Attr["align"]; a != "" {
20+ align, _ := strconv.Atoi(a)
21+ size = (-off) & (align - 1)
22+ } else {
23+ size, _ = strconv.Atoi(f.Attr["bytes"])
24+ }
25+ case "field", "exprfield":
26+ typ, err := lookup(m, f.Attr["type"])
27+ if err != nil {
28+ return 0, err
29+ }
30+ size = typ.Size
31+ case "list":
32+ if len(f.Children) == 1 && f.Children[0].Kind == "value" {
33+ count, _ := strconv.Atoi(f.Children[0].Text)
34+ typ, err := lookup(m, f.Attr["type"])
35+ if err != nil {
36+ return 0, err
37+ }
38+ size = count * typ.Size
39+ } else {
40+ goto done
41+ }
42+ default:
43+ return 0, f.fail("unsupported packet member %s", f.Kind)
44+ }
45+ off += size
46+ if off == 2 && n.Attr["no-sequence-number"] != "true" {
47+ if reply {
48+ off = 8
49+ } else {
50+ off = 4
51+ }
52+ }
53+ }
54+done:
55+ if off < 32 {
56+ off = 32
57+ }
58+ return off, nil
59+}
60+func packetSizeChecks(m *Module) error {
61+ for _, n := range m.Root.Children {
62+ if n.Kind == "event" || n.Kind == "eventcopy" {
63+ size := 32
64+ if n.Kind == "event" {
65+ var err error
66+ size, err = packetFixed(m, n, false)
67+ if err != nil {
68+ return err
69+ }
70+ }
71+ if size != 32 {
72+ return n.fail("event fixed size %d, expected 32", size)
73+ }
74+ m.SizeChecks = append(m.SizeChecks, sizeCheck("event "+n.Attr["name"], size, 32))
75+ }
76+ if n.Kind == "request" {
77+ for _, r := range n.Children {
78+ if r.Kind != "reply" {
79+ continue
80+ }
81+ size, err := packetFixed(m, r, true)
82+ if err != nil {
83+ return err
84+ }
85+ expected := 32
86+ if m.Header == "xproto" {
87+ switch n.Attr["name"] {
88+ case "QueryKeymap":
89+ expected = 40
90+ case "GetKeyboardControl":
91+ expected = 52
92+ case "GetWindowAttributes":
93+ expected = 44
94+ case "QueryFont", "ListFontsWithInfo":
95+ expected = 60
96+ }
97+ }
98+ m.SizeChecks = append(m.SizeChecks, sizeCheck("reply "+n.Attr["name"], size, expected))
99+ }
100+ }
101+ }
102+ return nil
103+}
M cmd/xtgen/main.go +44 -1
@@ -1,4 +1,47 @@
1 // Command xtgen generates bindings from the pinned xcb-proto XML.1 // Command xtgen generates bindings from the pinned xcb-proto XML.
2 package main2 package main
3 3
4-func main() {}4+import (
5+ "flag"
6+ "fmt"
7+ "os"
8+ "path/filepath"
9+)
10+
11+func main() {
12+ all := flag.Bool("all", false, "process all vendored modules")
13+ flag.Parse()
14+ paths := flag.Args()
15+ if *all {
16+ var err error
17+ paths, err = filepath.Glob("spec/xml/*.xml")
18+ if err != nil {
19+ fmt.Fprintln(os.Stderr, err)
20+ os.Exit(1)
21+ }
22+ }
23+ if len(paths) == 0 {
24+ fmt.Fprintln(os.Stderr, "xtgen: supply XML paths or -all")
25+ os.Exit(1)
26+ }
27+ if *all {
28+ modules, err := loadModules()
29+ if err == nil {
30+ err = emitTypes(modules)
31+ }
32+ if err == nil {
33+ err = emitRequests(modules)
34+ }
35+ if err != nil {
36+ fmt.Fprintln(os.Stderr, err)
37+ os.Exit(1)
38+ }
39+ return
40+ }
41+ for _, path := range paths {
42+ if _, err := parseFile(path); err != nil {
43+ fmt.Fprintln(os.Stderr, err)
44+ os.Exit(1)
45+ }
46+ }
47+}
A cmd/xtgen/naming.go +43 -0
@@ -0,0 +1,43 @@
1+package main
2+
3+import (
4+ "go/token"
5+ "strings"
6+ "unicode"
7+)
8+
9+func goName(s string) string {
10+ var out strings.Builder
11+ for _, part := range strings.Split(s, "_") {
12+ if part == "" {
13+ continue
14+ }
15+ if part == strings.ToUpper(part) {
16+ part = strings.ToLower(part)
17+ }
18+ r := []rune(part)
19+ r[0] = unicode.ToUpper(r[0])
20+ out.WriteString(string(r))
21+ }
22+ name := out.String()
23+ if name != "" && name[0] >= '0' && name[0] <= '9' {
24+ name = "X" + name
25+ }
26+ if token.Lookup(name).IsKeyword() {
27+ name += "_"
28+ }
29+ return name
30+}
31+func paramName(s string) string {
32+ name := goName(s)
33+ if name == "" {
34+ return name
35+ }
36+ r := []rune(name)
37+ r[0] = unicode.ToLower(r[0])
38+ name = string(r)
39+ if token.Lookup(name).IsKeyword() {
40+ name += "_"
41+ }
42+ return name
43+}
A cmd/xtgen/parse.go +292 -0
@@ -0,0 +1,292 @@
1+package main
2+
3+import (
4+ "encoding/xml"
5+ "fmt"
6+ "io"
7+ "os"
8+ "strconv"
9+ "strings"
10+)
11+
12+// Node retains XML order and source locations, including expressions. Resolution
13+// turns this syntax tree into the flat, typed emission IR; parsing makes no Go
14+// naming or layout choices.
15+type Node struct {
16+ Kind string
17+ Attr map[string]string
18+ Text string
19+ Children []*Node
20+ File string
21+ Line int
22+}
23+
24+func (n *Node) fail(format string, args ...any) error {
25+ return fmt.Errorf("%s:%d: %s", n.File, n.Line, fmt.Sprintf(format, args...))
26+}
27+
28+// Attribute and child whitelists are per element, not global: a known attribute
29+// or element used in the wrong place is also an error. Documentation is ignored.
30+var attributes = map[string]string{
31+ "xcb": "header extension-name extension-xname extension-multiword major-version minor-version",
32+ "import": "", "typedef": "oldname newname", "xidtype": "name", "xidunion": "name", "type": "",
33+ "enum": "name", "item": "name", "value": "", "bit": "", "struct": "name", "union": "name",
34+ "request": "name opcode combine-adjacent", "reply": "", "event": "name number no-sequence-number xge",
35+ "eventcopy": "name number ref", "error": "name number type", "errorcopy": "name number ref",
36+ "field": "name type enum altenum mask", "pad": "bytes align", "list": "name type enum",
37+ "exprfield": "name type", "switch": "name", "bitcase": "", "fieldref": "", "enumref": "ref",
38+ "op": "op", "unop": "op", "popcount": "", "doc": "",
39+}
40+var children = map[string]string{
41+ "xcb": "import typedef xidtype xidunion enum struct union request event eventcopy error errorcopy doc",
42+ "xidunion": "type", "enum": "item doc", "item": "value bit doc",
43+ "struct": "field pad list doc", "union": "field pad list doc",
44+ "request": "field pad list exprfield switch reply doc", "reply": "field pad list exprfield doc",
45+ "event": "field pad list exprfield doc", "error": "field pad doc",
46+ "list": "value fieldref op unop popcount enumref", "exprfield": "value fieldref op unop popcount enumref",
47+ "switch": "fieldref op unop popcount enumref bitcase", "bitcase": "enumref value field pad doc",
48+ "op": "value fieldref op unop popcount enumref", "unop": "value fieldref op unop popcount enumref",
49+ "popcount": "value fieldref op unop popcount enumref",
50+}
51+
52+func contains(words, word string) bool {
53+ for _, s := range strings.Fields(words) {
54+ if s == word {
55+ return true
56+ }
57+ }
58+ return false
59+}
60+
61+func parseFile(path string) (*Node, error) {
62+ f, err := os.Open(path)
63+ if err != nil {
64+ return nil, err
65+ }
66+ defer f.Close()
67+ return parseXML(path, f)
68+}
69+func parseXML(file string, r io.Reader) (*Node, error) {
70+ d := xml.NewDecoder(r)
71+ var root *Node
72+ var stack []*Node
73+ for {
74+ token, err := d.Token()
75+ if err == io.EOF {
76+ break
77+ }
78+ if err != nil {
79+ line, _ := d.InputPos()
80+ return nil, fmt.Errorf("%s:%d: %w", file, line, err)
81+ }
82+ switch t := token.(type) {
83+ case xml.StartElement:
84+ line, _ := d.InputPos()
85+ n := &Node{Kind: t.Name.Local, Attr: make(map[string]string), File: file, Line: line}
86+ allowed, ok := attributes[n.Kind]
87+ if !ok || t.Name.Space != "" {
88+ return nil, n.fail("unsupported element <%s>", t.Name.Local)
89+ }
90+ if len(stack) == 0 {
91+ if root != nil || n.Kind != "xcb" {
92+ return nil, n.fail("expected a single <xcb> root")
93+ }
94+ root = n
95+ } else {
96+ parent := stack[len(stack)-1]
97+ if !contains(children[parent.Kind], n.Kind) {
98+ return nil, n.fail("unsupported <%s> in <%s>", n.Kind, parent.Kind)
99+ }
100+ parent.Children = append(parent.Children, n)
101+ }
102+ if n.Kind == "doc" {
103+ if err := d.Skip(); err != nil {
104+ return nil, n.fail("invalid doc: %v", err)
105+ }
106+ continue
107+ }
108+ for _, a := range t.Attr {
109+ if a.Name.Space != "" || !contains(allowed, a.Name.Local) {
110+ return nil, n.fail("unknown attribute %q on <%s>", a.Name.Local, n.Kind)
111+ }
112+ if _, ok := n.Attr[a.Name.Local]; ok {
113+ return nil, n.fail("duplicate attribute %q", a.Name.Local)
114+ }
115+ n.Attr[a.Name.Local] = a.Value
116+ }
117+ stack = append(stack, n)
118+ case xml.EndElement:
119+ if len(stack) == 0 {
120+ return nil, fmt.Errorf("%s: unexpected closing element", file)
121+ }
122+ n := stack[len(stack)-1]
123+ n.Text = strings.TrimSpace(n.Text)
124+ if err := validateNode(n); err != nil {
125+ return nil, err
126+ }
127+ stack = stack[:len(stack)-1]
128+ case xml.CharData:
129+ if len(stack) > 0 {
130+ stack[len(stack)-1].Text += string(t)
131+ } else if strings.TrimSpace(string(t)) != "" {
132+ return nil, fmt.Errorf("%s: text outside root", file)
133+ }
134+ case xml.Directive:
135+ return nil, fmt.Errorf("%s: XML directives are unsupported", file)
136+ }
137+ }
138+ if root == nil {
139+ return nil, fmt.Errorf("%s:1: missing <xcb> root", file)
140+ }
141+ return root, nil
142+}
143+func require(n *Node, names string) error {
144+ for _, name := range strings.Fields(names) {
145+ if n.Attr[name] == "" {
146+ return n.fail("missing %s on <%s>", name, n.Kind)
147+ }
148+ }
149+ return nil
150+}
151+func number(n *Node, attr string, bits int) error {
152+ _, err := strconv.ParseUint(n.Attr[attr], 0, bits)
153+ if err != nil {
154+ return n.fail("invalid %s %q", attr, n.Attr[attr])
155+ }
156+ return nil
157+}
158+func exprCount(n *Node) int {
159+ count := 0
160+ for _, c := range n.Children {
161+ if c.Kind != "doc" {
162+ count++
163+ }
164+ }
165+ return count
166+}
167+func validateNode(n *Node) error {
168+ required := map[string]string{
169+ "xcb": "header", "typedef": "oldname newname", "xidtype": "name", "xidunion": "name",
170+ "enum": "name", "item": "name", "struct": "name", "union": "name", "request": "name opcode",
171+ "event": "name number", "eventcopy": "name number ref", "error": "name number", "errorcopy": "name number ref",
172+ "field": "name type", "list": "name type", "exprfield": "name type", "switch": "name", "enumref": "ref", "op": "op", "unop": "op",
173+ }
174+ if err := require(n, required[n.Kind]); err != nil {
175+ return err
176+ }
177+ switch n.Kind {
178+ case "import", "type", "fieldref", "enumref":
179+ if n.Text == "" {
180+ return n.fail("empty <%s>", n.Kind)
181+ }
182+ case "value", "bit":
183+ if _, err := strconv.ParseInt(n.Text, 0, 64); err != nil {
184+ return n.fail("invalid <%s> integer %q", n.Kind, n.Text)
185+ }
186+ case "pad":
187+ _, b := n.Attr["bytes"]
188+ _, a := n.Attr["align"]
189+ if b == a {
190+ return n.fail("pad requires exactly one of bytes or align")
191+ }
192+ key := "bytes"
193+ if a {
194+ key = "align"
195+ }
196+ if err := number(n, key, 31); err != nil {
197+ return err
198+ }
199+ if a {
200+ v, _ := strconv.Atoi(n.Attr[key])
201+ if v == 0 || v&(v-1) != 0 {
202+ return n.fail("pad alignment must be a positive power of two")
203+ }
204+ }
205+ case "request":
206+ if err := number(n, "opcode", 8); err != nil {
207+ return err
208+ }
209+ case "event", "eventcopy", "error", "errorcopy":
210+ if err := number(n, "number", 8); err != nil {
211+ return err
212+ }
213+ if n.Attr["xge"] == "true" {
214+ v, _ := strconv.Atoi(n.Attr["number"])
215+ if v >= 128 {
216+ return n.fail("xge evtype must be < 128")
217+ }
218+ }
219+ case "op":
220+ if !contains("+ - * / & | << >>", n.Attr["op"]) {
221+ return n.fail("unsupported operator %q", n.Attr["op"])
222+ }
223+ if exprCount(n) != 2 {
224+ return n.fail("op requires two operands")
225+ }
226+ case "unop":
227+ if n.Attr["op"] != "~" {
228+ return n.fail("unsupported unary operator %q", n.Attr["op"])
229+ }
230+ if exprCount(n) != 1 {
231+ return n.fail("unop requires one operand")
232+ }
233+ case "popcount", "exprfield", "item":
234+ if exprCount(n) != 1 {
235+ return n.fail("<%s> requires one expression", n.Kind)
236+ }
237+ case "list":
238+ if exprCount(n) > 1 {
239+ return n.fail("list has multiple length expressions")
240+ }
241+ case "bitcase":
242+ fields := 0
243+ for _, c := range n.Children {
244+ if c.Kind == "field" {
245+ fields++
246+ if contains("CARD8 CARD16 INT8 INT16 BOOL char BYTE void", c.Attr["type"]) {
247+ return c.fail("value-list bitcase requires a 4-byte field")
248+ }
249+ }
250+ }
251+ if fields != 1 {
252+ return n.fail("value-list bitcase requires exactly one field")
253+ }
254+ }
255+ for _, key := range []string{"xge", "no-sequence-number", "combine-adjacent", "extension-multiword"} {
256+ if v, ok := n.Attr[key]; ok && v != "true" && v != "false" {
257+ return n.fail("invalid boolean %s=%q", key, v)
258+ }
259+ }
260+ // Forward references cannot be laid out in one pass. Reject at the length
261+ // expression's location rather than failing later while emitting Go.
262+ declared := map[string]bool{}
263+ for _, c := range n.Children {
264+ if c.Kind == "field" || c.Kind == "exprfield" {
265+ declared[c.Attr["name"]] = true
266+ }
267+ }
268+ seen := map[string]bool{}
269+ for _, c := range n.Children {
270+ if c.Kind == "list" {
271+ var visit func(*Node) error
272+ visit = func(e *Node) error {
273+ if e.Kind == "fieldref" && declared[e.Text] && !seen[e.Text] {
274+ return e.fail("list length references later field %q", e.Text)
275+ }
276+ for _, child := range e.Children {
277+ if err := visit(child); err != nil {
278+ return err
279+ }
280+ }
281+ return nil
282+ }
283+ if err := visit(c); err != nil {
284+ return err
285+ }
286+ }
287+ if c.Kind == "field" || c.Kind == "exprfield" {
288+ seen[c.Attr["name"]] = true
289+ }
290+ }
291+ return nil
292+}
A cmd/xtgen/parse_test.go +74 -0
@@ -0,0 +1,74 @@
1+package main
2+
3+import (
4+ "path/filepath"
5+ "strings"
6+ "testing"
7+)
8+
9+func TestParseVendored(t *testing.T) {
10+ files, err := filepath.Glob("../../spec/xml/*.xml")
11+ if err != nil {
12+ t.Fatal(err)
13+ }
14+ if len(files) != 9 {
15+ t.Fatalf("got %d XML files, want 9", len(files))
16+ }
17+ for _, file := range files {
18+ t.Run(filepath.Base(file), func(t *testing.T) {
19+ n, err := parseFile(file)
20+ if err != nil {
21+ t.Fatal(err)
22+ }
23+ if n.Kind != "xcb" || len(n.Children) == 0 {
24+ t.Fatal("missing module AST")
25+ }
26+ })
27+ }
28+}
29+func TestParseRejects(t *testing.T) {
30+ cases := []struct{ name, body, want string }{
31+ {"unknown element", "<surprise/>", "unsupported element"},
32+ {"unknown attribute", `<xidtype name="WINDOW" surprise="yes"/>`, "unknown attribute"},
33+ {"misplaced known element", `<struct name="S"><reply/></struct>`, "unsupported <reply>"},
34+ {"sumof", `<request name="R" opcode="1"><list name="a" type="CARD8"><sumof ref="a"/></list></request>`, "sumof"},
35+ {"paramref", `<request name="R" opcode="1"><list name="a" type="CARD8"><paramref type="CARD8">a</paramref></list></request>`, "paramref"},
36+ {"case", `<request name="R" opcode="1"><switch name="s"><case/></switch></request>`, "case"},
37+ {"struct switch", `<struct name="S"><switch name="s"/></struct>`, "unsupported <switch>"},
38+ {"reply switch", `<request name="R" opcode="1"><reply><switch name="s"/></reply></request>`, "unsupported <switch>"},
39+ {"nested switch", `<request name="R" opcode="1"><switch name="s"><bitcase><switch name="s"/></bitcase></switch></request>`, "unsupported <switch>"},
40+ {"fd", `<request name="R" opcode="1"><fd name="fd"/></request>`, "fd"},
41+ {"eventstruct", `<eventstruct name="E"/>`, "eventstruct"},
42+ {"required alignment", `<struct name="S"><required_start_align align="4"/></struct>`, "required_start_align"},
43+ {"forward length", `<struct name="S"><list name="a" type="CARD8"><fieldref>n</fieldref></list><field name="n" type="CARD8"/></struct>`, "later field"},
44+ {"xge code", `<event name="E" number="128" xge="true"/>`, "evtype"},
45+ {"bad opcode", `<request name="R" opcode="256"/>`, "invalid opcode"},
46+ {"bad operator", `<request name="R" opcode="1"><exprfield name="x" type="CARD32"><op op="%"><value>1</value><value>2</value></op></exprfield></request>`, "unsupported operator"},
47+ {"wrong operands", `<request name="R" opcode="1"><exprfield name="x" type="CARD32"><op op="+"><value>1</value></op></exprfield></request>`, "two operands"},
48+ {"bad pad", `<struct name="S"><pad align="3"/></struct>`, "power of two"},
49+ {"namespace", `<xidtype xmlns="other" name="X"/>`, "unsupported element"},
50+ {"duplicate attr", `<xidtype name="X" name="Y"/>`, "duplicate attribute"},
51+ }
52+ for _, tc := range cases {
53+ t.Run(tc.name, func(t *testing.T) {
54+ _, err := parseXML("bad.xml", strings.NewReader("<xcb header=\"test\">\n"+tc.body+"\n</xcb>"))
55+ if err == nil || !strings.Contains(err.Error(), tc.want) || !strings.Contains(err.Error(), "bad.xml:2:") {
56+ t.Fatalf("got %v, want file:line and %q", err, tc.want)
57+ }
58+ })
59+ }
60+}
61+func TestParseAST(t *testing.T) {
62+ n, err := parseXML("ok.xml", strings.NewReader(`<xcb header="a"><doc><arbitrary/></doc><request name="R" opcode="1"><field type="CARD32" name="n"/><list type="CARD8" name="data"><op op="*"><fieldref>n</fieldref><value>4</value></op></list></request></xcb>`))
63+ if err != nil {
64+ t.Fatal(err)
65+ }
66+ r := n.Children[1]
67+ if r.Attr["name"] != "R" || r.Children[1].Children[0].Children[0].Text != "n" {
68+ t.Fatal("AST lost order or expression")
69+ }
70+}
71+func FuzzParseXML(f *testing.F) {
72+ f.Add(`<xcb header="test"/>`)
73+ f.Fuzz(func(t *testing.T, raw string) { _, _ = parseXML("fuzz.xml", strings.NewReader(raw)) })
74+}
A cmd/xtgen/requests.go +339 -0
@@ -0,0 +1,339 @@
1+package main
2+
3+import (
4+ "fmt"
5+ "path/filepath"
6+ "strconv"
7+ "strings"
8+)
9+
10+type Request struct {
11+ Name string
12+ Opcode uint8
13+ DataByte *Field
14+ Fixed int
15+ Params, Fields []Field
16+ Node *Node
17+ Derived map[string]string
18+ Lists []Field
19+}
20+
21+// resolveRequests lowers scalar and list requests. Value switches follow in T2.5.
22+func resolveRequests(m *Module) ([]Request, error) {
23+ var out []Request
24+ for _, n := range m.Root.Children {
25+ if n.Kind != "request" {
26+ continue
27+ }
28+ supported := true
29+ for _, f := range n.Children {
30+ if f.Kind == "switch" {
31+ supported = false
32+ }
33+ }
34+ if !supported {
35+ continue
36+ }
37+ name := goName(n.Attr["name"])
38+ if err := m.claim(name, n); err != nil {
39+ return nil, err
40+ }
41+ opcode, _ := strconv.Atoi(n.Attr["opcode"])
42+ r := Request{Name: name, Opcode: uint8(opcode), Node: n, Derived: map[string]string{}}
43+ refs := map[string]int{}
44+ var countRefs func(*Node)
45+ countRefs = func(x *Node) {
46+ if x.Kind == "reply" || x.Kind == "doc" {
47+ return
48+ }
49+ if x.Kind == "fieldref" {
50+ refs[x.Text]++
51+ }
52+ for _, c := range x.Children {
53+ countRefs(c)
54+ }
55+ }
56+ countRefs(n)
57+ for _, x := range n.Children {
58+ if x.Kind == "list" && len(x.Children) == 1 && x.Children[0].Kind == "fieldref" && refs[x.Children[0].Text] == 1 {
59+ r.Derived[x.Children[0].Text] = paramName(x.Attr["name"])
60+ }
61+ }
62+ dynamic := false
63+ off := 4
64+ first := true
65+ for _, n := range n.Children {
66+ if n.Kind == "reply" || n.Kind == "doc" {
67+ continue
68+ }
69+ f := Field{Name: goName(n.Attr["name"]), Param: paramName(n.Attr["name"]), Kind: n.Kind, Node: n, Off: off - 4}
70+ if n.Kind == "pad" {
71+ if n.Attr["align"] != "" {
72+ a, _ := strconv.Atoi(n.Attr["align"])
73+ f.Size = (-off) & (a - 1)
74+ } else {
75+ f.Size, _ = strconv.Atoi(n.Attr["bytes"])
76+ }
77+ } else {
78+ typ, err := lookup(m, n.Attr["type"])
79+ if err != nil {
80+ return nil, n.fail("%v", err)
81+ }
82+ if typ.Variable && n.Kind != "list" {
83+ return nil, n.fail("variable field requires list support")
84+ }
85+ f.Type = typ
86+ f.Size = typ.Size
87+ f.GoType = qualified(m, typ.Module, typ.GoType)
88+ if enum := n.Attr["enum"]; enum != "" {
89+ e, owner := findEnum(m, enum)
90+ if e == nil {
91+ return nil, n.fail("unknown enum %s", enum)
92+ }
93+ f.GoType = qualified(m, owner, e.Name)
94+ }
95+ if mask := n.Attr["mask"]; mask != "" {
96+ e, owner := findEnum(m, mask)
97+ if e == nil {
98+ return nil, n.fail("unknown mask %s", mask)
99+ }
100+ f.GoType = qualified(m, owner, e.Name)
101+ }
102+ if n.Kind == "list" {
103+ f.Size = 0
104+ f.GoType = "[]" + f.GoType
105+ if n.Attr["type"] == "char" {
106+ f.GoType = "string"
107+ }
108+ if n.Attr["type"] == "void" || n.Attr["type"] == "BYTE" || n.Attr["type"] == "CARD8" {
109+ f.GoType = "[]byte"
110+ }
111+ if len(n.Children) > 0 {
112+ f.Expr = n.Children[0]
113+ }
114+ if m.Header == "xproto" && r.Name == "SendEvent" {
115+ f.GoType = "*[32]byte"
116+ }
117+ r.Lists = append(r.Lists, f)
118+ r.Params = append(r.Params, f)
119+ } else if n.Kind == "field" && r.Derived[n.Attr["name"]] == "" {
120+ r.Params = append(r.Params, f)
121+ }
122+ if n.Kind == "exprfield" {
123+ f.Expr = n.Children[0]
124+ }
125+ }
126+ // Core's first XML byte is header byte 1; extensions have no data byte.
127+ if first && m.ExtName == "" {
128+ if f.Size != 1 {
129+ return nil, n.fail("core request first member must occupy header data byte")
130+ }
131+ if f.Kind != "pad" {
132+ copy := f
133+ r.DataByte = &copy
134+ }
135+ first = false
136+ continue
137+ }
138+ first = false
139+ if f.Kind == "list" {
140+ dynamic = true
141+ }
142+ if dynamic {
143+ f.Off = -1
144+ }
145+ if f.Kind == "pad" && n.Attr["align"] != "" {
146+ f.Align, _ = strconv.Atoi(n.Attr["align"])
147+ }
148+ r.Fields = append(r.Fields, f)
149+ off += f.Size
150+ }
151+ r.Fixed = off - 4
152+ out = append(out, r)
153+ }
154+ return out, nil
155+}
156+func requestDecl(m *Module, r Request) (string, error) {
157+ var b strings.Builder
158+ fmt.Fprintf(&b, "func %s(b *xturbo.Buf", r.Name)
159+ for _, p := range r.Params {
160+ fmt.Fprintf(&b, ", %s %s", p.Param, p.GoType)
161+ }
162+ b.WriteString(") xturbo.Seq {\n")
163+ ref := func(s string) string {
164+ // xcb-proto permits an exprfield to refer to a trailing list's
165+ // implicit <list>_len (QueryTextExtents.string_len).
166+ declared := false
167+ for _, n := range r.Node.Children {
168+ if n.Kind == "field" && n.Attr["name"] == s {
169+ declared = true
170+ }
171+ }
172+ for _, list := range r.Lists {
173+ if !declared && s == list.Node.Attr["name"]+"_len" {
174+ return "len(" + list.Param + ")"
175+ }
176+ }
177+ if list := r.Derived[s]; list != "" {
178+ return "len(" + list + ")"
179+ }
180+ return "int(" + paramName(s) + ")"
181+ }
182+ // Derived lengths are cast only after checking their wire width.
183+ for _, f := range append(append([]Field{}, r.Fields...), r.Params...) {
184+ if f.Kind != "field" || r.Derived[f.Node.Attr["name"]] == "" {
185+ continue
186+ }
187+ if f.Type.Size < 8 {
188+ fmt.Fprintf(&b, "if uint64(%s)>%d { b.Fail(xturbo.ErrBadLength); return 0 };", ref(f.Node.Attr["name"]), uint64(1)<<(8*f.Type.Size)-1)
189+ }
190+ }
191+ if r.DataByte != nil {
192+ f := r.DataByte
193+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
194+ fmt.Fprintf(&b, "if len(%s)>255 { b.Fail(xturbo.ErrBadLength); return 0 };", list)
195+ }
196+ }
197+ for _, f := range r.Lists {
198+ if f.Expr != nil && !(f.Expr.Kind == "fieldref" && r.Derived[f.Expr.Text] != "") {
199+ ex, err := renderExpr(f.Expr, ref, m)
200+ if err != nil {
201+ return "", err
202+ }
203+ fmt.Fprintf(&b, "if len(%s)!=%s { b.Fail(xturbo.ErrBadLength); return 0 };", f.Param, ex)
204+ }
205+ }
206+ body := fmt.Sprint((r.Fixed + 3) &^ 3)
207+ if len(r.Lists) > 0 {
208+ b.WriteString("size:=0;")
209+ for _, f := range r.Fields {
210+ if f.Kind == "list" {
211+ if f.Type.Variable {
212+ fmt.Fprintf(&b, "for i:=range %s { size+=%s[i].Size() };", f.Param, f.Param)
213+ } else {
214+ fmt.Fprintf(&b, "size+=len(%s)*%d;", f.Param, f.Type.Size)
215+ }
216+ } else if f.Align > 0 {
217+ fmt.Fprintf(&b, "size=(size+%d)&^%d;", f.Align-1, f.Align-1)
218+ } else {
219+ fmt.Fprintf(&b, "size+=%d;", f.Size)
220+ }
221+ }
222+ b.WriteString("size=(size+3)&^3;")
223+ body = "size"
224+ }
225+ major := fmt.Sprint(r.Opcode)
226+ data := "0"
227+ if m.ExtName != "" {
228+ fmt.Fprintf(&b, "if b.Ext==nil { b.Fail(xturbo.ErrExtMissing); return 0 }; major:=b.Ext.Major(xturbo.Ext%s); if major==0 { b.Fail(xturbo.ErrExtMissing); return 0 };\n", m.ExtName)
229+ major = "major"
230+ data = fmt.Sprint(r.Opcode)
231+ } else if r.DataByte != nil {
232+ f := r.DataByte
233+ if f.Type.Base == "bool" {
234+ value := f.Param
235+ if f.Kind == "exprfield" {
236+ ex, err := renderExpr(f.Expr, ref, m)
237+ if err != nil {
238+ return "", err
239+ }
240+ value = "(" + ex + " != 0)"
241+ }
242+ fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", value)
243+ data = "data"
244+ } else {
245+ data = "uint8(" + ref(f.Node.Attr["name"]) + ")"
246+ }
247+ }
248+ fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%s); if p==nil { return 0 };\n", major, data, body)
249+ if len(r.Lists) > 0 {
250+ b.WriteString("off:=0;")
251+ }
252+ for _, f := range r.Fields {
253+ if f.Kind == "pad" {
254+ if len(r.Lists) > 0 {
255+ if f.Align > 0 {
256+ fmt.Fprintf(&b, "off=(off+%d)&^%d;", f.Align-1, f.Align-1)
257+ } else {
258+ fmt.Fprintf(&b, "off+=%d;", f.Size)
259+ }
260+ }
261+ continue
262+ }
263+ if f.Kind == "list" {
264+ if f.GoType == "*[32]byte" {
265+ fmt.Fprintf(&b, "copy(p[off:],%s[:]);", f.Param)
266+ } else if f.GoType == "string" || f.GoType == "[]byte" {
267+ fmt.Fprintf(&b, "copy(p[off:],%s); off+=len(%s);", f.Param, f.Param)
268+ } else {
269+ fmt.Fprintf(&b, "for i:=range %s {", f.Param)
270+ if isScalar(f.Type) {
271+ b.WriteString(putScalar(f.Type, f.Param+"[i]", "p[off:]"))
272+ } else {
273+ fmt.Fprintf(&b, "%s[i].Put(p[off:]);", f.Param)
274+ }
275+ if f.Type.Variable {
276+ fmt.Fprintf(&b, "off+=%s[i].Size();", f.Param)
277+ } else {
278+ fmt.Fprintf(&b, "off+=%d;", f.Type.Size)
279+ }
280+ b.WriteString("};")
281+ }
282+ continue
283+ }
284+ src := f.Param
285+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
286+ src = "len(" + list + ")"
287+ }
288+ if f.Kind == "exprfield" {
289+ var err error
290+ src, err = renderExpr(f.Expr, ref, m)
291+ if err != nil {
292+ return "", err
293+ }
294+ }
295+ dst := fmt.Sprintf("p[%d:]", f.Off)
296+ if len(r.Lists) > 0 {
297+ dst = "p[off:]"
298+ }
299+ if isScalar(f.Type) {
300+ b.WriteString(putScalar(f.Type, src, dst))
301+ } else {
302+ fmt.Fprintf(&b, "%s.Put(%s);", src, dst)
303+ }
304+ if len(r.Lists) > 0 {
305+ fmt.Fprintf(&b, "off+=%d;", f.Size)
306+ }
307+ }
308+ b.WriteString("return seq }\n")
309+ return b.String(), nil
310+}
311+func emitRequests(modules []*Module) error {
312+ for _, m := range modules {
313+ requests, err := resolveRequests(m)
314+ if err != nil {
315+ return err
316+ }
317+ data := struct {
318+ Pkg string
319+ Decls []string
320+ }{Pkg: m.Pkg}
321+ for _, r := range requests {
322+ decl, err := requestDecl(m, r)
323+ if err != nil {
324+ return err
325+ }
326+ data.Decls = append(data.Decls, decl)
327+ }
328+ all := strings.Join(data.Decls, "\n")
329+ imp := importsFor(m, all)
330+ if len(requests) > 0 {
331+ imp += "\nimport \"bnema.dev/xturbo\""
332+ }
333+ data.Decls = append([]string{imp}, data.Decls...)
334+ if err := writeTemplate(filepath.Join(m.Pkg, "requests_generated.go"), "requests", data); err != nil {
335+ return err
336+ }
337+ }
338+ return nil
339+}
A cmd/xtgen/resolve.go +356 -0
@@ -0,0 +1,356 @@
1+package main
2+
3+import (
4+ "encoding/json"
5+ "fmt"
6+ "os"
7+ "path/filepath"
8+ "strconv"
9+ "strings"
10+)
11+
12+var builtin = map[string]*Type{}
13+
14+func init() {
15+ for _, b := range []struct {
16+ xml, goType string
17+ size int
18+ }{
19+ {"CARD8", "uint8", 1}, {"CARD16", "uint16", 2}, {"CARD32", "uint32", 4}, {"CARD64", "uint64", 8},
20+ {"INT8", "int8", 1}, {"INT16", "int16", 2}, {"INT32", "int32", 4}, {"INT64", "int64", 8},
21+ {"BOOL", "bool", 1}, {"BOOL32", "bool", 4}, {"char", "byte", 1}, {"void", "byte", 1}, {"BYTE", "byte", 1},
22+ } {
23+ builtin[b.xml] = &Type{Name: b.xml, GoType: b.goType, Base: b.goType, Size: b.size, Kind: "scalar", Resolved: true}
24+ }
25+}
26+func loadModules() ([]*Module, error) {
27+ var manifest struct {
28+ Files []struct {
29+ Path string `json:"path"`
30+ } `json:"files"`
31+ }
32+ b, err := os.ReadFile("spec/manifest.json")
33+ if err != nil {
34+ return nil, err
35+ }
36+ if err = json.Unmarshal(b, &manifest); err != nil {
37+ return nil, err
38+ }
39+ var nodes []*Node
40+ for _, f := range manifest.Files {
41+ if filepath.Ext(f.Path) != ".xml" {
42+ continue
43+ }
44+ n, err := parseFile(f.Path)
45+ if err != nil {
46+ return nil, err
47+ }
48+ nodes = append(nodes, n)
49+ }
50+ return resolveModules(nodes)
51+}
52+func (m *Module) claim(name string, n *Node) error {
53+ if old := m.Names[name]; old != nil {
54+ return n.fail("Go name collision %s (previously %s:%d)", name, old.File, old.Line)
55+ }
56+ m.Names[name] = n
57+ return nil
58+}
59+func resolveModules(nodes []*Node) ([]*Module, error) {
60+ var modules []*Module
61+ byHeader := map[string]*Module{}
62+ for _, n := range nodes {
63+ m := &Module{Header: n.Attr["header"], Pkg: strings.ReplaceAll(n.Attr["header"], "_", ""), XName: n.Attr["extension-xname"], ExtName: n.Attr["extension-name"], Root: n, Symbols: map[string]*Type{}, Names: map[string]*Node{}}
64+ if byHeader[m.Header] != nil {
65+ return nil, n.fail("duplicate module %s", m.Header)
66+ }
67+ byHeader[m.Header] = m
68+ modules = append(modules, m)
69+ for _, c := range n.Children {
70+ switch c.Kind {
71+ case "xidtype", "xidunion", "typedef", "struct", "union":
72+ raw := c.Attr["name"]
73+ if c.Kind == "typedef" {
74+ raw = c.Attr["newname"]
75+ }
76+ name := goName(raw)
77+ if err := m.claim(name, c); err != nil {
78+ return nil, err
79+ }
80+ typ := &Type{Name: raw, GoType: name, Kind: c.Kind, Node: c, Module: m}
81+ m.Types = append(m.Types, typ)
82+ m.Symbols[raw] = typ
83+ }
84+ }
85+ }
86+ for _, m := range modules {
87+ for _, n := range m.Root.Children {
88+ if n.Kind == "import" {
89+ dep := byHeader[n.Text]
90+ if dep == nil {
91+ return nil, n.fail("unknown import %s", n.Text)
92+ }
93+ m.Imports = append(m.Imports, dep)
94+ }
95+ }
96+ }
97+ for _, m := range modules {
98+ for _, typ := range m.Types {
99+ if err := resolveType(typ); err != nil {
100+ return nil, err
101+ }
102+ }
103+ }
104+ for _, m := range modules {
105+ if err := resolveEnums(m); err != nil {
106+ return nil, err
107+ }
108+ }
109+ // Re-resolve enum annotations after widths are known, without changing wire sizes.
110+ for _, m := range modules {
111+ for _, typ := range m.Types {
112+ for i := range typ.Fields {
113+ f := &typ.Fields[i]
114+ if f.Kind != "field" {
115+ continue
116+ }
117+ if enum := f.Node.Attr["enum"]; enum != "" {
118+ if e, owner := findEnum(m, enum); e != nil {
119+ f.GoType = qualified(m, owner, e.Name)
120+ }
121+ }
122+ if mask := f.Node.Attr["mask"]; mask != "" {
123+ if e, owner := findEnum(m, mask); e != nil {
124+ f.GoType = qualified(m, owner, e.Name)
125+ }
126+ }
127+ }
128+ }
129+ }
130+ return modules, nil
131+}
132+func lookup(m *Module, name string) (*Type, error) {
133+ if t := builtin[name]; t != nil {
134+ return t, nil
135+ }
136+ if strings.Contains(name, ":") {
137+ parts := strings.SplitN(name, ":", 2)
138+ for _, dep := range m.Imports {
139+ if dep.Header == parts[0] {
140+ return lookup(dep, parts[1])
141+ }
142+ }
143+ return nil, m.Root.fail("unknown qualified type %s", name)
144+ }
145+ if t := m.Symbols[name]; t != nil {
146+ return t, nil
147+ }
148+ var found *Type
149+ for _, dep := range m.Imports {
150+ if t := dep.Symbols[name]; t != nil {
151+ if found != nil && found != t {
152+ return nil, m.Root.fail("ambiguous type %s", name)
153+ }
154+ found = t
155+ }
156+ }
157+ if found != nil {
158+ return found, nil
159+ }
160+ return nil, m.Root.fail("unknown type %s", name)
161+}
162+func qualified(m, owner *Module, name string) string {
163+ if owner == nil || owner == m {
164+ return name
165+ }
166+ return owner.Pkg + "." + name
167+}
168+func resolveType(t *Type) error {
169+ if t.Resolved {
170+ return nil
171+ }
172+ if t.Resolving {
173+ return t.Node.fail("recursive type %s", t.Name)
174+ }
175+ t.Resolving = true
176+ switch t.Kind {
177+ case "xidtype", "xidunion":
178+ t.Size = 4
179+ t.Base = "uint32"
180+ case "typedef":
181+ base, err := lookup(t.Module, t.Node.Attr["oldname"])
182+ if err != nil {
183+ return err
184+ }
185+ if err := resolveType(base); err != nil {
186+ return err
187+ }
188+ t.Size = base.Size
189+ t.Base = base.Base
190+ t.Variable = base.Variable
191+ default:
192+ off := 0
193+ for _, n := range t.Node.Children {
194+ if n.Kind == "doc" {
195+ continue
196+ }
197+ f := Field{Name: goName(n.Attr["name"]), Param: paramName(n.Attr["name"]), Kind: n.Kind, Node: n, Off: off}
198+ if t.Kind == "union" {
199+ f.Off = 0
200+ }
201+ switch n.Kind {
202+ case "pad":
203+ if n.Attr["align"] != "" {
204+ f.Align, _ = strconv.Atoi(n.Attr["align"])
205+ f.Size = (-off) & (f.Align - 1)
206+ } else {
207+ f.Size, _ = strconv.Atoi(n.Attr["bytes"])
208+ }
209+ case "field", "list":
210+ elem, err := lookup(t.Module, n.Attr["type"])
211+ if err != nil {
212+ return n.fail("%v", err)
213+ }
214+ if err := resolveType(elem); err != nil {
215+ return err
216+ }
217+ f.Type = elem
218+ f.GoType = qualified(t.Module, elem.Module, elem.GoType)
219+ f.Size = elem.Size
220+ if n.Kind == "list" {
221+ if len(n.Children) > 0 {
222+ f.Expr = n.Children[0]
223+ }
224+ if f.Expr != nil && f.Expr.Kind == "value" && !elem.Variable {
225+ count, err := strconv.Atoi(f.Expr.Text)
226+ if err != nil || count < 0 {
227+ return n.fail("invalid constant list size")
228+ }
229+ f.Count = count
230+ f.Size *= count
231+ f.GoType = fmt.Sprintf("[%d]%s", count, f.GoType)
232+ } else {
233+ t.Variable = true
234+ f.Size = 0
235+ f.GoType = "[]" + f.GoType
236+ if n.Attr["type"] == "char" {
237+ f.GoType = "string"
238+ }
239+ }
240+ }
241+ if elem.Variable {
242+ t.Variable = true
243+ }
244+ default:
245+ return n.fail("unsupported type member %s", n.Kind)
246+ }
247+ t.Fields = append(t.Fields, f)
248+ if t.Kind == "union" {
249+ if f.Size > off {
250+ off = f.Size
251+ }
252+ } else if !t.Variable {
253+ off += f.Size
254+ }
255+ }
256+ t.Size = off
257+ }
258+ t.Resolving = false
259+ t.Resolved = true
260+ return nil
261+}
262+func findEnum(m *Module, name string) (*Enum, *Module) {
263+ if strings.Contains(name, ":") {
264+ p := strings.SplitN(name, ":", 2)
265+ for _, dep := range m.Imports {
266+ if dep.Header == p[0] {
267+ return findEnum(dep, p[1])
268+ }
269+ }
270+ return nil, nil
271+ }
272+ for i := range m.Enums {
273+ if m.Enums[i].Node.Attr["name"] == name {
274+ return &m.Enums[i], m
275+ }
276+ }
277+ for _, dep := range m.Imports {
278+ for i := range dep.Enums {
279+ if dep.Enums[i].Node.Attr["name"] == name {
280+ return &dep.Enums[i], dep
281+ }
282+ }
283+ }
284+ return nil, nil
285+}
286+func resolveEnums(m *Module) error {
287+ for _, n := range m.Root.Children {
288+ if n.Kind != "enum" {
289+ continue
290+ }
291+ e := Enum{Name: goName(n.Attr["name"]), Base: "uint32", Node: n}
292+ if old := m.Names[e.Name]; old != nil {
293+ if !contains("xidtype xidunion typedef", old.Kind) {
294+ return n.fail("Go name collision %s", e.Name)
295+ }
296+ e.Existing = true
297+ } else if err := m.claim(e.Name, n); err != nil {
298+ return err
299+ }
300+ var max int64
301+ for _, item := range n.Children {
302+ if item.Kind == "doc" {
303+ continue
304+ }
305+ ex := item.Children[0]
306+ v, err := strconv.ParseInt(ex.Text, 0, 64)
307+ if err != nil {
308+ return ex.fail("invalid enum value")
309+ }
310+ if ex.Kind == "bit" {
311+ if v < 0 || v > 31 {
312+ return ex.fail("enum bit out of range")
313+ }
314+ v = 1 << uint(v)
315+ }
316+ if v < 0 || v > 0xffffffff {
317+ return ex.fail("enum value out of range")
318+ }
319+ if v > max {
320+ max = v
321+ }
322+ name := e.Name + goName(item.Attr["name"])
323+ if err := m.claim(name, item); err != nil {
324+ return err
325+ }
326+ e.Items = append(e.Items, EnumItem{name, v})
327+ }
328+ // Narrow only when every wire use has the same narrower width.
329+ width := 0
330+ mixed := false
331+ var scan func(*Node)
332+ scan = func(x *Node) {
333+ if x.Attr["enum"] == n.Attr["name"] || x.Attr["mask"] == n.Attr["name"] || x.Attr["altenum"] == n.Attr["name"] {
334+ typ, err := lookup(m, x.Attr["type"])
335+ if err == nil {
336+ if width != 0 && width != typ.Size {
337+ mixed = true
338+ }
339+ width = typ.Size
340+ }
341+ }
342+ for _, c := range x.Children {
343+ scan(c)
344+ }
345+ }
346+ scan(m.Root)
347+ if !mixed && width == 1 && max <= 255 {
348+ e.Base = "uint8"
349+ }
350+ if !mixed && width == 2 && max <= 65535 {
351+ e.Base = "uint16"
352+ }
353+ m.Enums = append(m.Enums, e)
354+ }
355+ return nil
356+}
A cmd/xtgen/resolve_test.go +165 -0
@@ -0,0 +1,165 @@
1+package main
2+
3+import (
4+ "os"
5+ "strings"
6+ "testing"
7+)
8+
9+func testModules(t *testing.T) []*Module {
10+ t.Helper()
11+ old, err := os.Getwd()
12+ if err != nil {
13+ t.Fatal(err)
14+ }
15+ if err = os.Chdir("../.."); err != nil {
16+ t.Fatal(err)
17+ }
18+ defer func() {
19+ if err := os.Chdir(old); err != nil {
20+ t.Fatal(err)
21+ }
22+ }()
23+ ms, err := loadModules()
24+ if err != nil {
25+ t.Fatal(err)
26+ }
27+ return ms
28+}
29+func TestResolveLayouts(t *testing.T) {
30+ ms := testModules(t)
31+ expected := map[string]int{"Setup": 40, "Screen": 40, "Rectangle": 8, "Point": 4, "Arc": 12, "Visualtype": 24, "Format": 8, "Depth": 8, "ClientMessageData": 20}
32+ for _, typ := range ms[0].Types {
33+ if want, ok := expected[typ.GoType]; ok {
34+ if typ.Size != want {
35+ t.Errorf("%s size=%d want %d", typ.GoType, typ.Size, want)
36+ }
37+ delete(expected, typ.GoType)
38+ }
39+ if typ.GoType == "Rectangle" {
40+ for i, want := range []int{0, 2, 4, 6} {
41+ if typ.Fields[i].Off != want {
42+ t.Errorf("rectangle field %d offset", i)
43+ }
44+ }
45+ }
46+ }
47+ if len(expected) != 0 {
48+ t.Fatal("missing types", expected)
49+ }
50+ for _, name := range []string{"Window", "Atom", "Cursor", "Pixmap", "Font"} {
51+ found := false
52+ for _, e := range ms[0].Enums {
53+ if e.Name == name {
54+ found = e.Existing
55+ }
56+ }
57+ if !found {
58+ t.Errorf("%s must reuse XID type", name)
59+ }
60+ }
61+ for _, m := range ms {
62+ if err := packetSizeChecks(m); err != nil {
63+ t.Fatal(err)
64+ }
65+ }
66+}
67+func TestResolveRejectsCollisions(t *testing.T) {
68+ for _, body := range []string{
69+ `<struct name="A"/><enum name="A"><item name="B"><value>0</value></item></enum>`,
70+ `<xidtype name="A"/><xidtype name="a"/>`,
71+ `<enum name="A"><item name="B"><value>0</value></item></enum><enum name="A"><item name="C"><value>0</value></item></enum>`,
72+ } {
73+ n, err := parseXML("collision.xml", strings.NewReader(`<xcb header="test">`+body+`</xcb>`))
74+ if err != nil {
75+ t.Fatal(err)
76+ }
77+ _, err = resolveModules([]*Node{n})
78+ if err == nil || !strings.Contains(err.Error(), "collision.xml:1:") || !strings.Contains(err.Error(), "collision") {
79+ t.Fatalf("got %v", err)
80+ }
81+ }
82+}
83+func TestNaming(t *testing.T) {
84+ for in, want := range map[string]string{"WINDOW": "Window", "data_len": "DataLen", "ClientIdSpec": "ClientIdSpec", "2d": "X2d", "BOOL32": "Bool32"} {
85+ if got := goName(in); got != want {
86+ t.Errorf("%s => %s want %s", in, got, want)
87+ }
88+ }
89+ if paramName("type") != "type_" {
90+ t.Fatal("keyword parameter")
91+ }
92+}
93+
94+func TestRenderExpr(t *testing.T) {
95+ n, err := parseXML("expr.xml", strings.NewReader(`<xcb header="test"><request name="R" opcode="1"><exprfield name="x" type="CARD32"><op op="*"><fieldref>n</fieldref><value>4</value></op></exprfield></request></xcb>`))
96+ if err != nil {
97+ t.Fatal(err)
98+ }
99+ got, err := renderExpr(n.Children[0].Children[0].Children[0], func(s string) string { return "int(v." + goName(s) + ")" }, nil)
100+ if err != nil || got != "(int(v.N) * 4)" {
101+ t.Fatalf("%s %v", got, err)
102+ }
103+}
104+
105+func TestFixedRequests(t *testing.T) {
106+ ms := testModules(t)
107+ for _, m := range ms {
108+ requests, err := resolveRequests(m)
109+ if err != nil {
110+ t.Fatal(err)
111+ }
112+ for _, r := range requests {
113+ decl, err := requestDecl(m, r)
114+ if err != nil {
115+ t.Fatal(err)
116+ }
117+ if !strings.Contains(decl, "if p==nil { return 0 }") {
118+ t.Fatal("missing sticky-error guard")
119+ }
120+ if m.Header == "xproto" && r.Name == "MapWindow" {
121+ if r.Fixed != 4 || len(r.Params) != 1 || r.Fields[0].Off != 0 {
122+ t.Fatal("MapWindow layout")
123+ }
124+ }
125+ if m.Header == "xfixes" && r.Name == "QueryVersion" {
126+ if r.Fixed != 8 || r.DataByte != nil || r.Fields[1].Off != 4 {
127+ t.Fatal("extension layout")
128+ }
129+ }
130+ }
131+ }
132+}
133+
134+func TestListResolution(t *testing.T) {
135+ for _, m := range testModules(t) {
136+ rs, err := resolveRequests(m)
137+ if err != nil {
138+ t.Fatal(err)
139+ }
140+ for _, r := range rs {
141+ switch r.Name {
142+ case "InternAtom":
143+ if r.Derived["name_len"] != "name" || len(r.Params) != 2 {
144+ t.Fatal("InternAtom derived length")
145+ }
146+ case "ChangeProperty":
147+ if len(r.Derived) != 0 || len(r.Params) != 7 {
148+ t.Fatal("ChangeProperty explicit expression fields")
149+ }
150+ case "AddGlyphs":
151+ if r.Derived["glyphs_len"] != "" {
152+ t.Fatal("shared count must remain explicit")
153+ }
154+ case "QueryClientIds":
155+ if r.Derived["num_specs"] != "specs" || r.Params[0].GoType != "[]ClientIdSpec" {
156+ t.Fatal("fixed struct list")
157+ }
158+ case "SetFontPath":
159+ if r.Params[0].GoType != "[]Str" || !r.Lists[0].Type.Variable {
160+ t.Fatal("variable struct list")
161+ }
162+ }
163+ }
164+ }
165+}
A cmd/xtgen/templates/ext.tmpl +10 -0
@@ -0,0 +1,10 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xturbo
3+
4+type ExtID uint8
5+const (
6+ ExtCore ExtID = iota
7+{{range .}} Ext{{.ExtName}}
8+{{end}} extCount
9+)
10+var ExtXName = [extCount]string{"", {{range .}}{{printf "%q" .XName}},{{end}}}
A cmd/xtgen/templates/requests.tmpl +5 -0
@@ -0,0 +1,5 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package {{.Pkg}}
3+{{range .Decls}}
4+{{.}}
5+{{end}}
A cmd/xtgen/templates/sizes.tmpl +7 -0
@@ -0,0 +1,7 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package {{.Pkg}}
3+import "testing"
4+func TestWireSizes(t *testing.T) {
5+{{range .SizeChecks}}{{.}}
6+{{end}}
7+}
A cmd/xtgen/templates/types.tmpl +5 -0
@@ -0,0 +1,5 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package {{.Pkg}}
3+{{range .Decls}}
4+{{.}}
5+{{end}}
A composite/requests_generated.go +176 -0
@@ -0,0 +1,176 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package composite
3+
4+import "bnema.dev/xturbo/xfixes"
5+import "bnema.dev/xturbo/xproto"
6+import "encoding/binary"
7+import "bnema.dev/xturbo"
8+
9+func QueryVersion(b *xturbo.Buf, clientMajorVersion uint32, clientMinorVersion uint32) xturbo.Seq {
10+ if b.Ext == nil {
11+ b.Fail(xturbo.ErrExtMissing)
12+ return 0
13+ }
14+ major := b.Ext.Major(xturbo.ExtComposite)
15+ if major == 0 {
16+ b.Fail(xturbo.ErrExtMissing)
17+ return 0
18+ }
19+ p, seq := b.Request(major, 0, 8)
20+ if p == nil {
21+ return 0
22+ }
23+ binary.LittleEndian.PutUint32(p[0:], uint32(clientMajorVersion))
24+ binary.LittleEndian.PutUint32(p[4:], uint32(clientMinorVersion))
25+ return seq
26+}
27+
28+func RedirectWindow(b *xturbo.Buf, window xproto.Window, update Redirect) xturbo.Seq {
29+ if b.Ext == nil {
30+ b.Fail(xturbo.ErrExtMissing)
31+ return 0
32+ }
33+ major := b.Ext.Major(xturbo.ExtComposite)
34+ if major == 0 {
35+ b.Fail(xturbo.ErrExtMissing)
36+ return 0
37+ }
38+ p, seq := b.Request(major, 1, 8)
39+ if p == nil {
40+ return 0
41+ }
42+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
43+ p[4:][0] = byte(update)
44+ return seq
45+}
46+
47+func RedirectSubwindows(b *xturbo.Buf, window xproto.Window, update Redirect) xturbo.Seq {
48+ if b.Ext == nil {
49+ b.Fail(xturbo.ErrExtMissing)
50+ return 0
51+ }
52+ major := b.Ext.Major(xturbo.ExtComposite)
53+ if major == 0 {
54+ b.Fail(xturbo.ErrExtMissing)
55+ return 0
56+ }
57+ p, seq := b.Request(major, 2, 8)
58+ if p == nil {
59+ return 0
60+ }
61+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
62+ p[4:][0] = byte(update)
63+ return seq
64+}
65+
66+func UnredirectWindow(b *xturbo.Buf, window xproto.Window, update Redirect) xturbo.Seq {
67+ if b.Ext == nil {
68+ b.Fail(xturbo.ErrExtMissing)
69+ return 0
70+ }
71+ major := b.Ext.Major(xturbo.ExtComposite)
72+ if major == 0 {
73+ b.Fail(xturbo.ErrExtMissing)
74+ return 0
75+ }
76+ p, seq := b.Request(major, 3, 8)
77+ if p == nil {
78+ return 0
79+ }
80+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
81+ p[4:][0] = byte(update)
82+ return seq
83+}
84+
85+func UnredirectSubwindows(b *xturbo.Buf, window xproto.Window, update Redirect) xturbo.Seq {
86+ if b.Ext == nil {
87+ b.Fail(xturbo.ErrExtMissing)
88+ return 0
89+ }
90+ major := b.Ext.Major(xturbo.ExtComposite)
91+ if major == 0 {
92+ b.Fail(xturbo.ErrExtMissing)
93+ return 0
94+ }
95+ p, seq := b.Request(major, 4, 8)
96+ if p == nil {
97+ return 0
98+ }
99+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
100+ p[4:][0] = byte(update)
101+ return seq
102+}
103+
104+func CreateRegionFromBorderClip(b *xturbo.Buf, region xfixes.Region, window xproto.Window) xturbo.Seq {
105+ if b.Ext == nil {
106+ b.Fail(xturbo.ErrExtMissing)
107+ return 0
108+ }
109+ major := b.Ext.Major(xturbo.ExtComposite)
110+ if major == 0 {
111+ b.Fail(xturbo.ErrExtMissing)
112+ return 0
113+ }
114+ p, seq := b.Request(major, 5, 8)
115+ if p == nil {
116+ return 0
117+ }
118+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
119+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
120+ return seq
121+}
122+
123+func NameWindowPixmap(b *xturbo.Buf, window xproto.Window, pixmap xproto.Pixmap) xturbo.Seq {
124+ if b.Ext == nil {
125+ b.Fail(xturbo.ErrExtMissing)
126+ return 0
127+ }
128+ major := b.Ext.Major(xturbo.ExtComposite)
129+ if major == 0 {
130+ b.Fail(xturbo.ErrExtMissing)
131+ return 0
132+ }
133+ p, seq := b.Request(major, 6, 8)
134+ if p == nil {
135+ return 0
136+ }
137+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
138+ binary.LittleEndian.PutUint32(p[4:], uint32(pixmap))
139+ return seq
140+}
141+
142+func GetOverlayWindow(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
143+ if b.Ext == nil {
144+ b.Fail(xturbo.ErrExtMissing)
145+ return 0
146+ }
147+ major := b.Ext.Major(xturbo.ExtComposite)
148+ if major == 0 {
149+ b.Fail(xturbo.ErrExtMissing)
150+ return 0
151+ }
152+ p, seq := b.Request(major, 7, 4)
153+ if p == nil {
154+ return 0
155+ }
156+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
157+ return seq
158+}
159+
160+func ReleaseOverlayWindow(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
161+ if b.Ext == nil {
162+ b.Fail(xturbo.ErrExtMissing)
163+ return 0
164+ }
165+ major := b.Ext.Major(xturbo.ExtComposite)
166+ if major == 0 {
167+ b.Fail(xturbo.ErrExtMissing)
168+ return 0
169+ }
170+ p, seq := b.Request(major, 8, 4)
171+ if p == nil {
172+ return 0
173+ }
174+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
175+ return seq
176+}
A composite/sizes_test.go +14 -0
@@ -0,0 +1,14 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package composite
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("reply QueryVersion fixed size = %d", got)
9+ }
10+ if got := 32; got != 32 {
11+ t.Errorf("reply GetOverlayWindow fixed size = %d", got)
12+ }
13+
14+}
A composite/types_generated.go +7 -0
@@ -0,0 +1,7 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package composite
3+
4+type Redirect uint8
5+
6+const RedirectAutomatic Redirect = 0
7+const RedirectManual Redirect = 1
A ext.go +27 -0
@@ -0,0 +1,27 @@
1+package xturbo
2+
3+// ExtInfo is a negotiated extension's wire opcode and event/error bases.
4+type ExtInfo struct {
5+ Present bool
6+ Major, FirstEvent, FirstError uint8
7+}
8+
9+// ExtTable is populated during setup. Fixed arrays avoid lookup allocations.
10+// Reverse mapping is completed with the read-side runtime in Phase 3.
11+type ExtTable struct{ info [extCount]ExtInfo }
12+
13+func (t *ExtTable) Set(id ExtID, major, firstEvent, firstError uint8) {
14+ if id < extCount {
15+ t.info[id] = ExtInfo{true, major, firstEvent, firstError}
16+ }
17+}
18+func (t *ExtTable) Info(id ExtID) ExtInfo {
19+ if id >= extCount {
20+ return ExtInfo{}
21+ }
22+ if id == ExtCore {
23+ return ExtInfo{Present: true}
24+ }
25+ return t.info[id]
26+}
27+func (t *ExtTable) Major(id ExtID) uint8 { return t.Info(id).Major }
A ext_generated.go +19 -0
@@ -0,0 +1,19 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xturbo
3+
4+type ExtID uint8
5+
6+const (
7+ ExtCore ExtID = iota
8+ ExtBigRequests
9+ ExtGenericEvent
10+ ExtXCMisc
11+ ExtComposite
12+ ExtXFixes
13+ ExtRes
14+ ExtRender
15+ ExtShape
16+ extCount
17+)
18+
19+var ExtXName = [extCount]string{"", "BIG-REQUESTS", "Generic Event Extension", "XC-MISC", "Composite", "XFIXES", "X-Resource", "RENDER", "SHAPE"}
A ge/requests_generated.go +24 -0
@@ -0,0 +1,24 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package ge
3+
4+import "encoding/binary"
5+import "bnema.dev/xturbo"
6+
7+func QueryVersion(b *xturbo.Buf, clientMajorVersion uint16, clientMinorVersion uint16) xturbo.Seq {
8+ if b.Ext == nil {
9+ b.Fail(xturbo.ErrExtMissing)
10+ return 0
11+ }
12+ major := b.Ext.Major(xturbo.ExtGenericEvent)
13+ if major == 0 {
14+ b.Fail(xturbo.ErrExtMissing)
15+ return 0
16+ }
17+ p, seq := b.Request(major, 0, 4)
18+ if p == nil {
19+ return 0
20+ }
21+ binary.LittleEndian.PutUint16(p[0:], uint16(clientMajorVersion))
22+ binary.LittleEndian.PutUint16(p[2:], uint16(clientMinorVersion))
23+ return seq
24+}
A ge/sizes_test.go +11 -0
@@ -0,0 +1,11 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package ge
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("reply QueryVersion fixed size = %d", got)
9+ }
10+
11+}
A ge/types_generated.go +2 -0
@@ -0,0 +1,2 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package ge
A generate.go +3 -0
@@ -0,0 +1,3 @@
1+package xturbo
2+
3+//go:generate go run ./cmd/xtgen -all
A internal/xtest/README.md +24 -0
@@ -0,0 +1,24 @@
1+# Wire goldens
2+
3+Refresh the T2.3 fixtures from the repository root:
4+
5+```
6+PATH="$PATH:/usr/sbin" go test -tags xserver ./internal/xtest -update
7+```
8+
9+The local `/usr/sbin/xtrace` is glibc's program execution tracer, not the X11
10+protocol proxy. The permitted fallback uses a raw Unix socketpair tee connected
11+to a fresh Xvfb server. A small independent reference encoder (not the generated
12+bindings) sends the requests; the tee records their actual bytes. GetGeometry's
13+successful response also establishes that the preceding MapWindow was accepted.
14+The captured target is the root window; XFIXES's major opcode is negotiated.
15+Tests read target/opcode from the fixture, not a hard-coded server assignment.
16+No runtime Conn is needed at this phase.
17+
18+T2.4 should extend the independent encoder and capture cases for list requests.
19+Replies, events and runtime integration belong to their subsequent tasks.
20+
21+T2.4 adds InternAtom, ChangeProperty and XRes QueryClientIds. A GetProperty
22+read-back validates the property contents. XRes's major opcode is negotiated;
23+QueryVersion 1.2 precedes the ClientIdSpec-list query. The capture is independent
24+of generated code, including counts, framing, and padding.
A internal/xtest/capture_test.go +261 -0
@@ -0,0 +1,261 @@
1+//go:build xserver
2+
3+package xtest
4+
5+import (
6+ "bytes"
7+ "encoding/binary"
8+ "encoding/hex"
9+ "flag"
10+ "fmt"
11+ "io"
12+ "net"
13+ "os"
14+ "os/exec"
15+ "path/filepath"
16+ "strconv"
17+ "strings"
18+ "testing"
19+ "time"
20+
21+ "golang.org/x/sys/unix"
22+)
23+
24+var update = flag.Bool("update", false, "refresh request goldens using Xvfb and a raw socketpair tee")
25+
26+func TestCaptureRequests(t *testing.T) {
27+ if !*update {
28+ t.Skip("pass -update to capture request goldens")
29+ }
30+ // displayfd avoids display-number races and tells us when Xvfb is ready.
31+ r, w, err := os.Pipe()
32+ if err != nil {
33+ t.Fatal(err)
34+ }
35+ defer r.Close()
36+ cmd := exec.Command("Xvfb", "-displayfd", "3", "-screen", "0", "800x600x24", "-nolisten", "tcp", "-ac")
37+ cmd.ExtraFiles = []*os.File{w}
38+ var log bytes.Buffer
39+ cmd.Stderr = &log
40+ if err = cmd.Start(); err != nil {
41+ w.Close()
42+ t.Fatal(err)
43+ }
44+ w.Close()
45+ defer func() { _ = cmd.Process.Kill(); _ = cmd.Wait() }()
46+ _ = r.SetReadDeadline(time.Now().Add(5 * time.Second))
47+ var display [32]byte
48+ n, err := r.Read(display[:])
49+ if err != nil {
50+ t.Fatalf("Xvfb: %v: %s", err, log.String())
51+ }
52+ num, err := strconv.Atoi(strings.TrimSpace(string(display[:n])))
53+ if err != nil {
54+ t.Fatal(err)
55+ }
56+ server, err := net.DialTimeout("unix", fmt.Sprintf("/tmp/.X11-unix/X%d", num), 5*time.Second)
57+ if err != nil {
58+ t.Fatal(err)
59+ }
60+ defer server.Close()
61+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
62+ if err != nil {
63+ t.Fatal(err)
64+ }
65+ a := os.NewFile(uintptr(fds[0]), "capture-client")
66+ b := os.NewFile(uintptr(fds[1]), "capture-tee")
67+ client, err := net.FileConn(a)
68+ a.Close()
69+ if err != nil {
70+ b.Close()
71+ t.Fatal(err)
72+ }
73+ defer client.Close()
74+ tee, err := net.FileConn(b)
75+ b.Close()
76+ if err != nil {
77+ t.Fatal(err)
78+ }
79+ defer tee.Close()
80+ _ = client.SetDeadline(time.Now().Add(5 * time.Second))
81+ _ = server.SetDeadline(time.Now().Add(5 * time.Second))
82+ var recorded bytes.Buffer
83+ copied := make(chan error, 1)
84+ go func() { _, err := io.Copy(server, io.TeeReader(tee, &recorded)); copied <- err }()
85+ go func() { _, _ = io.Copy(tee, server) }()
86+ write := func(p []byte) {
87+ t.Helper()
88+ if _, err := client.Write(p); err != nil {
89+ t.Fatal(err)
90+ }
91+ }
92+ read := func(p []byte) {
93+ t.Helper()
94+ if _, err := io.ReadFull(client, p); err != nil {
95+ t.Fatal(err)
96+ }
97+ }
98+ // Independent reference encoder: no generated bindings participate in capture.
99+ write([]byte{'l', 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0})
100+ var setupHead [8]byte
101+ read(setupHead[:])
102+ if setupHead[0] != 1 {
103+ t.Fatalf("setup failed: %x", setupHead)
104+ }
105+ setup := make([]byte, int(binary.LittleEndian.Uint16(setupHead[6:]))*4)
106+ read(setup)
107+ vendorLen := int(binary.LittleEndian.Uint16(setup[16:]))
108+ formats := int(setup[21])
109+ screenOff := 32 + (vendorLen+3)&^3 + 8*formats
110+ root := binary.LittleEndian.Uint32(setup[screenOff:])
111+ // Query XFIXES dynamically rather than assuming a server-specific major opcode.
112+ query := []byte{98, 0, 4, 0, 6, 0, 0, 0, 'X', 'F', 'I', 'X', 'E', 'S', 0, 0}
113+ write(query)
114+ packet := func() []byte {
115+ t.Helper()
116+ head := make([]byte, 32)
117+ read(head)
118+ if head[0] == 1 {
119+ tail := make([]byte, int(binary.LittleEndian.Uint32(head[4:]))*4)
120+ read(tail)
121+ head = append(head, tail...)
122+ }
123+ return head
124+ }
125+ ext := packet()
126+ if ext[0] != 1 || ext[8] != 1 {
127+ t.Fatalf("XFIXES unavailable: %x", ext)
128+ }
129+ major := ext[9]
130+ version := make([]byte, 12)
131+ version[0] = major
132+ version[2] = 3
133+ binary.LittleEndian.PutUint32(version[4:], 6)
134+ write(version)
135+ reply := packet()
136+ if reply[0] != 1 {
137+ t.Fatalf("QueryVersion failed: %x", reply)
138+ }
139+ mapReq := make([]byte, 8)
140+ mapReq[0] = 8
141+ mapReq[2] = 2
142+ binary.LittleEndian.PutUint32(mapReq[4:], root)
143+ write(mapReq)
144+ geometry := append([]byte(nil), mapReq...)
145+ geometry[0] = 14
146+ write(geometry)
147+ geom := packet()
148+ if geom[0] != 1 || binary.LittleEndian.Uint16(geom[2:]) != 4 {
149+ t.Fatalf("MapWindow/GetGeometry rejected: %x", geom)
150+ }
151+
152+ // InternAtom, ChangeProperty and XRes QueryClientIds exercise derived lengths,
153+ // byte expressions and fixed-struct lists with independently assembled bytes.
154+ intern := []byte{16, 0, 4, 0, 7, 0, 0, 0, 'X', 'T', 'U', 'R', 'B', 'O', '_', 0}
155+ write(intern)
156+ atomReply := packet()
157+ if atomReply[0] != 1 {
158+ t.Fatalf("InternAtom: %x", atomReply)
159+ }
160+ atom := binary.LittleEndian.Uint32(atomReply[8:])
161+ property := make([]byte, 28)
162+ property[0] = 18
163+ property[2] = 7
164+ binary.LittleEndian.PutUint32(property[4:], root)
165+ binary.LittleEndian.PutUint32(property[8:], atom)
166+ binary.LittleEndian.PutUint32(property[12:], 31)
167+ property[16] = 8
168+ binary.LittleEndian.PutUint32(property[20:], 3)
169+ copy(property[24:], "abc")
170+ write(property)
171+ // A successful GetProperty reply proves the preceding write was accepted.
172+ get := make([]byte, 24)
173+ get[0] = 20
174+ get[2] = 6
175+ binary.LittleEndian.PutUint32(get[4:], root)
176+ binary.LittleEndian.PutUint32(get[8:], atom)
177+ binary.LittleEndian.PutUint32(get[20:], 1)
178+ write(get)
179+ got := packet()
180+ if got[0] != 1 || string(got[32:35]) != "abc" {
181+ t.Fatalf("ChangeProperty: %x", got)
182+ }
183+ resName := "X-Resource"
184+ queryRes := make([]byte, 20)
185+ queryRes[0] = 98
186+ queryRes[2] = 5
187+ queryRes[4] = byte(len(resName))
188+ copy(queryRes[8:], resName)
189+ write(queryRes)
190+ resExt := packet()
191+ if resExt[0] != 1 || resExt[8] != 1 {
192+ t.Fatalf("XRes unavailable: %x", resExt)
193+ }
194+ resMajor := resExt[9]
195+ resVersion := []byte{resMajor, 0, 2, 0, 1, 2, 0, 0}
196+ write(resVersion)
197+ if p := packet(); p[0] != 1 {
198+ t.Fatalf("XRes version: %x", p)
199+ }
200+ ids := make([]byte, 16)
201+ ids[0] = resMajor
202+ ids[1] = 4
203+ ids[2] = 4
204+ binary.LittleEndian.PutUint32(ids[4:], 1)
205+ binary.LittleEndian.PutUint32(ids[12:], 1)
206+ write(ids)
207+ if p := packet(); p[0] != 1 {
208+ t.Fatalf("QueryClientIds: %x", p)
209+ }
210+ // Closing the client drains the request direction; wait before inspecting tee.
211+ client.Close()
212+ select {
213+ case err := <-copied:
214+ if err != nil {
215+ t.Fatal(err)
216+ }
217+ case <-time.After(5 * time.Second):
218+ t.Fatal("tee did not drain")
219+ }
220+ stream := recorded.Bytes()
221+ requests := stream[12:]
222+ captured := map[string][]byte{}
223+ for len(requests) > 0 {
224+ size := int(binary.LittleEndian.Uint16(requests[2:])) * 4
225+ if size < 4 || size > len(requests) {
226+ t.Fatal("malformed capture")
227+ }
228+ p := requests[:size]
229+ switch p[0] {
230+ case 8:
231+ captured["xproto/MapWindow"] = p
232+ case 14:
233+ captured["xproto/GetGeometry"] = p
234+ case 16:
235+ captured["xproto/InternAtom"] = p
236+ case 18:
237+ captured["xproto/ChangeProperty"] = p
238+ default:
239+ if p[0] == resMajor && p[1] == 4 {
240+ captured["res/QueryClientIds"] = p
241+ }
242+ if p[0] == major {
243+ captured["xfixes/QueryVersion"] = p
244+ }
245+ }
246+ requests = requests[size:]
247+ }
248+ if len(captured) != 6 {
249+ t.Fatal("missing captured requests")
250+ }
251+ for name, p := range captured {
252+ path := filepath.Join("../../testdata/golden", name+".req.hex")
253+ if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
254+ t.Fatal(err)
255+ }
256+ text := "# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted\n# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace\n" + hex.EncodeToString(p) + "\n"
257+ if err := os.WriteFile(path, []byte(text), 0644); err != nil {
258+ t.Fatal(err)
259+ }
260+ }
261+}
A internal/xtest/golden.go +22 -0
@@ -0,0 +1,22 @@
1+// Package xtest provides wire fixtures shared by binding tests.
2+package xtest
3+
4+import (
5+ "encoding/hex"
6+ "os"
7+ "strings"
8+)
9+
10+// LoadHex reads whitespace-separated hex with optional # comments.
11+func LoadHex(path string) ([]byte, error) {
12+ b, err := os.ReadFile(path)
13+ if err != nil {
14+ return nil, err
15+ }
16+ var text strings.Builder
17+ for line := range strings.SplitSeq(string(b), "\n") {
18+ line, _, _ = strings.Cut(line, "#")
19+ text.WriteString(strings.Join(strings.Fields(line), ""))
20+ }
21+ return hex.DecodeString(text.String())
22+}
A lists_test.go +87 -0
@@ -0,0 +1,87 @@
1+package xturbo_test
2+
3+import (
4+ "bytes"
5+ "encoding/binary"
6+ "strings"
7+ "testing"
8+
9+ "bnema.dev/xturbo"
10+ "bnema.dev/xturbo/internal/xtest"
11+ "bnema.dev/xturbo/render"
12+ "bnema.dev/xturbo/res"
13+ "bnema.dev/xturbo/xproto"
14+)
15+
16+func TestListGoldens(t *testing.T) {
17+ for _, name := range []string{"xproto/InternAtom", "xproto/ChangeProperty", "res/QueryClientIds"} {
18+ t.Run(name, func(t *testing.T) {
19+ want, err := xtest.LoadHex("testdata/golden/" + name + ".req.hex")
20+ if err != nil {
21+ t.Fatal(err)
22+ }
23+ b := xturbo.NewBuf(0)
24+ switch name {
25+ case "xproto/InternAtom":
26+ xproto.InternAtom(b, false, "XTURBO_")
27+ case "xproto/ChangeProperty":
28+ xproto.ChangeProperty(b, xproto.PropModeReplace, xproto.Window(binary.LittleEndian.Uint32(want[4:])), xproto.Atom(binary.LittleEndian.Uint32(want[8:])), xproto.AtomString, 8, 3, []byte("abc"))
29+ case "res/QueryClientIds":
30+ var ext xturbo.ExtTable
31+ ext.Set(xturbo.ExtRes, want[0], 0, 0)
32+ b.Ext = &ext
33+ res.QueryClientIds(b, []res.ClientIdSpec{{Client: 0, Mask: res.ClientIdMaskClientXID}})
34+ }
35+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
36+ t.Fatalf("err %v got %x want %x", b.Err(), b.Bytes(), want)
37+ }
38+ })
39+ }
40+}
41+func TestListLengths(t *testing.T) {
42+ b := xturbo.NewBuf(0)
43+ if xproto.ChangeProperty(b, 0, 1, 1, 1, 16, 2, []byte{1, 2}) != 0 || b.Err() != xturbo.ErrBadLength || b.Len() != 0 {
44+ t.Fatal("expression length mismatch")
45+ }
46+ b = xturbo.NewBuf(0)
47+ if xproto.InternAtom(b, false, strings.Repeat("x", 65536)) != 0 || b.Err() != xturbo.ErrBadLength {
48+ t.Fatal("derived length truncation")
49+ }
50+ b = xturbo.NewBuf(0)
51+ xproto.SetFontPath(b, []xproto.Str{{NameLen: 3, Name: "abc"}, {NameLen: 1, Name: "d"}})
52+ want := []byte{51, 0, 4, 0, 2, 0, 0, 0, 3, 'a', 'b', 'c', 1, 'd', 0, 0}
53+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
54+ t.Fatalf("variable structs: %x err %v", b.Bytes(), b.Err())
55+ }
56+ b = xturbo.NewBuf(0)
57+ xproto.QueryTextExtents(b, 1, []xproto.Char2b{{Byte1: 0, Byte2: 'a'}})
58+ if b.Bytes()[1] != 1 {
59+ t.Fatal("implicit list length exprfield")
60+ }
61+ var ext xturbo.ExtTable
62+ ext.Set(xturbo.ExtRender, 140, 0, 0)
63+ b = xturbo.NewBuf(0)
64+ b.Ext = &ext
65+ if render.AddGlyphs(b, 1, 2, []uint32{1}, nil, nil) != 0 || b.Err() != xturbo.ErrBadLength {
66+ t.Fatal("shared length must remain explicit")
67+ }
68+}
69+func TestAllocListRequests(t *testing.T) {
70+ b := xturbo.NewBuf(0)
71+ data := make([]byte, 4096)
72+ specs := []res.ClientIdSpec{{Client: 1, Mask: res.ClientIdMaskClientXID}}
73+ var ext xturbo.ExtTable
74+ ext.Set(xturbo.ExtRes, 141, 0, 0)
75+ b.Ext = &ext
76+ if n := testing.AllocsPerRun(1000, func() {
77+ b.Reset()
78+ xproto.InternAtom(b, false, "WM_CLASS")
79+ xproto.ChangeProperty(b, 0, 1, 1, 1, 8, 4096, data)
80+ res.QueryClientIds(b, specs)
81+ }); n != 0 {
82+ t.Fatal(n)
83+ }
84+ if b.Err() != nil {
85+ t.Fatal(b.Err())
86+ }
87+}
A render/requests_generated.go +963 -0
@@ -0,0 +1,963 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package render
3+
4+import "bnema.dev/xturbo/xproto"
5+import "encoding/binary"
6+import "bnema.dev/xturbo"
7+
8+func QueryVersion(b *xturbo.Buf, clientMajorVersion uint32, clientMinorVersion uint32) xturbo.Seq {
9+ if b.Ext == nil {
10+ b.Fail(xturbo.ErrExtMissing)
11+ return 0
12+ }
13+ major := b.Ext.Major(xturbo.ExtRender)
14+ if major == 0 {
15+ b.Fail(xturbo.ErrExtMissing)
16+ return 0
17+ }
18+ p, seq := b.Request(major, 0, 8)
19+ if p == nil {
20+ return 0
21+ }
22+ binary.LittleEndian.PutUint32(p[0:], uint32(clientMajorVersion))
23+ binary.LittleEndian.PutUint32(p[4:], uint32(clientMinorVersion))
24+ return seq
25+}
26+
27+func QueryPictFormats(b *xturbo.Buf) xturbo.Seq {
28+ if b.Ext == nil {
29+ b.Fail(xturbo.ErrExtMissing)
30+ return 0
31+ }
32+ major := b.Ext.Major(xturbo.ExtRender)
33+ if major == 0 {
34+ b.Fail(xturbo.ErrExtMissing)
35+ return 0
36+ }
37+ p, seq := b.Request(major, 1, 0)
38+ if p == nil {
39+ return 0
40+ }
41+ return seq
42+}
43+
44+func QueryPictIndexValues(b *xturbo.Buf, format Pictformat) xturbo.Seq {
45+ if b.Ext == nil {
46+ b.Fail(xturbo.ErrExtMissing)
47+ return 0
48+ }
49+ major := b.Ext.Major(xturbo.ExtRender)
50+ if major == 0 {
51+ b.Fail(xturbo.ErrExtMissing)
52+ return 0
53+ }
54+ p, seq := b.Request(major, 2, 4)
55+ if p == nil {
56+ return 0
57+ }
58+ binary.LittleEndian.PutUint32(p[0:], uint32(format))
59+ return seq
60+}
61+
62+func SetPictureClipRectangles(b *xturbo.Buf, picture Picture, clipXOrigin int16, clipYOrigin int16, rectangles []xproto.Rectangle) xturbo.Seq {
63+ size := 0
64+ size += 4
65+ size += 2
66+ size += 2
67+ size += len(rectangles) * 8
68+ size = (size + 3) &^ 3
69+ if b.Ext == nil {
70+ b.Fail(xturbo.ErrExtMissing)
71+ return 0
72+ }
73+ major := b.Ext.Major(xturbo.ExtRender)
74+ if major == 0 {
75+ b.Fail(xturbo.ErrExtMissing)
76+ return 0
77+ }
78+ p, seq := b.Request(major, 6, size)
79+ if p == nil {
80+ return 0
81+ }
82+ off := 0
83+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
84+ off += 4
85+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
86+ off += 2
87+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
88+ off += 2
89+ for i := range rectangles {
90+ rectangles[i].Put(p[off:])
91+ off += 8
92+ }
93+ return seq
94+}
95+
96+func FreePicture(b *xturbo.Buf, picture Picture) xturbo.Seq {
97+ if b.Ext == nil {
98+ b.Fail(xturbo.ErrExtMissing)
99+ return 0
100+ }
101+ major := b.Ext.Major(xturbo.ExtRender)
102+ if major == 0 {
103+ b.Fail(xturbo.ErrExtMissing)
104+ return 0
105+ }
106+ p, seq := b.Request(major, 7, 4)
107+ if p == nil {
108+ return 0
109+ }
110+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
111+ return seq
112+}
113+
114+func Composite(b *xturbo.Buf, op PictOp, src Picture, mask Picture, dst Picture, srcX int16, srcY int16, maskX int16, maskY int16, dstX int16, dstY int16, width uint16, height uint16) xturbo.Seq {
115+ if b.Ext == nil {
116+ b.Fail(xturbo.ErrExtMissing)
117+ return 0
118+ }
119+ major := b.Ext.Major(xturbo.ExtRender)
120+ if major == 0 {
121+ b.Fail(xturbo.ErrExtMissing)
122+ return 0
123+ }
124+ p, seq := b.Request(major, 8, 32)
125+ if p == nil {
126+ return 0
127+ }
128+ p[0:][0] = byte(op)
129+ binary.LittleEndian.PutUint32(p[4:], uint32(src))
130+ binary.LittleEndian.PutUint32(p[8:], uint32(mask))
131+ binary.LittleEndian.PutUint32(p[12:], uint32(dst))
132+ binary.LittleEndian.PutUint16(p[16:], uint16(srcX))
133+ binary.LittleEndian.PutUint16(p[18:], uint16(srcY))
134+ binary.LittleEndian.PutUint16(p[20:], uint16(maskX))
135+ binary.LittleEndian.PutUint16(p[22:], uint16(maskY))
136+ binary.LittleEndian.PutUint16(p[24:], uint16(dstX))
137+ binary.LittleEndian.PutUint16(p[26:], uint16(dstY))
138+ binary.LittleEndian.PutUint16(p[28:], uint16(width))
139+ binary.LittleEndian.PutUint16(p[30:], uint16(height))
140+ return seq
141+}
142+
143+func Trapezoids(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, traps []Trapezoid) xturbo.Seq {
144+ size := 0
145+ size += 1
146+ size += 3
147+ size += 4
148+ size += 4
149+ size += 4
150+ size += 2
151+ size += 2
152+ size += len(traps) * 40
153+ size = (size + 3) &^ 3
154+ if b.Ext == nil {
155+ b.Fail(xturbo.ErrExtMissing)
156+ return 0
157+ }
158+ major := b.Ext.Major(xturbo.ExtRender)
159+ if major == 0 {
160+ b.Fail(xturbo.ErrExtMissing)
161+ return 0
162+ }
163+ p, seq := b.Request(major, 10, size)
164+ if p == nil {
165+ return 0
166+ }
167+ off := 0
168+ p[off:][0] = byte(op)
169+ off += 1
170+ off += 3
171+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
172+ off += 4
173+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
176+ off += 4
177+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
178+ off += 2
179+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
180+ off += 2
181+ for i := range traps {
182+ traps[i].Put(p[off:])
183+ off += 40
184+ }
185+ return seq
186+}
187+
188+func Triangles(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, triangles []Triangle) xturbo.Seq {
189+ size := 0
190+ size += 1
191+ size += 3
192+ size += 4
193+ size += 4
194+ size += 4
195+ size += 2
196+ size += 2
197+ size += len(triangles) * 24
198+ size = (size + 3) &^ 3
199+ if b.Ext == nil {
200+ b.Fail(xturbo.ErrExtMissing)
201+ return 0
202+ }
203+ major := b.Ext.Major(xturbo.ExtRender)
204+ if major == 0 {
205+ b.Fail(xturbo.ErrExtMissing)
206+ return 0
207+ }
208+ p, seq := b.Request(major, 11, size)
209+ if p == nil {
210+ return 0
211+ }
212+ off := 0
213+ p[off:][0] = byte(op)
214+ off += 1
215+ off += 3
216+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
217+ off += 4
218+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
219+ off += 4
220+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
221+ off += 4
222+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
223+ off += 2
224+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
225+ off += 2
226+ for i := range triangles {
227+ triangles[i].Put(p[off:])
228+ off += 24
229+ }
230+ return seq
231+}
232+
233+func TriStrip(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
234+ size := 0
235+ size += 1
236+ size += 3
237+ size += 4
238+ size += 4
239+ size += 4
240+ size += 2
241+ size += 2
242+ size += len(points) * 8
243+ size = (size + 3) &^ 3
244+ if b.Ext == nil {
245+ b.Fail(xturbo.ErrExtMissing)
246+ return 0
247+ }
248+ major := b.Ext.Major(xturbo.ExtRender)
249+ if major == 0 {
250+ b.Fail(xturbo.ErrExtMissing)
251+ return 0
252+ }
253+ p, seq := b.Request(major, 12, size)
254+ if p == nil {
255+ return 0
256+ }
257+ off := 0
258+ p[off:][0] = byte(op)
259+ off += 1
260+ off += 3
261+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
262+ off += 4
263+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
264+ off += 4
265+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
266+ off += 4
267+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
268+ off += 2
269+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
270+ off += 2
271+ for i := range points {
272+ points[i].Put(p[off:])
273+ off += 8
274+ }
275+ return seq
276+}
277+
278+func TriFan(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
279+ size := 0
280+ size += 1
281+ size += 3
282+ size += 4
283+ size += 4
284+ size += 4
285+ size += 2
286+ size += 2
287+ size += len(points) * 8
288+ size = (size + 3) &^ 3
289+ if b.Ext == nil {
290+ b.Fail(xturbo.ErrExtMissing)
291+ return 0
292+ }
293+ major := b.Ext.Major(xturbo.ExtRender)
294+ if major == 0 {
295+ b.Fail(xturbo.ErrExtMissing)
296+ return 0
297+ }
298+ p, seq := b.Request(major, 13, size)
299+ if p == nil {
300+ return 0
301+ }
302+ off := 0
303+ p[off:][0] = byte(op)
304+ off += 1
305+ off += 3
306+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
307+ off += 4
308+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
309+ off += 4
310+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
311+ off += 4
312+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
313+ off += 2
314+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
315+ off += 2
316+ for i := range points {
317+ points[i].Put(p[off:])
318+ off += 8
319+ }
320+ return seq
321+}
322+
323+func CreateGlyphSet(b *xturbo.Buf, gsid Glyphset, format Pictformat) xturbo.Seq {
324+ if b.Ext == nil {
325+ b.Fail(xturbo.ErrExtMissing)
326+ return 0
327+ }
328+ major := b.Ext.Major(xturbo.ExtRender)
329+ if major == 0 {
330+ b.Fail(xturbo.ErrExtMissing)
331+ return 0
332+ }
333+ p, seq := b.Request(major, 17, 8)
334+ if p == nil {
335+ return 0
336+ }
337+ binary.LittleEndian.PutUint32(p[0:], uint32(gsid))
338+ binary.LittleEndian.PutUint32(p[4:], uint32(format))
339+ return seq
340+}
341+
342+func ReferenceGlyphSet(b *xturbo.Buf, gsid Glyphset, existing Glyphset) xturbo.Seq {
343+ if b.Ext == nil {
344+ b.Fail(xturbo.ErrExtMissing)
345+ return 0
346+ }
347+ major := b.Ext.Major(xturbo.ExtRender)
348+ if major == 0 {
349+ b.Fail(xturbo.ErrExtMissing)
350+ return 0
351+ }
352+ p, seq := b.Request(major, 18, 8)
353+ if p == nil {
354+ return 0
355+ }
356+ binary.LittleEndian.PutUint32(p[0:], uint32(gsid))
357+ binary.LittleEndian.PutUint32(p[4:], uint32(existing))
358+ return seq
359+}
360+
361+func FreeGlyphSet(b *xturbo.Buf, glyphset Glyphset) xturbo.Seq {
362+ if b.Ext == nil {
363+ b.Fail(xturbo.ErrExtMissing)
364+ return 0
365+ }
366+ major := b.Ext.Major(xturbo.ExtRender)
367+ if major == 0 {
368+ b.Fail(xturbo.ErrExtMissing)
369+ return 0
370+ }
371+ p, seq := b.Request(major, 19, 4)
372+ if p == nil {
373+ return 0
374+ }
375+ binary.LittleEndian.PutUint32(p[0:], uint32(glyphset))
376+ return seq
377+}
378+
379+func AddGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphsLen uint32, glyphids []uint32, glyphs []Glyphinfo, data []byte) xturbo.Seq {
380+ if len(glyphids) != int(glyphsLen) {
381+ b.Fail(xturbo.ErrBadLength)
382+ return 0
383+ }
384+ if len(glyphs) != int(glyphsLen) {
385+ b.Fail(xturbo.ErrBadLength)
386+ return 0
387+ }
388+ size := 0
389+ size += 4
390+ size += 4
391+ size += len(glyphids) * 4
392+ size += len(glyphs) * 12
393+ size += len(data) * 1
394+ size = (size + 3) &^ 3
395+ if b.Ext == nil {
396+ b.Fail(xturbo.ErrExtMissing)
397+ return 0
398+ }
399+ major := b.Ext.Major(xturbo.ExtRender)
400+ if major == 0 {
401+ b.Fail(xturbo.ErrExtMissing)
402+ return 0
403+ }
404+ p, seq := b.Request(major, 20, size)
405+ if p == nil {
406+ return 0
407+ }
408+ off := 0
409+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
410+ off += 4
411+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphsLen))
412+ off += 4
413+ for i := range glyphids {
414+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphids[i]))
415+ off += 4
416+ }
417+ for i := range glyphs {
418+ glyphs[i].Put(p[off:])
419+ off += 12
420+ }
421+ copy(p[off:], data)
422+ off += len(data)
423+ return seq
424+}
425+
426+func FreeGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphs []Glyph) xturbo.Seq {
427+ size := 0
428+ size += 4
429+ size += len(glyphs) * 4
430+ size = (size + 3) &^ 3
431+ if b.Ext == nil {
432+ b.Fail(xturbo.ErrExtMissing)
433+ return 0
434+ }
435+ major := b.Ext.Major(xturbo.ExtRender)
436+ if major == 0 {
437+ b.Fail(xturbo.ErrExtMissing)
438+ return 0
439+ }
440+ p, seq := b.Request(major, 22, size)
441+ if p == nil {
442+ return 0
443+ }
444+ off := 0
445+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
446+ off += 4
447+ for i := range glyphs {
448+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphs[i]))
449+ off += 4
450+ }
451+ return seq
452+}
453+
454+func CompositeGlyphs8(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
455+ size := 0
456+ size += 1
457+ size += 3
458+ size += 4
459+ size += 4
460+ size += 4
461+ size += 4
462+ size += 2
463+ size += 2
464+ size += len(glyphcmds) * 1
465+ size = (size + 3) &^ 3
466+ if b.Ext == nil {
467+ b.Fail(xturbo.ErrExtMissing)
468+ return 0
469+ }
470+ major := b.Ext.Major(xturbo.ExtRender)
471+ if major == 0 {
472+ b.Fail(xturbo.ErrExtMissing)
473+ return 0
474+ }
475+ p, seq := b.Request(major, 23, size)
476+ if p == nil {
477+ return 0
478+ }
479+ off := 0
480+ p[off:][0] = byte(op)
481+ off += 1
482+ off += 3
483+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
484+ off += 4
485+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
486+ off += 4
487+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
488+ off += 4
489+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
490+ off += 4
491+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
492+ off += 2
493+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
494+ off += 2
495+ copy(p[off:], glyphcmds)
496+ off += len(glyphcmds)
497+ return seq
498+}
499+
500+func CompositeGlyphs16(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
501+ size := 0
502+ size += 1
503+ size += 3
504+ size += 4
505+ size += 4
506+ size += 4
507+ size += 4
508+ size += 2
509+ size += 2
510+ size += len(glyphcmds) * 1
511+ size = (size + 3) &^ 3
512+ if b.Ext == nil {
513+ b.Fail(xturbo.ErrExtMissing)
514+ return 0
515+ }
516+ major := b.Ext.Major(xturbo.ExtRender)
517+ if major == 0 {
518+ b.Fail(xturbo.ErrExtMissing)
519+ return 0
520+ }
521+ p, seq := b.Request(major, 24, size)
522+ if p == nil {
523+ return 0
524+ }
525+ off := 0
526+ p[off:][0] = byte(op)
527+ off += 1
528+ off += 3
529+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
530+ off += 4
531+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
532+ off += 4
533+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
534+ off += 4
535+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
536+ off += 4
537+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
538+ off += 2
539+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
540+ off += 2
541+ copy(p[off:], glyphcmds)
542+ off += len(glyphcmds)
543+ return seq
544+}
545+
546+func CompositeGlyphs32(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
547+ size := 0
548+ size += 1
549+ size += 3
550+ size += 4
551+ size += 4
552+ size += 4
553+ size += 4
554+ size += 2
555+ size += 2
556+ size += len(glyphcmds) * 1
557+ size = (size + 3) &^ 3
558+ if b.Ext == nil {
559+ b.Fail(xturbo.ErrExtMissing)
560+ return 0
561+ }
562+ major := b.Ext.Major(xturbo.ExtRender)
563+ if major == 0 {
564+ b.Fail(xturbo.ErrExtMissing)
565+ return 0
566+ }
567+ p, seq := b.Request(major, 25, size)
568+ if p == nil {
569+ return 0
570+ }
571+ off := 0
572+ p[off:][0] = byte(op)
573+ off += 1
574+ off += 3
575+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
576+ off += 4
577+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
578+ off += 4
579+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
580+ off += 4
581+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
582+ off += 4
583+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
584+ off += 2
585+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
586+ off += 2
587+ copy(p[off:], glyphcmds)
588+ off += len(glyphcmds)
589+ return seq
590+}
591+
592+func FillRectangles(b *xturbo.Buf, op PictOp, dst Picture, color Color, rects []xproto.Rectangle) xturbo.Seq {
593+ size := 0
594+ size += 1
595+ size += 3
596+ size += 4
597+ size += 8
598+ size += len(rects) * 8
599+ size = (size + 3) &^ 3
600+ if b.Ext == nil {
601+ b.Fail(xturbo.ErrExtMissing)
602+ return 0
603+ }
604+ major := b.Ext.Major(xturbo.ExtRender)
605+ if major == 0 {
606+ b.Fail(xturbo.ErrExtMissing)
607+ return 0
608+ }
609+ p, seq := b.Request(major, 26, size)
610+ if p == nil {
611+ return 0
612+ }
613+ off := 0
614+ p[off:][0] = byte(op)
615+ off += 1
616+ off += 3
617+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
618+ off += 4
619+ color.Put(p[off:])
620+ off += 8
621+ for i := range rects {
622+ rects[i].Put(p[off:])
623+ off += 8
624+ }
625+ return seq
626+}
627+
628+func CreateCursor(b *xturbo.Buf, cid xproto.Cursor, source Picture, x uint16, y uint16) xturbo.Seq {
629+ if b.Ext == nil {
630+ b.Fail(xturbo.ErrExtMissing)
631+ return 0
632+ }
633+ major := b.Ext.Major(xturbo.ExtRender)
634+ if major == 0 {
635+ b.Fail(xturbo.ErrExtMissing)
636+ return 0
637+ }
638+ p, seq := b.Request(major, 27, 12)
639+ if p == nil {
640+ return 0
641+ }
642+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
643+ binary.LittleEndian.PutUint32(p[4:], uint32(source))
644+ binary.LittleEndian.PutUint16(p[8:], uint16(x))
645+ binary.LittleEndian.PutUint16(p[10:], uint16(y))
646+ return seq
647+}
648+
649+func SetPictureTransform(b *xturbo.Buf, picture Picture, transform Transform) xturbo.Seq {
650+ if b.Ext == nil {
651+ b.Fail(xturbo.ErrExtMissing)
652+ return 0
653+ }
654+ major := b.Ext.Major(xturbo.ExtRender)
655+ if major == 0 {
656+ b.Fail(xturbo.ErrExtMissing)
657+ return 0
658+ }
659+ p, seq := b.Request(major, 28, 40)
660+ if p == nil {
661+ return 0
662+ }
663+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
664+ transform.Put(p[4:])
665+ return seq
666+}
667+
668+func QueryFilters(b *xturbo.Buf, drawable xproto.Drawable) xturbo.Seq {
669+ if b.Ext == nil {
670+ b.Fail(xturbo.ErrExtMissing)
671+ return 0
672+ }
673+ major := b.Ext.Major(xturbo.ExtRender)
674+ if major == 0 {
675+ b.Fail(xturbo.ErrExtMissing)
676+ return 0
677+ }
678+ p, seq := b.Request(major, 29, 4)
679+ if p == nil {
680+ return 0
681+ }
682+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
683+ return seq
684+}
685+
686+func SetPictureFilter(b *xturbo.Buf, picture Picture, filter string, values []Fixed) xturbo.Seq {
687+ if uint64(len(filter)) > 65535 {
688+ b.Fail(xturbo.ErrBadLength)
689+ return 0
690+ }
691+ size := 0
692+ size += 4
693+ size += 2
694+ size += 2
695+ size += len(filter) * 1
696+ size = (size + 3) &^ 3
697+ size += len(values) * 4
698+ size = (size + 3) &^ 3
699+ if b.Ext == nil {
700+ b.Fail(xturbo.ErrExtMissing)
701+ return 0
702+ }
703+ major := b.Ext.Major(xturbo.ExtRender)
704+ if major == 0 {
705+ b.Fail(xturbo.ErrExtMissing)
706+ return 0
707+ }
708+ p, seq := b.Request(major, 30, size)
709+ if p == nil {
710+ return 0
711+ }
712+ off := 0
713+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
714+ off += 4
715+ binary.LittleEndian.PutUint16(p[off:], uint16(len(filter)))
716+ off += 2
717+ off += 2
718+ copy(p[off:], filter)
719+ off += len(filter)
720+ off = (off + 3) &^ 3
721+ for i := range values {
722+ binary.LittleEndian.PutUint32(p[off:], uint32(values[i]))
723+ off += 4
724+ }
725+ return seq
726+}
727+
728+func CreateAnimCursor(b *xturbo.Buf, cid xproto.Cursor, cursors []Animcursorelt) xturbo.Seq {
729+ size := 0
730+ size += 4
731+ size += len(cursors) * 8
732+ size = (size + 3) &^ 3
733+ if b.Ext == nil {
734+ b.Fail(xturbo.ErrExtMissing)
735+ return 0
736+ }
737+ major := b.Ext.Major(xturbo.ExtRender)
738+ if major == 0 {
739+ b.Fail(xturbo.ErrExtMissing)
740+ return 0
741+ }
742+ p, seq := b.Request(major, 31, size)
743+ if p == nil {
744+ return 0
745+ }
746+ off := 0
747+ binary.LittleEndian.PutUint32(p[off:], uint32(cid))
748+ off += 4
749+ for i := range cursors {
750+ cursors[i].Put(p[off:])
751+ off += 8
752+ }
753+ return seq
754+}
755+
756+func AddTraps(b *xturbo.Buf, picture Picture, xOff int16, yOff int16, traps []Trap) xturbo.Seq {
757+ size := 0
758+ size += 4
759+ size += 2
760+ size += 2
761+ size += len(traps) * 24
762+ size = (size + 3) &^ 3
763+ if b.Ext == nil {
764+ b.Fail(xturbo.ErrExtMissing)
765+ return 0
766+ }
767+ major := b.Ext.Major(xturbo.ExtRender)
768+ if major == 0 {
769+ b.Fail(xturbo.ErrExtMissing)
770+ return 0
771+ }
772+ p, seq := b.Request(major, 32, size)
773+ if p == nil {
774+ return 0
775+ }
776+ off := 0
777+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
778+ off += 4
779+ binary.LittleEndian.PutUint16(p[off:], uint16(xOff))
780+ off += 2
781+ binary.LittleEndian.PutUint16(p[off:], uint16(yOff))
782+ off += 2
783+ for i := range traps {
784+ traps[i].Put(p[off:])
785+ off += 24
786+ }
787+ return seq
788+}
789+
790+func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
791+ if b.Ext == nil {
792+ b.Fail(xturbo.ErrExtMissing)
793+ return 0
794+ }
795+ major := b.Ext.Major(xturbo.ExtRender)
796+ if major == 0 {
797+ b.Fail(xturbo.ErrExtMissing)
798+ return 0
799+ }
800+ p, seq := b.Request(major, 33, 12)
801+ if p == nil {
802+ return 0
803+ }
804+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
805+ color.Put(p[4:])
806+ return seq
807+}
808+
809+func CreateLinearGradient(b *xturbo.Buf, picture Picture, p1 Pointfix, p2 Pointfix, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
810+ if len(stops) != int(numStops) {
811+ b.Fail(xturbo.ErrBadLength)
812+ return 0
813+ }
814+ if len(colors) != int(numStops) {
815+ b.Fail(xturbo.ErrBadLength)
816+ return 0
817+ }
818+ size := 0
819+ size += 4
820+ size += 8
821+ size += 8
822+ size += 4
823+ size += len(stops) * 4
824+ size += len(colors) * 8
825+ size = (size + 3) &^ 3
826+ if b.Ext == nil {
827+ b.Fail(xturbo.ErrExtMissing)
828+ return 0
829+ }
830+ major := b.Ext.Major(xturbo.ExtRender)
831+ if major == 0 {
832+ b.Fail(xturbo.ErrExtMissing)
833+ return 0
834+ }
835+ p, seq := b.Request(major, 34, size)
836+ if p == nil {
837+ return 0
838+ }
839+ off := 0
840+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
841+ off += 4
842+ p1.Put(p[off:])
843+ off += 8
844+ p2.Put(p[off:])
845+ off += 8
846+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
847+ off += 4
848+ for i := range stops {
849+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
850+ off += 4
851+ }
852+ for i := range colors {
853+ colors[i].Put(p[off:])
854+ off += 8
855+ }
856+ return seq
857+}
858+
859+func CreateRadialGradient(b *xturbo.Buf, picture Picture, inner Pointfix, outer Pointfix, innerRadius Fixed, outerRadius Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
860+ if len(stops) != int(numStops) {
861+ b.Fail(xturbo.ErrBadLength)
862+ return 0
863+ }
864+ if len(colors) != int(numStops) {
865+ b.Fail(xturbo.ErrBadLength)
866+ return 0
867+ }
868+ size := 0
869+ size += 4
870+ size += 8
871+ size += 8
872+ size += 4
873+ size += 4
874+ size += 4
875+ size += len(stops) * 4
876+ size += len(colors) * 8
877+ size = (size + 3) &^ 3
878+ if b.Ext == nil {
879+ b.Fail(xturbo.ErrExtMissing)
880+ return 0
881+ }
882+ major := b.Ext.Major(xturbo.ExtRender)
883+ if major == 0 {
884+ b.Fail(xturbo.ErrExtMissing)
885+ return 0
886+ }
887+ p, seq := b.Request(major, 35, size)
888+ if p == nil {
889+ return 0
890+ }
891+ off := 0
892+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
893+ off += 4
894+ inner.Put(p[off:])
895+ off += 8
896+ outer.Put(p[off:])
897+ off += 8
898+ binary.LittleEndian.PutUint32(p[off:], uint32(innerRadius))
899+ off += 4
900+ binary.LittleEndian.PutUint32(p[off:], uint32(outerRadius))
901+ off += 4
902+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
903+ off += 4
904+ for i := range stops {
905+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
906+ off += 4
907+ }
908+ for i := range colors {
909+ colors[i].Put(p[off:])
910+ off += 8
911+ }
912+ return seq
913+}
914+
915+func CreateConicalGradient(b *xturbo.Buf, picture Picture, center Pointfix, angle Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
916+ if len(stops) != int(numStops) {
917+ b.Fail(xturbo.ErrBadLength)
918+ return 0
919+ }
920+ if len(colors) != int(numStops) {
921+ b.Fail(xturbo.ErrBadLength)
922+ return 0
923+ }
924+ size := 0
925+ size += 4
926+ size += 8
927+ size += 4
928+ size += 4
929+ size += len(stops) * 4
930+ size += len(colors) * 8
931+ size = (size + 3) &^ 3
932+ if b.Ext == nil {
933+ b.Fail(xturbo.ErrExtMissing)
934+ return 0
935+ }
936+ major := b.Ext.Major(xturbo.ExtRender)
937+ if major == 0 {
938+ b.Fail(xturbo.ErrExtMissing)
939+ return 0
940+ }
941+ p, seq := b.Request(major, 36, size)
942+ if p == nil {
943+ return 0
944+ }
945+ off := 0
946+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
947+ off += 4
948+ center.Put(p[off:])
949+ off += 8
950+ binary.LittleEndian.PutUint32(p[off:], uint32(angle))
951+ off += 4
952+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
953+ off += 4
954+ for i := range stops {
955+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
956+ off += 4
957+ }
958+ for i := range colors {
959+ colors[i].Put(p[off:])
960+ off += 8
961+ }
962+ return seq
963+}
A render/sizes_test.go +68 -0
@@ -0,0 +1,68 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package render
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if DirectformatSize != 16 {
8+ t.Errorf("Directformat fixed prefix = %d", DirectformatSize)
9+ }
10+ if PictforminfoSize != 28 {
11+ t.Errorf("Pictforminfo fixed prefix = %d", PictforminfoSize)
12+ }
13+ if PictvisualSize != 8 {
14+ t.Errorf("Pictvisual fixed prefix = %d", PictvisualSize)
15+ }
16+ if PictdepthSize != 8 {
17+ t.Errorf("Pictdepth fixed prefix = %d", PictdepthSize)
18+ }
19+ if PictscreenSize != 8 {
20+ t.Errorf("Pictscreen fixed prefix = %d", PictscreenSize)
21+ }
22+ if IndexvalueSize != 12 {
23+ t.Errorf("Indexvalue fixed prefix = %d", IndexvalueSize)
24+ }
25+ if ColorSize != 8 {
26+ t.Errorf("Color fixed prefix = %d", ColorSize)
27+ }
28+ if PointfixSize != 8 {
29+ t.Errorf("Pointfix fixed prefix = %d", PointfixSize)
30+ }
31+ if LinefixSize != 16 {
32+ t.Errorf("Linefix fixed prefix = %d", LinefixSize)
33+ }
34+ if TriangleSize != 24 {
35+ t.Errorf("Triangle fixed prefix = %d", TriangleSize)
36+ }
37+ if TrapezoidSize != 40 {
38+ t.Errorf("Trapezoid fixed prefix = %d", TrapezoidSize)
39+ }
40+ if GlyphinfoSize != 12 {
41+ t.Errorf("Glyphinfo fixed prefix = %d", GlyphinfoSize)
42+ }
43+ if TransformSize != 36 {
44+ t.Errorf("Transform fixed prefix = %d", TransformSize)
45+ }
46+ if AnimcursoreltSize != 8 {
47+ t.Errorf("Animcursorelt fixed prefix = %d", AnimcursoreltSize)
48+ }
49+ if SpanfixSize != 12 {
50+ t.Errorf("Spanfix fixed prefix = %d", SpanfixSize)
51+ }
52+ if TrapSize != 24 {
53+ t.Errorf("Trap fixed prefix = %d", TrapSize)
54+ }
55+ if got := 32; got != 32 {
56+ t.Errorf("reply QueryVersion fixed size = %d", got)
57+ }
58+ if got := 32; got != 32 {
59+ t.Errorf("reply QueryPictFormats fixed size = %d", got)
60+ }
61+ if got := 32; got != 32 {
62+ t.Errorf("reply QueryPictIndexValues fixed size = %d", got)
63+ }
64+ if got := 32; got != 32 {
65+ t.Errorf("reply QueryFilters fixed size = %d", got)
66+ }
67+
68+}
A render/types_generated.go +522 -0
@@ -0,0 +1,522 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package render
3+
4+import "bnema.dev/xturbo/xproto"
5+import "encoding/binary"
6+
7+type Glyph uint32
8+
9+type Glyphset uint32
10+
11+type Picture uint32
12+
13+type Pictformat uint32
14+
15+type Fixed int32
16+
17+type Directformat struct {
18+ RedShift uint16
19+ RedMask uint16
20+ GreenShift uint16
21+ GreenMask uint16
22+ BlueShift uint16
23+ BlueMask uint16
24+ AlphaShift uint16
25+ AlphaMask uint16
26+}
27+
28+const DirectformatSize = 16
29+
30+func (v Directformat) Put(p []byte) {
31+ clear(p[:16])
32+ binary.LittleEndian.PutUint16(p[0:], uint16(v.RedShift))
33+ binary.LittleEndian.PutUint16(p[2:], uint16(v.RedMask))
34+ binary.LittleEndian.PutUint16(p[4:], uint16(v.GreenShift))
35+ binary.LittleEndian.PutUint16(p[6:], uint16(v.GreenMask))
36+ binary.LittleEndian.PutUint16(p[8:], uint16(v.BlueShift))
37+ binary.LittleEndian.PutUint16(p[10:], uint16(v.BlueMask))
38+ binary.LittleEndian.PutUint16(p[12:], uint16(v.AlphaShift))
39+ binary.LittleEndian.PutUint16(p[14:], uint16(v.AlphaMask))
40+}
41+func GetDirectformat(p []byte) (v Directformat) {
42+ _ = p[15]
43+ v.RedShift = uint16(binary.LittleEndian.Uint16(p[0:]))
44+ v.RedMask = uint16(binary.LittleEndian.Uint16(p[2:]))
45+ v.GreenShift = uint16(binary.LittleEndian.Uint16(p[4:]))
46+ v.GreenMask = uint16(binary.LittleEndian.Uint16(p[6:]))
47+ v.BlueShift = uint16(binary.LittleEndian.Uint16(p[8:]))
48+ v.BlueMask = uint16(binary.LittleEndian.Uint16(p[10:]))
49+ v.AlphaShift = uint16(binary.LittleEndian.Uint16(p[12:]))
50+ v.AlphaMask = uint16(binary.LittleEndian.Uint16(p[14:]))
51+ return
52+}
53+
54+type Pictforminfo struct {
55+ Id Pictformat
56+ Type PictType
57+ Depth uint8
58+ Direct Directformat
59+ Colormap xproto.Colormap
60+}
61+
62+const PictforminfoSize = 28
63+
64+func (v Pictforminfo) Put(p []byte) {
65+ clear(p[:28])
66+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Id))
67+ p[4:][0] = byte(v.Type)
68+ p[5:][0] = byte(v.Depth)
69+ v.Direct.Put(p[8:])
70+ binary.LittleEndian.PutUint32(p[24:], uint32(v.Colormap))
71+}
72+func GetPictforminfo(p []byte) (v Pictforminfo) {
73+ _ = p[27]
74+ v.Id = Pictformat(binary.LittleEndian.Uint32(p[0:]))
75+ v.Type = PictType(p[4:][0])
76+ v.Depth = uint8(p[5:][0])
77+ v.Direct = GetDirectformat(p[8:])
78+ v.Colormap = xproto.Colormap(binary.LittleEndian.Uint32(p[24:]))
79+ return
80+}
81+
82+type Pictvisual struct {
83+ Visual xproto.Visualid
84+ Format Pictformat
85+}
86+
87+const PictvisualSize = 8
88+
89+func (v Pictvisual) Put(p []byte) {
90+ clear(p[:8])
91+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Visual))
92+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Format))
93+}
94+func GetPictvisual(p []byte) (v Pictvisual) {
95+ _ = p[7]
96+ v.Visual = xproto.Visualid(binary.LittleEndian.Uint32(p[0:]))
97+ v.Format = Pictformat(binary.LittleEndian.Uint32(p[4:]))
98+ return
99+}
100+
101+type Pictdepth struct {
102+ Depth uint8
103+ NumVisuals uint16
104+ Visuals []Pictvisual
105+}
106+
107+const PictdepthSize = 8
108+
109+func (v Pictdepth) Size() int {
110+ off := 0
111+ off += 1
112+ off += 1
113+ off += 2
114+ off += 4
115+ off += len(v.Visuals) * 8
116+ return off
117+}
118+func (v Pictdepth) Put(p []byte) {
119+ off := 0
120+ p[off:][0] = byte(v.Depth)
121+ off += 1
122+ clear(p[off : off+1])
123+ off += 1
124+ binary.LittleEndian.PutUint16(p[off:], uint16(v.NumVisuals))
125+ off += 2
126+ clear(p[off : off+4])
127+ off += 4
128+ for i := range v.Visuals {
129+ v.Visuals[i].Put(p[off+i*8:])
130+ }
131+ off += len(v.Visuals) * 8
132+}
133+
134+type Pictscreen struct {
135+ NumDepths uint32
136+ Fallback Pictformat
137+ Depths []Pictdepth
138+}
139+
140+const PictscreenSize = 8
141+
142+func (v Pictscreen) Size() int {
143+ off := 0
144+ off += 4
145+ off += 4
146+ for i := range v.Depths {
147+ off += v.Depths[i].Size()
148+ }
149+ return off
150+}
151+func (v Pictscreen) Put(p []byte) {
152+ off := 0
153+ binary.LittleEndian.PutUint32(p[off:], uint32(v.NumDepths))
154+ off += 4
155+ binary.LittleEndian.PutUint32(p[off:], uint32(v.Fallback))
156+ off += 4
157+ for i := range v.Depths {
158+ v.Depths[i].Put(p[off:])
159+ off += v.Depths[i].Size()
160+ }
161+}
162+
163+type Indexvalue struct {
164+ Pixel uint32
165+ Red uint16
166+ Green uint16
167+ Blue uint16
168+ Alpha uint16
169+}
170+
171+const IndexvalueSize = 12
172+
173+func (v Indexvalue) Put(p []byte) {
174+ clear(p[:12])
175+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Pixel))
176+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Red))
177+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Green))
178+ binary.LittleEndian.PutUint16(p[8:], uint16(v.Blue))
179+ binary.LittleEndian.PutUint16(p[10:], uint16(v.Alpha))
180+}
181+func GetIndexvalue(p []byte) (v Indexvalue) {
182+ _ = p[11]
183+ v.Pixel = uint32(binary.LittleEndian.Uint32(p[0:]))
184+ v.Red = uint16(binary.LittleEndian.Uint16(p[4:]))
185+ v.Green = uint16(binary.LittleEndian.Uint16(p[6:]))
186+ v.Blue = uint16(binary.LittleEndian.Uint16(p[8:]))
187+ v.Alpha = uint16(binary.LittleEndian.Uint16(p[10:]))
188+ return
189+}
190+
191+type Color struct {
192+ Red uint16
193+ Green uint16
194+ Blue uint16
195+ Alpha uint16
196+}
197+
198+const ColorSize = 8
199+
200+func (v Color) Put(p []byte) {
201+ clear(p[:8])
202+ binary.LittleEndian.PutUint16(p[0:], uint16(v.Red))
203+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Green))
204+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Blue))
205+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Alpha))
206+}
207+func GetColor(p []byte) (v Color) {
208+ _ = p[7]
209+ v.Red = uint16(binary.LittleEndian.Uint16(p[0:]))
210+ v.Green = uint16(binary.LittleEndian.Uint16(p[2:]))
211+ v.Blue = uint16(binary.LittleEndian.Uint16(p[4:]))
212+ v.Alpha = uint16(binary.LittleEndian.Uint16(p[6:]))
213+ return
214+}
215+
216+type Pointfix struct {
217+ X Fixed
218+ Y Fixed
219+}
220+
221+const PointfixSize = 8
222+
223+func (v Pointfix) Put(p []byte) {
224+ clear(p[:8])
225+ binary.LittleEndian.PutUint32(p[0:], uint32(v.X))
226+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Y))
227+}
228+func GetPointfix(p []byte) (v Pointfix) {
229+ _ = p[7]
230+ v.X = Fixed(binary.LittleEndian.Uint32(p[0:]))
231+ v.Y = Fixed(binary.LittleEndian.Uint32(p[4:]))
232+ return
233+}
234+
235+type Linefix struct {
236+ P1 Pointfix
237+ P2 Pointfix
238+}
239+
240+const LinefixSize = 16
241+
242+func (v Linefix) Put(p []byte) { clear(p[:16]); v.P1.Put(p[0:]); v.P2.Put(p[8:]) }
243+func GetLinefix(p []byte) (v Linefix) {
244+ _ = p[15]
245+ v.P1 = GetPointfix(p[0:])
246+ v.P2 = GetPointfix(p[8:])
247+ return
248+}
249+
250+type Triangle struct {
251+ P1 Pointfix
252+ P2 Pointfix
253+ P3 Pointfix
254+}
255+
256+const TriangleSize = 24
257+
258+func (v Triangle) Put(p []byte) { clear(p[:24]); v.P1.Put(p[0:]); v.P2.Put(p[8:]); v.P3.Put(p[16:]) }
259+func GetTriangle(p []byte) (v Triangle) {
260+ _ = p[23]
261+ v.P1 = GetPointfix(p[0:])
262+ v.P2 = GetPointfix(p[8:])
263+ v.P3 = GetPointfix(p[16:])
264+ return
265+}
266+
267+type Trapezoid struct {
268+ Top Fixed
269+ Bottom Fixed
270+ Left Linefix
271+ Right Linefix
272+}
273+
274+const TrapezoidSize = 40
275+
276+func (v Trapezoid) Put(p []byte) {
277+ clear(p[:40])
278+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Top))
279+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Bottom))
280+ v.Left.Put(p[8:])
281+ v.Right.Put(p[24:])
282+}
283+func GetTrapezoid(p []byte) (v Trapezoid) {
284+ _ = p[39]
285+ v.Top = Fixed(binary.LittleEndian.Uint32(p[0:]))
286+ v.Bottom = Fixed(binary.LittleEndian.Uint32(p[4:]))
287+ v.Left = GetLinefix(p[8:])
288+ v.Right = GetLinefix(p[24:])
289+ return
290+}
291+
292+type Glyphinfo struct {
293+ Width uint16
294+ Height uint16
295+ X int16
296+ Y int16
297+ XOff int16
298+ YOff int16
299+}
300+
301+const GlyphinfoSize = 12
302+
303+func (v Glyphinfo) Put(p []byte) {
304+ clear(p[:12])
305+ binary.LittleEndian.PutUint16(p[0:], uint16(v.Width))
306+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Height))
307+ binary.LittleEndian.PutUint16(p[4:], uint16(v.X))
308+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Y))
309+ binary.LittleEndian.PutUint16(p[8:], uint16(v.XOff))
310+ binary.LittleEndian.PutUint16(p[10:], uint16(v.YOff))
311+}
312+func GetGlyphinfo(p []byte) (v Glyphinfo) {
313+ _ = p[11]
314+ v.Width = uint16(binary.LittleEndian.Uint16(p[0:]))
315+ v.Height = uint16(binary.LittleEndian.Uint16(p[2:]))
316+ v.X = int16(binary.LittleEndian.Uint16(p[4:]))
317+ v.Y = int16(binary.LittleEndian.Uint16(p[6:]))
318+ v.XOff = int16(binary.LittleEndian.Uint16(p[8:]))
319+ v.YOff = int16(binary.LittleEndian.Uint16(p[10:]))
320+ return
321+}
322+
323+type Transform struct {
324+ Matrix11 Fixed
325+ Matrix12 Fixed
326+ Matrix13 Fixed
327+ Matrix21 Fixed
328+ Matrix22 Fixed
329+ Matrix23 Fixed
330+ Matrix31 Fixed
331+ Matrix32 Fixed
332+ Matrix33 Fixed
333+}
334+
335+const TransformSize = 36
336+
337+func (v Transform) Put(p []byte) {
338+ clear(p[:36])
339+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Matrix11))
340+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Matrix12))
341+ binary.LittleEndian.PutUint32(p[8:], uint32(v.Matrix13))
342+ binary.LittleEndian.PutUint32(p[12:], uint32(v.Matrix21))
343+ binary.LittleEndian.PutUint32(p[16:], uint32(v.Matrix22))
344+ binary.LittleEndian.PutUint32(p[20:], uint32(v.Matrix23))
345+ binary.LittleEndian.PutUint32(p[24:], uint32(v.Matrix31))
346+ binary.LittleEndian.PutUint32(p[28:], uint32(v.Matrix32))
347+ binary.LittleEndian.PutUint32(p[32:], uint32(v.Matrix33))
348+}
349+func GetTransform(p []byte) (v Transform) {
350+ _ = p[35]
351+ v.Matrix11 = Fixed(binary.LittleEndian.Uint32(p[0:]))
352+ v.Matrix12 = Fixed(binary.LittleEndian.Uint32(p[4:]))
353+ v.Matrix13 = Fixed(binary.LittleEndian.Uint32(p[8:]))
354+ v.Matrix21 = Fixed(binary.LittleEndian.Uint32(p[12:]))
355+ v.Matrix22 = Fixed(binary.LittleEndian.Uint32(p[16:]))
356+ v.Matrix23 = Fixed(binary.LittleEndian.Uint32(p[20:]))
357+ v.Matrix31 = Fixed(binary.LittleEndian.Uint32(p[24:]))
358+ v.Matrix32 = Fixed(binary.LittleEndian.Uint32(p[28:]))
359+ v.Matrix33 = Fixed(binary.LittleEndian.Uint32(p[32:]))
360+ return
361+}
362+
363+type Animcursorelt struct {
364+ Cursor xproto.Cursor
365+ Delay uint32
366+}
367+
368+const AnimcursoreltSize = 8
369+
370+func (v Animcursorelt) Put(p []byte) {
371+ clear(p[:8])
372+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Cursor))
373+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Delay))
374+}
375+func GetAnimcursorelt(p []byte) (v Animcursorelt) {
376+ _ = p[7]
377+ v.Cursor = xproto.Cursor(binary.LittleEndian.Uint32(p[0:]))
378+ v.Delay = uint32(binary.LittleEndian.Uint32(p[4:]))
379+ return
380+}
381+
382+type Spanfix struct {
383+ L Fixed
384+ R Fixed
385+ Y Fixed
386+}
387+
388+const SpanfixSize = 12
389+
390+func (v Spanfix) Put(p []byte) {
391+ clear(p[:12])
392+ binary.LittleEndian.PutUint32(p[0:], uint32(v.L))
393+ binary.LittleEndian.PutUint32(p[4:], uint32(v.R))
394+ binary.LittleEndian.PutUint32(p[8:], uint32(v.Y))
395+}
396+func GetSpanfix(p []byte) (v Spanfix) {
397+ _ = p[11]
398+ v.L = Fixed(binary.LittleEndian.Uint32(p[0:]))
399+ v.R = Fixed(binary.LittleEndian.Uint32(p[4:]))
400+ v.Y = Fixed(binary.LittleEndian.Uint32(p[8:]))
401+ return
402+}
403+
404+type Trap struct {
405+ Top Spanfix
406+ Bot Spanfix
407+}
408+
409+const TrapSize = 24
410+
411+func (v Trap) Put(p []byte) { clear(p[:24]); v.Top.Put(p[0:]); v.Bot.Put(p[12:]) }
412+func GetTrap(p []byte) (v Trap) {
413+ _ = p[23]
414+ v.Top = GetSpanfix(p[0:])
415+ v.Bot = GetSpanfix(p[12:])
416+ return
417+}
418+
419+type PictType uint8
420+
421+const PictTypeIndexed PictType = 0
422+const PictTypeDirect PictType = 1
423+
424+const PictureNone Picture = 0
425+
426+type PictOp uint8
427+
428+const PictOpClear PictOp = 0
429+const PictOpSrc PictOp = 1
430+const PictOpDst PictOp = 2
431+const PictOpOver PictOp = 3
432+const PictOpOverReverse PictOp = 4
433+const PictOpIn PictOp = 5
434+const PictOpInReverse PictOp = 6
435+const PictOpOut PictOp = 7
436+const PictOpOutReverse PictOp = 8
437+const PictOpAtop PictOp = 9
438+const PictOpAtopReverse PictOp = 10
439+const PictOpXor PictOp = 11
440+const PictOpAdd PictOp = 12
441+const PictOpSaturate PictOp = 13
442+const PictOpDisjointClear PictOp = 16
443+const PictOpDisjointSrc PictOp = 17
444+const PictOpDisjointDst PictOp = 18
445+const PictOpDisjointOver PictOp = 19
446+const PictOpDisjointOverReverse PictOp = 20
447+const PictOpDisjointIn PictOp = 21
448+const PictOpDisjointInReverse PictOp = 22
449+const PictOpDisjointOut PictOp = 23
450+const PictOpDisjointOutReverse PictOp = 24
451+const PictOpDisjointAtop PictOp = 25
452+const PictOpDisjointAtopReverse PictOp = 26
453+const PictOpDisjointXor PictOp = 27
454+const PictOpConjointClear PictOp = 32
455+const PictOpConjointSrc PictOp = 33
456+const PictOpConjointDst PictOp = 34
457+const PictOpConjointOver PictOp = 35
458+const PictOpConjointOverReverse PictOp = 36
459+const PictOpConjointIn PictOp = 37
460+const PictOpConjointInReverse PictOp = 38
461+const PictOpConjointOut PictOp = 39
462+const PictOpConjointOutReverse PictOp = 40
463+const PictOpConjointAtop PictOp = 41
464+const PictOpConjointAtopReverse PictOp = 42
465+const PictOpConjointXor PictOp = 43
466+const PictOpMultiply PictOp = 48
467+const PictOpScreen PictOp = 49
468+const PictOpOverlay PictOp = 50
469+const PictOpDarken PictOp = 51
470+const PictOpLighten PictOp = 52
471+const PictOpColorDodge PictOp = 53
472+const PictOpColorBurn PictOp = 54
473+const PictOpHardLight PictOp = 55
474+const PictOpSoftLight PictOp = 56
475+const PictOpDifference PictOp = 57
476+const PictOpExclusion PictOp = 58
477+const PictOpHSLHue PictOp = 59
478+const PictOpHSLSaturation PictOp = 60
479+const PictOpHSLColor PictOp = 61
480+const PictOpHSLLuminosity PictOp = 62
481+
482+type PolyEdge uint32
483+
484+const PolyEdgeSharp PolyEdge = 0
485+const PolyEdgeSmooth PolyEdge = 1
486+
487+type PolyMode uint32
488+
489+const PolyModePrecise PolyMode = 0
490+const PolyModeImprecise PolyMode = 1
491+
492+type Cp uint32
493+
494+const CpRepeat Cp = 1
495+const CpAlphaMap Cp = 2
496+const CpAlphaXOrigin Cp = 4
497+const CpAlphaYOrigin Cp = 8
498+const CpClipXOrigin Cp = 16
499+const CpClipYOrigin Cp = 32
500+const CpClipMask Cp = 64
501+const CpGraphicsExposure Cp = 128
502+const CpSubwindowMode Cp = 256
503+const CpPolyEdge Cp = 512
504+const CpPolyMode Cp = 1024
505+const CpDither Cp = 2048
506+const CpComponentAlpha Cp = 4096
507+
508+type SubPixel uint32
509+
510+const SubPixelUnknown SubPixel = 0
511+const SubPixelHorizontalRGB SubPixel = 1
512+const SubPixelHorizontalBGR SubPixel = 2
513+const SubPixelVerticalRGB SubPixel = 3
514+const SubPixelVerticalBGR SubPixel = 4
515+const SubPixelNone SubPixel = 5
516+
517+type Repeat uint32
518+
519+const RepeatNone Repeat = 0
520+const RepeatNormal Repeat = 1
521+const RepeatPad Repeat = 2
522+const RepeatReflect Repeat = 3
A requests_test.go +62 -0
@@ -0,0 +1,62 @@
1+package xturbo_test
2+
3+import (
4+ "bytes"
5+ "encoding/binary"
6+ "testing"
7+
8+ "bnema.dev/xturbo"
9+ "bnema.dev/xturbo/internal/xtest"
10+ "bnema.dev/xturbo/xfixes"
11+ "bnema.dev/xturbo/xproto"
12+)
13+
14+func TestRequestGoldens(t *testing.T) {
15+ for _, tc := range []struct {
16+ name string
17+ encode func(*xturbo.Buf, uint32) xturbo.Seq
18+ }{
19+ {"xproto/MapWindow", func(b *xturbo.Buf, id uint32) xturbo.Seq { return xproto.MapWindow(b, xproto.Window(id)) }},
20+ {"xproto/GetGeometry", func(b *xturbo.Buf, id uint32) xturbo.Seq { return xproto.GetGeometry(b, xproto.Drawable(id)) }},
21+ {"xfixes/QueryVersion", func(b *xturbo.Buf, _ uint32) xturbo.Seq { return xfixes.QueryVersion(b, 6, 0) }},
22+ } {
23+ t.Run(tc.name, func(t *testing.T) {
24+ want, err := xtest.LoadHex("testdata/golden/" + tc.name + ".req.hex")
25+ if err != nil {
26+ t.Fatal(err)
27+ }
28+ b := xturbo.NewBuf(0)
29+ var ext xturbo.ExtTable
30+ ext.Set(xturbo.ExtXFixes, want[0], 0, 0)
31+ b.Ext = &ext
32+ id := binary.LittleEndian.Uint32(want[4:])
33+ if tc.encode(b, id) != 1 || b.Err() != nil {
34+ t.Fatalf("seq/err: %v", b.Err())
35+ }
36+ if !bytes.Equal(b.Bytes(), want) {
37+ t.Fatalf("got %x want %x", b.Bytes(), want)
38+ }
39+ })
40+ }
41+}
42+func TestMissingExtension(t *testing.T) {
43+ for _, table := range []*xturbo.ExtTable{nil, {}} {
44+ b := xturbo.NewBuf(0)
45+ b.Ext = table
46+ if xfixes.QueryVersion(b, 6, 0) != 0 || b.Err() != xturbo.ErrExtMissing || b.Len() != 0 || xproto.MapWindow(b, 1) != 0 {
47+ t.Fatal("missing extension must fail sticky")
48+ }
49+ }
50+}
51+func TestAllocFixedRequests(t *testing.T) {
52+ b := xturbo.NewBuf(0)
53+ var ext xturbo.ExtTable
54+ ext.Set(xturbo.ExtXFixes, 138, 0, 0)
55+ b.Ext = &ext
56+ if n := testing.AllocsPerRun(1000, func() { b.Reset(); xproto.MapWindow(b, 1); xproto.GetGeometry(b, 1); xfixes.QueryVersion(b, 6, 0) }); n != 0 {
57+ t.Fatal(n)
58+ }
59+ if b.Err() != nil {
60+ t.Fatal(b.Err())
61+ }
62+}
A res/requests_generated.go +144 -0
@@ -0,0 +1,144 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package res
3+
4+import "encoding/binary"
5+import "bnema.dev/xturbo"
6+
7+func QueryVersion(b *xturbo.Buf, clientMajor uint8, clientMinor uint8) xturbo.Seq {
8+ if b.Ext == nil {
9+ b.Fail(xturbo.ErrExtMissing)
10+ return 0
11+ }
12+ major := b.Ext.Major(xturbo.ExtRes)
13+ if major == 0 {
14+ b.Fail(xturbo.ErrExtMissing)
15+ return 0
16+ }
17+ p, seq := b.Request(major, 0, 4)
18+ if p == nil {
19+ return 0
20+ }
21+ p[0:][0] = byte(clientMajor)
22+ p[1:][0] = byte(clientMinor)
23+ return seq
24+}
25+
26+func QueryClients(b *xturbo.Buf) xturbo.Seq {
27+ if b.Ext == nil {
28+ b.Fail(xturbo.ErrExtMissing)
29+ return 0
30+ }
31+ major := b.Ext.Major(xturbo.ExtRes)
32+ if major == 0 {
33+ b.Fail(xturbo.ErrExtMissing)
34+ return 0
35+ }
36+ p, seq := b.Request(major, 1, 0)
37+ if p == nil {
38+ return 0
39+ }
40+ return seq
41+}
42+
43+func QueryClientResources(b *xturbo.Buf, xid uint32) xturbo.Seq {
44+ if b.Ext == nil {
45+ b.Fail(xturbo.ErrExtMissing)
46+ return 0
47+ }
48+ major := b.Ext.Major(xturbo.ExtRes)
49+ if major == 0 {
50+ b.Fail(xturbo.ErrExtMissing)
51+ return 0
52+ }
53+ p, seq := b.Request(major, 2, 4)
54+ if p == nil {
55+ return 0
56+ }
57+ binary.LittleEndian.PutUint32(p[0:], uint32(xid))
58+ return seq
59+}
60+
61+func QueryClientPixmapBytes(b *xturbo.Buf, xid uint32) xturbo.Seq {
62+ if b.Ext == nil {
63+ b.Fail(xturbo.ErrExtMissing)
64+ return 0
65+ }
66+ major := b.Ext.Major(xturbo.ExtRes)
67+ if major == 0 {
68+ b.Fail(xturbo.ErrExtMissing)
69+ return 0
70+ }
71+ p, seq := b.Request(major, 3, 4)
72+ if p == nil {
73+ return 0
74+ }
75+ binary.LittleEndian.PutUint32(p[0:], uint32(xid))
76+ return seq
77+}
78+
79+func QueryClientIds(b *xturbo.Buf, specs []ClientIdSpec) xturbo.Seq {
80+ if uint64(len(specs)) > 4294967295 {
81+ b.Fail(xturbo.ErrBadLength)
82+ return 0
83+ }
84+ size := 0
85+ size += 4
86+ size += len(specs) * 8
87+ size = (size + 3) &^ 3
88+ if b.Ext == nil {
89+ b.Fail(xturbo.ErrExtMissing)
90+ return 0
91+ }
92+ major := b.Ext.Major(xturbo.ExtRes)
93+ if major == 0 {
94+ b.Fail(xturbo.ErrExtMissing)
95+ return 0
96+ }
97+ p, seq := b.Request(major, 4, size)
98+ if p == nil {
99+ return 0
100+ }
101+ off := 0
102+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
103+ off += 4
104+ for i := range specs {
105+ specs[i].Put(p[off:])
106+ off += 8
107+ }
108+ return seq
109+}
110+
111+func QueryResourceBytes(b *xturbo.Buf, client uint32, specs []ResourceIdSpec) xturbo.Seq {
112+ if uint64(len(specs)) > 4294967295 {
113+ b.Fail(xturbo.ErrBadLength)
114+ return 0
115+ }
116+ size := 0
117+ size += 4
118+ size += 4
119+ size += len(specs) * 8
120+ size = (size + 3) &^ 3
121+ if b.Ext == nil {
122+ b.Fail(xturbo.ErrExtMissing)
123+ return 0
124+ }
125+ major := b.Ext.Major(xturbo.ExtRes)
126+ if major == 0 {
127+ b.Fail(xturbo.ErrExtMissing)
128+ return 0
129+ }
130+ p, seq := b.Request(major, 5, size)
131+ if p == nil {
132+ return 0
133+ }
134+ off := 0
135+ binary.LittleEndian.PutUint32(p[off:], uint32(client))
136+ off += 4
137+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
138+ off += 4
139+ for i := range specs {
140+ specs[i].Put(p[off:])
141+ off += 8
142+ }
143+ return seq
144+}
A res/sizes_test.go +47 -0
@@ -0,0 +1,47 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package res
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if ClientSize != 8 {
8+ t.Errorf("Client fixed prefix = %d", ClientSize)
9+ }
10+ if TypeSize != 8 {
11+ t.Errorf("Type fixed prefix = %d", TypeSize)
12+ }
13+ if ClientIdSpecSize != 8 {
14+ t.Errorf("ClientIdSpec fixed prefix = %d", ClientIdSpecSize)
15+ }
16+ if ClientIdValueSize != 12 {
17+ t.Errorf("ClientIdValue fixed prefix = %d", ClientIdValueSize)
18+ }
19+ if ResourceIdSpecSize != 8 {
20+ t.Errorf("ResourceIdSpec fixed prefix = %d", ResourceIdSpecSize)
21+ }
22+ if ResourceSizeSpecSize != 20 {
23+ t.Errorf("ResourceSizeSpec fixed prefix = %d", ResourceSizeSpecSize)
24+ }
25+ if ResourceSizeValueSize != 24 {
26+ t.Errorf("ResourceSizeValue fixed prefix = %d", ResourceSizeValueSize)
27+ }
28+ if got := 32; got != 32 {
29+ t.Errorf("reply QueryVersion fixed size = %d", got)
30+ }
31+ if got := 32; got != 32 {
32+ t.Errorf("reply QueryClients fixed size = %d", got)
33+ }
34+ if got := 32; got != 32 {
35+ t.Errorf("reply QueryClientResources fixed size = %d", got)
36+ }
37+ if got := 32; got != 32 {
38+ t.Errorf("reply QueryClientPixmapBytes fixed size = %d", got)
39+ }
40+ if got := 32; got != 32 {
41+ t.Errorf("reply QueryClientIds fixed size = %d", got)
42+ }
43+ if got := 32; got != 32 {
44+ t.Errorf("reply QueryResourceBytes fixed size = %d", got)
45+ }
46+
47+}
A res/types_generated.go +159 -0
@@ -0,0 +1,159 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package res
3+
4+import "bnema.dev/xturbo/xproto"
5+import "encoding/binary"
6+
7+type Client struct {
8+ ResourceBase uint32
9+ ResourceMask uint32
10+}
11+
12+const ClientSize = 8
13+
14+func (v Client) Put(p []byte) {
15+ clear(p[:8])
16+ binary.LittleEndian.PutUint32(p[0:], uint32(v.ResourceBase))
17+ binary.LittleEndian.PutUint32(p[4:], uint32(v.ResourceMask))
18+}
19+func GetClient(p []byte) (v Client) {
20+ _ = p[7]
21+ v.ResourceBase = uint32(binary.LittleEndian.Uint32(p[0:]))
22+ v.ResourceMask = uint32(binary.LittleEndian.Uint32(p[4:]))
23+ return
24+}
25+
26+type Type struct {
27+ ResourceType xproto.Atom
28+ Count uint32
29+}
30+
31+const TypeSize = 8
32+
33+func (v Type) Put(p []byte) {
34+ clear(p[:8])
35+ binary.LittleEndian.PutUint32(p[0:], uint32(v.ResourceType))
36+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Count))
37+}
38+func GetType(p []byte) (v Type) {
39+ _ = p[7]
40+ v.ResourceType = xproto.Atom(binary.LittleEndian.Uint32(p[0:]))
41+ v.Count = uint32(binary.LittleEndian.Uint32(p[4:]))
42+ return
43+}
44+
45+type ClientIdSpec struct {
46+ Client uint32
47+ Mask ClientIdMask
48+}
49+
50+const ClientIdSpecSize = 8
51+
52+func (v ClientIdSpec) Put(p []byte) {
53+ clear(p[:8])
54+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Client))
55+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Mask))
56+}
57+func GetClientIdSpec(p []byte) (v ClientIdSpec) {
58+ _ = p[7]
59+ v.Client = uint32(binary.LittleEndian.Uint32(p[0:]))
60+ v.Mask = ClientIdMask(binary.LittleEndian.Uint32(p[4:]))
61+ return
62+}
63+
64+type ClientIdValue struct {
65+ Spec ClientIdSpec
66+ Length uint32
67+ Value []uint32
68+}
69+
70+const ClientIdValueSize = 12
71+
72+func (v ClientIdValue) Size() int { off := 0; off += 8; off += 4; off += len(v.Value) * 4; return off }
73+func (v ClientIdValue) Put(p []byte) {
74+ off := 0
75+ v.Spec.Put(p[off:])
76+ off += 8
77+ binary.LittleEndian.PutUint32(p[off:], uint32(v.Length))
78+ off += 4
79+ for i := range v.Value {
80+ binary.LittleEndian.PutUint32(p[off+i*4:], uint32(v.Value[i]))
81+ }
82+ off += len(v.Value) * 4
83+}
84+
85+type ResourceIdSpec struct {
86+ Resource uint32
87+ Type uint32
88+}
89+
90+const ResourceIdSpecSize = 8
91+
92+func (v ResourceIdSpec) Put(p []byte) {
93+ clear(p[:8])
94+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Resource))
95+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Type))
96+}
97+func GetResourceIdSpec(p []byte) (v ResourceIdSpec) {
98+ _ = p[7]
99+ v.Resource = uint32(binary.LittleEndian.Uint32(p[0:]))
100+ v.Type = uint32(binary.LittleEndian.Uint32(p[4:]))
101+ return
102+}
103+
104+type ResourceSizeSpec struct {
105+ Spec ResourceIdSpec
106+ Bytes uint32
107+ RefCount uint32
108+ UseCount uint32
109+}
110+
111+const ResourceSizeSpecSize = 20
112+
113+func (v ResourceSizeSpec) Put(p []byte) {
114+ clear(p[:20])
115+ v.Spec.Put(p[0:])
116+ binary.LittleEndian.PutUint32(p[8:], uint32(v.Bytes))
117+ binary.LittleEndian.PutUint32(p[12:], uint32(v.RefCount))
118+ binary.LittleEndian.PutUint32(p[16:], uint32(v.UseCount))
119+}
120+func GetResourceSizeSpec(p []byte) (v ResourceSizeSpec) {
121+ _ = p[19]
122+ v.Spec = GetResourceIdSpec(p[0:])
123+ v.Bytes = uint32(binary.LittleEndian.Uint32(p[8:]))
124+ v.RefCount = uint32(binary.LittleEndian.Uint32(p[12:]))
125+ v.UseCount = uint32(binary.LittleEndian.Uint32(p[16:]))
126+ return
127+}
128+
129+type ResourceSizeValue struct {
130+ Size_ ResourceSizeSpec
131+ NumCrossReferences uint32
132+ CrossReferences []ResourceSizeSpec
133+}
134+
135+const ResourceSizeValueSize = 24
136+
137+func (v ResourceSizeValue) Size() int {
138+ off := 0
139+ off += 20
140+ off += 4
141+ off += len(v.CrossReferences) * 20
142+ return off
143+}
144+func (v ResourceSizeValue) Put(p []byte) {
145+ off := 0
146+ v.Size_.Put(p[off:])
147+ off += 20
148+ binary.LittleEndian.PutUint32(p[off:], uint32(v.NumCrossReferences))
149+ off += 4
150+ for i := range v.CrossReferences {
151+ v.CrossReferences[i].Put(p[off+i*20:])
152+ }
153+ off += len(v.CrossReferences) * 20
154+}
155+
156+type ClientIdMask uint32
157+
158+const ClientIdMaskClientXID ClientIdMask = 1
159+const ClientIdMaskLocalClientPID ClientIdMask = 2
A shape/requests_generated.go +214 -0
@@ -0,0 +1,214 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package shape
3+
4+import "bnema.dev/xturbo/xproto"
5+import "encoding/binary"
6+import "bnema.dev/xturbo"
7+
8+func QueryVersion(b *xturbo.Buf) xturbo.Seq {
9+ if b.Ext == nil {
10+ b.Fail(xturbo.ErrExtMissing)
11+ return 0
12+ }
13+ major := b.Ext.Major(xturbo.ExtShape)
14+ if major == 0 {
15+ b.Fail(xturbo.ErrExtMissing)
16+ return 0
17+ }
18+ p, seq := b.Request(major, 0, 0)
19+ if p == nil {
20+ return 0
21+ }
22+ return seq
23+}
24+
25+func Rectangles(b *xturbo.Buf, operation So, destinationKind Sk, ordering xproto.ClipOrdering, destinationWindow xproto.Window, xOffset int16, yOffset int16, rectangles []xproto.Rectangle) xturbo.Seq {
26+ size := 0
27+ size += 1
28+ size += 1
29+ size += 1
30+ size += 1
31+ size += 4
32+ size += 2
33+ size += 2
34+ size += len(rectangles) * 8
35+ size = (size + 3) &^ 3
36+ if b.Ext == nil {
37+ b.Fail(xturbo.ErrExtMissing)
38+ return 0
39+ }
40+ major := b.Ext.Major(xturbo.ExtShape)
41+ if major == 0 {
42+ b.Fail(xturbo.ErrExtMissing)
43+ return 0
44+ }
45+ p, seq := b.Request(major, 1, size)
46+ if p == nil {
47+ return 0
48+ }
49+ off := 0
50+ p[off:][0] = byte(operation)
51+ off += 1
52+ p[off:][0] = byte(destinationKind)
53+ off += 1
54+ p[off:][0] = byte(ordering)
55+ off += 1
56+ off += 1
57+ binary.LittleEndian.PutUint32(p[off:], uint32(destinationWindow))
58+ off += 4
59+ binary.LittleEndian.PutUint16(p[off:], uint16(xOffset))
60+ off += 2
61+ binary.LittleEndian.PutUint16(p[off:], uint16(yOffset))
62+ off += 2
63+ for i := range rectangles {
64+ rectangles[i].Put(p[off:])
65+ off += 8
66+ }
67+ return seq
68+}
69+
70+func Mask(b *xturbo.Buf, operation So, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceBitmap xproto.Pixmap) xturbo.Seq {
71+ if b.Ext == nil {
72+ b.Fail(xturbo.ErrExtMissing)
73+ return 0
74+ }
75+ major := b.Ext.Major(xturbo.ExtShape)
76+ if major == 0 {
77+ b.Fail(xturbo.ErrExtMissing)
78+ return 0
79+ }
80+ p, seq := b.Request(major, 2, 16)
81+ if p == nil {
82+ return 0
83+ }
84+ p[0:][0] = byte(operation)
85+ p[1:][0] = byte(destinationKind)
86+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
87+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
88+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
89+ binary.LittleEndian.PutUint32(p[12:], uint32(sourceBitmap))
90+ return seq
91+}
92+
93+func Combine(b *xturbo.Buf, operation So, destinationKind Sk, sourceKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceWindow xproto.Window) xturbo.Seq {
94+ if b.Ext == nil {
95+ b.Fail(xturbo.ErrExtMissing)
96+ return 0
97+ }
98+ major := b.Ext.Major(xturbo.ExtShape)
99+ if major == 0 {
100+ b.Fail(xturbo.ErrExtMissing)
101+ return 0
102+ }
103+ p, seq := b.Request(major, 3, 16)
104+ if p == nil {
105+ return 0
106+ }
107+ p[0:][0] = byte(operation)
108+ p[1:][0] = byte(destinationKind)
109+ p[2:][0] = byte(sourceKind)
110+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
111+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
112+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
113+ binary.LittleEndian.PutUint32(p[12:], uint32(sourceWindow))
114+ return seq
115+}
116+
117+func Offset(b *xturbo.Buf, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16) xturbo.Seq {
118+ if b.Ext == nil {
119+ b.Fail(xturbo.ErrExtMissing)
120+ return 0
121+ }
122+ major := b.Ext.Major(xturbo.ExtShape)
123+ if major == 0 {
124+ b.Fail(xturbo.ErrExtMissing)
125+ return 0
126+ }
127+ p, seq := b.Request(major, 4, 12)
128+ if p == nil {
129+ return 0
130+ }
131+ p[0:][0] = byte(destinationKind)
132+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
133+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
134+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
135+ return seq
136+}
137+
138+func QueryExtents(b *xturbo.Buf, destinationWindow xproto.Window) xturbo.Seq {
139+ if b.Ext == nil {
140+ b.Fail(xturbo.ErrExtMissing)
141+ return 0
142+ }
143+ major := b.Ext.Major(xturbo.ExtShape)
144+ if major == 0 {
145+ b.Fail(xturbo.ErrExtMissing)
146+ return 0
147+ }
148+ p, seq := b.Request(major, 5, 4)
149+ if p == nil {
150+ return 0
151+ }
152+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
153+ return seq
154+}
155+
156+func SelectInput(b *xturbo.Buf, destinationWindow xproto.Window, enable bool) xturbo.Seq {
157+ if b.Ext == nil {
158+ b.Fail(xturbo.ErrExtMissing)
159+ return 0
160+ }
161+ major := b.Ext.Major(xturbo.ExtShape)
162+ if major == 0 {
163+ b.Fail(xturbo.ErrExtMissing)
164+ return 0
165+ }
166+ p, seq := b.Request(major, 6, 8)
167+ if p == nil {
168+ return 0
169+ }
170+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
171+ if enable {
172+ p[4:][0] = 1
173+ } else {
174+ p[4:][0] = 0
175+ }
176+ return seq
177+}
178+
179+func InputSelected(b *xturbo.Buf, destinationWindow xproto.Window) xturbo.Seq {
180+ if b.Ext == nil {
181+ b.Fail(xturbo.ErrExtMissing)
182+ return 0
183+ }
184+ major := b.Ext.Major(xturbo.ExtShape)
185+ if major == 0 {
186+ b.Fail(xturbo.ErrExtMissing)
187+ return 0
188+ }
189+ p, seq := b.Request(major, 7, 4)
190+ if p == nil {
191+ return 0
192+ }
193+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
194+ return seq
195+}
196+
197+func GetRectangles(b *xturbo.Buf, window xproto.Window, sourceKind Sk) xturbo.Seq {
198+ if b.Ext == nil {
199+ b.Fail(xturbo.ErrExtMissing)
200+ return 0
201+ }
202+ major := b.Ext.Major(xturbo.ExtShape)
203+ if major == 0 {
204+ b.Fail(xturbo.ErrExtMissing)
205+ return 0
206+ }
207+ p, seq := b.Request(major, 8, 8)
208+ if p == nil {
209+ return 0
210+ }
211+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
212+ p[4:][0] = byte(sourceKind)
213+ return seq
214+}
A shape/sizes_test.go +23 -0
@@ -0,0 +1,23 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package shape
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("event Notify fixed size = %d", got)
9+ }
10+ if got := 32; got != 32 {
11+ t.Errorf("reply QueryVersion fixed size = %d", got)
12+ }
13+ if got := 32; got != 32 {
14+ t.Errorf("reply QueryExtents fixed size = %d", got)
15+ }
16+ if got := 32; got != 32 {
17+ t.Errorf("reply InputSelected fixed size = %d", got)
18+ }
19+ if got := 32; got != 32 {
20+ t.Errorf("reply GetRectangles fixed size = %d", got)
21+ }
22+
23+}
A shape/types_generated.go +20 -0
@@ -0,0 +1,20 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package shape
3+
4+type Op uint8
5+
6+type Kind uint8
7+
8+type So uint8
9+
10+const SoSet So = 0
11+const SoUnion So = 1
12+const SoIntersect So = 2
13+const SoSubtract So = 3
14+const SoInvert So = 4
15+
16+type Sk uint8
17+
18+const SkBounding Sk = 0
19+const SkClip Sk = 1
20+const SkInput Sk = 2
A testdata/golden/res/QueryClientIds.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+94040400010000000000000001000000
A testdata/golden/xfixes/QueryVersion.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+8a0003000600000000000000
A testdata/golden/xproto/ChangeProperty.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+120007009f030000e70000001f000000080000000300000061626300
A testdata/golden/xproto/GetGeometry.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+0e0002009f030000
A testdata/golden/xproto/InternAtom.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+100004000700000058545552424f5f00
A testdata/golden/xproto/MapWindow.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+080002009f030000
A xcmisc/requests_generated.go +59 -0
@@ -0,0 +1,59 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xcmisc
3+
4+import "encoding/binary"
5+import "bnema.dev/xturbo"
6+
7+func GetVersion(b *xturbo.Buf, clientMajorVersion uint16, clientMinorVersion uint16) xturbo.Seq {
8+ if b.Ext == nil {
9+ b.Fail(xturbo.ErrExtMissing)
10+ return 0
11+ }
12+ major := b.Ext.Major(xturbo.ExtXCMisc)
13+ if major == 0 {
14+ b.Fail(xturbo.ErrExtMissing)
15+ return 0
16+ }
17+ p, seq := b.Request(major, 0, 4)
18+ if p == nil {
19+ return 0
20+ }
21+ binary.LittleEndian.PutUint16(p[0:], uint16(clientMajorVersion))
22+ binary.LittleEndian.PutUint16(p[2:], uint16(clientMinorVersion))
23+ return seq
24+}
25+
26+func GetXIDRange(b *xturbo.Buf) xturbo.Seq {
27+ if b.Ext == nil {
28+ b.Fail(xturbo.ErrExtMissing)
29+ return 0
30+ }
31+ major := b.Ext.Major(xturbo.ExtXCMisc)
32+ if major == 0 {
33+ b.Fail(xturbo.ErrExtMissing)
34+ return 0
35+ }
36+ p, seq := b.Request(major, 1, 0)
37+ if p == nil {
38+ return 0
39+ }
40+ return seq
41+}
42+
43+func GetXIDList(b *xturbo.Buf, count uint32) xturbo.Seq {
44+ if b.Ext == nil {
45+ b.Fail(xturbo.ErrExtMissing)
46+ return 0
47+ }
48+ major := b.Ext.Major(xturbo.ExtXCMisc)
49+ if major == 0 {
50+ b.Fail(xturbo.ErrExtMissing)
51+ return 0
52+ }
53+ p, seq := b.Request(major, 2, 4)
54+ if p == nil {
55+ return 0
56+ }
57+ binary.LittleEndian.PutUint32(p[0:], uint32(count))
58+ return seq
59+}
A xcmisc/sizes_test.go +17 -0
@@ -0,0 +1,17 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xcmisc
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("reply GetVersion fixed size = %d", got)
9+ }
10+ if got := 32; got != 32 {
11+ t.Errorf("reply GetXIDRange fixed size = %d", got)
12+ }
13+ if got := 32; got != 32 {
14+ t.Errorf("reply GetXIDList fixed size = %d", got)
15+ }
16+
17+}
A xcmisc/types_generated.go +2 -0
@@ -0,0 +1,2 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xcmisc
A xfixes/requests_generated.go +766 -0
@@ -0,0 +1,766 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xfixes
3+
4+import "bnema.dev/xturbo/render"
5+import "bnema.dev/xturbo/shape"
6+import "bnema.dev/xturbo/xproto"
7+import "encoding/binary"
8+import "bnema.dev/xturbo"
9+
10+func QueryVersion(b *xturbo.Buf, clientMajorVersion uint32, clientMinorVersion uint32) xturbo.Seq {
11+ if b.Ext == nil {
12+ b.Fail(xturbo.ErrExtMissing)
13+ return 0
14+ }
15+ major := b.Ext.Major(xturbo.ExtXFixes)
16+ if major == 0 {
17+ b.Fail(xturbo.ErrExtMissing)
18+ return 0
19+ }
20+ p, seq := b.Request(major, 0, 8)
21+ if p == nil {
22+ return 0
23+ }
24+ binary.LittleEndian.PutUint32(p[0:], uint32(clientMajorVersion))
25+ binary.LittleEndian.PutUint32(p[4:], uint32(clientMinorVersion))
26+ return seq
27+}
28+
29+func ChangeSaveSet(b *xturbo.Buf, mode SaveSetMode, target SaveSetTarget, map_ SaveSetMapping, window xproto.Window) xturbo.Seq {
30+ if b.Ext == nil {
31+ b.Fail(xturbo.ErrExtMissing)
32+ return 0
33+ }
34+ major := b.Ext.Major(xturbo.ExtXFixes)
35+ if major == 0 {
36+ b.Fail(xturbo.ErrExtMissing)
37+ return 0
38+ }
39+ p, seq := b.Request(major, 1, 8)
40+ if p == nil {
41+ return 0
42+ }
43+ p[0:][0] = byte(mode)
44+ p[1:][0] = byte(target)
45+ p[2:][0] = byte(map_)
46+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
47+ return seq
48+}
49+
50+func SelectSelectionInput(b *xturbo.Buf, window xproto.Window, selection xproto.Atom, eventMask SelectionEventMask) xturbo.Seq {
51+ if b.Ext == nil {
52+ b.Fail(xturbo.ErrExtMissing)
53+ return 0
54+ }
55+ major := b.Ext.Major(xturbo.ExtXFixes)
56+ if major == 0 {
57+ b.Fail(xturbo.ErrExtMissing)
58+ return 0
59+ }
60+ p, seq := b.Request(major, 2, 12)
61+ if p == nil {
62+ return 0
63+ }
64+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
65+ binary.LittleEndian.PutUint32(p[4:], uint32(selection))
66+ binary.LittleEndian.PutUint32(p[8:], uint32(eventMask))
67+ return seq
68+}
69+
70+func SelectCursorInput(b *xturbo.Buf, window xproto.Window, eventMask CursorNotifyMask) xturbo.Seq {
71+ if b.Ext == nil {
72+ b.Fail(xturbo.ErrExtMissing)
73+ return 0
74+ }
75+ major := b.Ext.Major(xturbo.ExtXFixes)
76+ if major == 0 {
77+ b.Fail(xturbo.ErrExtMissing)
78+ return 0
79+ }
80+ p, seq := b.Request(major, 3, 8)
81+ if p == nil {
82+ return 0
83+ }
84+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
85+ binary.LittleEndian.PutUint32(p[4:], uint32(eventMask))
86+ return seq
87+}
88+
89+func GetCursorImage(b *xturbo.Buf) xturbo.Seq {
90+ if b.Ext == nil {
91+ b.Fail(xturbo.ErrExtMissing)
92+ return 0
93+ }
94+ major := b.Ext.Major(xturbo.ExtXFixes)
95+ if major == 0 {
96+ b.Fail(xturbo.ErrExtMissing)
97+ return 0
98+ }
99+ p, seq := b.Request(major, 4, 0)
100+ if p == nil {
101+ return 0
102+ }
103+ return seq
104+}
105+
106+func CreateRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
107+ size := 0
108+ size += 4
109+ size += len(rectangles) * 8
110+ size = (size + 3) &^ 3
111+ if b.Ext == nil {
112+ b.Fail(xturbo.ErrExtMissing)
113+ return 0
114+ }
115+ major := b.Ext.Major(xturbo.ExtXFixes)
116+ if major == 0 {
117+ b.Fail(xturbo.ErrExtMissing)
118+ return 0
119+ }
120+ p, seq := b.Request(major, 5, size)
121+ if p == nil {
122+ return 0
123+ }
124+ off := 0
125+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
126+ off += 4
127+ for i := range rectangles {
128+ rectangles[i].Put(p[off:])
129+ off += 8
130+ }
131+ return seq
132+}
133+
134+func CreateRegionFromBitmap(b *xturbo.Buf, region Region, bitmap xproto.Pixmap) xturbo.Seq {
135+ if b.Ext == nil {
136+ b.Fail(xturbo.ErrExtMissing)
137+ return 0
138+ }
139+ major := b.Ext.Major(xturbo.ExtXFixes)
140+ if major == 0 {
141+ b.Fail(xturbo.ErrExtMissing)
142+ return 0
143+ }
144+ p, seq := b.Request(major, 6, 8)
145+ if p == nil {
146+ return 0
147+ }
148+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
149+ binary.LittleEndian.PutUint32(p[4:], uint32(bitmap))
150+ return seq
151+}
152+
153+func CreateRegionFromWindow(b *xturbo.Buf, region Region, window xproto.Window, kind shape.Sk) xturbo.Seq {
154+ if b.Ext == nil {
155+ b.Fail(xturbo.ErrExtMissing)
156+ return 0
157+ }
158+ major := b.Ext.Major(xturbo.ExtXFixes)
159+ if major == 0 {
160+ b.Fail(xturbo.ErrExtMissing)
161+ return 0
162+ }
163+ p, seq := b.Request(major, 7, 12)
164+ if p == nil {
165+ return 0
166+ }
167+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
168+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
169+ p[8:][0] = byte(kind)
170+ return seq
171+}
172+
173+func CreateRegionFromGC(b *xturbo.Buf, region Region, gc xproto.Gcontext) xturbo.Seq {
174+ if b.Ext == nil {
175+ b.Fail(xturbo.ErrExtMissing)
176+ return 0
177+ }
178+ major := b.Ext.Major(xturbo.ExtXFixes)
179+ if major == 0 {
180+ b.Fail(xturbo.ErrExtMissing)
181+ return 0
182+ }
183+ p, seq := b.Request(major, 8, 8)
184+ if p == nil {
185+ return 0
186+ }
187+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
188+ binary.LittleEndian.PutUint32(p[4:], uint32(gc))
189+ return seq
190+}
191+
192+func CreateRegionFromPicture(b *xturbo.Buf, region Region, picture render.Picture) xturbo.Seq {
193+ if b.Ext == nil {
194+ b.Fail(xturbo.ErrExtMissing)
195+ return 0
196+ }
197+ major := b.Ext.Major(xturbo.ExtXFixes)
198+ if major == 0 {
199+ b.Fail(xturbo.ErrExtMissing)
200+ return 0
201+ }
202+ p, seq := b.Request(major, 9, 8)
203+ if p == nil {
204+ return 0
205+ }
206+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
207+ binary.LittleEndian.PutUint32(p[4:], uint32(picture))
208+ return seq
209+}
210+
211+func DestroyRegion(b *xturbo.Buf, region Region) xturbo.Seq {
212+ if b.Ext == nil {
213+ b.Fail(xturbo.ErrExtMissing)
214+ return 0
215+ }
216+ major := b.Ext.Major(xturbo.ExtXFixes)
217+ if major == 0 {
218+ b.Fail(xturbo.ErrExtMissing)
219+ return 0
220+ }
221+ p, seq := b.Request(major, 10, 4)
222+ if p == nil {
223+ return 0
224+ }
225+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
226+ return seq
227+}
228+
229+func SetRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
230+ size := 0
231+ size += 4
232+ size += len(rectangles) * 8
233+ size = (size + 3) &^ 3
234+ if b.Ext == nil {
235+ b.Fail(xturbo.ErrExtMissing)
236+ return 0
237+ }
238+ major := b.Ext.Major(xturbo.ExtXFixes)
239+ if major == 0 {
240+ b.Fail(xturbo.ErrExtMissing)
241+ return 0
242+ }
243+ p, seq := b.Request(major, 11, size)
244+ if p == nil {
245+ return 0
246+ }
247+ off := 0
248+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
249+ off += 4
250+ for i := range rectangles {
251+ rectangles[i].Put(p[off:])
252+ off += 8
253+ }
254+ return seq
255+}
256+
257+func CopyRegion(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
258+ if b.Ext == nil {
259+ b.Fail(xturbo.ErrExtMissing)
260+ return 0
261+ }
262+ major := b.Ext.Major(xturbo.ExtXFixes)
263+ if major == 0 {
264+ b.Fail(xturbo.ErrExtMissing)
265+ return 0
266+ }
267+ p, seq := b.Request(major, 12, 8)
268+ if p == nil {
269+ return 0
270+ }
271+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
272+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
273+ return seq
274+}
275+
276+func UnionRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
277+ if b.Ext == nil {
278+ b.Fail(xturbo.ErrExtMissing)
279+ return 0
280+ }
281+ major := b.Ext.Major(xturbo.ExtXFixes)
282+ if major == 0 {
283+ b.Fail(xturbo.ErrExtMissing)
284+ return 0
285+ }
286+ p, seq := b.Request(major, 13, 12)
287+ if p == nil {
288+ return 0
289+ }
290+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
291+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
292+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
293+ return seq
294+}
295+
296+func IntersectRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
297+ if b.Ext == nil {
298+ b.Fail(xturbo.ErrExtMissing)
299+ return 0
300+ }
301+ major := b.Ext.Major(xturbo.ExtXFixes)
302+ if major == 0 {
303+ b.Fail(xturbo.ErrExtMissing)
304+ return 0
305+ }
306+ p, seq := b.Request(major, 14, 12)
307+ if p == nil {
308+ return 0
309+ }
310+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
311+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
312+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
313+ return seq
314+}
315+
316+func SubtractRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
317+ if b.Ext == nil {
318+ b.Fail(xturbo.ErrExtMissing)
319+ return 0
320+ }
321+ major := b.Ext.Major(xturbo.ExtXFixes)
322+ if major == 0 {
323+ b.Fail(xturbo.ErrExtMissing)
324+ return 0
325+ }
326+ p, seq := b.Request(major, 15, 12)
327+ if p == nil {
328+ return 0
329+ }
330+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
331+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
332+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
333+ return seq
334+}
335+
336+func InvertRegion(b *xturbo.Buf, source Region, bounds xproto.Rectangle, destination Region) xturbo.Seq {
337+ if b.Ext == nil {
338+ b.Fail(xturbo.ErrExtMissing)
339+ return 0
340+ }
341+ major := b.Ext.Major(xturbo.ExtXFixes)
342+ if major == 0 {
343+ b.Fail(xturbo.ErrExtMissing)
344+ return 0
345+ }
346+ p, seq := b.Request(major, 16, 16)
347+ if p == nil {
348+ return 0
349+ }
350+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
351+ bounds.Put(p[4:])
352+ binary.LittleEndian.PutUint32(p[12:], uint32(destination))
353+ return seq
354+}
355+
356+func TranslateRegion(b *xturbo.Buf, region Region, dx int16, dy int16) xturbo.Seq {
357+ if b.Ext == nil {
358+ b.Fail(xturbo.ErrExtMissing)
359+ return 0
360+ }
361+ major := b.Ext.Major(xturbo.ExtXFixes)
362+ if major == 0 {
363+ b.Fail(xturbo.ErrExtMissing)
364+ return 0
365+ }
366+ p, seq := b.Request(major, 17, 8)
367+ if p == nil {
368+ return 0
369+ }
370+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
371+ binary.LittleEndian.PutUint16(p[4:], uint16(dx))
372+ binary.LittleEndian.PutUint16(p[6:], uint16(dy))
373+ return seq
374+}
375+
376+func RegionExtents(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
377+ if b.Ext == nil {
378+ b.Fail(xturbo.ErrExtMissing)
379+ return 0
380+ }
381+ major := b.Ext.Major(xturbo.ExtXFixes)
382+ if major == 0 {
383+ b.Fail(xturbo.ErrExtMissing)
384+ return 0
385+ }
386+ p, seq := b.Request(major, 18, 8)
387+ if p == nil {
388+ return 0
389+ }
390+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
391+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
392+ return seq
393+}
394+
395+func FetchRegion(b *xturbo.Buf, region Region) xturbo.Seq {
396+ if b.Ext == nil {
397+ b.Fail(xturbo.ErrExtMissing)
398+ return 0
399+ }
400+ major := b.Ext.Major(xturbo.ExtXFixes)
401+ if major == 0 {
402+ b.Fail(xturbo.ErrExtMissing)
403+ return 0
404+ }
405+ p, seq := b.Request(major, 19, 4)
406+ if p == nil {
407+ return 0
408+ }
409+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
410+ return seq
411+}
412+
413+func SetGCClipRegion(b *xturbo.Buf, gc xproto.Gcontext, region Region, xOrigin int16, yOrigin int16) xturbo.Seq {
414+ if b.Ext == nil {
415+ b.Fail(xturbo.ErrExtMissing)
416+ return 0
417+ }
418+ major := b.Ext.Major(xturbo.ExtXFixes)
419+ if major == 0 {
420+ b.Fail(xturbo.ErrExtMissing)
421+ return 0
422+ }
423+ p, seq := b.Request(major, 20, 12)
424+ if p == nil {
425+ return 0
426+ }
427+ binary.LittleEndian.PutUint32(p[0:], uint32(gc))
428+ binary.LittleEndian.PutUint32(p[4:], uint32(region))
429+ binary.LittleEndian.PutUint16(p[8:], uint16(xOrigin))
430+ binary.LittleEndian.PutUint16(p[10:], uint16(yOrigin))
431+ return seq
432+}
433+
434+func SetWindowShapeRegion(b *xturbo.Buf, dest xproto.Window, destKind shape.Sk, xOffset int16, yOffset int16, region Region) xturbo.Seq {
435+ if b.Ext == nil {
436+ b.Fail(xturbo.ErrExtMissing)
437+ return 0
438+ }
439+ major := b.Ext.Major(xturbo.ExtXFixes)
440+ if major == 0 {
441+ b.Fail(xturbo.ErrExtMissing)
442+ return 0
443+ }
444+ p, seq := b.Request(major, 21, 16)
445+ if p == nil {
446+ return 0
447+ }
448+ binary.LittleEndian.PutUint32(p[0:], uint32(dest))
449+ p[4:][0] = byte(destKind)
450+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
451+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
452+ binary.LittleEndian.PutUint32(p[12:], uint32(region))
453+ return seq
454+}
455+
456+func SetPictureClipRegion(b *xturbo.Buf, picture render.Picture, region Region, xOrigin int16, yOrigin int16) xturbo.Seq {
457+ if b.Ext == nil {
458+ b.Fail(xturbo.ErrExtMissing)
459+ return 0
460+ }
461+ major := b.Ext.Major(xturbo.ExtXFixes)
462+ if major == 0 {
463+ b.Fail(xturbo.ErrExtMissing)
464+ return 0
465+ }
466+ p, seq := b.Request(major, 22, 12)
467+ if p == nil {
468+ return 0
469+ }
470+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
471+ binary.LittleEndian.PutUint32(p[4:], uint32(region))
472+ binary.LittleEndian.PutUint16(p[8:], uint16(xOrigin))
473+ binary.LittleEndian.PutUint16(p[10:], uint16(yOrigin))
474+ return seq
475+}
476+
477+func SetCursorName(b *xturbo.Buf, cursor xproto.Cursor, name string) xturbo.Seq {
478+ if uint64(len(name)) > 65535 {
479+ b.Fail(xturbo.ErrBadLength)
480+ return 0
481+ }
482+ size := 0
483+ size += 4
484+ size += 2
485+ size += 2
486+ size += len(name) * 1
487+ size = (size + 3) &^ 3
488+ if b.Ext == nil {
489+ b.Fail(xturbo.ErrExtMissing)
490+ return 0
491+ }
492+ major := b.Ext.Major(xturbo.ExtXFixes)
493+ if major == 0 {
494+ b.Fail(xturbo.ErrExtMissing)
495+ return 0
496+ }
497+ p, seq := b.Request(major, 23, size)
498+ if p == nil {
499+ return 0
500+ }
501+ off := 0
502+ binary.LittleEndian.PutUint32(p[off:], uint32(cursor))
503+ off += 4
504+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
505+ off += 2
506+ off += 2
507+ copy(p[off:], name)
508+ off += len(name)
509+ return seq
510+}
511+
512+func GetCursorName(b *xturbo.Buf, cursor xproto.Cursor) xturbo.Seq {
513+ if b.Ext == nil {
514+ b.Fail(xturbo.ErrExtMissing)
515+ return 0
516+ }
517+ major := b.Ext.Major(xturbo.ExtXFixes)
518+ if major == 0 {
519+ b.Fail(xturbo.ErrExtMissing)
520+ return 0
521+ }
522+ p, seq := b.Request(major, 24, 4)
523+ if p == nil {
524+ return 0
525+ }
526+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
527+ return seq
528+}
529+
530+func GetCursorImageAndName(b *xturbo.Buf) xturbo.Seq {
531+ if b.Ext == nil {
532+ b.Fail(xturbo.ErrExtMissing)
533+ return 0
534+ }
535+ major := b.Ext.Major(xturbo.ExtXFixes)
536+ if major == 0 {
537+ b.Fail(xturbo.ErrExtMissing)
538+ return 0
539+ }
540+ p, seq := b.Request(major, 25, 0)
541+ if p == nil {
542+ return 0
543+ }
544+ return seq
545+}
546+
547+func ChangeCursor(b *xturbo.Buf, source xproto.Cursor, destination xproto.Cursor) xturbo.Seq {
548+ if b.Ext == nil {
549+ b.Fail(xturbo.ErrExtMissing)
550+ return 0
551+ }
552+ major := b.Ext.Major(xturbo.ExtXFixes)
553+ if major == 0 {
554+ b.Fail(xturbo.ErrExtMissing)
555+ return 0
556+ }
557+ p, seq := b.Request(major, 26, 8)
558+ if p == nil {
559+ return 0
560+ }
561+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
562+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
563+ return seq
564+}
565+
566+func ChangeCursorByName(b *xturbo.Buf, src xproto.Cursor, name string) xturbo.Seq {
567+ if uint64(len(name)) > 65535 {
568+ b.Fail(xturbo.ErrBadLength)
569+ return 0
570+ }
571+ size := 0
572+ size += 4
573+ size += 2
574+ size += 2
575+ size += len(name) * 1
576+ size = (size + 3) &^ 3
577+ if b.Ext == nil {
578+ b.Fail(xturbo.ErrExtMissing)
579+ return 0
580+ }
581+ major := b.Ext.Major(xturbo.ExtXFixes)
582+ if major == 0 {
583+ b.Fail(xturbo.ErrExtMissing)
584+ return 0
585+ }
586+ p, seq := b.Request(major, 27, size)
587+ if p == nil {
588+ return 0
589+ }
590+ off := 0
591+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
592+ off += 4
593+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
594+ off += 2
595+ off += 2
596+ copy(p[off:], name)
597+ off += len(name)
598+ return seq
599+}
600+
601+func ExpandRegion(b *xturbo.Buf, source Region, destination Region, left uint16, right uint16, top uint16, bottom uint16) xturbo.Seq {
602+ if b.Ext == nil {
603+ b.Fail(xturbo.ErrExtMissing)
604+ return 0
605+ }
606+ major := b.Ext.Major(xturbo.ExtXFixes)
607+ if major == 0 {
608+ b.Fail(xturbo.ErrExtMissing)
609+ return 0
610+ }
611+ p, seq := b.Request(major, 28, 16)
612+ if p == nil {
613+ return 0
614+ }
615+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
616+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
617+ binary.LittleEndian.PutUint16(p[8:], uint16(left))
618+ binary.LittleEndian.PutUint16(p[10:], uint16(right))
619+ binary.LittleEndian.PutUint16(p[12:], uint16(top))
620+ binary.LittleEndian.PutUint16(p[14:], uint16(bottom))
621+ return seq
622+}
623+
624+func HideCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
625+ if b.Ext == nil {
626+ b.Fail(xturbo.ErrExtMissing)
627+ return 0
628+ }
629+ major := b.Ext.Major(xturbo.ExtXFixes)
630+ if major == 0 {
631+ b.Fail(xturbo.ErrExtMissing)
632+ return 0
633+ }
634+ p, seq := b.Request(major, 29, 4)
635+ if p == nil {
636+ return 0
637+ }
638+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
639+ return seq
640+}
641+
642+func ShowCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
643+ if b.Ext == nil {
644+ b.Fail(xturbo.ErrExtMissing)
645+ return 0
646+ }
647+ major := b.Ext.Major(xturbo.ExtXFixes)
648+ if major == 0 {
649+ b.Fail(xturbo.ErrExtMissing)
650+ return 0
651+ }
652+ p, seq := b.Request(major, 30, 4)
653+ if p == nil {
654+ return 0
655+ }
656+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
657+ return seq
658+}
659+
660+func CreatePointerBarrier(b *xturbo.Buf, barrier Barrier, window xproto.Window, x1 uint16, y1 uint16, x2 uint16, y2 uint16, directions BarrierDirections, devices []uint16) xturbo.Seq {
661+ if uint64(len(devices)) > 65535 {
662+ b.Fail(xturbo.ErrBadLength)
663+ return 0
664+ }
665+ size := 0
666+ size += 4
667+ size += 4
668+ size += 2
669+ size += 2
670+ size += 2
671+ size += 2
672+ size += 4
673+ size += 2
674+ size += 2
675+ size += len(devices) * 2
676+ size = (size + 3) &^ 3
677+ if b.Ext == nil {
678+ b.Fail(xturbo.ErrExtMissing)
679+ return 0
680+ }
681+ major := b.Ext.Major(xturbo.ExtXFixes)
682+ if major == 0 {
683+ b.Fail(xturbo.ErrExtMissing)
684+ return 0
685+ }
686+ p, seq := b.Request(major, 31, size)
687+ if p == nil {
688+ return 0
689+ }
690+ off := 0
691+ binary.LittleEndian.PutUint32(p[off:], uint32(barrier))
692+ off += 4
693+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
694+ off += 4
695+ binary.LittleEndian.PutUint16(p[off:], uint16(x1))
696+ off += 2
697+ binary.LittleEndian.PutUint16(p[off:], uint16(y1))
698+ off += 2
699+ binary.LittleEndian.PutUint16(p[off:], uint16(x2))
700+ off += 2
701+ binary.LittleEndian.PutUint16(p[off:], uint16(y2))
702+ off += 2
703+ binary.LittleEndian.PutUint32(p[off:], uint32(directions))
704+ off += 4
705+ off += 2
706+ binary.LittleEndian.PutUint16(p[off:], uint16(len(devices)))
707+ off += 2
708+ for i := range devices {
709+ binary.LittleEndian.PutUint16(p[off:], uint16(devices[i]))
710+ off += 2
711+ }
712+ return seq
713+}
714+
715+func DeletePointerBarrier(b *xturbo.Buf, barrier Barrier) xturbo.Seq {
716+ if b.Ext == nil {
717+ b.Fail(xturbo.ErrExtMissing)
718+ return 0
719+ }
720+ major := b.Ext.Major(xturbo.ExtXFixes)
721+ if major == 0 {
722+ b.Fail(xturbo.ErrExtMissing)
723+ return 0
724+ }
725+ p, seq := b.Request(major, 32, 4)
726+ if p == nil {
727+ return 0
728+ }
729+ binary.LittleEndian.PutUint32(p[0:], uint32(barrier))
730+ return seq
731+}
732+
733+func SetClientDisconnectMode(b *xturbo.Buf, disconnectMode ClientDisconnectFlags) xturbo.Seq {
734+ if b.Ext == nil {
735+ b.Fail(xturbo.ErrExtMissing)
736+ return 0
737+ }
738+ major := b.Ext.Major(xturbo.ExtXFixes)
739+ if major == 0 {
740+ b.Fail(xturbo.ErrExtMissing)
741+ return 0
742+ }
743+ p, seq := b.Request(major, 33, 4)
744+ if p == nil {
745+ return 0
746+ }
747+ binary.LittleEndian.PutUint32(p[0:], uint32(disconnectMode))
748+ return seq
749+}
750+
751+func GetClientDisconnectMode(b *xturbo.Buf) xturbo.Seq {
752+ if b.Ext == nil {
753+ b.Fail(xturbo.ErrExtMissing)
754+ return 0
755+ }
756+ major := b.Ext.Major(xturbo.ExtXFixes)
757+ if major == 0 {
758+ b.Fail(xturbo.ErrExtMissing)
759+ return 0
760+ }
761+ p, seq := b.Request(major, 34, 0)
762+ if p == nil {
763+ return 0
764+ }
765+ return seq
766+}
A xfixes/sizes_test.go +32 -0
@@ -0,0 +1,32 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xfixes
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if got := 32; got != 32 {
8+ t.Errorf("reply QueryVersion fixed size = %d", got)
9+ }
10+ if got := 32; got != 32 {
11+ t.Errorf("event SelectionNotify fixed size = %d", got)
12+ }
13+ if got := 32; got != 32 {
14+ t.Errorf("event CursorNotify fixed size = %d", got)
15+ }
16+ if got := 32; got != 32 {
17+ t.Errorf("reply GetCursorImage fixed size = %d", got)
18+ }
19+ if got := 32; got != 32 {
20+ t.Errorf("reply FetchRegion fixed size = %d", got)
21+ }
22+ if got := 32; got != 32 {
23+ t.Errorf("reply GetCursorName fixed size = %d", got)
24+ }
25+ if got := 32; got != 32 {
26+ t.Errorf("reply GetCursorImageAndName fixed size = %d", got)
27+ }
28+ if got := 32; got != 32 {
29+ t.Errorf("reply GetClientDisconnectMode fixed size = %d", got)
30+ }
31+
32+}
A xfixes/types_generated.go +55 -0
@@ -0,0 +1,55 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xfixes
3+
4+type Region uint32
5+
6+type Barrier uint32
7+
8+type SaveSetMode uint8
9+
10+const SaveSetModeInsert SaveSetMode = 0
11+const SaveSetModeDelete SaveSetMode = 1
12+
13+type SaveSetTarget uint8
14+
15+const SaveSetTargetNearest SaveSetTarget = 0
16+const SaveSetTargetRoot SaveSetTarget = 1
17+
18+type SaveSetMapping uint8
19+
20+const SaveSetMappingMap SaveSetMapping = 0
21+const SaveSetMappingUnmap SaveSetMapping = 1
22+
23+type SelectionEvent uint8
24+
25+const SelectionEventSetSelectionOwner SelectionEvent = 0
26+const SelectionEventSelectionWindowDestroy SelectionEvent = 1
27+const SelectionEventSelectionClientClose SelectionEvent = 2
28+
29+type SelectionEventMask uint32
30+
31+const SelectionEventMaskSetSelectionOwner SelectionEventMask = 1
32+const SelectionEventMaskSelectionWindowDestroy SelectionEventMask = 2
33+const SelectionEventMaskSelectionClientClose SelectionEventMask = 4
34+
35+type CursorNotify uint8
36+
37+const CursorNotifyDisplayCursor CursorNotify = 0
38+
39+type CursorNotifyMask uint32
40+
41+const CursorNotifyMaskDisplayCursor CursorNotifyMask = 1
42+
43+const RegionNone Region = 0
44+
45+type BarrierDirections uint32
46+
47+const BarrierDirectionsPositiveX BarrierDirections = 1
48+const BarrierDirectionsPositiveY BarrierDirections = 2
49+const BarrierDirectionsNegativeX BarrierDirections = 4
50+const BarrierDirectionsNegativeY BarrierDirections = 8
51+
52+type ClientDisconnectFlags uint32
53+
54+const ClientDisconnectFlagsDefault ClientDisconnectFlags = 0
55+const ClientDisconnectFlagsTerminate ClientDisconnectFlags = 1
A xproto/requests_generated.go +1757 -0
@@ -0,0 +1,1757 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xproto
3+
4+import "encoding/binary"
5+import "bnema.dev/xturbo"
6+
7+func GetWindowAttributes(b *xturbo.Buf, window Window) xturbo.Seq {
8+ p, seq := b.Request(3, 0, 4)
9+ if p == nil {
10+ return 0
11+ }
12+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
13+ return seq
14+}
15+
16+func DestroyWindow(b *xturbo.Buf, window Window) xturbo.Seq {
17+ p, seq := b.Request(4, 0, 4)
18+ if p == nil {
19+ return 0
20+ }
21+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
22+ return seq
23+}
24+
25+func DestroySubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
26+ p, seq := b.Request(5, 0, 4)
27+ if p == nil {
28+ return 0
29+ }
30+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
31+ return seq
32+}
33+
34+func ChangeSaveSet(b *xturbo.Buf, mode SetMode, window Window) xturbo.Seq {
35+ p, seq := b.Request(6, uint8(int(mode)), 4)
36+ if p == nil {
37+ return 0
38+ }
39+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
40+ return seq
41+}
42+
43+func ReparentWindow(b *xturbo.Buf, window Window, parent Window, x int16, y int16) xturbo.Seq {
44+ p, seq := b.Request(7, 0, 12)
45+ if p == nil {
46+ return 0
47+ }
48+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
49+ binary.LittleEndian.PutUint32(p[4:], uint32(parent))
50+ binary.LittleEndian.PutUint16(p[8:], uint16(x))
51+ binary.LittleEndian.PutUint16(p[10:], uint16(y))
52+ return seq
53+}
54+
55+func MapWindow(b *xturbo.Buf, window Window) xturbo.Seq {
56+ p, seq := b.Request(8, 0, 4)
57+ if p == nil {
58+ return 0
59+ }
60+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
61+ return seq
62+}
63+
64+func MapSubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
65+ p, seq := b.Request(9, 0, 4)
66+ if p == nil {
67+ return 0
68+ }
69+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
70+ return seq
71+}
72+
73+func UnmapWindow(b *xturbo.Buf, window Window) xturbo.Seq {
74+ p, seq := b.Request(10, 0, 4)
75+ if p == nil {
76+ return 0
77+ }
78+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
79+ return seq
80+}
81+
82+func UnmapSubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
83+ p, seq := b.Request(11, 0, 4)
84+ if p == nil {
85+ return 0
86+ }
87+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
88+ return seq
89+}
90+
91+func CirculateWindow(b *xturbo.Buf, direction Circulate, window Window) xturbo.Seq {
92+ p, seq := b.Request(13, uint8(int(direction)), 4)
93+ if p == nil {
94+ return 0
95+ }
96+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
97+ return seq
98+}
99+
100+func GetGeometry(b *xturbo.Buf, drawable Drawable) xturbo.Seq {
101+ p, seq := b.Request(14, 0, 4)
102+ if p == nil {
103+ return 0
104+ }
105+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
106+ return seq
107+}
108+
109+func QueryTree(b *xturbo.Buf, window Window) xturbo.Seq {
110+ p, seq := b.Request(15, 0, 4)
111+ if p == nil {
112+ return 0
113+ }
114+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
115+ return seq
116+}
117+
118+func InternAtom(b *xturbo.Buf, onlyIfExists bool, name string) xturbo.Seq {
119+ if uint64(len(name)) > 65535 {
120+ b.Fail(xturbo.ErrBadLength)
121+ return 0
122+ }
123+ size := 0
124+ size += 2
125+ size += 2
126+ size += len(name) * 1
127+ size = (size + 3) &^ 3
128+ var data uint8
129+ if onlyIfExists {
130+ data = 1
131+ }
132+ p, seq := b.Request(16, data, size)
133+ if p == nil {
134+ return 0
135+ }
136+ off := 0
137+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
138+ off += 2
139+ off += 2
140+ copy(p[off:], name)
141+ off += len(name)
142+ return seq
143+}
144+
145+func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
146+ p, seq := b.Request(17, 0, 4)
147+ if p == nil {
148+ return 0
149+ }
150+ binary.LittleEndian.PutUint32(p[0:], uint32(atom))
151+ return seq
152+}
153+
154+func ChangeProperty(b *xturbo.Buf, mode PropMode, window Window, property Atom, type_ Atom, format uint8, dataLen uint32, data []byte) xturbo.Seq {
155+ if len(data) != ((int(dataLen) * int(format)) / 8) {
156+ b.Fail(xturbo.ErrBadLength)
157+ return 0
158+ }
159+ size := 0
160+ size += 4
161+ size += 4
162+ size += 4
163+ size += 1
164+ size += 3
165+ size += 4
166+ size += len(data) * 1
167+ size = (size + 3) &^ 3
168+ p, seq := b.Request(18, uint8(int(mode)), size)
169+ if p == nil {
170+ return 0
171+ }
172+ off := 0
173+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(property))
176+ off += 4
177+ binary.LittleEndian.PutUint32(p[off:], uint32(type_))
178+ off += 4
179+ p[off:][0] = byte(format)
180+ off += 1
181+ off += 3
182+ binary.LittleEndian.PutUint32(p[off:], uint32(dataLen))
183+ off += 4
184+ copy(p[off:], data)
185+ off += len(data)
186+ return seq
187+}
188+
189+func DeleteProperty(b *xturbo.Buf, window Window, property Atom) xturbo.Seq {
190+ p, seq := b.Request(19, 0, 8)
191+ if p == nil {
192+ return 0
193+ }
194+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
195+ binary.LittleEndian.PutUint32(p[4:], uint32(property))
196+ return seq
197+}
198+
199+func GetProperty(b *xturbo.Buf, delete bool, window Window, property Atom, type_ Atom, longOffset uint32, longLength uint32) xturbo.Seq {
200+ var data uint8
201+ if delete {
202+ data = 1
203+ }
204+ p, seq := b.Request(20, data, 20)
205+ if p == nil {
206+ return 0
207+ }
208+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
209+ binary.LittleEndian.PutUint32(p[4:], uint32(property))
210+ binary.LittleEndian.PutUint32(p[8:], uint32(type_))
211+ binary.LittleEndian.PutUint32(p[12:], uint32(longOffset))
212+ binary.LittleEndian.PutUint32(p[16:], uint32(longLength))
213+ return seq
214+}
215+
216+func ListProperties(b *xturbo.Buf, window Window) xturbo.Seq {
217+ p, seq := b.Request(21, 0, 4)
218+ if p == nil {
219+ return 0
220+ }
221+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
222+ return seq
223+}
224+
225+func SetSelectionOwner(b *xturbo.Buf, owner Window, selection Atom, time Timestamp) xturbo.Seq {
226+ p, seq := b.Request(22, 0, 12)
227+ if p == nil {
228+ return 0
229+ }
230+ binary.LittleEndian.PutUint32(p[0:], uint32(owner))
231+ binary.LittleEndian.PutUint32(p[4:], uint32(selection))
232+ binary.LittleEndian.PutUint32(p[8:], uint32(time))
233+ return seq
234+}
235+
236+func GetSelectionOwner(b *xturbo.Buf, selection Atom) xturbo.Seq {
237+ p, seq := b.Request(23, 0, 4)
238+ if p == nil {
239+ return 0
240+ }
241+ binary.LittleEndian.PutUint32(p[0:], uint32(selection))
242+ return seq
243+}
244+
245+func ConvertSelection(b *xturbo.Buf, requestor Window, selection Atom, target Atom, property Atom, time Timestamp) xturbo.Seq {
246+ p, seq := b.Request(24, 0, 20)
247+ if p == nil {
248+ return 0
249+ }
250+ binary.LittleEndian.PutUint32(p[0:], uint32(requestor))
251+ binary.LittleEndian.PutUint32(p[4:], uint32(selection))
252+ binary.LittleEndian.PutUint32(p[8:], uint32(target))
253+ binary.LittleEndian.PutUint32(p[12:], uint32(property))
254+ binary.LittleEndian.PutUint32(p[16:], uint32(time))
255+ return seq
256+}
257+
258+func SendEvent(b *xturbo.Buf, propagate bool, destination Window, eventMask EventMask, event *[32]byte) xturbo.Seq {
259+ if len(event) != 32 {
260+ b.Fail(xturbo.ErrBadLength)
261+ return 0
262+ }
263+ size := 0
264+ size += 4
265+ size += 4
266+ size += len(event) * 1
267+ size = (size + 3) &^ 3
268+ var data uint8
269+ if propagate {
270+ data = 1
271+ }
272+ p, seq := b.Request(25, data, size)
273+ if p == nil {
274+ return 0
275+ }
276+ off := 0
277+ binary.LittleEndian.PutUint32(p[off:], uint32(destination))
278+ off += 4
279+ binary.LittleEndian.PutUint32(p[off:], uint32(eventMask))
280+ off += 4
281+ copy(p[off:], event[:])
282+ return seq
283+}
284+
285+func GrabPointer(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask EventMask, pointerMode GrabMode, keyboardMode GrabMode, confineTo Window, cursor Cursor, time Timestamp) xturbo.Seq {
286+ var data uint8
287+ if ownerEvents {
288+ data = 1
289+ }
290+ p, seq := b.Request(26, data, 20)
291+ if p == nil {
292+ return 0
293+ }
294+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
295+ binary.LittleEndian.PutUint16(p[4:], uint16(eventMask))
296+ p[6:][0] = byte(pointerMode)
297+ p[7:][0] = byte(keyboardMode)
298+ binary.LittleEndian.PutUint32(p[8:], uint32(confineTo))
299+ binary.LittleEndian.PutUint32(p[12:], uint32(cursor))
300+ binary.LittleEndian.PutUint32(p[16:], uint32(time))
301+ return seq
302+}
303+
304+func UngrabPointer(b *xturbo.Buf, time Timestamp) xturbo.Seq {
305+ p, seq := b.Request(27, 0, 4)
306+ if p == nil {
307+ return 0
308+ }
309+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
310+ return seq
311+}
312+
313+func GrabButton(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask EventMask, pointerMode GrabMode, keyboardMode GrabMode, confineTo Window, cursor Cursor, button ButtonIndex, modifiers ModMask) xturbo.Seq {
314+ var data uint8
315+ if ownerEvents {
316+ data = 1
317+ }
318+ p, seq := b.Request(28, data, 20)
319+ if p == nil {
320+ return 0
321+ }
322+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
323+ binary.LittleEndian.PutUint16(p[4:], uint16(eventMask))
324+ p[6:][0] = byte(pointerMode)
325+ p[7:][0] = byte(keyboardMode)
326+ binary.LittleEndian.PutUint32(p[8:], uint32(confineTo))
327+ binary.LittleEndian.PutUint32(p[12:], uint32(cursor))
328+ p[16:][0] = byte(button)
329+ binary.LittleEndian.PutUint16(p[18:], uint16(modifiers))
330+ return seq
331+}
332+
333+func UngrabButton(b *xturbo.Buf, button ButtonIndex, grabWindow Window, modifiers ModMask) xturbo.Seq {
334+ p, seq := b.Request(29, uint8(int(button)), 8)
335+ if p == nil {
336+ return 0
337+ }
338+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
339+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
340+ return seq
341+}
342+
343+func ChangeActivePointerGrab(b *xturbo.Buf, cursor Cursor, time Timestamp, eventMask EventMask) xturbo.Seq {
344+ p, seq := b.Request(30, 0, 12)
345+ if p == nil {
346+ return 0
347+ }
348+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
349+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
350+ binary.LittleEndian.PutUint16(p[8:], uint16(eventMask))
351+ return seq
352+}
353+
354+func GrabKeyboard(b *xturbo.Buf, ownerEvents bool, grabWindow Window, time Timestamp, pointerMode GrabMode, keyboardMode GrabMode) xturbo.Seq {
355+ var data uint8
356+ if ownerEvents {
357+ data = 1
358+ }
359+ p, seq := b.Request(31, data, 12)
360+ if p == nil {
361+ return 0
362+ }
363+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
364+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
365+ p[8:][0] = byte(pointerMode)
366+ p[9:][0] = byte(keyboardMode)
367+ return seq
368+}
369+
370+func UngrabKeyboard(b *xturbo.Buf, time Timestamp) xturbo.Seq {
371+ p, seq := b.Request(32, 0, 4)
372+ if p == nil {
373+ return 0
374+ }
375+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
376+ return seq
377+}
378+
379+func GrabKey(b *xturbo.Buf, ownerEvents bool, grabWindow Window, modifiers ModMask, key Keycode, pointerMode GrabMode, keyboardMode GrabMode) xturbo.Seq {
380+ var data uint8
381+ if ownerEvents {
382+ data = 1
383+ }
384+ p, seq := b.Request(33, data, 12)
385+ if p == nil {
386+ return 0
387+ }
388+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
389+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
390+ p[6:][0] = byte(key)
391+ p[7:][0] = byte(pointerMode)
392+ p[8:][0] = byte(keyboardMode)
393+ return seq
394+}
395+
396+func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask) xturbo.Seq {
397+ p, seq := b.Request(34, uint8(int(key)), 8)
398+ if p == nil {
399+ return 0
400+ }
401+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
402+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
403+ return seq
404+}
405+
406+func AllowEvents(b *xturbo.Buf, mode Allow, time Timestamp) xturbo.Seq {
407+ p, seq := b.Request(35, uint8(int(mode)), 4)
408+ if p == nil {
409+ return 0
410+ }
411+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
412+ return seq
413+}
414+
415+func GrabServer(b *xturbo.Buf) xturbo.Seq {
416+ p, seq := b.Request(36, 0, 0)
417+ if p == nil {
418+ return 0
419+ }
420+ return seq
421+}
422+
423+func UngrabServer(b *xturbo.Buf) xturbo.Seq {
424+ p, seq := b.Request(37, 0, 0)
425+ if p == nil {
426+ return 0
427+ }
428+ return seq
429+}
430+
431+func QueryPointer(b *xturbo.Buf, window Window) xturbo.Seq {
432+ p, seq := b.Request(38, 0, 4)
433+ if p == nil {
434+ return 0
435+ }
436+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
437+ return seq
438+}
439+
440+func GetMotionEvents(b *xturbo.Buf, window Window, start Timestamp, stop Timestamp) xturbo.Seq {
441+ p, seq := b.Request(39, 0, 12)
442+ if p == nil {
443+ return 0
444+ }
445+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
446+ binary.LittleEndian.PutUint32(p[4:], uint32(start))
447+ binary.LittleEndian.PutUint32(p[8:], uint32(stop))
448+ return seq
449+}
450+
451+func TranslateCoordinates(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16, srcY int16) xturbo.Seq {
452+ p, seq := b.Request(40, 0, 12)
453+ if p == nil {
454+ return 0
455+ }
456+ binary.LittleEndian.PutUint32(p[0:], uint32(srcWindow))
457+ binary.LittleEndian.PutUint32(p[4:], uint32(dstWindow))
458+ binary.LittleEndian.PutUint16(p[8:], uint16(srcX))
459+ binary.LittleEndian.PutUint16(p[10:], uint16(srcY))
460+ return seq
461+}
462+
463+func WarpPointer(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16, srcY int16, srcWidth uint16, srcHeight uint16, dstX int16, dstY int16) xturbo.Seq {
464+ p, seq := b.Request(41, 0, 20)
465+ if p == nil {
466+ return 0
467+ }
468+ binary.LittleEndian.PutUint32(p[0:], uint32(srcWindow))
469+ binary.LittleEndian.PutUint32(p[4:], uint32(dstWindow))
470+ binary.LittleEndian.PutUint16(p[8:], uint16(srcX))
471+ binary.LittleEndian.PutUint16(p[10:], uint16(srcY))
472+ binary.LittleEndian.PutUint16(p[12:], uint16(srcWidth))
473+ binary.LittleEndian.PutUint16(p[14:], uint16(srcHeight))
474+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
475+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
476+ return seq
477+}
478+
479+func SetInputFocus(b *xturbo.Buf, revertTo InputFocus, focus Window, time Timestamp) xturbo.Seq {
480+ p, seq := b.Request(42, uint8(int(revertTo)), 8)
481+ if p == nil {
482+ return 0
483+ }
484+ binary.LittleEndian.PutUint32(p[0:], uint32(focus))
485+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
486+ return seq
487+}
488+
489+func GetInputFocus(b *xturbo.Buf) xturbo.Seq {
490+ p, seq := b.Request(43, 0, 0)
491+ if p == nil {
492+ return 0
493+ }
494+ return seq
495+}
496+
497+func QueryKeymap(b *xturbo.Buf) xturbo.Seq {
498+ p, seq := b.Request(44, 0, 0)
499+ if p == nil {
500+ return 0
501+ }
502+ return seq
503+}
504+
505+func OpenFont(b *xturbo.Buf, fid Font, name string) xturbo.Seq {
506+ if uint64(len(name)) > 65535 {
507+ b.Fail(xturbo.ErrBadLength)
508+ return 0
509+ }
510+ size := 0
511+ size += 4
512+ size += 2
513+ size += 2
514+ size += len(name) * 1
515+ size = (size + 3) &^ 3
516+ p, seq := b.Request(45, 0, size)
517+ if p == nil {
518+ return 0
519+ }
520+ off := 0
521+ binary.LittleEndian.PutUint32(p[off:], uint32(fid))
522+ off += 4
523+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
524+ off += 2
525+ off += 2
526+ copy(p[off:], name)
527+ off += len(name)
528+ return seq
529+}
530+
531+func CloseFont(b *xturbo.Buf, font Font) xturbo.Seq {
532+ p, seq := b.Request(46, 0, 4)
533+ if p == nil {
534+ return 0
535+ }
536+ binary.LittleEndian.PutUint32(p[0:], uint32(font))
537+ return seq
538+}
539+
540+func QueryFont(b *xturbo.Buf, font Fontable) xturbo.Seq {
541+ p, seq := b.Request(47, 0, 4)
542+ if p == nil {
543+ return 0
544+ }
545+ binary.LittleEndian.PutUint32(p[0:], uint32(font))
546+ return seq
547+}
548+
549+func QueryTextExtents(b *xturbo.Buf, font Fontable, string []Char2b) xturbo.Seq {
550+ size := 0
551+ size += 4
552+ size += len(string) * 2
553+ size = (size + 3) &^ 3
554+ var data uint8
555+ if (len(string) & 1) != 0 {
556+ data = 1
557+ }
558+ p, seq := b.Request(48, data, size)
559+ if p == nil {
560+ return 0
561+ }
562+ off := 0
563+ binary.LittleEndian.PutUint32(p[off:], uint32(font))
564+ off += 4
565+ for i := range string {
566+ string[i].Put(p[off:])
567+ off += 2
568+ }
569+ return seq
570+}
571+
572+func ListFonts(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
573+ if uint64(len(pattern)) > 65535 {
574+ b.Fail(xturbo.ErrBadLength)
575+ return 0
576+ }
577+ size := 0
578+ size += 2
579+ size += 2
580+ size += len(pattern) * 1
581+ size = (size + 3) &^ 3
582+ p, seq := b.Request(49, 0, size)
583+ if p == nil {
584+ return 0
585+ }
586+ off := 0
587+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
588+ off += 2
589+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
590+ off += 2
591+ copy(p[off:], pattern)
592+ off += len(pattern)
593+ return seq
594+}
595+
596+func ListFontsWithInfo(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
597+ if uint64(len(pattern)) > 65535 {
598+ b.Fail(xturbo.ErrBadLength)
599+ return 0
600+ }
601+ size := 0
602+ size += 2
603+ size += 2
604+ size += len(pattern) * 1
605+ size = (size + 3) &^ 3
606+ p, seq := b.Request(50, 0, size)
607+ if p == nil {
608+ return 0
609+ }
610+ off := 0
611+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
612+ off += 2
613+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
614+ off += 2
615+ copy(p[off:], pattern)
616+ off += len(pattern)
617+ return seq
618+}
619+
620+func SetFontPath(b *xturbo.Buf, font []Str) xturbo.Seq {
621+ if uint64(len(font)) > 65535 {
622+ b.Fail(xturbo.ErrBadLength)
623+ return 0
624+ }
625+ size := 0
626+ size += 2
627+ size += 2
628+ for i := range font {
629+ size += font[i].Size()
630+ }
631+ size = (size + 3) &^ 3
632+ p, seq := b.Request(51, 0, size)
633+ if p == nil {
634+ return 0
635+ }
636+ off := 0
637+ binary.LittleEndian.PutUint16(p[off:], uint16(len(font)))
638+ off += 2
639+ off += 2
640+ for i := range font {
641+ font[i].Put(p[off:])
642+ off += font[i].Size()
643+ }
644+ return seq
645+}
646+
647+func GetFontPath(b *xturbo.Buf) xturbo.Seq {
648+ p, seq := b.Request(52, 0, 0)
649+ if p == nil {
650+ return 0
651+ }
652+ return seq
653+}
654+
655+func CreatePixmap(b *xturbo.Buf, depth uint8, pid Pixmap, drawable Drawable, width uint16, height uint16) xturbo.Seq {
656+ p, seq := b.Request(53, uint8(int(depth)), 12)
657+ if p == nil {
658+ return 0
659+ }
660+ binary.LittleEndian.PutUint32(p[0:], uint32(pid))
661+ binary.LittleEndian.PutUint32(p[4:], uint32(drawable))
662+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
663+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
664+ return seq
665+}
666+
667+func FreePixmap(b *xturbo.Buf, pixmap Pixmap) xturbo.Seq {
668+ p, seq := b.Request(54, 0, 4)
669+ if p == nil {
670+ return 0
671+ }
672+ binary.LittleEndian.PutUint32(p[0:], uint32(pixmap))
673+ return seq
674+}
675+
676+func CopyGC(b *xturbo.Buf, srcGc Gcontext, dstGc Gcontext, valueMask Gc) xturbo.Seq {
677+ p, seq := b.Request(57, 0, 12)
678+ if p == nil {
679+ return 0
680+ }
681+ binary.LittleEndian.PutUint32(p[0:], uint32(srcGc))
682+ binary.LittleEndian.PutUint32(p[4:], uint32(dstGc))
683+ binary.LittleEndian.PutUint32(p[8:], uint32(valueMask))
684+ return seq
685+}
686+
687+func SetDashes(b *xturbo.Buf, gc Gcontext, dashOffset uint16, dashes []byte) xturbo.Seq {
688+ if uint64(len(dashes)) > 65535 {
689+ b.Fail(xturbo.ErrBadLength)
690+ return 0
691+ }
692+ size := 0
693+ size += 4
694+ size += 2
695+ size += 2
696+ size += len(dashes) * 1
697+ size = (size + 3) &^ 3
698+ p, seq := b.Request(58, 0, size)
699+ if p == nil {
700+ return 0
701+ }
702+ off := 0
703+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
704+ off += 4
705+ binary.LittleEndian.PutUint16(p[off:], uint16(dashOffset))
706+ off += 2
707+ binary.LittleEndian.PutUint16(p[off:], uint16(len(dashes)))
708+ off += 2
709+ copy(p[off:], dashes)
710+ off += len(dashes)
711+ return seq
712+}
713+
714+func SetClipRectangles(b *xturbo.Buf, ordering ClipOrdering, gc Gcontext, clipXOrigin int16, clipYOrigin int16, rectangles []Rectangle) xturbo.Seq {
715+ size := 0
716+ size += 4
717+ size += 2
718+ size += 2
719+ size += len(rectangles) * 8
720+ size = (size + 3) &^ 3
721+ p, seq := b.Request(59, uint8(int(ordering)), size)
722+ if p == nil {
723+ return 0
724+ }
725+ off := 0
726+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
727+ off += 4
728+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
729+ off += 2
730+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
731+ off += 2
732+ for i := range rectangles {
733+ rectangles[i].Put(p[off:])
734+ off += 8
735+ }
736+ return seq
737+}
738+
739+func FreeGC(b *xturbo.Buf, gc Gcontext) xturbo.Seq {
740+ p, seq := b.Request(60, 0, 4)
741+ if p == nil {
742+ return 0
743+ }
744+ binary.LittleEndian.PutUint32(p[0:], uint32(gc))
745+ return seq
746+}
747+
748+func ClearArea(b *xturbo.Buf, exposures bool, window Window, x int16, y int16, width uint16, height uint16) xturbo.Seq {
749+ var data uint8
750+ if exposures {
751+ data = 1
752+ }
753+ p, seq := b.Request(61, data, 12)
754+ if p == nil {
755+ return 0
756+ }
757+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
758+ binary.LittleEndian.PutUint16(p[4:], uint16(x))
759+ binary.LittleEndian.PutUint16(p[6:], uint16(y))
760+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
761+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
762+ return seq
763+}
764+
765+func CopyArea(b *xturbo.Buf, srcDrawable Drawable, dstDrawable Drawable, gc Gcontext, srcX int16, srcY int16, dstX int16, dstY int16, width uint16, height uint16) xturbo.Seq {
766+ p, seq := b.Request(62, 0, 24)
767+ if p == nil {
768+ return 0
769+ }
770+ binary.LittleEndian.PutUint32(p[0:], uint32(srcDrawable))
771+ binary.LittleEndian.PutUint32(p[4:], uint32(dstDrawable))
772+ binary.LittleEndian.PutUint32(p[8:], uint32(gc))
773+ binary.LittleEndian.PutUint16(p[12:], uint16(srcX))
774+ binary.LittleEndian.PutUint16(p[14:], uint16(srcY))
775+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
776+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
777+ binary.LittleEndian.PutUint16(p[20:], uint16(width))
778+ binary.LittleEndian.PutUint16(p[22:], uint16(height))
779+ return seq
780+}
781+
782+func CopyPlane(b *xturbo.Buf, srcDrawable Drawable, dstDrawable Drawable, gc Gcontext, srcX int16, srcY int16, dstX int16, dstY int16, width uint16, height uint16, bitPlane uint32) xturbo.Seq {
783+ p, seq := b.Request(63, 0, 28)
784+ if p == nil {
785+ return 0
786+ }
787+ binary.LittleEndian.PutUint32(p[0:], uint32(srcDrawable))
788+ binary.LittleEndian.PutUint32(p[4:], uint32(dstDrawable))
789+ binary.LittleEndian.PutUint32(p[8:], uint32(gc))
790+ binary.LittleEndian.PutUint16(p[12:], uint16(srcX))
791+ binary.LittleEndian.PutUint16(p[14:], uint16(srcY))
792+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
793+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
794+ binary.LittleEndian.PutUint16(p[20:], uint16(width))
795+ binary.LittleEndian.PutUint16(p[22:], uint16(height))
796+ binary.LittleEndian.PutUint32(p[24:], uint32(bitPlane))
797+ return seq
798+}
799+
800+func PolyPoint(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
801+ size := 0
802+ size += 4
803+ size += 4
804+ size += len(points) * 4
805+ size = (size + 3) &^ 3
806+ p, seq := b.Request(64, uint8(int(coordinateMode)), size)
807+ if p == nil {
808+ return 0
809+ }
810+ off := 0
811+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
812+ off += 4
813+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
814+ off += 4
815+ for i := range points {
816+ points[i].Put(p[off:])
817+ off += 4
818+ }
819+ return seq
820+}
821+
822+func PolyLine(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
823+ size := 0
824+ size += 4
825+ size += 4
826+ size += len(points) * 4
827+ size = (size + 3) &^ 3
828+ p, seq := b.Request(65, uint8(int(coordinateMode)), size)
829+ if p == nil {
830+ return 0
831+ }
832+ off := 0
833+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
834+ off += 4
835+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
836+ off += 4
837+ for i := range points {
838+ points[i].Put(p[off:])
839+ off += 4
840+ }
841+ return seq
842+}
843+
844+func PolySegment(b *xturbo.Buf, drawable Drawable, gc Gcontext, segments []Segment) xturbo.Seq {
845+ size := 0
846+ size += 4
847+ size += 4
848+ size += len(segments) * 8
849+ size = (size + 3) &^ 3
850+ p, seq := b.Request(66, 0, size)
851+ if p == nil {
852+ return 0
853+ }
854+ off := 0
855+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
856+ off += 4
857+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
858+ off += 4
859+ for i := range segments {
860+ segments[i].Put(p[off:])
861+ off += 8
862+ }
863+ return seq
864+}
865+
866+func PolyRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
867+ size := 0
868+ size += 4
869+ size += 4
870+ size += len(rectangles) * 8
871+ size = (size + 3) &^ 3
872+ p, seq := b.Request(67, 0, size)
873+ if p == nil {
874+ return 0
875+ }
876+ off := 0
877+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
878+ off += 4
879+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
880+ off += 4
881+ for i := range rectangles {
882+ rectangles[i].Put(p[off:])
883+ off += 8
884+ }
885+ return seq
886+}
887+
888+func PolyArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
889+ size := 0
890+ size += 4
891+ size += 4
892+ size += len(arcs) * 12
893+ size = (size + 3) &^ 3
894+ p, seq := b.Request(68, 0, size)
895+ if p == nil {
896+ return 0
897+ }
898+ off := 0
899+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
900+ off += 4
901+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
902+ off += 4
903+ for i := range arcs {
904+ arcs[i].Put(p[off:])
905+ off += 12
906+ }
907+ return seq
908+}
909+
910+func FillPoly(b *xturbo.Buf, drawable Drawable, gc Gcontext, shape PolyShape, coordinateMode CoordMode, points []Point) xturbo.Seq {
911+ size := 0
912+ size += 4
913+ size += 4
914+ size += 1
915+ size += 1
916+ size += 2
917+ size += len(points) * 4
918+ size = (size + 3) &^ 3
919+ p, seq := b.Request(69, 0, size)
920+ if p == nil {
921+ return 0
922+ }
923+ off := 0
924+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
925+ off += 4
926+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
927+ off += 4
928+ p[off:][0] = byte(shape)
929+ off += 1
930+ p[off:][0] = byte(coordinateMode)
931+ off += 1
932+ off += 2
933+ for i := range points {
934+ points[i].Put(p[off:])
935+ off += 4
936+ }
937+ return seq
938+}
939+
940+func PolyFillRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
941+ size := 0
942+ size += 4
943+ size += 4
944+ size += len(rectangles) * 8
945+ size = (size + 3) &^ 3
946+ p, seq := b.Request(70, 0, size)
947+ if p == nil {
948+ return 0
949+ }
950+ off := 0
951+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
952+ off += 4
953+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
954+ off += 4
955+ for i := range rectangles {
956+ rectangles[i].Put(p[off:])
957+ off += 8
958+ }
959+ return seq
960+}
961+
962+func PolyFillArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
963+ size := 0
964+ size += 4
965+ size += 4
966+ size += len(arcs) * 12
967+ size = (size + 3) &^ 3
968+ p, seq := b.Request(71, 0, size)
969+ if p == nil {
970+ return 0
971+ }
972+ off := 0
973+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
974+ off += 4
975+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
976+ off += 4
977+ for i := range arcs {
978+ arcs[i].Put(p[off:])
979+ off += 12
980+ }
981+ return seq
982+}
983+
984+func PutImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, gc Gcontext, width uint16, height uint16, dstX int16, dstY int16, leftPad uint8, depth uint8, data []byte) xturbo.Seq {
985+ size := 0
986+ size += 4
987+ size += 4
988+ size += 2
989+ size += 2
990+ size += 2
991+ size += 2
992+ size += 1
993+ size += 1
994+ size += 2
995+ size += len(data) * 1
996+ size = (size + 3) &^ 3
997+ p, seq := b.Request(72, uint8(int(format)), size)
998+ if p == nil {
999+ return 0
1000+ }
1001+ off := 0
1002+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1003+ off += 4
1004+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1005+ off += 4
1006+ binary.LittleEndian.PutUint16(p[off:], uint16(width))
1007+ off += 2
1008+ binary.LittleEndian.PutUint16(p[off:], uint16(height))
1009+ off += 2
1010+ binary.LittleEndian.PutUint16(p[off:], uint16(dstX))
1011+ off += 2
1012+ binary.LittleEndian.PutUint16(p[off:], uint16(dstY))
1013+ off += 2
1014+ p[off:][0] = byte(leftPad)
1015+ off += 1
1016+ p[off:][0] = byte(depth)
1017+ off += 1
1018+ off += 2
1019+ copy(p[off:], data)
1020+ off += len(data)
1021+ return seq
1022+}
1023+
1024+func GetImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, x int16, y int16, width uint16, height uint16, planeMask uint32) xturbo.Seq {
1025+ p, seq := b.Request(73, uint8(int(format)), 16)
1026+ if p == nil {
1027+ return 0
1028+ }
1029+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
1030+ binary.LittleEndian.PutUint16(p[4:], uint16(x))
1031+ binary.LittleEndian.PutUint16(p[6:], uint16(y))
1032+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
1033+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
1034+ binary.LittleEndian.PutUint32(p[12:], uint32(planeMask))
1035+ return seq
1036+}
1037+
1038+func PolyText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1039+ size := 0
1040+ size += 4
1041+ size += 4
1042+ size += 2
1043+ size += 2
1044+ size += len(items) * 1
1045+ size = (size + 3) &^ 3
1046+ p, seq := b.Request(74, 0, size)
1047+ if p == nil {
1048+ return 0
1049+ }
1050+ off := 0
1051+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1052+ off += 4
1053+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1054+ off += 4
1055+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1056+ off += 2
1057+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1058+ off += 2
1059+ copy(p[off:], items)
1060+ off += len(items)
1061+ return seq
1062+}
1063+
1064+func PolyText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1065+ size := 0
1066+ size += 4
1067+ size += 4
1068+ size += 2
1069+ size += 2
1070+ size += len(items) * 1
1071+ size = (size + 3) &^ 3
1072+ p, seq := b.Request(75, 0, size)
1073+ if p == nil {
1074+ return 0
1075+ }
1076+ off := 0
1077+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1078+ off += 4
1079+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1080+ off += 4
1081+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1082+ off += 2
1083+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1084+ off += 2
1085+ copy(p[off:], items)
1086+ off += len(items)
1087+ return seq
1088+}
1089+
1090+func ImageText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string string) xturbo.Seq {
1091+ if len(string) > 255 {
1092+ b.Fail(xturbo.ErrBadLength)
1093+ return 0
1094+ }
1095+ size := 0
1096+ size += 4
1097+ size += 4
1098+ size += 2
1099+ size += 2
1100+ size += len(string) * 1
1101+ size = (size + 3) &^ 3
1102+ p, seq := b.Request(76, uint8(len(string)), size)
1103+ if p == nil {
1104+ return 0
1105+ }
1106+ off := 0
1107+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1108+ off += 4
1109+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1110+ off += 4
1111+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1112+ off += 2
1113+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1114+ off += 2
1115+ copy(p[off:], string)
1116+ off += len(string)
1117+ return seq
1118+}
1119+
1120+func ImageText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string []Char2b) xturbo.Seq {
1121+ if len(string) > 255 {
1122+ b.Fail(xturbo.ErrBadLength)
1123+ return 0
1124+ }
1125+ size := 0
1126+ size += 4
1127+ size += 4
1128+ size += 2
1129+ size += 2
1130+ size += len(string) * 2
1131+ size = (size + 3) &^ 3
1132+ p, seq := b.Request(77, uint8(len(string)), size)
1133+ if p == nil {
1134+ return 0
1135+ }
1136+ off := 0
1137+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1138+ off += 4
1139+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1140+ off += 4
1141+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1142+ off += 2
1143+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1144+ off += 2
1145+ for i := range string {
1146+ string[i].Put(p[off:])
1147+ off += 2
1148+ }
1149+ return seq
1150+}
1151+
1152+func CreateColormap(b *xturbo.Buf, alloc ColormapAlloc, mid Colormap, window Window, visual Visualid) xturbo.Seq {
1153+ p, seq := b.Request(78, uint8(int(alloc)), 12)
1154+ if p == nil {
1155+ return 0
1156+ }
1157+ binary.LittleEndian.PutUint32(p[0:], uint32(mid))
1158+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
1159+ binary.LittleEndian.PutUint32(p[8:], uint32(visual))
1160+ return seq
1161+}
1162+
1163+func FreeColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
1164+ p, seq := b.Request(79, 0, 4)
1165+ if p == nil {
1166+ return 0
1167+ }
1168+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1169+ return seq
1170+}
1171+
1172+func CopyColormapAndFree(b *xturbo.Buf, mid Colormap, srcCmap Colormap) xturbo.Seq {
1173+ p, seq := b.Request(80, 0, 8)
1174+ if p == nil {
1175+ return 0
1176+ }
1177+ binary.LittleEndian.PutUint32(p[0:], uint32(mid))
1178+ binary.LittleEndian.PutUint32(p[4:], uint32(srcCmap))
1179+ return seq
1180+}
1181+
1182+func InstallColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
1183+ p, seq := b.Request(81, 0, 4)
1184+ if p == nil {
1185+ return 0
1186+ }
1187+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1188+ return seq
1189+}
1190+
1191+func UninstallColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
1192+ p, seq := b.Request(82, 0, 4)
1193+ if p == nil {
1194+ return 0
1195+ }
1196+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1197+ return seq
1198+}
1199+
1200+func ListInstalledColormaps(b *xturbo.Buf, window Window) xturbo.Seq {
1201+ p, seq := b.Request(83, 0, 4)
1202+ if p == nil {
1203+ return 0
1204+ }
1205+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
1206+ return seq
1207+}
1208+
1209+func AllocColor(b *xturbo.Buf, cmap Colormap, red uint16, green uint16, blue uint16) xturbo.Seq {
1210+ p, seq := b.Request(84, 0, 12)
1211+ if p == nil {
1212+ return 0
1213+ }
1214+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1215+ binary.LittleEndian.PutUint16(p[4:], uint16(red))
1216+ binary.LittleEndian.PutUint16(p[6:], uint16(green))
1217+ binary.LittleEndian.PutUint16(p[8:], uint16(blue))
1218+ return seq
1219+}
1220+
1221+func AllocNamedColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1222+ if uint64(len(name)) > 65535 {
1223+ b.Fail(xturbo.ErrBadLength)
1224+ return 0
1225+ }
1226+ size := 0
1227+ size += 4
1228+ size += 2
1229+ size += 2
1230+ size += len(name) * 1
1231+ size = (size + 3) &^ 3
1232+ p, seq := b.Request(85, 0, size)
1233+ if p == nil {
1234+ return 0
1235+ }
1236+ off := 0
1237+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1238+ off += 4
1239+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1240+ off += 2
1241+ off += 2
1242+ copy(p[off:], name)
1243+ off += len(name)
1244+ return seq
1245+}
1246+
1247+func AllocColorCells(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, planes uint16) xturbo.Seq {
1248+ var data uint8
1249+ if contiguous {
1250+ data = 1
1251+ }
1252+ p, seq := b.Request(86, data, 8)
1253+ if p == nil {
1254+ return 0
1255+ }
1256+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1257+ binary.LittleEndian.PutUint16(p[4:], uint16(colors))
1258+ binary.LittleEndian.PutUint16(p[6:], uint16(planes))
1259+ return seq
1260+}
1261+
1262+func AllocColorPlanes(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, reds uint16, greens uint16, blues uint16) xturbo.Seq {
1263+ var data uint8
1264+ if contiguous {
1265+ data = 1
1266+ }
1267+ p, seq := b.Request(87, data, 12)
1268+ if p == nil {
1269+ return 0
1270+ }
1271+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
1272+ binary.LittleEndian.PutUint16(p[4:], uint16(colors))
1273+ binary.LittleEndian.PutUint16(p[6:], uint16(reds))
1274+ binary.LittleEndian.PutUint16(p[8:], uint16(greens))
1275+ binary.LittleEndian.PutUint16(p[10:], uint16(blues))
1276+ return seq
1277+}
1278+
1279+func FreeColors(b *xturbo.Buf, cmap Colormap, planeMask uint32, pixels []uint32) xturbo.Seq {
1280+ size := 0
1281+ size += 4
1282+ size += 4
1283+ size += len(pixels) * 4
1284+ size = (size + 3) &^ 3
1285+ p, seq := b.Request(88, 0, size)
1286+ if p == nil {
1287+ return 0
1288+ }
1289+ off := 0
1290+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1291+ off += 4
1292+ binary.LittleEndian.PutUint32(p[off:], uint32(planeMask))
1293+ off += 4
1294+ for i := range pixels {
1295+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1296+ off += 4
1297+ }
1298+ return seq
1299+}
1300+
1301+func StoreColors(b *xturbo.Buf, cmap Colormap, items []Coloritem) xturbo.Seq {
1302+ size := 0
1303+ size += 4
1304+ size += len(items) * 12
1305+ size = (size + 3) &^ 3
1306+ p, seq := b.Request(89, 0, size)
1307+ if p == nil {
1308+ return 0
1309+ }
1310+ off := 0
1311+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1312+ off += 4
1313+ for i := range items {
1314+ items[i].Put(p[off:])
1315+ off += 12
1316+ }
1317+ return seq
1318+}
1319+
1320+func StoreNamedColor(b *xturbo.Buf, flags ColorFlag, cmap Colormap, pixel uint32, name string) xturbo.Seq {
1321+ if uint64(len(name)) > 65535 {
1322+ b.Fail(xturbo.ErrBadLength)
1323+ return 0
1324+ }
1325+ size := 0
1326+ size += 4
1327+ size += 4
1328+ size += 2
1329+ size += 2
1330+ size += len(name) * 1
1331+ size = (size + 3) &^ 3
1332+ p, seq := b.Request(90, uint8(int(flags)), size)
1333+ if p == nil {
1334+ return 0
1335+ }
1336+ off := 0
1337+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1338+ off += 4
1339+ binary.LittleEndian.PutUint32(p[off:], uint32(pixel))
1340+ off += 4
1341+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1342+ off += 2
1343+ off += 2
1344+ copy(p[off:], name)
1345+ off += len(name)
1346+ return seq
1347+}
1348+
1349+func QueryColors(b *xturbo.Buf, cmap Colormap, pixels []uint32) xturbo.Seq {
1350+ size := 0
1351+ size += 4
1352+ size += len(pixels) * 4
1353+ size = (size + 3) &^ 3
1354+ p, seq := b.Request(91, 0, size)
1355+ if p == nil {
1356+ return 0
1357+ }
1358+ off := 0
1359+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1360+ off += 4
1361+ for i := range pixels {
1362+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1363+ off += 4
1364+ }
1365+ return seq
1366+}
1367+
1368+func LookupColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1369+ if uint64(len(name)) > 65535 {
1370+ b.Fail(xturbo.ErrBadLength)
1371+ return 0
1372+ }
1373+ size := 0
1374+ size += 4
1375+ size += 2
1376+ size += 2
1377+ size += len(name) * 1
1378+ size = (size + 3) &^ 3
1379+ p, seq := b.Request(92, 0, size)
1380+ if p == nil {
1381+ return 0
1382+ }
1383+ off := 0
1384+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1385+ off += 4
1386+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1387+ off += 2
1388+ off += 2
1389+ copy(p[off:], name)
1390+ off += len(name)
1391+ return seq
1392+}
1393+
1394+func CreateCursor(b *xturbo.Buf, cid Cursor, source Pixmap, mask Pixmap, foreRed uint16, foreGreen uint16, foreBlue uint16, backRed uint16, backGreen uint16, backBlue uint16, x uint16, y uint16) xturbo.Seq {
1395+ p, seq := b.Request(93, 0, 28)
1396+ if p == nil {
1397+ return 0
1398+ }
1399+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
1400+ binary.LittleEndian.PutUint32(p[4:], uint32(source))
1401+ binary.LittleEndian.PutUint32(p[8:], uint32(mask))
1402+ binary.LittleEndian.PutUint16(p[12:], uint16(foreRed))
1403+ binary.LittleEndian.PutUint16(p[14:], uint16(foreGreen))
1404+ binary.LittleEndian.PutUint16(p[16:], uint16(foreBlue))
1405+ binary.LittleEndian.PutUint16(p[18:], uint16(backRed))
1406+ binary.LittleEndian.PutUint16(p[20:], uint16(backGreen))
1407+ binary.LittleEndian.PutUint16(p[22:], uint16(backBlue))
1408+ binary.LittleEndian.PutUint16(p[24:], uint16(x))
1409+ binary.LittleEndian.PutUint16(p[26:], uint16(y))
1410+ return seq
1411+}
1412+
1413+func CreateGlyphCursor(b *xturbo.Buf, cid Cursor, sourceFont Font, maskFont Font, sourceChar uint16, maskChar uint16, foreRed uint16, foreGreen uint16, foreBlue uint16, backRed uint16, backGreen uint16, backBlue uint16) xturbo.Seq {
1414+ p, seq := b.Request(94, 0, 28)
1415+ if p == nil {
1416+ return 0
1417+ }
1418+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
1419+ binary.LittleEndian.PutUint32(p[4:], uint32(sourceFont))
1420+ binary.LittleEndian.PutUint32(p[8:], uint32(maskFont))
1421+ binary.LittleEndian.PutUint16(p[12:], uint16(sourceChar))
1422+ binary.LittleEndian.PutUint16(p[14:], uint16(maskChar))
1423+ binary.LittleEndian.PutUint16(p[16:], uint16(foreRed))
1424+ binary.LittleEndian.PutUint16(p[18:], uint16(foreGreen))
1425+ binary.LittleEndian.PutUint16(p[20:], uint16(foreBlue))
1426+ binary.LittleEndian.PutUint16(p[22:], uint16(backRed))
1427+ binary.LittleEndian.PutUint16(p[24:], uint16(backGreen))
1428+ binary.LittleEndian.PutUint16(p[26:], uint16(backBlue))
1429+ return seq
1430+}
1431+
1432+func FreeCursor(b *xturbo.Buf, cursor Cursor) xturbo.Seq {
1433+ p, seq := b.Request(95, 0, 4)
1434+ if p == nil {
1435+ return 0
1436+ }
1437+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
1438+ return seq
1439+}
1440+
1441+func RecolorCursor(b *xturbo.Buf, cursor Cursor, foreRed uint16, foreGreen uint16, foreBlue uint16, backRed uint16, backGreen uint16, backBlue uint16) xturbo.Seq {
1442+ p, seq := b.Request(96, 0, 16)
1443+ if p == nil {
1444+ return 0
1445+ }
1446+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
1447+ binary.LittleEndian.PutUint16(p[4:], uint16(foreRed))
1448+ binary.LittleEndian.PutUint16(p[6:], uint16(foreGreen))
1449+ binary.LittleEndian.PutUint16(p[8:], uint16(foreBlue))
1450+ binary.LittleEndian.PutUint16(p[10:], uint16(backRed))
1451+ binary.LittleEndian.PutUint16(p[12:], uint16(backGreen))
1452+ binary.LittleEndian.PutUint16(p[14:], uint16(backBlue))
1453+ return seq
1454+}
1455+
1456+func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width uint16, height uint16) xturbo.Seq {
1457+ p, seq := b.Request(97, uint8(int(class)), 8)
1458+ if p == nil {
1459+ return 0
1460+ }
1461+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
1462+ binary.LittleEndian.PutUint16(p[4:], uint16(width))
1463+ binary.LittleEndian.PutUint16(p[6:], uint16(height))
1464+ return seq
1465+}
1466+
1467+func QueryExtension(b *xturbo.Buf, name string) xturbo.Seq {
1468+ if uint64(len(name)) > 65535 {
1469+ b.Fail(xturbo.ErrBadLength)
1470+ return 0
1471+ }
1472+ size := 0
1473+ size += 2
1474+ size += 2
1475+ size += len(name) * 1
1476+ size = (size + 3) &^ 3
1477+ p, seq := b.Request(98, 0, size)
1478+ if p == nil {
1479+ return 0
1480+ }
1481+ off := 0
1482+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1483+ off += 2
1484+ off += 2
1485+ copy(p[off:], name)
1486+ off += len(name)
1487+ return seq
1488+}
1489+
1490+func ListExtensions(b *xturbo.Buf) xturbo.Seq {
1491+ p, seq := b.Request(99, 0, 0)
1492+ if p == nil {
1493+ return 0
1494+ }
1495+ return seq
1496+}
1497+
1498+func ChangeKeyboardMapping(b *xturbo.Buf, keycodeCount uint8, firstKeycode Keycode, keysymsPerKeycode uint8, keysyms []Keysym) xturbo.Seq {
1499+ if len(keysyms) != (int(keycodeCount) * int(keysymsPerKeycode)) {
1500+ b.Fail(xturbo.ErrBadLength)
1501+ return 0
1502+ }
1503+ size := 0
1504+ size += 1
1505+ size += 1
1506+ size += 2
1507+ size += len(keysyms) * 4
1508+ size = (size + 3) &^ 3
1509+ p, seq := b.Request(100, uint8(int(keycodeCount)), size)
1510+ if p == nil {
1511+ return 0
1512+ }
1513+ off := 0
1514+ p[off:][0] = byte(firstKeycode)
1515+ off += 1
1516+ p[off:][0] = byte(keysymsPerKeycode)
1517+ off += 1
1518+ off += 2
1519+ for i := range keysyms {
1520+ binary.LittleEndian.PutUint32(p[off:], uint32(keysyms[i]))
1521+ off += 4
1522+ }
1523+ return seq
1524+}
1525+
1526+func GetKeyboardMapping(b *xturbo.Buf, firstKeycode Keycode, count uint8) xturbo.Seq {
1527+ p, seq := b.Request(101, 0, 4)
1528+ if p == nil {
1529+ return 0
1530+ }
1531+ p[0:][0] = byte(firstKeycode)
1532+ p[1:][0] = byte(count)
1533+ return seq
1534+}
1535+
1536+func GetKeyboardControl(b *xturbo.Buf) xturbo.Seq {
1537+ p, seq := b.Request(103, 0, 0)
1538+ if p == nil {
1539+ return 0
1540+ }
1541+ return seq
1542+}
1543+
1544+func Bell(b *xturbo.Buf, percent int8) xturbo.Seq {
1545+ p, seq := b.Request(104, uint8(int(percent)), 0)
1546+ if p == nil {
1547+ return 0
1548+ }
1549+ return seq
1550+}
1551+
1552+func ChangePointerControl(b *xturbo.Buf, accelerationNumerator int16, accelerationDenominator int16, threshold int16, doAcceleration bool, doThreshold bool) xturbo.Seq {
1553+ p, seq := b.Request(105, 0, 8)
1554+ if p == nil {
1555+ return 0
1556+ }
1557+ binary.LittleEndian.PutUint16(p[0:], uint16(accelerationNumerator))
1558+ binary.LittleEndian.PutUint16(p[2:], uint16(accelerationDenominator))
1559+ binary.LittleEndian.PutUint16(p[4:], uint16(threshold))
1560+ if doAcceleration {
1561+ p[6:][0] = 1
1562+ } else {
1563+ p[6:][0] = 0
1564+ }
1565+ if doThreshold {
1566+ p[7:][0] = 1
1567+ } else {
1568+ p[7:][0] = 0
1569+ }
1570+ return seq
1571+}
1572+
1573+func GetPointerControl(b *xturbo.Buf) xturbo.Seq {
1574+ p, seq := b.Request(106, 0, 0)
1575+ if p == nil {
1576+ return 0
1577+ }
1578+ return seq
1579+}
1580+
1581+func SetScreenSaver(b *xturbo.Buf, timeout int16, interval int16, preferBlanking Blanking, allowExposures Exposures) xturbo.Seq {
1582+ p, seq := b.Request(107, 0, 8)
1583+ if p == nil {
1584+ return 0
1585+ }
1586+ binary.LittleEndian.PutUint16(p[0:], uint16(timeout))
1587+ binary.LittleEndian.PutUint16(p[2:], uint16(interval))
1588+ p[4:][0] = byte(preferBlanking)
1589+ p[5:][0] = byte(allowExposures)
1590+ return seq
1591+}
1592+
1593+func GetScreenSaver(b *xturbo.Buf) xturbo.Seq {
1594+ p, seq := b.Request(108, 0, 0)
1595+ if p == nil {
1596+ return 0
1597+ }
1598+ return seq
1599+}
1600+
1601+func ChangeHosts(b *xturbo.Buf, mode HostMode, family Family, address []byte) xturbo.Seq {
1602+ if uint64(len(address)) > 65535 {
1603+ b.Fail(xturbo.ErrBadLength)
1604+ return 0
1605+ }
1606+ size := 0
1607+ size += 1
1608+ size += 1
1609+ size += 2
1610+ size += len(address) * 1
1611+ size = (size + 3) &^ 3
1612+ p, seq := b.Request(109, uint8(int(mode)), size)
1613+ if p == nil {
1614+ return 0
1615+ }
1616+ off := 0
1617+ p[off:][0] = byte(family)
1618+ off += 1
1619+ off += 1
1620+ binary.LittleEndian.PutUint16(p[off:], uint16(len(address)))
1621+ off += 2
1622+ copy(p[off:], address)
1623+ off += len(address)
1624+ return seq
1625+}
1626+
1627+func ListHosts(b *xturbo.Buf) xturbo.Seq {
1628+ p, seq := b.Request(110, 0, 0)
1629+ if p == nil {
1630+ return 0
1631+ }
1632+ return seq
1633+}
1634+
1635+func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
1636+ p, seq := b.Request(111, uint8(int(mode)), 0)
1637+ if p == nil {
1638+ return 0
1639+ }
1640+ return seq
1641+}
1642+
1643+func SetCloseDownMode(b *xturbo.Buf, mode CloseDown) xturbo.Seq {
1644+ p, seq := b.Request(112, uint8(int(mode)), 0)
1645+ if p == nil {
1646+ return 0
1647+ }
1648+ return seq
1649+}
1650+
1651+func KillClient(b *xturbo.Buf, resource uint32) xturbo.Seq {
1652+ p, seq := b.Request(113, 0, 4)
1653+ if p == nil {
1654+ return 0
1655+ }
1656+ binary.LittleEndian.PutUint32(p[0:], uint32(resource))
1657+ return seq
1658+}
1659+
1660+func RotateProperties(b *xturbo.Buf, window Window, delta int16, atoms []Atom) xturbo.Seq {
1661+ if uint64(len(atoms)) > 65535 {
1662+ b.Fail(xturbo.ErrBadLength)
1663+ return 0
1664+ }
1665+ size := 0
1666+ size += 4
1667+ size += 2
1668+ size += 2
1669+ size += len(atoms) * 4
1670+ size = (size + 3) &^ 3
1671+ p, seq := b.Request(114, 0, size)
1672+ if p == nil {
1673+ return 0
1674+ }
1675+ off := 0
1676+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
1677+ off += 4
1678+ binary.LittleEndian.PutUint16(p[off:], uint16(len(atoms)))
1679+ off += 2
1680+ binary.LittleEndian.PutUint16(p[off:], uint16(delta))
1681+ off += 2
1682+ for i := range atoms {
1683+ binary.LittleEndian.PutUint32(p[off:], uint32(atoms[i]))
1684+ off += 4
1685+ }
1686+ return seq
1687+}
1688+
1689+func ForceScreenSaver(b *xturbo.Buf, mode ScreenSaver) xturbo.Seq {
1690+ p, seq := b.Request(115, uint8(int(mode)), 0)
1691+ if p == nil {
1692+ return 0
1693+ }
1694+ return seq
1695+}
1696+
1697+func SetPointerMapping(b *xturbo.Buf, map_ []byte) xturbo.Seq {
1698+ if len(map_) > 255 {
1699+ b.Fail(xturbo.ErrBadLength)
1700+ return 0
1701+ }
1702+ size := 0
1703+ size += len(map_) * 1
1704+ size = (size + 3) &^ 3
1705+ p, seq := b.Request(116, uint8(len(map_)), size)
1706+ if p == nil {
1707+ return 0
1708+ }
1709+ off := 0
1710+ copy(p[off:], map_)
1711+ off += len(map_)
1712+ return seq
1713+}
1714+
1715+func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
1716+ p, seq := b.Request(117, 0, 0)
1717+ if p == nil {
1718+ return 0
1719+ }
1720+ return seq
1721+}
1722+
1723+func SetModifierMapping(b *xturbo.Buf, keycodesPerModifier uint8, keycodes []Keycode) xturbo.Seq {
1724+ if len(keycodes) != (int(keycodesPerModifier) * 8) {
1725+ b.Fail(xturbo.ErrBadLength)
1726+ return 0
1727+ }
1728+ size := 0
1729+ size += len(keycodes) * 1
1730+ size = (size + 3) &^ 3
1731+ p, seq := b.Request(118, uint8(int(keycodesPerModifier)), size)
1732+ if p == nil {
1733+ return 0
1734+ }
1735+ off := 0
1736+ for i := range keycodes {
1737+ p[off:][0] = byte(keycodes[i])
1738+ off += 1
1739+ }
1740+ return seq
1741+}
1742+
1743+func GetModifierMapping(b *xturbo.Buf) xturbo.Seq {
1744+ p, seq := b.Request(119, 0, 0)
1745+ if p == nil {
1746+ return 0
1747+ }
1748+ return seq
1749+}
1750+
1751+func NoOperation(b *xturbo.Buf) xturbo.Seq {
1752+ p, seq := b.Request(127, 0, 0)
1753+ if p == nil {
1754+ return 0
1755+ }
1756+ return seq
1757+}
A xproto/requests_test.go +60 -0
@@ -0,0 +1,60 @@
1+package xproto
2+
3+import (
4+ "bnema.dev/xturbo"
5+ "testing"
6+)
7+
8+func BenchmarkMapWindow(b *testing.B) {
9+ buf := xturbo.NewBuf(0)
10+ batch := 0
11+ b.ReportAllocs()
12+ b.ResetTimer()
13+ for i := 0; i < b.N; i++ {
14+ if batch == 60000 {
15+ b.StopTimer()
16+ buf = xturbo.NewBuf(0)
17+ batch = 0
18+ b.StartTimer()
19+ }
20+ buf.Reset()
21+ MapWindow(buf, 1)
22+ batch++
23+ }
24+}
25+
26+func BenchmarkInternAtom(b *testing.B) {
27+ buf := xturbo.NewBuf(0)
28+ batch := 0
29+ b.ReportAllocs()
30+ b.ResetTimer()
31+ for i := 0; i < b.N; i++ {
32+ if batch == 60000 {
33+ b.StopTimer()
34+ buf = xturbo.NewBuf(0)
35+ batch = 0
36+ b.StartTimer()
37+ }
38+ buf.Reset()
39+ InternAtom(buf, false, "WM_CLASS")
40+ batch++
41+ }
42+}
43+func BenchmarkChangeProperty4KiB(b *testing.B) {
44+ buf := xturbo.NewBuf(0)
45+ data := make([]byte, 4096)
46+ batch := 0
47+ b.ReportAllocs()
48+ b.ResetTimer()
49+ for i := 0; i < b.N; i++ {
50+ if batch == 60000 {
51+ b.StopTimer()
52+ buf = xturbo.NewBuf(0)
53+ batch = 0
54+ b.StartTimer()
55+ }
56+ buf.Reset()
57+ ChangeProperty(buf, 0, 1, 1, 1, 8, 4096, data)
58+ batch++
59+ }
60+}
A xproto/sizes_test.go +293 -0
@@ -0,0 +1,293 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xproto
3+
4+import "testing"
5+
6+func TestWireSizes(t *testing.T) {
7+ if Char2bSize != 2 {
8+ t.Errorf("Char2b fixed prefix = %d", Char2bSize)
9+ }
10+ if PointSize != 4 {
11+ t.Errorf("Point fixed prefix = %d", PointSize)
12+ }
13+ if RectangleSize != 8 {
14+ t.Errorf("Rectangle fixed prefix = %d", RectangleSize)
15+ }
16+ if ArcSize != 12 {
17+ t.Errorf("Arc fixed prefix = %d", ArcSize)
18+ }
19+ if FormatSize != 8 {
20+ t.Errorf("Format fixed prefix = %d", FormatSize)
21+ }
22+ if VisualtypeSize != 24 {
23+ t.Errorf("Visualtype fixed prefix = %d", VisualtypeSize)
24+ }
25+ if DepthSize != 8 {
26+ t.Errorf("Depth fixed prefix = %d", DepthSize)
27+ }
28+ if ScreenSize != 40 {
29+ t.Errorf("Screen fixed prefix = %d", ScreenSize)
30+ }
31+ if SetupRequestSize != 12 {
32+ t.Errorf("SetupRequest fixed prefix = %d", SetupRequestSize)
33+ }
34+ if SetupFailedSize != 8 {
35+ t.Errorf("SetupFailed fixed prefix = %d", SetupFailedSize)
36+ }
37+ if SetupAuthenticateSize != 8 {
38+ t.Errorf("SetupAuthenticate fixed prefix = %d", SetupAuthenticateSize)
39+ }
40+ if SetupSize != 40 {
41+ t.Errorf("Setup fixed prefix = %d", SetupSize)
42+ }
43+ if ClientMessageDataSize != 20 {
44+ t.Errorf("ClientMessageData fixed prefix = %d", ClientMessageDataSize)
45+ }
46+ if TimecoordSize != 8 {
47+ t.Errorf("Timecoord fixed prefix = %d", TimecoordSize)
48+ }
49+ if FontpropSize != 8 {
50+ t.Errorf("Fontprop fixed prefix = %d", FontpropSize)
51+ }
52+ if CharinfoSize != 12 {
53+ t.Errorf("Charinfo fixed prefix = %d", CharinfoSize)
54+ }
55+ if StrSize != 1 {
56+ t.Errorf("Str fixed prefix = %d", StrSize)
57+ }
58+ if SegmentSize != 8 {
59+ t.Errorf("Segment fixed prefix = %d", SegmentSize)
60+ }
61+ if ColoritemSize != 12 {
62+ t.Errorf("Coloritem fixed prefix = %d", ColoritemSize)
63+ }
64+ if RgbSize != 8 {
65+ t.Errorf("Rgb fixed prefix = %d", RgbSize)
66+ }
67+ if HostSize != 4 {
68+ t.Errorf("Host fixed prefix = %d", HostSize)
69+ }
70+ if got := 32; got != 32 {
71+ t.Errorf("event KeyPress fixed size = %d", got)
72+ }
73+ if got := 32; got != 32 {
74+ t.Errorf("event KeyRelease fixed size = %d", got)
75+ }
76+ if got := 32; got != 32 {
77+ t.Errorf("event ButtonPress fixed size = %d", got)
78+ }
79+ if got := 32; got != 32 {
80+ t.Errorf("event ButtonRelease fixed size = %d", got)
81+ }
82+ if got := 32; got != 32 {
83+ t.Errorf("event MotionNotify fixed size = %d", got)
84+ }
85+ if got := 32; got != 32 {
86+ t.Errorf("event EnterNotify fixed size = %d", got)
87+ }
88+ if got := 32; got != 32 {
89+ t.Errorf("event LeaveNotify fixed size = %d", got)
90+ }
91+ if got := 32; got != 32 {
92+ t.Errorf("event FocusIn fixed size = %d", got)
93+ }
94+ if got := 32; got != 32 {
95+ t.Errorf("event FocusOut fixed size = %d", got)
96+ }
97+ if got := 32; got != 32 {
98+ t.Errorf("event KeymapNotify fixed size = %d", got)
99+ }
100+ if got := 32; got != 32 {
101+ t.Errorf("event Expose fixed size = %d", got)
102+ }
103+ if got := 32; got != 32 {
104+ t.Errorf("event GraphicsExposure fixed size = %d", got)
105+ }
106+ if got := 32; got != 32 {
107+ t.Errorf("event NoExposure fixed size = %d", got)
108+ }
109+ if got := 32; got != 32 {
110+ t.Errorf("event VisibilityNotify fixed size = %d", got)
111+ }
112+ if got := 32; got != 32 {
113+ t.Errorf("event CreateNotify fixed size = %d", got)
114+ }
115+ if got := 32; got != 32 {
116+ t.Errorf("event DestroyNotify fixed size = %d", got)
117+ }
118+ if got := 32; got != 32 {
119+ t.Errorf("event UnmapNotify fixed size = %d", got)
120+ }
121+ if got := 32; got != 32 {
122+ t.Errorf("event MapNotify fixed size = %d", got)
123+ }
124+ if got := 32; got != 32 {
125+ t.Errorf("event MapRequest fixed size = %d", got)
126+ }
127+ if got := 32; got != 32 {
128+ t.Errorf("event ReparentNotify fixed size = %d", got)
129+ }
130+ if got := 32; got != 32 {
131+ t.Errorf("event ConfigureNotify fixed size = %d", got)
132+ }
133+ if got := 32; got != 32 {
134+ t.Errorf("event ConfigureRequest fixed size = %d", got)
135+ }
136+ if got := 32; got != 32 {
137+ t.Errorf("event GravityNotify fixed size = %d", got)
138+ }
139+ if got := 32; got != 32 {
140+ t.Errorf("event ResizeRequest fixed size = %d", got)
141+ }
142+ if got := 32; got != 32 {
143+ t.Errorf("event CirculateNotify fixed size = %d", got)
144+ }
145+ if got := 32; got != 32 {
146+ t.Errorf("event CirculateRequest fixed size = %d", got)
147+ }
148+ if got := 32; got != 32 {
149+ t.Errorf("event PropertyNotify fixed size = %d", got)
150+ }
151+ if got := 32; got != 32 {
152+ t.Errorf("event SelectionClear fixed size = %d", got)
153+ }
154+ if got := 32; got != 32 {
155+ t.Errorf("event SelectionRequest fixed size = %d", got)
156+ }
157+ if got := 32; got != 32 {
158+ t.Errorf("event SelectionNotify fixed size = %d", got)
159+ }
160+ if got := 32; got != 32 {
161+ t.Errorf("event ColormapNotify fixed size = %d", got)
162+ }
163+ if got := 32; got != 32 {
164+ t.Errorf("event ClientMessage fixed size = %d", got)
165+ }
166+ if got := 32; got != 32 {
167+ t.Errorf("event MappingNotify fixed size = %d", got)
168+ }
169+ if got := 32; got != 32 {
170+ t.Errorf("event GeGeneric fixed size = %d", got)
171+ }
172+ if got := 44; got != 44 {
173+ t.Errorf("reply GetWindowAttributes fixed size = %d", got)
174+ }
175+ if got := 32; got != 32 {
176+ t.Errorf("reply GetGeometry fixed size = %d", got)
177+ }
178+ if got := 32; got != 32 {
179+ t.Errorf("reply QueryTree fixed size = %d", got)
180+ }
181+ if got := 32; got != 32 {
182+ t.Errorf("reply InternAtom fixed size = %d", got)
183+ }
184+ if got := 32; got != 32 {
185+ t.Errorf("reply GetAtomName fixed size = %d", got)
186+ }
187+ if got := 32; got != 32 {
188+ t.Errorf("reply GetProperty fixed size = %d", got)
189+ }
190+ if got := 32; got != 32 {
191+ t.Errorf("reply ListProperties fixed size = %d", got)
192+ }
193+ if got := 32; got != 32 {
194+ t.Errorf("reply GetSelectionOwner fixed size = %d", got)
195+ }
196+ if got := 32; got != 32 {
197+ t.Errorf("reply GrabPointer fixed size = %d", got)
198+ }
199+ if got := 32; got != 32 {
200+ t.Errorf("reply GrabKeyboard fixed size = %d", got)
201+ }
202+ if got := 32; got != 32 {
203+ t.Errorf("reply QueryPointer fixed size = %d", got)
204+ }
205+ if got := 32; got != 32 {
206+ t.Errorf("reply GetMotionEvents fixed size = %d", got)
207+ }
208+ if got := 32; got != 32 {
209+ t.Errorf("reply TranslateCoordinates fixed size = %d", got)
210+ }
211+ if got := 32; got != 32 {
212+ t.Errorf("reply GetInputFocus fixed size = %d", got)
213+ }
214+ if got := 40; got != 40 {
215+ t.Errorf("reply QueryKeymap fixed size = %d", got)
216+ }
217+ if got := 60; got != 60 {
218+ t.Errorf("reply QueryFont fixed size = %d", got)
219+ }
220+ if got := 32; got != 32 {
221+ t.Errorf("reply QueryTextExtents fixed size = %d", got)
222+ }
223+ if got := 32; got != 32 {
224+ t.Errorf("reply ListFonts fixed size = %d", got)
225+ }
226+ if got := 60; got != 60 {
227+ t.Errorf("reply ListFontsWithInfo fixed size = %d", got)
228+ }
229+ if got := 32; got != 32 {
230+ t.Errorf("reply GetFontPath fixed size = %d", got)
231+ }
232+ if got := 32; got != 32 {
233+ t.Errorf("reply GetImage fixed size = %d", got)
234+ }
235+ if got := 32; got != 32 {
236+ t.Errorf("reply ListInstalledColormaps fixed size = %d", got)
237+ }
238+ if got := 32; got != 32 {
239+ t.Errorf("reply AllocColor fixed size = %d", got)
240+ }
241+ if got := 32; got != 32 {
242+ t.Errorf("reply AllocNamedColor fixed size = %d", got)
243+ }
244+ if got := 32; got != 32 {
245+ t.Errorf("reply AllocColorCells fixed size = %d", got)
246+ }
247+ if got := 32; got != 32 {
248+ t.Errorf("reply AllocColorPlanes fixed size = %d", got)
249+ }
250+ if got := 32; got != 32 {
251+ t.Errorf("reply QueryColors fixed size = %d", got)
252+ }
253+ if got := 32; got != 32 {
254+ t.Errorf("reply LookupColor fixed size = %d", got)
255+ }
256+ if got := 32; got != 32 {
257+ t.Errorf("reply QueryBestSize fixed size = %d", got)
258+ }
259+ if got := 32; got != 32 {
260+ t.Errorf("reply QueryExtension fixed size = %d", got)
261+ }
262+ if got := 32; got != 32 {
263+ t.Errorf("reply ListExtensions fixed size = %d", got)
264+ }
265+ if got := 32; got != 32 {
266+ t.Errorf("reply GetKeyboardMapping fixed size = %d", got)
267+ }
268+ if got := 52; got != 52 {
269+ t.Errorf("reply GetKeyboardControl fixed size = %d", got)
270+ }
271+ if got := 32; got != 32 {
272+ t.Errorf("reply GetPointerControl fixed size = %d", got)
273+ }
274+ if got := 32; got != 32 {
275+ t.Errorf("reply GetScreenSaver fixed size = %d", got)
276+ }
277+ if got := 32; got != 32 {
278+ t.Errorf("reply ListHosts fixed size = %d", got)
279+ }
280+ if got := 32; got != 32 {
281+ t.Errorf("reply SetPointerMapping fixed size = %d", got)
282+ }
283+ if got := 32; got != 32 {
284+ t.Errorf("reply GetPointerMapping fixed size = %d", got)
285+ }
286+ if got := 32; got != 32 {
287+ t.Errorf("reply SetModifierMapping fixed size = %d", got)
288+ }
289+ if got := 32; got != 32 {
290+ t.Errorf("reply GetModifierMapping fixed size = %d", got)
291+ }
292+
293+}
A xproto/types_generated.go +1353 -0
@@ -0,0 +1,1353 @@
1+// Code generated by xtgen; DO NOT EDIT.
2+package xproto
3+
4+import "encoding/binary"
5+
6+type Char2b struct {
7+ Byte1 uint8
8+ Byte2 uint8
9+}
10+
11+const Char2bSize = 2
12+
13+func (v Char2b) Put(p []byte) { clear(p[:2]); p[0:][0] = byte(v.Byte1); p[1:][0] = byte(v.Byte2) }
14+func GetChar2b(p []byte) (v Char2b) {
15+ _ = p[1]
16+ v.Byte1 = uint8(p[0:][0])
17+ v.Byte2 = uint8(p[1:][0])
18+ return
19+}
20+
21+type Window uint32
22+
23+type Pixmap uint32
24+
25+type Cursor uint32
26+
27+type Font uint32
28+
29+type Gcontext uint32
30+
31+type Colormap uint32
32+
33+type Atom uint32
34+
35+type Drawable uint32
36+
37+type Fontable uint32
38+
39+type Bool32 uint32
40+
41+type Visualid uint32
42+
43+type Timestamp uint32
44+
45+type Keysym uint32
46+
47+type Keycode uint8
48+
49+type Keycode32 uint32
50+
51+type Button uint8
52+
53+type Point struct {
54+ X int16
55+ Y int16
56+}
57+
58+const PointSize = 4
59+
60+func (v Point) Put(p []byte) {
61+ clear(p[:4])
62+ binary.LittleEndian.PutUint16(p[0:], uint16(v.X))
63+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Y))
64+}
65+func GetPoint(p []byte) (v Point) {
66+ _ = p[3]
67+ v.X = int16(binary.LittleEndian.Uint16(p[0:]))
68+ v.Y = int16(binary.LittleEndian.Uint16(p[2:]))
69+ return
70+}
71+
72+type Rectangle struct {
73+ X int16
74+ Y int16
75+ Width uint16
76+ Height uint16
77+}
78+
79+const RectangleSize = 8
80+
81+func (v Rectangle) Put(p []byte) {
82+ clear(p[:8])
83+ binary.LittleEndian.PutUint16(p[0:], uint16(v.X))
84+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Y))
85+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Width))
86+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Height))
87+}
88+func GetRectangle(p []byte) (v Rectangle) {
89+ _ = p[7]
90+ v.X = int16(binary.LittleEndian.Uint16(p[0:]))
91+ v.Y = int16(binary.LittleEndian.Uint16(p[2:]))
92+ v.Width = uint16(binary.LittleEndian.Uint16(p[4:]))
93+ v.Height = uint16(binary.LittleEndian.Uint16(p[6:]))
94+ return
95+}
96+
97+type Arc struct {
98+ X int16
99+ Y int16
100+ Width uint16
101+ Height uint16
102+ Angle1 int16
103+ Angle2 int16
104+}
105+
106+const ArcSize = 12
107+
108+func (v Arc) Put(p []byte) {
109+ clear(p[:12])
110+ binary.LittleEndian.PutUint16(p[0:], uint16(v.X))
111+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Y))
112+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Width))
113+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Height))
114+ binary.LittleEndian.PutUint16(p[8:], uint16(v.Angle1))
115+ binary.LittleEndian.PutUint16(p[10:], uint16(v.Angle2))
116+}
117+func GetArc(p []byte) (v Arc) {
118+ _ = p[11]
119+ v.X = int16(binary.LittleEndian.Uint16(p[0:]))
120+ v.Y = int16(binary.LittleEndian.Uint16(p[2:]))
121+ v.Width = uint16(binary.LittleEndian.Uint16(p[4:]))
122+ v.Height = uint16(binary.LittleEndian.Uint16(p[6:]))
123+ v.Angle1 = int16(binary.LittleEndian.Uint16(p[8:]))
124+ v.Angle2 = int16(binary.LittleEndian.Uint16(p[10:]))
125+ return
126+}
127+
128+type Format struct {
129+ Depth uint8
130+ BitsPerPixel uint8
131+ ScanlinePad uint8
132+}
133+
134+const FormatSize = 8
135+
136+func (v Format) Put(p []byte) {
137+ clear(p[:8])
138+ p[0:][0] = byte(v.Depth)
139+ p[1:][0] = byte(v.BitsPerPixel)
140+ p[2:][0] = byte(v.ScanlinePad)
141+}
142+func GetFormat(p []byte) (v Format) {
143+ _ = p[7]
144+ v.Depth = uint8(p[0:][0])
145+ v.BitsPerPixel = uint8(p[1:][0])
146+ v.ScanlinePad = uint8(p[2:][0])
147+ return
148+}
149+
150+type Visualtype struct {
151+ VisualId Visualid
152+ Class VisualClass
153+ BitsPerRgbValue uint8
154+ ColormapEntries uint16
155+ RedMask uint32
156+ GreenMask uint32
157+ BlueMask uint32
158+}
159+
160+const VisualtypeSize = 24
161+
162+func (v Visualtype) Put(p []byte) {
163+ clear(p[:24])
164+ binary.LittleEndian.PutUint32(p[0:], uint32(v.VisualId))
165+ p[4:][0] = byte(v.Class)
166+ p[5:][0] = byte(v.BitsPerRgbValue)
167+ binary.LittleEndian.PutUint16(p[6:], uint16(v.ColormapEntries))
168+ binary.LittleEndian.PutUint32(p[8:], uint32(v.RedMask))
169+ binary.LittleEndian.PutUint32(p[12:], uint32(v.GreenMask))
170+ binary.LittleEndian.PutUint32(p[16:], uint32(v.BlueMask))
171+}
172+func GetVisualtype(p []byte) (v Visualtype) {
173+ _ = p[23]
174+ v.VisualId = Visualid(binary.LittleEndian.Uint32(p[0:]))
175+ v.Class = VisualClass(p[4:][0])
176+ v.BitsPerRgbValue = uint8(p[5:][0])
177+ v.ColormapEntries = uint16(binary.LittleEndian.Uint16(p[6:]))
178+ v.RedMask = uint32(binary.LittleEndian.Uint32(p[8:]))
179+ v.GreenMask = uint32(binary.LittleEndian.Uint32(p[12:]))
180+ v.BlueMask = uint32(binary.LittleEndian.Uint32(p[16:]))
181+ return
182+}
183+
184+type Depth struct {
185+ Depth uint8
186+ VisualsLen uint16
187+ Visuals []Visualtype
188+}
189+
190+const DepthSize = 8
191+
192+func (v Depth) Size() int {
193+ off := 0
194+ off += 1
195+ off += 1
196+ off += 2
197+ off += 4
198+ off += len(v.Visuals) * 24
199+ return off
200+}
201+func (v Depth) Put(p []byte) {
202+ off := 0
203+ p[off:][0] = byte(v.Depth)
204+ off += 1
205+ clear(p[off : off+1])
206+ off += 1
207+ binary.LittleEndian.PutUint16(p[off:], uint16(v.VisualsLen))
208+ off += 2
209+ clear(p[off : off+4])
210+ off += 4
211+ for i := range v.Visuals {
212+ v.Visuals[i].Put(p[off+i*24:])
213+ }
214+ off += len(v.Visuals) * 24
215+}
216+
217+type Screen struct {
218+ Root Window
219+ DefaultColormap Colormap
220+ WhitePixel uint32
221+ BlackPixel uint32
222+ CurrentInputMasks EventMask
223+ WidthInPixels uint16
224+ HeightInPixels uint16
225+ WidthInMillimeters uint16
226+ HeightInMillimeters uint16
227+ MinInstalledMaps uint16
228+ MaxInstalledMaps uint16
229+ RootVisual Visualid
230+ BackingStores BackingStore
231+ SaveUnders bool
232+ RootDepth uint8
233+ AllowedDepthsLen uint8
234+ AllowedDepths []Depth
235+}
236+
237+const ScreenSize = 40
238+
239+func (v Screen) Size() int {
240+ off := 0
241+ off += 4
242+ off += 4
243+ off += 4
244+ off += 4
245+ off += 4
246+ off += 2
247+ off += 2
248+ off += 2
249+ off += 2
250+ off += 2
251+ off += 2
252+ off += 4
253+ off += 1
254+ off += 1
255+ off += 1
256+ off += 1
257+ for i := range v.AllowedDepths {
258+ off += v.AllowedDepths[i].Size()
259+ }
260+ return off
261+}
262+func (v Screen) Put(p []byte) {
263+ off := 0
264+ binary.LittleEndian.PutUint32(p[off:], uint32(v.Root))
265+ off += 4
266+ binary.LittleEndian.PutUint32(p[off:], uint32(v.DefaultColormap))
267+ off += 4
268+ binary.LittleEndian.PutUint32(p[off:], uint32(v.WhitePixel))
269+ off += 4
270+ binary.LittleEndian.PutUint32(p[off:], uint32(v.BlackPixel))
271+ off += 4
272+ binary.LittleEndian.PutUint32(p[off:], uint32(v.CurrentInputMasks))
273+ off += 4
274+ binary.LittleEndian.PutUint16(p[off:], uint16(v.WidthInPixels))
275+ off += 2
276+ binary.LittleEndian.PutUint16(p[off:], uint16(v.HeightInPixels))
277+ off += 2
278+ binary.LittleEndian.PutUint16(p[off:], uint16(v.WidthInMillimeters))
279+ off += 2
280+ binary.LittleEndian.PutUint16(p[off:], uint16(v.HeightInMillimeters))
281+ off += 2
282+ binary.LittleEndian.PutUint16(p[off:], uint16(v.MinInstalledMaps))
283+ off += 2
284+ binary.LittleEndian.PutUint16(p[off:], uint16(v.MaxInstalledMaps))
285+ off += 2
286+ binary.LittleEndian.PutUint32(p[off:], uint32(v.RootVisual))
287+ off += 4
288+ p[off:][0] = byte(v.BackingStores)
289+ off += 1
290+ if v.SaveUnders {
291+ p[off:][0] = 1
292+ } else {
293+ p[off:][0] = 0
294+ }
295+ off += 1
296+ p[off:][0] = byte(v.RootDepth)
297+ off += 1
298+ p[off:][0] = byte(v.AllowedDepthsLen)
299+ off += 1
300+ for i := range v.AllowedDepths {
301+ v.AllowedDepths[i].Put(p[off:])
302+ off += v.AllowedDepths[i].Size()
303+ }
304+}
305+
306+type SetupRequest struct {
307+ ByteOrder uint8
308+ ProtocolMajorVersion uint16
309+ ProtocolMinorVersion uint16
310+ AuthorizationProtocolNameLen uint16
311+ AuthorizationProtocolDataLen uint16
312+ AuthorizationProtocolName string
313+ AuthorizationProtocolData string
314+}
315+
316+const SetupRequestSize = 12
317+
318+func (v SetupRequest) Size() int {
319+ off := 0
320+ off += 1
321+ off += 1
322+ off += 2
323+ off += 2
324+ off += 2
325+ off += 2
326+ off += 2
327+ off += len(v.AuthorizationProtocolName) * 1
328+ off = (off + 3) &^ 3
329+ off += len(v.AuthorizationProtocolData) * 1
330+ off = (off + 3) &^ 3
331+ return off
332+}
333+func (v SetupRequest) Put(p []byte) {
334+ off := 0
335+ p[off:][0] = byte(v.ByteOrder)
336+ off += 1
337+ clear(p[off : off+1])
338+ off += 1
339+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMajorVersion))
340+ off += 2
341+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMinorVersion))
342+ off += 2
343+ binary.LittleEndian.PutUint16(p[off:], uint16(v.AuthorizationProtocolNameLen))
344+ off += 2
345+ binary.LittleEndian.PutUint16(p[off:], uint16(v.AuthorizationProtocolDataLen))
346+ off += 2
347+ clear(p[off : off+2])
348+ off += 2
349+ for i := range v.AuthorizationProtocolName {
350+ p[off+i*1:][0] = byte(v.AuthorizationProtocolName[i])
351+ }
352+ off += len(v.AuthorizationProtocolName) * 1
353+ {
354+ next := (off + 3) &^ 3
355+ clear(p[off:next])
356+ off = next
357+ }
358+ for i := range v.AuthorizationProtocolData {
359+ p[off+i*1:][0] = byte(v.AuthorizationProtocolData[i])
360+ }
361+ off += len(v.AuthorizationProtocolData) * 1
362+ {
363+ next := (off + 3) &^ 3
364+ clear(p[off:next])
365+ off = next
366+ }
367+}
368+
369+type SetupFailed struct {
370+ Status uint8
371+ ReasonLen uint8
372+ ProtocolMajorVersion uint16
373+ ProtocolMinorVersion uint16
374+ Length uint16
375+ Reason string
376+}
377+
378+const SetupFailedSize = 8
379+
380+func (v SetupFailed) Size() int {
381+ off := 0
382+ off += 1
383+ off += 1
384+ off += 2
385+ off += 2
386+ off += 2
387+ off += len(v.Reason) * 1
388+ return off
389+}
390+func (v SetupFailed) Put(p []byte) {
391+ off := 0
392+ p[off:][0] = byte(v.Status)
393+ off += 1
394+ p[off:][0] = byte(v.ReasonLen)
395+ off += 1
396+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMajorVersion))
397+ off += 2
398+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMinorVersion))
399+ off += 2
400+ binary.LittleEndian.PutUint16(p[off:], uint16(v.Length))
401+ off += 2
402+ for i := range v.Reason {
403+ p[off+i*1:][0] = byte(v.Reason[i])
404+ }
405+ off += len(v.Reason) * 1
406+}
407+
408+type SetupAuthenticate struct {
409+ Status uint8
410+ Length uint16
411+ Reason string
412+}
413+
414+const SetupAuthenticateSize = 8
415+
416+func (v SetupAuthenticate) Size() int {
417+ off := 0
418+ off += 1
419+ off += 5
420+ off += 2
421+ off += len(v.Reason) * 1
422+ return off
423+}
424+func (v SetupAuthenticate) Put(p []byte) {
425+ off := 0
426+ p[off:][0] = byte(v.Status)
427+ off += 1
428+ clear(p[off : off+5])
429+ off += 5
430+ binary.LittleEndian.PutUint16(p[off:], uint16(v.Length))
431+ off += 2
432+ for i := range v.Reason {
433+ p[off+i*1:][0] = byte(v.Reason[i])
434+ }
435+ off += len(v.Reason) * 1
436+}
437+
438+type Setup struct {
439+ Status uint8
440+ ProtocolMajorVersion uint16
441+ ProtocolMinorVersion uint16
442+ Length uint16
443+ ReleaseNumber uint32
444+ ResourceIdBase uint32
445+ ResourceIdMask uint32
446+ MotionBufferSize uint32
447+ VendorLen uint16
448+ MaximumRequestLength uint16
449+ RootsLen uint8
450+ PixmapFormatsLen uint8
451+ ImageByteOrder ImageOrder
452+ BitmapFormatBitOrder ImageOrder
453+ BitmapFormatScanlineUnit uint8
454+ BitmapFormatScanlinePad uint8
455+ MinKeycode Keycode
456+ MaxKeycode Keycode
457+ Vendor string
458+ PixmapFormats []Format
459+ Roots []Screen
460+}
461+
462+const SetupSize = 40
463+
464+func (v Setup) Size() int {
465+ off := 0
466+ off += 1
467+ off += 1
468+ off += 2
469+ off += 2
470+ off += 2
471+ off += 4
472+ off += 4
473+ off += 4
474+ off += 4
475+ off += 2
476+ off += 2
477+ off += 1
478+ off += 1
479+ off += 1
480+ off += 1
481+ off += 1
482+ off += 1
483+ off += 1
484+ off += 1
485+ off += 4
486+ off += len(v.Vendor) * 1
487+ off = (off + 3) &^ 3
488+ off += len(v.PixmapFormats) * 8
489+ for i := range v.Roots {
490+ off += v.Roots[i].Size()
491+ }
492+ return off
493+}
494+func (v Setup) Put(p []byte) {
495+ off := 0
496+ p[off:][0] = byte(v.Status)
497+ off += 1
498+ clear(p[off : off+1])
499+ off += 1
500+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMajorVersion))
501+ off += 2
502+ binary.LittleEndian.PutUint16(p[off:], uint16(v.ProtocolMinorVersion))
503+ off += 2
504+ binary.LittleEndian.PutUint16(p[off:], uint16(v.Length))
505+ off += 2
506+ binary.LittleEndian.PutUint32(p[off:], uint32(v.ReleaseNumber))
507+ off += 4
508+ binary.LittleEndian.PutUint32(p[off:], uint32(v.ResourceIdBase))
509+ off += 4
510+ binary.LittleEndian.PutUint32(p[off:], uint32(v.ResourceIdMask))
511+ off += 4
512+ binary.LittleEndian.PutUint32(p[off:], uint32(v.MotionBufferSize))
513+ off += 4
514+ binary.LittleEndian.PutUint16(p[off:], uint16(v.VendorLen))
515+ off += 2
516+ binary.LittleEndian.PutUint16(p[off:], uint16(v.MaximumRequestLength))
517+ off += 2
518+ p[off:][0] = byte(v.RootsLen)
519+ off += 1
520+ p[off:][0] = byte(v.PixmapFormatsLen)
521+ off += 1
522+ p[off:][0] = byte(v.ImageByteOrder)
523+ off += 1
524+ p[off:][0] = byte(v.BitmapFormatBitOrder)
525+ off += 1
526+ p[off:][0] = byte(v.BitmapFormatScanlineUnit)
527+ off += 1
528+ p[off:][0] = byte(v.BitmapFormatScanlinePad)
529+ off += 1
530+ p[off:][0] = byte(v.MinKeycode)
531+ off += 1
532+ p[off:][0] = byte(v.MaxKeycode)
533+ off += 1
534+ clear(p[off : off+4])
535+ off += 4
536+ for i := range v.Vendor {
537+ p[off+i*1:][0] = byte(v.Vendor[i])
538+ }
539+ off += len(v.Vendor) * 1
540+ {
541+ next := (off + 3) &^ 3
542+ clear(p[off:next])
543+ off = next
544+ }
545+ for i := range v.PixmapFormats {
546+ v.PixmapFormats[i].Put(p[off+i*8:])
547+ }
548+ off += len(v.PixmapFormats) * 8
549+ for i := range v.Roots {
550+ v.Roots[i].Put(p[off:])
551+ off += v.Roots[i].Size()
552+ }
553+}
554+
555+type ClientMessageData struct{ raw []byte }
556+
557+const ClientMessageDataSize = 20
558+
559+func GetClientMessageData(p []byte) ClientMessageData { return ClientMessageData{raw: p[:20]} }
560+func (v ClientMessageData) Put(p []byte) { copy(p[:20], v.raw) }
561+func (v ClientMessageData) Data8() (out [20]uint8) {
562+ for i := range out {
563+ out[i] = uint8(v.raw[i*1:][0])
564+ }
565+ return
566+}
567+func (v ClientMessageData) Data16() (out [10]uint16) {
568+ for i := range out {
569+ out[i] = uint16(binary.LittleEndian.Uint16(v.raw[i*2:]))
570+ }
571+ return
572+}
573+func (v ClientMessageData) Data32() (out [5]uint32) {
574+ for i := range out {
575+ out[i] = uint32(binary.LittleEndian.Uint32(v.raw[i*4:]))
576+ }
577+ return
578+}
579+
580+type Timecoord struct {
581+ Time Timestamp
582+ X int16
583+ Y int16
584+}
585+
586+const TimecoordSize = 8
587+
588+func (v Timecoord) Put(p []byte) {
589+ clear(p[:8])
590+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Time))
591+ binary.LittleEndian.PutUint16(p[4:], uint16(v.X))
592+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Y))
593+}
594+func GetTimecoord(p []byte) (v Timecoord) {
595+ _ = p[7]
596+ v.Time = Timestamp(binary.LittleEndian.Uint32(p[0:]))
597+ v.X = int16(binary.LittleEndian.Uint16(p[4:]))
598+ v.Y = int16(binary.LittleEndian.Uint16(p[6:]))
599+ return
600+}
601+
602+type Fontprop struct {
603+ Name Atom
604+ Value uint32
605+}
606+
607+const FontpropSize = 8
608+
609+func (v Fontprop) Put(p []byte) {
610+ clear(p[:8])
611+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Name))
612+ binary.LittleEndian.PutUint32(p[4:], uint32(v.Value))
613+}
614+func GetFontprop(p []byte) (v Fontprop) {
615+ _ = p[7]
616+ v.Name = Atom(binary.LittleEndian.Uint32(p[0:]))
617+ v.Value = uint32(binary.LittleEndian.Uint32(p[4:]))
618+ return
619+}
620+
621+type Charinfo struct {
622+ LeftSideBearing int16
623+ RightSideBearing int16
624+ CharacterWidth int16
625+ Ascent int16
626+ Descent int16
627+ Attributes uint16
628+}
629+
630+const CharinfoSize = 12
631+
632+func (v Charinfo) Put(p []byte) {
633+ clear(p[:12])
634+ binary.LittleEndian.PutUint16(p[0:], uint16(v.LeftSideBearing))
635+ binary.LittleEndian.PutUint16(p[2:], uint16(v.RightSideBearing))
636+ binary.LittleEndian.PutUint16(p[4:], uint16(v.CharacterWidth))
637+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Ascent))
638+ binary.LittleEndian.PutUint16(p[8:], uint16(v.Descent))
639+ binary.LittleEndian.PutUint16(p[10:], uint16(v.Attributes))
640+}
641+func GetCharinfo(p []byte) (v Charinfo) {
642+ _ = p[11]
643+ v.LeftSideBearing = int16(binary.LittleEndian.Uint16(p[0:]))
644+ v.RightSideBearing = int16(binary.LittleEndian.Uint16(p[2:]))
645+ v.CharacterWidth = int16(binary.LittleEndian.Uint16(p[4:]))
646+ v.Ascent = int16(binary.LittleEndian.Uint16(p[6:]))
647+ v.Descent = int16(binary.LittleEndian.Uint16(p[8:]))
648+ v.Attributes = uint16(binary.LittleEndian.Uint16(p[10:]))
649+ return
650+}
651+
652+type Str struct {
653+ NameLen uint8
654+ Name string
655+}
656+
657+const StrSize = 1
658+
659+func (v Str) Size() int { off := 0; off += 1; off += len(v.Name) * 1; return off }
660+func (v Str) Put(p []byte) {
661+ off := 0
662+ p[off:][0] = byte(v.NameLen)
663+ off += 1
664+ for i := range v.Name {
665+ p[off+i*1:][0] = byte(v.Name[i])
666+ }
667+ off += len(v.Name) * 1
668+}
669+
670+type Segment struct {
671+ X1 int16
672+ Y1 int16
673+ X2 int16
674+ Y2 int16
675+}
676+
677+const SegmentSize = 8
678+
679+func (v Segment) Put(p []byte) {
680+ clear(p[:8])
681+ binary.LittleEndian.PutUint16(p[0:], uint16(v.X1))
682+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Y1))
683+ binary.LittleEndian.PutUint16(p[4:], uint16(v.X2))
684+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Y2))
685+}
686+func GetSegment(p []byte) (v Segment) {
687+ _ = p[7]
688+ v.X1 = int16(binary.LittleEndian.Uint16(p[0:]))
689+ v.Y1 = int16(binary.LittleEndian.Uint16(p[2:]))
690+ v.X2 = int16(binary.LittleEndian.Uint16(p[4:]))
691+ v.Y2 = int16(binary.LittleEndian.Uint16(p[6:]))
692+ return
693+}
694+
695+type Coloritem struct {
696+ Pixel uint32
697+ Red uint16
698+ Green uint16
699+ Blue uint16
700+ Flags ColorFlag
701+}
702+
703+const ColoritemSize = 12
704+
705+func (v Coloritem) Put(p []byte) {
706+ clear(p[:12])
707+ binary.LittleEndian.PutUint32(p[0:], uint32(v.Pixel))
708+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Red))
709+ binary.LittleEndian.PutUint16(p[6:], uint16(v.Green))
710+ binary.LittleEndian.PutUint16(p[8:], uint16(v.Blue))
711+ p[10:][0] = byte(v.Flags)
712+}
713+func GetColoritem(p []byte) (v Coloritem) {
714+ _ = p[11]
715+ v.Pixel = uint32(binary.LittleEndian.Uint32(p[0:]))
716+ v.Red = uint16(binary.LittleEndian.Uint16(p[4:]))
717+ v.Green = uint16(binary.LittleEndian.Uint16(p[6:]))
718+ v.Blue = uint16(binary.LittleEndian.Uint16(p[8:]))
719+ v.Flags = ColorFlag(p[10:][0])
720+ return
721+}
722+
723+type Rgb struct {
724+ Red uint16
725+ Green uint16
726+ Blue uint16
727+}
728+
729+const RgbSize = 8
730+
731+func (v Rgb) Put(p []byte) {
732+ clear(p[:8])
733+ binary.LittleEndian.PutUint16(p[0:], uint16(v.Red))
734+ binary.LittleEndian.PutUint16(p[2:], uint16(v.Green))
735+ binary.LittleEndian.PutUint16(p[4:], uint16(v.Blue))
736+}
737+func GetRgb(p []byte) (v Rgb) {
738+ _ = p[7]
739+ v.Red = uint16(binary.LittleEndian.Uint16(p[0:]))
740+ v.Green = uint16(binary.LittleEndian.Uint16(p[2:]))
741+ v.Blue = uint16(binary.LittleEndian.Uint16(p[4:]))
742+ return
743+}
744+
745+type Host struct {
746+ Family Family
747+ AddressLen uint16
748+ Address []byte
749+}
750+
751+const HostSize = 4
752+
753+func (v Host) Size() int {
754+ off := 0
755+ off += 1
756+ off += 1
757+ off += 2
758+ off += len(v.Address) * 1
759+ off = (off + 3) &^ 3
760+ return off
761+}
762+func (v Host) Put(p []byte) {
763+ off := 0
764+ p[off:][0] = byte(v.Family)
765+ off += 1
766+ clear(p[off : off+1])
767+ off += 1
768+ binary.LittleEndian.PutUint16(p[off:], uint16(v.AddressLen))
769+ off += 2
770+ for i := range v.Address {
771+ p[off+i*1:][0] = byte(v.Address[i])
772+ }
773+ off += len(v.Address) * 1
774+ {
775+ next := (off + 3) &^ 3
776+ clear(p[off:next])
777+ off = next
778+ }
779+}
780+
781+type VisualClass uint8
782+
783+const VisualClassStaticGray VisualClass = 0
784+const VisualClassGrayScale VisualClass = 1
785+const VisualClassStaticColor VisualClass = 2
786+const VisualClassPseudoColor VisualClass = 3
787+const VisualClassTrueColor VisualClass = 4
788+const VisualClassDirectColor VisualClass = 5
789+
790+type EventMask uint32
791+
792+const EventMaskNoEvent EventMask = 0
793+const EventMaskKeyPress EventMask = 1
794+const EventMaskKeyRelease EventMask = 2
795+const EventMaskButtonPress EventMask = 4
796+const EventMaskButtonRelease EventMask = 8
797+const EventMaskEnterWindow EventMask = 16
798+const EventMaskLeaveWindow EventMask = 32
799+const EventMaskPointerMotion EventMask = 64
800+const EventMaskPointerMotionHint EventMask = 128
801+const EventMaskButton1Motion EventMask = 256
802+const EventMaskButton2Motion EventMask = 512
803+const EventMaskButton3Motion EventMask = 1024
804+const EventMaskButton4Motion EventMask = 2048
805+const EventMaskButton5Motion EventMask = 4096
806+const EventMaskButtonMotion EventMask = 8192
807+const EventMaskKeymapState EventMask = 16384
808+const EventMaskExposure EventMask = 32768
809+const EventMaskVisibilityChange EventMask = 65536
810+const EventMaskStructureNotify EventMask = 131072
811+const EventMaskResizeRedirect EventMask = 262144
812+const EventMaskSubstructureNotify EventMask = 524288
813+const EventMaskSubstructureRedirect EventMask = 1048576
814+const EventMaskFocusChange EventMask = 2097152
815+const EventMaskPropertyChange EventMask = 4194304
816+const EventMaskColorMapChange EventMask = 8388608
817+const EventMaskOwnerGrabButton EventMask = 16777216
818+
819+type BackingStore uint32
820+
821+const BackingStoreNotUseful BackingStore = 0
822+const BackingStoreWhenMapped BackingStore = 1
823+const BackingStoreAlways BackingStore = 2
824+
825+type ImageOrder uint8
826+
827+const ImageOrderLSBFirst ImageOrder = 0
828+const ImageOrderMSBFirst ImageOrder = 1
829+
830+type ModMask uint16
831+
832+const ModMaskShift ModMask = 1
833+const ModMaskLock ModMask = 2
834+const ModMaskControl ModMask = 4
835+const ModMaskX1 ModMask = 8
836+const ModMaskX2 ModMask = 16
837+const ModMaskX3 ModMask = 32
838+const ModMaskX4 ModMask = 64
839+const ModMaskX5 ModMask = 128
840+const ModMaskAny ModMask = 32768
841+
842+type KeyButMask uint16
843+
844+const KeyButMaskShift KeyButMask = 1
845+const KeyButMaskLock KeyButMask = 2
846+const KeyButMaskControl KeyButMask = 4
847+const KeyButMaskMod1 KeyButMask = 8
848+const KeyButMaskMod2 KeyButMask = 16
849+const KeyButMaskMod3 KeyButMask = 32
850+const KeyButMaskMod4 KeyButMask = 64
851+const KeyButMaskMod5 KeyButMask = 128
852+const KeyButMaskButton1 KeyButMask = 256
853+const KeyButMaskButton2 KeyButMask = 512
854+const KeyButMaskButton3 KeyButMask = 1024
855+const KeyButMaskButton4 KeyButMask = 2048
856+const KeyButMaskButton5 KeyButMask = 4096
857+
858+const WindowNone Window = 0
859+
860+type ButtonMask uint32
861+
862+const ButtonMaskX1 ButtonMask = 256
863+const ButtonMaskX2 ButtonMask = 512
864+const ButtonMaskX3 ButtonMask = 1024
865+const ButtonMaskX4 ButtonMask = 2048
866+const ButtonMaskX5 ButtonMask = 4096
867+const ButtonMaskAny ButtonMask = 32768
868+
869+type Motion uint8
870+
871+const MotionNormal Motion = 0
872+const MotionHint Motion = 1
873+
874+type NotifyDetail uint8
875+
876+const NotifyDetailAncestor NotifyDetail = 0
877+const NotifyDetailVirtual NotifyDetail = 1
878+const NotifyDetailInferior NotifyDetail = 2
879+const NotifyDetailNonlinear NotifyDetail = 3
880+const NotifyDetailNonlinearVirtual NotifyDetail = 4
881+const NotifyDetailPointer NotifyDetail = 5
882+const NotifyDetailPointerRoot NotifyDetail = 6
883+const NotifyDetailNone NotifyDetail = 7
884+
885+type NotifyMode uint8
886+
887+const NotifyModeNormal NotifyMode = 0
888+const NotifyModeGrab NotifyMode = 1
889+const NotifyModeUngrab NotifyMode = 2
890+const NotifyModeWhileGrabbed NotifyMode = 3
891+
892+type Visibility uint8
893+
894+const VisibilityUnobscured Visibility = 0
895+const VisibilityPartiallyObscured Visibility = 1
896+const VisibilityFullyObscured Visibility = 2
897+
898+type Place uint8
899+
900+const PlaceOnTop Place = 0
901+const PlaceOnBottom Place = 1
902+
903+type Property uint8
904+
905+const PropertyNewValue Property = 0
906+const PropertyDelete Property = 1
907+
908+type Time uint32
909+
910+const TimeCurrentTime Time = 0
911+
912+const AtomNone Atom = 0
913+const AtomAny Atom = 0
914+const AtomPrimary Atom = 1
915+const AtomSecondary Atom = 2
916+const AtomArc Atom = 3
917+const AtomAtom Atom = 4
918+const AtomBitmap Atom = 5
919+const AtomCardinal Atom = 6
920+const AtomColormap Atom = 7
921+const AtomCursor Atom = 8
922+const AtomCutBuffer0 Atom = 9
923+const AtomCutBuffer1 Atom = 10
924+const AtomCutBuffer2 Atom = 11
925+const AtomCutBuffer3 Atom = 12
926+const AtomCutBuffer4 Atom = 13
927+const AtomCutBuffer5 Atom = 14
928+const AtomCutBuffer6 Atom = 15
929+const AtomCutBuffer7 Atom = 16
930+const AtomDrawable Atom = 17
931+const AtomFont Atom = 18
932+const AtomInteger Atom = 19
933+const AtomPixmap Atom = 20
934+const AtomPoint Atom = 21
935+const AtomRectangle Atom = 22
936+const AtomResourceManager Atom = 23
937+const AtomRgbColorMap Atom = 24
938+const AtomRgbBestMap Atom = 25
939+const AtomRgbBlueMap Atom = 26
940+const AtomRgbDefaultMap Atom = 27
941+const AtomRgbGrayMap Atom = 28
942+const AtomRgbGreenMap Atom = 29
943+const AtomRgbRedMap Atom = 30
944+const AtomString Atom = 31
945+const AtomVisualid Atom = 32
946+const AtomWindow Atom = 33
947+const AtomWmCommand Atom = 34
948+const AtomWmHints Atom = 35
949+const AtomWmClientMachine Atom = 36
950+const AtomWmIconName Atom = 37
951+const AtomWmIconSize Atom = 38
952+const AtomWmName Atom = 39
953+const AtomWmNormalHints Atom = 40
954+const AtomWmSizeHints Atom = 41
955+const AtomWmZoomHints Atom = 42
956+const AtomMinSpace Atom = 43
957+const AtomNormSpace Atom = 44
958+const AtomMaxSpace Atom = 45
959+const AtomEndSpace Atom = 46
960+const AtomSuperscriptX Atom = 47
961+const AtomSuperscriptY Atom = 48
962+const AtomSubscriptX Atom = 49
963+const AtomSubscriptY Atom = 50
964+const AtomUnderlinePosition Atom = 51
965+const AtomUnderlineThickness Atom = 52
966+const AtomStrikeoutAscent Atom = 53
967+const AtomStrikeoutDescent Atom = 54
968+const AtomItalicAngle Atom = 55
969+const AtomXHeight Atom = 56
970+const AtomQuadWidth Atom = 57
971+const AtomWeight Atom = 58
972+const AtomPointSize Atom = 59
973+const AtomResolution Atom = 60
974+const AtomCopyright Atom = 61
975+const AtomNotice Atom = 62
976+const AtomFontName Atom = 63
977+const AtomFamilyName Atom = 64
978+const AtomFullName Atom = 65
979+const AtomCapHeight Atom = 66
980+const AtomWmClass Atom = 67
981+const AtomWmTransientFor Atom = 68
982+
983+type ColormapState uint8
984+
985+const ColormapStateUninstalled ColormapState = 0
986+const ColormapStateInstalled ColormapState = 1
987+
988+const ColormapNone Colormap = 0
989+
990+type Mapping uint8
991+
992+const MappingModifier Mapping = 0
993+const MappingKeyboard Mapping = 1
994+const MappingPointer Mapping = 2
995+
996+type WindowClass uint16
997+
998+const WindowClassCopyFromParent WindowClass = 0
999+const WindowClassInputOutput WindowClass = 1
1000+const WindowClassInputOnly WindowClass = 2
1001+
1002+type Cw uint32
1003+
1004+const CwBackPixmap Cw = 1
1005+const CwBackPixel Cw = 2
1006+const CwBorderPixmap Cw = 4
1007+const CwBorderPixel Cw = 8
1008+const CwBitGravity Cw = 16
1009+const CwWinGravity Cw = 32
1010+const CwBackingStore Cw = 64
1011+const CwBackingPlanes Cw = 128
1012+const CwBackingPixel Cw = 256
1013+const CwOverrideRedirect Cw = 512
1014+const CwSaveUnder Cw = 1024
1015+const CwEventMask Cw = 2048
1016+const CwDontPropagate Cw = 4096
1017+const CwColormap Cw = 8192
1018+const CwCursor Cw = 16384
1019+
1020+type BackPixmap uint32
1021+
1022+const BackPixmapNone BackPixmap = 0
1023+const BackPixmapParentRelative BackPixmap = 1
1024+
1025+type Gravity uint32
1026+
1027+const GravityBitForget Gravity = 0
1028+const GravityWinUnmap Gravity = 0
1029+const GravityNorthWest Gravity = 1
1030+const GravityNorth Gravity = 2
1031+const GravityNorthEast Gravity = 3
1032+const GravityWest Gravity = 4
1033+const GravityCenter Gravity = 5
1034+const GravityEast Gravity = 6
1035+const GravitySouthWest Gravity = 7
1036+const GravitySouth Gravity = 8
1037+const GravitySouthEast Gravity = 9
1038+const GravityStatic Gravity = 10
1039+
1040+type MapState uint8
1041+
1042+const MapStateUnmapped MapState = 0
1043+const MapStateUnviewable MapState = 1
1044+const MapStateViewable MapState = 2
1045+
1046+type SetMode uint8
1047+
1048+const SetModeInsert SetMode = 0
1049+const SetModeDelete SetMode = 1
1050+
1051+type ConfigWindow uint16
1052+
1053+const ConfigWindowX ConfigWindow = 1
1054+const ConfigWindowY ConfigWindow = 2
1055+const ConfigWindowWidth ConfigWindow = 4
1056+const ConfigWindowHeight ConfigWindow = 8
1057+const ConfigWindowBorderWidth ConfigWindow = 16
1058+const ConfigWindowSibling ConfigWindow = 32
1059+const ConfigWindowStackMode ConfigWindow = 64
1060+
1061+type StackMode uint32
1062+
1063+const StackModeAbove StackMode = 0
1064+const StackModeBelow StackMode = 1
1065+const StackModeTopIf StackMode = 2
1066+const StackModeBottomIf StackMode = 3
1067+const StackModeOpposite StackMode = 4
1068+
1069+type Circulate uint8
1070+
1071+const CirculateRaiseLowest Circulate = 0
1072+const CirculateLowerHighest Circulate = 1
1073+
1074+type PropMode uint8
1075+
1076+const PropModeReplace PropMode = 0
1077+const PropModePrepend PropMode = 1
1078+const PropModeAppend PropMode = 2
1079+
1080+type GetPropertyType uint32
1081+
1082+const GetPropertyTypeAny GetPropertyType = 0
1083+
1084+type SendEventDest uint32
1085+
1086+const SendEventDestPointerWindow SendEventDest = 0
1087+const SendEventDestItemFocus SendEventDest = 1
1088+
1089+type GrabMode uint8
1090+
1091+const GrabModeSync GrabMode = 0
1092+const GrabModeAsync GrabMode = 1
1093+
1094+type GrabStatus uint8
1095+
1096+const GrabStatusSuccess GrabStatus = 0
1097+const GrabStatusAlreadyGrabbed GrabStatus = 1
1098+const GrabStatusInvalidTime GrabStatus = 2
1099+const GrabStatusNotViewable GrabStatus = 3
1100+const GrabStatusFrozen GrabStatus = 4
1101+
1102+const CursorNone Cursor = 0
1103+
1104+type ButtonIndex uint8
1105+
1106+const ButtonIndexAny ButtonIndex = 0
1107+const ButtonIndexX1 ButtonIndex = 1
1108+const ButtonIndexX2 ButtonIndex = 2
1109+const ButtonIndexX3 ButtonIndex = 3
1110+const ButtonIndexX4 ButtonIndex = 4
1111+const ButtonIndexX5 ButtonIndex = 5
1112+
1113+type Grab uint8
1114+
1115+const GrabAny Grab = 0
1116+
1117+type Allow uint8
1118+
1119+const AllowAsyncPointer Allow = 0
1120+const AllowSyncPointer Allow = 1
1121+const AllowReplayPointer Allow = 2
1122+const AllowAsyncKeyboard Allow = 3
1123+const AllowSyncKeyboard Allow = 4
1124+const AllowReplayKeyboard Allow = 5
1125+const AllowAsyncBoth Allow = 6
1126+const AllowSyncBoth Allow = 7
1127+
1128+type InputFocus uint32
1129+
1130+const InputFocusNone InputFocus = 0
1131+const InputFocusPointerRoot InputFocus = 1
1132+const InputFocusParent InputFocus = 2
1133+const InputFocusFollowKeyboard InputFocus = 3
1134+
1135+type FontDraw uint8
1136+
1137+const FontDrawLeftToRight FontDraw = 0
1138+const FontDrawRightToLeft FontDraw = 1
1139+
1140+type Gc uint32
1141+
1142+const GcFunction Gc = 1
1143+const GcPlaneMask Gc = 2
1144+const GcForeground Gc = 4
1145+const GcBackground Gc = 8
1146+const GcLineWidth Gc = 16
1147+const GcLineStyle Gc = 32
1148+const GcCapStyle Gc = 64
1149+const GcJoinStyle Gc = 128
1150+const GcFillStyle Gc = 256
1151+const GcFillRule Gc = 512
1152+const GcTile Gc = 1024
1153+const GcStipple Gc = 2048
1154+const GcTileStippleOriginX Gc = 4096
1155+const GcTileStippleOriginY Gc = 8192
1156+const GcFont Gc = 16384
1157+const GcSubwindowMode Gc = 32768
1158+const GcGraphicsExposures Gc = 65536
1159+const GcClipOriginX Gc = 131072
1160+const GcClipOriginY Gc = 262144
1161+const GcClipMask Gc = 524288
1162+const GcDashOffset Gc = 1048576
1163+const GcDashList Gc = 2097152
1164+const GcArcMode Gc = 4194304
1165+
1166+type Gx uint32
1167+
1168+const GxClear Gx = 0
1169+const GxAnd Gx = 1
1170+const GxAndReverse Gx = 2
1171+const GxCopy Gx = 3
1172+const GxAndInverted Gx = 4
1173+const GxNoop Gx = 5
1174+const GxXor Gx = 6
1175+const GxOr Gx = 7
1176+const GxNor Gx = 8
1177+const GxEquiv Gx = 9
1178+const GxInvert Gx = 10
1179+const GxOrReverse Gx = 11
1180+const GxCopyInverted Gx = 12
1181+const GxOrInverted Gx = 13
1182+const GxNand Gx = 14
1183+const GxSet Gx = 15
1184+
1185+type LineStyle uint32
1186+
1187+const LineStyleSolid LineStyle = 0
1188+const LineStyleOnOffDash LineStyle = 1
1189+const LineStyleDoubleDash LineStyle = 2
1190+
1191+type CapStyle uint32
1192+
1193+const CapStyleNotLast CapStyle = 0
1194+const CapStyleButt CapStyle = 1
1195+const CapStyleRound CapStyle = 2
1196+const CapStyleProjecting CapStyle = 3
1197+
1198+type JoinStyle uint32
1199+
1200+const JoinStyleMiter JoinStyle = 0
1201+const JoinStyleRound JoinStyle = 1
1202+const JoinStyleBevel JoinStyle = 2
1203+
1204+type FillStyle uint32
1205+
1206+const FillStyleSolid FillStyle = 0
1207+const FillStyleTiled FillStyle = 1
1208+const FillStyleStippled FillStyle = 2
1209+const FillStyleOpaqueStippled FillStyle = 3
1210+
1211+type FillRule uint32
1212+
1213+const FillRuleEvenOdd FillRule = 0
1214+const FillRuleWinding FillRule = 1
1215+
1216+type SubwindowMode uint32
1217+
1218+const SubwindowModeClipByChildren SubwindowMode = 0
1219+const SubwindowModeIncludeInferiors SubwindowMode = 1
1220+
1221+type ArcMode uint32
1222+
1223+const ArcModeChord ArcMode = 0
1224+const ArcModePieSlice ArcMode = 1
1225+
1226+type ClipOrdering uint8
1227+
1228+const ClipOrderingUnsorted ClipOrdering = 0
1229+const ClipOrderingYSorted ClipOrdering = 1
1230+const ClipOrderingYXSorted ClipOrdering = 2
1231+const ClipOrderingYXBanded ClipOrdering = 3
1232+
1233+type CoordMode uint8
1234+
1235+const CoordModeOrigin CoordMode = 0
1236+const CoordModePrevious CoordMode = 1
1237+
1238+type PolyShape uint8
1239+
1240+const PolyShapeComplex PolyShape = 0
1241+const PolyShapeNonconvex PolyShape = 1
1242+const PolyShapeConvex PolyShape = 2
1243+
1244+type ImageFormat uint8
1245+
1246+const ImageFormatXYBitmap ImageFormat = 0
1247+const ImageFormatXYPixmap ImageFormat = 1
1248+const ImageFormatZPixmap ImageFormat = 2
1249+
1250+type ColormapAlloc uint8
1251+
1252+const ColormapAllocNone ColormapAlloc = 0
1253+const ColormapAllocAll ColormapAlloc = 1
1254+
1255+type ColorFlag uint8
1256+
1257+const ColorFlagRed ColorFlag = 1
1258+const ColorFlagGreen ColorFlag = 2
1259+const ColorFlagBlue ColorFlag = 4
1260+
1261+const PixmapNone Pixmap = 0
1262+
1263+const FontNone Font = 0
1264+
1265+type QueryShapeOf uint8
1266+
1267+const QueryShapeOfLargestCursor QueryShapeOf = 0
1268+const QueryShapeOfFastestTile QueryShapeOf = 1
1269+const QueryShapeOfFastestStipple QueryShapeOf = 2
1270+
1271+type Kb uint32
1272+
1273+const KbKeyClickPercent Kb = 1
1274+const KbBellPercent Kb = 2
1275+const KbBellPitch Kb = 4
1276+const KbBellDuration Kb = 8
1277+const KbLed Kb = 16
1278+const KbLedMode Kb = 32
1279+const KbKey Kb = 64
1280+const KbAutoRepeatMode Kb = 128
1281+
1282+type LedMode uint32
1283+
1284+const LedModeOff LedMode = 0
1285+const LedModeOn LedMode = 1
1286+
1287+type AutoRepeatMode uint32
1288+
1289+const AutoRepeatModeOff AutoRepeatMode = 0
1290+const AutoRepeatModeOn AutoRepeatMode = 1
1291+const AutoRepeatModeDefault AutoRepeatMode = 2
1292+
1293+type Blanking uint8
1294+
1295+const BlankingNotPreferred Blanking = 0
1296+const BlankingPreferred Blanking = 1
1297+const BlankingDefault Blanking = 2
1298+
1299+type Exposures uint8
1300+
1301+const ExposuresNotAllowed Exposures = 0
1302+const ExposuresAllowed Exposures = 1
1303+const ExposuresDefault Exposures = 2
1304+
1305+type HostMode uint8
1306+
1307+const HostModeInsert HostMode = 0
1308+const HostModeDelete HostMode = 1
1309+
1310+type Family uint8
1311+
1312+const FamilyInternet Family = 0
1313+const FamilyDECnet Family = 1
1314+const FamilyChaos Family = 2
1315+const FamilyServerInterpreted Family = 5
1316+const FamilyInternet6 Family = 6
1317+
1318+type AccessControl uint8
1319+
1320+const AccessControlDisable AccessControl = 0
1321+const AccessControlEnable AccessControl = 1
1322+
1323+type CloseDown uint8
1324+
1325+const CloseDownDestroyAll CloseDown = 0
1326+const CloseDownRetainPermanent CloseDown = 1
1327+const CloseDownRetainTemporary CloseDown = 2
1328+
1329+type Kill uint32
1330+
1331+const KillAllTemporary Kill = 0
1332+
1333+type ScreenSaver uint8
1334+
1335+const ScreenSaverReset ScreenSaver = 0
1336+const ScreenSaverActive ScreenSaver = 1
1337+
1338+type MappingStatus uint8
1339+
1340+const MappingStatusSuccess MappingStatus = 0
1341+const MappingStatusBusy MappingStatus = 1
1342+const MappingStatusFailure MappingStatus = 2
1343+
1344+type MapIndex uint32
1345+
1346+const MapIndexShift MapIndex = 0
1347+const MapIndexLock MapIndex = 1
1348+const MapIndexControl MapIndex = 2
1349+const MapIndexX1 MapIndex = 3
1350+const MapIndexX2 MapIndex = 4
1351+const MapIndexX3 MapIndex = 5
1352+const MapIndexX4 MapIndex = 6
1353+const MapIndexX5 MapIndex = 7
A xproto/types_test.go +54 -0
@@ -0,0 +1,54 @@
1+package xproto
2+
3+import (
4+ "encoding/binary"
5+ "testing"
6+)
7+
8+func TestRectangleWire(t *testing.T) {
9+ v := Rectangle{X: -2, Y: 3, Width: 640, Height: 480}
10+ var p [8]byte
11+ v.Put(p[:])
12+ want := [8]byte{254, 255, 3, 0, 128, 2, 224, 1}
13+ if p != want || GetRectangle(p[:]) != v {
14+ t.Fatalf("wire %x", p)
15+ }
16+}
17+func TestVariableStructWire(t *testing.T) {
18+ v := Str{NameLen: 3, Name: "abc"}
19+ p := make([]byte, v.Size())
20+ v.Put(p)
21+ if string(p) != "\x03abc" {
22+ t.Fatalf("wire %x", p)
23+ }
24+ s := SetupRequest{ByteOrder: 'l', ProtocolMajorVersion: 11, AuthorizationProtocolNameLen: 1, AuthorizationProtocolDataLen: 2, AuthorizationProtocolName: "a", AuthorizationProtocolData: "bc"}
25+ p = make([]byte, s.Size())
26+ s.Put(p)
27+ if len(p) != 20 || p[12] != 'a' || p[16] != 'b' || p[17] != 'c' || p[19] != 0 {
28+ t.Fatalf("aligned setup %x", p)
29+ }
30+}
31+func TestUnionView(t *testing.T) {
32+ var p [20]byte
33+ binary.LittleEndian.PutUint32(p[:], 0x12345678)
34+ v := GetClientMessageData(p[:])
35+ if v.Data8()[0] != 0x78 || v.Data16()[0] != 0x5678 || v.Data32()[0] != 0x12345678 {
36+ t.Fatal("union members")
37+ }
38+}
39+func TestAllocStructPut(t *testing.T) {
40+ v := Rectangle{Width: 10}
41+ var p [8]byte
42+ if n := testing.AllocsPerRun(1000, func() { v.Put(p[:]); _ = GetRectangle(p[:]) }); n != 0 {
43+ t.Fatal(n)
44+ }
45+}
46+
47+func BenchmarkRectanglePut(b *testing.B) {
48+ v := Rectangle{Width: 640, Height: 480}
49+ var p [8]byte
50+ b.ReportAllocs()
51+ for b.Loop() {
52+ v.Put(p[:])
53+ }
54+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 1

↑↓ moveenter openesc close