mirror of
https://codeberg.org/fairyglade/ly.git
synced 2026-08-14 09:39:14 +02:00
feature: add corner customization
This commit is contained in:
parent
25fad28c34
commit
031815b3cc
3 changed files with 265 additions and 0 deletions
|
|
@ -153,6 +153,35 @@ colormix_col2 = 0x000000FF
|
|||
# Color mixing animation third color id
|
||||
colormix_col3 = 0x20000000
|
||||
|
||||
# Screen corners customization
|
||||
# Keywords:
|
||||
# keys -> Power management keys (shutdown, restart, etc.)
|
||||
# clock -> Clock (format defined by 'clock' option)
|
||||
# tty -> Active TTY number
|
||||
# battery -> Battery percentage
|
||||
# version -> Ly version string
|
||||
# numlock -> Numlock state
|
||||
# capslock -> Capslock state
|
||||
# locks -> Both numlock and capslock
|
||||
# labels -> All custom info labels (lbl:)
|
||||
# binds -> All custom keybind hints (cmd:)
|
||||
# lbl:name -> Specific custom info label
|
||||
# cmd:key -> Specific custom keybind hint
|
||||
#
|
||||
# The order defines the vertical stack (first item is at the edge).
|
||||
|
||||
# Top left corner configuration
|
||||
corner_top_left = keys
|
||||
|
||||
# Top right corner configuration
|
||||
corner_top_right = clock tty
|
||||
|
||||
# Bottom left corner configuration
|
||||
corner_bottom_left = version
|
||||
|
||||
# Bottom right corner configuration
|
||||
corner_bottom_right = labels
|
||||
|
||||
# For custom binds: the horizontal limit in characters for each
|
||||
# line of custom binds before moving on to the next.
|
||||
# If null, defaults to the width of the terminal instead.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ cmatrix_max_codepoint: u16 = 0x7B,
|
|||
colormix_col1: u32 = 0x00FF0000,
|
||||
colormix_col2: u32 = 0x000000FF,
|
||||
colormix_col3: u32 = 0x20000000,
|
||||
corner_bottom_left: []const u8 = "version",
|
||||
corner_bottom_right: []const u8 = "labels",
|
||||
corner_top_left: []const u8 = "keys",
|
||||
corner_top_right: []const u8 = "clock tty",
|
||||
custom_bind_width: ?u32 = null,
|
||||
custom_sessions: []const u8 = build_options.config_directory ++ "/ly/custom-sessions",
|
||||
default_input: Input = .login,
|
||||
|
|
|
|||
232
src/main.zig
232
src/main.zig
|
|
@ -2062,6 +2062,238 @@ fn updateSessionSpecifier(self: *Label, ptr: *anyopaque) !void {
|
|||
self.setText(env.environment.specifier);
|
||||
}
|
||||
|
||||
const Corner = enum {
|
||||
corner_bottom_left,
|
||||
corner_bottom_right,
|
||||
corner_top_left,
|
||||
corner_top_right,
|
||||
};
|
||||
|
||||
const PositionedWidgets = struct {
|
||||
binds: []bool,
|
||||
labels: []bool,
|
||||
};
|
||||
|
||||
fn positionItem(state: *UiState, item: []const u8, current_x: *usize, current_y: usize, is_left: bool, is_top: bool, positioned: *PositionedWidgets) !bool {
|
||||
const base_x = state.edge_margin.x;
|
||||
|
||||
if (std.mem.eql(u8, item, "keys")) {
|
||||
if (state.config.hide_key_hints) return false;
|
||||
|
||||
var local_x = current_x.*;
|
||||
var local_y = current_y;
|
||||
var lines_consumed: usize = 0;
|
||||
|
||||
const labels = [_]?*Label{
|
||||
&state.shutdown_label,
|
||||
&state.restart_label,
|
||||
if (state.config.sleep_cmd != null) &state.sleep_label else null,
|
||||
if (state.config.hibernate_cmd != null) &state.hibernate_label else null,
|
||||
&state.toggle_password_label,
|
||||
if (state.config.brightness_down_key != null) &state.brightness_down_label else null,
|
||||
if (state.config.brightness_up_key != null) &state.brightness_up_label else null,
|
||||
};
|
||||
|
||||
for (labels) |maybe_label| {
|
||||
const label = maybe_label orelse continue;
|
||||
const width = TerminalBuffer.strWidth(label.text);
|
||||
|
||||
if (is_left) {
|
||||
if (local_x + width > state.buffer.width - state.edge_margin.x) {
|
||||
local_x = base_x;
|
||||
if (is_top) local_y += 1 else local_y -= 1;
|
||||
lines_consumed += 1;
|
||||
}
|
||||
label.positionXY(Position.init(local_x, local_y));
|
||||
local_x += width + 1;
|
||||
} else {
|
||||
if (width + state.edge_margin.x > local_x) {
|
||||
local_x = state.buffer.width - state.edge_margin.x;
|
||||
if (is_top) local_y += 1 else local_y -= 1;
|
||||
lines_consumed += 1;
|
||||
}
|
||||
label.positionXY(Position.init(local_x - width, local_y));
|
||||
local_x -= width + 1;
|
||||
}
|
||||
}
|
||||
current_x.* = local_x;
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "clock") or std.mem.eql(u8, item, "time")) {
|
||||
if (state.config.clock == null) return false;
|
||||
const width = TerminalBuffer.strWidth(state.clock_label.text);
|
||||
if (is_left) {
|
||||
state.clock_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.clock_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "tty")) {
|
||||
if (!state.config.show_tty) return false;
|
||||
const width = TerminalBuffer.strWidth(state.tty_label.text);
|
||||
if (is_left) {
|
||||
state.tty_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.tty_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "battery")) {
|
||||
if (state.config.battery_id == null) return false;
|
||||
const width = TerminalBuffer.strWidth(state.battery_label.text);
|
||||
if (is_left) {
|
||||
state.battery_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.battery_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "version")) {
|
||||
if (state.config.hide_version_string) return false;
|
||||
const width = TerminalBuffer.strWidth(state.version_label.text);
|
||||
if (is_left) {
|
||||
state.version_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.version_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "numlock")) {
|
||||
if (state.config.hide_keyboard_locks) return false;
|
||||
const width = TerminalBuffer.strWidth(state.lang.numlock);
|
||||
if (is_left) {
|
||||
state.numlock_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.numlock_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "capslock")) {
|
||||
if (state.config.hide_keyboard_locks) return false;
|
||||
const width = TerminalBuffer.strWidth(state.lang.capslock);
|
||||
if (is_left) {
|
||||
state.capslock_label.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
state.capslock_label.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "locks")) {
|
||||
if (state.config.hide_keyboard_locks) return false;
|
||||
const num_w = TerminalBuffer.strWidth(state.lang.numlock);
|
||||
const caps_w = TerminalBuffer.strWidth(state.lang.capslock);
|
||||
if (is_left) {
|
||||
state.numlock_label.positionXY(Position.init(current_x.*, current_y));
|
||||
state.capslock_label.positionXY(Position.init(current_x.* + num_w + 1, current_y));
|
||||
current_x.* += num_w + 1 + caps_w + 1;
|
||||
} else {
|
||||
state.capslock_label.positionXY(Position.init(current_x.* - caps_w, current_y));
|
||||
state.numlock_label.positionXY(Position.init(current_x.* - caps_w - 1 - num_w, current_y));
|
||||
current_x.* -= caps_w + 1 + num_w + 1;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "labels")) {
|
||||
for (state.custom_info.items, 0..) |*info, i| {
|
||||
if (positioned.labels[i]) continue;
|
||||
const width = TerminalBuffer.strWidth(info.lbl.text);
|
||||
if (is_left) {
|
||||
info.lbl.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
info.lbl.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
positioned.labels[i] = true;
|
||||
}
|
||||
return true;
|
||||
} else if (std.mem.eql(u8, item, "binds")) {
|
||||
var local_x = current_x.*;
|
||||
var local_y = current_y;
|
||||
|
||||
for (state.custom_binds.items, 0..) |*bind, i| {
|
||||
if (positioned.binds[i]) continue;
|
||||
const width = TerminalBuffer.strWidth(bind.lbl.text);
|
||||
|
||||
if (is_left) {
|
||||
if (local_x + width > (state.config.custom_bind_width orelse state.buffer.width) - state.edge_margin.x) {
|
||||
local_x = base_x;
|
||||
if (is_top) local_y += 1 else local_y -= 1;
|
||||
}
|
||||
bind.lbl.positionXY(Position.init(local_x, local_y));
|
||||
local_x += width + 1;
|
||||
} else {
|
||||
if (width + state.edge_margin.x > local_x) {
|
||||
local_x = state.buffer.width - state.edge_margin.x;
|
||||
if (is_top) local_y += 1 else local_y -= 1;
|
||||
}
|
||||
bind.lbl.positionXY(Position.init(local_x - width, local_y));
|
||||
local_x -= width + 1;
|
||||
}
|
||||
positioned.binds[i] = true;
|
||||
}
|
||||
current_x.* = local_x;
|
||||
return true;
|
||||
} else if (std.mem.startsWith(u8, item, "lbl:")) {
|
||||
const name = item[4..];
|
||||
for (state.custom_info.items, 0..) |*info, i| {
|
||||
if (std.mem.eql(u8, info.info.name, name)) {
|
||||
if (positioned.labels[i]) return false;
|
||||
const width = TerminalBuffer.strWidth(info.lbl.text);
|
||||
if (is_left) {
|
||||
info.lbl.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
info.lbl.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
positioned.labels[i] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (std.mem.startsWith(u8, item, "cmd:")) {
|
||||
const key = item[4..];
|
||||
for (state.custom_binds.items, 0..) |*bind, i| {
|
||||
if (std.mem.eql(u8, bind.key, key)) {
|
||||
if (positioned.binds[i]) return false;
|
||||
const width = TerminalBuffer.strWidth(bind.lbl.text);
|
||||
if (is_left) {
|
||||
bind.lbl.positionXY(Position.init(current_x.*, current_y));
|
||||
current_x.* += width + 1;
|
||||
} else {
|
||||
bind.lbl.positionXY(Position.init(current_x.* - width, current_y));
|
||||
current_x.* -= width + 1;
|
||||
}
|
||||
positioned.binds[i] = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn positionCorner(state: *UiState, config_str: []const u8, corner: Corner, positioned: *PositionedWidgets) !void {
|
||||
const is_left = corner == .corner_top_left or corner == .corner_bottom_left;
|
||||
const is_top = corner == .corner_top_right or corner == .corner_bottom_right;
|
||||
|
||||
var y_offset: usize = 0;
|
||||
var it = std.mem.tokenizeAny(u8, config_str, " []\"");
|
||||
|
||||
while (it.next()) |item| {
|
||||
var current_x = if (is_left) state.edge_margin.x else state.buffer.width - state.edge_margin.x;
|
||||
const current_y = if (is_top) state.edge_margin.y + y_offset else state.buffer.height - 1 - state.edge_margin.y - y_offset;
|
||||
|
||||
if (try positionItem(state, item, corner, ¤t_x, current_y, is_left, is_top, positioned)) {
|
||||
y_offset += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn positionWidgets(ptr: *anyopaque) !void {
|
||||
var state: *UiState = @ptrCast(@alignCast(ptr));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue