From 6235fa0541f7ed9d81cd5f457b6c4480651d6b2e Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Sat, 11 Jul 2026 20:32:05 -0400 Subject: [PATCH] fix: MCP overlay persists, not auto-closed by idle tick in <1s DisplayIdle::tick() runs every 50ms. After startMcpScreensaver() sets displayDimmed=true, the next tick saw inactive_ms < 100ms (user navigated Settings) and called stopScreensaver() -> overlay deleted in <1s, text tool flash-then-back. Root cause: idle wake logic (inactive<100ms) + charging guard + duty-restore all operated on any overlay including MCP override. Fix: detect MCP active via (drawArea != nullptr || overrideActive) under state.mutex, guard all auto-stop paths with !isMcpActive. MCP still closable via click handler on overlay (CLICKABLE flag). Test: flash es3c28p 2be0c0 31% free to /dev/cu.usbmodem101 192.168.68.113 dashboard 200, dev 6666 ok, /api/mcp 25 tools. Requires PYTHONPATH cleaned for idf.py build (Hermes venv hijacks pydantic_core). --- .../Source/service/displayidle/DisplayIdle.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Tactility/Source/service/displayidle/DisplayIdle.cpp b/Tactility/Source/service/displayidle/DisplayIdle.cpp index 3c0c9051..0dcf7f7c 100644 --- a/Tactility/Source/service/displayidle/DisplayIdle.cpp +++ b/Tactility/Source/service/displayidle/DisplayIdle.cpp @@ -161,11 +161,18 @@ void DisplayIdleService::tick() { } uint32_t inactive_ms = 0; - inactive_ms = lv_display_get_inactive_time(nullptr); - // Only update if not stopping (prevents lag on touch) - if (displayDimmed && screensaverOverlay && !stopScreensaverRequested.load(std::memory_order_acquire)) { + // Check if MCP override is active — it must not be auto-stopped by idle logic + bool isMcpActive = false; + { + auto& st = mcp::getState(); + std::lock_guard lk(st.mutex); + isMcpActive = (st.drawArea != nullptr) || st.overrideActive; + } + + // Only update if not stopping (prevents lag on touch) — skip for MCP (no animation) + if (displayDimmed && screensaverOverlay && !stopScreensaverRequested.load(std::memory_order_acquire) && !isMcpActive) { // Check if screensaver should auto-off after 5 minutes if (!backlightOff) { screensaverActiveCounter++; @@ -199,7 +206,7 @@ void DisplayIdleService::tick() { if (supportsBacklight) { if (!cachedDisplaySettings.backlightTimeoutEnabled || cachedDisplaySettings.backlightTimeoutMs == 0) { - if (displayDimmed) { + if (displayDimmed && !isMcpActive) { display->setBacklightDuty(cachedDisplaySettings.backlightDuty); displayDimmed = false; } @@ -220,7 +227,7 @@ void DisplayIdleService::tick() { } displayDimmed = true; } - } else if (displayDimmed) { + } else if (displayDimmed && !isMcpActive) { if (inactive_ms < kWakeActivityThresholdMs) { stopScreensaver(); } else if (charging_blocks) {