fix: fix desktop app loading cap

This commit is contained in:
2026-07-08 10:00:45 +02:00
parent c4480a3bf2
commit ab8c24844e
4 changed files with 124 additions and 71 deletions
+81 -56
View File
@@ -35,79 +35,104 @@ static void extract_basename(char* out, int outSz, const char* entry) {
out[base_len] = '\0';
}
// Return a slot for the next external app, doubling the array as needed.
// Returns nullptr if allocation failed.
static ExternalApp* next_external_app_slot(DesktopState* ds) {
if (ds->external_app_count >= ds->external_app_capacity) {
int new_cap = ds->external_app_capacity ? ds->external_app_capacity * 2 : 32;
auto* grown = (ExternalApp*)montauk::realloc(
ds->external_apps, (uint64_t)new_cap * sizeof(ExternalApp));
if (!grown) return nullptr;
ds->external_apps = grown;
ds->external_app_capacity = new_cap;
}
return &ds->external_apps[ds->external_app_count];
}
void desktop_scan_apps(DesktopState* ds) {
ds->external_app_count = 0;
// Ensure the apps directory exists
montauk::fmkdir("0:/apps");
const char* entries[32];
int count = montauk::readdir("0:/apps", entries, 32);
// Page through the directory with readdir_at; a single readdir call
// returns at most one batch and would silently drop apps past it.
constexpr int BATCH = 128;
const char* entries[BATCH];
int scanned = 0;
int got;
while ((got = montauk::readdir_at("0:/apps", entries, BATCH, scanned)) > 0) {
scanned += got;
for (int i = 0; i < count && ds->external_app_count < MAX_EXTERNAL_APPS; i++) {
// readdir returns paths like "apps/doom/" — extract just "doom"
char dirname[64];
extract_basename(dirname, sizeof(dirname), entries[i]);
if (dirname[0] == '\0') continue;
for (int i = 0; i < got; i++) {
// readdir returns paths like "apps/doom/" — extract just "doom"
char dirname[64];
extract_basename(dirname, sizeof(dirname), entries[i]);
if (dirname[0] == '\0') continue;
// Try to open the manifest in this app directory
char manifest_path[128];
snprintf(manifest_path, sizeof(manifest_path), "0:/apps/%s/manifest.toml", dirname);
// Try to open the manifest in this app directory
char manifest_path[128];
snprintf(manifest_path, sizeof(manifest_path), "0:/apps/%s/manifest.toml", dirname);
int fh = montauk::open(manifest_path);
if (fh < 0) continue;
int fh = montauk::open(manifest_path);
if (fh < 0) continue;
uint64_t sz = montauk::getsize(fh);
if (sz == 0 || sz > 4096) { montauk::close(fh); continue; }
uint64_t sz = montauk::getsize(fh);
if (sz == 0 || sz > 4096) { montauk::close(fh); continue; }
char* text = (char*)montauk::malloc(sz + 1);
if (!text) { montauk::close(fh); continue; }
int bytes_read = montauk::read(fh, (uint8_t*)text, 0, sz);
montauk::close(fh);
if (bytes_read != (int)sz) {
char* text = (char*)montauk::malloc(sz + 1);
if (!text) { montauk::close(fh); continue; }
int bytes_read = montauk::read(fh, (uint8_t*)text, 0, sz);
montauk::close(fh);
if (bytes_read != (int)sz) {
montauk::mfree(text);
continue;
}
text[sz] = '\0';
auto doc = montauk::toml::parse(text);
montauk::mfree(text);
continue;
}
text[sz] = '\0';
auto doc = montauk::toml::parse(text);
montauk::mfree(text);
// Read manifest fields
const char* name = doc.get_string("app.name", "Unknown");
const char* binary = doc.get_string("app.binary", "");
const char* icon_file = doc.get_string("app.icon", "");
const char* category = doc.get_string("menu.category", "Applications");
bool visible = doc.get_bool("menu.visible", true);
bool launch_with_home = doc.get_bool("launch.pass_home_dir", true);
if (binary[0] == '\0') {
doc.destroy();
continue;
}
ExternalApp* app = &ds->external_apps[ds->external_app_count];
ExternalApp* app = next_external_app_slot(ds);
if (!app) {
doc.destroy();
return;
}
montauk::strncpy(app->name, name, sizeof(app->name));
montauk::strncpy(app->category, category, sizeof(app->category));
app->menu_visible = visible;
app->launch_with_home = launch_with_home;
// Build full binary path: 0:/apps/<dir>/<binary>
snprintf(app->binary_path, sizeof(app->binary_path),
"0:/apps/%s/%s", dirname, binary);
// Load icon from app directory
app->icon = {};
app->icon_path[0] = '\0';
if (icon_file[0]) {
snprintf(app->icon_path, sizeof(app->icon_path),
"0:/apps/%s/%s", dirname, icon_file);
Color defColor = colors::ICON_COLOR;
app->icon = svg_load(app->icon_path, 20, 20, defColor);
}
// Read manifest fields
const char* name = doc.get_string("app.name", "Unknown");
const char* binary = doc.get_string("app.binary", "");
const char* icon_file = doc.get_string("app.icon", "");
const char* category = doc.get_string("menu.category", "Applications");
bool visible = doc.get_bool("menu.visible", true);
bool launch_with_home = doc.get_bool("launch.pass_home_dir", true);
if (binary[0] == '\0') {
doc.destroy();
continue;
ds->external_app_count++;
}
montauk::strncpy(app->name, name, sizeof(app->name));
montauk::strncpy(app->category, category, sizeof(app->category));
app->menu_visible = visible;
app->launch_with_home = launch_with_home;
// Build full binary path: 0:/apps/<dir>/<binary>
snprintf(app->binary_path, sizeof(app->binary_path),
"0:/apps/%s/%s", dirname, binary);
// Load icon from app directory
app->icon = {};
app->icon_path[0] = '\0';
if (icon_file[0]) {
snprintf(app->icon_path, sizeof(app->icon_path),
"0:/apps/%s/%s", dirname, icon_file);
Color defColor = colors::ICON_COLOR;
app->icon = svg_load(app->icon_path, 20, 20, defColor);
}
doc.destroy();
ds->external_app_count++;
}
}