feat: move Files to its own process; add window server messaging (multi-format clipboard, drag and drop), undo/redo, sidebar, breadcrumbs, thumbnails, file type icons, New menu and proper text fields

This commit is contained in:
daniel committed 2026-10-24 12:44:20 +02:00
1 parent 07191b1286
commit d3e49a925d
66 files changed
+6855 -905

No files matched your search

+94
View File
@@ -0,0 +1,94 @@
/*
* associations.cpp
* File type associations for the Files file manager
* Copyright (c) 2026 Daniel Hammer
*/
#include "filemanager_internal.hpp"
#include <montauk/config.h>
#include <gui/app_catalog.hpp>
namespace filemanager {
// Resolution is shared with the desktop (gui/app_catalog.hpp).
static bool assoc_item_launchable(const DesktopState* ds, const DesktopItem& item) {
return gui::app_catalog_launchable(ds, item);
}
static bool assoc_item_claims(const DesktopItem& item, const char* ext) {
return gui::app_catalog_claims(item, ext);
}
int filemanager_assoc_default(DesktopState* ds, const char* ext) {
return gui::app_catalog_default_for(ds, ext);
}
int filemanager_assoc_candidates(DesktopState* ds, const char* ext,
int* out, int max, int* recommended) {
if (recommended) *recommended = 0;
if (!ds || !out || max <= 0 || ds->desktop_item_count <= 0) return 0;
int* sorted = (int*)montauk::malloc((uint64_t)ds->desktop_item_count * sizeof(int));
if (!sorted) return 0;
int n = 0;
for (int i = 0; i < ds->desktop_item_count; i++) {
if (assoc_item_launchable(ds, ds->desktop_items[i])) sorted[n++] = i;
}
for (int i = 1; i < n; i++) {
int tmp = sorted[i];
int j = i - 1;
while (j >= 0 && str_compare_ci(ds->desktop_items[tmp].name,
ds->desktop_items[sorted[j]].name) < 0) {
sorted[j + 1] = sorted[j];
j--;
}
sorted[j + 1] = tmp;
}
// Apps that declare the type lead; any other regular app follows (an app
// that declares nothing may still open the file). Hidden and settings
// items only appear when they claim the type.
int count = 0;
for (int i = 0; i < n && count < max; i++) {
if (assoc_item_claims(ds->desktop_items[sorted[i]], ext)) out[count++] = sorted[i];
}
if (recommended) *recommended = count;
for (int i = 0; i < n && count < max; i++) {
const DesktopItem& item = ds->desktop_items[sorted[i]];
if (item.section == DESKTOP_ITEM_SECTION_APPS && !assoc_item_claims(item, ext))
out[count++] = sorted[i];
}
montauk::mfree(sorted);
return count;
}
bool filemanager_assoc_set_default(DesktopState* ds, const char* ext, int item_index) {
if (!ds || !ds->current_user[0] || !gui::app_catalog_ext_storable(ext)) return false;
if (item_index < 0 || item_index >= ds->desktop_item_count) return false;
auto doc = montauk::config::load_user(ds->current_user, gui::kAssociationsConfig);
char key[48];
gui::app_catalog_assoc_key(key, sizeof(key), ext);
montauk::config::set_string(&doc, key, ds->desktop_items[item_index].id);
int rc = montauk::config::save_user(ds->current_user, gui::kAssociationsConfig, &doc);
doc.destroy();
return rc == 0;
}
bool filemanager_file_looks_textual(const char* path) {
return gui::app_catalog_file_looks_textual(path);
}
bool filemanager_launch_with(DesktopState* ds, int item_index, const char* path) {
if (!ds || item_index < 0 || item_index >= ds->desktop_item_count) return false;
const DesktopItem& item = ds->desktop_items[item_index];
if (!assoc_item_launchable(ds, item)) return false;
// Apps that declare file types are started by the desktop, with the
// authority they get from the launcher. The desktop forwards a document
// path only to those, so anything else is started here.
if (item.file_types[0]) return files_host::launch_item(item.id, path);
return desktop_spawn_app(ds, item.binary_path, path) >= 0;
}
} // namespace filemanager