feat: unify system status codes
This commit is contained in:
1 parent
93894b8fe5
commit
8a3ffb2be1
46 files changed
+1499
-489
No files matched your search
@@ -217,6 +217,16 @@ struct DesktopState {
|
||||
uint64_t wifi_status_time;
|
||||
|
||||
|
||||
// Battery indicator. Absent entirely on a machine with no ACPI battery
|
||||
// device, which is how a desktop keeps a clean panel.
|
||||
SvgIcon icon_battery;
|
||||
char battery_icon_name[64]; // which glyph icon_battery holds
|
||||
bool battery_present; // a battery device exists
|
||||
bool battery_popup_open;
|
||||
Rect battery_icon_rect;
|
||||
montauk::abi::BatteryInfo battery_info;
|
||||
uint64_t battery_last_poll;
|
||||
|
||||
bool vol_popup_open;
|
||||
Rect vol_icon_rect;
|
||||
int vol_level; // 0-100
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <montauk/syscall.h>
|
||||
#include <montauk/string.h>
|
||||
#include <Api/Syscall.hpp>
|
||||
#include <montauk/capabilities.h>
|
||||
|
||||
namespace gui {
|
||||
|
||||
@@ -59,32 +60,47 @@ struct TerminalState {
|
||||
int csi_current_param;
|
||||
};
|
||||
|
||||
// ==== Palette ====
|
||||
//
|
||||
// The palette is a mutable global rather than a set of constants because the
|
||||
// terminal lets the user switch themes at runtime. Cells store resolved colors,
|
||||
// so a theme switch also has to rewrite the cells that were painted with the
|
||||
// outgoing palette -- see terminal_remap_palette below.
|
||||
|
||||
struct TermPalette {
|
||||
Color bg;
|
||||
Color fg;
|
||||
Color cursor;
|
||||
Color ansi[16];
|
||||
};
|
||||
|
||||
inline constexpr TermPalette TERM_PALETTE_DEFAULT = {
|
||||
colors::TERM_BG,
|
||||
colors::TERM_FG,
|
||||
colors::TERM_FG,
|
||||
{
|
||||
Color::from_hex(0x000000), Color::from_hex(0xCC0000),
|
||||
Color::from_hex(0x4E9A06), Color::from_hex(0xC4A000),
|
||||
Color::from_hex(0x3465A4), Color::from_hex(0x75507B),
|
||||
Color::from_hex(0x06989A), Color::from_hex(0xD3D7CF),
|
||||
Color::from_hex(0x555753), Color::from_hex(0xEF2929),
|
||||
Color::from_hex(0x8AE234), Color::from_hex(0xFCE94F),
|
||||
Color::from_hex(0x729FCF), Color::from_hex(0xAD7FA8),
|
||||
Color::from_hex(0x34E2E2), Color::from_hex(0xEEEEEC),
|
||||
}
|
||||
};
|
||||
|
||||
inline TermPalette g_term_palette = TERM_PALETTE_DEFAULT;
|
||||
|
||||
// Standard ANSI color palette as ARGB pixels
|
||||
static inline Color term_ansi_color(int idx) {
|
||||
switch (idx) {
|
||||
case 0: return Color::from_hex(0x000000);
|
||||
case 1: return Color::from_hex(0xCC0000);
|
||||
case 2: return Color::from_hex(0x4E9A06);
|
||||
case 3: return Color::from_hex(0xC4A000);
|
||||
case 4: return Color::from_hex(0x3465A4);
|
||||
case 5: return Color::from_hex(0x75507B);
|
||||
case 6: return Color::from_hex(0x06989A);
|
||||
case 7: return Color::from_hex(0xD3D7CF);
|
||||
case 8: return Color::from_hex(0x555753);
|
||||
case 9: return Color::from_hex(0xEF2929);
|
||||
case 10: return Color::from_hex(0x8AE234);
|
||||
case 11: return Color::from_hex(0xFCE94F);
|
||||
case 12: return Color::from_hex(0x729FCF);
|
||||
case 13: return Color::from_hex(0xAD7FA8);
|
||||
case 14: return Color::from_hex(0x34E2E2);
|
||||
case 15: return Color::from_hex(0xEEEEEC);
|
||||
default: return colors::TERM_FG;
|
||||
}
|
||||
if (idx < 0 || idx > 15) return g_term_palette.fg;
|
||||
return g_term_palette.ansi[idx];
|
||||
}
|
||||
|
||||
// ANSI 256-color palette (0-15 = standard, 16-231 = RGB cube, 232-255 = grayscale)
|
||||
static inline Color term_ansi_256_color(int idx) {
|
||||
if (idx < 0) return colors::TERM_FG;
|
||||
if (idx < 0) return g_term_palette.fg;
|
||||
if (idx <= 15) return term_ansi_color(idx);
|
||||
if (idx <= 231) {
|
||||
// 6x6x6 RGB cube: idx 16 = (0,0,0), idx 231 = (5,5,5)
|
||||
@@ -118,6 +134,47 @@ static inline void terminal_invalidate_render_cache(TerminalState* t) {
|
||||
t->render_cursor_visible = false;
|
||||
}
|
||||
|
||||
// Translate one already-resolved cell color from an outgoing palette to the
|
||||
// incoming one. Colors that are not palette entries -- 256-color cube and
|
||||
// grayscale ramp values -- are left exactly as the program asked for them.
|
||||
static inline Color term_remap_color(Color c, const TermPalette& from,
|
||||
const TermPalette& to) {
|
||||
if (term_color_equal(c, from.bg)) return to.bg;
|
||||
if (term_color_equal(c, from.fg)) return to.fg;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (term_color_equal(c, from.ansi[i])) return to.ansi[i];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// Repaint an existing terminal in a new palette. Cells carry resolved colors,
|
||||
// so switching themes without this leaves all scrollback -- and the shell's
|
||||
// colored prompt -- in the old theme's colors.
|
||||
static inline void terminal_remap_palette(TerminalState* t,
|
||||
const TermPalette& from,
|
||||
const TermPalette& to) {
|
||||
if (!t || !t->cells) return;
|
||||
|
||||
int total = (t->rows + t->max_scrollback) * t->cols;
|
||||
for (int i = 0; i < total; i++) {
|
||||
t->cells[i].fg = term_remap_color(t->cells[i].fg, from, to);
|
||||
t->cells[i].bg = term_remap_color(t->cells[i].bg, from, to);
|
||||
}
|
||||
|
||||
if (t->alt_cells) {
|
||||
int screen = t->rows * t->cols;
|
||||
for (int i = 0; i < screen; i++) {
|
||||
t->alt_cells[i].fg = term_remap_color(t->alt_cells[i].fg, from, to);
|
||||
t->alt_cells[i].bg = term_remap_color(t->alt_cells[i].bg, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
t->current_fg = term_remap_color(t->current_fg, from, to);
|
||||
t->current_bg = term_remap_color(t->current_bg, from, to);
|
||||
terminal_invalidate_render_cache(t);
|
||||
t->dirty = true;
|
||||
}
|
||||
|
||||
static inline Color terminal_erase_bg(TerminalState* t) {
|
||||
return t->current_bg;
|
||||
}
|
||||
@@ -162,8 +219,8 @@ static inline void terminal_init_cells(TerminalState* t, int cols, int rows, int
|
||||
t->scrollback_lines = 0;
|
||||
t->max_scrollback = max_sb;
|
||||
t->view_offset = 0;
|
||||
t->current_fg = colors::TERM_FG;
|
||||
t->current_bg = colors::TERM_BG;
|
||||
t->current_fg = g_term_palette.fg;
|
||||
t->current_bg = g_term_palette.bg;
|
||||
t->cursor_visible = false;
|
||||
t->alt_screen_active = false;
|
||||
t->reverse_video = false;
|
||||
@@ -201,10 +258,10 @@ static inline void terminal_init_cells(TerminalState* t, int cols, int rows, int
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < total_cells; i++) {
|
||||
t->cells[i] = {' ', colors::TERM_FG, colors::TERM_BG};
|
||||
t->cells[i] = {' ', g_term_palette.fg, g_term_palette.bg};
|
||||
}
|
||||
for (int i = 0; i < screen_cells; i++) {
|
||||
t->alt_cells[i] = {' ', colors::TERM_FG, colors::TERM_BG};
|
||||
t->alt_cells[i] = {' ', g_term_palette.fg, g_term_palette.bg};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +269,8 @@ static inline void terminal_init(TerminalState* t, int cols, int rows) {
|
||||
terminal_init_cells(t, cols, rows, TERM_MAX_SCROLLBACK);
|
||||
t->cursor_visible = true;
|
||||
|
||||
t->child_pid = montauk::spawn_redir("0:/os/shell.elf");
|
||||
static constexpr const char* kShellPath = "0:/os/shell.elf";
|
||||
t->child_pid = montauk::caps::launch(kShellPath, {.redirected = true});
|
||||
if (t->child_pid > 0)
|
||||
montauk::childio_settermsz(t->child_pid, cols, rows);
|
||||
}
|
||||
@@ -245,7 +303,7 @@ static inline void terminal_enter_alt_screen(TerminalState* t) {
|
||||
TermCell* screen = term_screen_row(t, 0);
|
||||
for (int i = 0; i < total; i++) {
|
||||
t->alt_cells[i] = screen[i];
|
||||
screen[i] = {' ', colors::TERM_FG, colors::TERM_BG};
|
||||
screen[i] = {' ', g_term_palette.fg, g_term_palette.bg};
|
||||
}
|
||||
t->view_offset = 0;
|
||||
t->cursor_x = 0;
|
||||
@@ -424,8 +482,8 @@ static inline void terminal_process_csi(TerminalState* t, char cmd) {
|
||||
}
|
||||
|
||||
if (code == 0) {
|
||||
t->current_fg = colors::TERM_FG;
|
||||
t->current_bg = colors::TERM_BG;
|
||||
t->current_fg = g_term_palette.fg;
|
||||
t->current_bg = g_term_palette.bg;
|
||||
t->reverse_video = false;
|
||||
} else if (code == 1) {
|
||||
// Bold: map to bright version of current color
|
||||
@@ -473,15 +531,15 @@ static inline void terminal_process_csi(TerminalState* t, char cmd) {
|
||||
} else if (code >= 100 && code <= 107) {
|
||||
t->current_bg = term_ansi_color(code - 100 + 8);
|
||||
} else if (code == 39) {
|
||||
t->current_fg = colors::TERM_FG;
|
||||
t->current_fg = g_term_palette.fg;
|
||||
} else if (code == 49) {
|
||||
t->current_bg = colors::TERM_BG;
|
||||
t->current_bg = g_term_palette.bg;
|
||||
}
|
||||
}
|
||||
if (t->csi_param_count == 0) {
|
||||
// ESC[m with no params = reset
|
||||
t->current_fg = colors::TERM_FG;
|
||||
t->current_bg = colors::TERM_BG;
|
||||
t->current_fg = g_term_palette.fg;
|
||||
t->current_bg = g_term_palette.bg;
|
||||
t->reverse_video = false;
|
||||
}
|
||||
break;
|
||||
@@ -532,8 +590,8 @@ static inline void terminal_feed(TerminalState* t, const char* data, int len) {
|
||||
for (int j = 0; j < 8; j++) t->csi_params[j] = 0;
|
||||
} else if (ch == 'c') {
|
||||
// Reset terminal
|
||||
t->current_fg = colors::TERM_FG;
|
||||
t->current_bg = colors::TERM_BG;
|
||||
t->current_fg = g_term_palette.fg;
|
||||
t->current_bg = g_term_palette.bg;
|
||||
t->cursor_x = 0;
|
||||
t->cursor_y = 0;
|
||||
t->parse_state = TerminalState::STATE_NORMAL;
|
||||
@@ -627,18 +685,21 @@ static inline void terminal_draw_cursor_pixels(const TermCell& cell,
|
||||
uint32_t* pixels, int pw, int ph,
|
||||
int px, int py, int cell_w, int cell_h,
|
||||
bool use_ttf, GlyphCache* gc) {
|
||||
// The block cursor takes its color from the palette and punches the glyph
|
||||
// out in the background color, so it stays legible on light themes too --
|
||||
// a hardcoded white block disappears on a white background.
|
||||
terminal_fill_pixel_rect(pixels, pw, ph, px, py, cell_w, cell_h,
|
||||
colors::WHITE.to_pixel());
|
||||
g_term_palette.cursor.to_pixel());
|
||||
|
||||
if (cell.ch <= 32 && cell.ch >= 0) return;
|
||||
|
||||
if (use_ttf) {
|
||||
int baseline = py + gc->ascent;
|
||||
fonts::mono->draw_char_to_buffer(pixels, pw, ph,
|
||||
px, baseline, (unsigned char)cell.ch, colors::BLACK, gc);
|
||||
px, baseline, (unsigned char)cell.ch, g_term_palette.bg, gc);
|
||||
} else {
|
||||
terminal_draw_bitmap_char(pixels, pw, ph, px, py, (unsigned char)cell.ch,
|
||||
colors::BLACK.to_pixel());
|
||||
g_term_palette.bg.to_pixel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +761,7 @@ static inline void terminal_render(TerminalState* t, uint32_t* pixels, int pw, i
|
||||
t->render_base_row != base_row ||
|
||||
t->render_term_cols != t->cols || t->render_term_rows != t->rows;
|
||||
|
||||
uint32_t bg_px = colors::TERM_BG.to_pixel();
|
||||
uint32_t bg_px = g_term_palette.bg.to_pixel();
|
||||
if (full_redraw) {
|
||||
int row_bytes = pw * sizeof(uint32_t);
|
||||
for (int i = 0; i < pw; i++) pixels[i] = bg_px;
|
||||
@@ -779,9 +840,9 @@ static inline void terminal_resize(TerminalState* t, int new_cols, int new_rows)
|
||||
|
||||
// Clear new buffers
|
||||
for (int i = 0; i < new_total; i++)
|
||||
new_cells[i] = {' ', colors::TERM_FG, colors::TERM_BG};
|
||||
new_cells[i] = {' ', g_term_palette.fg, g_term_palette.bg};
|
||||
for (int i = 0; i < new_rows * new_cols; i++)
|
||||
new_alt[i] = {' ', colors::TERM_FG, colors::TERM_BG};
|
||||
new_alt[i] = {' ', g_term_palette.fg, g_term_palette.bg};
|
||||
|
||||
// Copy content: scrollback + visible screen
|
||||
int old_content = t->scrollback_lines + t->rows;
|
||||
|
||||
@@ -483,10 +483,10 @@ namespace fonts {
|
||||
return f;
|
||||
};
|
||||
|
||||
system_font = load("0:/fonts/Roboto-Medium.ttf");
|
||||
system_bold = load("0:/fonts/Roboto-Bold.ttf");
|
||||
mono = load("0:/fonts/JetBrainsMono-Regular.ttf");
|
||||
mono_bold = load("0:/fonts/JetBrainsMono-Bold.ttf");
|
||||
system_font = load("0:/os/fonts/Roboto-Medium.ttf");
|
||||
system_bold = load("0:/os/fonts/Roboto-Bold.ttf");
|
||||
mono = load("0:/os/fonts/JetBrainsMono-Regular.ttf");
|
||||
mono_bold = load("0:/os/fonts/JetBrainsMono-Bold.ttf");
|
||||
|
||||
return system_font != nullptr;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user