Add layering system for widgets

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-02-12 11:29:14 +01:00
parent 01dcfa207e
commit 5a4605ffb6
2 changed files with 73 additions and 45 deletions

View File

@@ -996,57 +996,67 @@ pub fn main() !void {
} }
} }
// TODO: Layer system where we can put widgets in specific layers (to
// allow certain widgets to be below or above others, like animations)
const info_line_widget = state.info_line.widget(); const info_line_widget = state.info_line.widget();
const session_widget = state.session.widget(); const session_widget = state.session.widget();
const login_widget = state.login.widget(); const login_widget = state.login.widget();
var widgets: std.ArrayList(Widget) = .empty; var widgets: std.ArrayList([]Widget) = .empty;
defer widgets.deinit(state.allocator); defer widgets.deinit(state.allocator);
// Layer 1
if (animation) |a| { if (animation) |a| {
try widgets.append(state.allocator, a); var layer1 = [_]Widget{a};
try widgets.append(state.allocator, &layer1);
} }
// Layer 2
var layer2: std.ArrayList(Widget) = .empty;
defer layer2.deinit(state.allocator);
if (!state.config.hide_key_hints) { if (!state.config.hide_key_hints) {
try widgets.append(state.allocator, state.shutdown_label.widget()); try layer2.append(state.allocator, state.shutdown_label.widget());
try widgets.append(state.allocator, state.restart_label.widget()); try layer2.append(state.allocator, state.restart_label.widget());
if (state.config.sleep_cmd != null) { if (state.config.sleep_cmd != null) {
try widgets.append(state.allocator, state.sleep_label.widget()); try layer2.append(state.allocator, state.sleep_label.widget());
} }
if (state.config.brightness_down_key != null) { if (state.config.brightness_down_key != null) {
try widgets.append(state.allocator, state.brightness_down_label.widget()); try layer2.append(state.allocator, state.brightness_down_label.widget());
} }
if (state.config.brightness_up_key != null) { if (state.config.brightness_up_key != null) {
try widgets.append(state.allocator, state.brightness_up_label.widget()); try layer2.append(state.allocator, state.brightness_up_label.widget());
} }
} }
if (state.config.battery_id != null) { if (state.config.battery_id != null) {
try widgets.append(state.allocator, state.battery_label.widget()); try layer2.append(state.allocator, state.battery_label.widget());
} }
if (state.config.clock != null) { if (state.config.clock != null) {
try widgets.append(state.allocator, state.clock_label.widget()); try layer2.append(state.allocator, state.clock_label.widget());
} }
if (state.config.bigclock != .none) { if (state.config.bigclock != .none) {
try widgets.append(state.allocator, state.bigclock_label.widget()); try layer2.append(state.allocator, state.bigclock_label.widget());
} }
if (!state.config.hide_keyboard_locks) { if (!state.config.hide_keyboard_locks) {
try widgets.append(state.allocator, state.numlock_label.widget()); try layer2.append(state.allocator, state.numlock_label.widget());
try widgets.append(state.allocator, state.capslock_label.widget()); try layer2.append(state.allocator, state.capslock_label.widget());
} }
try widgets.append(state.allocator, state.box.widget()); try layer2.append(state.allocator, state.box.widget());
try widgets.append(state.allocator, info_line_widget); try layer2.append(state.allocator, info_line_widget);
try widgets.append(state.allocator, state.session_specifier_label.widget()); try layer2.append(state.allocator, state.session_specifier_label.widget());
try widgets.append(state.allocator, session_widget); try layer2.append(state.allocator, session_widget);
try widgets.append(state.allocator, state.login_label.widget()); try layer2.append(state.allocator, state.login_label.widget());
try widgets.append(state.allocator, login_widget); try layer2.append(state.allocator, login_widget);
try widgets.append(state.allocator, state.password_label.widget()); try layer2.append(state.allocator, state.password_label.widget());
try widgets.append(state.allocator, state.password_widget); try layer2.append(state.allocator, state.password_widget);
if (!state.config.hide_version_string) { if (!state.config.hide_version_string) {
try widgets.append(state.allocator, state.version_label.widget()); try layer2.append(state.allocator, state.version_label.widget());
} }
try widgets.append(state.allocator, layer2.items);
// Layer 3
if (state.config.auth_fails > 0) { if (state.config.auth_fails > 0) {
try widgets.append(state.allocator, cascade.widget()); var layer3 = [_]Widget{cascade.widget()};
try widgets.append(state.allocator, &layer3);
} }
try state.buffer.registerKeybind("Esc", &disableInsertMode, &state); try state.buffer.registerKeybind("Esc", &disableInsertMode, &state);

