Files
zterm/src/event.zig
Yves Biener ec22e68e8c
Some checks failed
Zig Project Action / Lint, Spell-check and test zig project (push) Failing after 40s
ref(event): remove .resize and replace with recursize method calls
This also means that currently the dynamic resizing through the app's
detached thread is not working, as it cannot send size updates. The
examples have been overhauled to still implement intermediate mode
applications accordingly.
2025-03-04 14:52:19 +01:00

95 lines
3.1 KiB
Zig

//! Events which are defined by the library. They might be extended by user
//! events. See `App` for more details about user defined events.
const std = @import("std");
const input = @import("input.zig");
const terminal = @import("terminal.zig");
const Key = input.Key;
const Mouse = input.Mouse;
const Point = @import("point.zig").Point;
/// System events available to every `zterm.App`
pub const SystemEvent = union(enum) {
/// Initialize event, which is send once at the beginning of the event loop and before the first render loop
/// TODO not sure if this is necessary or if there is an actual usecase for this - for now it will remain
init,
/// Quit event to signify the end of the event loop (rendering should stop afterwards)
quit,
/// Error event to notify other containers about a recoverable error
err: struct {
err: anyerror,
/// associated error message
msg: []const u8,
},
/// Input key event received from the user
key: Key,
/// Mouse input event
mouse: Mouse,
/// Focus event for mouse interaction
/// TODO this should instead be a union with a `Size` to derive which container / element the focus meant for
focus: bool,
};
pub fn mergeTaggedUnions(comptime A: type, comptime B: type) type {
if (!isTaggedUnion(A) or !isTaggedUnion(B)) {
@compileError("Both types for merging tagged unions need to be of type `union(enum)`.");
}
const a_fields = @typeInfo(A).@"union".fields;
const a_fields_tag = @typeInfo(A).@"union".tag_type.?;
const a_enum_fields = @typeInfo(a_fields_tag).@"enum".fields;
const b_fields = @typeInfo(B).@"union".fields;
const b_fields_tag = @typeInfo(B).@"union".tag_type.?;
const b_enum_fields = @typeInfo(b_fields_tag).@"enum".fields;
var fields: [a_fields.len + b_fields.len]std.builtin.Type.UnionField = undefined;
var enum_fields: [a_fields.len + b_fields.len]std.builtin.Type.EnumField = undefined;
var i: usize = 0;
for (a_fields, a_enum_fields) |field, enum_field| {
fields[i] = field;
var enum_f = enum_field;
enum_f.value = i;
enum_fields[i] = enum_f;
i += 1;
}
for (b_fields, b_enum_fields) |field, enum_field| {
fields[i] = field;
var enum_f = enum_field;
enum_f.value = i;
enum_fields[i] = enum_f;
i += 1;
}
const log2_i = @bitSizeOf(@TypeOf(i)) - @clz(i);
const EventType = @Type(.{ .int = .{
.signedness = .unsigned,
.bits = log2_i,
} });
const Event = @Type(.{ .@"enum" = .{
.tag_type = EventType,
.fields = enum_fields[0..],
.decls = &.{},
.is_exhaustive = true,
} });
return @Type(.{ .@"union" = .{
.layout = .auto,
.tag_type = Event,
.fields = fields[0..],
.decls = &.{},
} });
}
// Determine at `comptime` whether the provided type `E` is an `union(enum)`.
pub fn isTaggedUnion(comptime E: type) bool {
switch (@typeInfo(E)) {
.@"union" => |u| {
if (u.tag_type) |_| {} else {
return false;
}
},
else => return false,
}
return true;
}