detached 582be88

feat(xtgen): encode request lists and derive exclusive lengths

commit
582be8898a7ccc047433fa09a66bdcefe4ffeb8e
author
brice · · 2026-10-22 06:31 UTC
parent
8e6fe5c
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
checks
2/2
14 files · +2323 -26
M cmd/xtgen/requests.go +168 -11
@@ -14,10 +14,11 @@ type Request struct {
1414 Fixed int
1515 Params, Fields []Field
1616 Node *Node
17+ Derived map[string]string
18+ Lists []Field
1719 }
1820
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+// resolveRequests lowers scalar and list requests. Value switches follow in T2.5.
2122 func resolveRequests(m *Module) ([]Request, error) {
2223 var out []Request
2324 for _, n := range m.Root.Children {
@@ -26,7 +27,7 @@ func resolveRequests(m *Module) ([]Request, error) {
2627 }
2728 supported := true
2829 for _, f := range n.Children {
29- if f.Kind == "list" || f.Kind == "switch" {
30+ if f.Kind == "switch" {
3031 supported = false
3132 }
3233 }
@@ -38,7 +39,27 @@ func resolveRequests(m *Module) ([]Request, error) {
3839 return nil, err
3940 }
4041 opcode, _ := strconv.Atoi(n.Attr["opcode"])
41- r := Request{Name: name, Opcode: uint8(opcode), Node: n}
42+ r := Request{Name: name, Opcode: uint8(opcode), Node: n, Derived: map[string]string{}}
43+ refs := map[string]int{}
44+ var countRefs func(*Node)
45+ countRefs = func(x *Node) {
46+ if x.Kind == "reply" || x.Kind == "doc" {
47+ return
48+ }
49+ if x.Kind == "fieldref" {
50+ refs[x.Text]++
51+ }
52+ for _, c := range x.Children {
53+ countRefs(c)
54+ }
55+ }
56+ countRefs(n)
57+ for _, x := range n.Children {
58+ if x.Kind == "list" && len(x.Children) == 1 && x.Children[0].Kind == "fieldref" && refs[x.Children[0].Text] == 1 {
59+ r.Derived[x.Children[0].Text] = paramName(x.Attr["name"])
60+ }
61+ }
62+ dynamic := false
4263 off := 4
4364 first := true
4465 for _, n := range n.Children {
@@ -58,7 +79,7 @@ func resolveRequests(m *Module) ([]Request, error) {
5879 if err != nil {
5980 return nil, n.fail("%v", err)
6081 }
61- if typ.Variable {
82+ if typ.Variable && n.Kind != "list" {
6283 return nil, n.fail("variable field requires list support")
6384 }
6485 f.Type = typ
@@ -78,7 +99,24 @@ func resolveRequests(m *Module) ([]Request, error) {
7899 }
79100 f.GoType = qualified(m, owner, e.Name)
80101 }
81- if n.Kind == "field" {
102+ if n.Kind == "list" {
103+ f.Size = 0
104+ f.GoType = "[]" + f.GoType
105+ if n.Attr["type"] == "char" {
106+ f.GoType = "string"
107+ }
108+ if n.Attr["type"] == "void" || n.Attr["type"] == "BYTE" || n.Attr["type"] == "CARD8" {
109+ f.GoType = "[]byte"
110+ }
111+ if len(n.Children) > 0 {
112+ f.Expr = n.Children[0]
113+ }
114+ if m.Header == "xproto" && r.Name == "SendEvent" {
115+ f.GoType = "*[32]byte"
116+ }
117+ r.Lists = append(r.Lists, f)
118+ r.Params = append(r.Params, f)
119+ } else if n.Kind == "field" && r.Derived[n.Attr["name"]] == "" {
82120 r.Params = append(r.Params, f)
83121 }
84122 if n.Kind == "exprfield" {
@@ -98,10 +136,19 @@ func resolveRequests(m *Module) ([]Request, error) {
98136 continue
99137 }
100138 first = false
139+ if f.Kind == "list" {
140+ dynamic = true
141+ }
142+ if dynamic {
143+ f.Off = -1
144+ }
145+ if f.Kind == "pad" && n.Attr["align"] != "" {
146+ f.Align, _ = strconv.Atoi(n.Attr["align"])
147+ }
101148 r.Fields = append(r.Fields, f)
102149 off += f.Size
103150 }
104- r.Fixed = (off - 4 + 3) &^ 3
151+ r.Fixed = off - 4
105152 out = append(out, r)
106153 }
107154 return out, nil
@@ -113,6 +160,68 @@ func requestDecl(m *Module, r Request) (string, error) {
113160 fmt.Fprintf(&b, ", %s %s", p.Param, p.GoType)
114161 }
115162 b.WriteString(") xturbo.Seq {\n")
163+ ref := func(s string) string {
164+ // xcb-proto permits an exprfield to refer to a trailing list's
165+ // implicit <list>_len (QueryTextExtents.string_len).
166+ declared := false
167+ for _, n := range r.Node.Children {
168+ if n.Kind == "field" && n.Attr["name"] == s {
169+ declared = true
170+ }
171+ }
172+ for _, list := range r.Lists {
173+ if !declared && s == list.Node.Attr["name"]+"_len" {
174+ return "len(" + list.Param + ")"
175+ }
176+ }
177+ if list := r.Derived[s]; list != "" {
178+ return "len(" + list + ")"
179+ }
180+ return "int(" + paramName(s) + ")"
181+ }
182+ // Derived lengths are cast only after checking their wire width.
183+ for _, f := range append(append([]Field{}, r.Fields...), r.Params...) {
184+ if f.Kind != "field" || r.Derived[f.Node.Attr["name"]] == "" {
185+ continue
186+ }
187+ if f.Type.Size < 8 {
188+ fmt.Fprintf(&b, "if uint64(%s)>%d { b.Fail(xturbo.ErrBadLength); return 0 };", ref(f.Node.Attr["name"]), uint64(1)<<(8*f.Type.Size)-1)
189+ }
190+ }
191+ if r.DataByte != nil {
192+ f := r.DataByte
193+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
194+ fmt.Fprintf(&b, "if len(%s)>255 { b.Fail(xturbo.ErrBadLength); return 0 };", list)
195+ }
196+ }
197+ for _, f := range r.Lists {
198+ if f.Expr != nil && !(f.Expr.Kind == "fieldref" && r.Derived[f.Expr.Text] != "") {
199+ ex, err := renderExpr(f.Expr, ref, m)
200+ if err != nil {
201+ return "", err
202+ }
203+ fmt.Fprintf(&b, "if len(%s)!=%s { b.Fail(xturbo.ErrBadLength); return 0 };", f.Param, ex)
204+ }
205+ }
206+ body := fmt.Sprint((r.Fixed + 3) &^ 3)
207+ if len(r.Lists) > 0 {
208+ b.WriteString("size:=0;")
209+ for _, f := range r.Fields {
210+ if f.Kind == "list" {
211+ if f.Type.Variable {
212+ fmt.Fprintf(&b, "for i:=range %s { size+=%s[i].Size() };", f.Param, f.Param)
213+ } else {
214+ fmt.Fprintf(&b, "size+=len(%s)*%d;", f.Param, f.Type.Size)
215+ }
216+ } else if f.Align > 0 {
217+ fmt.Fprintf(&b, "size=(size+%d)&^%d;", f.Align-1, f.Align-1)
218+ } else {
219+ fmt.Fprintf(&b, "size+=%d;", f.Size)
220+ }
221+ }
222+ b.WriteString("size=(size+3)&^3;")
223+ body = "size"
224+ }
116225 major := fmt.Sprint(r.Opcode)
117226 data := "0"
118227 if m.ExtName != "" {
@@ -122,31 +231,79 @@ func requestDecl(m *Module, r Request) (string, error) {
122231 } else if r.DataByte != nil {
123232 f := r.DataByte
124233 if f.Type.Base == "bool" {
125- fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", f.Param)
234+ value := f.Param
235+ if f.Kind == "exprfield" {
236+ ex, err := renderExpr(f.Expr, ref, m)
237+ if err != nil {
238+ return "", err
239+ }
240+ value = "(" + ex + " != 0)"
241+ }
242+ fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", value)
126243 data = "data"
127244 } else {
128- data = "uint8(" + f.Param + ")"
245+ data = "uint8(" + ref(f.Node.Attr["name"]) + ")"
129246 }
130247 }
131- fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%d); if p==nil { return 0 };\n", major, data, r.Fixed)
248+ fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%s); if p==nil { return 0 };\n", major, data, body)
249+ if len(r.Lists) > 0 {
250+ b.WriteString("off:=0;")
251+ }
132252 for _, f := range r.Fields {
133253 if f.Kind == "pad" {
254+ if len(r.Lists) > 0 {
255+ if f.Align > 0 {
256+ fmt.Fprintf(&b, "off=(off+%d)&^%d;", f.Align-1, f.Align-1)
257+ } else {
258+ fmt.Fprintf(&b, "off+=%d;", f.Size)
259+ }
260+ }
261+ continue
262+ }
263+ if f.Kind == "list" {
264+ if f.GoType == "*[32]byte" {
265+ fmt.Fprintf(&b, "copy(p[off:],%s[:]);", f.Param)
266+ } else if f.GoType == "string" || f.GoType == "[]byte" {
267+ fmt.Fprintf(&b, "copy(p[off:],%s); off+=len(%s);", f.Param, f.Param)
268+ } else {
269+ fmt.Fprintf(&b, "for i:=range %s {", f.Param)
270+ if isScalar(f.Type) {
271+ b.WriteString(putScalar(f.Type, f.Param+"[i]", "p[off:]"))
272+ } else {
273+ fmt.Fprintf(&b, "%s[i].Put(p[off:]);", f.Param)
274+ }
275+ if f.Type.Variable {
276+ fmt.Fprintf(&b, "off+=%s[i].Size();", f.Param)
277+ } else {
278+ fmt.Fprintf(&b, "off+=%d;", f.Type.Size)
279+ }
280+ b.WriteString("};")
281+ }
134282 continue
135283 }
136284 src := f.Param
285+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
286+ src = "len(" + list + ")"
287+ }
137288 if f.Kind == "exprfield" {
138289 var err error
139- src, err = renderExpr(f.Expr, func(s string) string { return "int(" + paramName(s) + ")" }, m)
290+ src, err = renderExpr(f.Expr, ref, m)
140291 if err != nil {
141292 return "", err
142293 }
143294 }
144295 dst := fmt.Sprintf("p[%d:]", f.Off)
296+ if len(r.Lists) > 0 {
297+ dst = "p[off:]"
298+ }
145299 if isScalar(f.Type) {
146300 b.WriteString(putScalar(f.Type, src, dst))
147301 } else {
148302 fmt.Fprintf(&b, "%s.Put(%s);", src, dst)
149303 }
304+ if len(r.Lists) > 0 {
305+ fmt.Fprintf(&b, "off+=%d;", f.Size)
306+ }
150307 }
151308 b.WriteString("return seq }\n")
152309 return b.String(), nil
@@ -14,10 +14,11 @@ type Request struct {
14 Fixed int14 Fixed int
15 Params, Fields []Field15 Params, Fields []Field
16 Node *Node16 Node *Node
17+ Derived map[string]string
18+ Lists []Field
17 }19 }
18 20
19-// resolveRequests implements the fixed-body subset. Lists and value lists are21+// resolveRequests lowers scalar and list requests. Value switches follow in T2.5.
20-// deliberately left in the AST for T2.4/T2.5, not emitted as incomplete APIs.
21 func resolveRequests(m *Module) ([]Request, error) {22 func resolveRequests(m *Module) ([]Request, error) {
22 var out []Request23 var out []Request
23 for _, n := range m.Root.Children {24 for _, n := range m.Root.Children {
@@ -26,7 +27,7 @@ func resolveRequests(m *Module) ([]Request, error) {
26 }27 }
27 supported := true28 supported := true
28 for _, f := range n.Children {29 for _, f := range n.Children {
29- if f.Kind == "list" || f.Kind == "switch" {30+ if f.Kind == "switch" {
30 supported = false31 supported = false
31 }32 }
32 }33 }
@@ -38,7 +39,27 @@ func resolveRequests(m *Module) ([]Request, error) {
38 return nil, err39 return nil, err
39 }40 }
40 opcode, _ := strconv.Atoi(n.Attr["opcode"])41 opcode, _ := strconv.Atoi(n.Attr["opcode"])
41- r := Request{Name: name, Opcode: uint8(opcode), Node: n}42+ r := Request{Name: name, Opcode: uint8(opcode), Node: n, Derived: map[string]string{}}
43+ refs := map[string]int{}
44+ var countRefs func(*Node)
45+ countRefs = func(x *Node) {
46+ if x.Kind == "reply" || x.Kind == "doc" {
47+ return
48+ }
49+ if x.Kind == "fieldref" {
50+ refs[x.Text]++
51+ }
52+ for _, c := range x.Children {
53+ countRefs(c)
54+ }
55+ }
56+ countRefs(n)
57+ for _, x := range n.Children {
58+ if x.Kind == "list" && len(x.Children) == 1 && x.Children[0].Kind == "fieldref" && refs[x.Children[0].Text] == 1 {
59+ r.Derived[x.Children[0].Text] = paramName(x.Attr["name"])
60+ }
61+ }
62+ dynamic := false
42 off := 463 off := 4
43 first := true64 first := true
44 for _, n := range n.Children {65 for _, n := range n.Children {
@@ -58,7 +79,7 @@ func resolveRequests(m *Module) ([]Request, error) {
58 if err != nil {79 if err != nil {
59 return nil, n.fail("%v", err)80 return nil, n.fail("%v", err)
60 }81 }
61- if typ.Variable {82+ if typ.Variable && n.Kind != "list" {
62 return nil, n.fail("variable field requires list support")83 return nil, n.fail("variable field requires list support")
63 }84 }
64 f.Type = typ85 f.Type = typ
@@ -78,7 +99,24 @@ func resolveRequests(m *Module) ([]Request, error) {
78 }99 }
79 f.GoType = qualified(m, owner, e.Name)100 f.GoType = qualified(m, owner, e.Name)
80 }101 }
81- if n.Kind == "field" {102+ if n.Kind == "list" {
103+ f.Size = 0
104+ f.GoType = "[]" + f.GoType
105+ if n.Attr["type"] == "char" {
106+ f.GoType = "string"
107+ }
108+ if n.Attr["type"] == "void" || n.Attr["type"] == "BYTE" || n.Attr["type"] == "CARD8" {
109+ f.GoType = "[]byte"
110+ }
111+ if len(n.Children) > 0 {
112+ f.Expr = n.Children[0]
113+ }
114+ if m.Header == "xproto" && r.Name == "SendEvent" {
115+ f.GoType = "*[32]byte"
116+ }
117+ r.Lists = append(r.Lists, f)
118+ r.Params = append(r.Params, f)
119+ } else if n.Kind == "field" && r.Derived[n.Attr["name"]] == "" {
82 r.Params = append(r.Params, f)120 r.Params = append(r.Params, f)
83 }121 }
84 if n.Kind == "exprfield" {122 if n.Kind == "exprfield" {
@@ -98,10 +136,19 @@ func resolveRequests(m *Module) ([]Request, error) {
98 continue136 continue
99 }137 }
100 first = false138 first = false
139+ if f.Kind == "list" {
140+ dynamic = true
141+ }
142+ if dynamic {
143+ f.Off = -1
144+ }
145+ if f.Kind == "pad" && n.Attr["align"] != "" {
146+ f.Align, _ = strconv.Atoi(n.Attr["align"])
147+ }
101 r.Fields = append(r.Fields, f)148 r.Fields = append(r.Fields, f)
102 off += f.Size149 off += f.Size
103 }150 }
104- r.Fixed = (off - 4 + 3) &^ 3151+ r.Fixed = off - 4
105 out = append(out, r)152 out = append(out, r)
106 }153 }
107 return out, nil154 return out, nil
@@ -113,6 +160,68 @@ func requestDecl(m *Module, r Request) (string, error) {
113 fmt.Fprintf(&b, ", %s %s", p.Param, p.GoType)160 fmt.Fprintf(&b, ", %s %s", p.Param, p.GoType)
114 }161 }
115 b.WriteString(") xturbo.Seq {\n")162 b.WriteString(") xturbo.Seq {\n")
163+ ref := func(s string) string {
164+ // xcb-proto permits an exprfield to refer to a trailing list's
165+ // implicit <list>_len (QueryTextExtents.string_len).
166+ declared := false
167+ for _, n := range r.Node.Children {
168+ if n.Kind == "field" && n.Attr["name"] == s {
169+ declared = true
170+ }
171+ }
172+ for _, list := range r.Lists {
173+ if !declared && s == list.Node.Attr["name"]+"_len" {
174+ return "len(" + list.Param + ")"
175+ }
176+ }
177+ if list := r.Derived[s]; list != "" {
178+ return "len(" + list + ")"
179+ }
180+ return "int(" + paramName(s) + ")"
181+ }
182+ // Derived lengths are cast only after checking their wire width.
183+ for _, f := range append(append([]Field{}, r.Fields...), r.Params...) {
184+ if f.Kind != "field" || r.Derived[f.Node.Attr["name"]] == "" {
185+ continue
186+ }
187+ if f.Type.Size < 8 {
188+ fmt.Fprintf(&b, "if uint64(%s)>%d { b.Fail(xturbo.ErrBadLength); return 0 };", ref(f.Node.Attr["name"]), uint64(1)<<(8*f.Type.Size)-1)
189+ }
190+ }
191+ if r.DataByte != nil {
192+ f := r.DataByte
193+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
194+ fmt.Fprintf(&b, "if len(%s)>255 { b.Fail(xturbo.ErrBadLength); return 0 };", list)
195+ }
196+ }
197+ for _, f := range r.Lists {
198+ if f.Expr != nil && !(f.Expr.Kind == "fieldref" && r.Derived[f.Expr.Text] != "") {
199+ ex, err := renderExpr(f.Expr, ref, m)
200+ if err != nil {
201+ return "", err
202+ }
203+ fmt.Fprintf(&b, "if len(%s)!=%s { b.Fail(xturbo.ErrBadLength); return 0 };", f.Param, ex)
204+ }
205+ }
206+ body := fmt.Sprint((r.Fixed + 3) &^ 3)
207+ if len(r.Lists) > 0 {
208+ b.WriteString("size:=0;")
209+ for _, f := range r.Fields {
210+ if f.Kind == "list" {
211+ if f.Type.Variable {
212+ fmt.Fprintf(&b, "for i:=range %s { size+=%s[i].Size() };", f.Param, f.Param)
213+ } else {
214+ fmt.Fprintf(&b, "size+=len(%s)*%d;", f.Param, f.Type.Size)
215+ }
216+ } else if f.Align > 0 {
217+ fmt.Fprintf(&b, "size=(size+%d)&^%d;", f.Align-1, f.Align-1)
218+ } else {
219+ fmt.Fprintf(&b, "size+=%d;", f.Size)
220+ }
221+ }
222+ b.WriteString("size=(size+3)&^3;")
223+ body = "size"
224+ }
116 major := fmt.Sprint(r.Opcode)225 major := fmt.Sprint(r.Opcode)
117 data := "0"226 data := "0"
118 if m.ExtName != "" {227 if m.ExtName != "" {
@@ -122,31 +231,79 @@ func requestDecl(m *Module, r Request) (string, error) {
122 } else if r.DataByte != nil {231 } else if r.DataByte != nil {
123 f := r.DataByte232 f := r.DataByte
124 if f.Type.Base == "bool" {233 if f.Type.Base == "bool" {
125- fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", f.Param)234+ value := f.Param
235+ if f.Kind == "exprfield" {
236+ ex, err := renderExpr(f.Expr, ref, m)
237+ if err != nil {
238+ return "", err
239+ }
240+ value = "(" + ex + " != 0)"
241+ }
242+ fmt.Fprintf(&b, "var data uint8; if %s { data=1 };", value)
126 data = "data"243 data = "data"
127 } else {244 } else {
128- data = "uint8(" + f.Param + ")"245+ data = "uint8(" + ref(f.Node.Attr["name"]) + ")"
129 }246 }
130 }247 }
131- fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%d); if p==nil { return 0 };\n", major, data, r.Fixed)248+ fmt.Fprintf(&b, "p,seq:=b.Request(%s,%s,%s); if p==nil { return 0 };\n", major, data, body)
249+ if len(r.Lists) > 0 {
250+ b.WriteString("off:=0;")
251+ }
132 for _, f := range r.Fields {252 for _, f := range r.Fields {
133 if f.Kind == "pad" {253 if f.Kind == "pad" {
254+ if len(r.Lists) > 0 {
255+ if f.Align > 0 {
256+ fmt.Fprintf(&b, "off=(off+%d)&^%d;", f.Align-1, f.Align-1)
257+ } else {
258+ fmt.Fprintf(&b, "off+=%d;", f.Size)
259+ }
260+ }
261+ continue
262+ }
263+ if f.Kind == "list" {
264+ if f.GoType == "*[32]byte" {
265+ fmt.Fprintf(&b, "copy(p[off:],%s[:]);", f.Param)
266+ } else if f.GoType == "string" || f.GoType == "[]byte" {
267+ fmt.Fprintf(&b, "copy(p[off:],%s); off+=len(%s);", f.Param, f.Param)
268+ } else {
269+ fmt.Fprintf(&b, "for i:=range %s {", f.Param)
270+ if isScalar(f.Type) {
271+ b.WriteString(putScalar(f.Type, f.Param+"[i]", "p[off:]"))
272+ } else {
273+ fmt.Fprintf(&b, "%s[i].Put(p[off:]);", f.Param)
274+ }
275+ if f.Type.Variable {
276+ fmt.Fprintf(&b, "off+=%s[i].Size();", f.Param)
277+ } else {
278+ fmt.Fprintf(&b, "off+=%d;", f.Type.Size)
279+ }
280+ b.WriteString("};")
281+ }
134 continue282 continue
135 }283 }
136 src := f.Param284 src := f.Param
285+ if list := r.Derived[f.Node.Attr["name"]]; list != "" {
286+ src = "len(" + list + ")"
287+ }
137 if f.Kind == "exprfield" {288 if f.Kind == "exprfield" {
138 var err error289 var err error
139- src, err = renderExpr(f.Expr, func(s string) string { return "int(" + paramName(s) + ")" }, m)290+ src, err = renderExpr(f.Expr, ref, m)
140 if err != nil {291 if err != nil {
141 return "", err292 return "", err
142 }293 }
143 }294 }
144 dst := fmt.Sprintf("p[%d:]", f.Off)295 dst := fmt.Sprintf("p[%d:]", f.Off)
296+ if len(r.Lists) > 0 {
297+ dst = "p[off:]"
298+ }
145 if isScalar(f.Type) {299 if isScalar(f.Type) {
146 b.WriteString(putScalar(f.Type, src, dst))300 b.WriteString(putScalar(f.Type, src, dst))
147 } else {301 } else {
148 fmt.Fprintf(&b, "%s.Put(%s);", src, dst)302 fmt.Fprintf(&b, "%s.Put(%s);", src, dst)
149 }303 }
304+ if len(r.Lists) > 0 {
305+ fmt.Fprintf(&b, "off+=%d;", f.Size)
306+ }
150 }307 }
151 b.WriteString("return seq }\n")308 b.WriteString("return seq }\n")
152 return b.String(), nil309 return b.String(), nil
M cmd/xtgen/resolve_test.go +33 -0
@@ -130,3 +130,36 @@ func TestFixedRequests(t *testing.T) {
130130 }
131131 }
132132 }
133+
134+func TestListResolution(t *testing.T) {
135+ for _, m := range testModules(t) {
136+ rs, err := resolveRequests(m)
137+ if err != nil {
138+ t.Fatal(err)
139+ }
140+ for _, r := range rs {
141+ switch r.Name {
142+ case "InternAtom":
143+ if r.Derived["name_len"] != "name" || len(r.Params) != 2 {
144+ t.Fatal("InternAtom derived length")
145+ }
146+ case "ChangeProperty":
147+ if len(r.Derived) != 0 || len(r.Params) != 7 {
148+ t.Fatal("ChangeProperty explicit expression fields")
149+ }
150+ case "AddGlyphs":
151+ if r.Derived["glyphs_len"] != "" {
152+ t.Fatal("shared count must remain explicit")
153+ }
154+ case "QueryClientIds":
155+ if r.Derived["num_specs"] != "specs" || r.Params[0].GoType != "[]ClientIdSpec" {
156+ t.Fatal("fixed struct list")
157+ }
158+ case "SetFontPath":
159+ if r.Params[0].GoType != "[]Str" || !r.Lists[0].Type.Variable {
160+ t.Fatal("variable struct list")
161+ }
162+ }
163+ }
164+ }
165+}
@@ -130,3 +130,36 @@ func TestFixedRequests(t *testing.T) {
130 }130 }
131 }131 }
132 }132 }
133+
134+func TestListResolution(t *testing.T) {
135+ for _, m := range testModules(t) {
136+ rs, err := resolveRequests(m)
137+ if err != nil {
138+ t.Fatal(err)
139+ }
140+ for _, r := range rs {
141+ switch r.Name {
142+ case "InternAtom":
143+ if r.Derived["name_len"] != "name" || len(r.Params) != 2 {
144+ t.Fatal("InternAtom derived length")
145+ }
146+ case "ChangeProperty":
147+ if len(r.Derived) != 0 || len(r.Params) != 7 {
148+ t.Fatal("ChangeProperty explicit expression fields")
149+ }
150+ case "AddGlyphs":
151+ if r.Derived["glyphs_len"] != "" {
152+ t.Fatal("shared count must remain explicit")
153+ }
154+ case "QueryClientIds":
155+ if r.Derived["num_specs"] != "specs" || r.Params[0].GoType != "[]ClientIdSpec" {
156+ t.Fatal("fixed struct list")
157+ }
158+ case "SetFontPath":
159+ if r.Params[0].GoType != "[]Str" || !r.Lists[0].Type.Variable {
160+ t.Fatal("variable struct list")
161+ }
162+ }
163+ }
164+ }
165+}
M internal/xtest/README.md +5 -0
@@ -17,3 +17,8 @@ No runtime Conn is needed at this phase.
1717
1818 T2.4 should extend the independent encoder and capture cases for list requests.
1919 Replies, events and runtime integration belong to their subsequent tasks.
20+
21+T2.4 adds InternAtom, ChangeProperty and XRes QueryClientIds. A GetProperty
22+read-back validates the property contents. XRes's major opcode is negotiated;
23+QueryVersion 1.2 precedes the ClientIdSpec-list query. The capture is independent
24+of generated code, including counts, framing, and padding.
@@ -17,3 +17,8 @@ No runtime Conn is needed at this phase.
17 17
18 T2.4 should extend the independent encoder and capture cases for list requests.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.19 Replies, events and runtime integration belong to their subsequent tasks.
20+
21+T2.4 adds InternAtom, ChangeProperty and XRes QueryClientIds. A GetProperty
22+read-back validates the property contents. XRes's major opcode is negotiated;
23+QueryVersion 1.2 precedes the ClientIdSpec-list query. The capture is independent
24+of generated code, including counts, framing, and padding.
M internal/xtest/capture_test.go +67 -1
@@ -148,6 +148,65 @@ func TestCaptureRequests(t *testing.T) {
148148 if geom[0] != 1 || binary.LittleEndian.Uint16(geom[2:]) != 4 {
149149 t.Fatalf("MapWindow/GetGeometry rejected: %x", geom)
150150 }
151+
152+ // InternAtom, ChangeProperty and XRes QueryClientIds exercise derived lengths,
153+ // byte expressions and fixed-struct lists with independently assembled bytes.
154+ intern := []byte{16, 0, 4, 0, 7, 0, 0, 0, 'X', 'T', 'U', 'R', 'B', 'O', '_', 0}
155+ write(intern)
156+ atomReply := packet()
157+ if atomReply[0] != 1 {
158+ t.Fatalf("InternAtom: %x", atomReply)
159+ }
160+ atom := binary.LittleEndian.Uint32(atomReply[8:])
161+ property := make([]byte, 28)
162+ property[0] = 18
163+ property[2] = 7
164+ binary.LittleEndian.PutUint32(property[4:], root)
165+ binary.LittleEndian.PutUint32(property[8:], atom)
166+ binary.LittleEndian.PutUint32(property[12:], 31)
167+ property[16] = 8
168+ binary.LittleEndian.PutUint32(property[20:], 3)
169+ copy(property[24:], "abc")
170+ write(property)
171+ // A successful GetProperty reply proves the preceding write was accepted.
172+ get := make([]byte, 24)
173+ get[0] = 20
174+ get[2] = 6
175+ binary.LittleEndian.PutUint32(get[4:], root)
176+ binary.LittleEndian.PutUint32(get[8:], atom)
177+ binary.LittleEndian.PutUint32(get[20:], 1)
178+ write(get)
179+ got := packet()
180+ if got[0] != 1 || string(got[32:35]) != "abc" {
181+ t.Fatalf("ChangeProperty: %x", got)
182+ }
183+ resName := "X-Resource"
184+ queryRes := make([]byte, 20)
185+ queryRes[0] = 98
186+ queryRes[2] = 5
187+ queryRes[4] = byte(len(resName))
188+ copy(queryRes[8:], resName)
189+ write(queryRes)
190+ resExt := packet()
191+ if resExt[0] != 1 || resExt[8] != 1 {
192+ t.Fatalf("XRes unavailable: %x", resExt)
193+ }
194+ resMajor := resExt[9]
195+ resVersion := []byte{resMajor, 0, 2, 0, 1, 2, 0, 0}
196+ write(resVersion)
197+ if p := packet(); p[0] != 1 {
198+ t.Fatalf("XRes version: %x", p)
199+ }
200+ ids := make([]byte, 16)
201+ ids[0] = resMajor
202+ ids[1] = 4
203+ ids[2] = 4
204+ binary.LittleEndian.PutUint32(ids[4:], 1)
205+ binary.LittleEndian.PutUint32(ids[12:], 1)
206+ write(ids)
207+ if p := packet(); p[0] != 1 {
208+ t.Fatalf("QueryClientIds: %x", p)
209+ }
151210 // Closing the client drains the request direction; wait before inspecting tee.
152211 client.Close()
153212 select {
@@ -172,14 +231,21 @@ func TestCaptureRequests(t *testing.T) {
172231 captured["xproto/MapWindow"] = p
173232 case 14:
174233 captured["xproto/GetGeometry"] = p
234+ case 16:
235+ captured["xproto/InternAtom"] = p
236+ case 18:
237+ captured["xproto/ChangeProperty"] = p
175238 default:
239+ if p[0] == resMajor && p[1] == 4 {
240+ captured["res/QueryClientIds"] = p
241+ }
176242 if p[0] == major {
177243 captured["xfixes/QueryVersion"] = p
178244 }
179245 }
180246 requests = requests[size:]
181247 }
182- if len(captured) != 3 {
248+ if len(captured) != 6 {
183249 t.Fatal("missing captured requests")
184250 }
185251 for name, p := range captured {
@@ -148,6 +148,65 @@ func TestCaptureRequests(t *testing.T) {
148 if geom[0] != 1 || binary.LittleEndian.Uint16(geom[2:]) != 4 {148 if geom[0] != 1 || binary.LittleEndian.Uint16(geom[2:]) != 4 {
149 t.Fatalf("MapWindow/GetGeometry rejected: %x", geom)149 t.Fatalf("MapWindow/GetGeometry rejected: %x", geom)
150 }150 }
151+
152+ // InternAtom, ChangeProperty and XRes QueryClientIds exercise derived lengths,
153+ // byte expressions and fixed-struct lists with independently assembled bytes.
154+ intern := []byte{16, 0, 4, 0, 7, 0, 0, 0, 'X', 'T', 'U', 'R', 'B', 'O', '_', 0}
155+ write(intern)
156+ atomReply := packet()
157+ if atomReply[0] != 1 {
158+ t.Fatalf("InternAtom: %x", atomReply)
159+ }
160+ atom := binary.LittleEndian.Uint32(atomReply[8:])
161+ property := make([]byte, 28)
162+ property[0] = 18
163+ property[2] = 7
164+ binary.LittleEndian.PutUint32(property[4:], root)
165+ binary.LittleEndian.PutUint32(property[8:], atom)
166+ binary.LittleEndian.PutUint32(property[12:], 31)
167+ property[16] = 8
168+ binary.LittleEndian.PutUint32(property[20:], 3)
169+ copy(property[24:], "abc")
170+ write(property)
171+ // A successful GetProperty reply proves the preceding write was accepted.
172+ get := make([]byte, 24)
173+ get[0] = 20
174+ get[2] = 6
175+ binary.LittleEndian.PutUint32(get[4:], root)
176+ binary.LittleEndian.PutUint32(get[8:], atom)
177+ binary.LittleEndian.PutUint32(get[20:], 1)
178+ write(get)
179+ got := packet()
180+ if got[0] != 1 || string(got[32:35]) != "abc" {
181+ t.Fatalf("ChangeProperty: %x", got)
182+ }
183+ resName := "X-Resource"
184+ queryRes := make([]byte, 20)
185+ queryRes[0] = 98
186+ queryRes[2] = 5
187+ queryRes[4] = byte(len(resName))
188+ copy(queryRes[8:], resName)
189+ write(queryRes)
190+ resExt := packet()
191+ if resExt[0] != 1 || resExt[8] != 1 {
192+ t.Fatalf("XRes unavailable: %x", resExt)
193+ }
194+ resMajor := resExt[9]
195+ resVersion := []byte{resMajor, 0, 2, 0, 1, 2, 0, 0}
196+ write(resVersion)
197+ if p := packet(); p[0] != 1 {
198+ t.Fatalf("XRes version: %x", p)
199+ }
200+ ids := make([]byte, 16)
201+ ids[0] = resMajor
202+ ids[1] = 4
203+ ids[2] = 4
204+ binary.LittleEndian.PutUint32(ids[4:], 1)
205+ binary.LittleEndian.PutUint32(ids[12:], 1)
206+ write(ids)
207+ if p := packet(); p[0] != 1 {
208+ t.Fatalf("QueryClientIds: %x", p)
209+ }
151 // Closing the client drains the request direction; wait before inspecting tee.210 // Closing the client drains the request direction; wait before inspecting tee.
152 client.Close()211 client.Close()
153 select {212 select {
@@ -172,14 +231,21 @@ func TestCaptureRequests(t *testing.T) {
172 captured["xproto/MapWindow"] = p231 captured["xproto/MapWindow"] = p
173 case 14:232 case 14:
174 captured["xproto/GetGeometry"] = p233 captured["xproto/GetGeometry"] = p
234+ case 16:
235+ captured["xproto/InternAtom"] = p
236+ case 18:
237+ captured["xproto/ChangeProperty"] = p
175 default:238 default:
239+ if p[0] == resMajor && p[1] == 4 {
240+ captured["res/QueryClientIds"] = p
241+ }
176 if p[0] == major {242 if p[0] == major {
177 captured["xfixes/QueryVersion"] = p243 captured["xfixes/QueryVersion"] = p
178 }244 }
179 }245 }
180 requests = requests[size:]246 requests = requests[size:]
181 }247 }
182- if len(captured) != 3 {248+ if len(captured) != 6 {
183 t.Fatal("missing captured requests")249 t.Fatal("missing captured requests")
184 }250 }
185 for name, p := range captured {251 for name, p := range captured {
A lists_test.go +87 -0
@@ -0,0 +1,87 @@
1+package xturbo_test
2+
3+import (
4+ "bytes"
5+ "encoding/binary"
6+ "strings"
7+ "testing"
8+
9+ "bnema.dev/xturbo"
10+ "bnema.dev/xturbo/internal/xtest"
11+ "bnema.dev/xturbo/render"
12+ "bnema.dev/xturbo/res"
13+ "bnema.dev/xturbo/xproto"
14+)
15+
16+func TestListGoldens(t *testing.T) {
17+ for _, name := range []string{"xproto/InternAtom", "xproto/ChangeProperty", "res/QueryClientIds"} {
18+ t.Run(name, func(t *testing.T) {
19+ want, err := xtest.LoadHex("testdata/golden/" + name + ".req.hex")
20+ if err != nil {
21+ t.Fatal(err)
22+ }
23+ b := xturbo.NewBuf(0)
24+ switch name {
25+ case "xproto/InternAtom":
26+ xproto.InternAtom(b, false, "XTURBO_")
27+ case "xproto/ChangeProperty":
28+ xproto.ChangeProperty(b, xproto.PropModeReplace, xproto.Window(binary.LittleEndian.Uint32(want[4:])), xproto.Atom(binary.LittleEndian.Uint32(want[8:])), xproto.AtomString, 8, 3, []byte("abc"))
29+ case "res/QueryClientIds":
30+ var ext xturbo.ExtTable
31+ ext.Set(xturbo.ExtRes, want[0], 0, 0)
32+ b.Ext = &ext
33+ res.QueryClientIds(b, []res.ClientIdSpec{{Client: 0, Mask: res.ClientIdMaskClientXID}})
34+ }
35+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
36+ t.Fatalf("err %v got %x want %x", b.Err(), b.Bytes(), want)
37+ }
38+ })
39+ }
40+}
41+func TestListLengths(t *testing.T) {
42+ b := xturbo.NewBuf(0)
43+ if xproto.ChangeProperty(b, 0, 1, 1, 1, 16, 2, []byte{1, 2}) != 0 || b.Err() != xturbo.ErrBadLength || b.Len() != 0 {
44+ t.Fatal("expression length mismatch")
45+ }
46+ b = xturbo.NewBuf(0)
47+ if xproto.InternAtom(b, false, strings.Repeat("x", 65536)) != 0 || b.Err() != xturbo.ErrBadLength {
48+ t.Fatal("derived length truncation")
49+ }
50+ b = xturbo.NewBuf(0)
51+ xproto.SetFontPath(b, []xproto.Str{{NameLen: 3, Name: "abc"}, {NameLen: 1, Name: "d"}})
52+ want := []byte{51, 0, 4, 0, 2, 0, 0, 0, 3, 'a', 'b', 'c', 1, 'd', 0, 0}
53+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
54+ t.Fatalf("variable structs: %x err %v", b.Bytes(), b.Err())
55+ }
56+ b = xturbo.NewBuf(0)
57+ xproto.QueryTextExtents(b, 1, []xproto.Char2b{{Byte1: 0, Byte2: 'a'}})
58+ if b.Bytes()[1] != 1 {
59+ t.Fatal("implicit list length exprfield")
60+ }
61+ var ext xturbo.ExtTable
62+ ext.Set(xturbo.ExtRender, 140, 0, 0)
63+ b = xturbo.NewBuf(0)
64+ b.Ext = &ext
65+ if render.AddGlyphs(b, 1, 2, []uint32{1}, nil, nil) != 0 || b.Err() != xturbo.ErrBadLength {
66+ t.Fatal("shared length must remain explicit")
67+ }
68+}
69+func TestAllocListRequests(t *testing.T) {
70+ b := xturbo.NewBuf(0)
71+ data := make([]byte, 4096)
72+ specs := []res.ClientIdSpec{{Client: 1, Mask: res.ClientIdMaskClientXID}}
73+ var ext xturbo.ExtTable
74+ ext.Set(xturbo.ExtRes, 141, 0, 0)
75+ b.Ext = &ext
76+ if n := testing.AllocsPerRun(1000, func() {
77+ b.Reset()
78+ xproto.InternAtom(b, false, "WM_CLASS")
79+ xproto.ChangeProperty(b, 0, 1, 1, 1, 8, 4096, data)
80+ res.QueryClientIds(b, specs)
81+ }); n != 0 {
82+ t.Fatal(n)
83+ }
84+ if b.Err() != nil {
85+ t.Fatal(b.Err())
86+ }
87+}
@@ -0,0 +1,87 @@
1+package xturbo_test
2+
3+import (
4+ "bytes"
5+ "encoding/binary"
6+ "strings"
7+ "testing"
8+
9+ "bnema.dev/xturbo"
10+ "bnema.dev/xturbo/internal/xtest"
11+ "bnema.dev/xturbo/render"
12+ "bnema.dev/xturbo/res"
13+ "bnema.dev/xturbo/xproto"
14+)
15+
16+func TestListGoldens(t *testing.T) {
17+ for _, name := range []string{"xproto/InternAtom", "xproto/ChangeProperty", "res/QueryClientIds"} {
18+ t.Run(name, func(t *testing.T) {
19+ want, err := xtest.LoadHex("testdata/golden/" + name + ".req.hex")
20+ if err != nil {
21+ t.Fatal(err)
22+ }
23+ b := xturbo.NewBuf(0)
24+ switch name {
25+ case "xproto/InternAtom":
26+ xproto.InternAtom(b, false, "XTURBO_")
27+ case "xproto/ChangeProperty":
28+ xproto.ChangeProperty(b, xproto.PropModeReplace, xproto.Window(binary.LittleEndian.Uint32(want[4:])), xproto.Atom(binary.LittleEndian.Uint32(want[8:])), xproto.AtomString, 8, 3, []byte("abc"))
29+ case "res/QueryClientIds":
30+ var ext xturbo.ExtTable
31+ ext.Set(xturbo.ExtRes, want[0], 0, 0)
32+ b.Ext = &ext
33+ res.QueryClientIds(b, []res.ClientIdSpec{{Client: 0, Mask: res.ClientIdMaskClientXID}})
34+ }
35+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
36+ t.Fatalf("err %v got %x want %x", b.Err(), b.Bytes(), want)
37+ }
38+ })
39+ }
40+}
41+func TestListLengths(t *testing.T) {
42+ b := xturbo.NewBuf(0)
43+ if xproto.ChangeProperty(b, 0, 1, 1, 1, 16, 2, []byte{1, 2}) != 0 || b.Err() != xturbo.ErrBadLength || b.Len() != 0 {
44+ t.Fatal("expression length mismatch")
45+ }
46+ b = xturbo.NewBuf(0)
47+ if xproto.InternAtom(b, false, strings.Repeat("x", 65536)) != 0 || b.Err() != xturbo.ErrBadLength {
48+ t.Fatal("derived length truncation")
49+ }
50+ b = xturbo.NewBuf(0)
51+ xproto.SetFontPath(b, []xproto.Str{{NameLen: 3, Name: "abc"}, {NameLen: 1, Name: "d"}})
52+ want := []byte{51, 0, 4, 0, 2, 0, 0, 0, 3, 'a', 'b', 'c', 1, 'd', 0, 0}
53+ if b.Err() != nil || !bytes.Equal(b.Bytes(), want) {
54+ t.Fatalf("variable structs: %x err %v", b.Bytes(), b.Err())
55+ }
56+ b = xturbo.NewBuf(0)
57+ xproto.QueryTextExtents(b, 1, []xproto.Char2b{{Byte1: 0, Byte2: 'a'}})
58+ if b.Bytes()[1] != 1 {
59+ t.Fatal("implicit list length exprfield")
60+ }
61+ var ext xturbo.ExtTable
62+ ext.Set(xturbo.ExtRender, 140, 0, 0)
63+ b = xturbo.NewBuf(0)
64+ b.Ext = &ext
65+ if render.AddGlyphs(b, 1, 2, []uint32{1}, nil, nil) != 0 || b.Err() != xturbo.ErrBadLength {
66+ t.Fatal("shared length must remain explicit")
67+ }
68+}
69+func TestAllocListRequests(t *testing.T) {
70+ b := xturbo.NewBuf(0)
71+ data := make([]byte, 4096)
72+ specs := []res.ClientIdSpec{{Client: 1, Mask: res.ClientIdMaskClientXID}}
73+ var ext xturbo.ExtTable
74+ ext.Set(xturbo.ExtRes, 141, 0, 0)
75+ b.Ext = &ext
76+ if n := testing.AllocsPerRun(1000, func() {
77+ b.Reset()
78+ xproto.InternAtom(b, false, "WM_CLASS")
79+ xproto.ChangeProperty(b, 0, 1, 1, 1, 8, 4096, data)
80+ res.QueryClientIds(b, specs)
81+ }); n != 0 {
82+ t.Fatal(n)
83+ }
84+ if b.Err() != nil {
85+ t.Fatal(b.Err())
86+ }
87+}
M render/requests_generated.go +723 -0
@@ -59,6 +59,40 @@ func QueryPictIndexValues(b *xturbo.Buf, format Pictformat) xturbo.Seq {
5959 return seq
6060 }
6161
62+func SetPictureClipRectangles(b *xturbo.Buf, picture Picture, clipXOrigin int16, clipYOrigin int16, rectangles []xproto.Rectangle) xturbo.Seq {
63+ size := 0
64+ size += 4
65+ size += 2
66+ size += 2
67+ size += len(rectangles) * 8
68+ size = (size + 3) &^ 3
69+ if b.Ext == nil {
70+ b.Fail(xturbo.ErrExtMissing)
71+ return 0
72+ }
73+ major := b.Ext.Major(xturbo.ExtRender)
74+ if major == 0 {
75+ b.Fail(xturbo.ErrExtMissing)
76+ return 0
77+ }
78+ p, seq := b.Request(major, 6, size)
79+ if p == nil {
80+ return 0
81+ }
82+ off := 0
83+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
84+ off += 4
85+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
86+ off += 2
87+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
88+ off += 2
89+ for i := range rectangles {
90+ rectangles[i].Put(p[off:])
91+ off += 8
92+ }
93+ return seq
94+}
95+
6296 func FreePicture(b *xturbo.Buf, picture Picture) xturbo.Seq {
6397 if b.Ext == nil {
6498 b.Fail(xturbo.ErrExtMissing)
@@ -106,6 +140,186 @@ func Composite(b *xturbo.Buf, op PictOp, src Picture, mask Picture, dst Picture,
106140 return seq
107141 }
108142
143+func Trapezoids(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, traps []Trapezoid) xturbo.Seq {
144+ size := 0
145+ size += 1
146+ size += 3
147+ size += 4
148+ size += 4
149+ size += 4
150+ size += 2
151+ size += 2
152+ size += len(traps) * 40
153+ size = (size + 3) &^ 3
154+ if b.Ext == nil {
155+ b.Fail(xturbo.ErrExtMissing)
156+ return 0
157+ }
158+ major := b.Ext.Major(xturbo.ExtRender)
159+ if major == 0 {
160+ b.Fail(xturbo.ErrExtMissing)
161+ return 0
162+ }
163+ p, seq := b.Request(major, 10, size)
164+ if p == nil {
165+ return 0
166+ }
167+ off := 0
168+ p[off:][0] = byte(op)
169+ off += 1
170+ off += 3
171+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
172+ off += 4
173+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
176+ off += 4
177+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
178+ off += 2
179+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
180+ off += 2
181+ for i := range traps {
182+ traps[i].Put(p[off:])
183+ off += 40
184+ }
185+ return seq
186+}
187+
188+func Triangles(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, triangles []Triangle) xturbo.Seq {
189+ size := 0
190+ size += 1
191+ size += 3
192+ size += 4
193+ size += 4
194+ size += 4
195+ size += 2
196+ size += 2
197+ size += len(triangles) * 24
198+ size = (size + 3) &^ 3
199+ if b.Ext == nil {
200+ b.Fail(xturbo.ErrExtMissing)
201+ return 0
202+ }
203+ major := b.Ext.Major(xturbo.ExtRender)
204+ if major == 0 {
205+ b.Fail(xturbo.ErrExtMissing)
206+ return 0
207+ }
208+ p, seq := b.Request(major, 11, size)
209+ if p == nil {
210+ return 0
211+ }
212+ off := 0
213+ p[off:][0] = byte(op)
214+ off += 1
215+ off += 3
216+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
217+ off += 4
218+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
219+ off += 4
220+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
221+ off += 4
222+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
223+ off += 2
224+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
225+ off += 2
226+ for i := range triangles {
227+ triangles[i].Put(p[off:])
228+ off += 24
229+ }
230+ return seq
231+}
232+
233+func TriStrip(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
234+ size := 0
235+ size += 1
236+ size += 3
237+ size += 4
238+ size += 4
239+ size += 4
240+ size += 2
241+ size += 2
242+ size += len(points) * 8
243+ size = (size + 3) &^ 3
244+ if b.Ext == nil {
245+ b.Fail(xturbo.ErrExtMissing)
246+ return 0
247+ }
248+ major := b.Ext.Major(xturbo.ExtRender)
249+ if major == 0 {
250+ b.Fail(xturbo.ErrExtMissing)
251+ return 0
252+ }
253+ p, seq := b.Request(major, 12, size)
254+ if p == nil {
255+ return 0
256+ }
257+ off := 0
258+ p[off:][0] = byte(op)
259+ off += 1
260+ off += 3
261+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
262+ off += 4
263+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
264+ off += 4
265+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
266+ off += 4
267+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
268+ off += 2
269+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
270+ off += 2
271+ for i := range points {
272+ points[i].Put(p[off:])
273+ off += 8
274+ }
275+ return seq
276+}
277+
278+func TriFan(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
279+ size := 0
280+ size += 1
281+ size += 3
282+ size += 4
283+ size += 4
284+ size += 4
285+ size += 2
286+ size += 2
287+ size += len(points) * 8
288+ size = (size + 3) &^ 3
289+ if b.Ext == nil {
290+ b.Fail(xturbo.ErrExtMissing)
291+ return 0
292+ }
293+ major := b.Ext.Major(xturbo.ExtRender)
294+ if major == 0 {
295+ b.Fail(xturbo.ErrExtMissing)
296+ return 0
297+ }
298+ p, seq := b.Request(major, 13, size)
299+ if p == nil {
300+ return 0
301+ }
302+ off := 0
303+ p[off:][0] = byte(op)
304+ off += 1
305+ off += 3
306+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
307+ off += 4
308+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
309+ off += 4
310+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
311+ off += 4
312+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
313+ off += 2
314+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
315+ off += 2
316+ for i := range points {
317+ points[i].Put(p[off:])
318+ off += 8
319+ }
320+ return seq
321+}
322+
109323 func CreateGlyphSet(b *xturbo.Buf, gsid Glyphset, format Pictformat) xturbo.Seq {
110324 if b.Ext == nil {
111325 b.Fail(xturbo.ErrExtMissing)
@@ -162,6 +376,255 @@ func FreeGlyphSet(b *xturbo.Buf, glyphset Glyphset) xturbo.Seq {
162376 return seq
163377 }
164378
379+func AddGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphsLen uint32, glyphids []uint32, glyphs []Glyphinfo, data []byte) xturbo.Seq {
380+ if len(glyphids) != int(glyphsLen) {
381+ b.Fail(xturbo.ErrBadLength)
382+ return 0
383+ }
384+ if len(glyphs) != int(glyphsLen) {
385+ b.Fail(xturbo.ErrBadLength)
386+ return 0
387+ }
388+ size := 0
389+ size += 4
390+ size += 4
391+ size += len(glyphids) * 4
392+ size += len(glyphs) * 12
393+ size += len(data) * 1
394+ size = (size + 3) &^ 3
395+ if b.Ext == nil {
396+ b.Fail(xturbo.ErrExtMissing)
397+ return 0
398+ }
399+ major := b.Ext.Major(xturbo.ExtRender)
400+ if major == 0 {
401+ b.Fail(xturbo.ErrExtMissing)
402+ return 0
403+ }
404+ p, seq := b.Request(major, 20, size)
405+ if p == nil {
406+ return 0
407+ }
408+ off := 0
409+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
410+ off += 4
411+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphsLen))
412+ off += 4
413+ for i := range glyphids {
414+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphids[i]))
415+ off += 4
416+ }
417+ for i := range glyphs {
418+ glyphs[i].Put(p[off:])
419+ off += 12
420+ }
421+ copy(p[off:], data)
422+ off += len(data)
423+ return seq
424+}
425+
426+func FreeGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphs []Glyph) xturbo.Seq {
427+ size := 0
428+ size += 4
429+ size += len(glyphs) * 4
430+ size = (size + 3) &^ 3
431+ if b.Ext == nil {
432+ b.Fail(xturbo.ErrExtMissing)
433+ return 0
434+ }
435+ major := b.Ext.Major(xturbo.ExtRender)
436+ if major == 0 {
437+ b.Fail(xturbo.ErrExtMissing)
438+ return 0
439+ }
440+ p, seq := b.Request(major, 22, size)
441+ if p == nil {
442+ return 0
443+ }
444+ off := 0
445+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
446+ off += 4
447+ for i := range glyphs {
448+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphs[i]))
449+ off += 4
450+ }
451+ return seq
452+}
453+
454+func CompositeGlyphs8(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
455+ size := 0
456+ size += 1
457+ size += 3
458+ size += 4
459+ size += 4
460+ size += 4
461+ size += 4
462+ size += 2
463+ size += 2
464+ size += len(glyphcmds) * 1
465+ size = (size + 3) &^ 3
466+ if b.Ext == nil {
467+ b.Fail(xturbo.ErrExtMissing)
468+ return 0
469+ }
470+ major := b.Ext.Major(xturbo.ExtRender)
471+ if major == 0 {
472+ b.Fail(xturbo.ErrExtMissing)
473+ return 0
474+ }
475+ p, seq := b.Request(major, 23, size)
476+ if p == nil {
477+ return 0
478+ }
479+ off := 0
480+ p[off:][0] = byte(op)
481+ off += 1
482+ off += 3
483+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
484+ off += 4
485+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
486+ off += 4
487+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
488+ off += 4
489+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
490+ off += 4
491+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
492+ off += 2
493+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
494+ off += 2
495+ copy(p[off:], glyphcmds)
496+ off += len(glyphcmds)
497+ return seq
498+}
499+
500+func CompositeGlyphs16(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
501+ size := 0
502+ size += 1
503+ size += 3
504+ size += 4
505+ size += 4
506+ size += 4
507+ size += 4
508+ size += 2
509+ size += 2
510+ size += len(glyphcmds) * 1
511+ size = (size + 3) &^ 3
512+ if b.Ext == nil {
513+ b.Fail(xturbo.ErrExtMissing)
514+ return 0
515+ }
516+ major := b.Ext.Major(xturbo.ExtRender)
517+ if major == 0 {
518+ b.Fail(xturbo.ErrExtMissing)
519+ return 0
520+ }
521+ p, seq := b.Request(major, 24, size)
522+ if p == nil {
523+ return 0
524+ }
525+ off := 0
526+ p[off:][0] = byte(op)
527+ off += 1
528+ off += 3
529+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
530+ off += 4
531+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
532+ off += 4
533+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
534+ off += 4
535+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
536+ off += 4
537+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
538+ off += 2
539+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
540+ off += 2
541+ copy(p[off:], glyphcmds)
542+ off += len(glyphcmds)
543+ return seq
544+}
545+
546+func CompositeGlyphs32(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
547+ size := 0
548+ size += 1
549+ size += 3
550+ size += 4
551+ size += 4
552+ size += 4
553+ size += 4
554+ size += 2
555+ size += 2
556+ size += len(glyphcmds) * 1
557+ size = (size + 3) &^ 3
558+ if b.Ext == nil {
559+ b.Fail(xturbo.ErrExtMissing)
560+ return 0
561+ }
562+ major := b.Ext.Major(xturbo.ExtRender)
563+ if major == 0 {
564+ b.Fail(xturbo.ErrExtMissing)
565+ return 0
566+ }
567+ p, seq := b.Request(major, 25, size)
568+ if p == nil {
569+ return 0
570+ }
571+ off := 0
572+ p[off:][0] = byte(op)
573+ off += 1
574+ off += 3
575+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
576+ off += 4
577+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
578+ off += 4
579+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
580+ off += 4
581+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
582+ off += 4
583+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
584+ off += 2
585+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
586+ off += 2
587+ copy(p[off:], glyphcmds)
588+ off += len(glyphcmds)
589+ return seq
590+}
591+
592+func FillRectangles(b *xturbo.Buf, op PictOp, dst Picture, color Color, rects []xproto.Rectangle) xturbo.Seq {
593+ size := 0
594+ size += 1
595+ size += 3
596+ size += 4
597+ size += 8
598+ size += len(rects) * 8
599+ size = (size + 3) &^ 3
600+ if b.Ext == nil {
601+ b.Fail(xturbo.ErrExtMissing)
602+ return 0
603+ }
604+ major := b.Ext.Major(xturbo.ExtRender)
605+ if major == 0 {
606+ b.Fail(xturbo.ErrExtMissing)
607+ return 0
608+ }
609+ p, seq := b.Request(major, 26, size)
610+ if p == nil {
611+ return 0
612+ }
613+ off := 0
614+ p[off:][0] = byte(op)
615+ off += 1
616+ off += 3
617+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
618+ off += 4
619+ color.Put(p[off:])
620+ off += 8
621+ for i := range rects {
622+ rects[i].Put(p[off:])
623+ off += 8
624+ }
625+ return seq
626+}
627+
165628 func CreateCursor(b *xturbo.Buf, cid xproto.Cursor, source Picture, x uint16, y uint16) xturbo.Seq {
166629 if b.Ext == nil {
167630 b.Fail(xturbo.ErrExtMissing)
@@ -220,6 +683,110 @@ func QueryFilters(b *xturbo.Buf, drawable xproto.Drawable) xturbo.Seq {
220683 return seq
221684 }
222685
686+func SetPictureFilter(b *xturbo.Buf, picture Picture, filter string, values []Fixed) xturbo.Seq {
687+ if uint64(len(filter)) > 65535 {
688+ b.Fail(xturbo.ErrBadLength)
689+ return 0
690+ }
691+ size := 0
692+ size += 4
693+ size += 2
694+ size += 2
695+ size += len(filter) * 1
696+ size = (size + 3) &^ 3
697+ size += len(values) * 4
698+ size = (size + 3) &^ 3
699+ if b.Ext == nil {
700+ b.Fail(xturbo.ErrExtMissing)
701+ return 0
702+ }
703+ major := b.Ext.Major(xturbo.ExtRender)
704+ if major == 0 {
705+ b.Fail(xturbo.ErrExtMissing)
706+ return 0
707+ }
708+ p, seq := b.Request(major, 30, size)
709+ if p == nil {
710+ return 0
711+ }
712+ off := 0
713+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
714+ off += 4
715+ binary.LittleEndian.PutUint16(p[off:], uint16(len(filter)))
716+ off += 2
717+ off += 2
718+ copy(p[off:], filter)
719+ off += len(filter)
720+ off = (off + 3) &^ 3
721+ for i := range values {
722+ binary.LittleEndian.PutUint32(p[off:], uint32(values[i]))
723+ off += 4
724+ }
725+ return seq
726+}
727+
728+func CreateAnimCursor(b *xturbo.Buf, cid xproto.Cursor, cursors []Animcursorelt) xturbo.Seq {
729+ size := 0
730+ size += 4
731+ size += len(cursors) * 8
732+ size = (size + 3) &^ 3
733+ if b.Ext == nil {
734+ b.Fail(xturbo.ErrExtMissing)
735+ return 0
736+ }
737+ major := b.Ext.Major(xturbo.ExtRender)
738+ if major == 0 {
739+ b.Fail(xturbo.ErrExtMissing)
740+ return 0
741+ }
742+ p, seq := b.Request(major, 31, size)
743+ if p == nil {
744+ return 0
745+ }
746+ off := 0
747+ binary.LittleEndian.PutUint32(p[off:], uint32(cid))
748+ off += 4
749+ for i := range cursors {
750+ cursors[i].Put(p[off:])
751+ off += 8
752+ }
753+ return seq
754+}
755+
756+func AddTraps(b *xturbo.Buf, picture Picture, xOff int16, yOff int16, traps []Trap) xturbo.Seq {
757+ size := 0
758+ size += 4
759+ size += 2
760+ size += 2
761+ size += len(traps) * 24
762+ size = (size + 3) &^ 3
763+ if b.Ext == nil {
764+ b.Fail(xturbo.ErrExtMissing)
765+ return 0
766+ }
767+ major := b.Ext.Major(xturbo.ExtRender)
768+ if major == 0 {
769+ b.Fail(xturbo.ErrExtMissing)
770+ return 0
771+ }
772+ p, seq := b.Request(major, 32, size)
773+ if p == nil {
774+ return 0
775+ }
776+ off := 0
777+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
778+ off += 4
779+ binary.LittleEndian.PutUint16(p[off:], uint16(xOff))
780+ off += 2
781+ binary.LittleEndian.PutUint16(p[off:], uint16(yOff))
782+ off += 2
783+ for i := range traps {
784+ traps[i].Put(p[off:])
785+ off += 24
786+ }
787+ return seq
788+}
789+
223790 func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
224791 if b.Ext == nil {
225792 b.Fail(xturbo.ErrExtMissing)
@@ -238,3 +805,159 @@ func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
238805 color.Put(p[4:])
239806 return seq
240807 }
808+
809+func CreateLinearGradient(b *xturbo.Buf, picture Picture, p1 Pointfix, p2 Pointfix, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
810+ if len(stops) != int(numStops) {
811+ b.Fail(xturbo.ErrBadLength)
812+ return 0
813+ }
814+ if len(colors) != int(numStops) {
815+ b.Fail(xturbo.ErrBadLength)
816+ return 0
817+ }
818+ size := 0
819+ size += 4
820+ size += 8
821+ size += 8
822+ size += 4
823+ size += len(stops) * 4
824+ size += len(colors) * 8
825+ size = (size + 3) &^ 3
826+ if b.Ext == nil {
827+ b.Fail(xturbo.ErrExtMissing)
828+ return 0
829+ }
830+ major := b.Ext.Major(xturbo.ExtRender)
831+ if major == 0 {
832+ b.Fail(xturbo.ErrExtMissing)
833+ return 0
834+ }
835+ p, seq := b.Request(major, 34, size)
836+ if p == nil {
837+ return 0
838+ }
839+ off := 0
840+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
841+ off += 4
842+ p1.Put(p[off:])
843+ off += 8
844+ p2.Put(p[off:])
845+ off += 8
846+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
847+ off += 4
848+ for i := range stops {
849+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
850+ off += 4
851+ }
852+ for i := range colors {
853+ colors[i].Put(p[off:])
854+ off += 8
855+ }
856+ return seq
857+}
858+
859+func CreateRadialGradient(b *xturbo.Buf, picture Picture, inner Pointfix, outer Pointfix, innerRadius Fixed, outerRadius Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
860+ if len(stops) != int(numStops) {
861+ b.Fail(xturbo.ErrBadLength)
862+ return 0
863+ }
864+ if len(colors) != int(numStops) {
865+ b.Fail(xturbo.ErrBadLength)
866+ return 0
867+ }
868+ size := 0
869+ size += 4
870+ size += 8
871+ size += 8
872+ size += 4
873+ size += 4
874+ size += 4
875+ size += len(stops) * 4
876+ size += len(colors) * 8
877+ size = (size + 3) &^ 3
878+ if b.Ext == nil {
879+ b.Fail(xturbo.ErrExtMissing)
880+ return 0
881+ }
882+ major := b.Ext.Major(xturbo.ExtRender)
883+ if major == 0 {
884+ b.Fail(xturbo.ErrExtMissing)
885+ return 0
886+ }
887+ p, seq := b.Request(major, 35, size)
888+ if p == nil {
889+ return 0
890+ }
891+ off := 0
892+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
893+ off += 4
894+ inner.Put(p[off:])
895+ off += 8
896+ outer.Put(p[off:])
897+ off += 8
898+ binary.LittleEndian.PutUint32(p[off:], uint32(innerRadius))
899+ off += 4
900+ binary.LittleEndian.PutUint32(p[off:], uint32(outerRadius))
901+ off += 4
902+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
903+ off += 4
904+ for i := range stops {
905+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
906+ off += 4
907+ }
908+ for i := range colors {
909+ colors[i].Put(p[off:])
910+ off += 8
911+ }
912+ return seq
913+}
914+
915+func CreateConicalGradient(b *xturbo.Buf, picture Picture, center Pointfix, angle Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
916+ if len(stops) != int(numStops) {
917+ b.Fail(xturbo.ErrBadLength)
918+ return 0
919+ }
920+ if len(colors) != int(numStops) {
921+ b.Fail(xturbo.ErrBadLength)
922+ return 0
923+ }
924+ size := 0
925+ size += 4
926+ size += 8
927+ size += 4
928+ size += 4
929+ size += len(stops) * 4
930+ size += len(colors) * 8
931+ size = (size + 3) &^ 3
932+ if b.Ext == nil {
933+ b.Fail(xturbo.ErrExtMissing)
934+ return 0
935+ }
936+ major := b.Ext.Major(xturbo.ExtRender)
937+ if major == 0 {
938+ b.Fail(xturbo.ErrExtMissing)
939+ return 0
940+ }
941+ p, seq := b.Request(major, 36, size)
942+ if p == nil {
943+ return 0
944+ }
945+ off := 0
946+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
947+ off += 4
948+ center.Put(p[off:])
949+ off += 8
950+ binary.LittleEndian.PutUint32(p[off:], uint32(angle))
951+ off += 4
952+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
953+ off += 4
954+ for i := range stops {
955+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
956+ off += 4
957+ }
958+ for i := range colors {
959+ colors[i].Put(p[off:])
960+ off += 8
961+ }
962+ return seq
963+}
@@ -59,6 +59,40 @@ func QueryPictIndexValues(b *xturbo.Buf, format Pictformat) xturbo.Seq {
59 return seq59 return seq
60 }60 }
61 61
62+func SetPictureClipRectangles(b *xturbo.Buf, picture Picture, clipXOrigin int16, clipYOrigin int16, rectangles []xproto.Rectangle) xturbo.Seq {
63+ size := 0
64+ size += 4
65+ size += 2
66+ size += 2
67+ size += len(rectangles) * 8
68+ size = (size + 3) &^ 3
69+ if b.Ext == nil {
70+ b.Fail(xturbo.ErrExtMissing)
71+ return 0
72+ }
73+ major := b.Ext.Major(xturbo.ExtRender)
74+ if major == 0 {
75+ b.Fail(xturbo.ErrExtMissing)
76+ return 0
77+ }
78+ p, seq := b.Request(major, 6, size)
79+ if p == nil {
80+ return 0
81+ }
82+ off := 0
83+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
84+ off += 4
85+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
86+ off += 2
87+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
88+ off += 2
89+ for i := range rectangles {
90+ rectangles[i].Put(p[off:])
91+ off += 8
92+ }
93+ return seq
94+}
95+
62 func FreePicture(b *xturbo.Buf, picture Picture) xturbo.Seq {96 func FreePicture(b *xturbo.Buf, picture Picture) xturbo.Seq {
63 if b.Ext == nil {97 if b.Ext == nil {
64 b.Fail(xturbo.ErrExtMissing)98 b.Fail(xturbo.ErrExtMissing)
@@ -106,6 +140,186 @@ func Composite(b *xturbo.Buf, op PictOp, src Picture, mask Picture, dst Picture,
106 return seq140 return seq
107 }141 }
108 142
143+func Trapezoids(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, traps []Trapezoid) xturbo.Seq {
144+ size := 0
145+ size += 1
146+ size += 3
147+ size += 4
148+ size += 4
149+ size += 4
150+ size += 2
151+ size += 2
152+ size += len(traps) * 40
153+ size = (size + 3) &^ 3
154+ if b.Ext == nil {
155+ b.Fail(xturbo.ErrExtMissing)
156+ return 0
157+ }
158+ major := b.Ext.Major(xturbo.ExtRender)
159+ if major == 0 {
160+ b.Fail(xturbo.ErrExtMissing)
161+ return 0
162+ }
163+ p, seq := b.Request(major, 10, size)
164+ if p == nil {
165+ return 0
166+ }
167+ off := 0
168+ p[off:][0] = byte(op)
169+ off += 1
170+ off += 3
171+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
172+ off += 4
173+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
176+ off += 4
177+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
178+ off += 2
179+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
180+ off += 2
181+ for i := range traps {
182+ traps[i].Put(p[off:])
183+ off += 40
184+ }
185+ return seq
186+}
187+
188+func Triangles(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, triangles []Triangle) xturbo.Seq {
189+ size := 0
190+ size += 1
191+ size += 3
192+ size += 4
193+ size += 4
194+ size += 4
195+ size += 2
196+ size += 2
197+ size += len(triangles) * 24
198+ size = (size + 3) &^ 3
199+ if b.Ext == nil {
200+ b.Fail(xturbo.ErrExtMissing)
201+ return 0
202+ }
203+ major := b.Ext.Major(xturbo.ExtRender)
204+ if major == 0 {
205+ b.Fail(xturbo.ErrExtMissing)
206+ return 0
207+ }
208+ p, seq := b.Request(major, 11, size)
209+ if p == nil {
210+ return 0
211+ }
212+ off := 0
213+ p[off:][0] = byte(op)
214+ off += 1
215+ off += 3
216+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
217+ off += 4
218+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
219+ off += 4
220+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
221+ off += 4
222+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
223+ off += 2
224+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
225+ off += 2
226+ for i := range triangles {
227+ triangles[i].Put(p[off:])
228+ off += 24
229+ }
230+ return seq
231+}
232+
233+func TriStrip(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
234+ size := 0
235+ size += 1
236+ size += 3
237+ size += 4
238+ size += 4
239+ size += 4
240+ size += 2
241+ size += 2
242+ size += len(points) * 8
243+ size = (size + 3) &^ 3
244+ if b.Ext == nil {
245+ b.Fail(xturbo.ErrExtMissing)
246+ return 0
247+ }
248+ major := b.Ext.Major(xturbo.ExtRender)
249+ if major == 0 {
250+ b.Fail(xturbo.ErrExtMissing)
251+ return 0
252+ }
253+ p, seq := b.Request(major, 12, size)
254+ if p == nil {
255+ return 0
256+ }
257+ off := 0
258+ p[off:][0] = byte(op)
259+ off += 1
260+ off += 3
261+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
262+ off += 4
263+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
264+ off += 4
265+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
266+ off += 4
267+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
268+ off += 2
269+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
270+ off += 2
271+ for i := range points {
272+ points[i].Put(p[off:])
273+ off += 8
274+ }
275+ return seq
276+}
277+
278+func TriFan(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, srcX int16, srcY int16, points []Pointfix) xturbo.Seq {
279+ size := 0
280+ size += 1
281+ size += 3
282+ size += 4
283+ size += 4
284+ size += 4
285+ size += 2
286+ size += 2
287+ size += len(points) * 8
288+ size = (size + 3) &^ 3
289+ if b.Ext == nil {
290+ b.Fail(xturbo.ErrExtMissing)
291+ return 0
292+ }
293+ major := b.Ext.Major(xturbo.ExtRender)
294+ if major == 0 {
295+ b.Fail(xturbo.ErrExtMissing)
296+ return 0
297+ }
298+ p, seq := b.Request(major, 13, size)
299+ if p == nil {
300+ return 0
301+ }
302+ off := 0
303+ p[off:][0] = byte(op)
304+ off += 1
305+ off += 3
306+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
307+ off += 4
308+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
309+ off += 4
310+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
311+ off += 4
312+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
313+ off += 2
314+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
315+ off += 2
316+ for i := range points {
317+ points[i].Put(p[off:])
318+ off += 8
319+ }
320+ return seq
321+}
322+
109 func CreateGlyphSet(b *xturbo.Buf, gsid Glyphset, format Pictformat) xturbo.Seq {323 func CreateGlyphSet(b *xturbo.Buf, gsid Glyphset, format Pictformat) xturbo.Seq {
110 if b.Ext == nil {324 if b.Ext == nil {
111 b.Fail(xturbo.ErrExtMissing)325 b.Fail(xturbo.ErrExtMissing)
@@ -162,6 +376,255 @@ func FreeGlyphSet(b *xturbo.Buf, glyphset Glyphset) xturbo.Seq {
162 return seq376 return seq
163 }377 }
164 378
379+func AddGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphsLen uint32, glyphids []uint32, glyphs []Glyphinfo, data []byte) xturbo.Seq {
380+ if len(glyphids) != int(glyphsLen) {
381+ b.Fail(xturbo.ErrBadLength)
382+ return 0
383+ }
384+ if len(glyphs) != int(glyphsLen) {
385+ b.Fail(xturbo.ErrBadLength)
386+ return 0
387+ }
388+ size := 0
389+ size += 4
390+ size += 4
391+ size += len(glyphids) * 4
392+ size += len(glyphs) * 12
393+ size += len(data) * 1
394+ size = (size + 3) &^ 3
395+ if b.Ext == nil {
396+ b.Fail(xturbo.ErrExtMissing)
397+ return 0
398+ }
399+ major := b.Ext.Major(xturbo.ExtRender)
400+ if major == 0 {
401+ b.Fail(xturbo.ErrExtMissing)
402+ return 0
403+ }
404+ p, seq := b.Request(major, 20, size)
405+ if p == nil {
406+ return 0
407+ }
408+ off := 0
409+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
410+ off += 4
411+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphsLen))
412+ off += 4
413+ for i := range glyphids {
414+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphids[i]))
415+ off += 4
416+ }
417+ for i := range glyphs {
418+ glyphs[i].Put(p[off:])
419+ off += 12
420+ }
421+ copy(p[off:], data)
422+ off += len(data)
423+ return seq
424+}
425+
426+func FreeGlyphs(b *xturbo.Buf, glyphset Glyphset, glyphs []Glyph) xturbo.Seq {
427+ size := 0
428+ size += 4
429+ size += len(glyphs) * 4
430+ size = (size + 3) &^ 3
431+ if b.Ext == nil {
432+ b.Fail(xturbo.ErrExtMissing)
433+ return 0
434+ }
435+ major := b.Ext.Major(xturbo.ExtRender)
436+ if major == 0 {
437+ b.Fail(xturbo.ErrExtMissing)
438+ return 0
439+ }
440+ p, seq := b.Request(major, 22, size)
441+ if p == nil {
442+ return 0
443+ }
444+ off := 0
445+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
446+ off += 4
447+ for i := range glyphs {
448+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphs[i]))
449+ off += 4
450+ }
451+ return seq
452+}
453+
454+func CompositeGlyphs8(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
455+ size := 0
456+ size += 1
457+ size += 3
458+ size += 4
459+ size += 4
460+ size += 4
461+ size += 4
462+ size += 2
463+ size += 2
464+ size += len(glyphcmds) * 1
465+ size = (size + 3) &^ 3
466+ if b.Ext == nil {
467+ b.Fail(xturbo.ErrExtMissing)
468+ return 0
469+ }
470+ major := b.Ext.Major(xturbo.ExtRender)
471+ if major == 0 {
472+ b.Fail(xturbo.ErrExtMissing)
473+ return 0
474+ }
475+ p, seq := b.Request(major, 23, size)
476+ if p == nil {
477+ return 0
478+ }
479+ off := 0
480+ p[off:][0] = byte(op)
481+ off += 1
482+ off += 3
483+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
484+ off += 4
485+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
486+ off += 4
487+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
488+ off += 4
489+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
490+ off += 4
491+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
492+ off += 2
493+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
494+ off += 2
495+ copy(p[off:], glyphcmds)
496+ off += len(glyphcmds)
497+ return seq
498+}
499+
500+func CompositeGlyphs16(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
501+ size := 0
502+ size += 1
503+ size += 3
504+ size += 4
505+ size += 4
506+ size += 4
507+ size += 4
508+ size += 2
509+ size += 2
510+ size += len(glyphcmds) * 1
511+ size = (size + 3) &^ 3
512+ if b.Ext == nil {
513+ b.Fail(xturbo.ErrExtMissing)
514+ return 0
515+ }
516+ major := b.Ext.Major(xturbo.ExtRender)
517+ if major == 0 {
518+ b.Fail(xturbo.ErrExtMissing)
519+ return 0
520+ }
521+ p, seq := b.Request(major, 24, size)
522+ if p == nil {
523+ return 0
524+ }
525+ off := 0
526+ p[off:][0] = byte(op)
527+ off += 1
528+ off += 3
529+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
530+ off += 4
531+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
532+ off += 4
533+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
534+ off += 4
535+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
536+ off += 4
537+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
538+ off += 2
539+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
540+ off += 2
541+ copy(p[off:], glyphcmds)
542+ off += len(glyphcmds)
543+ return seq
544+}
545+
546+func CompositeGlyphs32(b *xturbo.Buf, op PictOp, src Picture, dst Picture, maskFormat Pictformat, glyphset Glyphset, srcX int16, srcY int16, glyphcmds []byte) xturbo.Seq {
547+ size := 0
548+ size += 1
549+ size += 3
550+ size += 4
551+ size += 4
552+ size += 4
553+ size += 4
554+ size += 2
555+ size += 2
556+ size += len(glyphcmds) * 1
557+ size = (size + 3) &^ 3
558+ if b.Ext == nil {
559+ b.Fail(xturbo.ErrExtMissing)
560+ return 0
561+ }
562+ major := b.Ext.Major(xturbo.ExtRender)
563+ if major == 0 {
564+ b.Fail(xturbo.ErrExtMissing)
565+ return 0
566+ }
567+ p, seq := b.Request(major, 25, size)
568+ if p == nil {
569+ return 0
570+ }
571+ off := 0
572+ p[off:][0] = byte(op)
573+ off += 1
574+ off += 3
575+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
576+ off += 4
577+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
578+ off += 4
579+ binary.LittleEndian.PutUint32(p[off:], uint32(maskFormat))
580+ off += 4
581+ binary.LittleEndian.PutUint32(p[off:], uint32(glyphset))
582+ off += 4
583+ binary.LittleEndian.PutUint16(p[off:], uint16(srcX))
584+ off += 2
585+ binary.LittleEndian.PutUint16(p[off:], uint16(srcY))
586+ off += 2
587+ copy(p[off:], glyphcmds)
588+ off += len(glyphcmds)
589+ return seq
590+}
591+
592+func FillRectangles(b *xturbo.Buf, op PictOp, dst Picture, color Color, rects []xproto.Rectangle) xturbo.Seq {
593+ size := 0
594+ size += 1
595+ size += 3
596+ size += 4
597+ size += 8
598+ size += len(rects) * 8
599+ size = (size + 3) &^ 3
600+ if b.Ext == nil {
601+ b.Fail(xturbo.ErrExtMissing)
602+ return 0
603+ }
604+ major := b.Ext.Major(xturbo.ExtRender)
605+ if major == 0 {
606+ b.Fail(xturbo.ErrExtMissing)
607+ return 0
608+ }
609+ p, seq := b.Request(major, 26, size)
610+ if p == nil {
611+ return 0
612+ }
613+ off := 0
614+ p[off:][0] = byte(op)
615+ off += 1
616+ off += 3
617+ binary.LittleEndian.PutUint32(p[off:], uint32(dst))
618+ off += 4
619+ color.Put(p[off:])
620+ off += 8
621+ for i := range rects {
622+ rects[i].Put(p[off:])
623+ off += 8
624+ }
625+ return seq
626+}
627+
165 func CreateCursor(b *xturbo.Buf, cid xproto.Cursor, source Picture, x uint16, y uint16) xturbo.Seq {628 func CreateCursor(b *xturbo.Buf, cid xproto.Cursor, source Picture, x uint16, y uint16) xturbo.Seq {
166 if b.Ext == nil {629 if b.Ext == nil {
167 b.Fail(xturbo.ErrExtMissing)630 b.Fail(xturbo.ErrExtMissing)
@@ -220,6 +683,110 @@ func QueryFilters(b *xturbo.Buf, drawable xproto.Drawable) xturbo.Seq {
220 return seq683 return seq
221 }684 }
222 685
686+func SetPictureFilter(b *xturbo.Buf, picture Picture, filter string, values []Fixed) xturbo.Seq {
687+ if uint64(len(filter)) > 65535 {
688+ b.Fail(xturbo.ErrBadLength)
689+ return 0
690+ }
691+ size := 0
692+ size += 4
693+ size += 2
694+ size += 2
695+ size += len(filter) * 1
696+ size = (size + 3) &^ 3
697+ size += len(values) * 4
698+ size = (size + 3) &^ 3
699+ if b.Ext == nil {
700+ b.Fail(xturbo.ErrExtMissing)
701+ return 0
702+ }
703+ major := b.Ext.Major(xturbo.ExtRender)
704+ if major == 0 {
705+ b.Fail(xturbo.ErrExtMissing)
706+ return 0
707+ }
708+ p, seq := b.Request(major, 30, size)
709+ if p == nil {
710+ return 0
711+ }
712+ off := 0
713+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
714+ off += 4
715+ binary.LittleEndian.PutUint16(p[off:], uint16(len(filter)))
716+ off += 2
717+ off += 2
718+ copy(p[off:], filter)
719+ off += len(filter)
720+ off = (off + 3) &^ 3
721+ for i := range values {
722+ binary.LittleEndian.PutUint32(p[off:], uint32(values[i]))
723+ off += 4
724+ }
725+ return seq
726+}
727+
728+func CreateAnimCursor(b *xturbo.Buf, cid xproto.Cursor, cursors []Animcursorelt) xturbo.Seq {
729+ size := 0
730+ size += 4
731+ size += len(cursors) * 8
732+ size = (size + 3) &^ 3
733+ if b.Ext == nil {
734+ b.Fail(xturbo.ErrExtMissing)
735+ return 0
736+ }
737+ major := b.Ext.Major(xturbo.ExtRender)
738+ if major == 0 {
739+ b.Fail(xturbo.ErrExtMissing)
740+ return 0
741+ }
742+ p, seq := b.Request(major, 31, size)
743+ if p == nil {
744+ return 0
745+ }
746+ off := 0
747+ binary.LittleEndian.PutUint32(p[off:], uint32(cid))
748+ off += 4
749+ for i := range cursors {
750+ cursors[i].Put(p[off:])
751+ off += 8
752+ }
753+ return seq
754+}
755+
756+func AddTraps(b *xturbo.Buf, picture Picture, xOff int16, yOff int16, traps []Trap) xturbo.Seq {
757+ size := 0
758+ size += 4
759+ size += 2
760+ size += 2
761+ size += len(traps) * 24
762+ size = (size + 3) &^ 3
763+ if b.Ext == nil {
764+ b.Fail(xturbo.ErrExtMissing)
765+ return 0
766+ }
767+ major := b.Ext.Major(xturbo.ExtRender)
768+ if major == 0 {
769+ b.Fail(xturbo.ErrExtMissing)
770+ return 0
771+ }
772+ p, seq := b.Request(major, 32, size)
773+ if p == nil {
774+ return 0
775+ }
776+ off := 0
777+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
778+ off += 4
779+ binary.LittleEndian.PutUint16(p[off:], uint16(xOff))
780+ off += 2
781+ binary.LittleEndian.PutUint16(p[off:], uint16(yOff))
782+ off += 2
783+ for i := range traps {
784+ traps[i].Put(p[off:])
785+ off += 24
786+ }
787+ return seq
788+}
789+
223 func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {790 func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
224 if b.Ext == nil {791 if b.Ext == nil {
225 b.Fail(xturbo.ErrExtMissing)792 b.Fail(xturbo.ErrExtMissing)
@@ -238,3 +805,159 @@ func CreateSolidFill(b *xturbo.Buf, picture Picture, color Color) xturbo.Seq {
238 color.Put(p[4:])805 color.Put(p[4:])
239 return seq806 return seq
240 }807 }
808+
809+func CreateLinearGradient(b *xturbo.Buf, picture Picture, p1 Pointfix, p2 Pointfix, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
810+ if len(stops) != int(numStops) {
811+ b.Fail(xturbo.ErrBadLength)
812+ return 0
813+ }
814+ if len(colors) != int(numStops) {
815+ b.Fail(xturbo.ErrBadLength)
816+ return 0
817+ }
818+ size := 0
819+ size += 4
820+ size += 8
821+ size += 8
822+ size += 4
823+ size += len(stops) * 4
824+ size += len(colors) * 8
825+ size = (size + 3) &^ 3
826+ if b.Ext == nil {
827+ b.Fail(xturbo.ErrExtMissing)
828+ return 0
829+ }
830+ major := b.Ext.Major(xturbo.ExtRender)
831+ if major == 0 {
832+ b.Fail(xturbo.ErrExtMissing)
833+ return 0
834+ }
835+ p, seq := b.Request(major, 34, size)
836+ if p == nil {
837+ return 0
838+ }
839+ off := 0
840+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
841+ off += 4
842+ p1.Put(p[off:])
843+ off += 8
844+ p2.Put(p[off:])
845+ off += 8
846+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
847+ off += 4
848+ for i := range stops {
849+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
850+ off += 4
851+ }
852+ for i := range colors {
853+ colors[i].Put(p[off:])
854+ off += 8
855+ }
856+ return seq
857+}
858+
859+func CreateRadialGradient(b *xturbo.Buf, picture Picture, inner Pointfix, outer Pointfix, innerRadius Fixed, outerRadius Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
860+ if len(stops) != int(numStops) {
861+ b.Fail(xturbo.ErrBadLength)
862+ return 0
863+ }
864+ if len(colors) != int(numStops) {
865+ b.Fail(xturbo.ErrBadLength)
866+ return 0
867+ }
868+ size := 0
869+ size += 4
870+ size += 8
871+ size += 8
872+ size += 4
873+ size += 4
874+ size += 4
875+ size += len(stops) * 4
876+ size += len(colors) * 8
877+ size = (size + 3) &^ 3
878+ if b.Ext == nil {
879+ b.Fail(xturbo.ErrExtMissing)
880+ return 0
881+ }
882+ major := b.Ext.Major(xturbo.ExtRender)
883+ if major == 0 {
884+ b.Fail(xturbo.ErrExtMissing)
885+ return 0
886+ }
887+ p, seq := b.Request(major, 35, size)
888+ if p == nil {
889+ return 0
890+ }
891+ off := 0
892+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
893+ off += 4
894+ inner.Put(p[off:])
895+ off += 8
896+ outer.Put(p[off:])
897+ off += 8
898+ binary.LittleEndian.PutUint32(p[off:], uint32(innerRadius))
899+ off += 4
900+ binary.LittleEndian.PutUint32(p[off:], uint32(outerRadius))
901+ off += 4
902+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
903+ off += 4
904+ for i := range stops {
905+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
906+ off += 4
907+ }
908+ for i := range colors {
909+ colors[i].Put(p[off:])
910+ off += 8
911+ }
912+ return seq
913+}
914+
915+func CreateConicalGradient(b *xturbo.Buf, picture Picture, center Pointfix, angle Fixed, numStops uint32, stops []Fixed, colors []Color) xturbo.Seq {
916+ if len(stops) != int(numStops) {
917+ b.Fail(xturbo.ErrBadLength)
918+ return 0
919+ }
920+ if len(colors) != int(numStops) {
921+ b.Fail(xturbo.ErrBadLength)
922+ return 0
923+ }
924+ size := 0
925+ size += 4
926+ size += 8
927+ size += 4
928+ size += 4
929+ size += len(stops) * 4
930+ size += len(colors) * 8
931+ size = (size + 3) &^ 3
932+ if b.Ext == nil {
933+ b.Fail(xturbo.ErrExtMissing)
934+ return 0
935+ }
936+ major := b.Ext.Major(xturbo.ExtRender)
937+ if major == 0 {
938+ b.Fail(xturbo.ErrExtMissing)
939+ return 0
940+ }
941+ p, seq := b.Request(major, 36, size)
942+ if p == nil {
943+ return 0
944+ }
945+ off := 0
946+ binary.LittleEndian.PutUint32(p[off:], uint32(picture))
947+ off += 4
948+ center.Put(p[off:])
949+ off += 8
950+ binary.LittleEndian.PutUint32(p[off:], uint32(angle))
951+ off += 4
952+ binary.LittleEndian.PutUint32(p[off:], uint32(numStops))
953+ off += 4
954+ for i := range stops {
955+ binary.LittleEndian.PutUint32(p[off:], uint32(stops[i]))
956+ off += 4
957+ }
958+ for i := range colors {
959+ colors[i].Put(p[off:])
960+ off += 8
961+ }
962+ return seq
963+}
M res/requests_generated.go +67 -0
@@ -75,3 +75,70 @@ func QueryClientPixmapBytes(b *xturbo.Buf, xid uint32) xturbo.Seq {
7575 binary.LittleEndian.PutUint32(p[0:], uint32(xid))
7676 return seq
7777 }
78+
79+func QueryClientIds(b *xturbo.Buf, specs []ClientIdSpec) xturbo.Seq {
80+ if uint64(len(specs)) > 4294967295 {
81+ b.Fail(xturbo.ErrBadLength)
82+ return 0
83+ }
84+ size := 0
85+ size += 4
86+ size += len(specs) * 8
87+ size = (size + 3) &^ 3
88+ if b.Ext == nil {
89+ b.Fail(xturbo.ErrExtMissing)
90+ return 0
91+ }
92+ major := b.Ext.Major(xturbo.ExtRes)
93+ if major == 0 {
94+ b.Fail(xturbo.ErrExtMissing)
95+ return 0
96+ }
97+ p, seq := b.Request(major, 4, size)
98+ if p == nil {
99+ return 0
100+ }
101+ off := 0
102+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
103+ off += 4
104+ for i := range specs {
105+ specs[i].Put(p[off:])
106+ off += 8
107+ }
108+ return seq
109+}
110+
111+func QueryResourceBytes(b *xturbo.Buf, client uint32, specs []ResourceIdSpec) xturbo.Seq {
112+ if uint64(len(specs)) > 4294967295 {
113+ b.Fail(xturbo.ErrBadLength)
114+ return 0
115+ }
116+ size := 0
117+ size += 4
118+ size += 4
119+ size += len(specs) * 8
120+ size = (size + 3) &^ 3
121+ if b.Ext == nil {
122+ b.Fail(xturbo.ErrExtMissing)
123+ return 0
124+ }
125+ major := b.Ext.Major(xturbo.ExtRes)
126+ if major == 0 {
127+ b.Fail(xturbo.ErrExtMissing)
128+ return 0
129+ }
130+ p, seq := b.Request(major, 5, size)
131+ if p == nil {
132+ return 0
133+ }
134+ off := 0
135+ binary.LittleEndian.PutUint32(p[off:], uint32(client))
136+ off += 4
137+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
138+ off += 4
139+ for i := range specs {
140+ specs[i].Put(p[off:])
141+ off += 8
142+ }
143+ return seq
144+}
@@ -75,3 +75,70 @@ func QueryClientPixmapBytes(b *xturbo.Buf, xid uint32) xturbo.Seq {
75 binary.LittleEndian.PutUint32(p[0:], uint32(xid))75 binary.LittleEndian.PutUint32(p[0:], uint32(xid))
76 return seq76 return seq
77 }77 }
78+
79+func QueryClientIds(b *xturbo.Buf, specs []ClientIdSpec) xturbo.Seq {
80+ if uint64(len(specs)) > 4294967295 {
81+ b.Fail(xturbo.ErrBadLength)
82+ return 0
83+ }
84+ size := 0
85+ size += 4
86+ size += len(specs) * 8
87+ size = (size + 3) &^ 3
88+ if b.Ext == nil {
89+ b.Fail(xturbo.ErrExtMissing)
90+ return 0
91+ }
92+ major := b.Ext.Major(xturbo.ExtRes)
93+ if major == 0 {
94+ b.Fail(xturbo.ErrExtMissing)
95+ return 0
96+ }
97+ p, seq := b.Request(major, 4, size)
98+ if p == nil {
99+ return 0
100+ }
101+ off := 0
102+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
103+ off += 4
104+ for i := range specs {
105+ specs[i].Put(p[off:])
106+ off += 8
107+ }
108+ return seq
109+}
110+
111+func QueryResourceBytes(b *xturbo.Buf, client uint32, specs []ResourceIdSpec) xturbo.Seq {
112+ if uint64(len(specs)) > 4294967295 {
113+ b.Fail(xturbo.ErrBadLength)
114+ return 0
115+ }
116+ size := 0
117+ size += 4
118+ size += 4
119+ size += len(specs) * 8
120+ size = (size + 3) &^ 3
121+ if b.Ext == nil {
122+ b.Fail(xturbo.ErrExtMissing)
123+ return 0
124+ }
125+ major := b.Ext.Major(xturbo.ExtRes)
126+ if major == 0 {
127+ b.Fail(xturbo.ErrExtMissing)
128+ return 0
129+ }
130+ p, seq := b.Request(major, 5, size)
131+ if p == nil {
132+ return 0
133+ }
134+ off := 0
135+ binary.LittleEndian.PutUint32(p[off:], uint32(client))
136+ off += 4
137+ binary.LittleEndian.PutUint32(p[off:], uint32(len(specs)))
138+ off += 4
139+ for i := range specs {
140+ specs[i].Put(p[off:])
141+ off += 8
142+ }
143+ return seq
144+}
M shape/requests_generated.go +45 -0
@@ -22,6 +22,51 @@ func QueryVersion(b *xturbo.Buf) xturbo.Seq {
2222 return seq
2323 }
2424
25+func Rectangles(b *xturbo.Buf, operation So, destinationKind Sk, ordering xproto.ClipOrdering, destinationWindow xproto.Window, xOffset int16, yOffset int16, rectangles []xproto.Rectangle) xturbo.Seq {
26+ size := 0
27+ size += 1
28+ size += 1
29+ size += 1
30+ size += 1
31+ size += 4
32+ size += 2
33+ size += 2
34+ size += len(rectangles) * 8
35+ size = (size + 3) &^ 3
36+ if b.Ext == nil {
37+ b.Fail(xturbo.ErrExtMissing)
38+ return 0
39+ }
40+ major := b.Ext.Major(xturbo.ExtShape)
41+ if major == 0 {
42+ b.Fail(xturbo.ErrExtMissing)
43+ return 0
44+ }
45+ p, seq := b.Request(major, 1, size)
46+ if p == nil {
47+ return 0
48+ }
49+ off := 0
50+ p[off:][0] = byte(operation)
51+ off += 1
52+ p[off:][0] = byte(destinationKind)
53+ off += 1
54+ p[off:][0] = byte(ordering)
55+ off += 1
56+ off += 1
57+ binary.LittleEndian.PutUint32(p[off:], uint32(destinationWindow))
58+ off += 4
59+ binary.LittleEndian.PutUint16(p[off:], uint16(xOffset))
60+ off += 2
61+ binary.LittleEndian.PutUint16(p[off:], uint16(yOffset))
62+ off += 2
63+ for i := range rectangles {
64+ rectangles[i].Put(p[off:])
65+ off += 8
66+ }
67+ return seq
68+}
69+
2570 func Mask(b *xturbo.Buf, operation So, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceBitmap xproto.Pixmap) xturbo.Seq {
2671 if b.Ext == nil {
2772 b.Fail(xturbo.ErrExtMissing)
@@ -22,6 +22,51 @@ func QueryVersion(b *xturbo.Buf) xturbo.Seq {
22 return seq22 return seq
23 }23 }
24 24
25+func Rectangles(b *xturbo.Buf, operation So, destinationKind Sk, ordering xproto.ClipOrdering, destinationWindow xproto.Window, xOffset int16, yOffset int16, rectangles []xproto.Rectangle) xturbo.Seq {
26+ size := 0
27+ size += 1
28+ size += 1
29+ size += 1
30+ size += 1
31+ size += 4
32+ size += 2
33+ size += 2
34+ size += len(rectangles) * 8
35+ size = (size + 3) &^ 3
36+ if b.Ext == nil {
37+ b.Fail(xturbo.ErrExtMissing)
38+ return 0
39+ }
40+ major := b.Ext.Major(xturbo.ExtShape)
41+ if major == 0 {
42+ b.Fail(xturbo.ErrExtMissing)
43+ return 0
44+ }
45+ p, seq := b.Request(major, 1, size)
46+ if p == nil {
47+ return 0
48+ }
49+ off := 0
50+ p[off:][0] = byte(operation)
51+ off += 1
52+ p[off:][0] = byte(destinationKind)
53+ off += 1
54+ p[off:][0] = byte(ordering)
55+ off += 1
56+ off += 1
57+ binary.LittleEndian.PutUint32(p[off:], uint32(destinationWindow))
58+ off += 4
59+ binary.LittleEndian.PutUint16(p[off:], uint16(xOffset))
60+ off += 2
61+ binary.LittleEndian.PutUint16(p[off:], uint16(yOffset))
62+ off += 2
63+ for i := range rectangles {
64+ rectangles[i].Put(p[off:])
65+ off += 8
66+ }
67+ return seq
68+}
69+
25 func Mask(b *xturbo.Buf, operation So, destinationKind Sk, destinationWindow xproto.Window, xOffset int16, yOffset int16, sourceBitmap xproto.Pixmap) xturbo.Seq {70 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 {71 if b.Ext == nil {
27 b.Fail(xturbo.ErrExtMissing)72 b.Fail(xturbo.ErrExtMissing)
A testdata/golden/res/QueryClientIds.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+94040400010000000000000001000000
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+94040400010000000000000001000000
A testdata/golden/xproto/ChangeProperty.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+120007009f030000e70000001f000000080000000300000061626300
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+120007009f030000e70000001f000000080000000300000061626300
A testdata/golden/xproto/InternAtom.req.hex +3 -0
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+100004000700000058545552424f5f00
@@ -0,0 +1,3 @@
1+# source: Xvfb via raw socketpair tee; independent reference encoder; server accepted
2+# xtrace fallback: local xtrace is glibc's execution tracer, not X11 xtrace
3+100004000700000058545552424f5f00
M xfixes/requests_generated.go +181 -0
@@ -103,6 +103,34 @@ func GetCursorImage(b *xturbo.Buf) xturbo.Seq {
103103 return seq
104104 }
105105
106+func CreateRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
107+ size := 0
108+ size += 4
109+ size += len(rectangles) * 8
110+ size = (size + 3) &^ 3
111+ if b.Ext == nil {
112+ b.Fail(xturbo.ErrExtMissing)
113+ return 0
114+ }
115+ major := b.Ext.Major(xturbo.ExtXFixes)
116+ if major == 0 {
117+ b.Fail(xturbo.ErrExtMissing)
118+ return 0
119+ }
120+ p, seq := b.Request(major, 5, size)
121+ if p == nil {
122+ return 0
123+ }
124+ off := 0
125+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
126+ off += 4
127+ for i := range rectangles {
128+ rectangles[i].Put(p[off:])
129+ off += 8
130+ }
131+ return seq
132+}
133+
106134 func CreateRegionFromBitmap(b *xturbo.Buf, region Region, bitmap xproto.Pixmap) xturbo.Seq {
107135 if b.Ext == nil {
108136 b.Fail(xturbo.ErrExtMissing)
@@ -198,6 +226,34 @@ func DestroyRegion(b *xturbo.Buf, region Region) xturbo.Seq {
198226 return seq
199227 }
200228
229+func SetRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
230+ size := 0
231+ size += 4
232+ size += len(rectangles) * 8
233+ size = (size + 3) &^ 3
234+ if b.Ext == nil {
235+ b.Fail(xturbo.ErrExtMissing)
236+ return 0
237+ }
238+ major := b.Ext.Major(xturbo.ExtXFixes)
239+ if major == 0 {
240+ b.Fail(xturbo.ErrExtMissing)
241+ return 0
242+ }
243+ p, seq := b.Request(major, 11, size)
244+ if p == nil {
245+ return 0
246+ }
247+ off := 0
248+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
249+ off += 4
250+ for i := range rectangles {
251+ rectangles[i].Put(p[off:])
252+ off += 8
253+ }
254+ return seq
255+}
256+
201257 func CopyRegion(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
202258 if b.Ext == nil {
203259 b.Fail(xturbo.ErrExtMissing)
@@ -418,6 +474,41 @@ func SetPictureClipRegion(b *xturbo.Buf, picture render.Picture, region Region,
418474 return seq
419475 }
420476
477+func SetCursorName(b *xturbo.Buf, cursor xproto.Cursor, name string) xturbo.Seq {
478+ if uint64(len(name)) > 65535 {
479+ b.Fail(xturbo.ErrBadLength)
480+ return 0
481+ }
482+ size := 0
483+ size += 4
484+ size += 2
485+ size += 2
486+ size += len(name) * 1
487+ size = (size + 3) &^ 3
488+ if b.Ext == nil {
489+ b.Fail(xturbo.ErrExtMissing)
490+ return 0
491+ }
492+ major := b.Ext.Major(xturbo.ExtXFixes)
493+ if major == 0 {
494+ b.Fail(xturbo.ErrExtMissing)
495+ return 0
496+ }
497+ p, seq := b.Request(major, 23, size)
498+ if p == nil {
499+ return 0
500+ }
501+ off := 0
502+ binary.LittleEndian.PutUint32(p[off:], uint32(cursor))
503+ off += 4
504+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
505+ off += 2
506+ off += 2
507+ copy(p[off:], name)
508+ off += len(name)
509+ return seq
510+}
511+
421512 func GetCursorName(b *xturbo.Buf, cursor xproto.Cursor) xturbo.Seq {
422513 if b.Ext == nil {
423514 b.Fail(xturbo.ErrExtMissing)
@@ -472,6 +563,41 @@ func ChangeCursor(b *xturbo.Buf, source xproto.Cursor, destination xproto.Cursor
472563 return seq
473564 }
474565
566+func ChangeCursorByName(b *xturbo.Buf, src xproto.Cursor, name string) xturbo.Seq {
567+ if uint64(len(name)) > 65535 {
568+ b.Fail(xturbo.ErrBadLength)
569+ return 0
570+ }
571+ size := 0
572+ size += 4
573+ size += 2
574+ size += 2
575+ size += len(name) * 1
576+ size = (size + 3) &^ 3
577+ if b.Ext == nil {
578+ b.Fail(xturbo.ErrExtMissing)
579+ return 0
580+ }
581+ major := b.Ext.Major(xturbo.ExtXFixes)
582+ if major == 0 {
583+ b.Fail(xturbo.ErrExtMissing)
584+ return 0
585+ }
586+ p, seq := b.Request(major, 27, size)
587+ if p == nil {
588+ return 0
589+ }
590+ off := 0
591+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
592+ off += 4
593+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
594+ off += 2
595+ off += 2
596+ copy(p[off:], name)
597+ off += len(name)
598+ return seq
599+}
600+
475601 func ExpandRegion(b *xturbo.Buf, source Region, destination Region, left uint16, right uint16, top uint16, bottom uint16) xturbo.Seq {
476602 if b.Ext == nil {
477603 b.Fail(xturbo.ErrExtMissing)
@@ -531,6 +657,61 @@ func ShowCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
531657 return seq
532658 }
533659
660+func CreatePointerBarrier(b *xturbo.Buf, barrier Barrier, window xproto.Window, x1 uint16, y1 uint16, x2 uint16, y2 uint16, directions BarrierDirections, devices []uint16) xturbo.Seq {
661+ if uint64(len(devices)) > 65535 {
662+ b.Fail(xturbo.ErrBadLength)
663+ return 0
664+ }
665+ size := 0
666+ size += 4
667+ size += 4
668+ size += 2
669+ size += 2
670+ size += 2
671+ size += 2
672+ size += 4
673+ size += 2
674+ size += 2
675+ size += len(devices) * 2
676+ size = (size + 3) &^ 3
677+ if b.Ext == nil {
678+ b.Fail(xturbo.ErrExtMissing)
679+ return 0
680+ }
681+ major := b.Ext.Major(xturbo.ExtXFixes)
682+ if major == 0 {
683+ b.Fail(xturbo.ErrExtMissing)
684+ return 0
685+ }
686+ p, seq := b.Request(major, 31, size)
687+ if p == nil {
688+ return 0
689+ }
690+ off := 0
691+ binary.LittleEndian.PutUint32(p[off:], uint32(barrier))
692+ off += 4
693+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
694+ off += 4
695+ binary.LittleEndian.PutUint16(p[off:], uint16(x1))
696+ off += 2
697+ binary.LittleEndian.PutUint16(p[off:], uint16(y1))
698+ off += 2
699+ binary.LittleEndian.PutUint16(p[off:], uint16(x2))
700+ off += 2
701+ binary.LittleEndian.PutUint16(p[off:], uint16(y2))
702+ off += 2
703+ binary.LittleEndian.PutUint32(p[off:], uint32(directions))
704+ off += 4
705+ off += 2
706+ binary.LittleEndian.PutUint16(p[off:], uint16(len(devices)))
707+ off += 2
708+ for i := range devices {
709+ binary.LittleEndian.PutUint16(p[off:], uint16(devices[i]))
710+ off += 2
711+ }
712+ return seq
713+}
714+
534715 func DeletePointerBarrier(b *xturbo.Buf, barrier Barrier) xturbo.Seq {
535716 if b.Ext == nil {
536717 b.Fail(xturbo.ErrExtMissing)
@@ -103,6 +103,34 @@ func GetCursorImage(b *xturbo.Buf) xturbo.Seq {
103 return seq103 return seq
104 }104 }
105 105
106+func CreateRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
107+ size := 0
108+ size += 4
109+ size += len(rectangles) * 8
110+ size = (size + 3) &^ 3
111+ if b.Ext == nil {
112+ b.Fail(xturbo.ErrExtMissing)
113+ return 0
114+ }
115+ major := b.Ext.Major(xturbo.ExtXFixes)
116+ if major == 0 {
117+ b.Fail(xturbo.ErrExtMissing)
118+ return 0
119+ }
120+ p, seq := b.Request(major, 5, size)
121+ if p == nil {
122+ return 0
123+ }
124+ off := 0
125+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
126+ off += 4
127+ for i := range rectangles {
128+ rectangles[i].Put(p[off:])
129+ off += 8
130+ }
131+ return seq
132+}
133+
106 func CreateRegionFromBitmap(b *xturbo.Buf, region Region, bitmap xproto.Pixmap) xturbo.Seq {134 func CreateRegionFromBitmap(b *xturbo.Buf, region Region, bitmap xproto.Pixmap) xturbo.Seq {
107 if b.Ext == nil {135 if b.Ext == nil {
108 b.Fail(xturbo.ErrExtMissing)136 b.Fail(xturbo.ErrExtMissing)
@@ -198,6 +226,34 @@ func DestroyRegion(b *xturbo.Buf, region Region) xturbo.Seq {
198 return seq226 return seq
199 }227 }
200 228
229+func SetRegion(b *xturbo.Buf, region Region, rectangles []xproto.Rectangle) xturbo.Seq {
230+ size := 0
231+ size += 4
232+ size += len(rectangles) * 8
233+ size = (size + 3) &^ 3
234+ if b.Ext == nil {
235+ b.Fail(xturbo.ErrExtMissing)
236+ return 0
237+ }
238+ major := b.Ext.Major(xturbo.ExtXFixes)
239+ if major == 0 {
240+ b.Fail(xturbo.ErrExtMissing)
241+ return 0
242+ }
243+ p, seq := b.Request(major, 11, size)
244+ if p == nil {
245+ return 0
246+ }
247+ off := 0
248+ binary.LittleEndian.PutUint32(p[off:], uint32(region))
249+ off += 4
250+ for i := range rectangles {
251+ rectangles[i].Put(p[off:])
252+ off += 8
253+ }
254+ return seq
255+}
256+
201 func CopyRegion(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {257 func CopyRegion(b *xturbo.Buf, source Region, destination Region) xturbo.Seq {
202 if b.Ext == nil {258 if b.Ext == nil {
203 b.Fail(xturbo.ErrExtMissing)259 b.Fail(xturbo.ErrExtMissing)
@@ -418,6 +474,41 @@ func SetPictureClipRegion(b *xturbo.Buf, picture render.Picture, region Region,
418 return seq474 return seq
419 }475 }
420 476
477+func SetCursorName(b *xturbo.Buf, cursor xproto.Cursor, name string) xturbo.Seq {
478+ if uint64(len(name)) > 65535 {
479+ b.Fail(xturbo.ErrBadLength)
480+ return 0
481+ }
482+ size := 0
483+ size += 4
484+ size += 2
485+ size += 2
486+ size += len(name) * 1
487+ size = (size + 3) &^ 3
488+ if b.Ext == nil {
489+ b.Fail(xturbo.ErrExtMissing)
490+ return 0
491+ }
492+ major := b.Ext.Major(xturbo.ExtXFixes)
493+ if major == 0 {
494+ b.Fail(xturbo.ErrExtMissing)
495+ return 0
496+ }
497+ p, seq := b.Request(major, 23, size)
498+ if p == nil {
499+ return 0
500+ }
501+ off := 0
502+ binary.LittleEndian.PutUint32(p[off:], uint32(cursor))
503+ off += 4
504+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
505+ off += 2
506+ off += 2
507+ copy(p[off:], name)
508+ off += len(name)
509+ return seq
510+}
511+
421 func GetCursorName(b *xturbo.Buf, cursor xproto.Cursor) xturbo.Seq {512 func GetCursorName(b *xturbo.Buf, cursor xproto.Cursor) xturbo.Seq {
422 if b.Ext == nil {513 if b.Ext == nil {
423 b.Fail(xturbo.ErrExtMissing)514 b.Fail(xturbo.ErrExtMissing)
@@ -472,6 +563,41 @@ func ChangeCursor(b *xturbo.Buf, source xproto.Cursor, destination xproto.Cursor
472 return seq563 return seq
473 }564 }
474 565
566+func ChangeCursorByName(b *xturbo.Buf, src xproto.Cursor, name string) xturbo.Seq {
567+ if uint64(len(name)) > 65535 {
568+ b.Fail(xturbo.ErrBadLength)
569+ return 0
570+ }
571+ size := 0
572+ size += 4
573+ size += 2
574+ size += 2
575+ size += len(name) * 1
576+ size = (size + 3) &^ 3
577+ if b.Ext == nil {
578+ b.Fail(xturbo.ErrExtMissing)
579+ return 0
580+ }
581+ major := b.Ext.Major(xturbo.ExtXFixes)
582+ if major == 0 {
583+ b.Fail(xturbo.ErrExtMissing)
584+ return 0
585+ }
586+ p, seq := b.Request(major, 27, size)
587+ if p == nil {
588+ return 0
589+ }
590+ off := 0
591+ binary.LittleEndian.PutUint32(p[off:], uint32(src))
592+ off += 4
593+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
594+ off += 2
595+ off += 2
596+ copy(p[off:], name)
597+ off += len(name)
598+ return seq
599+}
600+
475 func ExpandRegion(b *xturbo.Buf, source Region, destination Region, left uint16, right uint16, top uint16, bottom uint16) xturbo.Seq {601 func ExpandRegion(b *xturbo.Buf, source Region, destination Region, left uint16, right uint16, top uint16, bottom uint16) xturbo.Seq {
476 if b.Ext == nil {602 if b.Ext == nil {
477 b.Fail(xturbo.ErrExtMissing)603 b.Fail(xturbo.ErrExtMissing)
@@ -531,6 +657,61 @@ func ShowCursor(b *xturbo.Buf, window xproto.Window) xturbo.Seq {
531 return seq657 return seq
532 }658 }
533 659
660+func CreatePointerBarrier(b *xturbo.Buf, barrier Barrier, window xproto.Window, x1 uint16, y1 uint16, x2 uint16, y2 uint16, directions BarrierDirections, devices []uint16) xturbo.Seq {
661+ if uint64(len(devices)) > 65535 {
662+ b.Fail(xturbo.ErrBadLength)
663+ return 0
664+ }
665+ size := 0
666+ size += 4
667+ size += 4
668+ size += 2
669+ size += 2
670+ size += 2
671+ size += 2
672+ size += 4
673+ size += 2
674+ size += 2
675+ size += len(devices) * 2
676+ size = (size + 3) &^ 3
677+ if b.Ext == nil {
678+ b.Fail(xturbo.ErrExtMissing)
679+ return 0
680+ }
681+ major := b.Ext.Major(xturbo.ExtXFixes)
682+ if major == 0 {
683+ b.Fail(xturbo.ErrExtMissing)
684+ return 0
685+ }
686+ p, seq := b.Request(major, 31, size)
687+ if p == nil {
688+ return 0
689+ }
690+ off := 0
691+ binary.LittleEndian.PutUint32(p[off:], uint32(barrier))
692+ off += 4
693+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
694+ off += 4
695+ binary.LittleEndian.PutUint16(p[off:], uint16(x1))
696+ off += 2
697+ binary.LittleEndian.PutUint16(p[off:], uint16(y1))
698+ off += 2
699+ binary.LittleEndian.PutUint16(p[off:], uint16(x2))
700+ off += 2
701+ binary.LittleEndian.PutUint16(p[off:], uint16(y2))
702+ off += 2
703+ binary.LittleEndian.PutUint32(p[off:], uint32(directions))
704+ off += 4
705+ off += 2
706+ binary.LittleEndian.PutUint16(p[off:], uint16(len(devices)))
707+ off += 2
708+ for i := range devices {
709+ binary.LittleEndian.PutUint16(p[off:], uint16(devices[i]))
710+ off += 2
711+ }
712+ return seq
713+}
714+
534 func DeletePointerBarrier(b *xturbo.Buf, barrier Barrier) xturbo.Seq {715 func DeletePointerBarrier(b *xturbo.Buf, barrier Barrier) xturbo.Seq {
535 if b.Ext == nil {716 if b.Ext == nil {
536 b.Fail(xturbo.ErrExtMissing)717 b.Fail(xturbo.ErrExtMissing)
M xproto/requests_generated.go +902 -14
@@ -32,7 +32,7 @@ func DestroySubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
3232 }
3333
3434 func ChangeSaveSet(b *xturbo.Buf, mode SetMode, window Window) xturbo.Seq {
35- p, seq := b.Request(6, uint8(mode), 4)
35+ p, seq := b.Request(6, uint8(int(mode)), 4)
3636 if p == nil {
3737 return 0
3838 }
@@ -89,7 +89,7 @@ func UnmapSubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
8989 }
9090
9191 func CirculateWindow(b *xturbo.Buf, direction Circulate, window Window) xturbo.Seq {
92- p, seq := b.Request(13, uint8(direction), 4)
92+ p, seq := b.Request(13, uint8(int(direction)), 4)
9393 if p == nil {
9494 return 0
9595 }
@@ -115,6 +115,33 @@ func QueryTree(b *xturbo.Buf, window Window) xturbo.Seq {
115115 return seq
116116 }
117117
118+func InternAtom(b *xturbo.Buf, onlyIfExists bool, name string) xturbo.Seq {
119+ if uint64(len(name)) > 65535 {
120+ b.Fail(xturbo.ErrBadLength)
121+ return 0
122+ }
123+ size := 0
124+ size += 2
125+ size += 2
126+ size += len(name) * 1
127+ size = (size + 3) &^ 3
128+ var data uint8
129+ if onlyIfExists {
130+ data = 1
131+ }
132+ p, seq := b.Request(16, data, size)
133+ if p == nil {
134+ return 0
135+ }
136+ off := 0
137+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
138+ off += 2
139+ off += 2
140+ copy(p[off:], name)
141+ off += len(name)
142+ return seq
143+}
144+
118145 func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
119146 p, seq := b.Request(17, 0, 4)
120147 if p == nil {
@@ -124,6 +151,41 @@ func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
124151 return seq
125152 }
126153
154+func ChangeProperty(b *xturbo.Buf, mode PropMode, window Window, property Atom, type_ Atom, format uint8, dataLen uint32, data []byte) xturbo.Seq {
155+ if len(data) != ((int(dataLen) * int(format)) / 8) {
156+ b.Fail(xturbo.ErrBadLength)
157+ return 0
158+ }
159+ size := 0
160+ size += 4
161+ size += 4
162+ size += 4
163+ size += 1
164+ size += 3
165+ size += 4
166+ size += len(data) * 1
167+ size = (size + 3) &^ 3
168+ p, seq := b.Request(18, uint8(int(mode)), size)
169+ if p == nil {
170+ return 0
171+ }
172+ off := 0
173+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(property))
176+ off += 4
177+ binary.LittleEndian.PutUint32(p[off:], uint32(type_))
178+ off += 4
179+ p[off:][0] = byte(format)
180+ off += 1
181+ off += 3
182+ binary.LittleEndian.PutUint32(p[off:], uint32(dataLen))
183+ off += 4
184+ copy(p[off:], data)
185+ off += len(data)
186+ return seq
187+}
188+
127189 func DeleteProperty(b *xturbo.Buf, window Window, property Atom) xturbo.Seq {
128190 p, seq := b.Request(19, 0, 8)
129191 if p == nil {
@@ -193,6 +255,33 @@ func ConvertSelection(b *xturbo.Buf, requestor Window, selection Atom, target At
193255 return seq
194256 }
195257
258+func SendEvent(b *xturbo.Buf, propagate bool, destination Window, eventMask EventMask, event *[32]byte) xturbo.Seq {
259+ if len(event) != 32 {
260+ b.Fail(xturbo.ErrBadLength)
261+ return 0
262+ }
263+ size := 0
264+ size += 4
265+ size += 4
266+ size += len(event) * 1
267+ size = (size + 3) &^ 3
268+ var data uint8
269+ if propagate {
270+ data = 1
271+ }
272+ p, seq := b.Request(25, data, size)
273+ if p == nil {
274+ return 0
275+ }
276+ off := 0
277+ binary.LittleEndian.PutUint32(p[off:], uint32(destination))
278+ off += 4
279+ binary.LittleEndian.PutUint32(p[off:], uint32(eventMask))
280+ off += 4
281+ copy(p[off:], event[:])
282+ return seq
283+}
284+
196285 func GrabPointer(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask EventMask, pointerMode GrabMode, keyboardMode GrabMode, confineTo Window, cursor Cursor, time Timestamp) xturbo.Seq {
197286 var data uint8
198287 if ownerEvents {
@@ -242,7 +331,7 @@ func GrabButton(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask Ev
242331 }
243332
244333 func UngrabButton(b *xturbo.Buf, button ButtonIndex, grabWindow Window, modifiers ModMask) xturbo.Seq {
245- p, seq := b.Request(29, uint8(button), 8)
334+ p, seq := b.Request(29, uint8(int(button)), 8)
246335 if p == nil {
247336 return 0
248337 }
@@ -305,7 +394,7 @@ func GrabKey(b *xturbo.Buf, ownerEvents bool, grabWindow Window, modifiers ModMa
305394 }
306395
307396 func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask) xturbo.Seq {
308- p, seq := b.Request(34, uint8(key), 8)
397+ p, seq := b.Request(34, uint8(int(key)), 8)
309398 if p == nil {
310399 return 0
311400 }
@@ -315,7 +404,7 @@ func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask)
315404 }
316405
317406 func AllowEvents(b *xturbo.Buf, mode Allow, time Timestamp) xturbo.Seq {
318- p, seq := b.Request(35, uint8(mode), 4)
407+ p, seq := b.Request(35, uint8(int(mode)), 4)
319408 if p == nil {
320409 return 0
321410 }
@@ -388,7 +477,7 @@ func WarpPointer(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16,
388477 }
389478
390479 func SetInputFocus(b *xturbo.Buf, revertTo InputFocus, focus Window, time Timestamp) xturbo.Seq {
391- p, seq := b.Request(42, uint8(revertTo), 8)
480+ p, seq := b.Request(42, uint8(int(revertTo)), 8)
392481 if p == nil {
393482 return 0
394483 }
@@ -413,6 +502,32 @@ func QueryKeymap(b *xturbo.Buf) xturbo.Seq {
413502 return seq
414503 }
415504
505+func OpenFont(b *xturbo.Buf, fid Font, name string) xturbo.Seq {
506+ if uint64(len(name)) > 65535 {
507+ b.Fail(xturbo.ErrBadLength)
508+ return 0
509+ }
510+ size := 0
511+ size += 4
512+ size += 2
513+ size += 2
514+ size += len(name) * 1
515+ size = (size + 3) &^ 3
516+ p, seq := b.Request(45, 0, size)
517+ if p == nil {
518+ return 0
519+ }
520+ off := 0
521+ binary.LittleEndian.PutUint32(p[off:], uint32(fid))
522+ off += 4
523+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
524+ off += 2
525+ off += 2
526+ copy(p[off:], name)
527+ off += len(name)
528+ return seq
529+}
530+
416531 func CloseFont(b *xturbo.Buf, font Font) xturbo.Seq {
417532 p, seq := b.Request(46, 0, 4)
418533 if p == nil {
@@ -431,6 +546,104 @@ func QueryFont(b *xturbo.Buf, font Fontable) xturbo.Seq {
431546 return seq
432547 }
433548
549+func QueryTextExtents(b *xturbo.Buf, font Fontable, string []Char2b) xturbo.Seq {
550+ size := 0
551+ size += 4
552+ size += len(string) * 2
553+ size = (size + 3) &^ 3
554+ var data uint8
555+ if (len(string) & 1) != 0 {
556+ data = 1
557+ }
558+ p, seq := b.Request(48, data, size)
559+ if p == nil {
560+ return 0
561+ }
562+ off := 0
563+ binary.LittleEndian.PutUint32(p[off:], uint32(font))
564+ off += 4
565+ for i := range string {
566+ string[i].Put(p[off:])
567+ off += 2
568+ }
569+ return seq
570+}
571+
572+func ListFonts(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
573+ if uint64(len(pattern)) > 65535 {
574+ b.Fail(xturbo.ErrBadLength)
575+ return 0
576+ }
577+ size := 0
578+ size += 2
579+ size += 2
580+ size += len(pattern) * 1
581+ size = (size + 3) &^ 3
582+ p, seq := b.Request(49, 0, size)
583+ if p == nil {
584+ return 0
585+ }
586+ off := 0
587+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
588+ off += 2
589+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
590+ off += 2
591+ copy(p[off:], pattern)
592+ off += len(pattern)
593+ return seq
594+}
595+
596+func ListFontsWithInfo(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
597+ if uint64(len(pattern)) > 65535 {
598+ b.Fail(xturbo.ErrBadLength)
599+ return 0
600+ }
601+ size := 0
602+ size += 2
603+ size += 2
604+ size += len(pattern) * 1
605+ size = (size + 3) &^ 3
606+ p, seq := b.Request(50, 0, size)
607+ if p == nil {
608+ return 0
609+ }
610+ off := 0
611+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
612+ off += 2
613+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
614+ off += 2
615+ copy(p[off:], pattern)
616+ off += len(pattern)
617+ return seq
618+}
619+
620+func SetFontPath(b *xturbo.Buf, font []Str) xturbo.Seq {
621+ if uint64(len(font)) > 65535 {
622+ b.Fail(xturbo.ErrBadLength)
623+ return 0
624+ }
625+ size := 0
626+ size += 2
627+ size += 2
628+ for i := range font {
629+ size += font[i].Size()
630+ }
631+ size = (size + 3) &^ 3
632+ p, seq := b.Request(51, 0, size)
633+ if p == nil {
634+ return 0
635+ }
636+ off := 0
637+ binary.LittleEndian.PutUint16(p[off:], uint16(len(font)))
638+ off += 2
639+ off += 2
640+ for i := range font {
641+ font[i].Put(p[off:])
642+ off += font[i].Size()
643+ }
644+ return seq
645+}
646+
434647 func GetFontPath(b *xturbo.Buf) xturbo.Seq {
435648 p, seq := b.Request(52, 0, 0)
436649 if p == nil {
@@ -440,7 +653,7 @@ func GetFontPath(b *xturbo.Buf) xturbo.Seq {
440653 }
441654
442655 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)
656+ p, seq := b.Request(53, uint8(int(depth)), 12)
444657 if p == nil {
445658 return 0
446659 }
@@ -471,6 +684,58 @@ func CopyGC(b *xturbo.Buf, srcGc Gcontext, dstGc Gcontext, valueMask Gc) xturbo.
471684 return seq
472685 }
473686
687+func SetDashes(b *xturbo.Buf, gc Gcontext, dashOffset uint16, dashes []byte) xturbo.Seq {
688+ if uint64(len(dashes)) > 65535 {
689+ b.Fail(xturbo.ErrBadLength)
690+ return 0
691+ }
692+ size := 0
693+ size += 4
694+ size += 2
695+ size += 2
696+ size += len(dashes) * 1
697+ size = (size + 3) &^ 3
698+ p, seq := b.Request(58, 0, size)
699+ if p == nil {
700+ return 0
701+ }
702+ off := 0
703+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
704+ off += 4
705+ binary.LittleEndian.PutUint16(p[off:], uint16(dashOffset))
706+ off += 2
707+ binary.LittleEndian.PutUint16(p[off:], uint16(len(dashes)))
708+ off += 2
709+ copy(p[off:], dashes)
710+ off += len(dashes)
711+ return seq
712+}
713+
714+func SetClipRectangles(b *xturbo.Buf, ordering ClipOrdering, gc Gcontext, clipXOrigin int16, clipYOrigin int16, rectangles []Rectangle) xturbo.Seq {
715+ size := 0
716+ size += 4
717+ size += 2
718+ size += 2
719+ size += len(rectangles) * 8
720+ size = (size + 3) &^ 3
721+ p, seq := b.Request(59, uint8(int(ordering)), size)
722+ if p == nil {
723+ return 0
724+ }
725+ off := 0
726+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
727+ off += 4
728+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
729+ off += 2
730+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
731+ off += 2
732+ for i := range rectangles {
733+ rectangles[i].Put(p[off:])
734+ off += 8
735+ }
736+ return seq
737+}
738+
474739 func FreeGC(b *xturbo.Buf, gc Gcontext) xturbo.Seq {
475740 p, seq := b.Request(60, 0, 4)
476741 if p == nil {
@@ -532,8 +797,232 @@ func CopyPlane(b *xturbo.Buf, srcDrawable Drawable, dstDrawable Drawable, gc Gco
532797 return seq
533798 }
534799
800+func PolyPoint(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
801+ size := 0
802+ size += 4
803+ size += 4
804+ size += len(points) * 4
805+ size = (size + 3) &^ 3
806+ p, seq := b.Request(64, uint8(int(coordinateMode)), size)
807+ if p == nil {
808+ return 0
809+ }
810+ off := 0
811+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
812+ off += 4
813+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
814+ off += 4
815+ for i := range points {
816+ points[i].Put(p[off:])
817+ off += 4
818+ }
819+ return seq
820+}
821+
822+func PolyLine(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
823+ size := 0
824+ size += 4
825+ size += 4
826+ size += len(points) * 4
827+ size = (size + 3) &^ 3
828+ p, seq := b.Request(65, uint8(int(coordinateMode)), size)
829+ if p == nil {
830+ return 0
831+ }
832+ off := 0
833+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
834+ off += 4
835+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
836+ off += 4
837+ for i := range points {
838+ points[i].Put(p[off:])
839+ off += 4
840+ }
841+ return seq
842+}
843+
844+func PolySegment(b *xturbo.Buf, drawable Drawable, gc Gcontext, segments []Segment) xturbo.Seq {
845+ size := 0
846+ size += 4
847+ size += 4
848+ size += len(segments) * 8
849+ size = (size + 3) &^ 3
850+ p, seq := b.Request(66, 0, size)
851+ if p == nil {
852+ return 0
853+ }
854+ off := 0
855+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
856+ off += 4
857+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
858+ off += 4
859+ for i := range segments {
860+ segments[i].Put(p[off:])
861+ off += 8
862+ }
863+ return seq
864+}
865+
866+func PolyRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
867+ size := 0
868+ size += 4
869+ size += 4
870+ size += len(rectangles) * 8
871+ size = (size + 3) &^ 3
872+ p, seq := b.Request(67, 0, size)
873+ if p == nil {
874+ return 0
875+ }
876+ off := 0
877+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
878+ off += 4
879+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
880+ off += 4
881+ for i := range rectangles {
882+ rectangles[i].Put(p[off:])
883+ off += 8
884+ }
885+ return seq
886+}
887+
888+func PolyArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
889+ size := 0
890+ size += 4
891+ size += 4
892+ size += len(arcs) * 12
893+ size = (size + 3) &^ 3
894+ p, seq := b.Request(68, 0, size)
895+ if p == nil {
896+ return 0
897+ }
898+ off := 0
899+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
900+ off += 4
901+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
902+ off += 4
903+ for i := range arcs {
904+ arcs[i].Put(p[off:])
905+ off += 12
906+ }
907+ return seq
908+}
909+
910+func FillPoly(b *xturbo.Buf, drawable Drawable, gc Gcontext, shape PolyShape, coordinateMode CoordMode, points []Point) xturbo.Seq {
911+ size := 0
912+ size += 4
913+ size += 4
914+ size += 1
915+ size += 1
916+ size += 2
917+ size += len(points) * 4
918+ size = (size + 3) &^ 3
919+ p, seq := b.Request(69, 0, size)
920+ if p == nil {
921+ return 0
922+ }
923+ off := 0
924+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
925+ off += 4
926+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
927+ off += 4
928+ p[off:][0] = byte(shape)
929+ off += 1
930+ p[off:][0] = byte(coordinateMode)
931+ off += 1
932+ off += 2
933+ for i := range points {
934+ points[i].Put(p[off:])
935+ off += 4
936+ }
937+ return seq
938+}
939+
940+func PolyFillRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
941+ size := 0
942+ size += 4
943+ size += 4
944+ size += len(rectangles) * 8
945+ size = (size + 3) &^ 3
946+ p, seq := b.Request(70, 0, size)
947+ if p == nil {
948+ return 0
949+ }
950+ off := 0
951+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
952+ off += 4
953+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
954+ off += 4
955+ for i := range rectangles {
956+ rectangles[i].Put(p[off:])
957+ off += 8
958+ }
959+ return seq
960+}
961+
962+func PolyFillArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
963+ size := 0
964+ size += 4
965+ size += 4
966+ size += len(arcs) * 12
967+ size = (size + 3) &^ 3
968+ p, seq := b.Request(71, 0, size)
969+ if p == nil {
970+ return 0
971+ }
972+ off := 0
973+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
974+ off += 4
975+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
976+ off += 4
977+ for i := range arcs {
978+ arcs[i].Put(p[off:])
979+ off += 12
980+ }
981+ return seq
982+}
983+
984+func PutImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, gc Gcontext, width uint16, height uint16, dstX int16, dstY int16, leftPad uint8, depth uint8, data []byte) xturbo.Seq {
985+ size := 0
986+ size += 4
987+ size += 4
988+ size += 2
989+ size += 2
990+ size += 2
991+ size += 2
992+ size += 1
993+ size += 1
994+ size += 2
995+ size += len(data) * 1
996+ size = (size + 3) &^ 3
997+ p, seq := b.Request(72, uint8(int(format)), size)
998+ if p == nil {
999+ return 0
1000+ }
1001+ off := 0
1002+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1003+ off += 4
1004+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1005+ off += 4
1006+ binary.LittleEndian.PutUint16(p[off:], uint16(width))
1007+ off += 2
1008+ binary.LittleEndian.PutUint16(p[off:], uint16(height))
1009+ off += 2
1010+ binary.LittleEndian.PutUint16(p[off:], uint16(dstX))
1011+ off += 2
1012+ binary.LittleEndian.PutUint16(p[off:], uint16(dstY))
1013+ off += 2
1014+ p[off:][0] = byte(leftPad)
1015+ off += 1
1016+ p[off:][0] = byte(depth)
1017+ off += 1
1018+ off += 2
1019+ copy(p[off:], data)
1020+ off += len(data)
1021+ return seq
1022+}
1023+
5351024 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)
1025+ p, seq := b.Request(73, uint8(int(format)), 16)
5371026 if p == nil {
5381027 return 0
5391028 }
@@ -546,8 +1035,122 @@ func GetImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, x int16, y i
5461035 return seq
5471036 }
5481037
1038+func PolyText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1039+ size := 0
1040+ size += 4
1041+ size += 4
1042+ size += 2
1043+ size += 2
1044+ size += len(items) * 1
1045+ size = (size + 3) &^ 3
1046+ p, seq := b.Request(74, 0, size)
1047+ if p == nil {
1048+ return 0
1049+ }
1050+ off := 0
1051+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1052+ off += 4
1053+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1054+ off += 4
1055+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1056+ off += 2
1057+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1058+ off += 2
1059+ copy(p[off:], items)
1060+ off += len(items)
1061+ return seq
1062+}
1063+
1064+func PolyText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1065+ size := 0
1066+ size += 4
1067+ size += 4
1068+ size += 2
1069+ size += 2
1070+ size += len(items) * 1
1071+ size = (size + 3) &^ 3
1072+ p, seq := b.Request(75, 0, size)
1073+ if p == nil {
1074+ return 0
1075+ }
1076+ off := 0
1077+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1078+ off += 4
1079+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1080+ off += 4
1081+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1082+ off += 2
1083+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1084+ off += 2
1085+ copy(p[off:], items)
1086+ off += len(items)
1087+ return seq
1088+}
1089+
1090+func ImageText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string string) xturbo.Seq {
1091+ if len(string) > 255 {
1092+ b.Fail(xturbo.ErrBadLength)
1093+ return 0
1094+ }
1095+ size := 0
1096+ size += 4
1097+ size += 4
1098+ size += 2
1099+ size += 2
1100+ size += len(string) * 1
1101+ size = (size + 3) &^ 3
1102+ p, seq := b.Request(76, uint8(len(string)), size)
1103+ if p == nil {
1104+ return 0
1105+ }
1106+ off := 0
1107+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1108+ off += 4
1109+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1110+ off += 4
1111+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1112+ off += 2
1113+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1114+ off += 2
1115+ copy(p[off:], string)
1116+ off += len(string)
1117+ return seq
1118+}
1119+
1120+func ImageText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string []Char2b) xturbo.Seq {
1121+ if len(string) > 255 {
1122+ b.Fail(xturbo.ErrBadLength)
1123+ return 0
1124+ }
1125+ size := 0
1126+ size += 4
1127+ size += 4
1128+ size += 2
1129+ size += 2
1130+ size += len(string) * 2
1131+ size = (size + 3) &^ 3
1132+ p, seq := b.Request(77, uint8(len(string)), size)
1133+ if p == nil {
1134+ return 0
1135+ }
1136+ off := 0
1137+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1138+ off += 4
1139+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1140+ off += 4
1141+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1142+ off += 2
1143+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1144+ off += 2
1145+ for i := range string {
1146+ string[i].Put(p[off:])
1147+ off += 2
1148+ }
1149+ return seq
1150+}
1151+
5491152 func CreateColormap(b *xturbo.Buf, alloc ColormapAlloc, mid Colormap, window Window, visual Visualid) xturbo.Seq {
550- p, seq := b.Request(78, uint8(alloc), 12)
1153+ p, seq := b.Request(78, uint8(int(alloc)), 12)
5511154 if p == nil {
5521155 return 0
5531156 }
@@ -615,6 +1218,32 @@ func AllocColor(b *xturbo.Buf, cmap Colormap, red uint16, green uint16, blue uin
6151218 return seq
6161219 }
6171220
1221+func AllocNamedColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1222+ if uint64(len(name)) > 65535 {
1223+ b.Fail(xturbo.ErrBadLength)
1224+ return 0
1225+ }
1226+ size := 0
1227+ size += 4
1228+ size += 2
1229+ size += 2
1230+ size += len(name) * 1
1231+ size = (size + 3) &^ 3
1232+ p, seq := b.Request(85, 0, size)
1233+ if p == nil {
1234+ return 0
1235+ }
1236+ off := 0
1237+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1238+ off += 4
1239+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1240+ off += 2
1241+ off += 2
1242+ copy(p[off:], name)
1243+ off += len(name)
1244+ return seq
1245+}
1246+
6181247 func AllocColorCells(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, planes uint16) xturbo.Seq {
6191248 var data uint8
6201249 if contiguous {
@@ -647,6 +1276,121 @@ func AllocColorPlanes(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint
6471276 return seq
6481277 }
6491278
1279+func FreeColors(b *xturbo.Buf, cmap Colormap, planeMask uint32, pixels []uint32) xturbo.Seq {
1280+ size := 0
1281+ size += 4
1282+ size += 4
1283+ size += len(pixels) * 4
1284+ size = (size + 3) &^ 3
1285+ p, seq := b.Request(88, 0, size)
1286+ if p == nil {
1287+ return 0
1288+ }
1289+ off := 0
1290+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1291+ off += 4
1292+ binary.LittleEndian.PutUint32(p[off:], uint32(planeMask))
1293+ off += 4
1294+ for i := range pixels {
1295+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1296+ off += 4
1297+ }
1298+ return seq
1299+}
1300+
1301+func StoreColors(b *xturbo.Buf, cmap Colormap, items []Coloritem) xturbo.Seq {
1302+ size := 0
1303+ size += 4
1304+ size += len(items) * 12
1305+ size = (size + 3) &^ 3
1306+ p, seq := b.Request(89, 0, size)
1307+ if p == nil {
1308+ return 0
1309+ }
1310+ off := 0
1311+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1312+ off += 4
1313+ for i := range items {
1314+ items[i].Put(p[off:])
1315+ off += 12
1316+ }
1317+ return seq
1318+}
1319+
1320+func StoreNamedColor(b *xturbo.Buf, flags ColorFlag, cmap Colormap, pixel uint32, name string) xturbo.Seq {
1321+ if uint64(len(name)) > 65535 {
1322+ b.Fail(xturbo.ErrBadLength)
1323+ return 0
1324+ }
1325+ size := 0
1326+ size += 4
1327+ size += 4
1328+ size += 2
1329+ size += 2
1330+ size += len(name) * 1
1331+ size = (size + 3) &^ 3
1332+ p, seq := b.Request(90, uint8(int(flags)), size)
1333+ if p == nil {
1334+ return 0
1335+ }
1336+ off := 0
1337+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1338+ off += 4
1339+ binary.LittleEndian.PutUint32(p[off:], uint32(pixel))
1340+ off += 4
1341+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1342+ off += 2
1343+ off += 2
1344+ copy(p[off:], name)
1345+ off += len(name)
1346+ return seq
1347+}
1348+
1349+func QueryColors(b *xturbo.Buf, cmap Colormap, pixels []uint32) xturbo.Seq {
1350+ size := 0
1351+ size += 4
1352+ size += len(pixels) * 4
1353+ size = (size + 3) &^ 3
1354+ p, seq := b.Request(91, 0, size)
1355+ if p == nil {
1356+ return 0
1357+ }
1358+ off := 0
1359+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1360+ off += 4
1361+ for i := range pixels {
1362+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1363+ off += 4
1364+ }
1365+ return seq
1366+}
1367+
1368+func LookupColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1369+ if uint64(len(name)) > 65535 {
1370+ b.Fail(xturbo.ErrBadLength)
1371+ return 0
1372+ }
1373+ size := 0
1374+ size += 4
1375+ size += 2
1376+ size += 2
1377+ size += len(name) * 1
1378+ size = (size + 3) &^ 3
1379+ p, seq := b.Request(92, 0, size)
1380+ if p == nil {
1381+ return 0
1382+ }
1383+ off := 0
1384+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1385+ off += 4
1386+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1387+ off += 2
1388+ off += 2
1389+ copy(p[off:], name)
1390+ off += len(name)
1391+ return seq
1392+}
1393+
6501394 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 {
6511395 p, seq := b.Request(93, 0, 28)
6521396 if p == nil {
@@ -710,7 +1454,7 @@ func RecolorCursor(b *xturbo.Buf, cursor Cursor, foreRed uint16, foreGreen uint1
7101454 }
7111455
7121456 func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width uint16, height uint16) xturbo.Seq {
713- p, seq := b.Request(97, uint8(class), 8)
1457+ p, seq := b.Request(97, uint8(int(class)), 8)
7141458 if p == nil {
7151459 return 0
7161460 }
@@ -720,6 +1464,29 @@ func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width u
7201464 return seq
7211465 }
7221466
1467+func QueryExtension(b *xturbo.Buf, name string) xturbo.Seq {
1468+ if uint64(len(name)) > 65535 {
1469+ b.Fail(xturbo.ErrBadLength)
1470+ return 0
1471+ }
1472+ size := 0
1473+ size += 2
1474+ size += 2
1475+ size += len(name) * 1
1476+ size = (size + 3) &^ 3
1477+ p, seq := b.Request(98, 0, size)
1478+ if p == nil {
1479+ return 0
1480+ }
1481+ off := 0
1482+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1483+ off += 2
1484+ off += 2
1485+ copy(p[off:], name)
1486+ off += len(name)
1487+ return seq
1488+}
1489+
7231490 func ListExtensions(b *xturbo.Buf) xturbo.Seq {
7241491 p, seq := b.Request(99, 0, 0)
7251492 if p == nil {
@@ -728,6 +1495,34 @@ func ListExtensions(b *xturbo.Buf) xturbo.Seq {
7281495 return seq
7291496 }
7301497
1498+func ChangeKeyboardMapping(b *xturbo.Buf, keycodeCount uint8, firstKeycode Keycode, keysymsPerKeycode uint8, keysyms []Keysym) xturbo.Seq {
1499+ if len(keysyms) != (int(keycodeCount) * int(keysymsPerKeycode)) {
1500+ b.Fail(xturbo.ErrBadLength)
1501+ return 0
1502+ }
1503+ size := 0
1504+ size += 1
1505+ size += 1
1506+ size += 2
1507+ size += len(keysyms) * 4
1508+ size = (size + 3) &^ 3
1509+ p, seq := b.Request(100, uint8(int(keycodeCount)), size)
1510+ if p == nil {
1511+ return 0
1512+ }
1513+ off := 0
1514+ p[off:][0] = byte(firstKeycode)
1515+ off += 1
1516+ p[off:][0] = byte(keysymsPerKeycode)
1517+ off += 1
1518+ off += 2
1519+ for i := range keysyms {
1520+ binary.LittleEndian.PutUint32(p[off:], uint32(keysyms[i]))
1521+ off += 4
1522+ }
1523+ return seq
1524+}
1525+
7311526 func GetKeyboardMapping(b *xturbo.Buf, firstKeycode Keycode, count uint8) xturbo.Seq {
7321527 p, seq := b.Request(101, 0, 4)
7331528 if p == nil {
@@ -747,7 +1542,7 @@ func GetKeyboardControl(b *xturbo.Buf) xturbo.Seq {
7471542 }
7481543
7491544 func Bell(b *xturbo.Buf, percent int8) xturbo.Seq {
750- p, seq := b.Request(104, uint8(percent), 0)
1545+ p, seq := b.Request(104, uint8(int(percent)), 0)
7511546 if p == nil {
7521547 return 0
7531548 }
@@ -803,6 +1598,32 @@ func GetScreenSaver(b *xturbo.Buf) xturbo.Seq {
8031598 return seq
8041599 }
8051600
1601+func ChangeHosts(b *xturbo.Buf, mode HostMode, family Family, address []byte) xturbo.Seq {
1602+ if uint64(len(address)) > 65535 {
1603+ b.Fail(xturbo.ErrBadLength)
1604+ return 0
1605+ }
1606+ size := 0
1607+ size += 1
1608+ size += 1
1609+ size += 2
1610+ size += len(address) * 1
1611+ size = (size + 3) &^ 3
1612+ p, seq := b.Request(109, uint8(int(mode)), size)
1613+ if p == nil {
1614+ return 0
1615+ }
1616+ off := 0
1617+ p[off:][0] = byte(family)
1618+ off += 1
1619+ off += 1
1620+ binary.LittleEndian.PutUint16(p[off:], uint16(len(address)))
1621+ off += 2
1622+ copy(p[off:], address)
1623+ off += len(address)
1624+ return seq
1625+}
1626+
8061627 func ListHosts(b *xturbo.Buf) xturbo.Seq {
8071628 p, seq := b.Request(110, 0, 0)
8081629 if p == nil {
@@ -812,7 +1633,7 @@ func ListHosts(b *xturbo.Buf) xturbo.Seq {
8121633 }
8131634
8141635 func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
815- p, seq := b.Request(111, uint8(mode), 0)
1636+ p, seq := b.Request(111, uint8(int(mode)), 0)
8161637 if p == nil {
8171638 return 0
8181639 }
@@ -820,7 +1641,7 @@ func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
8201641 }
8211642
8221643 func SetCloseDownMode(b *xturbo.Buf, mode CloseDown) xturbo.Seq {
823- p, seq := b.Request(112, uint8(mode), 0)
1644+ p, seq := b.Request(112, uint8(int(mode)), 0)
8241645 if p == nil {
8251646 return 0
8261647 }
@@ -836,14 +1657,61 @@ func KillClient(b *xturbo.Buf, resource uint32) xturbo.Seq {
8361657 return seq
8371658 }
8381659
1660+func RotateProperties(b *xturbo.Buf, window Window, delta int16, atoms []Atom) xturbo.Seq {
1661+ if uint64(len(atoms)) > 65535 {
1662+ b.Fail(xturbo.ErrBadLength)
1663+ return 0
1664+ }
1665+ size := 0
1666+ size += 4
1667+ size += 2
1668+ size += 2
1669+ size += len(atoms) * 4
1670+ size = (size + 3) &^ 3
1671+ p, seq := b.Request(114, 0, size)
1672+ if p == nil {
1673+ return 0
1674+ }
1675+ off := 0
1676+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
1677+ off += 4
1678+ binary.LittleEndian.PutUint16(p[off:], uint16(len(atoms)))
1679+ off += 2
1680+ binary.LittleEndian.PutUint16(p[off:], uint16(delta))
1681+ off += 2
1682+ for i := range atoms {
1683+ binary.LittleEndian.PutUint32(p[off:], uint32(atoms[i]))
1684+ off += 4
1685+ }
1686+ return seq
1687+}
1688+
8391689 func ForceScreenSaver(b *xturbo.Buf, mode ScreenSaver) xturbo.Seq {
840- p, seq := b.Request(115, uint8(mode), 0)
1690+ p, seq := b.Request(115, uint8(int(mode)), 0)
8411691 if p == nil {
8421692 return 0
8431693 }
8441694 return seq
8451695 }
8461696
1697+func SetPointerMapping(b *xturbo.Buf, map_ []byte) xturbo.Seq {
1698+ if len(map_) > 255 {
1699+ b.Fail(xturbo.ErrBadLength)
1700+ return 0
1701+ }
1702+ size := 0
1703+ size += len(map_) * 1
1704+ size = (size + 3) &^ 3
1705+ p, seq := b.Request(116, uint8(len(map_)), size)
1706+ if p == nil {
1707+ return 0
1708+ }
1709+ off := 0
1710+ copy(p[off:], map_)
1711+ off += len(map_)
1712+ return seq
1713+}
1714+
8471715 func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
8481716 p, seq := b.Request(117, 0, 0)
8491717 if p == nil {
@@ -852,6 +1720,26 @@ func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
8521720 return seq
8531721 }
8541722
1723+func SetModifierMapping(b *xturbo.Buf, keycodesPerModifier uint8, keycodes []Keycode) xturbo.Seq {
1724+ if len(keycodes) != (int(keycodesPerModifier) * 8) {
1725+ b.Fail(xturbo.ErrBadLength)
1726+ return 0
1727+ }
1728+ size := 0
1729+ size += len(keycodes) * 1
1730+ size = (size + 3) &^ 3
1731+ p, seq := b.Request(118, uint8(int(keycodesPerModifier)), size)
1732+ if p == nil {
1733+ return 0
1734+ }
1735+ off := 0
1736+ for i := range keycodes {
1737+ p[off:][0] = byte(keycodes[i])
1738+ off += 1
1739+ }
1740+ return seq
1741+}
1742+
8551743 func GetModifierMapping(b *xturbo.Buf) xturbo.Seq {
8561744 p, seq := b.Request(119, 0, 0)
8571745 if p == nil {
@@ -32,7 +32,7 @@ func DestroySubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
32 }32 }
33 33
34 func ChangeSaveSet(b *xturbo.Buf, mode SetMode, window Window) xturbo.Seq {34 func ChangeSaveSet(b *xturbo.Buf, mode SetMode, window Window) xturbo.Seq {
35- p, seq := b.Request(6, uint8(mode), 4)35+ p, seq := b.Request(6, uint8(int(mode)), 4)
36 if p == nil {36 if p == nil {
37 return 037 return 0
38 }38 }
@@ -89,7 +89,7 @@ func UnmapSubwindows(b *xturbo.Buf, window Window) xturbo.Seq {
89 }89 }
90 90
91 func CirculateWindow(b *xturbo.Buf, direction Circulate, window Window) xturbo.Seq {91 func CirculateWindow(b *xturbo.Buf, direction Circulate, window Window) xturbo.Seq {
92- p, seq := b.Request(13, uint8(direction), 4)92+ p, seq := b.Request(13, uint8(int(direction)), 4)
93 if p == nil {93 if p == nil {
94 return 094 return 0
95 }95 }
@@ -115,6 +115,33 @@ func QueryTree(b *xturbo.Buf, window Window) xturbo.Seq {
115 return seq115 return seq
116 }116 }
117 117
118+func InternAtom(b *xturbo.Buf, onlyIfExists bool, name string) xturbo.Seq {
119+ if uint64(len(name)) > 65535 {
120+ b.Fail(xturbo.ErrBadLength)
121+ return 0
122+ }
123+ size := 0
124+ size += 2
125+ size += 2
126+ size += len(name) * 1
127+ size = (size + 3) &^ 3
128+ var data uint8
129+ if onlyIfExists {
130+ data = 1
131+ }
132+ p, seq := b.Request(16, data, size)
133+ if p == nil {
134+ return 0
135+ }
136+ off := 0
137+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
138+ off += 2
139+ off += 2
140+ copy(p[off:], name)
141+ off += len(name)
142+ return seq
143+}
144+
118 func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {145 func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
119 p, seq := b.Request(17, 0, 4)146 p, seq := b.Request(17, 0, 4)
120 if p == nil {147 if p == nil {
@@ -124,6 +151,41 @@ func GetAtomName(b *xturbo.Buf, atom Atom) xturbo.Seq {
124 return seq151 return seq
125 }152 }
126 153
154+func ChangeProperty(b *xturbo.Buf, mode PropMode, window Window, property Atom, type_ Atom, format uint8, dataLen uint32, data []byte) xturbo.Seq {
155+ if len(data) != ((int(dataLen) * int(format)) / 8) {
156+ b.Fail(xturbo.ErrBadLength)
157+ return 0
158+ }
159+ size := 0
160+ size += 4
161+ size += 4
162+ size += 4
163+ size += 1
164+ size += 3
165+ size += 4
166+ size += len(data) * 1
167+ size = (size + 3) &^ 3
168+ p, seq := b.Request(18, uint8(int(mode)), size)
169+ if p == nil {
170+ return 0
171+ }
172+ off := 0
173+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
174+ off += 4
175+ binary.LittleEndian.PutUint32(p[off:], uint32(property))
176+ off += 4
177+ binary.LittleEndian.PutUint32(p[off:], uint32(type_))
178+ off += 4
179+ p[off:][0] = byte(format)
180+ off += 1
181+ off += 3
182+ binary.LittleEndian.PutUint32(p[off:], uint32(dataLen))
183+ off += 4
184+ copy(p[off:], data)
185+ off += len(data)
186+ return seq
187+}
188+
127 func DeleteProperty(b *xturbo.Buf, window Window, property Atom) xturbo.Seq {189 func DeleteProperty(b *xturbo.Buf, window Window, property Atom) xturbo.Seq {
128 p, seq := b.Request(19, 0, 8)190 p, seq := b.Request(19, 0, 8)
129 if p == nil {191 if p == nil {
@@ -193,6 +255,33 @@ func ConvertSelection(b *xturbo.Buf, requestor Window, selection Atom, target At
193 return seq255 return seq
194 }256 }
195 257
258+func SendEvent(b *xturbo.Buf, propagate bool, destination Window, eventMask EventMask, event *[32]byte) xturbo.Seq {
259+ if len(event) != 32 {
260+ b.Fail(xturbo.ErrBadLength)
261+ return 0
262+ }
263+ size := 0
264+ size += 4
265+ size += 4
266+ size += len(event) * 1
267+ size = (size + 3) &^ 3
268+ var data uint8
269+ if propagate {
270+ data = 1
271+ }
272+ p, seq := b.Request(25, data, size)
273+ if p == nil {
274+ return 0
275+ }
276+ off := 0
277+ binary.LittleEndian.PutUint32(p[off:], uint32(destination))
278+ off += 4
279+ binary.LittleEndian.PutUint32(p[off:], uint32(eventMask))
280+ off += 4
281+ copy(p[off:], event[:])
282+ return seq
283+}
284+
196 func GrabPointer(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask EventMask, pointerMode GrabMode, keyboardMode GrabMode, confineTo Window, cursor Cursor, time Timestamp) xturbo.Seq {285 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 uint8286 var data uint8
198 if ownerEvents {287 if ownerEvents {
@@ -242,7 +331,7 @@ func GrabButton(b *xturbo.Buf, ownerEvents bool, grabWindow Window, eventMask Ev
242 }331 }
243 332
244 func UngrabButton(b *xturbo.Buf, button ButtonIndex, grabWindow Window, modifiers ModMask) xturbo.Seq {333 func UngrabButton(b *xturbo.Buf, button ButtonIndex, grabWindow Window, modifiers ModMask) xturbo.Seq {
245- p, seq := b.Request(29, uint8(button), 8)334+ p, seq := b.Request(29, uint8(int(button)), 8)
246 if p == nil {335 if p == nil {
247 return 0336 return 0
248 }337 }
@@ -305,7 +394,7 @@ func GrabKey(b *xturbo.Buf, ownerEvents bool, grabWindow Window, modifiers ModMa
305 }394 }
306 395
307 func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask) xturbo.Seq {396 func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask) xturbo.Seq {
308- p, seq := b.Request(34, uint8(key), 8)397+ p, seq := b.Request(34, uint8(int(key)), 8)
309 if p == nil {398 if p == nil {
310 return 0399 return 0
311 }400 }
@@ -315,7 +404,7 @@ func UngrabKey(b *xturbo.Buf, key Keycode, grabWindow Window, modifiers ModMask)
315 }404 }
316 405
317 func AllowEvents(b *xturbo.Buf, mode Allow, time Timestamp) xturbo.Seq {406 func AllowEvents(b *xturbo.Buf, mode Allow, time Timestamp) xturbo.Seq {
318- p, seq := b.Request(35, uint8(mode), 4)407+ p, seq := b.Request(35, uint8(int(mode)), 4)
319 if p == nil {408 if p == nil {
320 return 0409 return 0
321 }410 }
@@ -388,7 +477,7 @@ func WarpPointer(b *xturbo.Buf, srcWindow Window, dstWindow Window, srcX int16,
388 }477 }
389 478
390 func SetInputFocus(b *xturbo.Buf, revertTo InputFocus, focus Window, time Timestamp) xturbo.Seq {479 func SetInputFocus(b *xturbo.Buf, revertTo InputFocus, focus Window, time Timestamp) xturbo.Seq {
391- p, seq := b.Request(42, uint8(revertTo), 8)480+ p, seq := b.Request(42, uint8(int(revertTo)), 8)
392 if p == nil {481 if p == nil {
393 return 0482 return 0
394 }483 }
@@ -413,6 +502,32 @@ func QueryKeymap(b *xturbo.Buf) xturbo.Seq {
413 return seq502 return seq
414 }503 }
415 504
505+func OpenFont(b *xturbo.Buf, fid Font, name string) xturbo.Seq {
506+ if uint64(len(name)) > 65535 {
507+ b.Fail(xturbo.ErrBadLength)
508+ return 0
509+ }
510+ size := 0
511+ size += 4
512+ size += 2
513+ size += 2
514+ size += len(name) * 1
515+ size = (size + 3) &^ 3
516+ p, seq := b.Request(45, 0, size)
517+ if p == nil {
518+ return 0
519+ }
520+ off := 0
521+ binary.LittleEndian.PutUint32(p[off:], uint32(fid))
522+ off += 4
523+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
524+ off += 2
525+ off += 2
526+ copy(p[off:], name)
527+ off += len(name)
528+ return seq
529+}
530+
416 func CloseFont(b *xturbo.Buf, font Font) xturbo.Seq {531 func CloseFont(b *xturbo.Buf, font Font) xturbo.Seq {
417 p, seq := b.Request(46, 0, 4)532 p, seq := b.Request(46, 0, 4)
418 if p == nil {533 if p == nil {
@@ -431,6 +546,104 @@ func QueryFont(b *xturbo.Buf, font Fontable) xturbo.Seq {
431 return seq546 return seq
432 }547 }
433 548
549+func QueryTextExtents(b *xturbo.Buf, font Fontable, string []Char2b) xturbo.Seq {
550+ size := 0
551+ size += 4
552+ size += len(string) * 2
553+ size = (size + 3) &^ 3
554+ var data uint8
555+ if (len(string) & 1) != 0 {
556+ data = 1
557+ }
558+ p, seq := b.Request(48, data, size)
559+ if p == nil {
560+ return 0
561+ }
562+ off := 0
563+ binary.LittleEndian.PutUint32(p[off:], uint32(font))
564+ off += 4
565+ for i := range string {
566+ string[i].Put(p[off:])
567+ off += 2
568+ }
569+ return seq
570+}
571+
572+func ListFonts(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
573+ if uint64(len(pattern)) > 65535 {
574+ b.Fail(xturbo.ErrBadLength)
575+ return 0
576+ }
577+ size := 0
578+ size += 2
579+ size += 2
580+ size += len(pattern) * 1
581+ size = (size + 3) &^ 3
582+ p, seq := b.Request(49, 0, size)
583+ if p == nil {
584+ return 0
585+ }
586+ off := 0
587+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
588+ off += 2
589+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
590+ off += 2
591+ copy(p[off:], pattern)
592+ off += len(pattern)
593+ return seq
594+}
595+
596+func ListFontsWithInfo(b *xturbo.Buf, maxNames uint16, pattern string) xturbo.Seq {
597+ if uint64(len(pattern)) > 65535 {
598+ b.Fail(xturbo.ErrBadLength)
599+ return 0
600+ }
601+ size := 0
602+ size += 2
603+ size += 2
604+ size += len(pattern) * 1
605+ size = (size + 3) &^ 3
606+ p, seq := b.Request(50, 0, size)
607+ if p == nil {
608+ return 0
609+ }
610+ off := 0
611+ binary.LittleEndian.PutUint16(p[off:], uint16(maxNames))
612+ off += 2
613+ binary.LittleEndian.PutUint16(p[off:], uint16(len(pattern)))
614+ off += 2
615+ copy(p[off:], pattern)
616+ off += len(pattern)
617+ return seq
618+}
619+
620+func SetFontPath(b *xturbo.Buf, font []Str) xturbo.Seq {
621+ if uint64(len(font)) > 65535 {
622+ b.Fail(xturbo.ErrBadLength)
623+ return 0
624+ }
625+ size := 0
626+ size += 2
627+ size += 2
628+ for i := range font {
629+ size += font[i].Size()
630+ }
631+ size = (size + 3) &^ 3
632+ p, seq := b.Request(51, 0, size)
633+ if p == nil {
634+ return 0
635+ }
636+ off := 0
637+ binary.LittleEndian.PutUint16(p[off:], uint16(len(font)))
638+ off += 2
639+ off += 2
640+ for i := range font {
641+ font[i].Put(p[off:])
642+ off += font[i].Size()
643+ }
644+ return seq
645+}
646+
434 func GetFontPath(b *xturbo.Buf) xturbo.Seq {647 func GetFontPath(b *xturbo.Buf) xturbo.Seq {
435 p, seq := b.Request(52, 0, 0)648 p, seq := b.Request(52, 0, 0)
436 if p == nil {649 if p == nil {
@@ -440,7 +653,7 @@ func GetFontPath(b *xturbo.Buf) xturbo.Seq {
440 }653 }
441 654
442 func CreatePixmap(b *xturbo.Buf, depth uint8, pid Pixmap, drawable Drawable, width uint16, height uint16) xturbo.Seq {655 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)656+ p, seq := b.Request(53, uint8(int(depth)), 12)
444 if p == nil {657 if p == nil {
445 return 0658 return 0
446 }659 }
@@ -471,6 +684,58 @@ func CopyGC(b *xturbo.Buf, srcGc Gcontext, dstGc Gcontext, valueMask Gc) xturbo.
471 return seq684 return seq
472 }685 }
473 686
687+func SetDashes(b *xturbo.Buf, gc Gcontext, dashOffset uint16, dashes []byte) xturbo.Seq {
688+ if uint64(len(dashes)) > 65535 {
689+ b.Fail(xturbo.ErrBadLength)
690+ return 0
691+ }
692+ size := 0
693+ size += 4
694+ size += 2
695+ size += 2
696+ size += len(dashes) * 1
697+ size = (size + 3) &^ 3
698+ p, seq := b.Request(58, 0, size)
699+ if p == nil {
700+ return 0
701+ }
702+ off := 0
703+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
704+ off += 4
705+ binary.LittleEndian.PutUint16(p[off:], uint16(dashOffset))
706+ off += 2
707+ binary.LittleEndian.PutUint16(p[off:], uint16(len(dashes)))
708+ off += 2
709+ copy(p[off:], dashes)
710+ off += len(dashes)
711+ return seq
712+}
713+
714+func SetClipRectangles(b *xturbo.Buf, ordering ClipOrdering, gc Gcontext, clipXOrigin int16, clipYOrigin int16, rectangles []Rectangle) xturbo.Seq {
715+ size := 0
716+ size += 4
717+ size += 2
718+ size += 2
719+ size += len(rectangles) * 8
720+ size = (size + 3) &^ 3
721+ p, seq := b.Request(59, uint8(int(ordering)), size)
722+ if p == nil {
723+ return 0
724+ }
725+ off := 0
726+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
727+ off += 4
728+ binary.LittleEndian.PutUint16(p[off:], uint16(clipXOrigin))
729+ off += 2
730+ binary.LittleEndian.PutUint16(p[off:], uint16(clipYOrigin))
731+ off += 2
732+ for i := range rectangles {
733+ rectangles[i].Put(p[off:])
734+ off += 8
735+ }
736+ return seq
737+}
738+
474 func FreeGC(b *xturbo.Buf, gc Gcontext) xturbo.Seq {739 func FreeGC(b *xturbo.Buf, gc Gcontext) xturbo.Seq {
475 p, seq := b.Request(60, 0, 4)740 p, seq := b.Request(60, 0, 4)
476 if p == nil {741 if p == nil {
@@ -532,8 +797,232 @@ func CopyPlane(b *xturbo.Buf, srcDrawable Drawable, dstDrawable Drawable, gc Gco
532 return seq797 return seq
533 }798 }
534 799
800+func PolyPoint(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
801+ size := 0
802+ size += 4
803+ size += 4
804+ size += len(points) * 4
805+ size = (size + 3) &^ 3
806+ p, seq := b.Request(64, uint8(int(coordinateMode)), size)
807+ if p == nil {
808+ return 0
809+ }
810+ off := 0
811+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
812+ off += 4
813+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
814+ off += 4
815+ for i := range points {
816+ points[i].Put(p[off:])
817+ off += 4
818+ }
819+ return seq
820+}
821+
822+func PolyLine(b *xturbo.Buf, coordinateMode CoordMode, drawable Drawable, gc Gcontext, points []Point) xturbo.Seq {
823+ size := 0
824+ size += 4
825+ size += 4
826+ size += len(points) * 4
827+ size = (size + 3) &^ 3
828+ p, seq := b.Request(65, uint8(int(coordinateMode)), size)
829+ if p == nil {
830+ return 0
831+ }
832+ off := 0
833+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
834+ off += 4
835+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
836+ off += 4
837+ for i := range points {
838+ points[i].Put(p[off:])
839+ off += 4
840+ }
841+ return seq
842+}
843+
844+func PolySegment(b *xturbo.Buf, drawable Drawable, gc Gcontext, segments []Segment) xturbo.Seq {
845+ size := 0
846+ size += 4
847+ size += 4
848+ size += len(segments) * 8
849+ size = (size + 3) &^ 3
850+ p, seq := b.Request(66, 0, size)
851+ if p == nil {
852+ return 0
853+ }
854+ off := 0
855+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
856+ off += 4
857+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
858+ off += 4
859+ for i := range segments {
860+ segments[i].Put(p[off:])
861+ off += 8
862+ }
863+ return seq
864+}
865+
866+func PolyRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
867+ size := 0
868+ size += 4
869+ size += 4
870+ size += len(rectangles) * 8
871+ size = (size + 3) &^ 3
872+ p, seq := b.Request(67, 0, size)
873+ if p == nil {
874+ return 0
875+ }
876+ off := 0
877+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
878+ off += 4
879+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
880+ off += 4
881+ for i := range rectangles {
882+ rectangles[i].Put(p[off:])
883+ off += 8
884+ }
885+ return seq
886+}
887+
888+func PolyArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
889+ size := 0
890+ size += 4
891+ size += 4
892+ size += len(arcs) * 12
893+ size = (size + 3) &^ 3
894+ p, seq := b.Request(68, 0, size)
895+ if p == nil {
896+ return 0
897+ }
898+ off := 0
899+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
900+ off += 4
901+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
902+ off += 4
903+ for i := range arcs {
904+ arcs[i].Put(p[off:])
905+ off += 12
906+ }
907+ return seq
908+}
909+
910+func FillPoly(b *xturbo.Buf, drawable Drawable, gc Gcontext, shape PolyShape, coordinateMode CoordMode, points []Point) xturbo.Seq {
911+ size := 0
912+ size += 4
913+ size += 4
914+ size += 1
915+ size += 1
916+ size += 2
917+ size += len(points) * 4
918+ size = (size + 3) &^ 3
919+ p, seq := b.Request(69, 0, size)
920+ if p == nil {
921+ return 0
922+ }
923+ off := 0
924+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
925+ off += 4
926+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
927+ off += 4
928+ p[off:][0] = byte(shape)
929+ off += 1
930+ p[off:][0] = byte(coordinateMode)
931+ off += 1
932+ off += 2
933+ for i := range points {
934+ points[i].Put(p[off:])
935+ off += 4
936+ }
937+ return seq
938+}
939+
940+func PolyFillRectangle(b *xturbo.Buf, drawable Drawable, gc Gcontext, rectangles []Rectangle) xturbo.Seq {
941+ size := 0
942+ size += 4
943+ size += 4
944+ size += len(rectangles) * 8
945+ size = (size + 3) &^ 3
946+ p, seq := b.Request(70, 0, size)
947+ if p == nil {
948+ return 0
949+ }
950+ off := 0
951+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
952+ off += 4
953+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
954+ off += 4
955+ for i := range rectangles {
956+ rectangles[i].Put(p[off:])
957+ off += 8
958+ }
959+ return seq
960+}
961+
962+func PolyFillArc(b *xturbo.Buf, drawable Drawable, gc Gcontext, arcs []Arc) xturbo.Seq {
963+ size := 0
964+ size += 4
965+ size += 4
966+ size += len(arcs) * 12
967+ size = (size + 3) &^ 3
968+ p, seq := b.Request(71, 0, size)
969+ if p == nil {
970+ return 0
971+ }
972+ off := 0
973+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
974+ off += 4
975+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
976+ off += 4
977+ for i := range arcs {
978+ arcs[i].Put(p[off:])
979+ off += 12
980+ }
981+ return seq
982+}
983+
984+func PutImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, gc Gcontext, width uint16, height uint16, dstX int16, dstY int16, leftPad uint8, depth uint8, data []byte) xturbo.Seq {
985+ size := 0
986+ size += 4
987+ size += 4
988+ size += 2
989+ size += 2
990+ size += 2
991+ size += 2
992+ size += 1
993+ size += 1
994+ size += 2
995+ size += len(data) * 1
996+ size = (size + 3) &^ 3
997+ p, seq := b.Request(72, uint8(int(format)), size)
998+ if p == nil {
999+ return 0
1000+ }
1001+ off := 0
1002+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1003+ off += 4
1004+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1005+ off += 4
1006+ binary.LittleEndian.PutUint16(p[off:], uint16(width))
1007+ off += 2
1008+ binary.LittleEndian.PutUint16(p[off:], uint16(height))
1009+ off += 2
1010+ binary.LittleEndian.PutUint16(p[off:], uint16(dstX))
1011+ off += 2
1012+ binary.LittleEndian.PutUint16(p[off:], uint16(dstY))
1013+ off += 2
1014+ p[off:][0] = byte(leftPad)
1015+ off += 1
1016+ p[off:][0] = byte(depth)
1017+ off += 1
1018+ off += 2
1019+ copy(p[off:], data)
1020+ off += len(data)
1021+ return seq
1022+}
1023+
535 func GetImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, x int16, y int16, width uint16, height uint16, planeMask uint32) xturbo.Seq {1024 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)1025+ p, seq := b.Request(73, uint8(int(format)), 16)
537 if p == nil {1026 if p == nil {
538 return 01027 return 0
539 }1028 }
@@ -546,8 +1035,122 @@ func GetImage(b *xturbo.Buf, format ImageFormat, drawable Drawable, x int16, y i
546 return seq1035 return seq
547 }1036 }
548 1037
1038+func PolyText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1039+ size := 0
1040+ size += 4
1041+ size += 4
1042+ size += 2
1043+ size += 2
1044+ size += len(items) * 1
1045+ size = (size + 3) &^ 3
1046+ p, seq := b.Request(74, 0, size)
1047+ if p == nil {
1048+ return 0
1049+ }
1050+ off := 0
1051+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1052+ off += 4
1053+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1054+ off += 4
1055+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1056+ off += 2
1057+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1058+ off += 2
1059+ copy(p[off:], items)
1060+ off += len(items)
1061+ return seq
1062+}
1063+
1064+func PolyText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, items []byte) xturbo.Seq {
1065+ size := 0
1066+ size += 4
1067+ size += 4
1068+ size += 2
1069+ size += 2
1070+ size += len(items) * 1
1071+ size = (size + 3) &^ 3
1072+ p, seq := b.Request(75, 0, size)
1073+ if p == nil {
1074+ return 0
1075+ }
1076+ off := 0
1077+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1078+ off += 4
1079+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1080+ off += 4
1081+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1082+ off += 2
1083+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1084+ off += 2
1085+ copy(p[off:], items)
1086+ off += len(items)
1087+ return seq
1088+}
1089+
1090+func ImageText8(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string string) xturbo.Seq {
1091+ if len(string) > 255 {
1092+ b.Fail(xturbo.ErrBadLength)
1093+ return 0
1094+ }
1095+ size := 0
1096+ size += 4
1097+ size += 4
1098+ size += 2
1099+ size += 2
1100+ size += len(string) * 1
1101+ size = (size + 3) &^ 3
1102+ p, seq := b.Request(76, uint8(len(string)), size)
1103+ if p == nil {
1104+ return 0
1105+ }
1106+ off := 0
1107+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1108+ off += 4
1109+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1110+ off += 4
1111+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1112+ off += 2
1113+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1114+ off += 2
1115+ copy(p[off:], string)
1116+ off += len(string)
1117+ return seq
1118+}
1119+
1120+func ImageText16(b *xturbo.Buf, drawable Drawable, gc Gcontext, x int16, y int16, string []Char2b) xturbo.Seq {
1121+ if len(string) > 255 {
1122+ b.Fail(xturbo.ErrBadLength)
1123+ return 0
1124+ }
1125+ size := 0
1126+ size += 4
1127+ size += 4
1128+ size += 2
1129+ size += 2
1130+ size += len(string) * 2
1131+ size = (size + 3) &^ 3
1132+ p, seq := b.Request(77, uint8(len(string)), size)
1133+ if p == nil {
1134+ return 0
1135+ }
1136+ off := 0
1137+ binary.LittleEndian.PutUint32(p[off:], uint32(drawable))
1138+ off += 4
1139+ binary.LittleEndian.PutUint32(p[off:], uint32(gc))
1140+ off += 4
1141+ binary.LittleEndian.PutUint16(p[off:], uint16(x))
1142+ off += 2
1143+ binary.LittleEndian.PutUint16(p[off:], uint16(y))
1144+ off += 2
1145+ for i := range string {
1146+ string[i].Put(p[off:])
1147+ off += 2
1148+ }
1149+ return seq
1150+}
1151+
549 func CreateColormap(b *xturbo.Buf, alloc ColormapAlloc, mid Colormap, window Window, visual Visualid) xturbo.Seq {1152 func CreateColormap(b *xturbo.Buf, alloc ColormapAlloc, mid Colormap, window Window, visual Visualid) xturbo.Seq {
550- p, seq := b.Request(78, uint8(alloc), 12)1153+ p, seq := b.Request(78, uint8(int(alloc)), 12)
551 if p == nil {1154 if p == nil {
552 return 01155 return 0
553 }1156 }
@@ -615,6 +1218,32 @@ func AllocColor(b *xturbo.Buf, cmap Colormap, red uint16, green uint16, blue uin
615 return seq1218 return seq
616 }1219 }
617 1220
1221+func AllocNamedColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1222+ if uint64(len(name)) > 65535 {
1223+ b.Fail(xturbo.ErrBadLength)
1224+ return 0
1225+ }
1226+ size := 0
1227+ size += 4
1228+ size += 2
1229+ size += 2
1230+ size += len(name) * 1
1231+ size = (size + 3) &^ 3
1232+ p, seq := b.Request(85, 0, size)
1233+ if p == nil {
1234+ return 0
1235+ }
1236+ off := 0
1237+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1238+ off += 4
1239+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1240+ off += 2
1241+ off += 2
1242+ copy(p[off:], name)
1243+ off += len(name)
1244+ return seq
1245+}
1246+
618 func AllocColorCells(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, planes uint16) xturbo.Seq {1247 func AllocColorCells(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint16, planes uint16) xturbo.Seq {
619 var data uint81248 var data uint8
620 if contiguous {1249 if contiguous {
@@ -647,6 +1276,121 @@ func AllocColorPlanes(b *xturbo.Buf, contiguous bool, cmap Colormap, colors uint
647 return seq1276 return seq
648 }1277 }
649 1278
1279+func FreeColors(b *xturbo.Buf, cmap Colormap, planeMask uint32, pixels []uint32) xturbo.Seq {
1280+ size := 0
1281+ size += 4
1282+ size += 4
1283+ size += len(pixels) * 4
1284+ size = (size + 3) &^ 3
1285+ p, seq := b.Request(88, 0, size)
1286+ if p == nil {
1287+ return 0
1288+ }
1289+ off := 0
1290+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1291+ off += 4
1292+ binary.LittleEndian.PutUint32(p[off:], uint32(planeMask))
1293+ off += 4
1294+ for i := range pixels {
1295+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1296+ off += 4
1297+ }
1298+ return seq
1299+}
1300+
1301+func StoreColors(b *xturbo.Buf, cmap Colormap, items []Coloritem) xturbo.Seq {
1302+ size := 0
1303+ size += 4
1304+ size += len(items) * 12
1305+ size = (size + 3) &^ 3
1306+ p, seq := b.Request(89, 0, size)
1307+ if p == nil {
1308+ return 0
1309+ }
1310+ off := 0
1311+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1312+ off += 4
1313+ for i := range items {
1314+ items[i].Put(p[off:])
1315+ off += 12
1316+ }
1317+ return seq
1318+}
1319+
1320+func StoreNamedColor(b *xturbo.Buf, flags ColorFlag, cmap Colormap, pixel uint32, name string) xturbo.Seq {
1321+ if uint64(len(name)) > 65535 {
1322+ b.Fail(xturbo.ErrBadLength)
1323+ return 0
1324+ }
1325+ size := 0
1326+ size += 4
1327+ size += 4
1328+ size += 2
1329+ size += 2
1330+ size += len(name) * 1
1331+ size = (size + 3) &^ 3
1332+ p, seq := b.Request(90, uint8(int(flags)), size)
1333+ if p == nil {
1334+ return 0
1335+ }
1336+ off := 0
1337+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1338+ off += 4
1339+ binary.LittleEndian.PutUint32(p[off:], uint32(pixel))
1340+ off += 4
1341+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1342+ off += 2
1343+ off += 2
1344+ copy(p[off:], name)
1345+ off += len(name)
1346+ return seq
1347+}
1348+
1349+func QueryColors(b *xturbo.Buf, cmap Colormap, pixels []uint32) xturbo.Seq {
1350+ size := 0
1351+ size += 4
1352+ size += len(pixels) * 4
1353+ size = (size + 3) &^ 3
1354+ p, seq := b.Request(91, 0, size)
1355+ if p == nil {
1356+ return 0
1357+ }
1358+ off := 0
1359+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1360+ off += 4
1361+ for i := range pixels {
1362+ binary.LittleEndian.PutUint32(p[off:], uint32(pixels[i]))
1363+ off += 4
1364+ }
1365+ return seq
1366+}
1367+
1368+func LookupColor(b *xturbo.Buf, cmap Colormap, name string) xturbo.Seq {
1369+ if uint64(len(name)) > 65535 {
1370+ b.Fail(xturbo.ErrBadLength)
1371+ return 0
1372+ }
1373+ size := 0
1374+ size += 4
1375+ size += 2
1376+ size += 2
1377+ size += len(name) * 1
1378+ size = (size + 3) &^ 3
1379+ p, seq := b.Request(92, 0, size)
1380+ if p == nil {
1381+ return 0
1382+ }
1383+ off := 0
1384+ binary.LittleEndian.PutUint32(p[off:], uint32(cmap))
1385+ off += 4
1386+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1387+ off += 2
1388+ off += 2
1389+ copy(p[off:], name)
1390+ off += len(name)
1391+ return seq
1392+}
1393+
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 {1394 func CreateCursor(b *xturbo.Buf, cid Cursor, source Pixmap, mask Pixmap, foreRed uint16, foreGreen uint16, foreBlue uint16, backRed uint16, backGreen uint16, backBlue uint16, x uint16, y uint16) xturbo.Seq {
651 p, seq := b.Request(93, 0, 28)1395 p, seq := b.Request(93, 0, 28)
652 if p == nil {1396 if p == nil {
@@ -710,7 +1454,7 @@ func RecolorCursor(b *xturbo.Buf, cursor Cursor, foreRed uint16, foreGreen uint1
710 }1454 }
711 1455
712 func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width uint16, height uint16) xturbo.Seq {1456 func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width uint16, height uint16) xturbo.Seq {
713- p, seq := b.Request(97, uint8(class), 8)1457+ p, seq := b.Request(97, uint8(int(class)), 8)
714 if p == nil {1458 if p == nil {
715 return 01459 return 0
716 }1460 }
@@ -720,6 +1464,29 @@ func QueryBestSize(b *xturbo.Buf, class QueryShapeOf, drawable Drawable, width u
720 return seq1464 return seq
721 }1465 }
722 1466
1467+func QueryExtension(b *xturbo.Buf, name string) xturbo.Seq {
1468+ if uint64(len(name)) > 65535 {
1469+ b.Fail(xturbo.ErrBadLength)
1470+ return 0
1471+ }
1472+ size := 0
1473+ size += 2
1474+ size += 2
1475+ size += len(name) * 1
1476+ size = (size + 3) &^ 3
1477+ p, seq := b.Request(98, 0, size)
1478+ if p == nil {
1479+ return 0
1480+ }
1481+ off := 0
1482+ binary.LittleEndian.PutUint16(p[off:], uint16(len(name)))
1483+ off += 2
1484+ off += 2
1485+ copy(p[off:], name)
1486+ off += len(name)
1487+ return seq
1488+}
1489+
723 func ListExtensions(b *xturbo.Buf) xturbo.Seq {1490 func ListExtensions(b *xturbo.Buf) xturbo.Seq {
724 p, seq := b.Request(99, 0, 0)1491 p, seq := b.Request(99, 0, 0)
725 if p == nil {1492 if p == nil {
@@ -728,6 +1495,34 @@ func ListExtensions(b *xturbo.Buf) xturbo.Seq {
728 return seq1495 return seq
729 }1496 }
730 1497
1498+func ChangeKeyboardMapping(b *xturbo.Buf, keycodeCount uint8, firstKeycode Keycode, keysymsPerKeycode uint8, keysyms []Keysym) xturbo.Seq {
1499+ if len(keysyms) != (int(keycodeCount) * int(keysymsPerKeycode)) {
1500+ b.Fail(xturbo.ErrBadLength)
1501+ return 0
1502+ }
1503+ size := 0
1504+ size += 1
1505+ size += 1
1506+ size += 2
1507+ size += len(keysyms) * 4
1508+ size = (size + 3) &^ 3
1509+ p, seq := b.Request(100, uint8(int(keycodeCount)), size)
1510+ if p == nil {
1511+ return 0
1512+ }
1513+ off := 0
1514+ p[off:][0] = byte(firstKeycode)
1515+ off += 1
1516+ p[off:][0] = byte(keysymsPerKeycode)
1517+ off += 1
1518+ off += 2
1519+ for i := range keysyms {
1520+ binary.LittleEndian.PutUint32(p[off:], uint32(keysyms[i]))
1521+ off += 4
1522+ }
1523+ return seq
1524+}
1525+
731 func GetKeyboardMapping(b *xturbo.Buf, firstKeycode Keycode, count uint8) xturbo.Seq {1526 func GetKeyboardMapping(b *xturbo.Buf, firstKeycode Keycode, count uint8) xturbo.Seq {
732 p, seq := b.Request(101, 0, 4)1527 p, seq := b.Request(101, 0, 4)
733 if p == nil {1528 if p == nil {
@@ -747,7 +1542,7 @@ func GetKeyboardControl(b *xturbo.Buf) xturbo.Seq {
747 }1542 }
748 1543
749 func Bell(b *xturbo.Buf, percent int8) xturbo.Seq {1544 func Bell(b *xturbo.Buf, percent int8) xturbo.Seq {
750- p, seq := b.Request(104, uint8(percent), 0)1545+ p, seq := b.Request(104, uint8(int(percent)), 0)
751 if p == nil {1546 if p == nil {
752 return 01547 return 0
753 }1548 }
@@ -803,6 +1598,32 @@ func GetScreenSaver(b *xturbo.Buf) xturbo.Seq {
803 return seq1598 return seq
804 }1599 }
805 1600
1601+func ChangeHosts(b *xturbo.Buf, mode HostMode, family Family, address []byte) xturbo.Seq {
1602+ if uint64(len(address)) > 65535 {
1603+ b.Fail(xturbo.ErrBadLength)
1604+ return 0
1605+ }
1606+ size := 0
1607+ size += 1
1608+ size += 1
1609+ size += 2
1610+ size += len(address) * 1
1611+ size = (size + 3) &^ 3
1612+ p, seq := b.Request(109, uint8(int(mode)), size)
1613+ if p == nil {
1614+ return 0
1615+ }
1616+ off := 0
1617+ p[off:][0] = byte(family)
1618+ off += 1
1619+ off += 1
1620+ binary.LittleEndian.PutUint16(p[off:], uint16(len(address)))
1621+ off += 2
1622+ copy(p[off:], address)
1623+ off += len(address)
1624+ return seq
1625+}
1626+
806 func ListHosts(b *xturbo.Buf) xturbo.Seq {1627 func ListHosts(b *xturbo.Buf) xturbo.Seq {
807 p, seq := b.Request(110, 0, 0)1628 p, seq := b.Request(110, 0, 0)
808 if p == nil {1629 if p == nil {
@@ -812,7 +1633,7 @@ func ListHosts(b *xturbo.Buf) xturbo.Seq {
812 }1633 }
813 1634
814 func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {1635 func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
815- p, seq := b.Request(111, uint8(mode), 0)1636+ p, seq := b.Request(111, uint8(int(mode)), 0)
816 if p == nil {1637 if p == nil {
817 return 01638 return 0
818 }1639 }
@@ -820,7 +1641,7 @@ func SetAccessControl(b *xturbo.Buf, mode AccessControl) xturbo.Seq {
820 }1641 }
821 1642
822 func SetCloseDownMode(b *xturbo.Buf, mode CloseDown) xturbo.Seq {1643 func SetCloseDownMode(b *xturbo.Buf, mode CloseDown) xturbo.Seq {
823- p, seq := b.Request(112, uint8(mode), 0)1644+ p, seq := b.Request(112, uint8(int(mode)), 0)
824 if p == nil {1645 if p == nil {
825 return 01646 return 0
826 }1647 }
@@ -836,14 +1657,61 @@ func KillClient(b *xturbo.Buf, resource uint32) xturbo.Seq {
836 return seq1657 return seq
837 }1658 }
838 1659
1660+func RotateProperties(b *xturbo.Buf, window Window, delta int16, atoms []Atom) xturbo.Seq {
1661+ if uint64(len(atoms)) > 65535 {
1662+ b.Fail(xturbo.ErrBadLength)
1663+ return 0
1664+ }
1665+ size := 0
1666+ size += 4
1667+ size += 2
1668+ size += 2
1669+ size += len(atoms) * 4
1670+ size = (size + 3) &^ 3
1671+ p, seq := b.Request(114, 0, size)
1672+ if p == nil {
1673+ return 0
1674+ }
1675+ off := 0
1676+ binary.LittleEndian.PutUint32(p[off:], uint32(window))
1677+ off += 4
1678+ binary.LittleEndian.PutUint16(p[off:], uint16(len(atoms)))
1679+ off += 2
1680+ binary.LittleEndian.PutUint16(p[off:], uint16(delta))
1681+ off += 2
1682+ for i := range atoms {
1683+ binary.LittleEndian.PutUint32(p[off:], uint32(atoms[i]))
1684+ off += 4
1685+ }
1686+ return seq
1687+}
1688+
839 func ForceScreenSaver(b *xturbo.Buf, mode ScreenSaver) xturbo.Seq {1689 func ForceScreenSaver(b *xturbo.Buf, mode ScreenSaver) xturbo.Seq {
840- p, seq := b.Request(115, uint8(mode), 0)1690+ p, seq := b.Request(115, uint8(int(mode)), 0)
841 if p == nil {1691 if p == nil {
842 return 01692 return 0
843 }1693 }
844 return seq1694 return seq
845 }1695 }
846 1696
1697+func SetPointerMapping(b *xturbo.Buf, map_ []byte) xturbo.Seq {
1698+ if len(map_) > 255 {
1699+ b.Fail(xturbo.ErrBadLength)
1700+ return 0
1701+ }
1702+ size := 0
1703+ size += len(map_) * 1
1704+ size = (size + 3) &^ 3
1705+ p, seq := b.Request(116, uint8(len(map_)), size)
1706+ if p == nil {
1707+ return 0
1708+ }
1709+ off := 0
1710+ copy(p[off:], map_)
1711+ off += len(map_)
1712+ return seq
1713+}
1714+
847 func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {1715 func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
848 p, seq := b.Request(117, 0, 0)1716 p, seq := b.Request(117, 0, 0)
849 if p == nil {1717 if p == nil {
@@ -852,6 +1720,26 @@ func GetPointerMapping(b *xturbo.Buf) xturbo.Seq {
852 return seq1720 return seq
853 }1721 }
854 1722
1723+func SetModifierMapping(b *xturbo.Buf, keycodesPerModifier uint8, keycodes []Keycode) xturbo.Seq {
1724+ if len(keycodes) != (int(keycodesPerModifier) * 8) {
1725+ b.Fail(xturbo.ErrBadLength)
1726+ return 0
1727+ }
1728+ size := 0
1729+ size += len(keycodes) * 1
1730+ size = (size + 3) &^ 3
1731+ p, seq := b.Request(118, uint8(int(keycodesPerModifier)), size)
1732+ if p == nil {
1733+ return 0
1734+ }
1735+ off := 0
1736+ for i := range keycodes {
1737+ p[off:][0] = byte(keycodes[i])
1738+ off += 1
1739+ }
1740+ return seq
1741+}
1742+
855 func GetModifierMapping(b *xturbo.Buf) xturbo.Seq {1743 func GetModifierMapping(b *xturbo.Buf) xturbo.Seq {
856 p, seq := b.Request(119, 0, 0)1744 p, seq := b.Request(119, 0, 0)
857 if p == nil {1745 if p == nil {
M xproto/requests_test.go +36 -0
@@ -22,3 +22,39 @@ func BenchmarkMapWindow(b *testing.B) {
2222 batch++
2323 }
2424 }
25+
26+func BenchmarkInternAtom(b *testing.B) {
27+ buf := xturbo.NewBuf(0)
28+ batch := 0
29+ b.ReportAllocs()
30+ b.ResetTimer()
31+ for i := 0; i < b.N; i++ {
32+ if batch == 60000 {
33+ b.StopTimer()
34+ buf = xturbo.NewBuf(0)
35+ batch = 0
36+ b.StartTimer()
37+ }
38+ buf.Reset()
39+ InternAtom(buf, false, "WM_CLASS")
40+ batch++
41+ }
42+}
43+func BenchmarkChangeProperty4KiB(b *testing.B) {
44+ buf := xturbo.NewBuf(0)
45+ data := make([]byte, 4096)
46+ batch := 0
47+ b.ReportAllocs()
48+ b.ResetTimer()
49+ for i := 0; i < b.N; i++ {
50+ if batch == 60000 {
51+ b.StopTimer()
52+ buf = xturbo.NewBuf(0)
53+ batch = 0
54+ b.StartTimer()
55+ }
56+ buf.Reset()
57+ ChangeProperty(buf, 0, 1, 1, 1, 8, 4096, data)
58+ batch++
59+ }
60+}
@@ -22,3 +22,39 @@ func BenchmarkMapWindow(b *testing.B) {
22 batch++22 batch++
23 }23 }
24 }24 }
25+
26+func BenchmarkInternAtom(b *testing.B) {
27+ buf := xturbo.NewBuf(0)
28+ batch := 0
29+ b.ReportAllocs()
30+ b.ResetTimer()
31+ for i := 0; i < b.N; i++ {
32+ if batch == 60000 {
33+ b.StopTimer()
34+ buf = xturbo.NewBuf(0)
35+ batch = 0
36+ b.StartTimer()
37+ }
38+ buf.Reset()
39+ InternAtom(buf, false, "WM_CLASS")
40+ batch++
41+ }
42+}
43+func BenchmarkChangeProperty4KiB(b *testing.B) {
44+ buf := xturbo.NewBuf(0)
45+ data := make([]byte, 4096)
46+ batch := 0
47+ b.ReportAllocs()
48+ b.ResetTimer()
49+ for i := 0; i < b.N; i++ {
50+ if batch == 60000 {
51+ b.StopTimer()
52+ buf = xturbo.NewBuf(0)
53+ batch = 0
54+ b.StartTimer()
55+ }
56+ buf.Reset()
57+ ChangeProperty(buf, 0, 1, 1, 1, 8, 4096, data)
58+ batch++
59+ }
60+}

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