pure-x11 0.0.2 → 0.0.5
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 +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:
|