detached 245a75f

Merge 8e6fe5c385ec0c7334a5b626149497024cd03110 into ba4ad521151d3500de111a037937f8e1dd3922d2

commit
245a75f5944bb161f0e10aad625328f961691f63
author
ermite · · 2026-10-22 06:23 UTC
merge of
ba4ad52 + 8e6fe5c · diff against the first parent
signature
unsigned
56 files · +7040 -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 @@
11 // Command xtgen generates bindings from the pinned xcb-proto XML.
22 package main
33
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 +182 -0
@@ -0,0 +1,182 @@
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+}
18+
19+// resolveRequests implements the fixed-body subset. Lists and value lists are
20+// deliberately left in the AST for T2.4/T2.5, not emitted as incomplete APIs.
21+func resolveRequests(m *Module) ([]Request, error) {
22+ var out []Request
23+ for _, n := range m.Root.Children {
24+ if n.Kind != "request" {
25+ continue
26+ }
27+ supported := true
28+ for _, f := range n.Children {
29+ if f.Kind == "list" || f.Kind == "switch" {
30+ supported = false
31+ }
32+ }
33+ if !supported {
34+ continue
35+ }
36+ name := goName(n.Attr["name"])
37+ if err := m.claim(name, n); err != nil {
38+ return nil, err
39+ }
40+ opcode, _ := strconv.Atoi(n.Attr["opcode"])
41+ r := Request{Name: name, Opcode: uint8(opcode), Node: n}
42+ off := 4
43+ first := true
44+ for _, n := range n.Children {
45+ if n.Kind == "reply" || n.Kind == "doc" {
46+ continue
47+ }
48+ f := Field{Name: goName(n.Attr["name"]), Param: paramName(n.Attr["name"]), Kind: n.Kind, Node: n, Off: off - 4}
49+ if n.Kind == "pad" {
50+ if n.Attr["align"] != "" {
51+ a, _ := strconv.Atoi(n.Attr["align"])
52+ f.Size = (-off) & (a - 1)
53+ } else {
54+ f.Size, _ = strconv.Atoi(n.Attr["bytes"])
55+ }
56+ } else {
57+ typ, err := lookup(m, n.Attr["type"])
58+ if err != nil {
59+ return nil, n.fail("%v", err)
60+ }
61+ if typ.Variable {
62+ return nil, n.fail("variable field requires list support")
63+ }
64+ f.Type = typ
65+ f.Size = typ.Size
66+ f.GoType = qualified(m, typ.Module, typ.GoType)
67+ if enum := n.Attr["enum"]; enum != "" {
68+ e, owner := findEnum(m, enum)
69+ if e == nil {
70+ return nil, n.fail("unknown enum %s", enum)
71+ }
72+ f.GoType = qualified(m, owner, e.Name)
73+ }
74+ if mask := n.Attr["mask"]; mask != "" {
75+ e, owner := findEnum(m, mask)
76+ if e == nil {
77+ return nil, n.fail("unknown mask %s", mask)
78+ }
79+ f.GoType = qualified(m, owner, e.Name)
80+ }
81+ if n.Kind == "field" {
82+ r.Params = append(r.Params, f)
83+ }
84+ if n.Kind == "exprfield" {
85+ f.Expr = n.Children[0]
86+ }
87+ }
88+ // Core's first XML byte is header byte 1; extensions have no data byte.
89+ if first && m.ExtName == "" {
90+ if f.Size != 1 {
91+ return nil, n.fail("core request first member must occupy header data byte")
92+ }
93+ if f.Kind != "pad" {
94+ copy := f
95+ r.DataByte = &copy
96+ }
97+ first = false
98+ continue
99+ }
100+ first = false
101+ r.Fields = append(r.Fields, f)
102+ off += f.Size
103+ }
104+ r.Fixed = (off - 4 + 3) &^ 3
105+ out = append(out, r)
106+ }
107+ return out, nil
108+}
109+func requestDecl(m *Module, r Request) (string, error) {
110+ var b strings.Builder
111+ fmt.Fprintf(&b, "func %s(b *xturbo.Buf", r.Name)
112+ for _, p := range r.Params {
113+ fmt.Fprintf(&b, ", %s %s", p.Param, p.GoType)
114+ }
115+ b.WriteString(") xturbo.Seq {\n")
116+ major := fmt.Sprint(r.Opcode)
117+ data := "0"
118+ if m.ExtName != "" {
119+ 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)
120+ major = "major"
121+ data = fmt.Sprint(r.Opcode)
122+ } else if r.DataByte != nil {
123+ f := r.DataByte
124+ if f.Type.Base == "bool" {
125+ fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", f.Param)
126+ data = "data"
127+ } else {
128+ data = "uint8(" + f.Param + ")"
129+ }
130+ }
131+ fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%d); if p==nil { return 0 };\n", major, data, r.Fixed)
132+ for _, f := range r.Fields {
133+ if f.Kind == "pad" {
134+ continue
135+ }
136+ src := f.Param
137+ if f.Kind == "exprfield" {
138+ var err error
139+ src, err = renderExpr(f.Expr, func(s string) string { return "int(" + paramName(s) + ")" }, m)
140+ if err != nil {
141+ return "", err
142+ }
143+ }
144+ dst := fmt.Sprintf("p[%d:]", f.Off)
145+ if isScalar(f.Type) {
146+ b.WriteString(putScalar(f.Type, src, dst))
147+ } else {
148+ fmt.Fprintf(&b, "%s.Put(%s);", src, dst)
149+ }
150+ }
151+ b.WriteString("return seq }\n")
152+ return b.String(), nil
153+}
154+func emitRequests(modules []*Module) error {
155+ for _, m := range modules {
156+ requests, err := resolveRequests(m)
157+ if err != nil {
158+ return err
159+ }
160+ data := struct {
161+ Pkg string
162+ Decls []string
163+ }{Pkg: m.Pkg}
164+ for _, r := range requests {
165+ decl, err := requestDecl(m, r)
166+ if err != nil {
167+ return err
168+ }
169+ data.Decls = append(data.Decls, decl)
170+ }
171+ all := strings.Join(data.Decls, "\n")
172+ imp := importsFor(m, all)
173+ if len(requests) > 0 {
174+ imp += "\nimport \"bnema.dev/xturbo\""
175+ }
176+ data.Decls = append([]string{imp}, data.Decls...)
177+ if err := writeTemplate(filepath.Join(m.Pkg, "requests_generated.go"), "requests", data); err != nil {
178+ return err
179+ }
180+ }
181+ return nil
182+}
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 +132 -0
@@ -0,0 +1,132 @@
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+}
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 +19 -0
@@ -0,0 +1,19 @@
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.
A internal/xtest/capture_test.go +195 -0
@@ -0,0 +1,195 @@
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+ // Closing the client drains the request direction; wait before inspecting tee.
152+ client.Close()
153+ select {
154+ case err := <-copied:
155+ if err != nil {
156+ t.Fatal(err)
157+ }
158+ case <-time.After(5 * time.Second):
159+ t.Fatal("tee did not drain")
160+ }
161+ stream := recorded.Bytes()
162+ requests := stream[12:]
163+ captured := map[string][]byte{}
164+ for len(requests) > 0 {
165+ size := int(binary.LittleEndian.Uint16(requests[2:])) * 4
166+ if size < 4 || size > len(requests) {
167+ t.Fatal("malformed capture")
168+ }
169+ p := requests[:size]
170+ switch p[0] {
171+ case 8:
172+ captured["xproto/MapWindow"] = p
173+ case 14:
174+ captured["xproto/GetGeometry"] = p
175+ default:
176+ if p[0] == major {
177+ captured["xfixes/QueryVersion"] = p
178+ }
179+ }
180+ requests = requests[size:]
181+ }
182+ if len(captured) != 3 {
183+ t.Fatal("missing captured requests")
184+ }
185+ for name, p := range captured {
186+ path := filepath.Join("../../testdata/golden", name+".req.hex")
187+ if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
188+ t.Fatal(err)
189+ }
190+ 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"
191+ if err := os.WriteFile(path, []byte(text), 0644); err != nil {
192+ t.Fatal(err)
193+ }
194+ }
195+}
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 render/requests_generated.go +240 -0
@@ -0,0 +1,240 @@
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 FreePicture(b *xturbo.Buf, picture Picture) xturbo.Seq {
63+ if b.Ext == nil {
64+ b.Fail(xturbo.ErrExtMissing)
65+ return 0
66+ }
67+ major := b.Ext.Major(xturbo.ExtRender)
68+ if major == 0 {
69+ b.Fail(xturbo.ErrExtMissing)
70+ return 0
71+ }
72+ p, seq := b.Request(major, 7, 4)
73+ if p == nil {
74+ return 0
75+ }
76+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
77+ return seq
78+}
79+
80+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 {
81+ if b.Ext == nil {
82+ b.Fail(xturbo.ErrExtMissing)
83+ return 0
84+ }
85+ major := b.Ext.Major(xturbo.ExtRender)
86+ if major == 0 {
87+ b.Fail(xturbo.ErrExtMissing)
88+ return 0
89+ }
90+ p, seq := b.Request(major, 8, 32)
91+ if p == nil {
92+ return 0
93+ }
94+ p[0:][0] = byte(op)
95+ binary.LittleEndian.PutUint32(p[4:], uint32(src))
96+ binary.LittleEndian.PutUint32(p[8:], uint32(mask))
97+ binary.LittleEndian.PutUint32(p[12:], uint32(dst))
98+ binary.LittleEndian.PutUint16(p[16:], uint16(srcX))
99+ binary.LittleEndian.PutUint16(p[18:], uint16(srcY))
100+ binary.LittleEndian.PutUint16(p[20:], uint16(maskX))
101+ binary.LittleEndian.PutUint16(p[22:], uint16(maskY))
102+ binary.LittleEndian.PutUint16(p[24:], uint16(dstX))
103+ binary.LittleEndian.PutUint16(p[26:], uint16(dstY))
104+ binary.LittleEndian.PutUint16(p[28:], uint16(width))
105+ binary.LittleEndian.PutUint16(p[30:], uint16(height))
106+ return seq
107+}
108+
109+func CreateGlyphSet(b *xturbo.Buf, gsid Glyphset, format Pictformat) xturbo.Seq {
110+ if b.Ext == nil {
111+ b.Fail(xturbo.ErrExtMissing)
112+ return 0
113+ }
114+ major := b.Ext.Major(xturbo.ExtRender)
115+ if major == 0 {
116+ b.Fail(xturbo.ErrExtMissing)
117+ return 0
118+ }
119+ p, seq := b.Request(major, 17, 8)
120+ if p == nil {
121+ return 0
122+ }
123+ binary.LittleEndian.PutUint32(p[0:], uint32(gsid))
124+ binary.LittleEndian.PutUint32(p[4:], uint32(format))
125+ return seq
126+}
127+
128+func ReferenceGlyphSet(b *xturbo.Buf, gsid Glyphset, existing Glyphset) xturbo.Seq {
129+ if b.Ext == nil {
130+ b.Fail(xturbo.ErrExtMissing)
131+ return 0
132+ }
133+ major := b.Ext.Major(xturbo.ExtRender)
134+ if major == 0 {
135+ b.Fail(xturbo.ErrExtMissing)
136+ return 0
137+ }
138+ p, seq := b.Request(major, 18, 8)
139+ if p == nil {
140+ return 0
141+ }
142+ binary.LittleEndian.PutUint32(p[0:], uint32(gsid))
143+ binary.LittleEndian.PutUint32(p[4:], uint32(existing))
144+ return seq
145+}
146+
147+func FreeGlyphSet(b *xturbo.Buf, glyphset Glyphset) xturbo.Seq {
148+ if b.Ext == nil {
149+ b.Fail(xturbo.ErrExtMissing)
150+ return 0
151+ }
152+ major := b.Ext.Major(xturbo.ExtRender)
153+ if major == 0 {
154+ b.Fail(xturbo.ErrExtMissing)
155+ return 0
156+ }
157+ p, seq := b.Request(major, 19, 4)
158+ if p == nil {
159+ return 0
160+ }
161+ binary.LittleEndian.PutUint32(p[0:], uint32(glyphset))
162+ return seq
163+}
164+
165+func CreateCursor(b *xturbo.Buf, cid xproto.Cursor, source Picture, x uint16, y uint16) xturbo.Seq {
166+ if b.Ext == nil {
167+ b.Fail(xturbo.ErrExtMissing)
168+ return 0
169+ }
170+ major := b.Ext.Major(xturbo.ExtRender)
171+ if major == 0 {
172+ b.Fail(xturbo.ErrExtMissing)
173+ return 0
174+ }
175+ p, seq := b.Request(major, 27, 12)
176+ if p == nil {
177+ return 0
178+ }
179+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
180+ binary.LittleEndian.PutUint32(p[4:], uint32(source))
181+ binary.LittleEndian.PutUint16(p[8:], uint16(x))
182+ binary.LittleEndian.PutUint16(p[10:], uint16(y))
183+ return seq
184+}
185+
186+func SetPictureTransform(b *xturbo.Buf, picture Picture, transform Transform) xturbo.Seq {
187+ if b.Ext == nil {
188+ b.Fail(xturbo.ErrExtMissing)
189+ return 0
190+ }
191+ major := b.Ext.Major(xturbo.ExtRender)
192+ if major == 0 {
193+ b.Fail(xturbo.ErrExtMissing)
194+ return 0
195+ }
196+ p, seq := b.Request(major, 28, 40)
197+ if p == nil {
198+ return 0
199+ }
200+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
201+ transform.Put(p[4:])
202+ return seq
203+}
204+
205+func QueryFilters(b *xturbo.Buf, drawable xproto.Drawable) xturbo.Seq {
206+ if b.Ext == nil {
207+ b.Fail(xturbo.ErrExtMissing)
208+ return 0
209+ }
210+ major := b.Ext.Major(xturbo.ExtRender)
211+ if major == 0 {
212+ b.Fail(xturbo.ErrExtMissing)
213+ return 0
214+ }
215+ p, seq := b.Request(major, 29, 4)
216+ if p == nil {
217+ return 0
218+ }
219+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
220+ return seq
221+}
222+
223+func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
224+ if b.Ext == nil {
225+ b.Fail(xturbo.ErrExtMissing)
226+ return 0
227+ }
228+ major := b.Ext.Major(xturbo.ExtRender)
229+ if major == 0 {
230+ b.Fail(xturbo.ErrExtMissing)
231+ return 0
232+ }
233+ p, seq := b.Request(major, 33, 12)
234+ if p == nil {
235+ return 0
236+ }
237+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
238+ color.Put(p[4:])
239+ return seq
240+}
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 +77 -0
@@ -0,0 +1,77 @@
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+}
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 +169 -0
@@ -0,0 +1,169 @@
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 Mask(b *xturbo.Buf, operation So, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceBitmap xproto.Pixmap) xturbo.Seq {
26+ if b.Ext == nil {
27+ b.Fail(xturbo.ErrExtMissing)
28+ return 0
29+ }
30+ major := b.Ext.Major(xturbo.ExtShape)
31+ if major == 0 {
32+ b.Fail(xturbo.ErrExtMissing)
33+ return 0
34+ }
35+ p, seq := b.Request(major, 2, 16)
36+ if p == nil {
37+ return 0
38+ }
39+ p[0:][0] = byte(operation)
40+ p[1:][0] = byte(destinationKind)
41+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
42+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
43+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
44+ binary.LittleEndian.PutUint32(p[12:], uint32(sourceBitmap))
45+ return seq
46+}
47+
48+func Combine(b *xturbo.Buf, operation So, destinationKind Sk, sourceKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceWindow xproto.Window) xturbo.Seq {
49+ if b.Ext == nil {
50+ b.Fail(xturbo.ErrExtMissing)
51+ return 0
52+ }
53+ major := b.Ext.Major(xturbo.ExtShape)
54+ if major == 0 {
55+ b.Fail(xturbo.ErrExtMissing)
56+ return 0
57+ }
58+ p, seq := b.Request(major, 3, 16)
59+ if p == nil {
60+ return 0
61+ }
62+ p[0:][0] = byte(operation)
63+ p[1:][0] = byte(destinationKind)
64+ p[2:][0] = byte(sourceKind)
65+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
66+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
67+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
68+ binary.LittleEndian.PutUint32(p[12:], uint32(sourceWindow))
69+ return seq
70+}
71+
72+func Offset(b *xturbo.Buf, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16) xturbo.Seq {
73+ if b.Ext == nil {
74+ b.Fail(xturbo.ErrExtMissing)
75+ return 0
76+ }
77+ major := b.Ext.Major(xturbo.ExtShape)
78+ if major == 0 {
79+ b.Fail(xturbo.ErrExtMissing)
80+ return 0
81+ }
82+ p, seq := b.Request(major, 4, 12)
83+ if p == nil {
84+ return 0
85+ }
86+ p[0:][0] = byte(destinationKind)
87+ binary.LittleEndian.PutUint32(p[4:], uint32(destinationWindow))
88+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
89+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
90+ return seq
91+}
92+
93+func QueryExtents(b *xturbo.Buf, destinationWindow 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, 5, 4)
104+ if p == nil {
105+ return 0
106+ }
107+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
108+ return seq
109+}
110+
111+func SelectInput(b *xturbo.Buf, destinationWindow xproto.Window, enable bool) xturbo.Seq {
112+ if b.Ext == nil {
113+ b.Fail(xturbo.ErrExtMissing)
114+ return 0
115+ }
116+ major := b.Ext.Major(xturbo.ExtShape)
117+ if major == 0 {
118+ b.Fail(xturbo.ErrExtMissing)
119+ return 0
120+ }
121+ p, seq := b.Request(major, 6, 8)
122+ if p == nil {
123+ return 0
124+ }
125+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
126+ if enable {
127+ p[4:][0] = 1
128+ } else {
129+ p[4:][0] = 0
130+ }
131+ return seq
132+}
133+
134+func InputSelected(b *xturbo.Buf, destinationWindow xproto.Window) xturbo.Seq {
135+ if b.Ext == nil {
136+ b.Fail(xturbo.ErrExtMissing)
137+ return 0
138+ }
139+ major := b.Ext.Major(xturbo.ExtShape)
140+ if major == 0 {
141+ b.Fail(xturbo.ErrExtMissing)
142+ return 0
143+ }
144+ p, seq := b.Request(major, 7, 4)
145+ if p == nil {
146+ return 0
147+ }
148+ binary.LittleEndian.PutUint32(p[0:], uint32(destinationWindow))
149+ return seq
150+}
151+
152+func GetRectangles(b *xturbo.Buf, window xproto.Window, sourceKind Sk) xturbo.Seq {
153+ if b.Ext == nil {
154+ b.Fail(xturbo.ErrExtMissing)
155+ return 0
156+ }
157+ major := b.Ext.Major(xturbo.ExtShape)
158+ if major == 0 {
159+ b.Fail(xturbo.ErrExtMissing)
160+ return 0
161+ }
162+ p, seq := b.Request(major, 8, 8)
163+ if p == nil {
164+ return 0
165+ }
166+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
167+ p[4:][0] = byte(sourceKind)
168+ return seq
169+}
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/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/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/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 +585 -0
@@ -0,0 +1,585 @@
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 CreateRegionFromBitmap(b *xturbo.Buf, region Region, bitmap xproto.Pixmap) xturbo.Seq {
107+ if b.Ext == nil {
108+ b.Fail(xturbo.ErrExtMissing)
109+ return 0
110+ }
111+ major := b.Ext.Major(xturbo.ExtXFixes)
112+ if major == 0 {
113+ b.Fail(xturbo.ErrExtMissing)
114+ return 0
115+ }
116+ p, seq := b.Request(major, 6, 8)
117+ if p == nil {
118+ return 0
119+ }
120+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
121+ binary.LittleEndian.PutUint32(p[4:], uint32(bitmap))
122+ return seq
123+}
124+
125+func CreateRegionFromWindow(b *xturbo.Buf, region Region, window xproto.Window, kind shape.Sk) xturbo.Seq {
126+ if b.Ext == nil {
127+ b.Fail(xturbo.ErrExtMissing)
128+ return 0
129+ }
130+ major := b.Ext.Major(xturbo.ExtXFixes)
131+ if major == 0 {
132+ b.Fail(xturbo.ErrExtMissing)
133+ return 0
134+ }
135+ p, seq := b.Request(major, 7, 12)
136+ if p == nil {
137+ return 0
138+ }
139+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
140+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
141+ p[8:][0] = byte(kind)
142+ return seq
143+}
144+
145+func CreateRegionFromGC(b *xturbo.Buf, region Region, gc xproto.Gcontext) xturbo.Seq {
146+ if b.Ext == nil {
147+ b.Fail(xturbo.ErrExtMissing)
148+ return 0
149+ }
150+ major := b.Ext.Major(xturbo.ExtXFixes)
151+ if major == 0 {
152+ b.Fail(xturbo.ErrExtMissing)
153+ return 0
154+ }
155+ p, seq := b.Request(major, 8, 8)
156+ if p == nil {
157+ return 0
158+ }
159+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
160+ binary.LittleEndian.PutUint32(p[4:], uint32(gc))
161+ return seq
162+}
163+
164+func CreateRegionFromPicture(b *xturbo.Buf, region Region, picture render.Picture) xturbo.Seq {
165+ if b.Ext == nil {
166+ b.Fail(xturbo.ErrExtMissing)
167+ return 0
168+ }
169+ major := b.Ext.Major(xturbo.ExtXFixes)
170+ if major == 0 {
171+ b.Fail(xturbo.ErrExtMissing)
172+ return 0
173+ }
174+ p, seq := b.Request(major, 9, 8)
175+ if p == nil {
176+ return 0
177+ }
178+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
179+ binary.LittleEndian.PutUint32(p[4:], uint32(picture))
180+ return seq
181+}
182+
183+func DestroyRegion(b *xturbo.Buf, region Region) xturbo.Seq {
184+ if b.Ext == nil {
185+ b.Fail(xturbo.ErrExtMissing)
186+ return 0
187+ }
188+ major := b.Ext.Major(xturbo.ExtXFixes)
189+ if major == 0 {
190+ b.Fail(xturbo.ErrExtMissing)
191+ return 0
192+ }
193+ p, seq := b.Request(major, 10, 4)
194+ if p == nil {
195+ return 0
196+ }
197+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
198+ return seq
199+}
200+
201+func CopyRegion(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
202+ if b.Ext == nil {
203+ b.Fail(xturbo.ErrExtMissing)
204+ return 0
205+ }
206+ major := b.Ext.Major(xturbo.ExtXFixes)
207+ if major == 0 {
208+ b.Fail(xturbo.ErrExtMissing)
209+ return 0
210+ }
211+ p, seq := b.Request(major, 12, 8)
212+ if p == nil {
213+ return 0
214+ }
215+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
216+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
217+ return seq
218+}
219+
220+func UnionRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
221+ if b.Ext == nil {
222+ b.Fail(xturbo.ErrExtMissing)
223+ return 0
224+ }
225+ major := b.Ext.Major(xturbo.ExtXFixes)
226+ if major == 0 {
227+ b.Fail(xturbo.ErrExtMissing)
228+ return 0
229+ }
230+ p, seq := b.Request(major, 13, 12)
231+ if p == nil {
232+ return 0
233+ }
234+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
235+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
236+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
237+ return seq
238+}
239+
240+func IntersectRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
241+ if b.Ext == nil {
242+ b.Fail(xturbo.ErrExtMissing)
243+ return 0
244+ }
245+ major := b.Ext.Major(xturbo.ExtXFixes)
246+ if major == 0 {
247+ b.Fail(xturbo.ErrExtMissing)
248+ return 0
249+ }
250+ p, seq := b.Request(major, 14, 12)
251+ if p == nil {
252+ return 0
253+ }
254+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
255+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
256+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
257+ return seq
258+}
259+
260+func SubtractRegion(b *xturbo.Buf, source1 Region, source2 Region, destination Region) xturbo.Seq {
261+ if b.Ext == nil {
262+ b.Fail(xturbo.ErrExtMissing)
263+ return 0
264+ }
265+ major := b.Ext.Major(xturbo.ExtXFixes)
266+ if major == 0 {
267+ b.Fail(xturbo.ErrExtMissing)
268+ return 0
269+ }
270+ p, seq := b.Request(major, 15, 12)
271+ if p == nil {
272+ return 0
273+ }
274+ binary.LittleEndian.PutUint32(p[0:], uint32(source1))
275+ binary.LittleEndian.PutUint32(p[4:], uint32(source2))
276+ binary.LittleEndian.PutUint32(p[8:], uint32(destination))
277+ return seq
278+}
279+
280+func InvertRegion(b *xturbo.Buf, source Region, bounds xproto.Rectangle, destination Region) xturbo.Seq {
281+ if b.Ext == nil {
282+ b.Fail(xturbo.ErrExtMissing)
283+ return 0
284+ }
285+ major := b.Ext.Major(xturbo.ExtXFixes)
286+ if major == 0 {
287+ b.Fail(xturbo.ErrExtMissing)
288+ return 0
289+ }
290+ p, seq := b.Request(major, 16, 16)
291+ if p == nil {
292+ return 0
293+ }
294+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
295+ bounds.Put(p[4:])
296+ binary.LittleEndian.PutUint32(p[12:], uint32(destination))
297+ return seq
298+}
299+
300+func TranslateRegion(b *xturbo.Buf, region Region, dx int16, dy int16) xturbo.Seq {
301+ if b.Ext == nil {
302+ b.Fail(xturbo.ErrExtMissing)
303+ return 0
304+ }
305+ major := b.Ext.Major(xturbo.ExtXFixes)
306+ if major == 0 {
307+ b.Fail(xturbo.ErrExtMissing)
308+ return 0
309+ }
310+ p, seq := b.Request(major, 17, 8)
311+ if p == nil {
312+ return 0
313+ }
314+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
315+ binary.LittleEndian.PutUint16(p[4:], uint16(dx))
316+ binary.LittleEndian.PutUint16(p[6:], uint16(dy))
317+ return seq
318+}
319+
320+func RegionExtents(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
321+ if b.Ext == nil {
322+ b.Fail(xturbo.ErrExtMissing)
323+ return 0
324+ }
325+ major := b.Ext.Major(xturbo.ExtXFixes)
326+ if major == 0 {
327+ b.Fail(xturbo.ErrExtMissing)
328+ return 0
329+ }
330+ p, seq := b.Request(major, 18, 8)
331+ if p == nil {
332+ return 0
333+ }
334+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
335+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
336+ return seq
337+}
338+
339+func FetchRegion(b *xturbo.Buf, region Region) xturbo.Seq {
340+ if b.Ext == nil {
341+ b.Fail(xturbo.ErrExtMissing)
342+ return 0
343+ }
344+ major := b.Ext.Major(xturbo.ExtXFixes)
345+ if major == 0 {
346+ b.Fail(xturbo.ErrExtMissing)
347+ return 0
348+ }
349+ p, seq := b.Request(major, 19, 4)
350+ if p == nil {
351+ return 0
352+ }
353+ binary.LittleEndian.PutUint32(p[0:], uint32(region))
354+ return seq
355+}
356+
357+func SetGCClipRegion(b *xturbo.Buf, gc xproto.Gcontext, region Region, xOrigin int16, yOrigin int16) xturbo.Seq {
358+ if b.Ext == nil {
359+ b.Fail(xturbo.ErrExtMissing)
360+ return 0
361+ }
362+ major := b.Ext.Major(xturbo.ExtXFixes)
363+ if major == 0 {
364+ b.Fail(xturbo.ErrExtMissing)
365+ return 0
366+ }
367+ p, seq := b.Request(major, 20, 12)
368+ if p == nil {
369+ return 0
370+ }
371+ binary.LittleEndian.PutUint32(p[0:], uint32(gc))
372+ binary.LittleEndian.PutUint32(p[4:], uint32(region))
373+ binary.LittleEndian.PutUint16(p[8:], uint16(xOrigin))
374+ binary.LittleEndian.PutUint16(p[10:], uint16(yOrigin))
375+ return seq
376+}
377+
378+func SetWindowShapeRegion(b *xturbo.Buf, dest xproto.Window, destKind shape.Sk, xOffset int16, yOffset int16, region Region) xturbo.Seq {
379+ if b.Ext == nil {
380+ b.Fail(xturbo.ErrExtMissing)
381+ return 0
382+ }
383+ major := b.Ext.Major(xturbo.ExtXFixes)
384+ if major == 0 {
385+ b.Fail(xturbo.ErrExtMissing)
386+ return 0
387+ }
388+ p, seq := b.Request(major, 21, 16)
389+ if p == nil {
390+ return 0
391+ }
392+ binary.LittleEndian.PutUint32(p[0:], uint32(dest))
393+ p[4:][0] = byte(destKind)
394+ binary.LittleEndian.PutUint16(p[8:], uint16(xOffset))
395+ binary.LittleEndian.PutUint16(p[10:], uint16(yOffset))
396+ binary.LittleEndian.PutUint32(p[12:], uint32(region))
397+ return seq
398+}
399+
400+func SetPictureClipRegion(b *xturbo.Buf, picture render.Picture, region Region, xOrigin int16, yOrigin int16) xturbo.Seq {
401+ if b.Ext == nil {
402+ b.Fail(xturbo.ErrExtMissing)
403+ return 0
404+ }
405+ major := b.Ext.Major(xturbo.ExtXFixes)
406+ if major == 0 {
407+ b.Fail(xturbo.ErrExtMissing)
408+ return 0
409+ }
410+ p, seq := b.Request(major, 22, 12)
411+ if p == nil {
412+ return 0
413+ }
414+ binary.LittleEndian.PutUint32(p[0:], uint32(picture))
415+ binary.LittleEndian.PutUint32(p[4:], uint32(region))
416+ binary.LittleEndian.PutUint16(p[8:], uint16(xOrigin))
417+ binary.LittleEndian.PutUint16(p[10:], uint16(yOrigin))
418+ return seq
419+}
420+
421+func GetCursorName(b *xturbo.Buf, cursor xproto.Cursor) xturbo.Seq {
422+ if b.Ext == nil {
423+ b.Fail(xturbo.ErrExtMissing)
424+ return 0
425+ }
426+ major := b.Ext.Major(xturbo.ExtXFixes)
427+ if major == 0 {
428+ b.Fail(xturbo.ErrExtMissing)
429+ return 0
430+ }
431+ p, seq := b.Request(major, 24, 4)
432+ if p == nil {
433+ return 0
434+ }
435+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
436+ return seq
437+}
438+
439+func GetCursorImageAndName(b *xturbo.Buf) xturbo.Seq {
440+ if b.Ext == nil {
441+ b.Fail(xturbo.ErrExtMissing)
442+ return 0
443+ }
444+ major := b.Ext.Major(xturbo.ExtXFixes)
445+ if major == 0 {
446+ b.Fail(xturbo.ErrExtMissing)
447+ return 0
448+ }
449+ p, seq := b.Request(major, 25, 0)
450+ if p == nil {
451+ return 0
452+ }
453+ return seq
454+}
455+
456+func ChangeCursor(b *xturbo.Buf, source xproto.Cursor, destination xproto.Cursor) 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, 26, 8)
467+ if p == nil {
468+ return 0
469+ }
470+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
471+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
472+ return seq
473+}
474+
475+func ExpandRegion(b *xturbo.Buf, source Region, destination Region, left uint16, right uint16, top uint16, bottom uint16) xturbo.Seq {
476+ if b.Ext == nil {
477+ b.Fail(xturbo.ErrExtMissing)
478+ return 0
479+ }
480+ major := b.Ext.Major(xturbo.ExtXFixes)
481+ if major == 0 {
482+ b.Fail(xturbo.ErrExtMissing)
483+ return 0
484+ }
485+ p, seq := b.Request(major, 28, 16)
486+ if p == nil {
487+ return 0
488+ }
489+ binary.LittleEndian.PutUint32(p[0:], uint32(source))
490+ binary.LittleEndian.PutUint32(p[4:], uint32(destination))
491+ binary.LittleEndian.PutUint16(p[8:], uint16(left))
492+ binary.LittleEndian.PutUint16(p[10:], uint16(right))
493+ binary.LittleEndian.PutUint16(p[12:], uint16(top))
494+ binary.LittleEndian.PutUint16(p[14:], uint16(bottom))
495+ return seq
496+}
497+
498+func HideCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
499+ if b.Ext == nil {
500+ b.Fail(xturbo.ErrExtMissing)
501+ return 0
502+ }
503+ major := b.Ext.Major(xturbo.ExtXFixes)
504+ if major == 0 {
505+ b.Fail(xturbo.ErrExtMissing)
506+ return 0
507+ }
508+ p, seq := b.Request(major, 29, 4)
509+ if p == nil {
510+ return 0
511+ }
512+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
513+ return seq
514+}
515+
516+func ShowCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
517+ if b.Ext == nil {
518+ b.Fail(xturbo.ErrExtMissing)
519+ return 0
520+ }
521+ major := b.Ext.Major(xturbo.ExtXFixes)
522+ if major == 0 {
523+ b.Fail(xturbo.ErrExtMissing)
524+ return 0
525+ }
526+ p, seq := b.Request(major, 30, 4)
527+ if p == nil {
528+ return 0
529+ }
530+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
531+ return seq
532+}
533+
534+func DeletePointerBarrier(b *xturbo.Buf, barrier Barrier) xturbo.Seq {
535+ if b.Ext == nil {
536+ b.Fail(xturbo.ErrExtMissing)
537+ return 0
538+ }
539+ major := b.Ext.Major(xturbo.ExtXFixes)
540+ if major == 0 {
541+ b.Fail(xturbo.ErrExtMissing)
542+ return 0
543+ }
544+ p, seq := b.Request(major, 32, 4)
545+ if p == nil {
546+ return 0
547+ }
548+ binary.LittleEndian.PutUint32(p[0:], uint32(barrier))
549+ return seq
550+}
551+
552+func SetClientDisconnectMode(b *xturbo.Buf, disconnectMode ClientDisconnectFlags) xturbo.Seq {
553+ if b.Ext == nil {
554+ b.Fail(xturbo.ErrExtMissing)
555+ return 0
556+ }
557+ major := b.Ext.Major(xturbo.ExtXFixes)
558+ if major == 0 {
559+ b.Fail(xturbo.ErrExtMissing)
560+ return 0
561+ }
562+ p, seq := b.Request(major, 33, 4)
563+ if p == nil {
564+ return 0
565+ }
566+ binary.LittleEndian.PutUint32(p[0:], uint32(disconnectMode))
567+ return seq
568+}
569+
570+func GetClientDisconnectMode(b *xturbo.Buf) xturbo.Seq {
571+ if b.Ext == nil {
572+ b.Fail(xturbo.ErrExtMissing)
573+ return 0
574+ }
575+ major := b.Ext.Major(xturbo.ExtXFixes)
576+ if major == 0 {
577+ b.Fail(xturbo.ErrExtMissing)
578+ return 0
579+ }
580+ p, seq := b.Request(major, 34, 0)
581+ if p == nil {
582+ return 0
583+ }
584+ return seq
585+}
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 +869 -0
@@ -0,0 +1,869 @@
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(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(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 GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
119+ p, seq := b.Request(17, 0, 4)
120+ if p == nil {
121+ return 0
122+ }
123+ binary.LittleEndian.PutUint32(p[0:], uint32(atom))
124+ return seq
125+}
126+
127+func DeleteProperty(b *xturbo.Buf, window Window, property Atom) xturbo.Seq {
128+ p, seq := b.Request(19, 0, 8)
129+ if p == nil {
130+ return 0
131+ }
132+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
133+ binary.LittleEndian.PutUint32(p[4:], uint32(property))
134+ return seq
135+}
136+
137+func GetProperty(b *xturbo.Buf, delete bool, window Window, property Atom, type_ Atom, longOffset uint32, longLength uint32) xturbo.Seq {
138+ var data uint8
139+ if delete {
140+ data = 1
141+ }
142+ p, seq := b.Request(20, data, 20)
143+ if p == nil {
144+ return 0
145+ }
146+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
147+ binary.LittleEndian.PutUint32(p[4:], uint32(property))
148+ binary.LittleEndian.PutUint32(p[8:], uint32(type_))
149+ binary.LittleEndian.PutUint32(p[12:], uint32(longOffset))
150+ binary.LittleEndian.PutUint32(p[16:], uint32(longLength))
151+ return seq
152+}
153+
154+func ListProperties(b *xturbo.Buf, window Window) xturbo.Seq {
155+ p, seq := b.Request(21, 0, 4)
156+ if p == nil {
157+ return 0
158+ }
159+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
160+ return seq
161+}
162+
163+func SetSelectionOwner(b *xturbo.Buf, owner Window, selection Atom, time Timestamp) xturbo.Seq {
164+ p, seq := b.Request(22, 0, 12)
165+ if p == nil {
166+ return 0
167+ }
168+ binary.LittleEndian.PutUint32(p[0:], uint32(owner))
169+ binary.LittleEndian.PutUint32(p[4:], uint32(selection))
170+ binary.LittleEndian.PutUint32(p[8:], uint32(time))
171+ return seq
172+}
173+
174+func GetSelectionOwner(b *xturbo.Buf, selection Atom) xturbo.Seq {
175+ p, seq := b.Request(23, 0, 4)
176+ if p == nil {
177+ return 0
178+ }
179+ binary.LittleEndian.PutUint32(p[0:], uint32(selection))
180+ return seq
181+}
182+
183+func ConvertSelection(b *xturbo.Buf, requestor Window, selection Atom, target Atom, property Atom, time Timestamp) xturbo.Seq {
184+ p, seq := b.Request(24, 0, 20)
185+ if p == nil {
186+ return 0
187+ }
188+ binary.LittleEndian.PutUint32(p[0:], uint32(requestor))
189+ binary.LittleEndian.PutUint32(p[4:], uint32(selection))
190+ binary.LittleEndian.PutUint32(p[8:], uint32(target))
191+ binary.LittleEndian.PutUint32(p[12:], uint32(property))
192+ binary.LittleEndian.PutUint32(p[16:], uint32(time))
193+ return seq
194+}
195+
196+func GrabPointer(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask EventMask, pointerMode GrabMode, keyboardMode GrabMode, confineTo Window, cursor Cursor, time Timestamp) xturbo.Seq {
197+ var data uint8
198+ if ownerEvents {
199+ data = 1
200+ }
201+ p, seq := b.Request(26, data, 20)
202+ if p == nil {
203+ return 0
204+ }
205+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
206+ binary.LittleEndian.PutUint16(p[4:], uint16(eventMask))
207+ p[6:][0] = byte(pointerMode)
208+ p[7:][0] = byte(keyboardMode)
209+ binary.LittleEndian.PutUint32(p[8:], uint32(confineTo))
210+ binary.LittleEndian.PutUint32(p[12:], uint32(cursor))
211+ binary.LittleEndian.PutUint32(p[16:], uint32(time))
212+ return seq
213+}
214+
215+func UngrabPointer(b *xturbo.Buf, time Timestamp) xturbo.Seq {
216+ p, seq := b.Request(27, 0, 4)
217+ if p == nil {
218+ return 0
219+ }
220+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
221+ return seq
222+}
223+
224+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 {
225+ var data uint8
226+ if ownerEvents {
227+ data = 1
228+ }
229+ p, seq := b.Request(28, data, 20)
230+ if p == nil {
231+ return 0
232+ }
233+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
234+ binary.LittleEndian.PutUint16(p[4:], uint16(eventMask))
235+ p[6:][0] = byte(pointerMode)
236+ p[7:][0] = byte(keyboardMode)
237+ binary.LittleEndian.PutUint32(p[8:], uint32(confineTo))
238+ binary.LittleEndian.PutUint32(p[12:], uint32(cursor))
239+ p[16:][0] = byte(button)
240+ binary.LittleEndian.PutUint16(p[18:], uint16(modifiers))
241+ return seq
242+}
243+
244+func UngrabButton(b *xturbo.Buf, button ButtonIndex, grabWindow Window, modifiers ModMask) xturbo.Seq {
245+ p, seq := b.Request(29, uint8(button), 8)
246+ if p == nil {
247+ return 0
248+ }
249+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
250+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
251+ return seq
252+}
253+
254+func ChangeActivePointerGrab(b *xturbo.Buf, cursor Cursor, time Timestamp, eventMask EventMask) xturbo.Seq {
255+ p, seq := b.Request(30, 0, 12)
256+ if p == nil {
257+ return 0
258+ }
259+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
260+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
261+ binary.LittleEndian.PutUint16(p[8:], uint16(eventMask))
262+ return seq
263+}
264+
265+func GrabKeyboard(b *xturbo.Buf, ownerEvents bool, grabWindow Window, time Timestamp, pointerMode GrabMode, keyboardMode GrabMode) xturbo.Seq {
266+ var data uint8
267+ if ownerEvents {
268+ data = 1
269+ }
270+ p, seq := b.Request(31, data, 12)
271+ if p == nil {
272+ return 0
273+ }
274+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
275+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
276+ p[8:][0] = byte(pointerMode)
277+ p[9:][0] = byte(keyboardMode)
278+ return seq
279+}
280+
281+func UngrabKeyboard(b *xturbo.Buf, time Timestamp) xturbo.Seq {
282+ p, seq := b.Request(32, 0, 4)
283+ if p == nil {
284+ return 0
285+ }
286+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
287+ return seq
288+}
289+
290+func GrabKey(b *xturbo.Buf, ownerEvents bool, grabWindow Window, modifiers ModMask, key Keycode, pointerMode GrabMode, keyboardMode GrabMode) xturbo.Seq {
291+ var data uint8
292+ if ownerEvents {
293+ data = 1
294+ }
295+ p, seq := b.Request(33, data, 12)
296+ if p == nil {
297+ return 0
298+ }
299+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
300+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
301+ p[6:][0] = byte(key)
302+ p[7:][0] = byte(pointerMode)
303+ p[8:][0] = byte(keyboardMode)
304+ return seq
305+}
306+
307+func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask) xturbo.Seq {
308+ p, seq := b.Request(34, uint8(key), 8)
309+ if p == nil {
310+ return 0
311+ }
312+ binary.LittleEndian.PutUint32(p[0:], uint32(grabWindow))
313+ binary.LittleEndian.PutUint16(p[4:], uint16(modifiers))
314+ return seq
315+}
316+
317+func AllowEvents(b *xturbo.Buf, mode Allow, time Timestamp) xturbo.Seq {
318+ p, seq := b.Request(35, uint8(mode), 4)
319+ if p == nil {
320+ return 0
321+ }
322+ binary.LittleEndian.PutUint32(p[0:], uint32(time))
323+ return seq
324+}
325+
326+func GrabServer(b *xturbo.Buf) xturbo.Seq {
327+ p, seq := b.Request(36, 0, 0)
328+ if p == nil {
329+ return 0
330+ }
331+ return seq
332+}
333+
334+func UngrabServer(b *xturbo.Buf) xturbo.Seq {
335+ p, seq := b.Request(37, 0, 0)
336+ if p == nil {
337+ return 0
338+ }
339+ return seq
340+}
341+
342+func QueryPointer(b *xturbo.Buf, window Window) xturbo.Seq {
343+ p, seq := b.Request(38, 0, 4)
344+ if p == nil {
345+ return 0
346+ }
347+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
348+ return seq
349+}
350+
351+func GetMotionEvents(b *xturbo.Buf, window Window, start Timestamp, stop Timestamp) xturbo.Seq {
352+ p, seq := b.Request(39, 0, 12)
353+ if p == nil {
354+ return 0
355+ }
356+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
357+ binary.LittleEndian.PutUint32(p[4:], uint32(start))
358+ binary.LittleEndian.PutUint32(p[8:], uint32(stop))
359+ return seq
360+}
361+
362+func TranslateCoordinates(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16, srcY int16) xturbo.Seq {
363+ p, seq := b.Request(40, 0, 12)
364+ if p == nil {
365+ return 0
366+ }
367+ binary.LittleEndian.PutUint32(p[0:], uint32(srcWindow))
368+ binary.LittleEndian.PutUint32(p[4:], uint32(dstWindow))
369+ binary.LittleEndian.PutUint16(p[8:], uint16(srcX))
370+ binary.LittleEndian.PutUint16(p[10:], uint16(srcY))
371+ return seq
372+}
373+
374+func WarpPointer(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16, srcY int16, srcWidth uint16, srcHeight uint16, dstX int16, dstY int16) xturbo.Seq {
375+ p, seq := b.Request(41, 0, 20)
376+ if p == nil {
377+ return 0
378+ }
379+ binary.LittleEndian.PutUint32(p[0:], uint32(srcWindow))
380+ binary.LittleEndian.PutUint32(p[4:], uint32(dstWindow))
381+ binary.LittleEndian.PutUint16(p[8:], uint16(srcX))
382+ binary.LittleEndian.PutUint16(p[10:], uint16(srcY))
383+ binary.LittleEndian.PutUint16(p[12:], uint16(srcWidth))
384+ binary.LittleEndian.PutUint16(p[14:], uint16(srcHeight))
385+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
386+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
387+ return seq
388+}
389+
390+func SetInputFocus(b *xturbo.Buf, revertTo InputFocus, focus Window, time Timestamp) xturbo.Seq {
391+ p, seq := b.Request(42, uint8(revertTo), 8)
392+ if p == nil {
393+ return 0
394+ }
395+ binary.LittleEndian.PutUint32(p[0:], uint32(focus))
396+ binary.LittleEndian.PutUint32(p[4:], uint32(time))
397+ return seq
398+}
399+
400+func GetInputFocus(b *xturbo.Buf) xturbo.Seq {
401+ p, seq := b.Request(43, 0, 0)
402+ if p == nil {
403+ return 0
404+ }
405+ return seq
406+}
407+
408+func QueryKeymap(b *xturbo.Buf) xturbo.Seq {
409+ p, seq := b.Request(44, 0, 0)
410+ if p == nil {
411+ return 0
412+ }
413+ return seq
414+}
415+
416+func CloseFont(b *xturbo.Buf, font Font) xturbo.Seq {
417+ p, seq := b.Request(46, 0, 4)
418+ if p == nil {
419+ return 0
420+ }
421+ binary.LittleEndian.PutUint32(p[0:], uint32(font))
422+ return seq
423+}
424+
425+func QueryFont(b *xturbo.Buf, font Fontable) xturbo.Seq {
426+ p, seq := b.Request(47, 0, 4)
427+ if p == nil {
428+ return 0
429+ }
430+ binary.LittleEndian.PutUint32(p[0:], uint32(font))
431+ return seq
432+}
433+
434+func GetFontPath(b *xturbo.Buf) xturbo.Seq {
435+ p, seq := b.Request(52, 0, 0)
436+ if p == nil {
437+ return 0
438+ }
439+ return seq
440+}
441+
442+func CreatePixmap(b *xturbo.Buf, depth uint8, pid Pixmap, drawable Drawable, width uint16, height uint16) xturbo.Seq {
443+ p, seq := b.Request(53, uint8(depth), 12)
444+ if p == nil {
445+ return 0
446+ }
447+ binary.LittleEndian.PutUint32(p[0:], uint32(pid))
448+ binary.LittleEndian.PutUint32(p[4:], uint32(drawable))
449+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
450+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
451+ return seq
452+}
453+
454+func FreePixmap(b *xturbo.Buf, pixmap Pixmap) xturbo.Seq {
455+ p, seq := b.Request(54, 0, 4)
456+ if p == nil {
457+ return 0
458+ }
459+ binary.LittleEndian.PutUint32(p[0:], uint32(pixmap))
460+ return seq
461+}
462+
463+func CopyGC(b *xturbo.Buf, srcGc Gcontext, dstGc Gcontext, valueMask Gc) xturbo.Seq {
464+ p, seq := b.Request(57, 0, 12)
465+ if p == nil {
466+ return 0
467+ }
468+ binary.LittleEndian.PutUint32(p[0:], uint32(srcGc))
469+ binary.LittleEndian.PutUint32(p[4:], uint32(dstGc))
470+ binary.LittleEndian.PutUint32(p[8:], uint32(valueMask))
471+ return seq
472+}
473+
474+func FreeGC(b *xturbo.Buf, gc Gcontext) xturbo.Seq {
475+ p, seq := b.Request(60, 0, 4)
476+ if p == nil {
477+ return 0
478+ }
479+ binary.LittleEndian.PutUint32(p[0:], uint32(gc))
480+ return seq
481+}
482+
483+func ClearArea(b *xturbo.Buf, exposures bool, window Window, x int16, y int16, width uint16, height uint16) xturbo.Seq {
484+ var data uint8
485+ if exposures {
486+ data = 1
487+ }
488+ p, seq := b.Request(61, data, 12)
489+ if p == nil {
490+ return 0
491+ }
492+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
493+ binary.LittleEndian.PutUint16(p[4:], uint16(x))
494+ binary.LittleEndian.PutUint16(p[6:], uint16(y))
495+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
496+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
497+ return seq
498+}
499+
500+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 {
501+ p, seq := b.Request(62, 0, 24)
502+ if p == nil {
503+ return 0
504+ }
505+ binary.LittleEndian.PutUint32(p[0:], uint32(srcDrawable))
506+ binary.LittleEndian.PutUint32(p[4:], uint32(dstDrawable))
507+ binary.LittleEndian.PutUint32(p[8:], uint32(gc))
508+ binary.LittleEndian.PutUint16(p[12:], uint16(srcX))
509+ binary.LittleEndian.PutUint16(p[14:], uint16(srcY))
510+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
511+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
512+ binary.LittleEndian.PutUint16(p[20:], uint16(width))
513+ binary.LittleEndian.PutUint16(p[22:], uint16(height))
514+ return seq
515+}
516+
517+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 {
518+ p, seq := b.Request(63, 0, 28)
519+ if p == nil {
520+ return 0
521+ }
522+ binary.LittleEndian.PutUint32(p[0:], uint32(srcDrawable))
523+ binary.LittleEndian.PutUint32(p[4:], uint32(dstDrawable))
524+ binary.LittleEndian.PutUint32(p[8:], uint32(gc))
525+ binary.LittleEndian.PutUint16(p[12:], uint16(srcX))
526+ binary.LittleEndian.PutUint16(p[14:], uint16(srcY))
527+ binary.LittleEndian.PutUint16(p[16:], uint16(dstX))
528+ binary.LittleEndian.PutUint16(p[18:], uint16(dstY))
529+ binary.LittleEndian.PutUint16(p[20:], uint16(width))
530+ binary.LittleEndian.PutUint16(p[22:], uint16(height))
531+ binary.LittleEndian.PutUint32(p[24:], uint32(bitPlane))
532+ return seq
533+}
534+
535+func GetImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, x int16, y int16, width uint16, height uint16, planeMask uint32) xturbo.Seq {
536+ p, seq := b.Request(73, uint8(format), 16)
537+ if p == nil {
538+ return 0
539+ }
540+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
541+ binary.LittleEndian.PutUint16(p[4:], uint16(x))
542+ binary.LittleEndian.PutUint16(p[6:], uint16(y))
543+ binary.LittleEndian.PutUint16(p[8:], uint16(width))
544+ binary.LittleEndian.PutUint16(p[10:], uint16(height))
545+ binary.LittleEndian.PutUint32(p[12:], uint32(planeMask))
546+ return seq
547+}
548+
549+func CreateColormap(b *xturbo.Buf, alloc ColormapAlloc, mid Colormap, window Window, visual Visualid) xturbo.Seq {
550+ p, seq := b.Request(78, uint8(alloc), 12)
551+ if p == nil {
552+ return 0
553+ }
554+ binary.LittleEndian.PutUint32(p[0:], uint32(mid))
555+ binary.LittleEndian.PutUint32(p[4:], uint32(window))
556+ binary.LittleEndian.PutUint32(p[8:], uint32(visual))
557+ return seq
558+}
559+
560+func FreeColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
561+ p, seq := b.Request(79, 0, 4)
562+ if p == nil {
563+ return 0
564+ }
565+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
566+ return seq
567+}
568+
569+func CopyColormapAndFree(b *xturbo.Buf, mid Colormap, srcCmap Colormap) xturbo.Seq {
570+ p, seq := b.Request(80, 0, 8)
571+ if p == nil {
572+ return 0
573+ }
574+ binary.LittleEndian.PutUint32(p[0:], uint32(mid))
575+ binary.LittleEndian.PutUint32(p[4:], uint32(srcCmap))
576+ return seq
577+}
578+
579+func InstallColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
580+ p, seq := b.Request(81, 0, 4)
581+ if p == nil {
582+ return 0
583+ }
584+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
585+ return seq
586+}
587+
588+func UninstallColormap(b *xturbo.Buf, cmap Colormap) xturbo.Seq {
589+ p, seq := b.Request(82, 0, 4)
590+ if p == nil {
591+ return 0
592+ }
593+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
594+ return seq
595+}
596+
597+func ListInstalledColormaps(b *xturbo.Buf, window Window) xturbo.Seq {
598+ p, seq := b.Request(83, 0, 4)
599+ if p == nil {
600+ return 0
601+ }
602+ binary.LittleEndian.PutUint32(p[0:], uint32(window))
603+ return seq
604+}
605+
606+func AllocColor(b *xturbo.Buf, cmap Colormap, red uint16, green uint16, blue uint16) xturbo.Seq {
607+ p, seq := b.Request(84, 0, 12)
608+ if p == nil {
609+ return 0
610+ }
611+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
612+ binary.LittleEndian.PutUint16(p[4:], uint16(red))
613+ binary.LittleEndian.PutUint16(p[6:], uint16(green))
614+ binary.LittleEndian.PutUint16(p[8:], uint16(blue))
615+ return seq
616+}
617+
618+func AllocColorCells(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, planes uint16) xturbo.Seq {
619+ var data uint8
620+ if contiguous {
621+ data = 1
622+ }
623+ p, seq := b.Request(86, data, 8)
624+ if p == nil {
625+ return 0
626+ }
627+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
628+ binary.LittleEndian.PutUint16(p[4:], uint16(colors))
629+ binary.LittleEndian.PutUint16(p[6:], uint16(planes))
630+ return seq
631+}
632+
633+func AllocColorPlanes(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, reds uint16, greens uint16, blues uint16) xturbo.Seq {
634+ var data uint8
635+ if contiguous {
636+ data = 1
637+ }
638+ p, seq := b.Request(87, data, 12)
639+ if p == nil {
640+ return 0
641+ }
642+ binary.LittleEndian.PutUint32(p[0:], uint32(cmap))
643+ binary.LittleEndian.PutUint16(p[4:], uint16(colors))
644+ binary.LittleEndian.PutUint16(p[6:], uint16(reds))
645+ binary.LittleEndian.PutUint16(p[8:], uint16(greens))
646+ binary.LittleEndian.PutUint16(p[10:], uint16(blues))
647+ return seq
648+}
649+
650+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 {
651+ p, seq := b.Request(93, 0, 28)
652+ if p == nil {
653+ return 0
654+ }
655+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
656+ binary.LittleEndian.PutUint32(p[4:], uint32(source))
657+ binary.LittleEndian.PutUint32(p[8:], uint32(mask))
658+ binary.LittleEndian.PutUint16(p[12:], uint16(foreRed))
659+ binary.LittleEndian.PutUint16(p[14:], uint16(foreGreen))
660+ binary.LittleEndian.PutUint16(p[16:], uint16(foreBlue))
661+ binary.LittleEndian.PutUint16(p[18:], uint16(backRed))
662+ binary.LittleEndian.PutUint16(p[20:], uint16(backGreen))
663+ binary.LittleEndian.PutUint16(p[22:], uint16(backBlue))
664+ binary.LittleEndian.PutUint16(p[24:], uint16(x))
665+ binary.LittleEndian.PutUint16(p[26:], uint16(y))
666+ return seq
667+}
668+
669+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 {
670+ p, seq := b.Request(94, 0, 28)
671+ if p == nil {
672+ return 0
673+ }
674+ binary.LittleEndian.PutUint32(p[0:], uint32(cid))
675+ binary.LittleEndian.PutUint32(p[4:], uint32(sourceFont))
676+ binary.LittleEndian.PutUint32(p[8:], uint32(maskFont))
677+ binary.LittleEndian.PutUint16(p[12:], uint16(sourceChar))
678+ binary.LittleEndian.PutUint16(p[14:], uint16(maskChar))
679+ binary.LittleEndian.PutUint16(p[16:], uint16(foreRed))
680+ binary.LittleEndian.PutUint16(p[18:], uint16(foreGreen))
681+ binary.LittleEndian.PutUint16(p[20:], uint16(foreBlue))
682+ binary.LittleEndian.PutUint16(p[22:], uint16(backRed))
683+ binary.LittleEndian.PutUint16(p[24:], uint16(backGreen))
684+ binary.LittleEndian.PutUint16(p[26:], uint16(backBlue))
685+ return seq
686+}
687+
688+func FreeCursor(b *xturbo.Buf, cursor Cursor) xturbo.Seq {
689+ p, seq := b.Request(95, 0, 4)
690+ if p == nil {
691+ return 0
692+ }
693+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
694+ return seq
695+}
696+
697+func RecolorCursor(b *xturbo.Buf, cursor Cursor, foreRed uint16, foreGreen uint16, foreBlue uint16, backRed uint16, backGreen uint16, backBlue uint16) xturbo.Seq {
698+ p, seq := b.Request(96, 0, 16)
699+ if p == nil {
700+ return 0
701+ }
702+ binary.LittleEndian.PutUint32(p[0:], uint32(cursor))
703+ binary.LittleEndian.PutUint16(p[4:], uint16(foreRed))
704+ binary.LittleEndian.PutUint16(p[6:], uint16(foreGreen))
705+ binary.LittleEndian.PutUint16(p[8:], uint16(foreBlue))
706+ binary.LittleEndian.PutUint16(p[10:], uint16(backRed))
707+ binary.LittleEndian.PutUint16(p[12:], uint16(backGreen))
708+ binary.LittleEndian.PutUint16(p[14:], uint16(backBlue))
709+ return seq
710+}
711+
712+func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width uint16, height uint16) xturbo.Seq {
713+ p, seq := b.Request(97, uint8(class), 8)
714+ if p == nil {
715+ return 0
716+ }
717+ binary.LittleEndian.PutUint32(p[0:], uint32(drawable))
718+ binary.LittleEndian.PutUint16(p[4:], uint16(width))
719+ binary.LittleEndian.PutUint16(p[6:], uint16(height))
720+ return seq
721+}
722+
723+func ListExtensions(b *xturbo.Buf) xturbo.Seq {
724+ p, seq := b.Request(99, 0, 0)
725+ if p == nil {
726+ return 0
727+ }
728+ return seq
729+}
730+
731+func GetKeyboardMapping(b *xturbo.Buf, firstKeycode Keycode, count uint8) xturbo.Seq {
732+ p, seq := b.Request(101, 0, 4)
733+ if p == nil {
734+ return 0
735+ }
736+ p[0:][0] = byte(firstKeycode)
737+ p[1:][0] = byte(count)
738+ return seq
739+}
740+
741+func GetKeyboardControl(b *xturbo.Buf) xturbo.Seq {
742+ p, seq := b.Request(103, 0, 0)
743+ if p == nil {
744+ return 0
745+ }
746+ return seq
747+}
748+
749+func Bell(b *xturbo.Buf, percent int8) xturbo.Seq {
750+ p, seq := b.Request(104, uint8(percent), 0)
751+ if p == nil {
752+ return 0
753+ }
754+ return seq
755+}
756+
757+func ChangePointerControl(b *xturbo.Buf, accelerationNumerator int16, accelerationDenominator int16, threshold int16, doAcceleration bool, doThreshold bool) xturbo.Seq {
758+ p, seq := b.Request(105, 0, 8)
759+ if p == nil {
760+ return 0
761+ }
762+ binary.LittleEndian.PutUint16(p[0:], uint16(accelerationNumerator))
763+ binary.LittleEndian.PutUint16(p[2:], uint16(accelerationDenominator))
764+ binary.LittleEndian.PutUint16(p[4:], uint16(threshold))
765+ if doAcceleration {
766+ p[6:][0] = 1
767+ } else {
768+ p[6:][0] = 0
769+ }
770+ if doThreshold {
771+ p[7:][0] = 1
772+ } else {
773+ p[7:][0] = 0
774+ }
775+ return seq
776+}
777+
778+func GetPointerControl(b *xturbo.Buf) xturbo.Seq {
779+ p, seq := b.Request(106, 0, 0)
780+ if p == nil {
781+ return 0
782+ }
783+ return seq
784+}
785+
786+func SetScreenSaver(b *xturbo.Buf, timeout int16, interval int16, preferBlanking Blanking, allowExposures Exposures) xturbo.Seq {
787+ p, seq := b.Request(107, 0, 8)
788+ if p == nil {
789+ return 0
790+ }
791+ binary.LittleEndian.PutUint16(p[0:], uint16(timeout))
792+ binary.LittleEndian.PutUint16(p[2:], uint16(interval))
793+ p[4:][0] = byte(preferBlanking)
794+ p[5:][0] = byte(allowExposures)
795+ return seq
796+}
797+
798+func GetScreenSaver(b *xturbo.Buf) xturbo.Seq {
799+ p, seq := b.Request(108, 0, 0)
800+ if p == nil {
801+ return 0
802+ }
803+ return seq
804+}
805+
806+func ListHosts(b *xturbo.Buf) xturbo.Seq {
807+ p, seq := b.Request(110, 0, 0)
808+ if p == nil {
809+ return 0
810+ }
811+ return seq
812+}
813+
814+func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
815+ p, seq := b.Request(111, uint8(mode), 0)
816+ if p == nil {
817+ return 0
818+ }
819+ return seq
820+}
821+
822+func SetCloseDownMode(b *xturbo.Buf, mode CloseDown) xturbo.Seq {
823+ p, seq := b.Request(112, uint8(mode), 0)
824+ if p == nil {
825+ return 0
826+ }
827+ return seq
828+}
829+
830+func KillClient(b *xturbo.Buf, resource uint32) xturbo.Seq {
831+ p, seq := b.Request(113, 0, 4)
832+ if p == nil {
833+ return 0
834+ }
835+ binary.LittleEndian.PutUint32(p[0:], uint32(resource))
836+ return seq
837+}
838+
839+func ForceScreenSaver(b *xturbo.Buf, mode ScreenSaver) xturbo.Seq {
840+ p, seq := b.Request(115, uint8(mode), 0)
841+ if p == nil {
842+ return 0
843+ }
844+ return seq
845+}
846+
847+func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
848+ p, seq := b.Request(117, 0, 0)
849+ if p == nil {
850+ return 0
851+ }
852+ return seq
853+}
854+
855+func GetModifierMapping(b *xturbo.Buf) xturbo.Seq {
856+ p, seq := b.Request(119, 0, 0)
857+ if p == nil {
858+ return 0
859+ }
860+ return seq
861+}
862+
863+func NoOperation(b *xturbo.Buf) xturbo.Seq {
864+ p, seq := b.Request(127, 0, 0)
865+ if p == nil {
866+ return 0
867+ }
868+ return seq
869+}
A xproto/requests_test.go +24 -0
@@ -0,0 +1,24 @@
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+}
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