package wayland import "base:intrinsics" import "base:runtime" import "core:io" import "core:log" import "core:math/fixed" import "core:os" import "core:path/filepath" import "core:strconv" import "core:strings" import "core:sys/linux" _allocate_object :: proc(session: ^Session, kind: Object_Kind) -> Object_ID { id := session.next_id session.next_id += 1 session.objects[id] = {kind=kind} return id } _get_object_interface_name :: proc(session: ^Session, object_id: Object_ID) -> string { if object_info, ok := session.objects[object_id]; ok { return object_kind_to_interface_name[object_info.kind] } else { return "[unknown]" } } _get_socket_path :: proc(temp_allocator: runtime.Allocator) -> (string, bool) { xdg_runtime_directory, xdg_runtime_directory_ok := os.lookup_env("XDG_RUNTIME_DIR", temp_allocator) if !xdg_runtime_directory_ok { return "", false } defer delete(xdg_runtime_directory, temp_allocator) wayland_display := os.lookup_env("WAYLAND_DISPLAY", temp_allocator) or_else "wayland-0" defer delete(wayland_display, temp_allocator) final_path, err := filepath.join({xdg_runtime_directory, wayland_display}, temp_allocator) if err != nil { log.debug("Socket path:", final_path) } return final_path, err == nil } _get_socket :: proc(temp_allocator: runtime.Allocator) -> (fd: linux.Fd, ok: bool) { if wayland_socket, ok := os.lookup_env("WAYLAND_SOCKET", temp_allocator); ok { fd_num, fd_ok := strconv.parse_int(wayland_socket) if fd_ok { return linux.Fd(fd_num), true } else { log.error("Ignoring bad WAYLAND_SOCKET value '{}'", wayland_socket) } } socket_fd, socket_errno := linux.socket(.UNIX, .STREAM, {}, nil) if socket_errno != .NONE { log.error("Failed to create wayland socket:", socket_errno) return 0, false } socket_path := _get_socket_path(temp_allocator) or_return defer delete(socket_path, temp_allocator) socket_address := linux.Sock_Addr_Un{sun_family = .UNIX} ensure(len(socket_path) < size_of(socket_address.sun_path), "Socket path is too long.") copy(socket_address.sun_path[:], socket_path) connect_errno := linux.connect(socket_fd, &socket_address) if connect_errno != .NONE { log.error("Failed to connect to wayland socket:", connect_errno) return 0, false } return socket_fd, true } // Stolen from core:strings and modified to work with a string builder as input. _string_builder_write_fixed :: proc(builder: ^strings.Builder, value: $T/fixed.Fixed($Backing, $Fraction_Width)) -> (n: int) { Integer_Width :: 8*size_of(Backing) - Fraction_Width value := value buffer: [48]byte i := 0 if !intrinsics.type_is_unsigned(Backing) && value.i == min(Backing) { // edge case handling for signed numbers buffer[i] = '-' i += 1 i += copy(buffer[i:], _power_of_two_table[Integer_Width]) } else { if value.i < 0 { buffer[i] = '-' i += 1 value.i = -value.i } when size_of(Backing) < 16 { T :: u64 write_uint :: strconv.write_uint } else { T :: u128 write_uint :: strconv.write_u128 } integer := T(value.i) >> Fraction_Width fraction := T(value.i) & (1< 0 { fraction *= 10 buffer[i] = byte('0' + (fraction>>Fraction_Width) % 10) i += 1 fraction &= 1<