fix: ensure backlight turns back on during startMcpScreensaver and invalidate canvas on drawText

This commit is contained in:
Adolfo Reyna
2026-06-27 09:41:40 -04:00
parent cd921e1aa9
commit 598af546fd
3 changed files with 66 additions and 4 deletions
@@ -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
+5 -4
View File
@@ -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;
}
@@ -16,6 +16,7 @@
#include <Tactility/service/ServiceContext.h>
#include <Tactility/service/ServiceManifest.h>
#include <Tactility/service/ServiceRegistration.h>
#include <Tactility/mcp/McpSystem.h>
#include <cstdlib>
#include <ctime>
@@ -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<McpScreensaver>();
screensaver->start(screensaverOverlay, screenW, screenH);
lvgl::unlock();
displayDimmed = true;
LOGGER.info("MCP screensaver activated");
}
std::shared_ptr<DisplayIdleService> findService() {
return std::static_pointer_cast<DisplayIdleService>(
findServiceById("DisplayIdle")