pure-x11 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/client_message.rb +13 -0
- data/lib/X11/auth.rb +10 -13
- data/lib/X11/display.rb +144 -59
- data/lib/X11/form.rb +51 -8
- data/lib/X11/protocol.rb +4 -6
- data/lib/X11/screen.rb +5 -19
- data/lib/X11/type.rb +16 -13
- data/lib/X11/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37b5a813f478de65ecb12e89bafd332ef219baabac729a1baf29cf016d055347
|
4
|
+
data.tar.gz: 357ef8cd392bad30e9c2d8a7b6771c5c4fd1dd68f3e77da1544cf93f22df14f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81d50a93f9df23fe424f4dd62fe10fa09f840ab16eccb5de4d83b0d2f681b3cdb8fc9416e2b818f230399276974cac7455f38bfa1fe66c55968f70fc5c1661bb
|
7
|
+
data.tar.gz: 00bc7b7851c843a92988c23feacba461e6b9e1c2ef1f27b025c363f452f759492a30d4c1ff5d8117ba6bb4940eaebb19234c5fef9012d6cf8339a2ee143bf875
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'X11'
|
5
|
+
|
6
|
+
display = X11::Display.new
|
7
|
+
|
8
|
+
display.client_message(
|
9
|
+
mask: X11::Form::SubstructureNotifyMask | X11::Form::SubstructureRedirectMask,
|
10
|
+
type: :_NET_CURRENT_DESKTOP,
|
11
|
+
data: ARGV.shift.to_i
|
12
|
+
)
|
13
|
+
|
data/lib/X11/auth.rb
CHANGED
@@ -11,14 +11,14 @@ module X11
|
|
11
11
|
AUTHENTICATE = 2
|
12
12
|
|
13
13
|
ADDRESS_TYPES = {
|
14
|
-
|
14
|
+
0 => :Internet,
|
15
|
+
1 => :DECnet,
|
16
|
+
2 => :Chaos,
|
17
|
+
252 => :LocalHost,
|
18
|
+
253 => :Krb5Principal,
|
19
|
+
254 => :Netname,
|
20
|
+
256 => :Local,
|
15
21
|
65535 => :Wild,
|
16
|
-
254 => :Netname,
|
17
|
-
253 => :Krb5Principal,
|
18
|
-
252 => :LocalHost,
|
19
|
-
0 => :Internet,
|
20
|
-
1 => :DECnet,
|
21
|
-
2 => :Chaos
|
22
22
|
}
|
23
23
|
|
24
24
|
AuthInfo = Struct.new :family, :address, :display, :auth_name, :auth_data
|
@@ -52,18 +52,15 @@ module X11
|
|
52
52
|
|
53
53
|
# returns one entry from Xauthority file
|
54
54
|
def read
|
55
|
-
auth_info = [] << ADDRESS_TYPES[ @file.read(2).
|
55
|
+
auth_info = [] << ADDRESS_TYPES[ @file.read(2).unpack1('n') ]
|
56
56
|
|
57
57
|
4.times do
|
58
|
-
length = @file.read(2).
|
58
|
+
length = @file.read(2).unpack1('n')
|
59
59
|
auth_info << @file.read(length)
|
60
60
|
end
|
61
61
|
AuthInfo[*auth_info]
|
62
62
|
end
|
63
63
|
|
64
|
-
def reset
|
65
|
-
@file.seek(0, IO::SEEK_SET)
|
66
|
-
end
|
67
|
-
|
64
|
+
def reset = @file.seek(0, IO::SEEK_SET)
|
68
65
|
end
|
69
66
|
end
|
data/lib/X11/display.rb
CHANGED
@@ -17,6 +17,8 @@ module X11
|
|
17
17
|
host, display_id, screen_id = $1, $2, $3
|
18
18
|
family = nil
|
19
19
|
|
20
|
+
@debug = ENV["PUREX_DEBUG"].to_s.strip == "true"
|
21
|
+
|
20
22
|
if host.empty?
|
21
23
|
@socket = UNIXSocket.new("/tmp/.X11-unix/X#{display_id}")
|
22
24
|
family = :Local
|
@@ -26,22 +28,27 @@ module X11
|
|
26
28
|
family = :Internet
|
27
29
|
end
|
28
30
|
|
29
|
-
|
30
|
-
authorize(host, family, display_id) rescue nil
|
31
|
+
authorize(host, family, display_id)
|
31
32
|
|
32
33
|
@requestseq = 1
|
33
|
-
@
|
34
|
-
|
35
|
-
@extensions = {}
|
34
|
+
@rqueue = Queue.new # Read but not returned events
|
35
|
+
@wqueue = Queue.new
|
36
|
+
@extensions = {} # Known extensions
|
37
|
+
@atoms = {} # Interned atoms
|
36
38
|
|
37
|
-
|
38
|
-
@atoms = {}
|
39
|
+
start_io
|
39
40
|
end
|
40
41
|
|
41
42
|
def event_handler= block
|
42
43
|
@event_handler= block
|
43
44
|
end
|
44
45
|
|
46
|
+
def flush
|
47
|
+
while !@wqueue.empty?
|
48
|
+
sleep(0.01)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
45
52
|
def display_info
|
46
53
|
@internal
|
47
54
|
end
|
@@ -67,8 +74,15 @@ module X11
|
|
67
74
|
|
68
75
|
def read_error data
|
69
76
|
error = Form::Error.from_packet(StringIO.new(data))
|
77
|
+
# FIXME: Maybe make this configurable, as it means potentially
|
78
|
+
# keeping along really heavy requests. or alternative purge them
|
79
|
+
# more aggressively also when there are no errors, as otherwise
|
80
|
+
# the growth might be unbounded
|
81
|
+
error.request = @requests[error.sequence_number]
|
82
|
+
@requests.keys.find_all{|s| s <= error.sequence_number}.each do |s|
|
83
|
+
@requests.delete(s)
|
84
|
+
end
|
70
85
|
STDERR.puts "ERROR: #{error.inspect}"
|
71
|
-
raise error.inspect
|
72
86
|
error
|
73
87
|
end
|
74
88
|
|
@@ -126,22 +140,24 @@ module X11
|
|
126
140
|
end
|
127
141
|
|
128
142
|
def read_full_packet(len = 32)
|
129
|
-
data = @socket.
|
143
|
+
data = @socket.read(32)
|
130
144
|
return nil if data.nil?
|
131
145
|
while data.length < 32
|
132
146
|
IO.select([@socket],nil,nil,0.001)
|
133
147
|
data.concat(@socket.read_nonblock(32 - data.length))
|
134
148
|
end
|
135
149
|
return data
|
136
|
-
rescue IO::WaitReadable
|
137
|
-
return nil
|
138
150
|
end
|
139
151
|
|
140
|
-
def read_packet
|
141
|
-
IO.select([@socket],nil,nil, timeout)
|
152
|
+
def read_packet
|
142
153
|
data = read_full_packet(32)
|
143
154
|
return nil if data.nil?
|
144
155
|
|
156
|
+
# FIXME: Make it configurable.
|
157
|
+
@requests.keys.find_all{|s| s <= @requestseq - 50}.each do |s|
|
158
|
+
@requests.delete(s)
|
159
|
+
end
|
160
|
+
|
145
161
|
# FIXME: What is bit 8 for? Synthentic?
|
146
162
|
type = data.unpack("C").first & 0x7f
|
147
163
|
case type
|
@@ -153,57 +169,100 @@ module X11
|
|
153
169
|
end
|
154
170
|
end
|
155
171
|
|
156
|
-
def write_raw_packet(pkt)
|
157
|
-
@requestseq += 1
|
158
|
-
@socket.write(pkt)
|
159
|
-
end
|
160
|
-
|
161
172
|
def write_packet(*args)
|
162
173
|
pkt = args.join
|
163
174
|
pkt[2..3] = u16(pkt.length/4)
|
164
|
-
|
175
|
+
@wqueue << [nil,nil,pkt]
|
165
176
|
end
|
166
177
|
|
167
178
|
def write_request ob
|
168
|
-
data = ob.to_packet if ob.respond_to?(:to_packet)
|
179
|
+
data = ob.to_packet(self) if ob.respond_to?(:to_packet)
|
169
180
|
raise "BAD LENGTH for #{ob.inspect} (#{ob.request_length.to_i*4} ! #{data.size} " if ob.request_length && ob.request_length.to_i*4 != data.size
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
181
|
+
STDERR.puts "write_req: #{ob.inspect}" if @debug
|
182
|
+
@wqueue << [ob,nil,data]
|
183
|
+
end
|
184
|
+
|
185
|
+
def write_sync(ob, reply=nil)
|
186
|
+
data = ob.to_packet(self) if ob.respond_to?(:to_packet)
|
187
|
+
q = Queue.new
|
188
|
+
@wqueue << [ob,q,data]
|
189
|
+
STDERR.puts "write_sync_req: #{ob.inspect}" if @debug
|
190
|
+
pkt = q.shift
|
191
|
+
STDERR.puts "write_sync_rep: #{pkt.inspect}" if @debug
|
192
|
+
raise(pkt) if pkt.is_a?(X11::Form::Error)
|
193
|
+
return pkt if !pkt.is_a?(String)
|
180
194
|
reply ? reply.from_packet(StringIO.new(pkt)) : pkt
|
181
195
|
end
|
182
196
|
|
183
|
-
def peek_packet
|
184
|
-
|
185
|
-
end
|
197
|
+
def peek_packet = !@rqueue.empty?
|
198
|
+
def next_packet = @rqueue.shift
|
186
199
|
|
187
|
-
def
|
188
|
-
|
189
|
-
|
200
|
+
def close = @rqueue.close
|
201
|
+
|
202
|
+
def start_io
|
203
|
+
@replies ||= {}
|
204
|
+
@requests ||= {}
|
205
|
+
# Read thread.
|
206
|
+
# FIXME: Drop the select.
|
207
|
+
rt = Thread.new do
|
208
|
+
while pkt = read_packet
|
209
|
+
#STDERR.puts "read: #{pkt.inspect}"
|
210
|
+
if !pkt
|
211
|
+
sleep 0.1
|
212
|
+
elsif pkt.is_a?(String)
|
213
|
+
# This is a reply. We need the sequence number.
|
214
|
+
#
|
215
|
+
seq = pkt.unpack1("@2S")
|
216
|
+
STDERR.puts " - seq= #{seq}" if @debug
|
217
|
+
STDERR.puts @replies.inspect if @debug
|
218
|
+
if @replies[seq]
|
219
|
+
q = @replies.delete(seq)
|
220
|
+
STDERR.puts " - reply to #{q}" if @debug
|
221
|
+
q << pkt
|
222
|
+
end
|
223
|
+
elsif pkt.is_a?(X11::Form::Error)
|
224
|
+
if @replies[pkt.sequence_number]
|
225
|
+
q = @replies.delete(pkt.sequence_number)
|
226
|
+
q << pkt
|
227
|
+
else
|
228
|
+
@rqueue << pkt
|
229
|
+
end
|
230
|
+
else
|
231
|
+
@rqueue << pkt
|
232
|
+
end
|
233
|
+
end
|
234
|
+
@rqueue.close
|
235
|
+
@replies.values.each(&:close)
|
236
|
+
end
|
190
237
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
@queue.push(pkt)
|
238
|
+
# Write thread
|
239
|
+
wt = Thread.new do
|
240
|
+
while msg = @wqueue.shift
|
241
|
+
ob, q, data = *msg
|
242
|
+
@requests[@requestseq] = ob
|
243
|
+
@replies[@requestseq] = q if q
|
244
|
+
@requestseq = (@requestseq + 1) % 65536
|
245
|
+
@socket.write(data)
|
200
246
|
end
|
201
247
|
end
|
248
|
+
|
249
|
+
at_exit do
|
250
|
+
flush
|
251
|
+
@rqueue.close
|
252
|
+
@wqueue.close
|
253
|
+
# We kill this because it may be stuck in a read
|
254
|
+
# we'll never care about
|
255
|
+
Thread.kill(rt)
|
256
|
+
|
257
|
+
# We wait for this to finish because otherwise we may
|
258
|
+
# lose side-effects
|
259
|
+
wt.join
|
260
|
+
end
|
202
261
|
end
|
203
|
-
|
262
|
+
|
204
263
|
def run
|
205
264
|
loop do
|
206
|
-
pkt =
|
265
|
+
pkt = next_packet
|
207
266
|
return if !pkt
|
208
267
|
yield(pkt)
|
209
268
|
end
|
@@ -214,13 +273,15 @@ module X11
|
|
214
273
|
d.depth == depth }.visuals.find{|v| v.qlass = qlass }
|
215
274
|
end
|
216
275
|
|
276
|
+
def default_root = screens.first.root
|
277
|
+
|
217
278
|
# Requests
|
218
279
|
def create_window(x,y,w,h,
|
219
280
|
values: {},
|
220
281
|
depth: 32, parent: nil, border_width: 0, wclass: X11::Form::InputOutput, visual: nil
|
221
282
|
)
|
222
283
|
wid = new_id
|
223
|
-
parent ||=
|
284
|
+
parent ||= default_root
|
224
285
|
|
225
286
|
if visual.nil?
|
226
287
|
visual = find_visual(0, depth).visual_id
|
@@ -255,6 +316,12 @@ module X11
|
|
255
316
|
|
256
317
|
def atom(name)
|
257
318
|
return name if name.is_a?(Integer) # Allow atom(atom_integer_or_symbol)
|
319
|
+
begin
|
320
|
+
return Form::Atoms.const_get(name.to_sym) if Form::Atoms.const_defined?(name.to_sym)
|
321
|
+
rescue
|
322
|
+
# const_defined? will throw if name isn't a valid constant name, but
|
323
|
+
# that's fine
|
324
|
+
end
|
258
325
|
name = name.to_sym
|
259
326
|
intern_atom(false, name) if !@atoms[name]
|
260
327
|
@atoms[name]
|
@@ -343,7 +410,10 @@ module X11
|
|
343
410
|
def u8(*args) = args.pack("c*")
|
344
411
|
def u16(*args) = args.pack("v*")
|
345
412
|
def u32(*args) = args.pack("V*")
|
346
|
-
def atom_enum(val)
|
413
|
+
def atom_enum(val)
|
414
|
+
open_enum(val, {cardinal: Form::CardinalAtom, atom: Form::AtomAtom, window: Form::WindowAtom}) || atom(val)
|
415
|
+
end
|
416
|
+
|
347
417
|
def window(*args)
|
348
418
|
args.each {|a| raise "Window expected" if a.nil? }
|
349
419
|
u32(*args)
|
@@ -354,7 +424,7 @@ module X11
|
|
354
424
|
def set_input_focus(revert_to, focus, time=:now)
|
355
425
|
# FIXME: This is an experiment.
|
356
426
|
# Upside: Simpler. Downside: Doesn't work server-side.
|
357
|
-
#
|
427
|
+
# Probably a bad idea.
|
358
428
|
revert_to = open_enum(revert_to, {none: 0, pointer_root: 1, parent: 2})
|
359
429
|
focus = open_enum(focus, {none: 0, pointer_root: 1 })
|
360
430
|
time = open_enum(time, {current_time: 0, now: 0})
|
@@ -394,9 +464,8 @@ module X11
|
|
394
464
|
def configure_window(window, x: nil, y: nil, width: nil, height: nil,
|
395
465
|
border_width: nil, sibling: nil, stack_mode: nil)
|
396
466
|
|
397
|
-
mask = 0
|
398
467
|
values = []
|
399
|
-
|
468
|
+
mask = 0
|
400
469
|
mask |= set_value(values, 0x001, x)
|
401
470
|
mask |= set_value(values, 0x002, y)
|
402
471
|
mask |= set_value(values, 0x004, width)
|
@@ -419,7 +488,9 @@ module X11
|
|
419
488
|
end
|
420
489
|
|
421
490
|
|
422
|
-
def create_gc(window, foreground: nil, background: nil
|
491
|
+
def create_gc(window, foreground: nil, background: nil,
|
492
|
+
graphics_exposures: nil
|
493
|
+
)
|
423
494
|
mask = 0
|
424
495
|
args = []
|
425
496
|
|
@@ -428,12 +499,27 @@ module X11
|
|
428
499
|
# https://tronche.com/gui/x/xlib/GC/manipulating.html#XGCValues
|
429
500
|
mask |= set_value(args, 0x04, foreground)
|
430
501
|
mask |= set_value(args, 0x08, background)
|
502
|
+
mask |= set_value(args, 0x10000, graphics_exposures)
|
431
503
|
|
432
504
|
gc = new_id
|
433
505
|
write_request(X11::Form::CreateGC.new(gc, window, mask, args))
|
434
506
|
gc
|
435
507
|
end
|
436
508
|
|
509
|
+
def send_event(...) = write_request(Form::SendEvent.new(...))
|
510
|
+
def client_message(window: default_root, type: :ClientMessage, format: 32, destination: default_root, mask: 0, data: [], propagate: true)
|
511
|
+
f = {8 => "C20", 16 => "S10", 32 => "L5"}[format]
|
512
|
+
p f
|
513
|
+
data = (Array(data).map{|item|atom(item)} +[0]*20).pack(f)
|
514
|
+
event = Form::ClientMessage.new(
|
515
|
+
format, 0, window, atom(type), data
|
516
|
+
)
|
517
|
+
event.code =33
|
518
|
+
pp event
|
519
|
+
|
520
|
+
send_event(propagate, destination, mask, event)
|
521
|
+
end
|
522
|
+
|
437
523
|
def put_image(*args) = write_request(X11::Form::PutImage.new(*args))
|
438
524
|
def clear_area(*args) = write_request(X11::Form::ClearArea.new(*args))
|
439
525
|
def copy_area(*args) = write_request(X11::Form::CopyArea.new(*args))
|
@@ -499,19 +585,19 @@ module X11
|
|
499
585
|
end
|
500
586
|
when :rgb24
|
501
587
|
@rgb24 ||= formats.formats.find do |f|
|
502
|
-
f.type == 1
|
588
|
+
f.type == 1 &&
|
503
589
|
f.depth == 24 &&
|
504
590
|
f.direct.red == 16 &&
|
505
|
-
f.direct.green == 8
|
591
|
+
f.direct.green == 8 &&
|
506
592
|
f.direct.blue == 0
|
507
593
|
end
|
508
594
|
when :argb24
|
509
595
|
@argb24 ||= formats.formats.find do |f|
|
510
|
-
f.type == 1
|
596
|
+
f.type == 1 &&
|
511
597
|
f.depth == 32 &&
|
512
598
|
f.direct.alpha == 24 &&
|
513
599
|
f.direct.red == 16 &&
|
514
|
-
f.direct.green == 8
|
600
|
+
f.direct.green == 8 &&
|
515
601
|
f.direct.blue == 0
|
516
602
|
end
|
517
603
|
else
|
@@ -570,7 +656,6 @@ module X11
|
|
570
656
|
auth_name = ""
|
571
657
|
auth_data = ""
|
572
658
|
end
|
573
|
-
p [auth_name, auth_data]
|
574
659
|
|
575
660
|
handshake = Form::ClientHandshake.new(
|
576
661
|
Protocol::BYTE_ORDER,
|
@@ -580,7 +665,7 @@ module X11
|
|
580
665
|
auth_data
|
581
666
|
)
|
582
667
|
|
583
|
-
@socket.write(handshake.to_packet)
|
668
|
+
@socket.write(handshake.to_packet(self))
|
584
669
|
|
585
670
|
data = @socket.read(1)
|
586
671
|
raise AuthorizationError, "Failed to read response from server" if !data
|
data/lib/X11/form.rb
CHANGED
@@ -44,7 +44,7 @@ module X11
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def to_packet
|
47
|
+
def to_packet(dpy)
|
48
48
|
# fetch class level instance variable holding defined fields
|
49
49
|
structs = self.class.structs
|
50
50
|
|
@@ -64,10 +64,10 @@ module X11
|
|
64
64
|
#p [s,value]
|
65
65
|
|
66
66
|
if value.is_a?(BaseForm)
|
67
|
-
v = value.to_packet
|
67
|
+
v = value.to_packet(dpy)
|
68
68
|
else
|
69
69
|
#p [s,value]
|
70
|
-
v = s.type_klass.pack(value)
|
70
|
+
v = s.type_klass.pack(value, dpy)
|
71
71
|
end
|
72
72
|
#p v
|
73
73
|
v
|
@@ -77,15 +77,15 @@ module X11
|
|
77
77
|
when :length, :format_length
|
78
78
|
#p [s,value]
|
79
79
|
#p [value.size]
|
80
|
-
s.type_klass.pack(value.size)
|
80
|
+
s.type_klass.pack(value.size, dpy)
|
81
81
|
when :string
|
82
|
-
s.type_klass.pack(value)
|
82
|
+
s.type_klass.pack(value, dpy)
|
83
83
|
when :list
|
84
84
|
Array(value).collect do |obj|
|
85
85
|
if obj.is_a?(BaseForm)
|
86
|
-
obj.to_packet
|
86
|
+
obj.to_packet(dpy)
|
87
87
|
else
|
88
|
-
s.type_klass.pack(obj)
|
88
|
+
s.type_klass.pack(obj, dpy)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -184,6 +184,29 @@ module X11
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
+
# # Predefined constants, that can be used in the form of symbols
|
188
|
+
|
189
|
+
module Atoms
|
190
|
+
PRIMARY = 1
|
191
|
+
SECONDARY = 2
|
192
|
+
ARC = 3
|
193
|
+
ATOM = 4
|
194
|
+
BITMAP = 5
|
195
|
+
CARDINAL = 6
|
196
|
+
COLORMAP = 7
|
197
|
+
CURSOR = 8
|
198
|
+
#...
|
199
|
+
STRING = 31
|
200
|
+
VISUALID = 32
|
201
|
+
WINDOW = 33
|
202
|
+
WM_COMMAND = 34
|
203
|
+
WM_HINTS = 35
|
204
|
+
end
|
205
|
+
|
206
|
+
PointerWindow = 0
|
207
|
+
InputFocus = 1
|
208
|
+
|
209
|
+
# FIXME: Deprecated in favour of the Constants module
|
187
210
|
AtomAtom=4
|
188
211
|
CardinalAtom=6
|
189
212
|
WindowAtom=33
|
@@ -286,6 +309,9 @@ module X11
|
|
286
309
|
field :minor_opcode, Uint16
|
287
310
|
field :major_opcode, Uint8
|
288
311
|
unused 21
|
312
|
+
|
313
|
+
# The original request
|
314
|
+
attr_accessor :request
|
289
315
|
end
|
290
316
|
|
291
317
|
# XRender structures
|
@@ -329,8 +355,9 @@ module X11
|
|
329
355
|
field :colormap, Colormap
|
330
356
|
end
|
331
357
|
|
332
|
-
# Requests
|
358
|
+
# # Requests
|
333
359
|
|
360
|
+
# Constants, p112 onwards
|
334
361
|
CopyFromParent = 0
|
335
362
|
InputOutput = 1
|
336
363
|
InputOnly = 2
|
@@ -358,12 +385,17 @@ module X11
|
|
358
385
|
PointerMotionMask = 0x000040
|
359
386
|
PointerMotionHintMask = 0x000080
|
360
387
|
Button1MotionMask = 0x000100
|
388
|
+
# 0x200 .. 0x40000; page 113
|
361
389
|
ExposureMask = 0x008000
|
390
|
+
VisibilityChangeMask = 0x010000
|
362
391
|
StructureNotifyMask = 0x020000
|
392
|
+
ResizeRedirectMask = 0x040000
|
363
393
|
SubstructureNotifyMask = 0x080000
|
364
394
|
SubstructureRedirectMask=0x100000
|
365
395
|
FocusChangeMask = 0x200000
|
366
396
|
PropertyChangeMask = 0x400000
|
397
|
+
ColormapChangeMask = 0x800000
|
398
|
+
OwnerGrabButtonMask = 0x100000
|
367
399
|
|
368
400
|
class CreateWindow < BaseForm
|
369
401
|
field :opcode, Uint8, value: 1
|
@@ -592,6 +624,15 @@ module X11
|
|
592
624
|
field :value, String8, :string
|
593
625
|
end
|
594
626
|
|
627
|
+
class SendEvent < BaseForm
|
628
|
+
field :opcode, Uint8, value: 25
|
629
|
+
field :propagate, Bool
|
630
|
+
field :request_length, Uint16, value: 11
|
631
|
+
field :destination, Window
|
632
|
+
field :event_mask, Uint32
|
633
|
+
field :event, Uint32 # FIXME: This is wrong, and will break on parsing.
|
634
|
+
end
|
635
|
+
|
595
636
|
class GrabButton < BaseForm
|
596
637
|
field :opcode, Uint8, value: 28
|
597
638
|
field :owner_events, Bool
|
@@ -678,6 +719,7 @@ module X11
|
|
678
719
|
ForegroundMask = 0x04
|
679
720
|
BackgroundMask = 0x08
|
680
721
|
FontMask = 0x4000
|
722
|
+
GraphicsExposures = 0x10000
|
681
723
|
|
682
724
|
class CreateGC < BaseForm
|
683
725
|
field :opcode, Uint8, value: 55
|
@@ -1002,6 +1044,7 @@ module X11
|
|
1002
1044
|
unused 1
|
1003
1045
|
field :sequence_number, Uint16
|
1004
1046
|
field :event, Window
|
1047
|
+
field :window, Window
|
1005
1048
|
field :above_sibling, Window
|
1006
1049
|
field :x, Int16
|
1007
1050
|
field :y, Int16
|
data/lib/X11/protocol.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
module X11
|
2
2
|
module Protocol
|
3
|
-
#
|
3
|
+
# endianess of your machine
|
4
4
|
BYTE_ORDER = case [1].pack("L")
|
5
|
-
when "\0\0\0\1"
|
6
|
-
|
7
|
-
when "\1\0\0\0"
|
8
|
-
"l".ord
|
5
|
+
when "\0\0\0\1" then "B".ord
|
6
|
+
when "\1\0\0\0" then "l".ord
|
9
7
|
else
|
10
8
|
raise ByteOrderError.new "Cannot determine byte order"
|
11
|
-
|
9
|
+
end
|
12
10
|
|
13
11
|
MAJOR = 11
|
14
12
|
MINOR = 0
|
data/lib/X11/screen.rb
CHANGED
@@ -7,25 +7,11 @@ module X11
|
|
7
7
|
@internal = data
|
8
8
|
end
|
9
9
|
|
10
|
-
def root
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def
|
15
|
-
@internal.root_depth
|
16
|
-
end
|
17
|
-
|
18
|
-
def root_visual
|
19
|
-
@internal.root_visual
|
20
|
-
end
|
21
|
-
|
22
|
-
def width
|
23
|
-
@internal.width_in_pixels
|
24
|
-
end
|
25
|
-
|
26
|
-
def height
|
27
|
-
@internal.height_in_pixels
|
28
|
-
end
|
10
|
+
def root = @internal.root
|
11
|
+
def root_depth = @internal.root_depth
|
12
|
+
def root_visual = @internal.root_visual
|
13
|
+
def width = @internal.width_in_pixels
|
14
|
+
def height = @internal.height_in_pixels
|
29
15
|
|
30
16
|
def to_s
|
31
17
|
"#<X11::Screen(#{id}) width=#{width} height=#{height}>"
|
data/lib/X11/type.rb
CHANGED
@@ -11,7 +11,7 @@ module X11
|
|
11
11
|
|
12
12
|
def self.config(d,b) = (@directive, @bytesize = d,b)
|
13
13
|
|
14
|
-
def self.pack(x)
|
14
|
+
def self.pack(x, dpy)
|
15
15
|
if x.is_a?(Symbol)
|
16
16
|
if (t = X11::Form.const_get(x)) && t.is_a?(Numeric)
|
17
17
|
x = t
|
@@ -27,7 +27,6 @@ module X11
|
|
27
27
|
def self.from_packet(sock) = unpack(sock.read(size))
|
28
28
|
end
|
29
29
|
|
30
|
-
# Primitive Types
|
31
30
|
class Int8 < BaseType; config("c",1); end
|
32
31
|
class Int16 < BaseType; config("s",2); end
|
33
32
|
class Int32 < BaseType; config("l",4); end
|
@@ -36,16 +35,14 @@ module X11
|
|
36
35
|
class Uint32 < BaseType; config("L",4); end
|
37
36
|
|
38
37
|
class Message
|
39
|
-
def self.pack(x)
|
40
|
-
def self.unpack(x)
|
41
|
-
def self.size
|
38
|
+
def self.pack(x,dpy) = x.b
|
39
|
+
def self.unpack(x) = x.b
|
40
|
+
def self.size = 20
|
42
41
|
def self.from_packet(sock) = sock.read(2).b
|
43
42
|
end
|
44
43
|
|
45
44
|
class String8
|
46
|
-
def self.pack(x)
|
47
|
-
x.b + "\x00"*(-x.length & 3)
|
48
|
-
end
|
45
|
+
def self.pack(x, dpy) = (x.b + "\x00"*(-x.length & 3))
|
49
46
|
|
50
47
|
def self.unpack(socket, size)
|
51
48
|
raise "Expected size for String8" if size.nil?
|
@@ -57,7 +54,7 @@ module X11
|
|
57
54
|
end
|
58
55
|
|
59
56
|
class String16
|
60
|
-
def self.pack(x)
|
57
|
+
def self.pack(x, dpy)
|
61
58
|
x.encode("UTF-16BE").b + "\x00\x00"*(-x.length & 1)
|
62
59
|
end
|
63
60
|
|
@@ -71,13 +68,13 @@ module X11
|
|
71
68
|
|
72
69
|
|
73
70
|
class String8Unpadded
|
74
|
-
def self.pack(x) = x
|
71
|
+
def self.pack(x,dpy) = x
|
75
72
|
def self.unpack(socket, size) = socket.read(size)
|
76
73
|
end
|
77
74
|
|
78
75
|
class Bool
|
79
|
-
def self.pack(x)
|
80
|
-
def self.unpack(str)
|
76
|
+
def self.pack(x, dpy) = (x ? "\x01" : "\x00")
|
77
|
+
def self.unpack(str) = (str[0] == "\x01")
|
81
78
|
def self.size = 1
|
82
79
|
end
|
83
80
|
|
@@ -96,10 +93,16 @@ module X11
|
|
96
93
|
Colormap = Uint32
|
97
94
|
Drawable = Uint32
|
98
95
|
Fontable = Uint32
|
99
|
-
Atom = Uint32
|
100
96
|
VisualID = Uint32
|
101
97
|
Mask = Uint32
|
102
98
|
Timestamp = Uint32
|
103
99
|
Keysym = Uint32
|
100
|
+
|
101
|
+
class Atom
|
102
|
+
def self.pack(x,dpy) = [dpy.atom(x)].pack("L")
|
103
|
+
def self.unpack(x) = x.nil? ? nil : x.unpack1("L")
|
104
|
+
def self.size = 4
|
105
|
+
def self.from_packet(sock) = unpack(sock.read(size))
|
106
|
+
end
|
104
107
|
end
|
105
108
|
end
|
data/lib/X11/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pure-x11
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vidar Hokstad
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-01-11 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Pure Ruby X11 bindings
|
15
15
|
email:
|
@@ -25,6 +25,7 @@ files:
|
|
25
25
|
- README.md
|
26
26
|
- Rakefile
|
27
27
|
- docs/protocol.pdf
|
28
|
+
- example/client_message.rb
|
28
29
|
- example/genie.png
|
29
30
|
- example/test.rb
|
30
31
|
- lib/X11.rb
|