From 598af546fd6f5d1bf8e2f87cab94110026a47962 Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Sat, 27 Jun 2026 09:41:40 -0400 Subject: [PATCH] fix: ensure backlight turns back on during startMcpScreensaver and invalidate canvas on drawText --- .../service/displayidle/DisplayIdleService.h | 6 ++ Tactility/Source/mcp/McpSystem.cpp | 9 +-- .../service/displayidle/DisplayIdle.cpp | 55 +++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Tactility/Private/Tactility/service/displayidle/DisplayIdleService.h b/Tactility/Private/Tactility/service/displayidle/DisplayIdleService.h index 8f71322c..53b31697 100644 --- a/Tactility/Private/Tactility/service/displayidle/DisplayIdleService.h +++ b/Tactility/Private/Tactility/service/displayidle/DisplayIdleService.h @@ -57,6 +57,12 @@ public: */ void startScreensaver(); + /** + * Force the MCP screensaver specifically, regardless of the current + * screensaver type setting. Safe to call from any thread (acquires LVGL lock). + */ + void startMcpScreensaver(); + /** * Force the screensaver to stop immediately and restore backlight. * @note Not thread-safe. Call from LVGL/main context only, not from diff --git a/Tactility/Source/mcp/McpSystem.cpp b/Tactility/Source/mcp/McpSystem.cpp index 62d72b70..929f2bb3 100644 --- a/Tactility/Source/mcp/McpSystem.cpp +++ b/Tactility/Source/mcp/McpSystem.cpp @@ -78,12 +78,12 @@ static bool display_ready(McpSystemState& state) { static bool ensureOverrideScreen() { auto& state = getState(); if (state.drawArea == nullptr) { - // Activate the MCP Screen screensaver via DisplayIdle + // Activate the MCP screensaver via DisplayIdle (force McpScreensaver type) auto idleService = service::displayidle::findService(); if (idleService) { - LOGGER.info("MCP draw triggered: starting MCP screensaver"); - idleService->startScreensaver(); - // Wait up to 500ms for the canvas to be registered + LOGGER.info("MCP draw triggered: activating MCP screensaver"); + idleService->startMcpScreensaver(); + // Wait up to 500ms for the canvas to be registered by McpScreensaver::start() for (int i = 0; i < 10; ++i) { vTaskDelay(pdMS_TO_TICKS(50)); if (state.drawArea != nullptr) { @@ -162,6 +162,7 @@ bool drawText(const std::string& text, int x, int y, int size) { } #endif + lv_obj_invalidate(state.drawArea); // Trigger repaint state.overrideActive = true; success = true; } diff --git a/Tactility/Source/service/displayidle/DisplayIdle.cpp b/Tactility/Source/service/displayidle/DisplayIdle.cpp index 1188fd6e..8bf5771c 100644 --- a/Tactility/Source/service/displayidle/DisplayIdle.cpp +++ b/Tactility/Source/service/displayidle/DisplayIdle.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -263,6 +264,60 @@ void DisplayIdleService::reloadSettings() { settingsReloadRequested.store(true, std::memory_order_release); } +void DisplayIdleService::startMcpScreensaver() { + if (!lvgl::lock(200)) { + LOGGER.warn("startMcpScreensaver: failed to acquire LVGL lock"); + return; + } + + if (screensaverOverlay != nullptr) { + // Screensaver already active — if drawArea is registered we're done, + // otherwise stop the current one so we can replace it with McpScreensaver. + const auto& mcpState = mcp::getState(); + if (mcpState.drawArea != nullptr) { + lvgl::unlock(); + return; // McpScreensaver already running + } + // Wrong screensaver type active — tear it down first + if (screensaver) { + screensaver->stop(); + screensaver.reset(); + } + lv_obj_delete(screensaverOverlay); + screensaverOverlay = nullptr; + } + + screensaverActiveCounter = 0; + backlightOff = false; + + // Ensure backlight is active and set to configured duty cycle + auto display = getDisplay(); + if (display) { + display->setBacklightDuty(cachedDisplaySettings.backlightDuty); + } + + lv_coord_t screenW = lv_display_get_horizontal_resolution(nullptr); + + lv_coord_t screenH = lv_display_get_vertical_resolution(nullptr); + + lv_obj_t* top = lv_layer_top(); + screensaverOverlay = lv_obj_create(top); + lv_obj_remove_style_all(screensaverOverlay); + lv_obj_set_size(screensaverOverlay, LV_PCT(100), LV_PCT(100)); + lv_obj_set_pos(screensaverOverlay, 0, 0); + lv_obj_set_style_bg_color(screensaverOverlay, lv_color_black(), 0); + lv_obj_set_style_bg_opa(screensaverOverlay, LV_OPA_COVER, 0); + lv_obj_add_flag(screensaverOverlay, LV_OBJ_FLAG_CLICKABLE); + lv_obj_add_event_cb(screensaverOverlay, stopScreensaverCb, LV_EVENT_CLICKED, this); + + screensaver = std::make_unique(); + screensaver->start(screensaverOverlay, screenW, screenH); + + lvgl::unlock(); + displayDimmed = true; + LOGGER.info("MCP screensaver activated"); +} + std::shared_ptr findService() { return std::static_pointer_cast( findServiceById("DisplayIdle")