raiguard/odin-wayland

git clone https://git.raiguard.me/raiguard/odin-wayland

Caleb HeuerMove generated -> mockgenfd8ef50

trunk
3.6 KiB115 linesraw
1#+build linux
2#+vet explicit-allocators
3package wayland
4
5import intr "base:intrinsics"
6import rt "base:runtime"
7import "core:bufio"
8import "core:bytes"
9import "core:fmt"
10import "core:io"
11import "core:log"
12import "core:math/fixed"
13import "core:os"
14import "core:path/filepath"
15import "core:strconv"
16import "core:strings"
17import "core:sys/linux"
18
19DISPLAY :: Display_ID(1) // wl_display singleton is hardcoded to an ID of 1.
20
21init :: proc(session: ^Session, allocator := context.allocator, frame_allocator := context.temp_allocator) -> (ok: bool) {
22	// Set up socket boilerplate.
23	{
24		socket_data := &session.socket_data
25
26		socket_fd, socket_ok := _get_socket(allocator)
27		if !socket_ok {
28			return false
29		}
30		socket_data.fd = socket_fd
31
32		socket_data.reader_stream = {
33			procedure = _unix_socket_read,
34			data = session,
35		}
36		bufio.reader_init(&socket_data.reader, socket_data.reader_stream, allocator=allocator)
37
38		socket_data.writer_stream = {
39			procedure = _unix_socket_write,
40			data = session,
41		}
42		bufio.writer_init(&socket_data.writer, socket_data.writer_stream, allocator=allocator)
43
44		bufio.read_writer_init(&socket_data.read_writer, &socket_data.reader, &socket_data.writer)
45		session.socket_stream = bufio.read_writer_to_stream(&socket_data.read_writer)
46	}
47
48	bytes.buffer_init_allocator(&session.message_read_buffer, 0, 16, allocator=allocator)
49	bytes.buffer_init_allocator(&session.message_write_buffer, 0, 16, allocator=allocator)
50	strings.builder_init(&session.debug_log_builder, allocator=allocator)
51
52	session.objects.allocator = allocator
53	session.next_id = 1
54	// wl_display is hardcoded to an ID of 1 in Wayland.
55	display_id := _allocate_object(session, .Display)
56	ensure(display_id == Object_ID(DISPLAY))
57
58	session.allocator = allocator
59	session.frame_allocator = frame_allocator
60
61	wayland_debug_env := os.get_env("WAYLAND_DEBUG", allocator)
62	session.debug_logging_enabled = wayland_debug_env == "1"
63	delete(wayland_debug_env, allocator)
64
65	return true
66}
67
68fini :: proc(session: ^Session) {
69	delete(session.objects)
70	bytes.buffer_destroy(&session.message_read_buffer)
71	bytes.buffer_destroy(&session.message_write_buffer)
72	strings.builder_destroy(&session.debug_log_builder)
73	free_all(session.frame_allocator)
74}
75
76pump_events :: proc(session: ^Session) -> Error {
77	io.flush(session.socket_stream)
78	// TODO: Handle events until there are no more events to be handled!
79	// for _handle_next_event(session) or_return {}
80	_handle_next_event(session) or_return
81	// free_all(session.frame_allocator)
82	return nil
83}
84
85_on_event_internal :: proc(session: ^Session, object_id: Object_ID, opcode: Opcode, handler_info: Handler_Info) {
86	// TODO: Gracefully handle if we don't have handler_info for a given object.
87	ensure(object_id in session.objects)
88	object_info := &session.objects[object_id]
89	object_info.handlers[opcode] = handler_info
90}
91
92_handle_next_event :: proc(session: ^Session) -> (ok: bool, error: Error) {
93	// TODO: Non-blocking
94	message := _message_read(session) or_return
95	// log.debug(message)
96
97	object_id := message.header.object_id
98	object_info, object_info_ok := session.objects[object_id]
99	if !object_info_ok {
100		log.errorf("Received event for unknown object ID '{}'", message.header.object_id)
101		return true, nil
102	}
103
104	handler_info, handler_info_ok := object_info.handlers[message.header.opcode]
105	if !handler_info_ok {
106		log.error("Unhandled event:", message.header)
107		// TODO: We will need to parse the event in order to log it, so we'll need a special code path for that.
108		return true, nil
109	}
110
111	stream := bytes.buffer_to_stream(&session.message_read_buffer)
112	handler_info.dispatcher(session, stream, object_id, message.header.opcode, handler_info) or_return
113
114	return true, nil
115}