feat: printer UX improvements
This commit is contained in:
@@ -47,6 +47,7 @@ CXXFLAGS := \
|
||||
-mcmodel=small \
|
||||
-I $(PROG_INC) \
|
||||
-isystem $(PROG_INC)/libc \
|
||||
-I ../../lib/bearssl/inc \
|
||||
-isystem ../../../kernel/freestnd-c-hdrs/x86_64/include \
|
||||
-isystem ../../../kernel/freestnd-cxx-hdrs/x86_64/include
|
||||
|
||||
@@ -63,7 +64,7 @@ LDFLAGS := \
|
||||
|
||||
# ---- Source files ----
|
||||
|
||||
SRCS := main.cpp render.cpp diskdetail.cpp stb_truetype_impl.cpp
|
||||
SRCS := main.cpp render.cpp diskdetail.cpp printers.cpp stb_truetype_impl.cpp
|
||||
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
|
||||
|
||||
# ---- Target ----
|
||||
|
||||
@@ -29,11 +29,27 @@ static constexpr int TOOLBAR_H = 36;
|
||||
static constexpr int CAT_H = 28;
|
||||
static constexpr int ITEM_H = 24;
|
||||
static constexpr int MAX_DEVS = 64;
|
||||
static constexpr int MAX_VIRTUAL_DEVS = 4;
|
||||
static constexpr int MAX_TOTAL_DEVS = MAX_DEVS + MAX_VIRTUAL_DEVS;
|
||||
static constexpr int POLL_MS = 2000;
|
||||
static constexpr int INDENT = 28;
|
||||
static constexpr int FONT_SIZE = 18;
|
||||
|
||||
static constexpr int NUM_CATEGORIES = 9;
|
||||
enum DeviceCategory {
|
||||
CAT_CPU = 0,
|
||||
CAT_INTERRUPT,
|
||||
CAT_TIMER,
|
||||
CAT_INPUT,
|
||||
CAT_USB,
|
||||
CAT_NETWORK,
|
||||
CAT_DISPLAY,
|
||||
CAT_STORAGE,
|
||||
CAT_PCI,
|
||||
CAT_AUDIO,
|
||||
CAT_ACPI,
|
||||
CAT_PRINTER,
|
||||
NUM_CATEGORIES
|
||||
};
|
||||
|
||||
static constexpr Color BG_COLOR = Color::from_rgb(0xFF, 0xFF, 0xFF);
|
||||
static constexpr Color TOOLBAR_BG = Color::from_rgb(0xF5, 0xF5, 0xF5);
|
||||
@@ -48,27 +64,33 @@ static constexpr Color ACCENT_COLOR = Color::from_rgb(0x33, 0x66, 0xCC);
|
||||
// ============================================================================
|
||||
|
||||
static const char* category_names[] = {
|
||||
"CPU", // 0
|
||||
"Interrupt", // 1
|
||||
"Timer", // 2
|
||||
"Input", // 3
|
||||
"USB", // 4
|
||||
"Network", // 5
|
||||
"Display", // 6
|
||||
"Storage", // 7
|
||||
"PCI", // 8
|
||||
"CPU",
|
||||
"Interrupt",
|
||||
"Timer",
|
||||
"Input",
|
||||
"USB",
|
||||
"Network",
|
||||
"Display",
|
||||
"Storage",
|
||||
"PCI",
|
||||
"Audio",
|
||||
"ACPI",
|
||||
"Printers",
|
||||
};
|
||||
|
||||
static const Color category_colors[] = {
|
||||
Color::from_rgb(0x33, 0x66, 0xCC), // CPU - blue
|
||||
Color::from_rgb(0x88, 0x44, 0xAA), // Interrupt - purple
|
||||
Color::from_rgb(0x22, 0x88, 0x22), // Timer - green
|
||||
Color::from_rgb(0xCC, 0x88, 0x00), // Input - amber
|
||||
Color::from_rgb(0x00, 0x88, 0x88), // USB - teal
|
||||
Color::from_rgb(0xCC, 0x55, 0x22), // Network - orange
|
||||
Color::from_rgb(0x44, 0x66, 0xCC), // Display - indigo
|
||||
Color::from_rgb(0x99, 0x55, 0x00), // Storage - brown
|
||||
Color::from_rgb(0x66, 0x66, 0x66), // PCI - gray
|
||||
Color::from_rgb(0x33, 0x66, 0xCC),
|
||||
Color::from_rgb(0x88, 0x44, 0xAA),
|
||||
Color::from_rgb(0x22, 0x88, 0x22),
|
||||
Color::from_rgb(0xCC, 0x88, 0x00),
|
||||
Color::from_rgb(0x00, 0x88, 0x88),
|
||||
Color::from_rgb(0xCC, 0x55, 0x22),
|
||||
Color::from_rgb(0x44, 0x66, 0xCC),
|
||||
Color::from_rgb(0x99, 0x55, 0x00),
|
||||
Color::from_rgb(0x66, 0x66, 0x66),
|
||||
Color::from_rgb(0x8A, 0x5A, 0xCC),
|
||||
Color::from_rgb(0x55, 0x77, 0x88),
|
||||
Color::from_rgb(0x2F, 0x8B, 0x57),
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -83,7 +105,7 @@ struct DisplayRow {
|
||||
int dev_index;
|
||||
};
|
||||
|
||||
static constexpr int MAX_DISPLAY_ROWS = MAX_DEVS + NUM_CATEGORIES;
|
||||
static constexpr int MAX_DISPLAY_ROWS = MAX_TOTAL_DEVS + NUM_CATEGORIES;
|
||||
|
||||
// ============================================================================
|
||||
// Disk detail window
|
||||
@@ -110,7 +132,7 @@ struct DiskDetailState {
|
||||
// ============================================================================
|
||||
|
||||
struct DevExplorerState {
|
||||
Montauk::DevInfo devs[MAX_DEVS];
|
||||
Montauk::DevInfo devs[MAX_TOTAL_DEVS];
|
||||
int dev_count;
|
||||
bool collapsed[NUM_CATEGORIES];
|
||||
int selected_row;
|
||||
@@ -142,6 +164,7 @@ void render(uint32_t* pixels);
|
||||
// ============================================================================
|
||||
|
||||
int build_display_rows(DevExplorerState* de, DisplayRow* rows);
|
||||
int append_printer_devices(Montauk::DevInfo* out, int max_count);
|
||||
|
||||
// ============================================================================
|
||||
// Function declarations — diskdetail.cpp
|
||||
|
||||
@@ -17,6 +17,21 @@ int g_win_h = INIT_H;
|
||||
DevExplorerState g_state;
|
||||
TrueTypeFont* g_font = nullptr;
|
||||
|
||||
static void refresh_devices(DevExplorerState* de) {
|
||||
if (de == nullptr) return;
|
||||
|
||||
int kernel_count = montauk::devlist(de->devs, MAX_DEVS);
|
||||
if (kernel_count < 0) kernel_count = 0;
|
||||
if (kernel_count > MAX_DEVS) kernel_count = MAX_DEVS;
|
||||
|
||||
int printer_count = append_printer_devices(
|
||||
de->devs + kernel_count, MAX_TOTAL_DEVS - kernel_count);
|
||||
if (printer_count < 0) printer_count = 0;
|
||||
|
||||
de->dev_count = kernel_count + printer_count;
|
||||
de->last_poll_ms = montauk::get_milliseconds();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Display row building
|
||||
// ============================================================================
|
||||
@@ -92,7 +107,7 @@ static bool handle_list_click(int mx, int my) {
|
||||
bool is_double = (de.last_click_row == i)
|
||||
&& (now - de.last_click_ms < 400);
|
||||
|
||||
if (is_double && de.devs[di].category == 7) {
|
||||
if (is_double && de.devs[di].category == CAT_STORAGE) {
|
||||
int port = (int)de.devs[di]._pad[0];
|
||||
open_disk_detail(port, de.devs[di].name);
|
||||
de.last_click_row = -1;
|
||||
@@ -201,8 +216,7 @@ extern "C" void _start() {
|
||||
}
|
||||
|
||||
// Initial device poll
|
||||
g_state.dev_count = montauk::devlist(g_state.devs, MAX_DEVS);
|
||||
g_state.last_poll_ms = montauk::get_milliseconds();
|
||||
refresh_devices(&g_state);
|
||||
|
||||
WsWindow win;
|
||||
if (!win.create("Devices", INIT_W, INIT_H))
|
||||
@@ -221,8 +235,7 @@ extern "C" void _start() {
|
||||
// Poll for device refresh
|
||||
uint64_t now = montauk::get_milliseconds();
|
||||
if (now - g_state.last_poll_ms >= POLL_MS) {
|
||||
g_state.dev_count = montauk::devlist(g_state.devs, MAX_DEVS);
|
||||
g_state.last_poll_ms = now;
|
||||
refresh_devices(&g_state);
|
||||
redraw_main = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* printers.cpp
|
||||
* Virtual printer-device registration for the MontaukOS Device Explorer
|
||||
* Copyright (c) 2026 Daniel Hammer
|
||||
*/
|
||||
|
||||
#include "devexplorer.h"
|
||||
#include <print/print.hpp>
|
||||
|
||||
using namespace print;
|
||||
|
||||
static void format_printer_detail(const ProbeState& probe,
|
||||
const IppUri* normalized,
|
||||
char* out, int out_len) {
|
||||
if (out == nullptr || out_len <= 0) return;
|
||||
out[0] = '\0';
|
||||
|
||||
const char* host = nullptr;
|
||||
if (probe.caps.host[0]) host = probe.caps.host;
|
||||
else if (normalized && normalized->host[0]) host = normalized->host;
|
||||
|
||||
if (probe.ok) {
|
||||
if (host && *host)
|
||||
snprintf(out, (size_t)out_len, "Ready on %s", host);
|
||||
else
|
||||
snprintf(out, (size_t)out_len, "Ready");
|
||||
return;
|
||||
}
|
||||
|
||||
if (probe.message[0]) {
|
||||
if (strstr(probe.message, "resolve"))
|
||||
snprintf(out, (size_t)out_len, "Host resolution failed");
|
||||
else if (strstr(probe.message, "mDNS"))
|
||||
snprintf(out, (size_t)out_len, "mDNS host not supported");
|
||||
else if (strstr(probe.message, "Unsupported format"))
|
||||
snprintf(out, (size_t)out_len, "Unsupported format");
|
||||
else
|
||||
safe_copy(out, out_len, probe.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (host && *host)
|
||||
snprintf(out, (size_t)out_len, "Awaiting probe on %s", host);
|
||||
else
|
||||
snprintf(out, (size_t)out_len, "Awaiting spooler probe");
|
||||
}
|
||||
|
||||
int append_printer_devices(Montauk::DevInfo* out, int max_count) {
|
||||
if (out == nullptr || max_count <= 0) return 0;
|
||||
|
||||
char current_uri[MAX_PATH_LEN] = {};
|
||||
bool has_current_uri = read_default_printer_uri(current_uri, sizeof(current_uri));
|
||||
|
||||
ProbeState probe = {};
|
||||
bool has_probe = load_printer_probe_state(&probe);
|
||||
if (has_probe && has_current_uri && !montauk::streq(probe.printer_uri, current_uri))
|
||||
has_probe = false;
|
||||
|
||||
const char* effective_uri = nullptr;
|
||||
if (has_current_uri) effective_uri = current_uri;
|
||||
else if (has_probe && probe.printer_uri[0]) effective_uri = probe.printer_uri;
|
||||
else return 0;
|
||||
|
||||
IppUri normalized = {};
|
||||
char uri_err[128] = {};
|
||||
bool normalized_ok = normalize_ipp_uri(effective_uri, &normalized, uri_err, sizeof(uri_err));
|
||||
|
||||
Montauk::DevInfo dev = {};
|
||||
dev.category = CAT_PRINTER;
|
||||
|
||||
if (has_probe && probe.caps.printer_name[0]) {
|
||||
safe_copy(dev.name, sizeof(dev.name), probe.caps.printer_name);
|
||||
} else if (normalized_ok && normalized.host[0]) {
|
||||
safe_copy(dev.name, sizeof(dev.name), normalized.host);
|
||||
} else {
|
||||
safe_copy(dev.name, sizeof(dev.name), "Configured Printer");
|
||||
}
|
||||
|
||||
if (has_probe) {
|
||||
format_printer_detail(probe, normalized_ok ? &normalized : nullptr,
|
||||
dev.detail, sizeof(dev.detail));
|
||||
} else if (normalized_ok && normalized.host[0]) {
|
||||
snprintf(dev.detail, sizeof(dev.detail), "Awaiting probe on %s", normalized.host);
|
||||
} else {
|
||||
safe_copy(dev.detail, sizeof(dev.detail), "Awaiting spooler probe");
|
||||
}
|
||||
|
||||
out[0] = dev;
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user