rbgl 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.codespellignore +4 -0
- data/.rubocop.yml +3 -0
- data/.yamllint +16 -0
- data/CHANGELOG.md +11 -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 +55 -9
- data/lib/rbgl/engine/clip_space_clipper.rb +23 -3
- data/lib/rbgl/engine/context.rb +23 -6
- data/lib/rbgl/engine/framebuffer.rb +146 -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 +38 -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,81 @@
|
|
|
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.2
|
|
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-26 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
|
+
- ".codespellignore"
|
|
51
|
+
- ".rubocop.yml"
|
|
52
|
+
- ".yamllint"
|
|
48
53
|
- CHANGELOG.md
|
|
49
54
|
- LICENSE
|
|
50
55
|
- README.md
|
|
51
56
|
- Rakefile
|
|
57
|
+
- bench/renderer_bench.rb
|
|
58
|
+
- docs/.nojekyll
|
|
59
|
+
- docs/index.html
|
|
52
60
|
- examples/array_test.rb
|
|
53
|
-
- examples/chemical_heartbeat.rb
|
|
54
61
|
- examples/color_test.rb
|
|
55
62
|
- examples/cube_spinning.rb
|
|
56
|
-
- examples/dark_transit.rb
|
|
57
|
-
- examples/fractured_orb.rb
|
|
58
|
-
- examples/fractured_orb_rb.rb
|
|
59
63
|
- examples/gradient.rb
|
|
60
|
-
- examples/hexagonal_flow.rb
|
|
61
64
|
- examples/multi_return_test.rb
|
|
62
65
|
- examples/plasma.rb
|
|
63
66
|
- examples/sphere_raymarch.rb
|
|
64
|
-
- examples/teapot.rb
|
|
65
|
-
- examples/teapot_mcu.rb
|
|
66
67
|
- examples/triangle_basic.rb
|
|
67
68
|
- examples/triangle_window.rb
|
|
68
69
|
- examples/window_test.rb
|
|
70
|
+
- exe/rbgl
|
|
69
71
|
- lib/rbgl.rb
|
|
72
|
+
- lib/rbgl/cli/doctor.rb
|
|
70
73
|
- lib/rbgl/engine.rb
|
|
71
74
|
- lib/rbgl/engine/buffer.rb
|
|
72
75
|
- lib/rbgl/engine/clip_space_clipper.rb
|
|
73
76
|
- lib/rbgl/engine/context.rb
|
|
74
77
|
- lib/rbgl/engine/framebuffer.rb
|
|
78
|
+
- lib/rbgl/engine/immutable_color.rb
|
|
75
79
|
- lib/rbgl/engine/pipeline.rb
|
|
76
80
|
- lib/rbgl/engine/rasterizer.rb
|
|
77
81
|
- lib/rbgl/engine/rasterizer/attribute_interpolator.rb
|
|
@@ -87,19 +91,23 @@ files:
|
|
|
87
91
|
- lib/rbgl/gui/backend.rb
|
|
88
92
|
- lib/rbgl/gui/backend_factory.rb
|
|
89
93
|
- lib/rbgl/gui/cocoa/backend.rb
|
|
94
|
+
- lib/rbgl/gui/cocoa/key_mapper.rb
|
|
90
95
|
- lib/rbgl/gui/event.rb
|
|
91
96
|
- lib/rbgl/gui/file_backend.rb
|
|
92
97
|
- lib/rbgl/gui/file_backend/bmp_writer.rb
|
|
93
98
|
- lib/rbgl/gui/file_backend/frame_writer.rb
|
|
99
|
+
- lib/rbgl/gui/file_backend/png_writer.rb
|
|
94
100
|
- lib/rbgl/gui/file_backend/ppm_writer.rb
|
|
95
101
|
- lib/rbgl/gui/wayland/backend.rb
|
|
96
102
|
- lib/rbgl/gui/wayland/codec.rb
|
|
97
103
|
- lib/rbgl/gui/wayland/connection.rb
|
|
98
104
|
- lib/rbgl/gui/wayland/event_dispatcher.rb
|
|
99
105
|
- lib/rbgl/gui/wayland/global_binder.rb
|
|
106
|
+
- lib/rbgl/gui/wayland/input_mapper.rb
|
|
100
107
|
- lib/rbgl/gui/wayland/protocol_objects.rb
|
|
101
108
|
- lib/rbgl/gui/wayland/protocol_objects/arguments.rb
|
|
102
109
|
- lib/rbgl/gui/wayland/protocol_objects/display.rb
|
|
110
|
+
- lib/rbgl/gui/wayland/protocol_objects/seat.rb
|
|
103
111
|
- lib/rbgl/gui/wayland/protocol_objects/shm.rb
|
|
104
112
|
- lib/rbgl/gui/wayland/protocol_objects/surface.rb
|
|
105
113
|
- lib/rbgl/gui/wayland/protocol_objects/xdg_shell.rb
|
|
@@ -110,16 +118,21 @@ files:
|
|
|
110
118
|
- lib/rbgl/gui/x11/backend.rb
|
|
111
119
|
- lib/rbgl/gui/x11/connection.rb
|
|
112
120
|
- lib/rbgl/gui/x11/event_parser.rb
|
|
121
|
+
- lib/rbgl/gui/x11/key_mapper.rb
|
|
122
|
+
- lib/rbgl/gui/x11/pixel_encoder.rb
|
|
113
123
|
- lib/rbgl/gui/x11/request_encoder.rb
|
|
124
|
+
- lib/rbgl/gui/x11/setup_parser.rb
|
|
114
125
|
- lib/rbgl/gui/x11/transport.rb
|
|
126
|
+
- lib/rbgl/gui/x11/x_authority.rb
|
|
115
127
|
- lib/rbgl/version.rb
|
|
116
|
-
homepage: https://github.
|
|
128
|
+
homepage: https://rbgfx.github.io/rbgl/
|
|
117
129
|
licenses:
|
|
118
130
|
- MIT
|
|
119
131
|
metadata:
|
|
120
|
-
homepage_uri: https://github.
|
|
121
|
-
source_code_uri: https://github.com/
|
|
122
|
-
changelog_uri: https://github.com/
|
|
132
|
+
homepage_uri: https://rbgfx.github.io/rbgl/
|
|
133
|
+
source_code_uri: https://github.com/rbgfx/rbgl/tree/main
|
|
134
|
+
changelog_uri: https://github.com/rbgfx/rbgl/blob/main/CHANGELOG.md
|
|
135
|
+
post_install_message:
|
|
123
136
|
rdoc_options: []
|
|
124
137
|
require_paths:
|
|
125
138
|
- lib
|
|
@@ -134,7 +147,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
147
|
- !ruby/object:Gem::Version
|
|
135
148
|
version: '0'
|
|
136
149
|
requirements: []
|
|
137
|
-
rubygems_version: 4.
|
|
150
|
+
rubygems_version: 3.4.19
|
|
151
|
+
signing_key:
|
|
138
152
|
specification_version: 4
|
|
139
153
|
summary: RuBy Graphics Library - Pure Ruby software rendering with cross-platform
|
|
140
154
|
GUI
|