rbgl 1.0.0 → 1.0.1
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/.rubocop.yml +3 -0
- data/CHANGELOG.md +7 -1
- data/README.md +130 -74
- data/Rakefile +7 -0
- data/bench/renderer_bench.rb +283 -0
- data/docs/.nojekyll +1 -0
- data/docs/index.html +38 -0
- data/examples/array_test.rb +1 -1
- data/examples/color_test.rb +1 -1
- data/examples/cube_spinning.rb +1 -1
- data/examples/gradient.rb +1 -1
- data/examples/multi_return_test.rb +1 -1
- data/examples/plasma.rb +1 -1
- data/examples/sphere_raymarch.rb +1 -1
- data/examples/triangle_window.rb +1 -1
- data/exe/rbgl +42 -0
- data/lib/rbgl/cli/doctor.rb +155 -0
- data/lib/rbgl/engine/buffer.rb +49 -8
- data/lib/rbgl/engine/clip_space_clipper.rb +23 -3
- data/lib/rbgl/engine/context.rb +23 -6
- data/lib/rbgl/engine/framebuffer.rb +137 -41
- data/lib/rbgl/engine/immutable_color.rb +32 -0
- data/lib/rbgl/engine/rasterizer/attribute_interpolator.rb +100 -10
- data/lib/rbgl/engine/rasterizer/line_renderer.rb +30 -14
- data/lib/rbgl/engine/rasterizer/point_renderer.rb +3 -3
- data/lib/rbgl/engine/rasterizer/triangle_renderer.rb +72 -23
- data/lib/rbgl/engine/rasterizer.rb +3 -20
- data/lib/rbgl/engine/shader/base_shader.rb +3 -7
- data/lib/rbgl/engine/shader/builtins.rb +13 -10
- data/lib/rbgl/engine/shader/dynamic_data.rb +18 -10
- data/lib/rbgl/engine/texture.rb +74 -50
- data/lib/rbgl/engine.rb +3 -1
- data/lib/rbgl/gui/backend.rb +12 -7
- data/lib/rbgl/gui/backend_factory.rb +7 -3
- data/lib/rbgl/gui/cocoa/backend.rb +50 -17
- data/lib/rbgl/gui/cocoa/key_mapper.rb +48 -0
- data/lib/rbgl/gui/event.rb +4 -2
- data/lib/rbgl/gui/file_backend/bmp_writer.rb +2 -2
- data/lib/rbgl/gui/file_backend/frame_writer.rb +7 -0
- data/lib/rbgl/gui/file_backend/png_writer.rb +18 -0
- data/lib/rbgl/gui/file_backend/ppm_writer.rb +1 -0
- data/lib/rbgl/gui/file_backend.rb +24 -6
- data/lib/rbgl/gui/wayland/backend.rb +127 -55
- data/lib/rbgl/gui/wayland/codec.rb +7 -11
- data/lib/rbgl/gui/wayland/connection.rb +137 -20
- data/lib/rbgl/gui/wayland/event_dispatcher.rb +103 -12
- data/lib/rbgl/gui/wayland/global_binder.rb +6 -4
- data/lib/rbgl/gui/wayland/input_mapper.rb +61 -0
- data/lib/rbgl/gui/wayland/protocol_objects/arguments.rb +14 -2
- data/lib/rbgl/gui/wayland/protocol_objects/seat.rb +115 -0
- data/lib/rbgl/gui/wayland/protocol_objects/shm.rb +23 -12
- data/lib/rbgl/gui/wayland/protocol_objects/xdg_shell.rb +15 -0
- data/lib/rbgl/gui/wayland/protocol_objects.rb +1 -0
- data/lib/rbgl/gui/window/render_loop.rb +71 -18
- data/lib/rbgl/gui/window.rb +39 -8
- data/lib/rbgl/gui/x11/atom_cache.rb +4 -1
- data/lib/rbgl/gui/x11/backend.rb +66 -28
- data/lib/rbgl/gui/x11/connection.rb +216 -86
- data/lib/rbgl/gui/x11/event_parser.rb +13 -2
- data/lib/rbgl/gui/x11/key_mapper.rb +48 -0
- data/lib/rbgl/gui/x11/pixel_encoder.rb +164 -0
- data/lib/rbgl/gui/x11/request_encoder.rb +29 -28
- data/lib/rbgl/gui/x11/setup_parser.rb +138 -0
- data/lib/rbgl/gui/x11/transport.rb +52 -2
- data/lib/rbgl/gui/x11/x_authority.rb +107 -0
- data/lib/rbgl/gui.rb +2 -5
- data/lib/rbgl/version.rb +1 -1
- metadata +36 -24
- data/examples/chemical_heartbeat.rb +0 -166
- data/examples/dark_transit.rb +0 -166
- data/examples/fractured_orb.rb +0 -428
- data/examples/fractured_orb_rb.rb +0 -598
- data/examples/hexagonal_flow.rb +0 -333
- data/examples/teapot.rb +0 -362
- data/examples/teapot_mcu.rb +0 -344
|
@@ -46,17 +46,18 @@ module RBGL
|
|
|
46
46
|
value_list << encode_event_mask(values[:event_mask])
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
[
|
|
50
|
-
depth,
|
|
49
|
+
data = [
|
|
51
50
|
wid,
|
|
52
51
|
parent,
|
|
53
52
|
x, y,
|
|
54
53
|
width, height,
|
|
55
54
|
border_width,
|
|
56
|
-
WINDOW_CLASSES.fetch(window_class
|
|
55
|
+
WINDOW_CLASSES.fetch(window_class),
|
|
57
56
|
visual,
|
|
58
57
|
mask
|
|
59
|
-
].pack("
|
|
58
|
+
].pack("VVs<s<vvvvVV") + value_list.pack("V*")
|
|
59
|
+
|
|
60
|
+
[depth, data]
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def create_gc_data(gc_id, drawable, values = {})
|
|
@@ -77,7 +78,7 @@ module RBGL
|
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
def put_image_data(format:, drawable:, gc:, width:, height:, dst_x:, dst_y:, depth:, data:)
|
|
80
|
-
format_byte = IMAGE_FORMATS.fetch(format
|
|
81
|
+
format_byte = IMAGE_FORMATS.fetch(format)
|
|
81
82
|
header = [
|
|
82
83
|
drawable,
|
|
83
84
|
gc,
|
|
@@ -85,22 +86,19 @@ module RBGL
|
|
|
85
86
|
dst_x, dst_y,
|
|
86
87
|
0,
|
|
87
88
|
depth
|
|
88
|
-
].pack("
|
|
89
|
+
].pack("VVvvs<s<CC") + "\x00\x00"
|
|
89
90
|
|
|
90
91
|
[format_byte, header, data]
|
|
91
92
|
end
|
|
92
93
|
|
|
93
94
|
def change_property_data(window, property_atom, type_atom, data, mode: :replace, format: 8)
|
|
94
95
|
data_bytes, value_count = pack_property_data(data, format)
|
|
95
|
-
request = [
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
].pack("VVVCV") + "\x00\x00\x00" + pad_to_4(data_bytes)
|
|
102
|
-
|
|
103
|
-
[PROPERTY_MODES.fetch(mode, 0), request]
|
|
96
|
+
request = [window, property_atom, type_atom, format].pack("VVVC") +
|
|
97
|
+
"\x00\x00\x00" +
|
|
98
|
+
[value_count].pack("V") +
|
|
99
|
+
pad_to_4(data_bytes)
|
|
100
|
+
|
|
101
|
+
[PROPERTY_MODES.fetch(mode), request]
|
|
104
102
|
end
|
|
105
103
|
|
|
106
104
|
def intern_atom_data(name)
|
|
@@ -108,24 +106,17 @@ module RBGL
|
|
|
108
106
|
end
|
|
109
107
|
|
|
110
108
|
def request_packet(opcode, data, extra = 0)
|
|
111
|
-
|
|
112
|
-
header = [opcode, extra, length].pack("CCv")
|
|
113
|
-
padding = "\x00" * (length * 4 - 4 - data.bytesize)
|
|
114
|
-
header + data + padding
|
|
109
|
+
encode_packet(opcode, extra, data)
|
|
115
110
|
end
|
|
116
111
|
|
|
117
112
|
def request_packet_with_data(opcode, extra, header_data, bulk_data)
|
|
118
|
-
|
|
119
|
-
length = (4 + total_data.bytesize + 3) / 4
|
|
120
|
-
header = [opcode, extra, length].pack("CCv")
|
|
121
|
-
padding = "\x00" * (length * 4 - 4 - total_data.bytesize)
|
|
122
|
-
header + total_data + padding
|
|
113
|
+
encode_packet(opcode, extra, header_data + bulk_data)
|
|
123
114
|
end
|
|
124
115
|
|
|
125
116
|
def pack_property_data(data, format)
|
|
126
117
|
case format
|
|
127
118
|
when 8
|
|
128
|
-
bytes = data.to_s
|
|
119
|
+
bytes = data.to_s.b
|
|
129
120
|
[bytes, bytes.bytesize]
|
|
130
121
|
when 16
|
|
131
122
|
values = Array(data)
|
|
@@ -139,14 +130,24 @@ module RBGL
|
|
|
139
130
|
end
|
|
140
131
|
|
|
141
132
|
def pad_to_4(str)
|
|
142
|
-
|
|
143
|
-
|
|
133
|
+
bytes = str.b
|
|
134
|
+
padding = (4 - (bytes.bytesize % 4)) % 4
|
|
135
|
+
bytes + ("\x00" * padding)
|
|
144
136
|
end
|
|
145
137
|
|
|
146
138
|
private
|
|
147
139
|
|
|
140
|
+
def encode_packet(opcode, extra, data)
|
|
141
|
+
length = (4 + data.bytesize + 3) / 4
|
|
142
|
+
raise ArgumentError, "X11 request exceeds the 16-bit core protocol limit" if length > 65_535
|
|
143
|
+
|
|
144
|
+
header = [opcode, extra, length].pack("CCv")
|
|
145
|
+
padding = "\x00" * ((length * 4) - 4 - data.bytesize)
|
|
146
|
+
header + data + padding
|
|
147
|
+
end
|
|
148
|
+
|
|
148
149
|
def encode_event_mask(events)
|
|
149
|
-
Array(events).sum { |event| EVENT_MASKS.fetch(event
|
|
150
|
+
Array(events).sum { |event| EVENT_MASKS.fetch(event) }
|
|
150
151
|
end
|
|
151
152
|
end
|
|
152
153
|
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBGL
|
|
4
|
+
module GUI
|
|
5
|
+
module X11
|
|
6
|
+
class SetupParser
|
|
7
|
+
Setup = Struct.new(
|
|
8
|
+
:resource_id_base,
|
|
9
|
+
:resource_id_mask,
|
|
10
|
+
:maximum_request_length,
|
|
11
|
+
:image_byte_order,
|
|
12
|
+
:minimum_keycode,
|
|
13
|
+
:maximum_keycode,
|
|
14
|
+
:pixmap_formats,
|
|
15
|
+
:screens,
|
|
16
|
+
keyword_init: true
|
|
17
|
+
)
|
|
18
|
+
PixmapFormat = Struct.new(:depth, :bits_per_pixel, :scanline_pad, keyword_init: true)
|
|
19
|
+
Depth = Struct.new(:depth, :visuals, keyword_init: true)
|
|
20
|
+
Screen = Struct.new(
|
|
21
|
+
:root,
|
|
22
|
+
:white_pixel,
|
|
23
|
+
:black_pixel,
|
|
24
|
+
:root_visual,
|
|
25
|
+
:root_depth,
|
|
26
|
+
:depths,
|
|
27
|
+
keyword_init: true
|
|
28
|
+
) do
|
|
29
|
+
def visuals
|
|
30
|
+
depths.flat_map(&:visuals)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
Visual = Struct.new(:id, :visual_class, :red_mask, :green_mask, :blue_mask, keyword_init: true)
|
|
34
|
+
|
|
35
|
+
def parse(data)
|
|
36
|
+
raise ArgumentError, "Truncated X11 setup response" if data.bytesize < 32
|
|
37
|
+
|
|
38
|
+
vendor_length = data.byteslice(16, 2).unpack1("v")
|
|
39
|
+
screen_count = data.getbyte(20)
|
|
40
|
+
format_count = data.getbyte(21)
|
|
41
|
+
format_offset = 32 + padded_length(vendor_length)
|
|
42
|
+
formats = parse_formats(data, format_offset, format_count)
|
|
43
|
+
screens = parse_screens(data, format_offset + (format_count * 8), screen_count)
|
|
44
|
+
|
|
45
|
+
Setup.new(
|
|
46
|
+
resource_id_base: data.byteslice(4, 4).unpack1("V"),
|
|
47
|
+
resource_id_mask: data.byteslice(8, 4).unpack1("V"),
|
|
48
|
+
maximum_request_length: data.byteslice(18, 2).unpack1("v"),
|
|
49
|
+
image_byte_order: parse_image_byte_order(data.getbyte(22)),
|
|
50
|
+
minimum_keycode: data.getbyte(26),
|
|
51
|
+
maximum_keycode: data.getbyte(27),
|
|
52
|
+
pixmap_formats: formats,
|
|
53
|
+
screens: screens
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def parse_formats(data, offset, count)
|
|
60
|
+
count.times.map do |index|
|
|
61
|
+
bytes = required_slice(data, offset + (index * 8), 8)
|
|
62
|
+
PixmapFormat.new(
|
|
63
|
+
depth: bytes.getbyte(0),
|
|
64
|
+
bits_per_pixel: bytes.getbyte(1),
|
|
65
|
+
scanline_pad: bytes.getbyte(2)
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def parse_screens(data, offset, count)
|
|
71
|
+
screens = []
|
|
72
|
+
count.times do
|
|
73
|
+
screen, offset = parse_screen(data, offset)
|
|
74
|
+
screens << screen
|
|
75
|
+
end
|
|
76
|
+
screens
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def parse_screen(data, offset)
|
|
80
|
+
header = required_slice(data, offset, 40)
|
|
81
|
+
depth_count = header.getbyte(39)
|
|
82
|
+
cursor = offset + 40
|
|
83
|
+
depths = []
|
|
84
|
+
|
|
85
|
+
depth_count.times do
|
|
86
|
+
depth_header = required_slice(data, cursor, 8)
|
|
87
|
+
depth_value = depth_header.getbyte(0)
|
|
88
|
+
visual_count = depth_header.byteslice(2, 2).unpack1("v")
|
|
89
|
+
cursor += 8
|
|
90
|
+
visuals = []
|
|
91
|
+
visual_count.times do
|
|
92
|
+
visuals << parse_visual(required_slice(data, cursor, 24))
|
|
93
|
+
cursor += 24
|
|
94
|
+
end
|
|
95
|
+
depths << Depth.new(depth: depth_value, visuals: visuals)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
screen = Screen.new(
|
|
99
|
+
root: header.byteslice(0, 4).unpack1("V"),
|
|
100
|
+
white_pixel: header.byteslice(8, 4).unpack1("V"),
|
|
101
|
+
black_pixel: header.byteslice(12, 4).unpack1("V"),
|
|
102
|
+
root_visual: header.byteslice(32, 4).unpack1("V"),
|
|
103
|
+
root_depth: header.getbyte(38),
|
|
104
|
+
depths: depths
|
|
105
|
+
)
|
|
106
|
+
[screen, cursor]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def parse_visual(bytes)
|
|
110
|
+
Visual.new(
|
|
111
|
+
id: bytes.byteslice(0, 4).unpack1("V"),
|
|
112
|
+
visual_class: bytes.getbyte(4),
|
|
113
|
+
red_mask: bytes.byteslice(8, 4).unpack1("V"),
|
|
114
|
+
green_mask: bytes.byteslice(12, 4).unpack1("V"),
|
|
115
|
+
blue_mask: bytes.byteslice(16, 4).unpack1("V")
|
|
116
|
+
)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def required_slice(data, offset, length)
|
|
120
|
+
bytes = data.byteslice(offset, length)
|
|
121
|
+
raise ArgumentError, "Truncated X11 setup response" unless bytes&.bytesize == length
|
|
122
|
+
|
|
123
|
+
bytes
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def padded_length(length)
|
|
127
|
+
(length + 3) & ~3
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def parse_image_byte_order(value)
|
|
131
|
+
{ 0 => :little, 1 => :big }.fetch(value) do
|
|
132
|
+
raise ArgumentError, "Unsupported X11 image byte order: #{value}"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "io/wait"
|
|
4
|
+
|
|
3
5
|
module RBGL
|
|
4
6
|
module GUI
|
|
5
7
|
module X11
|
|
6
8
|
class Transport
|
|
9
|
+
READ_CHUNK_SIZE = 16_384
|
|
10
|
+
|
|
7
11
|
attr_reader :socket
|
|
8
12
|
|
|
9
13
|
def initialize(socket)
|
|
10
14
|
@socket = socket
|
|
15
|
+
@read_buffer = String.new(encoding: Encoding::BINARY)
|
|
11
16
|
end
|
|
12
17
|
|
|
13
18
|
def write(data)
|
|
@@ -15,7 +20,12 @@ module RBGL
|
|
|
15
20
|
end
|
|
16
21
|
|
|
17
22
|
def read(length)
|
|
18
|
-
|
|
23
|
+
read_exact(length)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def read_exact(length, timeout: nil)
|
|
27
|
+
fill_buffer(length, timeout: timeout)
|
|
28
|
+
@read_buffer.slice!(0, length)
|
|
19
29
|
end
|
|
20
30
|
|
|
21
31
|
def flush
|
|
@@ -23,7 +33,47 @@ module RBGL
|
|
|
23
33
|
end
|
|
24
34
|
|
|
25
35
|
def pending
|
|
26
|
-
|
|
36
|
+
read_available
|
|
37
|
+
return 0 if @read_buffer.bytesize < 32
|
|
38
|
+
|
|
39
|
+
packet_size = 32
|
|
40
|
+
if @read_buffer.getbyte(0) == 1
|
|
41
|
+
packet_size += @read_buffer.byteslice(4, 4).unpack1("V") * 4
|
|
42
|
+
end
|
|
43
|
+
@read_buffer.bytesize >= packet_size ? 1 : 0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def close
|
|
47
|
+
@socket.close unless @socket.closed?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def fill_buffer(length, timeout:)
|
|
53
|
+
deadline = timeout && (monotonic_time + timeout)
|
|
54
|
+
|
|
55
|
+
while @read_buffer.bytesize < length
|
|
56
|
+
wait = deadline && [deadline - monotonic_time, 0].max
|
|
57
|
+
raise IO::EAGAINWaitReadable unless @socket.wait_readable(wait)
|
|
58
|
+
|
|
59
|
+
read_available
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def read_available
|
|
64
|
+
return unless @socket.wait_readable(0)
|
|
65
|
+
|
|
66
|
+
loop do
|
|
67
|
+
chunk = @socket.read_nonblock(READ_CHUNK_SIZE, exception: false)
|
|
68
|
+
break if chunk == :wait_readable
|
|
69
|
+
raise EOFError, "X11 server closed the connection" if chunk.nil?
|
|
70
|
+
|
|
71
|
+
@read_buffer << chunk
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def monotonic_time
|
|
76
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
27
77
|
end
|
|
28
78
|
end
|
|
29
79
|
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "ipaddr"
|
|
5
|
+
|
|
6
|
+
module RBGL
|
|
7
|
+
module GUI
|
|
8
|
+
module X11
|
|
9
|
+
class XAuthority
|
|
10
|
+
FAMILY_INTERNET = 0
|
|
11
|
+
FAMILY_INTERNET6 = 6
|
|
12
|
+
FAMILY_LOCAL = 256
|
|
13
|
+
FAMILY_WILD = 65_535
|
|
14
|
+
AUTH_NAME = "MIT-MAGIC-COOKIE-1"
|
|
15
|
+
|
|
16
|
+
Entry = Struct.new(:family, :address, :display_number, :name, :data, keyword_init: true)
|
|
17
|
+
|
|
18
|
+
def self.cookie_for(host:, display_number:, env: ENV)
|
|
19
|
+
path = env["XAUTHORITY"] || default_path(env)
|
|
20
|
+
return nil unless path && File.file?(path)
|
|
21
|
+
|
|
22
|
+
new(File.binread(path)).cookie_for(host: host, display_number: display_number)
|
|
23
|
+
rescue ArgumentError, EOFError
|
|
24
|
+
nil
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.default_path(env)
|
|
28
|
+
home = env["HOME"] || Dir.home
|
|
29
|
+
File.join(home, ".Xauthority")
|
|
30
|
+
rescue ArgumentError
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize(data)
|
|
35
|
+
@entries = parse(data)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cookie_for(host:, display_number:)
|
|
39
|
+
candidates = @entries.select do |entry|
|
|
40
|
+
(entry.display_number.empty? || entry.display_number == display_number.to_s) && entry.name == AUTH_NAME
|
|
41
|
+
end
|
|
42
|
+
candidates.find { |entry| address_matches?(entry, host) }&.data
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def parse(data)
|
|
48
|
+
offset = 0
|
|
49
|
+
entries = []
|
|
50
|
+
|
|
51
|
+
while offset < data.bytesize
|
|
52
|
+
family, offset = read_u16(data, offset)
|
|
53
|
+
address, offset = read_field(data, offset)
|
|
54
|
+
display_number, offset = read_field(data, offset)
|
|
55
|
+
name, offset = read_field(data, offset)
|
|
56
|
+
cookie, offset = read_field(data, offset)
|
|
57
|
+
entries << Entry.new(
|
|
58
|
+
family: family,
|
|
59
|
+
address: address,
|
|
60
|
+
display_number: display_number,
|
|
61
|
+
name: name,
|
|
62
|
+
data: cookie
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
entries
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def read_u16(data, offset)
|
|
70
|
+
bytes = data.byteslice(offset, 2)
|
|
71
|
+
raise EOFError, "Truncated Xauthority entry" unless bytes&.bytesize == 2
|
|
72
|
+
|
|
73
|
+
[bytes.unpack1("n"), offset + 2]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def read_field(data, offset)
|
|
77
|
+
length, offset = read_u16(data, offset)
|
|
78
|
+
value = data.byteslice(offset, length)
|
|
79
|
+
raise EOFError, "Truncated Xauthority field" unless value&.bytesize == length
|
|
80
|
+
|
|
81
|
+
[value, offset + length]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def address_matches?(entry, host)
|
|
85
|
+
return true if entry.family == FAMILY_WILD
|
|
86
|
+
return local_address_matches?(entry.address) if host.nil? && entry.family == FAMILY_LOCAL
|
|
87
|
+
return false unless [FAMILY_INTERNET, FAMILY_INTERNET6].include?(entry.family)
|
|
88
|
+
|
|
89
|
+
family = entry.family == FAMILY_INTERNET ? :INET : :INET6
|
|
90
|
+
Addrinfo.getaddrinfo(host, nil, family).any? do |address|
|
|
91
|
+
IPAddr.new(address.ip_address).hton == entry.address
|
|
92
|
+
end
|
|
93
|
+
rescue SocketError
|
|
94
|
+
false
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def local_address_matches?(address)
|
|
98
|
+
return true if address.empty?
|
|
99
|
+
|
|
100
|
+
expected = address.downcase
|
|
101
|
+
actual = Socket.gethostname.downcase
|
|
102
|
+
expected == actual || expected.split(".", 2).first == actual.split(".", 2).first
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
data/lib/rbgl/gui.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "version"
|
|
3
4
|
require_relative "gui/event"
|
|
4
5
|
require_relative "gui/backend"
|
|
5
6
|
require_relative "gui/backend_factory"
|
|
@@ -8,10 +9,6 @@ require_relative "gui/window"
|
|
|
8
9
|
|
|
9
10
|
module RBGL
|
|
10
11
|
module GUI
|
|
11
|
-
VERSION =
|
|
12
|
-
|
|
13
|
-
def self.load_tk_backend
|
|
14
|
-
require_relative "gui/tk_backend"
|
|
15
|
-
end
|
|
12
|
+
VERSION = RBGL::VERSION
|
|
16
13
|
end
|
|
17
14
|
end
|
data/lib/rbgl/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,77 +1,79 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rbgl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yudai Takada
|
|
8
|
-
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-09-25 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: larb
|
|
14
15
|
requirement: !ruby/object:Gem::Requirement
|
|
15
16
|
requirements:
|
|
16
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 1.0
|
|
19
|
+
version: '1.0'
|
|
19
20
|
type: :runtime
|
|
20
21
|
prerelease: false
|
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
23
|
requirements:
|
|
23
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
24
25
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 1.0
|
|
26
|
+
version: '1.0'
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
28
|
name: rlsl
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
29
30
|
requirements:
|
|
30
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
31
32
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0'
|
|
33
|
+
version: '1.0'
|
|
33
34
|
type: :runtime
|
|
34
35
|
prerelease: false
|
|
35
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
37
|
requirements:
|
|
37
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
38
39
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0'
|
|
40
|
+
version: '1.0'
|
|
40
41
|
description: A pure Ruby graphics library with software rendering engine and cross-platform
|
|
41
42
|
GUI support (X11, Wayland, Cocoa).
|
|
42
43
|
email:
|
|
43
44
|
- t.yudai92@gmail.com
|
|
44
|
-
executables:
|
|
45
|
+
executables:
|
|
46
|
+
- rbgl
|
|
45
47
|
extensions: []
|
|
46
48
|
extra_rdoc_files: []
|
|
47
49
|
files:
|
|
50
|
+
- ".rubocop.yml"
|
|
48
51
|
- CHANGELOG.md
|
|
49
52
|
- LICENSE
|
|
50
53
|
- README.md
|
|
51
54
|
- Rakefile
|
|
55
|
+
- bench/renderer_bench.rb
|
|
56
|
+
- docs/.nojekyll
|
|
57
|
+
- docs/index.html
|
|
52
58
|
- examples/array_test.rb
|
|
53
|
-
- examples/chemical_heartbeat.rb
|
|
54
59
|
- examples/color_test.rb
|
|
55
60
|
- examples/cube_spinning.rb
|
|
56
|
-
- examples/dark_transit.rb
|
|
57
|
-
- examples/fractured_orb.rb
|
|
58
|
-
- examples/fractured_orb_rb.rb
|
|
59
61
|
- examples/gradient.rb
|
|
60
|
-
- examples/hexagonal_flow.rb
|
|
61
62
|
- examples/multi_return_test.rb
|
|
62
63
|
- examples/plasma.rb
|
|
63
64
|
- examples/sphere_raymarch.rb
|
|
64
|
-
- examples/teapot.rb
|
|
65
|
-
- examples/teapot_mcu.rb
|
|
66
65
|
- examples/triangle_basic.rb
|
|
67
66
|
- examples/triangle_window.rb
|
|
68
67
|
- examples/window_test.rb
|
|
68
|
+
- exe/rbgl
|
|
69
69
|
- lib/rbgl.rb
|
|
70
|
+
- lib/rbgl/cli/doctor.rb
|
|
70
71
|
- lib/rbgl/engine.rb
|
|
71
72
|
- lib/rbgl/engine/buffer.rb
|
|
72
73
|
- lib/rbgl/engine/clip_space_clipper.rb
|
|
73
74
|
- lib/rbgl/engine/context.rb
|
|
74
75
|
- lib/rbgl/engine/framebuffer.rb
|
|
76
|
+
- lib/rbgl/engine/immutable_color.rb
|
|
75
77
|
- lib/rbgl/engine/pipeline.rb
|
|
76
78
|
- lib/rbgl/engine/rasterizer.rb
|
|
77
79
|
- lib/rbgl/engine/rasterizer/attribute_interpolator.rb
|
|
@@ -87,19 +89,23 @@ files:
|
|
|
87
89
|
- lib/rbgl/gui/backend.rb
|
|
88
90
|
- lib/rbgl/gui/backend_factory.rb
|
|
89
91
|
- lib/rbgl/gui/cocoa/backend.rb
|
|
92
|
+
- lib/rbgl/gui/cocoa/key_mapper.rb
|
|
90
93
|
- lib/rbgl/gui/event.rb
|
|
91
94
|
- lib/rbgl/gui/file_backend.rb
|
|
92
95
|
- lib/rbgl/gui/file_backend/bmp_writer.rb
|
|
93
96
|
- lib/rbgl/gui/file_backend/frame_writer.rb
|
|
97
|
+
- lib/rbgl/gui/file_backend/png_writer.rb
|
|
94
98
|
- lib/rbgl/gui/file_backend/ppm_writer.rb
|
|
95
99
|
- lib/rbgl/gui/wayland/backend.rb
|
|
96
100
|
- lib/rbgl/gui/wayland/codec.rb
|
|
97
101
|
- lib/rbgl/gui/wayland/connection.rb
|
|
98
102
|
- lib/rbgl/gui/wayland/event_dispatcher.rb
|
|
99
103
|
- lib/rbgl/gui/wayland/global_binder.rb
|
|
104
|
+
- lib/rbgl/gui/wayland/input_mapper.rb
|
|
100
105
|
- lib/rbgl/gui/wayland/protocol_objects.rb
|
|
101
106
|
- lib/rbgl/gui/wayland/protocol_objects/arguments.rb
|
|
102
107
|
- lib/rbgl/gui/wayland/protocol_objects/display.rb
|
|
108
|
+
- lib/rbgl/gui/wayland/protocol_objects/seat.rb
|
|
103
109
|
- lib/rbgl/gui/wayland/protocol_objects/shm.rb
|
|
104
110
|
- lib/rbgl/gui/wayland/protocol_objects/surface.rb
|
|
105
111
|
- lib/rbgl/gui/wayland/protocol_objects/xdg_shell.rb
|
|
@@ -110,16 +116,21 @@ files:
|
|
|
110
116
|
- lib/rbgl/gui/x11/backend.rb
|
|
111
117
|
- lib/rbgl/gui/x11/connection.rb
|
|
112
118
|
- lib/rbgl/gui/x11/event_parser.rb
|
|
119
|
+
- lib/rbgl/gui/x11/key_mapper.rb
|
|
120
|
+
- lib/rbgl/gui/x11/pixel_encoder.rb
|
|
113
121
|
- lib/rbgl/gui/x11/request_encoder.rb
|
|
122
|
+
- lib/rbgl/gui/x11/setup_parser.rb
|
|
114
123
|
- lib/rbgl/gui/x11/transport.rb
|
|
124
|
+
- lib/rbgl/gui/x11/x_authority.rb
|
|
115
125
|
- lib/rbgl/version.rb
|
|
116
|
-
homepage: https://github.
|
|
126
|
+
homepage: https://rbgfx.github.io/rbgl/
|
|
117
127
|
licenses:
|
|
118
128
|
- MIT
|
|
119
129
|
metadata:
|
|
120
|
-
homepage_uri: https://github.
|
|
121
|
-
source_code_uri: https://github.com/
|
|
122
|
-
changelog_uri: https://github.com/
|
|
130
|
+
homepage_uri: https://rbgfx.github.io/rbgl/
|
|
131
|
+
source_code_uri: https://github.com/rbgfx/rbgl/tree/main
|
|
132
|
+
changelog_uri: https://github.com/rbgfx/rbgl/blob/main/CHANGELOG.md
|
|
133
|
+
post_install_message:
|
|
123
134
|
rdoc_options: []
|
|
124
135
|
require_paths:
|
|
125
136
|
- lib
|
|
@@ -134,7 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
145
|
- !ruby/object:Gem::Version
|
|
135
146
|
version: '0'
|
|
136
147
|
requirements: []
|
|
137
|
-
rubygems_version: 4.
|
|
148
|
+
rubygems_version: 3.4.19
|
|
149
|
+
signing_key:
|
|
138
150
|
specification_version: 4
|
|
139
151
|
summary: RuBy Graphics Library - Pure Ruby software rendering with cross-platform
|
|
140
152
|
GUI
|