#include "ui/interaction_handler.h" #include "ui/events.h" #include "esp_err.h" #include "esp_log.h" #define TAG "InteractionHandler" InteractionHandler::~InteractionHandler() { esp_err_t err = deinit(); if (err != ESP_OK) { ESP_LOGE(TAG, "Error during InteractionHandler deinit: %s", esp_err_to_name(err)); } } esp_err_t InteractionHandler::init(lv_obj_t* parent_container) { if (!parent_container) { ESP_LOGE(TAG, "Invalid argument: parent_container is nullptr"); return ESP_ERR_INVALID_ARG; } parent_container_ = parent_container; keyboard_ = lv_keyboard_create(parent_container_); if (!keyboard_) { ESP_LOGE(TAG, "Failed to create keyboard object"); return ESP_ERR_NO_MEM; } ESP_LOGI(TAG, "Keyboard created successfully at %p", keyboard_); lv_obj_add_flag(keyboard_, LV_OBJ_FLAG_HIDDEN); // start hidden lv_obj_add_event_cb( keyboard_, [](lv_event_t* e) { InteractionHandler* handler = static_cast(lv_event_get_user_data(e)); handler->on_keyboard_event_(e); } , LV_EVENT_ALL, this); return ESP_OK; } esp_err_t InteractionHandler::deinit(void) { if (keyboard_) { lv_obj_del(keyboard_); keyboard_ = nullptr; } return ESP_OK; } esp_err_t InteractionHandler::register_text_area_keyboard_support(lv_obj_t* text_area) { if (!text_area) { ESP_LOGE(TAG, "Invalid argument: text_area is nullptr"); return ESP_ERR_INVALID_ARG; } lv_obj_add_event_cb( text_area, [](lv_event_t* e) { lv_event_code_t code = lv_event_get_code(e); if (code != LV_EVENT_FOCUSED) { return; } InteractionHandler* handler = static_cast(lv_event_get_user_data(e)); esp_err_t err = handler->show_keyboard_for_textarea_(static_cast(lv_event_get_target(e))); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to show keyboard: %s", esp_err_to_name(err)); } } , LV_EVENT_FOCUSED, this); lv_obj_add_event_cb( text_area, [](lv_event_t* e) { lv_event_code_t code = lv_event_get_code(e); if (code != LV_EVENT_DEFOCUSED) { return; } InteractionHandler* handler = static_cast(lv_event_get_user_data(e)); esp_err_t err = handler->hide_keyboard_(); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to hide keyboard: %s", esp_err_to_name(err)); } } , LV_EVENT_DEFOCUSED, this); return ESP_OK; } // // Private methods // void InteractionHandler::on_keyboard_event_(lv_event_t* e) { lv_event_code_t code = lv_event_get_code(e); if (code == LV_EVENT_READY || code == LV_EVENT_CANCEL) { // Keyboard is cancelled esp_err_t err = hide_keyboard_(); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to hide keyboard: %s", esp_err_to_name(err)); } if (focused_textarea_) { lv_obj_clear_state(focused_textarea_, LV_STATE_FOCUSED); lv_keyboard_set_textarea(keyboard_, nullptr); focused_textarea_ = nullptr; } } } esp_err_t InteractionHandler::show_keyboard_for_textarea_(lv_obj_t* textarea) { if (!textarea) { ESP_LOGE(TAG, "Invalid argument: textarea is nullptr"); return ESP_ERR_INVALID_ARG; } if (!keyboard_) { ESP_LOGE(TAG, "Keyboard object is nullptr - was InteractionHandler properly initialized?"); return ESP_ERR_INVALID_STATE; } // Verify keyboard object is still valid if (!lv_obj_is_valid(keyboard_)) { ESP_LOGE(TAG, "Keyboard object is no longer valid - it may have been deleted"); keyboard_ = nullptr; return ESP_ERR_INVALID_STATE; } ESP_LOGI(TAG, "Showing keyboard for textarea %p", textarea); focused_textarea_ = textarea; lv_keyboard_set_textarea(keyboard_, textarea); lv_obj_clear_flag(keyboard_, LV_OBJ_FLAG_HIDDEN); // emit keyboard shown event KeyboardEventData event_data = { .textarea = textarea }; esp_err_t err = esp_event_post_to( NULL, UI_EVENT_BASE, UI_EVENT_KEYBOARD_SHOWN, &event_data, sizeof(event_data), portMAX_DELAY ); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to post keyboard shown event: %s", esp_err_to_name(err)); } return ESP_OK; } esp_err_t InteractionHandler::hide_keyboard_(void) { if (!keyboard_) { return ESP_ERR_INVALID_STATE; } lv_obj_add_flag(keyboard_, LV_OBJ_FLAG_HIDDEN); // emit keyboard hidden event KeyboardEventData event_data = { .textarea = nullptr }; esp_err_t err = esp_event_post_to( NULL, UI_EVENT_BASE, UI_EVENT_KEYBOARD_HIDDEN, &event_data, sizeof(event_data), portMAX_DELAY ); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to post keyboard hidden event: %s", esp_err_to_name(err)); } return ESP_OK; }