Fix GIF emoji flickering by merging lock scopes in SetEmotion() (#1880)
* Initial plan * Fix GIF emoji flickering by merging lock scopes in SetEmotion() Remove the separate first lock scope that hid emoji_image_ before destroying gif_controller_ (added by PR #1848). Instead, move the gif_controller_ cleanup into each lock scope where new content is set, so destruction and creation happen atomically. This prevents both the original race condition crash AND the visible flickering. Co-authored-by: 78 <4488133+78@users.noreply.github.com> Agent-Logs-Url: https://github.com/78/xiaozhi-esp32/sessions/2dd0ff3a-4556-47a6-8d40-a30e18c01923 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: 78 <4488133+78@users.noreply.github.com>
This commit is contained in:
@ -1075,18 +1075,6 @@ void LcdDisplay::SetEmotion(const char* emotion) {
|
|||||||
if (!setup_ui_called_) {
|
if (!setup_ui_called_) {
|
||||||
ESP_LOGW(TAG, "SetEmotion('%s') called before SetupUI() - emotion will not be displayed!", emotion);
|
ESP_LOGW(TAG, "SetEmotion('%s') called before SetupUI() - emotion will not be displayed!", emotion);
|
||||||
}
|
}
|
||||||
// Stop any running GIF animation
|
|
||||||
if (gif_controller_) {
|
|
||||||
DisplayLockGuard lock(this);
|
|
||||||
gif_controller_->Stop();
|
|
||||||
// Hide image before destroying GIF controller to prevent LVGL from
|
|
||||||
// accessing freed image data during rendering between lock scopes
|
|
||||||
if (emoji_image_) {
|
|
||||||
lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
}
|
|
||||||
gif_controller_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emoji_image_ == nullptr) {
|
if (emoji_image_ == nullptr) {
|
||||||
if (setup_ui_called_) {
|
if (setup_ui_called_) {
|
||||||
ESP_LOGW(TAG, "SetEmotion('%s') failed: emoji_image_ is nullptr (SetupUI() was called but emoji image not created)", emotion);
|
ESP_LOGW(TAG, "SetEmotion('%s') failed: emoji_image_ is nullptr (SetupUI() was called but emoji image not created)", emotion);
|
||||||
@ -1100,6 +1088,10 @@ void LcdDisplay::SetEmotion(const char* emotion) {
|
|||||||
const char* utf8 = font_awesome_get_utf8(emotion);
|
const char* utf8 = font_awesome_get_utf8(emotion);
|
||||||
if (utf8 != nullptr && emoji_label_ != nullptr) {
|
if (utf8 != nullptr && emoji_label_ != nullptr) {
|
||||||
DisplayLockGuard lock(this);
|
DisplayLockGuard lock(this);
|
||||||
|
if (gif_controller_) {
|
||||||
|
gif_controller_->Stop();
|
||||||
|
gif_controller_.reset();
|
||||||
|
}
|
||||||
lv_label_set_text(emoji_label_, utf8);
|
lv_label_set_text(emoji_label_, utf8);
|
||||||
lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN);
|
||||||
lv_obj_remove_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_remove_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN);
|
||||||
@ -1108,6 +1100,12 @@ void LcdDisplay::SetEmotion(const char* emotion) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DisplayLockGuard lock(this);
|
DisplayLockGuard lock(this);
|
||||||
|
// Stop any running GIF animation in the same lock scope as setting new image
|
||||||
|
// to prevent LVGL from accessing freed image data between operations
|
||||||
|
if (gif_controller_) {
|
||||||
|
gif_controller_->Stop();
|
||||||
|
gif_controller_.reset();
|
||||||
|
}
|
||||||
if (image->IsGif()) {
|
if (image->IsGif()) {
|
||||||
// Create new GIF controller
|
// Create new GIF controller
|
||||||
gif_controller_ = std::make_unique<LvglGif>(image->image_dsc());
|
gif_controller_ = std::make_unique<LvglGif>(image->image_dsc());
|
||||||
|
|||||||
Reference in New Issue
Block a user