View File

@@ -169,7 +169,7 @@ pub fn runEventLoop(
self: *TerminalBuffer, self: *TerminalBuffer,
allocator: Allocator, allocator: Allocator,
shared_error: SharedError, shared_error: SharedError,
widgets: []Widget, layers: [][]Widget,
active_widget: Widget, active_widget: Widget,
inactivity_delay: u16, inactivity_delay: u16,
insert_mode: *bool, insert_mode: *bool,
@@ -189,7 +189,8 @@ pub fn runEventLoop(
defer self.handlable_widgets.deinit(allocator); defer self.handlable_widgets.deinit(allocator);
var i: usize = 0; var i: usize = 0;
for (widgets) |*widget| { for (layers) |layer| {
for (layer) |*widget| {
if (widget.vtable.handle_fn != null) { if (widget.vtable.handle_fn != null) {
try self.handlable_widgets.append(allocator, widget); try self.handlable_widgets.append(allocator, widget);
@@ -197,8 +198,13 @@ pub fn runEventLoop(
i += 1; i += 1;
} }
} }
}
for (widgets) |*widget| try widget.update(context); for (layers) |layer| {
for (layer) |*widget| {
try widget.update(context);
}
}
try @call(.auto, position_widgets_fn, .{context}); try @call(.auto, position_widgets_fn, .{context});
var event: termbox.tb_event = undefined; var event: termbox.tb_event = undefined;
@@ -207,7 +213,11 @@ pub fn runEventLoop(
while (self.run) { while (self.run) {
if (self.update) { if (self.update) {
for (widgets) |*widget| try widget.update(context); for (layers) |layer| {
for (layer) |*widget| {
try widget.update(context);
}
}
// Reset cursor // Reset cursor
const current_widget = self.getActiveWidget(); const current_widget = self.getActiveWidget();
@@ -222,17 +232,23 @@ pub fn runEventLoop(
try TerminalBuffer.clearScreen(false); try TerminalBuffer.clearScreen(false);
for (widgets) |*widget| widget.draw(); for (layers) |layer| {
for (layer) |*widget| {
widget.draw();
}
}
TerminalBuffer.presentBuffer(); TerminalBuffer.presentBuffer();
} }
var maybe_timeout: ?usize = null; var maybe_timeout: ?usize = null;
for (widgets) |*widget| { for (layers) |layer| {
for (layer) |*widget| {
if (try widget.calculateTimeout(context)) |widget_timeout| { if (try widget.calculateTimeout(context)) |widget_timeout| {
if (maybe_timeout == null or widget_timeout < maybe_timeout.?) maybe_timeout = widget_timeout; if (maybe_timeout == null or widget_timeout < maybe_timeout.?) maybe_timeout = widget_timeout;
} }
} }
}
if (inactivity_event_fn) |inactivity_fn| { if (inactivity_event_fn) |inactivity_fn| {
const time = try interop.getTimeOfDay(); const time = try interop.getTimeOfDay();
@@ -262,7 +278,8 @@ pub fn runEventLoop(
.{ self.width, self.height }, .{ self.width, self.height },
); );
for (widgets) |*widget| { for (layers) |layer| {
for (layer) |*widget| {
widget.realloc() catch |err| { widget.realloc() catch |err| {
shared_error.writeError(error.WidgetReallocationFailed); shared_error.writeError(error.WidgetReallocationFailed);
try self.log_file.err( try self.log_file.err(
@@ -272,6 +289,7 @@ pub fn runEventLoop(
); );
}; };
} }
}
try @call(.auto, position_widgets_fn, .{context}); try @call(.auto, position_widgets_fn, .{context});