feat(ui): keep the wallet syncing while minimized
Previously the main loop just did SDL_Delay+continue when minimized, skipping app.update() — so the wallet stopped draining RPC results, ticking the refresh scheduler, and reconnecting until it was restored (and a large daemon-output backlog piled up, which is what produced the spurious "rescan complete" toast on restore). Now app.update() runs while minimized (it only reads GetIO/GetTime/IsAnyItemActive, all valid outside a NewFrame) with a real-clock DeltaTime, skipping only the ImGui frame + GPU present, throttled to ~5 Hz so CPU stays near-idle. Also clamp io.DeltaTime at the top of App::update() so a long minimize (or machine sleep) can't report a huge delta and fire every refresh/animation timer at once on the next update. No backlog now builds, so skipDaemonOutputBacklog becomes a harmless no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -739,6 +739,10 @@ void App::update()
|
|||||||
{
|
{
|
||||||
PERF_SCOPE("Update.Total");
|
PERF_SCOPE("Update.Total");
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
// Clamp the frame delta: after a long pause (window minimized, or the machine slept) NewFrame reports
|
||||||
|
// a huge DeltaTime that would fire every refresh/animation timer at once. Every timer reads
|
||||||
|
// io.DeltaTime, so one clamp here bounds them all (also caps the real-clock delta fed while minimized).
|
||||||
|
if (io.DeltaTime > 0.25f) io.DeltaTime = 0.25f;
|
||||||
|
|
||||||
// Full UI screenshot sweep: demo state is injected once and must stay frozen. Skip every live
|
// Full UI screenshot sweep: demo state is injected once and must stay frozen. Skip every live
|
||||||
// op (refresh/connect/pumps) so a real daemon can't clobber it — on Windows a running node's
|
// op (refresh/connect/pumps) so a real daemon can't clobber it — on Windows a running node's
|
||||||
|
|||||||
26
src/main.cpp
26
src/main.cpp
@@ -1500,6 +1500,7 @@ int main(int argc, char* argv[])
|
|||||||
// WINDOW_RESIZED events during the transition can't corrupt savedSizeForScale / lastKnownW/H.
|
// WINDOW_RESIZED events during the transition can't corrupt savedSizeForScale / lastKnownW/H.
|
||||||
int dpiSettleFrames = 0;
|
int dpiSettleFrames = 0;
|
||||||
SDL_DisplayID lastLoggedDisplay = 0; // [WINLOG] throttle: log MOVED only when the display changes
|
SDL_DisplayID lastLoggedDisplay = 0; // [WINLOG] throttle: log MOVED only when the display changes
|
||||||
|
Uint64 minimizedLastTickMs = 0; // real-clock tick for the minimized "keep syncing" update
|
||||||
{
|
{
|
||||||
float s = dragonx::ui::material::Typography::instance().getDpiScale();
|
float s = dragonx::ui::material::Typography::instance().getDpiScale();
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
@@ -1734,13 +1735,28 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Check if window is minimized
|
// Check if window is minimized
|
||||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
|
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
|
||||||
// Still check shouldQuit while minimized to avoid hang
|
// Keep the wallet syncing while minimized: run the logic update (drains RPC results, ticks the
|
||||||
if (app.shouldQuit()) {
|
// refresh scheduler, keeps the daemon connection/reconnect + sync status live) but skip the
|
||||||
running = false;
|
// ImGui frame + GPU present since nothing is visible. app.update() only reads
|
||||||
}
|
// GetIO()/GetTime()/IsAnyItemActive() — all valid outside a frame — so it's safe without a
|
||||||
SDL_Delay(10);
|
// NewFrame; feed it a real-clock DeltaTime (NewFrame, which normally sets it, is skipped) and
|
||||||
|
// let app.update() clamp it. Throttled to ~5 Hz so CPU stays near-idle (refresh cadences are
|
||||||
|
// seconds-scale). shouldQuit is still checked so a quit request never hangs behind minimize.
|
||||||
|
Uint64 nowMs = SDL_GetTicks();
|
||||||
|
float minDelta = (minimizedLastTickMs == 0) ? 0.001f
|
||||||
|
: (float)(nowMs - minimizedLastTickMs) / 1000.0f;
|
||||||
|
minimizedLastTickMs = nowMs;
|
||||||
|
ImGui::GetIO().DeltaTime = (minDelta > 0.0f) ? minDelta : 0.001f;
|
||||||
|
try {
|
||||||
|
app.update();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
DEBUG_LOGF("[Main] minimized app.update() threw: %s\n", e.what());
|
||||||
|
} catch (...) {}
|
||||||
|
if (app.shouldQuit()) running = false;
|
||||||
|
SDL_Delay(200);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
minimizedLastTickMs = 0; // visible again — reset the minimized clock
|
||||||
|
|
||||||
// --- PerfLog: begin frame ---
|
// --- PerfLog: begin frame ---
|
||||||
dragonx::util::PerfLog::instance().beginFrame();
|
dragonx::util::PerfLog::instance().beginFrame();
|
||||||
|
|||||||
Reference in New Issue
Block a user