2024-04-29 19:26:50 +02:00
|
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
const Queue = @import("queue.zig").Queue;
|
|
|
|
const Tty = @import("Tty.zig");
|
|
|
|
const Vaxis = @import("Vaxis.zig");
|
|
|
|
|
|
|
|
pub fn Loop(comptime T: type) type {
|
|
|
|
return struct {
|
|
|
|
const Self = @This();
|
|
|
|
|
|
|
|
const log = std.log.scoped(.loop);
|
|
|
|
|
|
|
|
queue: Queue(T, 512) = .{},
|
|
|
|
|
|
|
|
thread: ?std.Thread = null,
|
|
|
|
|
|
|
|
vaxis: *Vaxis,
|
|
|
|
|
|
|
|
/// spawns the input thread to read input from the tty
|
|
|
|
pub fn run(self: *Self) !void {
|
|
|
|
if (self.thread) |_| return;
|
|
|
|
if (self.vaxis.tty == null) self.vaxis.tty = try Tty.init();
|
2024-04-29 21:00:08 +02:00
|
|
|
self.thread = try std.Thread.spawn(.{}, Tty.run, .{
|
|
|
|
&self.vaxis.tty.?,
|
|
|
|
T,
|
|
|
|
self,
|
|
|
|
&self.vaxis.unicode.grapheme_data,
|
2024-05-20 22:01:02 +02:00
|
|
|
self.vaxis.opts.system_clipboard_allocator,
|
2024-04-29 21:00:08 +02:00
|
|
|
});
|
2024-04-29 19:26:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// stops reading from the tty and returns it to it's initial state
|
|
|
|
pub fn stop(self: *Self) void {
|
2024-04-30 23:42:10 +02:00
|
|
|
if (self.vaxis.tty) |*tty| {
|
|
|
|
// stop the read loop, then join the thread
|
|
|
|
tty.stop();
|
|
|
|
if (self.thread) |thread| {
|
|
|
|
thread.join();
|
|
|
|
self.thread = null;
|
|
|
|
}
|
|
|
|
// once thread is closed we can deinit the tty
|
|
|
|
tty.deinit();
|
|
|
|
self.vaxis.tty = null;
|
2024-04-29 19:26:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// returns the next available event, blocking until one is available
|
|
|
|
pub fn nextEvent(self: *Self) T {
|
|
|
|
return self.queue.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// blocks until an event is available. Useful when your application is
|
|
|
|
/// operating on a poll + drain architecture (see tryEvent)
|
|
|
|
pub fn pollEvent(self: *Self) void {
|
|
|
|
self.queue.poll();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// returns an event if one is available, otherwise null. Non-blocking.
|
|
|
|
pub fn tryEvent(self: *Self) ?T {
|
|
|
|
return self.queue.tryPop();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// posts an event into the event queue. Will block if there is not
|
|
|
|
/// capacity for the event
|
|
|
|
pub fn postEvent(self: *Self, event: T) void {
|
|
|
|
self.queue.push(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tryPostEvent(self: *Self, event: T) bool {
|
|
|
|
return self.queue.tryPush(event);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|