feat: wi-fi - expand support and fix issues, add GUI components

This commit is contained in:
2026-08-07 10:36:53 +02:00
parent bbe1df62fd
commit 9eb21eb3e3
67 changed files with 4573 additions and 245 deletions
+89 -33
View File
@@ -141,25 +141,48 @@ void gui::desktop_draw_panel(DesktopState* ds) {
}
}
// Network icon (to the left of the volume icon)
int net_icon_x = vol_icon_x - 16 - 10;
int net_icon_y = (PANEL_HEIGHT - 16) / 2;
ds->net_icon_rect = {net_icon_x, net_icon_y, 16, 16};
// Status icons fill in leftwards from the volume icon. Ethernet only
// appears when a wired interface is registered, Wi-Fi only when a
// supported adapter is present, so a machine without either shows neither.
int icon_y = (PANEL_HEIGHT - 16) / 2;
int next_icon_x = vol_icon_x - 16 - 10;
if (ds->icon_network.pixels) {
if (ds->cached_net_cfg.ipAddress == 0) {
uint32_t* src = ds->icon_network.pixels;
int npx = 16 * 16;
uint32_t tinted[256];
for (int p = 0; p < npx; p++) {
uint32_t px = src[p];
uint8_t a = (px >> 24) & 0xFF;
tinted[p] = ((uint32_t)a << 24) | 0x004444CC;
if (ds->eth_present) {
ds->net_icon_rect = {next_icon_x, icon_y, 16, 16};
next_icon_x -= 16 + 10;
if (ds->icon_network.pixels) {
// Tinted while the cable is doing nothing for us: no link, or a
// link that is not the one carrying traffic.
if (!desktop_eth_online(ds)) {
uint32_t* src = ds->icon_network.pixels;
uint32_t tinted[256];
for (int p = 0; p < 16 * 16; p++) {
uint8_t a = (src[p] >> 24) & 0xFF;
tinted[p] = ((uint32_t)a << 24) | 0x004444CC;
}
fb.blit_alpha(ds->net_icon_rect.x, icon_y, 16, 16, tinted);
} else {
fb.blit_alpha(ds->net_icon_rect.x, icon_y, ds->icon_network.width,
ds->icon_network.height, ds->icon_network.pixels);
}
fb.blit_alpha(net_icon_x, net_icon_y, 16, 16, tinted);
} else {
fb.blit_alpha(net_icon_x, net_icon_y, ds->icon_network.width, ds->icon_network.height, ds->icon_network.pixels);
}
} else {
ds->net_icon_rect = {0, 0, 0, 0};
}
// Wi-Fi stays white whatever the radio is doing: the popup carries the
// state, and a colour-shifting icon next to the clock is just noise.
if (ds->wifi_present) {
ds->wifi_icon_rect = {next_icon_x, icon_y, 16, 16};
next_icon_x -= 16 + 10;
if (ds->icon_wifi.pixels) {
fb.blit_alpha(ds->wifi_icon_rect.x, icon_y, ds->icon_wifi.width,
ds->icon_wifi.height, ds->icon_wifi.pixels);
}
} else {
ds->wifi_icon_rect = {0, 0, 0, 0};
}
}
@@ -265,16 +288,38 @@ void desktop_draw_app_menu(DesktopState* ds) {
// Network Popup
// ============================================================================
// The wired interface, if one is registered.
const montauk::abi::NetIfInfo* desktop_eth_iface(const DesktopState* ds) {
for (int i = 0; i < ds->netif_count; i++) {
if (ds->netifs[i].kind == montauk::abi::NETIF_KIND_ETHERNET)
return &ds->netifs[i];
}
return nullptr;
}
// "Online" for the panel icon means the cable is both up and the interface the
// stack is actually sending through, with an address to send from.
bool desktop_eth_online(const DesktopState* ds) {
const montauk::abi::NetIfInfo* eth = desktop_eth_iface(ds);
return eth && eth->linkUp && eth->active && ds->cached_net_cfg.ipAddress != 0;
}
void desktop_draw_net_popup(DesktopState* ds) {
Framebuffer& fb = ds->fb;
montauk::abi::NetCfg& nc = ds->cached_net_cfg;
bool connected = nc.ipAddress != 0;
const montauk::abi::NetIfInfo* eth = desktop_eth_iface(ds);
bool link_up = eth && eth->linkUp;
// The IP configuration is global to the stack, so it is only this
// interface's address while this interface is the active one.
bool owns_address = eth && eth->active && nc.ipAddress != 0;
bool connected = link_up && owns_address;
int popup_w = 220;
int fh = system_font_height();
int row_h = fh + 8;
int header_h = row_h + 8; // title + status row + padding
int body_rows = 5; // IP, Subnet, Gateway, DNS, MAC
int body_rows = 6; // Interface, IP, Subnet, Gateway, DNS, MAC
int popup_h = header_h + row_h * body_rows + 12;
int popup_x = ds->net_icon_rect.x + ds->net_icon_rect.w - popup_w;
int popup_y = PANEL_HEIGHT + 2;
@@ -290,11 +335,14 @@ void desktop_draw_net_popup(DesktopState* ds) {
// Header: "Ethernet" + status dot
draw_text(fb, lx, ty, "Ethernet", colors::TEXT_COLOR);
// Status dot + label (right-aligned in header)
// Status dot + label (right-aligned in header). A cable that is plugged
// in but idle (Wi-Fi is carrying the traffic) is not the same as unplugged.
Color dot_color = connected
? Color::from_rgb(0x4C, 0xAF, 0x50) // green
: Color::from_rgb(0xCC, 0x33, 0x33); // red
const char* status_str = connected ? "Connected" : "Disconnected";
: (link_up ? Color::from_rgb(0xD0, 0x9A, 0x2E) // amber
: Color::from_rgb(0xCC, 0x33, 0x33)); // red
const char* status_str = connected ? "Connected"
: (link_up ? "Link up" : "Disconnected");
int sw = text_width(status_str);
int dot_r = 4;
int status_x = popup_x + popup_w - 14 - sw;
@@ -318,23 +366,31 @@ void desktop_draw_net_popup(DesktopState* ds) {
int val_x = popup_x + 76; // fixed column for values
struct NetRow { const char* label; char value[24]; };
NetRow rows[5];
NetRow rows[6];
rows[0].label = "IP";
if (connected) format_ip(rows[0].value, nc.ipAddress);
else montauk::strcpy(rows[0].value, "0.0.0.0");
rows[0].label = "Interface";
montauk::strncpy(rows[0].value, eth ? eth->name : "None", sizeof(rows[0].value));
rows[1].label = "Subnet";
format_ip(rows[1].value, nc.subnetMask);
// Addresses are shown only when this interface owns them; otherwise the
// wireless popup is where they belong.
rows[1].label = "IP";
if (owns_address) format_ip(rows[1].value, nc.ipAddress);
else montauk::strcpy(rows[1].value, link_up ? "Not in use" : "0.0.0.0");
rows[2].label = "Gateway";
format_ip(rows[2].value, nc.gateway);
rows[2].label = "Subnet";
if (owns_address) format_ip(rows[2].value, nc.subnetMask);
else montauk::strcpy(rows[2].value, "-");
rows[3].label = "DNS";
format_ip(rows[3].value, nc.dnsServer);
rows[3].label = "Gateway";
if (owns_address) format_ip(rows[3].value, nc.gateway);
else montauk::strcpy(rows[3].value, "-");
rows[4].label = "MAC";
format_mac(rows[4].value, nc.macAddress);
rows[4].label = "DNS";
if (owns_address) format_ip(rows[4].value, nc.dnsServer);
else montauk::strcpy(rows[4].value, "-");
rows[5].label = "MAC";
format_mac(rows[5].value, eth ? eth->mac : nc.macAddress);
for (int i = 0; i < body_rows; i++) {
draw_text(fb, lx, ty, rows[i].label, dim);