diff --git a/Tactility/Source/service/displayidle/DisplayIdle.cpp b/Tactility/Source/service/displayidle/DisplayIdle.cpp index 0dcf7f7c..c5f6afb6 100644 --- a/Tactility/Source/service/displayidle/DisplayIdle.cpp +++ b/Tactility/Source/service/displayidle/DisplayIdle.cpp @@ -147,6 +147,16 @@ void DisplayIdleService::updateScreensaver() { } void DisplayIdleService::tick() { + // Check if MCP override is active — must not be auto-stopped by idle logic + // READ OUTSIDE LVGL lock to avoid lock inversion: + // MCP video task locks mutex -> LVGL, we must NOT do LVGL -> mutex + bool isMcpActive = false; + { + auto& st = mcp::getState(); + std::lock_guard lk(st.mutex); + isMcpActive = (st.drawArea != nullptr) || st.overrideActive; + } + if (!lvgl::lock(100)) { return; } @@ -163,14 +173,6 @@ void DisplayIdleService::tick() { uint32_t inactive_ms = 0; inactive_ms = lv_display_get_inactive_time(nullptr); - // 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