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.
- checksums.yaml +7 -0
- data/.gitignore +48 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +19 -0
- data/LICENSE.txt +20 -0
- data/README.md +12 -0
- data/Rakefile +7 -0
- data/docs/protocol.pdf +0 -0
- data/example/genie.png +0 -0
- data/example/test.rb +108 -0
- data/lib/X11/auth.rb +69 -0
- data/lib/X11/display.rb +450 -0
- data/lib/X11/event.rb +0 -0
- data/lib/X11/form.rb +865 -0
- data/lib/X11/keysyms.rb +328 -0
- data/lib/X11/protocol.rb +16 -0
- data/lib/X11/screen.rb +34 -0
- data/lib/X11/type.rb +116 -0
- data/lib/X11/version.rb +3 -0
- data/lib/X11.rb +12 -0
- data/ruby-x11.gemspec +24 -0
- data/test/core_test.rb +15 -0
- data/test/form_test.rb +66 -0
- data/test/helper.rb +11 -0
- metadata +66 -0
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
|