pure-x11 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/X11/form.rb ADDED
@@ -0,0 +1,865 @@
1
+ require 'ostruct'
2
+
3
+ module X11
4
+ module Form
5
+ # A form object is an X11 packet definition. We use forms to encode
6
+ # and decode X11 packets as we send and receive them over a socket.
7
+ #
8
+ # We can create a packet definition as follows:
9
+ #
10
+ # class Point < BaseForm
11
+ # field :x, Int8
12
+ # field :y, Int8
13
+ # end
14
+ #
15
+ # p = Point.new(10,20)
16
+ # p.x => 10
17
+ # p.y => 20
18
+ # p.to_packet => "\n\x14"
19
+ #
20
+ # You can also read from a socket:
21
+ #
22
+ # Point.from_packet(socket) => #<Point @x=10 @y=20>
23
+ #
24
+ class Form
25
+ def self.structs
26
+ []
27
+ end
28
+
29
+ def self.fields
30
+ []
31
+ end
32
+ end
33
+
34
+ class BaseForm < Form
35
+ include X11::Type
36
+
37
+ # initialize field accessors
38
+ def initialize(*params)
39
+ self.class.fields.each do |f|
40
+ if !f.value
41
+ param = params.shift
42
+ #p [f,param]
43
+ instance_variable_set("@#{f.name}", param)
44
+ end
45
+ end
46
+ end
47
+
48
+ def to_packet
49
+ # fetch class level instance variable holding defined fields
50
+ structs = self.class.structs
51
+
52
+ packet = structs.map do |s|
53
+ # fetch value of field set in initialization
54
+
55
+ value = s.type == :unused ? nil : instance_variable_get("@#{s.name}")
56
+ case s.type
57
+ when :field
58
+ if s.value
59
+ if s.value.respond_to?(:call)
60
+ value = s.value.call(self)
61
+ else
62
+ value = s.value
63
+ end
64
+ end
65
+ #p [s,value]
66
+
67
+ if value.is_a?(BaseForm)
68
+ v = value.to_packet
69
+ elsif value.is_a?(Symbol)
70
+ #if !@atoms[value]
71
+ # reply = write_sync(X11::Forms::InternAtom.new(false, value.to_s), X11::Forms::InternAtomReply)
72
+ # @
73
+ #end
74
+ #value = @atoms[value]
75
+ raise "FIXME"
76
+ else
77
+ #p [s,value]
78
+ v = s.type_klass.pack(value)
79
+ end
80
+ #p v
81
+ v
82
+ when :unused
83
+ sz = s.size.respond_to?(:call) ? s.size.call(self) : s.size
84
+ "\x00" * sz
85
+ when :length
86
+ #p [s,value]
87
+ #p [value.size]
88
+ s.type_klass.pack(value.size)
89
+ when :string
90
+ s.type_klass.pack(value)
91
+ when :list
92
+ value.collect do |obj|
93
+ if obj.is_a?(BaseForm)
94
+ obj.to_packet
95
+ else
96
+ s.type_klass.pack(obj)
97
+ end
98
+ end
99
+ end
100
+ end.join
101
+ end
102
+
103
+ class << self
104
+ def structs
105
+ superclass.structs + Array(@structs) #instance_variable_get("@structs"))
106
+ end
107
+
108
+ # FIXME: Doing small reads from socket is a bad idea, and
109
+ # the protocol provides length fields that makes it unnecessary.
110
+ def from_packet(socket)
111
+ # fetch class level instance variable holding defined fields
112
+
113
+ form = new
114
+ lengths = {}
115
+
116
+ structs.each do |s|
117
+ case s.type
118
+ when :field
119
+ val = if s.type_klass.superclass == BaseForm
120
+ s.type_klass.from_packet(socket)
121
+ else
122
+ s.type_klass.unpack( socket.read(s.type_klass.size) )
123
+ end
124
+ form.instance_variable_set("@#{s.name}", val)
125
+ when :unused
126
+ sz = s.size.respond_to?(:call) ? s.size.call(self) : s.size
127
+ socket.read(sz)
128
+ when :length
129
+ size = s.type_klass.unpack( socket.read(s.type_klass.size) )
130
+ lengths[s.name] = size
131
+ when :string
132
+ val = s.type_klass.unpack(socket, lengths[s.name])
133
+ form.instance_variable_set("@#{s.name}", val)
134
+ when :list
135
+ len = lengths[s.name]
136
+ if len
137
+ val = len.times.collect do
138
+ s.type_klass.from_packet(socket)
139
+ end
140
+ else
141
+ val = []
142
+ while ob = s.type_klass.from_packet(socket)
143
+ val << ob
144
+ end
145
+ end
146
+ form.instance_variable_set("@#{s.name}", val)
147
+ end
148
+ end
149
+
150
+ return form
151
+ end
152
+
153
+ Field = Struct.new(:name, :type, :type_klass, :value, :size, keyword_init: true)
154
+
155
+ def field(name, type_klass, type = nil, value: nil)
156
+ # name, type_klass, type = args
157
+ class_eval do
158
+ if value && value.respond_to?(:call)
159
+ define_method(name.to_sym) { value.call(self) }
160
+ else
161
+ attr_accessor name
162
+ end
163
+ end
164
+
165
+ s = Field.new
166
+ s.name = name
167
+ s.type = (type == nil ? :field : type)
168
+ s.type_klass = type_klass
169
+ s.value = value
170
+
171
+ @structs ||= []
172
+ @structs << s
173
+ end
174
+
175
+ def unused(size)
176
+ @structs ||= []
177
+ @structs << Field.new(size: size, type: :unused)
178
+ end
179
+
180
+ def fields
181
+ super+Array(@structs).dup.delete_if{|s| s.type == :unused or s.type == :length }
182
+ end
183
+ end
184
+ end
185
+
186
+ CardinalAtom=6
187
+
188
+ ##
189
+ ## X11 Packet Defintions
190
+ ##
191
+
192
+ class ClientHandshake < BaseForm
193
+ field :byte_order, Uint8
194
+ unused 1
195
+ field :protocol_major_version, Uint16
196
+ field :protocol_minor_version, Uint16
197
+ field :auth_proto_name, Uint16, :length
198
+ field :auth_proto_data, Uint16, :length
199
+ unused 2
200
+ field :auth_proto_name, String8, :string
201
+ field :auth_proto_data, String8, :string
202
+ end
203
+
204
+ class FormatInfo < BaseForm
205
+ field :depth, Uint8
206
+ field :bits_per_pixel, Uint8
207
+ field :scanline_pad, Uint8
208
+ unused 5
209
+ end
210
+
211
+ class VisualInfo < BaseForm
212
+ field :visual_id, VisualID
213
+ field :qlass, Uint8
214
+ field :bits_per_rgb_value, Uint8
215
+ field :colormap_entries, Uint16
216
+ field :red_mask, Uint32
217
+ field :green_mask, Uint32
218
+ field :blue_mask, Uint32
219
+ unused 4
220
+ end
221
+
222
+ class DepthInfo < BaseForm
223
+ field :depth, Uint8
224
+ unused 1
225
+ field :visuals, Uint16, :length
226
+ unused 4
227
+ field :visuals, VisualInfo, :list
228
+ end
229
+
230
+ class ScreenInfo < BaseForm
231
+ field :root, Window
232
+ field :default_colormap, Colormap
233
+ field :white_pixel, Colornum
234
+ field :black_pixel, Colornum
235
+ field :current_input_masks, Mask
236
+ field :width_in_pixels, Uint16
237
+ field :height_in_pixels, Uint16
238
+ field :width_in_millimeters, Uint16
239
+ field :height_in_millimeters, Uint16
240
+ field :min_installed_maps, Uint16
241
+ field :max_installed_maps, Uint16
242
+ field :root_visual, VisualID
243
+ field :backing_stores, Uint8
244
+ field :save_unders, Bool
245
+ field :root_depth, Uint8
246
+ field :depths, Uint8,:length
247
+ field :depths, DepthInfo, :list
248
+ end
249
+
250
+ class DisplayInfo < BaseForm
251
+ field :release_number, Uint32
252
+ field :resource_id_base, Uint32
253
+ field :resource_id_mask, Uint32
254
+ field :motion_buffer_size, Uint32
255
+ field :vendor, Uint16, :length
256
+ field :maximum_request_length, Uint16
257
+ field :screens, Uint8, :length
258
+ field :formats, Uint8, :length
259
+ field :image_byte_order, Signifigance
260
+ field :bitmap_bit_order, Signifigance
261
+ field :bitmap_format_scanline_unit, Uint8
262
+ field :bitmap_format_scanline_pad, Uint8
263
+ field :min_keycode, KeyCode
264
+ field :max_keycode, KeyCode
265
+ unused 4
266
+ field :vendor, String8, :string
267
+ field :formats, FormatInfo, :list
268
+ field :screens, ScreenInfo, :list
269
+ end
270
+
271
+ class Rectangle < BaseForm
272
+ field :x, Int16
273
+ field :y, Int16
274
+ field :width, Uint16
275
+ field :height, Uint16
276
+ end
277
+
278
+ class Error < BaseForm
279
+ field :error, Uint8
280
+ field :code, Uint8
281
+ field :sequence_number, Uint16
282
+ field :bad_resource_id, Uint32
283
+ field :minor_opcode, Uint16
284
+ field :major_opcode, Uint8
285
+ unused 21
286
+ end
287
+
288
+ # XRender structures
289
+
290
+ class DirectFormat < BaseForm
291
+ field :red, Uint16
292
+ field :red_mask, Uint16
293
+ field :green, Uint16
294
+ field :green_mask, Uint16
295
+ field :blue, Uint16
296
+ field :blue_mask, Uint16
297
+ field :alpha, Uint16
298
+ field :alpha_mask, Uint16
299
+ end
300
+
301
+ class PictVisual < BaseForm
302
+ field :visual, Uint32
303
+ field :format, Uint32
304
+ end
305
+
306
+ class PictDepth < BaseForm
307
+ field :depth, Uint8
308
+ unused 1
309
+ field :visuals, Uint16, :length
310
+ unused 4
311
+ field :visuals, PictVisual, :list
312
+ end
313
+
314
+ class PictScreen < BaseForm
315
+ field :depths, Uint32, :length
316
+ field :fallback, Uint32
317
+ field :depths, PictDepth, :list
318
+ end
319
+
320
+ class PictFormInfo < BaseForm
321
+ field :id, Uint32
322
+ field :type, Uint8
323
+ field :depth, Uint8
324
+ unused 2
325
+ field :direct, DirectFormat
326
+ field :colormap, Colormap
327
+ end
328
+
329
+ # Requests
330
+
331
+ CopyFromParent = 0
332
+ InputOutput = 1
333
+ InputOnly = 2
334
+
335
+ CWBackPixel = 0x0002
336
+ CWBorderPixel = 0x0008
337
+ CWEventMask = 0x0800
338
+ CWColorMap = 0x2000
339
+
340
+ KeyPressMask = 0x00001
341
+ ButtonPressMask = 0x00004
342
+ PointerMotionMask = 0x00040
343
+ ExposureMask = 0x08000
344
+ StructureNotifyMask = 0x20000
345
+ SubstructureNotifyMask = 0x80000
346
+
347
+ class CreateWindow < BaseForm
348
+ field :opcode, Uint8, value: 1
349
+ field :depth, Uint8
350
+ field :request_length, Uint16, value: ->(cw) { len = 8 + cw.value_list.length }
351
+ field :wid, Window
352
+ field :parent, Window
353
+ field :x, Int16
354
+ field :y, Int16
355
+ field :width, Uint16
356
+ field :height, Uint16
357
+ field :border_width, Uint16
358
+ field :window_class, Uint16
359
+ field :visual, VisualID
360
+ field :value_mask, Bitmask
361
+ field :value_list, Uint32, :list
362
+ end
363
+
364
+ class MapWindow < BaseForm
365
+ field :opcode, Uint8, value: 8
366
+ unused 1
367
+ field :request_length, Uint16, value: 2
368
+ field :window, Window
369
+ end
370
+
371
+ class InternAtom < BaseForm
372
+ field :opcode, Uint8, value: 16
373
+ field :only_if_exists, Bool
374
+ field :request_length, Uint16, value: ->(ia) {
375
+ 2+(ia.name.length+3)/4
376
+ }
377
+ field :name, Uint16, value: ->(ia) {
378
+ ia.name.length
379
+ }
380
+ unused 2
381
+ field :name, String8, :string
382
+ end
383
+
384
+ class Reply < BaseForm
385
+ field :reply, Uint8
386
+ end
387
+
388
+ class InternAtomReply < Reply
389
+ unused 1
390
+ field :sequence_number, Uint16
391
+ field :reply_length, Uint32
392
+ field :atom, Atom
393
+ unused 20
394
+ end
395
+
396
+ Replace = 0
397
+ Prepend = 1
398
+ Append = 2
399
+
400
+ class ChangeProperty < BaseForm
401
+ field :opcode, Uint8, value: 18
402
+ field :mode, Uint8
403
+ field :request_length, Uint16, value: ->(cp) {
404
+ #p [:data, cp.data, :len, cp.data.length, :total, 6+(cp.data.length+3)/4]
405
+ 6+(cp.data.length+3)/4
406
+ }
407
+ field :window, Window
408
+ field :property, Atom
409
+ field :type, Atom
410
+ field :format, Uint8
411
+ unused 3
412
+ field :data, Uint32, value: ->(cp) {
413
+ cp.data.length / 4
414
+ }
415
+ field :data, Uint8, :list
416
+ end
417
+
418
+ class OpenFont < BaseForm
419
+ field :opcode, Uint8, value: 45
420
+ unused 1
421
+ field :request_length, Uint16, value: ->(of) {
422
+ 3+(of.name.length+3)/4
423
+ }
424
+ field :fid, Font
425
+ field :name, Uint16, :length
426
+ unused 2
427
+ field :name, String8, :string
428
+ end
429
+
430
+ class ListFonts < BaseForm
431
+ field :opcode, Uint8, value: 49
432
+ unused 1
433
+ field :request_length, Uint16, value: ->(lf) {
434
+ 2+(lf.pattern.length+4)/4
435
+ }
436
+ field :max_names, Uint16
437
+ field :length_of_pattern, Uint16,value: ->(lf) {
438
+ lf.pattern.length
439
+ }
440
+ field :pattern, String8
441
+ end
442
+
443
+ class CreatePixmap < BaseForm
444
+ field :opcode, Uint8, value: 53
445
+ field :depth, Uint8
446
+ field :request_length, Uint16, value: 4
447
+ field :pid, Pixmap
448
+ field :drawable, Uint32
449
+ field :width, Uint16
450
+ field :height, Uint16
451
+ end
452
+
453
+ class Str < BaseForm
454
+ field :name, Uint8, :length, value: ->(str) { str.name.length }
455
+ field :name, String8Unpadded, :string
456
+
457
+ def to_s
458
+ name
459
+ end
460
+ end
461
+
462
+ class ListFontsReply < BaseForm
463
+ field :reply, Uint8, value: 1
464
+ unused 1
465
+ field :sequence_number, Uint16
466
+ field :reply_length, Uint32
467
+ field :names, Uint16, :length
468
+ unused 22
469
+ field :names, Str, :list
470
+ end
471
+
472
+ FunctionMask = 0x1
473
+ PlaneMask = 0x2
474
+ ForegroundMask = 0x04
475
+ BackgroundMask = 0x08
476
+ FontMask = 0x4000
477
+
478
+ class CreateGC < BaseForm
479
+ field :opcode, Uint8, value: 55
480
+ unused 1
481
+ field :request_length, Uint16, value: ->(cw) {
482
+ len = 4 + cw.value_list.length
483
+ }
484
+ field :cid, Gcontext
485
+ field :drawable, Drawable
486
+ field :value_mask, Bitmask
487
+ field :value_list, Uint32, :list
488
+ end
489
+
490
+ class ChangeGC < BaseForm
491
+ field :opcode, Uint8, value: 56
492
+ unused 1
493
+ field :request_length, Uint16, value: ->(ch) {
494
+ 3+ ch.value_list.length
495
+ }
496
+ field :gc, Gcontext
497
+ field :value_mask, Bitmask
498
+ field :value_list, Uint32, :list
499
+ end
500
+
501
+ class ClearArea < BaseForm
502
+ field :opcode, Uint8, value: 61
503
+ field :exposures, Bool
504
+ field :request_length, Uint16, value: 4
505
+ field :window, Window
506
+ field :x, Int16
507
+ field :y, Int16
508
+ field :width, Uint16
509
+ field :height, Uint16
510
+ end
511
+
512
+ class CopyArea < BaseForm
513
+ field :opcode, Uint8, value: 62
514
+ unused 1
515
+ field :request_length, Uint16, value: 7
516
+ field :src_drawable, Drawable
517
+ field :dst_drawable, Drawable
518
+ field :gc, Gcontext
519
+ field :src_x, Uint16
520
+ field :src_y, Uint16
521
+ field :dst_x, Uint16
522
+ field :dst_y, Uint16
523
+ field :width, Uint16
524
+ field :height, Uint16
525
+ end
526
+
527
+ class PolyFillRectangle < BaseForm
528
+ field :opcode, Uint8, value: 70
529
+ unused 1
530
+ field :request_length, Uint16, value: ->(ob) {
531
+ len = 3 + 2*(Array(ob.rectangles).length)
532
+ }
533
+ field :drawable, Drawable
534
+ field :gc, Uint32
535
+ field :rectangles, Rectangle, :list
536
+ end
537
+
538
+ Bitmap = 0
539
+ XYPixmap=1
540
+ ZPixmap=2
541
+
542
+ class PutImage < BaseForm
543
+ field :opcode, Uint8, value: 72
544
+ field :format, Uint8
545
+ field :request_length, Uint16, value: ->(pi) {
546
+ 6+(pi.data.length+3)/4
547
+ }
548
+ field :drawable, Drawable
549
+ field :gc, Gcontext
550
+ field :width, Uint16
551
+ field :height, Uint16
552
+ field :dstx, Int16
553
+ field :dsty, Int16
554
+ field :left_pad, Uint8
555
+ field :depth, Uint8
556
+ unused 2
557
+ field :data, String8 #, :string
558
+ end
559
+
560
+ class ImageText8 < BaseForm
561
+ field :opcode, Uint8, value: 76
562
+ field :n, Uint8, :length
563
+ field :request_length, Uint16, value: ->(it) { 4+(it.n.length+3)/4 }
564
+ field :drawable, Drawable
565
+ field :gc, Gcontext
566
+ field :x, Int16
567
+ field :y, Int16
568
+ field :n, String8, :string
569
+ end
570
+
571
+ class ImageText16 < BaseForm
572
+ field :opcode, Uint8, value: 77
573
+ field :n, Uint8, :length
574
+ field :request_length, Uint16, value: ->(it) { 4+(it.n.length*2+3)/4 }
575
+ field :drawable, Drawable
576
+ field :gc, Gcontext
577
+ field :x, Int16
578
+ field :y, Int16
579
+ field :n, String16, :string
580
+ end
581
+
582
+ class CreateColormap < BaseForm
583
+ field :opcode, Uint8, value: 78
584
+ field :alloc, Uint8
585
+ field :request_length, Uint16, value: 4
586
+ field :mid, Colormap
587
+ field :window, Window
588
+ field :visual, Uint32
589
+ end
590
+
591
+ class QueryExtension < BaseForm
592
+ field :opcode, Uint8, value: 98
593
+ unused 1
594
+ field :request_length, Uint16, value: ->(qe) { 2+(qe.name.length+3)/4 }
595
+ field :name, Uint16, :length
596
+ unused 2
597
+ field :name, String8
598
+ end
599
+
600
+ class QueryExtensionReply < Reply
601
+ unused 1
602
+ field :sequence_number, Uint16
603
+ field :reply_length, Uint32
604
+ field :present, Bool
605
+ field :major_opcode, Uint8
606
+ field :first_event, Uint8
607
+ field :first_error, Uint8
608
+ unused 20
609
+ end
610
+
611
+ class GetKeyboardMapping < BaseForm
612
+ field :opcode, Uint8, value: 101
613
+ unused 1
614
+ field :request_length, Uint16, value: 2
615
+ field :first_keycode, Uint8
616
+ field :count, Uint8
617
+ unused 2
618
+ end
619
+
620
+ class GetKeyboardMappingReply < Reply
621
+ field :keysyms_per_keycode, Uint8
622
+ field :sequence_number, Uint16
623
+ field :reply_length, Uint32
624
+ unused 24
625
+ field :keysyms, Keysym, :list
626
+ end
627
+
628
+ # Events (page ~157)
629
+ # FIXME: Events have quite a bit of redundancy, but unfortunately
630
+ # BaseForm can't handle subclassing well.
631
+
632
+ Shift = 0x001
633
+ Lock = 0x002
634
+ Control = 0x004
635
+ Mod1 = 0x008
636
+ Mod2 = 0x010
637
+ Mod3 = 0x0020
638
+ Mod4 = 0x0040
639
+ Mod5 = 0x0080
640
+ Button1 = 0x100
641
+ Button2 = 0x200
642
+ Button3 = 0x400
643
+ Button4 = 0x800
644
+ Button5 = 0x1000
645
+
646
+ class Event < BaseForm
647
+ field :code, Uint8
648
+ end
649
+
650
+ class SimpleEvent < Event
651
+ field :detail, Uint8
652
+ field :sequence_number, Uint16
653
+ end
654
+
655
+ class PressEvent < SimpleEvent
656
+ field :time, Uint32
657
+ field :root, Window
658
+ field :event, Window
659
+ field :child, Window
660
+ field :root_x, Int16
661
+ field :root_y, Int16
662
+ field :event_x, Int16
663
+ field :event_y, Int16
664
+ field :state, Uint16
665
+ field :same_screen, Bool
666
+ unused 1
667
+ end
668
+
669
+ class ButtonPress < PressEvent
670
+ end
671
+
672
+ class KeyPress < PressEvent
673
+ end
674
+
675
+ class KeyRelease < PressEvent
676
+ end
677
+
678
+ class MotionNotify < PressEvent
679
+ end
680
+
681
+ class Expose < SimpleEvent
682
+ field :window, Window
683
+ field :x, Uint16
684
+ field :y, Uint16
685
+ field :width, Uint16
686
+ field :height, Uint16
687
+ field :count, Uint16
688
+ unused 14
689
+ end
690
+
691
+ class NoExposure < SimpleEvent # 14
692
+ field :drawable, Drawable
693
+ field :minor_opcode, Uint16
694
+ field :major_opcode, Uint8
695
+ unused 21
696
+ end
697
+
698
+ class MapNotify < Event
699
+ unused 1
700
+ field :sequence_number, Uint16
701
+ field :event, Window
702
+ field :override_redirect, Bool
703
+ unused 19
704
+ end
705
+
706
+ class ConfigureNotify < Event
707
+ unused 1
708
+ field :sequence_number, Uint16
709
+ field :event, Window
710
+ field :above_sibling, Window
711
+ field :x, Int16
712
+ field :y, Int16
713
+ field :width, Uint16
714
+ field :height, Uint16
715
+ field :border_width, Uint16
716
+ field :override_redirect, Bool
717
+ unused 5
718
+ end
719
+
720
+
721
+ # XRender extension
722
+ # From https://cgit.freedesktop.org/xorg/proto/renderproto/tree/renderproto.h
723
+ class XRenderQueryVersion < BaseForm
724
+ field :req_type, Uint8
725
+ field :render_req_type, Uint8, value: 0
726
+ field :request_length, Uint16, value: 3
727
+ field :major_version, Uint32
728
+ field :minor_version, Uint32
729
+ end
730
+
731
+ class XRenderQueryVersionReply < Reply
732
+ unused 1
733
+ field :sequence_number, Uint16
734
+ field :request_length, Uint32
735
+ field :major_version, Uint32
736
+ field :minor_version, Uint32
737
+ #unused 16
738
+ end
739
+
740
+ class XRenderQueryPictFormats < BaseForm
741
+ field :req_type, Uint8
742
+ field :render_req_type, Uint8, value: 1
743
+ field :request_length, Uint16, value: 1
744
+ end
745
+
746
+ class XRenderQueryPictFormatsReply < Reply
747
+ unused 1
748
+ field :sequence_number, Uint16
749
+ field :length, Uint32
750
+ field :formats, Uint32, :length
751
+ field :screens, Uint32, :length
752
+ field :depths, Uint32, :length
753
+ field :visuals, Uint32, :length
754
+ field :subpixel, Uint32, :length
755
+ unused 4
756
+ field :formats, PictFormInfo, :list
757
+ field :screens, PictScreen, :list
758
+ field :subpixels, Uint32, :list
759
+ end
760
+
761
+ class XRenderCreatePicture < BaseForm
762
+ field :req_type, Uint8
763
+ field :render_req_type, Uint8, value: 4
764
+ field :request_length, Uint16, value: ->(cp) {
765
+ 5 + Array(cp.value_list).length
766
+ }
767
+ field :pid, Uint32
768
+ field :drawable, Uint32
769
+ field :format, Uint32
770
+ field :value_mask, Uint32
771
+ field :value_list, Uint32, :list
772
+ end
773
+
774
+ class XRenderCreateGlyphSet < BaseForm
775
+ field :req_type, Uint8
776
+ field :render_req_type, Uint8, value: 17
777
+ field :request_length, Uint16, value: 3
778
+ field :gsid, Uint32
779
+ field :format, Uint32
780
+ end
781
+
782
+ class GlyphInfo < BaseForm
783
+ field :width, Uint16
784
+ field :height, Uint16
785
+ field :x, Int16
786
+ field :y, Int16
787
+ field :x_off, Int16
788
+ field :y_off, Int16
789
+ end
790
+
791
+ class XRenderAddGlyphs < BaseForm
792
+ field :req_type, Uint8
793
+ field :render_req_type, Uint8, value: 20
794
+ field :request_length, Uint16, value: ->(ag) {
795
+ if ag.glyphs.length != ag.glyphids.length
796
+ raise "Mismatch: Expected XRenderAddGlyphs glyphs and glyphids to be same length"
797
+ end
798
+
799
+ # GlyphInfo length == 3 + Glyphid length == 1
800
+ 3 + ag.glyphs.length * 4 + (ag.data.length+3)/4
801
+ }
802
+ field :glyphset, Uint32
803
+ field :glyphs, Uint32, :length
804
+ field :glyphids, Uint32, :list
805
+ field :glyphs, GlyphInfo, :list
806
+ field :data, String8
807
+ end
808
+
809
+ class XRenderColor < BaseForm
810
+ field :red, Uint16
811
+ field :green, Uint16
812
+ field :blue, Uint16
813
+ field :alpha, Uint16
814
+ end
815
+
816
+ class GlyphElt32 < BaseForm
817
+ field :glyphs, Uint8, :length
818
+ unused 3
819
+ field :delta_x, Uint16
820
+ field :delta_y, Uint16
821
+ field :glyphs, Uint32, :list
822
+ end
823
+
824
+ # This is *also* the same as XRenderCOmpositeGlyphs16 and 8 w/other render_req_type,
825
+ # but do we care?
826
+ class XRenderCompositeGlyphs32 < BaseForm
827
+ field :req_type, Uint8
828
+ field :render_req_type, Uint8, value: 25
829
+ field :request_length, Uint16, value: ->(ch) {
830
+ 7 + (ch.glyphcmds[0].glyphs.length + 2) # per glyphcmd
831
+ }
832
+ field :op, Uint8
833
+ unused 3
834
+ field :src, Uint32
835
+ field :dst, Uint32
836
+ field :mask_format, Uint32
837
+ field :glyphset, Uint32
838
+ field :xsrc, Uint16
839
+ field :ysrc, Uint16
840
+ # FIXME:
841
+ # We say this is a list, because technically it is
842
+ # But currently it'll break with more than one item.
843
+ field :glyphcmds, GlyphElt32, :list
844
+ end
845
+
846
+ class XRenderFillRectangles < BaseForm
847
+ field :req_type, Uint8
848
+ field :render_req_type, Uint8, value: 26
849
+ field :request_length, Uint16, value: ->(fr) { 5 + fr.rects.length * 2 }
850
+ field :op, Uint8
851
+ unused 3
852
+ field :dst, Uint32
853
+ field :color, Uint32
854
+ field :rects, Rectangle, :list
855
+ end
856
+
857
+ class XRenderCreateSolidFill < BaseForm
858
+ field :req_type, Uint8
859
+ field :render_req_type, Uint8, value: 33
860
+ field :request_length, Uint16, value: 4
861
+ field :fill, Uint32
862
+ field :color, XRenderColor
863
+ end
864
+ end
865
+ end