feat: wi-fi - expand support and fix issues, add GUI components
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user