pure-x11 0.0.2 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +7 -2
- data/example/test.rb +149 -75
- data/lib/X11/display.rb +258 -65
- data/lib/X11/form.rb +357 -37
- data/lib/X11/keysyms.rb +6 -1
- data/lib/X11/type.rb +10 -3
- data/lib/X11/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ecd289a7ec4a0a7f44bba1d05a437774ca6ed3d4c403b572b28a8691ef2a950
|
4
|
+
data.tar.gz: ac9460f0c0db0635e33358550176802119db88c9bb4dee097807f21c970f68ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db23062260daabe75bfe5a9f419772be329023777c405ae7bb3a08125b9942f63ec8d635c1c11869648272d2c3ecad16a432fbca2d4d584d80ad2dbf15250d5a
|
7
|
+
data.tar.gz: f303d01e2c4b43fa2c5d44af4e469288684887c3efe71ee644275f233d584b9e342f9ebd80374632afe1199ad0d4182cebb515a95a7408b79aa36d239c9c9ffb
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
-
|
1
|
+
Pure X11
|
2
2
|
========
|
3
3
|
|
4
|
+
This library is now on Rubygems.org as "pure-X11" as I (vidarh) has not had a
|
5
|
+
response from the original author. If that should change, I'll be happy to
|
6
|
+
upstread everything.
|
7
|
+
|
4
8
|
(under-development) Pure Ruby implementation of the X Window System Protocol.
|
5
|
-
This library is based off of Mathieu Bouchard's work on his RubyX11 project
|
9
|
+
This library is based off of Mathieu Bouchard's work on his RubyX11 project,
|
10
|
+
and Richard Ramsdens excellent start on Ruby-X11.
|
6
11
|
|
7
12
|
Contributors
|
8
13
|
------------
|
data/example/test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'skrift'
|
2
3
|
require 'bundler'
|
3
4
|
require 'chunky_png'
|
4
5
|
Bundler.setup(:default, :development)
|
@@ -8,95 +9,164 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
8
9
|
|
9
10
|
require 'X11'
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
|
13
|
+
dpy = display = X11::Display.new
|
14
|
+
screen = dpy.screens.first
|
13
15
|
root = screen.root
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
16
|
+
|
17
|
+
wid = dpy.create_window(
|
18
|
+
0, 0, # x,y
|
19
|
+
1000, 600, # w,h
|
20
|
+
# FIXME: WTH isn't depth: 32 working here?
|
21
|
+
depth: 24,
|
22
|
+
values: {
|
23
|
+
X11::Form::CWBackPixel => 0x0,
|
24
|
+
X11::Form::CWEventMask =>
|
25
|
+
(X11::Form::SubstructureNotifyMask |
|
26
|
+
X11::Form::StructureNotifyMask | ## Move
|
27
|
+
X11::Form::ExposureMask |
|
28
|
+
X11::Form::KeyPressMask |
|
29
|
+
X11::Form::ButtonPressMask)
|
30
|
+
}
|
31
|
+
)
|
32
|
+
#dpy.next_packet
|
33
|
+
#exit(0)
|
34
|
+
|
35
|
+
def set_window_opacity(dpy, wid, opacity)
|
36
|
+
dpy.change_property(
|
37
|
+
:replace,
|
38
|
+
wid, "_NET_WM_WINDOW_OPACITY",
|
39
|
+
:cardinal, 32,
|
40
|
+
[(0xffffffff * opacity).to_i].pack("V").unpack("C*")
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
set_window_opacity(dpy, wid, 0.8)
|
46
|
+
|
47
|
+
#p dpy.display_info
|
48
|
+
|
49
|
+
#reply = dpy.query_extension("XKEYBOARD")
|
50
|
+
|
51
|
+
$kmap = nil
|
52
|
+
def update_keymap(dpy)
|
53
|
+
reply = dpy.get_keyboard_mapping
|
54
|
+
|
55
|
+
|
56
|
+
if reply
|
57
|
+
$kmap = reply.keysyms.map do |c|
|
58
|
+
if c == 0
|
59
|
+
nil
|
60
|
+
elsif X11::KeySyms[c]
|
61
|
+
X11::KeySyms[c]
|
62
|
+
elsif c < 0x100
|
63
|
+
c.chr(Encoding::ISO_8859_1)
|
64
|
+
elsif c.between?(0xffb0, 0xffb9)
|
65
|
+
"KP_#{c-0xffb0}".to_sym
|
66
|
+
elsif c.between?(0xffbe, 0xffe0)
|
67
|
+
"F#{c-0xffbe+1}".to_sym
|
68
|
+
elsif c.between?(0xff08, 0xffff)
|
69
|
+
# FIIXME:
|
70
|
+
raise "keyboard_#{c.to_s(16)}".to_s
|
71
|
+
elsif c.between?(0x01000100, 0x0110FFFF)
|
72
|
+
(c-0x01000100).
|
73
|
+
chr(Encoding::UTF_32) rescue c.to_s(16)
|
74
|
+
else
|
75
|
+
raise "unknown_#{c.to_s(16)}"
|
76
|
+
end
|
77
|
+
end.each_slice(reply.keysyms_per_keycode).to_a
|
78
|
+
#ks = ks.map {|s| s.compact.sort_by{|x| x.to_s}.uniq }.to_a # This is for testing/ease of reading only
|
79
|
+
p $kmap[47-dpy.display_info.min_keycode]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def lookup_keysym(dpy, event)
|
85
|
+
update_keymap(dpy) if !$kmap
|
86
|
+
p $kmap[event.detail-dpy.display_info.min_keycode]
|
87
|
+
end
|
88
|
+
|
36
89
|
puts "Mapping"
|
37
|
-
|
38
|
-
|
39
|
-
gc =
|
40
|
-
|
41
|
-
|
42
|
-
X11::Form::ForegroundMask,
|
43
|
-
[0xff0000, # RGB foreground
|
44
|
-
]
|
45
|
-
))
|
46
|
-
|
47
|
-
$gc2 = display.new_id
|
48
|
-
display.write_request(X11::Form::CreateGC.new(
|
49
|
-
$gc2,
|
50
|
-
screen.root,
|
51
|
-
X11::Form::ForegroundMask|X11::Form::BackgroundMask,
|
52
|
-
[0xffffff, # RGB foreground
|
53
|
-
0x444444,
|
54
|
-
]
|
55
|
-
))
|
56
|
-
|
57
|
-
$gc3 = display.new_id
|
58
|
-
display.write_request(X11::Form::CreateGC.new(
|
59
|
-
$gc3,
|
60
|
-
screen.root,
|
61
|
-
0, []
|
62
|
-
))
|
90
|
+
dpy.map_window(wid)
|
91
|
+
|
92
|
+
$gc = gc = dpy.create_gc(wid, foreground: 0xff0000)
|
93
|
+
$gc2 = dpy.create_gc(wid,foreground: 0xffffff, background: 0x444444)
|
94
|
+
$gc3 = dpy.create_gc(wid)
|
63
95
|
|
64
96
|
|
65
97
|
puts "Main loop"
|
66
|
-
p gc
|
67
98
|
|
68
|
-
#
|
69
|
-
p display.write_sync(X11::Form::ListFonts.new(10, "*7x13*"),
|
70
|
-
X11::Form::ListFontsReply).names.map(&:to_s)
|
99
|
+
#p dpy.list_fonts(10, "*7x13*").names.map(&:to_s)
|
71
100
|
|
72
|
-
fid =
|
73
|
-
|
74
|
-
|
101
|
+
fid = dpy.new_id
|
102
|
+
dpy.open_font(fid, "-misc-fixed-bold-r-normal--13-120-75-75-c-70-iso10646-1")
|
103
|
+
#"-bitstream-courier 10 pitch-medium-r-normal--0-0-0-0-m-0-iso10646-1")
|
104
|
+
dpy.change_gc($gc2, X11::Form::FontMask, [fid])
|
75
105
|
|
76
106
|
$png = ChunkyPNG::Image.from_file('genie.png')
|
77
|
-
p $png.width
|
78
|
-
p $png.height
|
79
107
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
108
|
+
$data = ""
|
109
|
+
$png.pixels.each do |px|
|
110
|
+
str = [px].pack("N")
|
111
|
+
if str[3] == "\x00"
|
112
|
+
$data << "\0\0\0\0".force_encoding("ASCII-8BIT")
|
113
|
+
else
|
114
|
+
$data << str[2] << str[1] << str[0] << str[3]
|
115
|
+
end
|
116
|
+
end
|
86
117
|
|
87
|
-
|
88
|
-
|
118
|
+
#$f = Font.load("/usr/share/fonts/truetype/tlwg/Umpush-BoldOblique.ttf")
|
119
|
+
$f = Font.load("/usr/share/fonts/truetype/tlwg/Garuda.ttf")
|
120
|
+
#$f = Font.load("resources/FiraGO-Regular.ttf")
|
89
121
|
|
122
|
+
$sft = SFT.new($f)
|
123
|
+
$sft.x_scale = 15
|
124
|
+
$sft.y_scale = 15
|
125
|
+
$glyphcache = {}
|
126
|
+
def render_glyph(display, wid, x,y, ch)
|
127
|
+
gid = $sft.lookup(ch.ord)
|
128
|
+
mtx = $sft.gmetrics(gid)
|
129
|
+
data = $glyphcache[gid]
|
130
|
+
if !data
|
131
|
+
img = Image.new(mtx.min_width, mtx.min_height) #(mtx .min_width + 3) & ~3, mtx.min_height)
|
132
|
+
if !$sft.render(gid, img)
|
133
|
+
raise "Unable to render #{gid}\n"
|
134
|
+
end
|
135
|
+
# p img
|
136
|
+
data = img.pixels.map {|px|
|
137
|
+
"\0\0"+px.chr+"\0" #+ "\0\0\0"
|
138
|
+
}.join.force_encoding("ASCII-8BIT")
|
139
|
+
$glyphcache[gid] = data
|
140
|
+
end
|
90
141
|
depth = 24
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
142
|
+
# p data
|
143
|
+
#p img
|
144
|
+
# p ch
|
145
|
+
display.put_image(
|
146
|
+
X11::Form::ZPixmap, wid, $gc2,
|
147
|
+
mtx.min_width,mtx.min_height,
|
148
|
+
x, y - mtx.y_offset, 0, depth, data
|
149
|
+
)
|
150
|
+
mtx.advance_width
|
151
|
+
end
|
152
|
+
|
153
|
+
def render_str(display, wid, x,y, str)
|
154
|
+
str.each_byte do |ch|
|
155
|
+
off = render_glyph(display, wid, x, y, ch.chr)
|
156
|
+
x+= off
|
97
157
|
end
|
98
|
-
|
99
|
-
|
158
|
+
end
|
159
|
+
|
160
|
+
def redraw(dpy, wid, gc)
|
161
|
+
dpy.poly_fill_rectangle(wid, gc, [X11::Form::Rectangle.new(20,20, 60, 80)])
|
162
|
+
dpy.clear_area(false, wid, 30, 30, 5, 5)
|
163
|
+
dpy.image_text16(wid, $gc2, 30, 70, "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ")
|
164
|
+
#"\u25f0\u25ef Hello World")
|
165
|
+
dpy.put_image(
|
166
|
+
X11::Form::ZPixmap, wid, $gc2,
|
167
|
+
$png.width, $png.height, 80, 120, 0, 24, $data
|
168
|
+
)
|
169
|
+
render_str(dpy, wid, 30,90, 'HelloWorld')
|
100
170
|
end
|
101
171
|
|
102
172
|
loop do
|
@@ -104,5 +174,9 @@ loop do
|
|
104
174
|
if pkt
|
105
175
|
p pkt
|
106
176
|
redraw(display, wid, gc) if pkt.is_a?(X11::Form::Expose)
|
177
|
+
|
178
|
+
if pkt.is_a?(X11::Form::KeyPress)
|
179
|
+
lookup_keysym(dpy,pkt)
|
180
|
+
end
|
107
181
|
end
|
108
182
|
end
|
data/lib/X11/display.rb
CHANGED
@@ -26,7 +26,8 @@ module X11
|
|
26
26
|
family = :Internet
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
# FIXME
|
30
|
+
authorize(host, family, display_id) rescue nil
|
30
31
|
|
31
32
|
@requestseq = 1
|
32
33
|
@queue = []
|
@@ -67,6 +68,7 @@ module X11
|
|
67
68
|
def read_error data
|
68
69
|
error = Form::Error.from_packet(StringIO.new(data))
|
69
70
|
STDERR.puts "ERROR: #{error.inspect}"
|
71
|
+
raise error.inspect
|
70
72
|
error
|
71
73
|
end
|
72
74
|
|
@@ -79,26 +81,47 @@ module X11
|
|
79
81
|
end
|
80
82
|
|
81
83
|
def read_event type, data, event_class
|
84
|
+
io = StringIO.new(data)
|
82
85
|
case type
|
83
|
-
|
84
|
-
|
85
|
-
when
|
86
|
-
|
87
|
-
when 4
|
88
|
-
|
89
|
-
when 6
|
90
|
-
|
91
|
-
when
|
92
|
-
|
93
|
-
when
|
94
|
-
|
95
|
-
when
|
96
|
-
|
97
|
-
when
|
98
|
-
|
86
|
+
# 0 is error, not handled here
|
87
|
+
# 1 is reply, not handled here
|
88
|
+
when 2 then return Form::KeyPress.from_packet(io)
|
89
|
+
when 3 then return Form::KeyRelease.from_packet(io)
|
90
|
+
when 4 then return Form::ButtonPress.from_packet(io)
|
91
|
+
when 5 then return Form::ButtonRelease.from_packet(io)
|
92
|
+
when 6 then return Form::MotionNotify.from_packet(io)
|
93
|
+
when 7 then return Form::EnterNotify.from_packet(io)
|
94
|
+
when 8 then return Form::LeaveNotify.from_packet(io)
|
95
|
+
when 9 then return Form::FocusIn.from_packet(io)
|
96
|
+
when 10 then return Form::FocusOut.from_packet(io)
|
97
|
+
# FIXME 11: KeymapNotify
|
98
|
+
when 12 then return Form::Expose.from_packet(io)
|
99
|
+
# FIXME 13: GraphicsExposure
|
100
|
+
when 14 then return Form::NoExposure.from_packet(io)
|
101
|
+
# FIXME: 15: VisibilityNotify
|
102
|
+
when 16 then return Form::CreateNotify.from_packet(io)
|
103
|
+
when 17 then return Form::DestroyNotify.from_packet(io)
|
104
|
+
when 18 then return Form::UnmapNotify.from_packet(io)
|
105
|
+
when 19 then return Form::MapNotify.from_packet(io)
|
106
|
+
when 20 then return Form::MapRequest.from_packet(io)
|
107
|
+
when 21 then return Form::ReparentNotify.from_packet(io)
|
108
|
+
when 22 then return Form::ConfigureNotify.from_packet(io)
|
109
|
+
when 23 then return Form::ConfigureRequest.from_packet(io)
|
110
|
+
# FIXME: 24: GravityNotify
|
111
|
+
# FIXME: 25: ResizeRequest
|
112
|
+
# FIXME: 26: CirculateNotify
|
113
|
+
# FIXME: 27: CirculateRequest
|
114
|
+
when 28 then return Form::PropertyNotify.from_packet(io)
|
115
|
+
# FIXME: 29: SelectionClear
|
116
|
+
# FIXME: 30: SelectionRequest
|
117
|
+
# FIXME: 31: SelectionNotify
|
118
|
+
# FIXME: 32: ColormapNotify
|
119
|
+
when 33 then return Form::ClientMessage.from_packet(StringIO.new(data))
|
120
|
+
# FIXME: 34: MappingNotify
|
99
121
|
else
|
100
122
|
STDERR.puts "FIXME: Event: #{type}"
|
101
123
|
STDERR.puts "EVENT: #{data.inspect}"
|
124
|
+
data
|
102
125
|
end
|
103
126
|
end
|
104
127
|
|
@@ -119,19 +142,28 @@ module X11
|
|
119
142
|
data = read_full_packet(32)
|
120
143
|
return nil if data.nil?
|
121
144
|
|
122
|
-
|
145
|
+
# FIXME: What is bit 8 for? Synthentic?
|
146
|
+
type = data.unpack("C").first & 0x7f
|
123
147
|
case type
|
124
|
-
when 0
|
125
|
-
|
126
|
-
when
|
127
|
-
read_reply(data)
|
128
|
-
when 2..34
|
129
|
-
read_event(type, data, nil)
|
148
|
+
when 0 then read_error(data)
|
149
|
+
when 1 then read_reply(data)
|
150
|
+
when 2..34 then read_event(type, data, nil)
|
130
151
|
else
|
131
|
-
raise ProtocolError, "Unsupported reply type: #{type}"
|
152
|
+
raise ProtocolError, "Unsupported reply type: #{type} #{data.inspect}"
|
132
153
|
end
|
133
154
|
end
|
134
155
|
|
156
|
+
def write_raw_packet(pkt)
|
157
|
+
@requestseq += 1
|
158
|
+
@socket.write(pkt)
|
159
|
+
end
|
160
|
+
|
161
|
+
def write_packet(*args)
|
162
|
+
pkt = args.join
|
163
|
+
pkt[2..3] = u16(pkt.length/4)
|
164
|
+
write_raw_packet(pkt)
|
165
|
+
end
|
166
|
+
|
135
167
|
def write_request ob
|
136
168
|
#p data
|
137
169
|
#p [:write_request, @requestseq, ob.class]
|
@@ -139,14 +171,16 @@ module X11
|
|
139
171
|
#p [:AddGlyph,data] if ob.is_a?(X11::Form::XRenderAddGlyphs)
|
140
172
|
#p [ob.request_length.to_i*4, data.size]
|
141
173
|
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
|
142
|
-
|
143
|
-
@socket.write(data)
|
174
|
+
write_raw_packet(data)
|
144
175
|
end
|
145
176
|
|
146
177
|
def write_sync(data, reply=nil)
|
178
|
+
seq = @requestseq
|
147
179
|
write_request(data)
|
148
|
-
pkt = next_reply
|
180
|
+
pkt = next_reply(seq)
|
149
181
|
return nil if !pkt
|
182
|
+
return pkt if pkt.is_a?(X11::Form::Error)
|
183
|
+
pp reply
|
150
184
|
reply ? reply.from_packet(StringIO.new(pkt)) : pkt
|
151
185
|
end
|
152
186
|
|
@@ -158,17 +192,19 @@ module X11
|
|
158
192
|
@queue.shift || read_packet
|
159
193
|
end
|
160
194
|
|
161
|
-
def next_reply
|
195
|
+
def next_reply(errseq)
|
162
196
|
# FIXME: This is totally broken
|
163
197
|
while pkt = read_packet
|
164
198
|
if pkt.is_a?(String)
|
165
199
|
return pkt
|
200
|
+
elsif pkt.is_a?(X11::Form::Error) && pkt.sequence_number == errseq
|
201
|
+
return pkt
|
166
202
|
else
|
167
203
|
@queue.push(pkt)
|
168
204
|
end
|
169
205
|
end
|
170
206
|
end
|
171
|
-
|
207
|
+
|
172
208
|
def run
|
173
209
|
loop do
|
174
210
|
pkt = read_packet
|
@@ -177,12 +213,54 @@ module X11
|
|
177
213
|
end
|
178
214
|
end
|
179
215
|
|
216
|
+
def find_visual(screen, depth, qlass = 4)
|
217
|
+
self.display_info.screens[screen].depths.find{|d|
|
218
|
+
d.depth == depth }.visuals.find{|v| v.qlass = qlass }
|
219
|
+
end
|
220
|
+
|
180
221
|
# Requests
|
181
|
-
def create_window(
|
182
|
-
|
222
|
+
def create_window(x,y,w,h,
|
223
|
+
values: {},
|
224
|
+
depth: 32, parent: nil, border_width: 0, wclass: X11::Form::InputOutput, visual: nil
|
225
|
+
)
|
226
|
+
wid = new_id
|
227
|
+
parent ||= screens.first.root
|
228
|
+
|
229
|
+
if visual.nil?
|
230
|
+
visual = find_visual(0, depth).visual_id
|
231
|
+
end
|
232
|
+
|
233
|
+
values[X11::Form::CWColorMap] ||= create_colormap(0, parent, visual)
|
234
|
+
|
235
|
+
values = values.sort_by{_1[0]}
|
236
|
+
mask = values.inject(0) {|acc,v| (acc | v[0]) }
|
237
|
+
values = values.map{_1[1]}
|
238
|
+
write_request(
|
239
|
+
X11::Form::CreateWindow.new(
|
240
|
+
depth, wid, parent,
|
241
|
+
x,y,w,h,border_width, wclass, visual, mask, values)
|
242
|
+
)
|
243
|
+
return wid
|
244
|
+
end
|
245
|
+
|
246
|
+
def get_window_attributes(wid)
|
247
|
+
write_sync( Form::GetWindowAttributes.new(wid), Form::WindowAttributes )
|
248
|
+
end
|
249
|
+
|
250
|
+
def change_window_attributes(wid,
|
251
|
+
values: {})
|
252
|
+
values = values.sort_by{_1[0]}
|
253
|
+
mask = values.inject(0) {|acc,v| (acc | v[0]) }
|
254
|
+
values = values.map{_1[1]}
|
255
|
+
write_request(
|
256
|
+
X11::Form::ChangeWindowAttributes.new(wid, mask, values)
|
257
|
+
)
|
183
258
|
end
|
184
259
|
|
260
|
+
def select_input(w, events) = change_window_attributes(w, values: {Form::CWEventMask => events})
|
261
|
+
|
185
262
|
def atom(name)
|
263
|
+
name = name.to_sym
|
186
264
|
intern_atom(false, name) if !@atoms[name]
|
187
265
|
@atoms[name]
|
188
266
|
end
|
@@ -211,6 +289,14 @@ module X11
|
|
211
289
|
end
|
212
290
|
end
|
213
291
|
|
292
|
+
def get_atom_name(atom)
|
293
|
+
reply = write_sync(X11::Form::GetAtomName.new(atom), X11::Form::AtomName)
|
294
|
+
reply&.name
|
295
|
+
end
|
296
|
+
|
297
|
+
def destroy_window(window) = write_request(X11::Form::DestroyWindow.new(window))
|
298
|
+
def get_geometry(drawable) = write_sync(X11::Form::GetGeometry.new(drawable), X11::Form::Geometry)
|
299
|
+
|
214
300
|
def get_keyboard_mapping(min_keycode=display_info.min_keycode, count= display_info.max_keycode - min_keycode)
|
215
301
|
write_sync(X11::Form::GetKeyboardMapping.new(min_keycode, count), X11::Form::GetKeyboardMappingReply)
|
216
302
|
end
|
@@ -221,8 +307,35 @@ module X11
|
|
221
307
|
mid
|
222
308
|
end
|
223
309
|
|
224
|
-
def
|
225
|
-
|
310
|
+
def get_property(window, property, type, offset: 0, length: 4, delete: false)
|
311
|
+
property = atom(property) if !property.is_a?(Integer)
|
312
|
+
type = atom_enum(type)
|
313
|
+
|
314
|
+
result = write_sync(X11::Form::GetProperty.new(
|
315
|
+
delete, window, property, type, offset, length
|
316
|
+
), X11::Form::Property)
|
317
|
+
|
318
|
+
if result && result.format != 0
|
319
|
+
case result.format
|
320
|
+
when 16
|
321
|
+
result.value = result.value.unpack("v")
|
322
|
+
result.value = result.value.first if length == 2
|
323
|
+
when 32
|
324
|
+
result.value = result.value.unpack("V")
|
325
|
+
result.value = result.value.first if length == 4
|
326
|
+
end
|
327
|
+
elsif result
|
328
|
+
result.value = nil
|
329
|
+
end
|
330
|
+
result
|
331
|
+
end
|
332
|
+
|
333
|
+
def change_property(mode, window, property, type, format, data)
|
334
|
+
property = atom(property.to_sym) if property.is_a?(Symbol) || property.is_a?(String)
|
335
|
+
|
336
|
+
mode = open_enum(mode, {replace: 0, prepend: 1, append: 2})
|
337
|
+
type = atom_enum(type)
|
338
|
+
write_request(X11::Form::ChangeProperty.new(mode, window, property, type, format, data))
|
226
339
|
end
|
227
340
|
|
228
341
|
def list_fonts(*args)
|
@@ -230,16 +343,108 @@ module X11
|
|
230
343
|
X11::Form::ListFontsReply)
|
231
344
|
end
|
232
345
|
|
233
|
-
def open_font(*args)
|
234
|
-
|
346
|
+
def open_font(*args) = write_request(X11::Form::OpenFont.new(*args))
|
347
|
+
def change_gc(*args) = write_request(X11::Form::ChangeGC.new(*args))
|
348
|
+
def change_save_set(...)= write_request(X11::Form::ChangeSaveSet.new(...))
|
349
|
+
def reparent_window(window, parent, x, y, save: true)
|
350
|
+
# You so almost always want this that it should've been a single request
|
351
|
+
change_save_set(0, window) if save
|
352
|
+
write_request(X11::Form::ReparentWindow.new(window, parent, x,y))
|
353
|
+
end
|
354
|
+
|
355
|
+
def map_window(*args) = write_request(X11::Form::MapWindow.new(*args))
|
356
|
+
def unmap_window(*args) = write_request(X11::Form::UnmapWindow.new(*args))
|
357
|
+
|
358
|
+
def u8(*args) = args.pack("c*")
|
359
|
+
def u16(*args) = args.pack("v*")
|
360
|
+
def u32(*args) = args.pack("V*")
|
361
|
+
def atom_enum(val) = open_enum(val, {cardinal: Form::CardinalAtom, atom: Form::AtomAtom, window: Form::WindowAtom})
|
362
|
+
def window(*args)
|
363
|
+
args.each {|a| raise "Window expected" if a.nil? }
|
364
|
+
u32(*args)
|
365
|
+
end
|
366
|
+
|
367
|
+
def open_enum(val, map) = (map[val].nil? ? val : map[val])
|
368
|
+
|
369
|
+
def set_input_focus(revert_to, focus, time=:now)
|
370
|
+
# FIXME: This is an experiment.
|
371
|
+
# Upside: Simpler. Downside: Doesn't work server-side.
|
372
|
+
#
|
373
|
+
revert_to = open_enum(revert_to, {none: 0, pointer_root: 1, parent: 2})
|
374
|
+
focus = open_enum(focus, {none: 0, pointer_root: 1 })
|
375
|
+
time = open_enum(time, {current_time: 0, now: 0})
|
376
|
+
write_packet(u8(42,revert_to), u16(3), window(focus), u32(time))
|
377
|
+
end
|
378
|
+
|
379
|
+
def grab_key(owner_events, grab_window, modifiers, keycode, pointer_mode, keyboard_mode)
|
380
|
+
write_request(X11::Form::GrabKey.new(
|
381
|
+
owner_events,
|
382
|
+
grab_window,
|
383
|
+
modifiers,
|
384
|
+
keycode,
|
385
|
+
pointer_mode == :async ? 1 : 0,
|
386
|
+
keyboard_mode == :async ? 1 : 0
|
387
|
+
))
|
235
388
|
end
|
236
389
|
|
237
|
-
def
|
238
|
-
|
390
|
+
def grab_button(owner_events, grab_window, event_mask, pointer_mode,
|
391
|
+
keyboard_mode, confine_to, cursor, button, modifiers)
|
392
|
+
write_request(X11::Form::GrabButton.new(
|
393
|
+
owner_events, grab_window, event_mask,
|
394
|
+
pointer_mode == :async ? 1 : 0,
|
395
|
+
keyboard_mode == :async ? 1 : 0,
|
396
|
+
confine_to.to_i, cursor.to_i, button, modifiers)
|
397
|
+
)
|
239
398
|
end
|
240
399
|
|
241
|
-
def
|
242
|
-
|
400
|
+
def configure_window(window, x: nil, y: nil, width: nil, height: nil,
|
401
|
+
border_width: nil, sibling: nil, stack_mode: nil)
|
402
|
+
|
403
|
+
mask = 0
|
404
|
+
values = []
|
405
|
+
|
406
|
+
if x
|
407
|
+
mask |= 0x001
|
408
|
+
values << x
|
409
|
+
end
|
410
|
+
|
411
|
+
if y
|
412
|
+
mask |= 0x002
|
413
|
+
values << y
|
414
|
+
end
|
415
|
+
|
416
|
+
if width
|
417
|
+
mask |= 0x004
|
418
|
+
values << width
|
419
|
+
end
|
420
|
+
|
421
|
+
if height
|
422
|
+
mask |= 0x008
|
423
|
+
values << height
|
424
|
+
end
|
425
|
+
|
426
|
+
if border_width
|
427
|
+
mask |= 0x010
|
428
|
+
values << border_width
|
429
|
+
end
|
430
|
+
|
431
|
+
if sibling
|
432
|
+
mask |= 0x020
|
433
|
+
values << sibling
|
434
|
+
end
|
435
|
+
|
436
|
+
if stack_mode
|
437
|
+
mask |= 0x040
|
438
|
+
values << case stack_mode
|
439
|
+
when :above then 0
|
440
|
+
when :below then 1
|
441
|
+
when :top_if then 2
|
442
|
+
when :bottom_if then 3
|
443
|
+
when :opposite then 4
|
444
|
+
else raise "Unknown stack_mode #{stack_mode.inspect}"
|
445
|
+
end
|
446
|
+
end
|
447
|
+
write_request(X11::Form::ConfigureWindow.new(window, mask, values))
|
243
448
|
end
|
244
449
|
|
245
450
|
|
@@ -265,29 +470,12 @@ module X11
|
|
265
470
|
gc
|
266
471
|
end
|
267
472
|
|
268
|
-
def put_image(*args)
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
def
|
273
|
-
|
274
|
-
end
|
275
|
-
|
276
|
-
def copy_area(*args)
|
277
|
-
write_request(X11::Form::CopyArea.new(*args))
|
278
|
-
end
|
279
|
-
|
280
|
-
def image_text8(*args)
|
281
|
-
write_request(X11::Form::ImageText8.new(*args))
|
282
|
-
end
|
283
|
-
|
284
|
-
def image_text16(*args)
|
285
|
-
write_request(X11::Form::ImageText16.new(*args))
|
286
|
-
end
|
287
|
-
|
288
|
-
def poly_fill_rectangle(*args)
|
289
|
-
write_request(X11::Form::PolyFillRectangle.new(*args))
|
290
|
-
end
|
473
|
+
def put_image(*args) = write_request(X11::Form::PutImage.new(*args))
|
474
|
+
def clear_area(*args) = write_request(X11::Form::ClearArea.new(*args))
|
475
|
+
def copy_area(*args) = write_request(X11::Form::CopyArea.new(*args))
|
476
|
+
def image_text8(*args) = write_request(X11::Form::ImageText8.new(*args))
|
477
|
+
def image_text16(*args)= write_request(X11::Form::ImageText16.new(*args))
|
478
|
+
def poly_fill_rectangle(*args) = write_request(X11::Form::PolyFillRectangle.new(*args))
|
291
479
|
|
292
480
|
def create_pixmap(depth, drawable, w,h)
|
293
481
|
pid = new_id
|
@@ -329,7 +517,7 @@ module X11
|
|
329
517
|
s.depths.map do |d|
|
330
518
|
d.visuals.map {|v| v.visual == visual ? v : nil }
|
331
519
|
end
|
332
|
-
end.flatten.compact.first
|
520
|
+
end.flatten.compact.first&.format
|
333
521
|
end
|
334
522
|
|
335
523
|
def render_find_standard_format(sym)
|
@@ -411,7 +599,12 @@ module X11
|
|
411
599
|
auth = Auth.new
|
412
600
|
auth_info = auth.get_by_hostname(host||"localhost", family, display_id)
|
413
601
|
|
414
|
-
|
602
|
+
if auth_info
|
603
|
+
auth_name, auth_data = auth_info.auth_name, auth_info.auth_data
|
604
|
+
else
|
605
|
+
auth_name = ""
|
606
|
+
auth_data = ""
|
607
|
+
end
|
415
608
|
p [auth_name, auth_data]
|
416
609
|
|
417
610
|
handshake = Form::ClientHandshake.new(
|
data/lib/X11/form.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
|
3
2
|
module X11
|
4
3
|
module Form
|
@@ -82,14 +81,14 @@ module X11
|
|
82
81
|
when :unused
|
83
82
|
sz = s.size.respond_to?(:call) ? s.size.call(self) : s.size
|
84
83
|
"\x00" * sz
|
85
|
-
when :length
|
84
|
+
when :length, :format_length
|
86
85
|
#p [s,value]
|
87
86
|
#p [value.size]
|
88
87
|
s.type_klass.pack(value.size)
|
89
88
|
when :string
|
90
89
|
s.type_klass.pack(value)
|
91
90
|
when :list
|
92
|
-
value.collect do |obj|
|
91
|
+
Array(value).collect do |obj|
|
93
92
|
if obj.is_a?(BaseForm)
|
94
93
|
obj.to_packet
|
95
94
|
else
|
@@ -128,8 +127,17 @@ module X11
|
|
128
127
|
when :length
|
129
128
|
size = s.type_klass.unpack( socket.read(s.type_klass.size) )
|
130
129
|
lengths[s.name] = size
|
130
|
+
when :format_length
|
131
|
+
size = s.type_klass.unpack( socket.read(s.type_klass.size) )
|
132
|
+
lengths[s.name] = case form.format
|
133
|
+
when 8 then size
|
134
|
+
when 16 then size*2
|
135
|
+
when 32 then size*4
|
136
|
+
else 0
|
137
|
+
end
|
131
138
|
when :string
|
132
|
-
|
139
|
+
len = lengths[s.name]
|
140
|
+
val = s.type_klass.unpack(socket, len)
|
133
141
|
form.instance_variable_set("@#{s.name}", val)
|
134
142
|
when :list
|
135
143
|
len = lengths[s.name]
|
@@ -178,12 +186,14 @@ module X11
|
|
178
186
|
end
|
179
187
|
|
180
188
|
def fields
|
181
|
-
super+Array(@structs).dup.delete_if{|s| s.type == :unused or s.type == :length }
|
189
|
+
super+Array(@structs).dup.delete_if{|s| s.type == :unused or s.type == :length or s.type == :format_length}
|
182
190
|
end
|
183
191
|
end
|
184
192
|
end
|
185
193
|
|
194
|
+
AtomAtom=4
|
186
195
|
CardinalAtom=6
|
196
|
+
WindowAtom=33
|
187
197
|
|
188
198
|
##
|
189
199
|
## X11 Packet Defintions
|
@@ -248,9 +258,9 @@ module X11
|
|
248
258
|
end
|
249
259
|
|
250
260
|
class DisplayInfo < BaseForm
|
251
|
-
field :release_number,
|
252
|
-
field :resource_id_base,
|
253
|
-
field :resource_id_mask,
|
261
|
+
field :release_number, Uint32
|
262
|
+
field :resource_id_base, Uint32
|
263
|
+
field :resource_id_mask, Uint32
|
254
264
|
field :motion_buffer_size, Uint32
|
255
265
|
field :vendor, Uint16, :length
|
256
266
|
field :maximum_request_length, Uint16
|
@@ -259,11 +269,11 @@ module X11
|
|
259
269
|
field :image_byte_order, Signifigance
|
260
270
|
field :bitmap_bit_order, Signifigance
|
261
271
|
field :bitmap_format_scanline_unit, Uint8
|
262
|
-
field :bitmap_format_scanline_pad,
|
272
|
+
field :bitmap_format_scanline_pad, Uint8
|
263
273
|
field :min_keycode, KeyCode
|
264
274
|
field :max_keycode, KeyCode
|
265
275
|
unused 4
|
266
|
-
field :vendor,
|
276
|
+
field :vendor, String8, :string
|
267
277
|
field :formats, FormatInfo, :list
|
268
278
|
field :screens, ScreenInfo, :list
|
269
279
|
end
|
@@ -288,13 +298,13 @@ module X11
|
|
288
298
|
# XRender structures
|
289
299
|
|
290
300
|
class DirectFormat < BaseForm
|
291
|
-
field :red,
|
292
|
-
field :red_mask,
|
293
|
-
field :green,
|
301
|
+
field :red, Uint16
|
302
|
+
field :red_mask, Uint16
|
303
|
+
field :green, Uint16
|
294
304
|
field :green_mask, Uint16
|
295
|
-
field :blue,
|
296
|
-
field :blue_mask,
|
297
|
-
field :alpha,
|
305
|
+
field :blue, Uint16
|
306
|
+
field :blue_mask, Uint16
|
307
|
+
field :alpha, Uint16
|
298
308
|
field :alpha_mask, Uint16
|
299
309
|
end
|
300
310
|
|
@@ -329,20 +339,38 @@ module X11
|
|
329
339
|
# Requests
|
330
340
|
|
331
341
|
CopyFromParent = 0
|
332
|
-
InputOutput
|
333
|
-
InputOnly
|
342
|
+
InputOutput = 1
|
343
|
+
InputOnly = 2
|
334
344
|
|
335
|
-
|
345
|
+
CWBackPixmap = 0x0001
|
346
|
+
CWBackPixel = 0x0002
|
347
|
+
CWBorderPixmap= 0x0004
|
336
348
|
CWBorderPixel = 0x0008
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
349
|
+
CWBitGravity = 0x0010
|
350
|
+
CWWinGravity = 0x0020
|
351
|
+
CWBackingStore = 0x0040
|
352
|
+
CWBackingPlanes = 0x0080
|
353
|
+
CWBackingPixel = 0x0100
|
354
|
+
CWOverrideRedirect = 0x0200
|
355
|
+
CWSaveUnder = 0x0400
|
356
|
+
CWEventMask = 0x0800
|
357
|
+
CWColorMap = 0x2000
|
358
|
+
|
359
|
+
KeyPressMask = 0x000001
|
360
|
+
KeyReleaseMask = 0x000002
|
361
|
+
ButtonPressMask = 0x000004
|
362
|
+
ButtonReleaseMask = 0x000008
|
363
|
+
EnterWindowMask = 0x000010
|
364
|
+
LeaveWindowMask = 0x000020
|
365
|
+
PointerMotionMask = 0x000040
|
366
|
+
PointerMotionHintMask = 0x000080
|
367
|
+
Button1MotionMask = 0x000100
|
368
|
+
ExposureMask = 0x008000
|
369
|
+
StructureNotifyMask = 0x020000
|
370
|
+
SubstructureNotifyMask = 0x080000
|
371
|
+
SubstructureRedirectMask=0x100000
|
372
|
+
FocusChangeMask = 0x200000
|
373
|
+
PropertyChangeMask = 0x400000
|
346
374
|
|
347
375
|
class CreateWindow < BaseForm
|
348
376
|
field :opcode, Uint8, value: 1
|
@@ -361,6 +389,68 @@ module X11
|
|
361
389
|
field :value_list, Uint32, :list
|
362
390
|
end
|
363
391
|
|
392
|
+
class ChangeWindowAttributes < BaseForm
|
393
|
+
field :opcode, Uint8, value: 2
|
394
|
+
unused 1
|
395
|
+
field :request_length, Uint16, value: ->(cw) { 3 + cw.value_list.length }
|
396
|
+
field :window, Window
|
397
|
+
field :value_mask, Bitmask
|
398
|
+
field :value_list, Uint32, :list
|
399
|
+
end
|
400
|
+
|
401
|
+
class GetWindowAttributes < BaseForm
|
402
|
+
field :opcode, Uint8, value: 3
|
403
|
+
unused 1
|
404
|
+
field :request_length, Uint16, value: 2
|
405
|
+
field :window, Window
|
406
|
+
end
|
407
|
+
|
408
|
+
class WindowAttributes < BaseForm
|
409
|
+
field :reply, Uint8, value: 1
|
410
|
+
field :backing_store, Uint8
|
411
|
+
field :sequence_number, Uint16
|
412
|
+
field :reply_length, Uint32
|
413
|
+
field :visual, VisualID
|
414
|
+
field :wclass, Uint16
|
415
|
+
field :bit_gravity, Uint8
|
416
|
+
field :win_gravity, Uint8
|
417
|
+
field :backing_planes, Uint32
|
418
|
+
field :backing_pixel, Uint32
|
419
|
+
field :save_under, Bool
|
420
|
+
field :map_is_installed, Bool
|
421
|
+
field :map_state, Uint8
|
422
|
+
field :override_redirect, Bool
|
423
|
+
field :colormap, Colormap
|
424
|
+
field :all_event_masks, Uint32
|
425
|
+
field :your_event_masks, Uint32
|
426
|
+
field :do_not_propagate_mask, Uint16
|
427
|
+
unused 2
|
428
|
+
end
|
429
|
+
|
430
|
+
class DestroyWindow < BaseForm
|
431
|
+
field :opcode, Uint8, value: 4
|
432
|
+
unused 1
|
433
|
+
field :request_length, Uint16, value: 2
|
434
|
+
field :window, Window
|
435
|
+
end
|
436
|
+
|
437
|
+
class ChangeSaveSet < BaseForm
|
438
|
+
field :opcode, Uint8, value: 6
|
439
|
+
field :mode, Uint8
|
440
|
+
field :request_length, Uint16, value: 2
|
441
|
+
field :window, Window
|
442
|
+
end
|
443
|
+
|
444
|
+
class ReparentWindow < BaseForm
|
445
|
+
field :opcode, Uint8, value: 7
|
446
|
+
unused 1
|
447
|
+
field :request_length, Uint16, value: 4
|
448
|
+
field :window, Window
|
449
|
+
field :parent, Window
|
450
|
+
field :x, Int16
|
451
|
+
field :y, Int16
|
452
|
+
end
|
453
|
+
|
364
454
|
class MapWindow < BaseForm
|
365
455
|
field :opcode, Uint8, value: 8
|
366
456
|
unused 1
|
@@ -368,6 +458,63 @@ module X11
|
|
368
458
|
field :window, Window
|
369
459
|
end
|
370
460
|
|
461
|
+
class UnmapWindow < BaseForm
|
462
|
+
field :opcode, Uint8, value: 10
|
463
|
+
unused 1
|
464
|
+
field :request_length, Uint16, value: 2
|
465
|
+
field :window, Window
|
466
|
+
end
|
467
|
+
|
468
|
+
class ConfigureWindow < BaseForm
|
469
|
+
field :opcode, Uint8, value: 12
|
470
|
+
unused 1
|
471
|
+
field :request_length, Uint16, value: ->(cw) { 3 + cw.values.length }
|
472
|
+
field :window, Window
|
473
|
+
field :value_mask, Uint16
|
474
|
+
unused 2
|
475
|
+
field :values, Uint32, :list
|
476
|
+
end
|
477
|
+
|
478
|
+
class GetGeometry < BaseForm
|
479
|
+
field :opcode, Uint8, value: 14
|
480
|
+
unused 1
|
481
|
+
field :request_length, Uint16, value: 2
|
482
|
+
field :drawable, Drawable
|
483
|
+
end
|
484
|
+
|
485
|
+
class Geometry < BaseForm
|
486
|
+
field :reply, Uint8, value: 1
|
487
|
+
field :depth, Uint8
|
488
|
+
field :sequence_number, Uint16
|
489
|
+
field :reply_length, Uint32
|
490
|
+
field :root, Window
|
491
|
+
field :x, Int16
|
492
|
+
field :y, Int16
|
493
|
+
field :width, Uint16
|
494
|
+
field :height, Uint16
|
495
|
+
field :border_width, Uint16
|
496
|
+
unused 10
|
497
|
+
end
|
498
|
+
|
499
|
+
class QueryTree < BaseForm
|
500
|
+
field :opcode, Uint8, value: 15
|
501
|
+
unused 1
|
502
|
+
field :request_length, Uint16, value: 2
|
503
|
+
field :window, Window
|
504
|
+
end
|
505
|
+
|
506
|
+
class QueryTreeReply < BaseForm
|
507
|
+
field :reply, Uint8, value: 1
|
508
|
+
unused 1
|
509
|
+
field :sequence_number, Uint16
|
510
|
+
field :reply_length, Uint32
|
511
|
+
field :root, Window
|
512
|
+
field :parent, Window
|
513
|
+
field :children, Uint16, :length
|
514
|
+
unused 14
|
515
|
+
field :children, Window, :list
|
516
|
+
end
|
517
|
+
|
371
518
|
class InternAtom < BaseForm
|
372
519
|
field :opcode, Uint8, value: 16
|
373
520
|
field :only_if_exists, Bool
|
@@ -393,6 +540,22 @@ module X11
|
|
393
540
|
unused 20
|
394
541
|
end
|
395
542
|
|
543
|
+
class GetAtomName < BaseForm
|
544
|
+
field :opcode, Uint8, value: 17
|
545
|
+
unused 1
|
546
|
+
field :request_length, Uint16, value: 2
|
547
|
+
field :atom, Atom
|
548
|
+
end
|
549
|
+
|
550
|
+
class AtomName < Reply
|
551
|
+
unused 1
|
552
|
+
field :sequence_number, Uint16
|
553
|
+
field :reply_length, Uint32
|
554
|
+
field :name, Uint16, :length
|
555
|
+
unused 22
|
556
|
+
field :name, String8, :string
|
557
|
+
end
|
558
|
+
|
396
559
|
Replace = 0
|
397
560
|
Prepend = 1
|
398
561
|
Append = 2
|
@@ -409,12 +572,60 @@ module X11
|
|
409
572
|
field :type, Atom
|
410
573
|
field :format, Uint8
|
411
574
|
unused 3
|
412
|
-
field :data, Uint32, value: ->(cp) {
|
413
|
-
cp.data.length / 4
|
414
|
-
}
|
575
|
+
field :data, Uint32, value: ->(cp) { cp.data.length / (cp.format/8) }
|
415
576
|
field :data, Uint8, :list
|
416
577
|
end
|
417
578
|
|
579
|
+
class GetProperty < BaseForm
|
580
|
+
field :opcode, Uint8, value: 20
|
581
|
+
field :delete, Bool
|
582
|
+
field :request_length, Uint16, value: 6
|
583
|
+
field :window, Window
|
584
|
+
field :property, Atom
|
585
|
+
field :type, Atom
|
586
|
+
field :long_offset, Uint32
|
587
|
+
field :long_length, Uint32
|
588
|
+
end
|
589
|
+
|
590
|
+
class Property < BaseForm
|
591
|
+
field :reply, Uint8, value: 1
|
592
|
+
field :format, Uint8
|
593
|
+
field :sequence_number, Uint16
|
594
|
+
field :reply_length, Uint32
|
595
|
+
field :type, Atom
|
596
|
+
field :bytes_after, Uint32
|
597
|
+
field :value, Uint32, :format_length
|
598
|
+
unused 12
|
599
|
+
field :value, String8, :string
|
600
|
+
end
|
601
|
+
|
602
|
+
class GrabButton < BaseForm
|
603
|
+
field :opcode, Uint8, value: 28
|
604
|
+
field :owner_events, Bool
|
605
|
+
field :request_length, Uint16, value: 6
|
606
|
+
field :grab_window, Window
|
607
|
+
field :event_mask, Uint16
|
608
|
+
field :pointer_mode, Uint8
|
609
|
+
field :keyboard_mode, Uint8
|
610
|
+
field :confine_to, Window
|
611
|
+
field :cursor, Cursor
|
612
|
+
field :button, Uint8
|
613
|
+
unused 1
|
614
|
+
field :modifiers, Uint16
|
615
|
+
end
|
616
|
+
|
617
|
+
class GrabKey < BaseForm
|
618
|
+
field :opcode, Uint8, value: 33
|
619
|
+
field :owner_event, Bool
|
620
|
+
field :request_length, Uint16, value: 4
|
621
|
+
field :grab_window, Window
|
622
|
+
field :modifiers, Uint16
|
623
|
+
field :keycode, Uint8
|
624
|
+
field :pointer_mode, Uint8
|
625
|
+
field :keyboard_mode, Uint8
|
626
|
+
unused 3
|
627
|
+
end
|
628
|
+
|
418
629
|
class OpenFont < BaseForm
|
419
630
|
field :opcode, Uint8, value: 45
|
420
631
|
unused 1
|
@@ -516,11 +727,11 @@ module X11
|
|
516
727
|
field :src_drawable, Drawable
|
517
728
|
field :dst_drawable, Drawable
|
518
729
|
field :gc, Gcontext
|
519
|
-
field :src_x,
|
520
|
-
field :src_y,
|
521
|
-
field :dst_x,
|
522
|
-
field :dst_y,
|
523
|
-
field :width,
|
730
|
+
field :src_x, Uint16
|
731
|
+
field :src_y, Uint16
|
732
|
+
field :dst_x, Uint16
|
733
|
+
field :dst_y, Uint16
|
734
|
+
field :width, Uint16
|
524
735
|
field :height, Uint16
|
525
736
|
end
|
526
737
|
|
@@ -652,7 +863,7 @@ module X11
|
|
652
863
|
field :sequence_number, Uint16
|
653
864
|
end
|
654
865
|
|
655
|
-
class
|
866
|
+
class InputEvent < SimpleEvent
|
656
867
|
field :time, Uint32
|
657
868
|
field :root, Window
|
658
869
|
field :event, Window
|
@@ -662,6 +873,32 @@ module X11
|
|
662
873
|
field :event_x, Int16
|
663
874
|
field :event_y, Int16
|
664
875
|
field :state, Uint16
|
876
|
+
end
|
877
|
+
|
878
|
+
class EnterLeaveNotify < InputEvent
|
879
|
+
field :mode, Uint8
|
880
|
+
field :same_screen_or_focus, Uint8
|
881
|
+
|
882
|
+
def same_screen = same_screen_or_focus.anybit?(0x02)
|
883
|
+
def focus = same_screen_or_focus.anybit?(0x01)
|
884
|
+
end
|
885
|
+
|
886
|
+
class EnterNotify < EnterLeaveNotify
|
887
|
+
end
|
888
|
+
|
889
|
+
class LeaveNotify < EnterLeaveNotify
|
890
|
+
end
|
891
|
+
|
892
|
+
class FocusIn < SimpleEvent
|
893
|
+
field :event, Window
|
894
|
+
field :mode, Uint8
|
895
|
+
unused 23
|
896
|
+
end
|
897
|
+
|
898
|
+
class FocusOut < FocusIn
|
899
|
+
end
|
900
|
+
|
901
|
+
class PressEvent < InputEvent
|
665
902
|
field :same_screen, Bool
|
666
903
|
unused 1
|
667
904
|
end
|
@@ -677,6 +914,34 @@ module X11
|
|
677
914
|
|
678
915
|
class MotionNotify < PressEvent
|
679
916
|
end
|
917
|
+
|
918
|
+
class ButtonRelease < PressEvent
|
919
|
+
end
|
920
|
+
|
921
|
+
class ReparentNotify < SimpleEvent
|
922
|
+
field :event, Window
|
923
|
+
field :window, Window
|
924
|
+
field :parent, Window
|
925
|
+
field :x, Int16
|
926
|
+
field :y, Int16
|
927
|
+
field :override_redirect, Bool
|
928
|
+
unused 11
|
929
|
+
end
|
930
|
+
|
931
|
+
class ConfigureRequest < Event # 23
|
932
|
+
field :stack_mode, Uint8
|
933
|
+
field :sequence_number, Uint16
|
934
|
+
field :parent, Window
|
935
|
+
field :window, Window
|
936
|
+
field :sibling, Window
|
937
|
+
field :x, Int16
|
938
|
+
field :y, Int16
|
939
|
+
field :width, Uint16
|
940
|
+
field :height, Uint16
|
941
|
+
field :border_width, Uint16
|
942
|
+
field :value_mask, Uint16
|
943
|
+
unused 4
|
944
|
+
end
|
680
945
|
|
681
946
|
class Expose < SimpleEvent
|
682
947
|
field :window, Window
|
@@ -695,14 +960,51 @@ module X11
|
|
695
960
|
unused 21
|
696
961
|
end
|
697
962
|
|
963
|
+
class CreateNotify < SimpleEvent # 16
|
964
|
+
field :parent, Window
|
965
|
+
field :window, Window
|
966
|
+
field :x, Int16
|
967
|
+
field :y, Int16
|
968
|
+
field :width, Uint16
|
969
|
+
field :height, Uint16
|
970
|
+
field :border_width, Uint16
|
971
|
+
field :override_redirect, Bool
|
972
|
+
end
|
973
|
+
|
974
|
+
class DestroyNotify < Event
|
975
|
+
unused 1
|
976
|
+
field :sequence_number, Uint16
|
977
|
+
field :event, Window
|
978
|
+
field :window, Window
|
979
|
+
unused 20
|
980
|
+
end
|
981
|
+
|
982
|
+
class UnmapNotify < Event
|
983
|
+
unused 1
|
984
|
+
field :sequence_number, Uint16
|
985
|
+
field :event, Window
|
986
|
+
field :window, Window
|
987
|
+
field :from_configure, Bool
|
988
|
+
unused 19
|
989
|
+
end
|
990
|
+
|
698
991
|
class MapNotify < Event
|
699
992
|
unused 1
|
700
993
|
field :sequence_number, Uint16
|
701
994
|
field :event, Window
|
995
|
+
field :window, Window
|
702
996
|
field :override_redirect, Bool
|
703
997
|
unused 19
|
704
998
|
end
|
705
999
|
|
1000
|
+
class MapRequest < Event
|
1001
|
+
unused 1
|
1002
|
+
field :sequence_number, Uint16
|
1003
|
+
field :parent, Window
|
1004
|
+
field :window, Window
|
1005
|
+
unused 20
|
1006
|
+
end
|
1007
|
+
|
706
1008
|
class ConfigureNotify < Event
|
707
1009
|
unused 1
|
708
1010
|
field :sequence_number, Uint16
|
@@ -717,6 +1019,24 @@ module X11
|
|
717
1019
|
unused 5
|
718
1020
|
end
|
719
1021
|
|
1022
|
+
class ClientMessage < Event
|
1023
|
+
field :format, Uint8
|
1024
|
+
field :sequence_number, Uint16
|
1025
|
+
field :window, Window
|
1026
|
+
field :type, Atom
|
1027
|
+
field :data, X11::Type::Message
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
class PropertyNotify < Event # 28
|
1031
|
+
unused 1
|
1032
|
+
field :sequence_number, Uint16
|
1033
|
+
field :window, Window
|
1034
|
+
field :atom, Atom
|
1035
|
+
field :time, Uint32
|
1036
|
+
field :state, Uint8
|
1037
|
+
unused 15
|
1038
|
+
end
|
1039
|
+
|
720
1040
|
|
721
1041
|
# XRender extension
|
722
1042
|
# From https://cgit.freedesktop.org/xorg/proto/renderproto/tree/renderproto.h
|
data/lib/X11/keysyms.rb
CHANGED
@@ -114,13 +114,18 @@ module X11
|
|
114
114
|
0xff9d => :XK_KP_Begin,
|
115
115
|
0xff9e => :XK_KP_Insert,
|
116
116
|
0xff9f => :XK_KP_Delete,
|
117
|
-
0xffbd => :XK_KP_Equal,
|
118
117
|
0xffaa => :XK_KP_Multiply,
|
119
118
|
0xffab => :XK_KP_Add,
|
120
119
|
0xffac => :XK_KP_Separator,
|
121
120
|
0xffad => :XK_KP_Subtract,
|
122
121
|
0xffae => :XK_KP_Decimal,
|
123
122
|
0xffaf => :XK_KP_Divide,
|
123
|
+
0xffbd => :XK_KP_Equal,
|
124
|
+
0xffbe => :f1,
|
125
|
+
0xffbf => :f2,
|
126
|
+
0xffc0 => :f3,
|
127
|
+
0xffc1 => :f4, # And so on
|
128
|
+
|
124
129
|
|
125
130
|
0xffe1 => :XK_Shift_L,
|
126
131
|
0xffe2 => :XK_Shift_R,
|
data/lib/X11/type.rb
CHANGED
@@ -36,16 +36,23 @@ module X11
|
|
36
36
|
define "Uint8", "C", 1
|
37
37
|
define "Uint16", "S", 2
|
38
38
|
define "Uint32", "L", 4
|
39
|
+
|
40
|
+
define "Message", "c*", 20
|
41
|
+
|
42
|
+
class Message
|
43
|
+
def self.pack(x) = x.b
|
44
|
+
def self.unpack(x) = x.b
|
45
|
+
def self.size = 20
|
46
|
+
def self.from_packet(sock) = sock.read(2).b
|
47
|
+
end
|
39
48
|
|
40
49
|
class String8
|
41
50
|
def self.pack(x)
|
42
51
|
x.force_encoding("ASCII-8BIT") + "\x00"*(-x.length & 3)
|
43
52
|
end
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
54
|
def self.unpack(socket, size)
|
55
|
+
raise "Expected size for String8" if size.nil?
|
49
56
|
val = socket.read(size)
|
50
57
|
unused_padding = (4 - (size % 4)) % 4
|
51
58
|
socket.read(unused_padding)
|
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.5
|
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: 2023-
|
12
|
+
date: 2023-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Pure Ruby X11 bindings
|
15
15
|
email:
|