2024-11-30 15:52:18 -06:00
|
|
|
.{math, log, string, random, buffer, memory} := @use("stn");
|
|
|
|
.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("lib:render");
|
|
|
|
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("lib:sunset_proto")
|
2024-11-10 12:57:48 -06:00
|
|
|
|
2024-11-10 19:03:01 -06:00
|
|
|
WindowServer := struct {
|
|
|
|
window_count: uint,
|
2024-11-13 11:03:31 -06:00
|
|
|
channel: Channel,
|
2024-11-13 17:08:20 -06:00
|
|
|
// ! replace this with a collection when we get an allocator
|
2024-11-14 10:43:23 -06:00
|
|
|
windows: [?Window; 10],
|
2024-11-13 17:08:20 -06:00
|
|
|
font: text.Font,
|
2024-11-10 19:03:01 -06:00
|
|
|
}
|
2024-11-10 12:57:48 -06:00
|
|
|
|
2024-11-11 15:48:43 -06:00
|
|
|
// ! in the future this should be safely handled
|
|
|
|
server := @as(WindowServer, idk)
|
2024-11-10 12:57:48 -06:00
|
|
|
|
2024-11-13 17:08:20 -06:00
|
|
|
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
|
|
|
|
|
2024-11-11 15:48:43 -06:00
|
|
|
start := fn(): void {
|
2024-11-13 17:08:20 -06:00
|
|
|
font := text.font_from_psf2(@bitcast(&psf), false)
|
|
|
|
if font == null {
|
|
|
|
log.error("server: failed to load asset\0")
|
|
|
|
return
|
|
|
|
}
|
2024-11-14 15:28:21 -06:00
|
|
|
server = .(
|
|
|
|
0,
|
|
|
|
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
|
|
|
|
.(null, null, null, null, null, null, null, null, null, null),
|
|
|
|
@as(text.Font, font),
|
|
|
|
)
|
2024-11-13 11:03:31 -06:00
|
|
|
log.info("server: started server\0")
|
2024-11-10 12:57:48 -06:00
|
|
|
}
|
|
|
|
|
2024-11-13 11:03:31 -06:00
|
|
|
incoming := fn(): bool {
|
|
|
|
msg := recv_header(server.channel.server)
|
|
|
|
if msg == null {
|
2024-11-10 19:03:01 -06:00
|
|
|
return true
|
2024-11-11 15:48:43 -06:00
|
|
|
}
|
2024-11-13 11:03:31 -06:00
|
|
|
if msg.kind == message.syn {
|
|
|
|
log.info("server: recv syn\0")
|
|
|
|
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
|
2024-11-13 17:08:20 -06:00
|
|
|
send_message(Channel, message.ack, channel, server.channel.client)
|
2024-11-13 11:03:31 -06:00
|
|
|
props := await_message(WindowProps, channel.server)
|
|
|
|
if props.header.kind != message.props {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
log.info("server: recv props\0")
|
|
|
|
// ! do inspection of requested props here
|
2024-11-13 17:08:20 -06:00
|
|
|
data := WindowData.(props.body, channel, permissions.default)
|
|
|
|
send_message(WindowData, message.ack, data, channel.client)
|
2024-11-14 10:43:23 -06:00
|
|
|
surface := new_window_decorations(data.props.dimensions)
|
2024-11-14 15:28:21 -06:00
|
|
|
// decorations
|
|
|
|
{
|
2024-11-14 18:09:54 -06:00
|
|
|
title := data.props.title
|
|
|
|
title_length := string.length(title)
|
|
|
|
deco_length := title_length * 10
|
|
|
|
// draw the window tab bar
|
|
|
|
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
|
|
|
|
// Draw the window tab
|
|
|
|
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
|
|
|
|
|
|
|
|
// Draw the outside box
|
|
|
|
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
|
|
|
|
|
2024-11-14 15:28:21 -06:00
|
|
|
put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
|
|
|
|
}
|
2024-11-14 10:43:23 -06:00
|
|
|
server.windows[server.window_count] = .(data, surface)
|
2024-11-13 17:08:20 -06:00
|
|
|
server.window_count += 1
|
2024-11-10 12:57:48 -06:00
|
|
|
}
|
2024-11-10 19:03:01 -06:00
|
|
|
return true
|
2024-11-13 11:03:31 -06:00
|
|
|
}
|
|
|
|
|
2024-11-14 10:43:23 -06:00
|
|
|
$DECO_WIDTH := 2
|
|
|
|
$DECO_HEIGHT_TOP := 20
|
|
|
|
$DECO_HEIGHT_BOTTOM := 1
|
|
|
|
$DECO_COLOUR := Color.(100, 200, 255, 255)
|
2024-11-14 18:09:54 -06:00
|
|
|
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
|
2024-11-14 10:43:23 -06:00
|
|
|
|
|
|
|
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
|
2024-11-14 15:28:21 -06:00
|
|
|
return new_surface(
|
|
|
|
dimensions.x + DECO_WIDTH,
|
|
|
|
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
|
|
|
|
)
|
2024-11-14 10:43:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// ! compositor code. this currently disallows tearing.
|
|
|
|
|
|
|
|
collect_frames := fn(): void {
|
2024-11-14 15:28:21 -06:00
|
|
|
i := 0
|
|
|
|
loop if i == 10 break else {
|
|
|
|
window := server.windows[i]
|
|
|
|
if window == null {
|
|
|
|
i += 1
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
header := recv_header(window.data.channel.server)
|
|
|
|
if header == null {
|
|
|
|
i += 1
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if header.kind != message.frame_ready {
|
|
|
|
i += 1
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
send_header(message.ack, window.data.channel.client)
|
|
|
|
ptr := await_message(^Color, window.data.channel.server)
|
|
|
|
if ptr.header.kind != message.ack {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
put_surface(
|
|
|
|
window.surface,
|
|
|
|
Surface.(
|
|
|
|
ptr.body,
|
|
|
|
window.data.props.dimensions.x,
|
|
|
|
window.data.props.dimensions.y,
|
|
|
|
window.data.props.dimensions.x * window.data.props.dimensions.y,
|
|
|
|
),
|
|
|
|
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
|
|
|
|
false,
|
|
|
|
)
|
|
|
|
i += 1
|
2024-11-13 17:08:20 -06:00
|
|
|
}
|
2024-11-14 10:43:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
render_clients := fn(screen: Surface): void {
|
2024-11-14 15:28:21 -06:00
|
|
|
i := 0
|
|
|
|
loop if i == 10 break else {
|
|
|
|
window := server.windows[i]
|
|
|
|
if window == null {
|
|
|
|
i += 1
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
put_surface(screen, window.surface, window.data.props.position, false)
|
|
|
|
i += 1
|
2024-11-13 11:03:31 -06:00
|
|
|
}
|
2024-11-10 12:57:48 -06:00
|
|
|
}
|