diff --git a/cpp/framework/app_base.cpp b/cpp/framework/app_base.cpp index 96ed1cbf..ef0be521 100644 --- a/cpp/framework/app_base.cpp +++ b/cpp/framework/app_base.cpp @@ -464,13 +464,19 @@ int run_app(AppConfig config, std::function render_fn) { // Si auto_layouts esta gestionando el storage, aplica el layout // pendiente ANTES de que el render_fn cree ventanas. Si la app gestiona - // su propio storage, debe llamar layout_storage_apply_pending ella misma - // dentro de render_fn (patron que ya usan shaders_lab y graph_explorer). + // su propio storage, debe usar cfg.pre_frame para llamar + // layout_storage_apply_pending en el mismo punto. if (auto_layouts_storage) { std::string applied = fn_ui::layout_storage_apply_pending(auto_layouts_storage); if (!applied.empty()) auto_layouts_cb.active_name = applied; } + // Hook pre-frame de la app — se ejecuta despues de NewFrame y antes + // de menubar/auto-dockspace. Punto correcto para LoadIniSettingsFromMemory. + if (config.pre_frame) { + config.pre_frame(); + } + // Menubar canonica (View / Layouts / Settings / About) — siempre se // renderiza para que Settings/Logs/About esten disponibles aunque la // app no declare panels/layouts/view_extras propios. Se dibuja ANTES @@ -490,6 +496,14 @@ int run_app(AppConfig config, std::function render_fn) { config.layouts_cb, extras_fn, extras_user); } + // Auto-dockspace central. Permite re-anclar ventanas flotantes al + // main viewport sin que cada app llame DockSpaceOverViewport en su + // render(). Apps con layout custom ponen cfg.auto_dockspace=false. + if (config.auto_dockspace) { + ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), + ImGuiDockNodeFlags_PassthruCentralNode); + } + render_fn(); // Ventana de Settings (no-op si esta cerrada). @@ -665,6 +679,8 @@ int run_app_test(AppConfig config, ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); + if (config.pre_frame) config.pre_frame(); + render_fn(); ImGui::Render(); diff --git a/cpp/framework/app_base.h b/cpp/framework/app_base.h index a232cbf3..3a2e1a0c 100644 --- a/cpp/framework/app_base.h +++ b/cpp/framework/app_base.h @@ -143,11 +143,29 @@ struct AppConfig { // en Windows (en Linux es no-op). bool init_gl_loader = false; + // Auto-dockspace: si true, run_app llama + // ImGui::DockSpaceOverViewport(0, GetMainViewport(), PassthruCentralNode) + // ANTES de render_fn() cada frame. Asi cualquier app obtiene un dockspace + // central donde re-anclar ventanas flotantes (incl. viewports OS) sin + // tocar su render(). Apps con layout custom (shaders_lab) o galerias + // (primitives_gallery) pueden poner false para gestionarlo ellas. + bool auto_dockspace = true; + // Logging opcional. Si log.file_path != nullptr, run_app inicializa el // logger global antes del primer frame y lo cierra al exit. La ventana // "Logs..." en el menubar siempre esta disponible (lee del buffer // in-memory aunque no haya archivo). fn_ui::AppLogConfig log{}; + + // Hook opcional ejecutado al inicio de cada frame (despues de + // ImGui::NewFrame, ANTES de app_menubar y de auto-dockspace). Pensado para + // que apps con LayoutStorage propio llamen layout_storage_apply_pending + // en el momento correcto: ImGui requiere LoadIniSettingsFromMemory antes + // de cualquier Begin() del frame para que las dock-nodes guardadas se + // restauren correctamente. Si la app llama LoadIni mid-frame (dentro de + // render_fn) las ventanas docked aparecen flotantes hasta el siguiente + // ciclo. Default null = no-op. + std::function pre_frame{}; }; // Run an ImGui application. The render_fn is called every frame