From ea44f0bba46fad2392c08f0406c69dcf0318e036 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Mon, 19 Jan 2026 15:01:40 +0100 Subject: [PATCH] Add simulator mode with app discovery and mosis.apps API Simulator mode (--simulator flag): - Starts from main home.rml instead of separate simulator home - Discovers apps from test-apps folder automatically - Shows discovered apps in home screen grid mosis.apps API for Lua: - getInstalled() returns array of discovered apps - launch(package_id) starts an app with its own sandbox goHome improvements: - Uses g_main_assets_path to find home.rml correctly - Works when running test apps directly - Properly clears current app state Co-Authored-By: Claude Opus 4.5 --- designer/main.cpp | 171 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 10 deletions(-) diff --git a/designer/main.cpp b/designer/main.cpp index ebb0e77..60c9749 100644 --- a/designer/main.cpp +++ b/designer/main.cpp @@ -66,6 +66,7 @@ static std::ofstream g_log_file; static bool g_simulator_mode = false; static std::string g_test_apps_path; // Path to test-apps directory static std::string g_simulator_home_path; // Path to simulator home.rml +static std::string g_main_assets_path; // Path to main assets (for goHome) static std::vector g_discovered_apps; static std::string g_current_app_id; // Currently running app (empty = home) @@ -364,27 +365,31 @@ int main(int argc, char* argv[]) { g_test_apps_path = fs::absolute(g_test_apps_path).string(); } - // Simulator home screen path - std::vector sim_search_paths = { - "simulator/home.rml", - "../designer/assets/simulator/home.rml", - fs::absolute("simulator/home.rml").string(), + // Find main assets home.rml for simulator mode + // Look for src/main/assets/apps/home/home.rml relative to test-apps + fs::path test_apps_fs = fs::path(g_test_apps_path); + std::vector home_search_paths = { + test_apps_fs.parent_path() / "src" / "main" / "assets" / "apps" / "home" / "home.rml", + fs::path("src/main/assets/apps/home/home.rml"), + fs::absolute("src/main/assets/apps/home/home.rml"), }; - for (const auto& path : sim_search_paths) { + for (const auto& path : home_search_paths) { if (fs::exists(path)) { g_simulator_home_path = fs::absolute(path).string(); break; } } - // Override document path to simulator home + // Override document path to main home screen if (!g_simulator_home_path.empty()) { document_path = g_simulator_home_path; + // Also set the main assets path for proper resource loading + g_main_assets_path = fs::path(g_simulator_home_path).parent_path().parent_path().parent_path().string(); std::cout << "Simulator mode enabled" << std::endl; std::cout << "Test apps path: " << g_test_apps_path << std::endl; - std::cout << "Simulator home: " << g_simulator_home_path << std::endl; + std::cout << "Home screen: " << g_simulator_home_path << std::endl; } else { - std::cerr << "Warning: Could not find simulator home.rml" << std::endl; + std::cerr << "Warning: Could not find home.rml for simulator" << std::endl; g_simulator_mode = false; } } @@ -453,6 +458,26 @@ int main(int argc, char* argv[]) { // Make assets_path absolute assets_path = fs::absolute(assets_path).string(); std::cout << "Assets path: " << assets_path << std::endl; + + // Determine main assets path (where home.rml lives) + // This is important for goHome() when running test apps + g_main_assets_path = assets_path; + + // Check if we're running from test-apps folder + fs::path assets_fs = fs::path(assets_path); + if (assets_fs.filename().string().find("com.") == 0 || + assets_fs.parent_path().filename() == "test-apps") { + // Running a test app - find the main assets + fs::path test_apps_root = assets_fs.parent_path(); + if (test_apps_root.filename() != "test-apps") { + test_apps_root = test_apps_root.parent_path(); + } + fs::path main_assets = test_apps_root.parent_path() / "src" / "main" / "assets"; + if (fs::exists(main_assets / "apps" / "home" / "home.rml")) { + g_main_assets_path = main_assets.string(); + std::cout << "Main assets: " << g_main_assets_path << std::endl; + } + } std::cout << "Resolution: " << g_width << "x" << g_height << std::endl; // Print mode info @@ -775,7 +800,46 @@ bool InitializeRmlUi(const std::string& assets_path, int fb_width, int fb_height return 1; }); lua_setglobal(L, "loadScreen"); - std::cout << "Registered Lua loadScreen function" << std::endl; + + // Register goHome function to return to home screen + lua_pushcfunction(L, [](lua_State* L) -> int { + if (!g_context) { + lua_pushboolean(L, false); + return 1; + } + + std::cout << "goHome called - returning to home screen" << std::endl; + + // Close existing documents (except debugger) + while (g_context->GetNumDocuments() > 1) { + auto* doc = g_context->GetDocument(0); + if (doc && doc->GetSourceURL().find("__rmlui") == std::string::npos) { + doc->Close(); + } else { + break; + } + } + + // Load home screen from main assets path + std::string home_path = (fs::path(g_main_assets_path) / "apps" / "home" / "home.rml").string(); + std::cout << "Loading home from: " << home_path << std::endl; + + auto* document = g_context->LoadDocument(home_path); + if (document) { + document->Show(); + g_current_document_path = home_path; + g_current_screen_url = home_path; + g_current_app_id = ""; // Clear current app + Rml::Log::Message(Rml::Log::LT_INFO, "Returned to home screen"); + lua_pushboolean(L, true); + } else { + Rml::Log::Message(Rml::Log::LT_ERROR, "Failed to load home screen from: %s", home_path.c_str()); + lua_pushboolean(L, false); + } + return 1; + }); + lua_setglobal(L, "goHome"); + std::cout << "Registered Lua loadScreen and goHome functions" << std::endl; // Register simulator API (if in simulator mode) if (g_simulator_mode) { @@ -938,6 +1002,93 @@ bool InitializeRmlUi(const std::string& assets_path, int fb_width, int fb_height lua_setglobal(L, "simulator"); std::cout << "Registered simulator Lua API" << std::endl; + + // Also register mosis.apps API for compatibility with home.lua + // Create mosis table (or get existing) + lua_getglobal(L, "mosis"); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_newtable(L); + } + + // Create mosis.apps table + lua_newtable(L); + + // mosis.apps.getInstalled() - returns installed apps + lua_pushcfunction(L, [](lua_State* L) -> int { + // Discover apps if not already done + if (g_discovered_apps.empty() && !g_test_apps_path.empty()) { + g_discovered_apps = mosis::AppDiscovery::DiscoverApps(g_test_apps_path); + std::cout << "Discovered " << g_discovered_apps.size() << " apps in " << g_test_apps_path << std::endl; + } + + // Create apps table (array format expected by home.lua) + lua_newtable(L); + int app_index = 1; + for (const auto& app : g_discovered_apps) { + lua_pushinteger(L, app_index++); + lua_newtable(L); + + lua_pushstring(L, app.name.c_str()); + lua_setfield(L, -2, "name"); + + lua_pushstring(L, app.id.c_str()); + lua_setfield(L, -2, "package_id"); + + lua_pushstring(L, app.GetIconPath().c_str()); + lua_setfield(L, -2, "icon"); + + lua_pushboolean(L, false); // Not a system app + lua_setfield(L, -2, "is_system_app"); + + lua_pushstring(L, app.app_path.c_str()); + lua_setfield(L, -2, "install_path"); + + lua_pushstring(L, app.entry.c_str()); + lua_setfield(L, -2, "entry_point"); + + lua_settable(L, -3); // apps[index] = app_table + } + return 1; + }); + lua_setfield(L, -2, "getInstalled"); + + // mosis.apps.launch(package_id) - launch an app + lua_pushcfunction(L, [](lua_State* L) -> int { + const char* package_id = luaL_checkstring(L, 1); + + // Find the app + for (const auto& app : g_discovered_apps) { + if (app.id == package_id) { + std::cout << "mosis.apps.launch: Starting " << package_id << std::endl; + g_current_app_id = package_id; + + // Reset sandbox for the new app + if (g_sandbox) { + g_sandbox->UnregisterAPIs(L); + g_sandbox->Reset(); + + mosis::DesktopSandboxConfig config; + config.app_id = package_id; + config.data_root = app.app_path + "/sandbox_data"; + g_sandbox = std::make_unique(config); + g_sandbox->RegisterAPIs(L); + } + + lua_pushboolean(L, true); + return 1; + } + } + + std::cerr << "mosis.apps.launch: App not found: " << package_id << std::endl; + lua_pushboolean(L, false); + return 1; + }); + lua_setfield(L, -2, "launch"); + + lua_setfield(L, -2, "apps"); // mosis.apps = apps_table + lua_setglobal(L, "mosis"); + std::cout << "Registered mosis.apps Lua API" << std::endl; } // Load fonts - search for fonts directory in multiple locations