pure-x11 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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