WIP fix issues introduced by lvgl version bump

custom
jacqueline 10 months ago
parent 64bd9053a2
commit e58dcf6dc5
  1. 2
      dependencies.lock
  2. 18
      lua/theme_dark.lua
  3. 18
      lua/theme_light.lua
  4. 10
      luals-stubs/lvgl.lua
  5. 52
      src/drivers/display.cpp
  6. 9
      src/drivers/include/drivers/display.hpp
  7. 14598
      src/graphics/splash.c
  8. 4
      src/tangara/input/feedback_haptics.cpp
  9. 10
      src/tangara/input/feedback_tts.cpp
  10. 2
      src/tangara/input/input_device.hpp
  11. 2
      src/tangara/input/input_hook.cpp
  12. 2
      src/tangara/input/input_hook.hpp
  13. 2
      src/tangara/input/input_hook_actions.cpp
  14. 1
      src/tangara/input/input_hook_actions.hpp
  15. 3
      src/tangara/input/input_nav_buttons.cpp
  16. 6
      src/tangara/input/input_nav_buttons.hpp
  17. 3
      src/tangara/input/input_touch_dpad.cpp
  18. 2
      src/tangara/input/input_touch_dpad.hpp
  19. 2
      src/tangara/input/input_touch_wheel.cpp
  20. 2
      src/tangara/input/input_touch_wheel.hpp
  21. 6
      src/tangara/input/input_trigger.hpp
  22. 6
      src/tangara/input/input_volume_buttons.hpp
  23. 53
      src/tangara/input/lvgl_input_driver.cpp
  24. 11
      src/tangara/input/lvgl_input_driver.hpp
  25. 3
      src/tangara/lua/bridge.cpp
  26. 32
      src/tangara/ui/lvgl_task.cpp
  27. 57
      src/tangara/ui/modal.cpp
  28. 36
      src/tangara/ui/modal.hpp
  29. 8
      src/tangara/ui/screen.cpp
  30. 11
      src/tangara/ui/screen.hpp
  31. 2
      src/tangara/ui/screen_splash.cpp
  32. 18
      src/tangara/ui/themes.cpp
  33. 11
      src/tangara/ui/ui_events.hpp
  34. 24
      src/tangara/ui/ui_fsm.cpp
  35. 9
      src/tangara/ui/ui_fsm.hpp

@ -4,6 +4,6 @@ dependencies:
source: source:
type: idf type: idf
version: 5.2.1 version: 5.2.1
manifest_hash: 9e4320e6f25503854c6c93bcbfa9b80f780485bcf066bdbad31a820544492538 manifest_hash: ef2ae3a0fda058a8cda5b69636300c99782b077919557a63f8f572a6a9e0707b
target: esp32 target: esp32
version: 1.0.0 version: 1.0.0

@ -43,14 +43,14 @@ local theme_dark = {
pad_top = 1, pad_top = 1,
pad_bottom = 1, pad_bottom = 1,
bg_color = background_color, bg_color = background_color,
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = highlight_color, image_recolor = highlight_color,
radius = 5, radius = 5,
}}, }},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style { {lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100), bg_opa = lvgl.OPA(100),
bg_color = highlight_color, bg_color = highlight_color,
img_recolor_opa = 0, image_recolor_opa = 0,
}}, }},
}, },
listbutton = { listbutton = {
@ -146,8 +146,8 @@ local theme_dark = {
}, },
database_indicator = { database_indicator = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = highlight_color, image_recolor = highlight_color,
}}, }},
}, },
settings_title = { settings_title = {
@ -160,14 +160,14 @@ local theme_dark = {
}, },
icon_disabled = { icon_disabled = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = icon_disabled_color, image_recolor = icon_disabled_color,
}}, }},
}, },
icon_enabled = { icon_enabled = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = icon_enabled_color, image_recolor = icon_enabled_color,
}}, }},
}, },

@ -41,14 +41,14 @@ local theme_light = {
pad_top = 1, pad_top = 1,
pad_bottom = 1, pad_bottom = 1,
bg_color = background_color, bg_color = background_color,
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = highlight_color, image_recolor = highlight_color,
radius = 5, radius = 5,
}}, }},
{lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style { {lvgl.PART.MAIN | lvgl.STATE.FOCUSED, lvgl.Style {
bg_opa = lvgl.OPA(100), bg_opa = lvgl.OPA(100),
bg_color = highlight_color, bg_color = highlight_color,
img_recolor_opa = 0, image_recolor_opa = 0,
}}, }},
}, },
listbutton = { listbutton = {
@ -144,8 +144,8 @@ local theme_light = {
}, },
database_indicator = { database_indicator = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = highlight_color, image_recolor = highlight_color,
}}, }},
}, },
settings_title = { settings_title = {
@ -158,14 +158,14 @@ local theme_light = {
}, },
icon_disabled = { icon_disabled = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = icon_disabled_color, image_recolor = icon_disabled_color,
}}, }},
}, },
icon_enabled = { icon_enabled = {
{lvgl.PART.MAIN, lvgl.Style { {lvgl.PART.MAIN, lvgl.Style {
img_recolor_opa = 180, image_recolor_opa = 180,
img_recolor = icon_enabled_color, image_recolor = icon_enabled_color,
}}, }},
}, },

@ -418,13 +418,11 @@ end
function lvgl.Timer(p) function lvgl.Timer(p)
end end
--- Create a new a font. Currently only the inbuilt "fusion" font family is --- Create a new a font. Fonts can be located on internal flash or the SD card,
--- available, in "normal" weight and sizes 12 and 10. --- and must be in LVGL's binary font format.
--- @param family string Name of the font family. --- @param path string location of the binary font file
--- @param size integer the font size in px
--- @param weight string the weight of the font. e.g.g "normal", "bold", "light"
--- @return Font --- @return Font
function lvgl.Font(family, size, weight) function lvgl.Font(path)
end end
--- Decodes an image from the filesystem and pins it into RAM, returning a --- Decodes an image from the filesystem and pins it into RAM, returning a

@ -13,6 +13,8 @@
#include <memory> #include <memory>
#include "assert.h" #include "assert.h"
#include "display/lv_display.h"
#include "draw/sw/lv_draw_sw.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/ledc.h" #include "driver/ledc.h"
#include "driver/spi_common.h" #include "driver/spi_common.h"
@ -27,7 +29,6 @@
#include "freertos/projdefs.h" #include "freertos/projdefs.h"
#include "hal/gpio_types.h" #include "hal/gpio_types.h"
#include "hal/ledc_types.h" #include "hal/ledc_types.h"
#include "hal/lv_hal_disp.h"
#include "hal/spi_types.h" #include "hal/spi_types.h"
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
@ -61,13 +62,11 @@ namespace drivers {
/* /*
* Callback invoked by LVGL when there is new data to be written to the display. * Callback invoked by LVGL when there is new data to be written to the display.
*/ */
extern "C" void FlushDataCallback(lv_disp_drv_t* disp_drv, extern "C" void FlushDataCallback(lv_display_t* display,
const lv_area_t* area, const lv_area_t* area,
lv_color_t* color_map) { uint8_t* px_map) {
taskYIELD(); Display* instance = static_cast<Display*>(lv_display_get_user_data(display));
Display* instance = static_cast<Display*>(disp_drv->user_data); instance->OnLvglFlush(area, px_map);
instance->OnLvglFlush(disp_drv, area, color_map);
taskYIELD();
} }
auto Display::Create(IGpios& expander, auto Display::Create(IGpios& expander,
@ -149,21 +148,16 @@ auto Display::Create(IGpios& expander,
// driver. // driver.
ESP_LOGI(kTag, "Init buffers"); ESP_LOGI(kTag, "Init buffers");
assert(esp_ptr_dma_capable(kDisplayBuffer)); assert(esp_ptr_dma_capable(kDisplayBuffer));
lv_disp_draw_buf_init(&display->buffers_, kDisplayBuffer, NULL,
kDisplayBufferSize); ESP_LOGI(kTag, "Creating display");
display->display_ = lv_display_create(init_data.width, init_data.height);
lv_disp_drv_init(&display->driver_); lv_display_set_buffers(display->display_, kDisplayBuffer, NULL,
display->driver_.draw_buf = &display->buffers_; sizeof(kDisplayBuffer),
display->driver_.hor_res = init_data.width; LV_DISPLAY_RENDER_MODE_PARTIAL);
display->driver_.ver_res = init_data.height; lv_display_set_color_format(display->display_, LV_COLOR_FORMAT_RGB565);
display->driver_.sw_rotate = 0; lv_display_set_user_data(display->display_, display.get());
display->driver_.rotated = LV_DISP_ROT_NONE; lv_display_set_flush_cb(display->display_, &FlushDataCallback);
display->driver_.antialiasing = 0; lv_display_set_default(display->display_);
display->driver_.flush_cb = &FlushDataCallback;
display->driver_.user_data = display.get();
ESP_LOGI(kTag, "Registering driver");
display->display_ = lv_disp_drv_register(&display->driver_);
return display.release(); return display.release();
} }
@ -288,9 +282,12 @@ void Display::SendTransaction(TransactionType type,
ESP_ERROR_CHECK(spi_device_transmit(handle_, &sTransaction)); ESP_ERROR_CHECK(spi_device_transmit(handle_, &sTransaction));
} }
void Display::OnLvglFlush(lv_disp_drv_t* disp_drv, void Display::OnLvglFlush(const lv_area_t* area, uint8_t* color_map) {
const lv_area_t* area, // Swap the pixel byte order first, since we don't want to do this whilst
lv_color_t* color_map) { // holding the SPI bus lock.
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
lv_draw_sw_rgb565_swap(color_map, size);
spi_device_acquire_bus(handle_, portMAX_DELAY); spi_device_acquire_bus(handle_, portMAX_DELAY);
// First we need to specify the rectangle of the display we're writing into. // First we need to specify the rectangle of the display we're writing into.
@ -307,18 +304,17 @@ void Display::OnLvglFlush(lv_disp_drv_t* disp_drv,
4); 4);
// Now send the pixels for this region. // Now send the pixels for this region.
uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
SendCommandWithData(displays::ST77XX_RAMWR, SendCommandWithData(displays::ST77XX_RAMWR,
reinterpret_cast<uint8_t*>(color_map), size * 2); reinterpret_cast<uint8_t*>(color_map), size * 2);
spi_device_release_bus(handle_); spi_device_release_bus(handle_);
if (!first_flush_finished_ && lv_disp_flush_is_last(disp_drv)) { if (!first_flush_finished_ && lv_disp_flush_is_last(display_)) {
first_flush_finished_ = true; first_flush_finished_ = true;
SetDisplayOn(display_on_); SetDisplayOn(display_on_);
} }
lv_disp_flush_ready(&driver_); lv_display_flush_ready(display_);
} }
} // namespace drivers } // namespace drivers

@ -12,6 +12,7 @@
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#include "misc/lv_types.h"
#include "result.hpp" #include "result.hpp"
#include "tasks.hpp" #include "tasks.hpp"
@ -40,9 +41,7 @@ class Display {
auto SetBrightness(uint_fast8_t) -> void; auto SetBrightness(uint_fast8_t) -> void;
/* Driver callback invoked by LVGL when there is new data to display. */ /* Driver callback invoked by LVGL when there is new data to display. */
void OnLvglFlush(lv_disp_drv_t* disp_drv, void OnLvglFlush(const lv_area_t* area, uint8_t* px_map);
const lv_area_t* area,
lv_color_t* color_map);
// Not copyable or movable. // Not copyable or movable.
Display(const Display&) = delete; Display(const Display&) = delete;
@ -56,9 +55,7 @@ class Display {
bool display_on_; bool display_on_;
uint_fast8_t brightness_; uint_fast8_t brightness_;
lv_disp_draw_buf_t buffers_; lv_display_t* display_ = nullptr;
lv_disp_drv_t driver_;
lv_disp_t* display_ = nullptr;
enum TransactionType { enum TransactionType {
COMMAND = 0, COMMAND = 0,

File diff suppressed because it is too large Load Diff

@ -9,10 +9,8 @@
#include <cstdint> #include <cstdint>
#include "core/lv_group.h" #include "core/lv_group.h"
#include "lvgl/lvgl.h"
#include "core/lv_event.h"
#include "esp_log.h" #include "esp_log.h"
#include "lvgl/lvgl.h"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"

@ -11,14 +11,14 @@
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#include "core/lv_event.h"
#include "core/lv_group.h" #include "core/lv_group.h"
#include "core/lv_obj.h" #include "core/lv_obj.h"
#include "core/lv_obj_class.h" #include "core/lv_obj_class.h"
#include "core/lv_obj_tree.h" #include "core/lv_obj_tree.h"
#include "extra/widgets/list/lv_list.h"
#include "tts/events.hpp" #include "tts/events.hpp"
#include "widgets/lv_label.h" #include "widgets/button/lv_button.h"
#include "widgets/label/lv_label.h"
#include "widgets/list/lv_list.h"
#include "tts/events.hpp" #include "tts/events.hpp"
#include "tts/provider.hpp" #include "tts/provider.hpp"
@ -51,8 +51,8 @@ auto TextToSpeech::feedback(lv_group_t* group, uint8_t event_type) -> void {
} }
auto TextToSpeech::describe(lv_obj_t& obj) -> void { auto TextToSpeech::describe(lv_obj_t& obj) -> void {
if (lv_obj_check_type(&obj, &lv_btn_class) || if (lv_obj_check_type(&obj, &lv_button_class) ||
lv_obj_check_type(&obj, &lv_list_btn_class)) { lv_obj_check_type(&obj, &lv_list_button_class)) {
auto desc = findDescription(obj); auto desc = findDescription(obj);
tts_.feed(tts::SelectionChanged{ tts_.feed(tts::SelectionChanged{
.new_selection = .new_selection =

@ -10,7 +10,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "input/input_hook.hpp" #include "input/input_hook.hpp"
#include "lua/property.hpp" #include "lua/property.hpp"

@ -9,7 +9,7 @@
#include <functional> #include <functional>
#include <optional> #include <optional>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "lua.hpp" #include "lua.hpp"
#include "input/input_trigger.hpp" #include "input/input_trigger.hpp"

@ -10,7 +10,7 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "lua.hpp" #include "lua.hpp"
#include "input/input_trigger.hpp" #include "input/input_trigger.hpp"

@ -8,7 +8,7 @@
#include <cstdint> #include <cstdint>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "events/event_queue.hpp" #include "events/event_queue.hpp"
#include "ui/ui_events.hpp" #include "ui/ui_events.hpp"

@ -6,7 +6,6 @@
#pragma once #pragma once
#include "hal/lv_hal_indev.h"
#include "input/input_hook.hpp" #include "input/input_hook.hpp"
namespace input { namespace input {

@ -6,9 +6,10 @@
#include "input/input_nav_buttons.hpp" #include "input/input_nav_buttons.hpp"
#include "indev/lv_indev.h"
#include "drivers/gpios.hpp" #include "drivers/gpios.hpp"
#include "events/event_queue.hpp" #include "events/event_queue.hpp"
#include "hal/lv_hal_indev.h"
#include "input/input_hook_actions.hpp" #include "input/input_hook_actions.hpp"
namespace input { namespace input {

@ -8,14 +8,14 @@
#include <cstdint> #include <cstdint>
#include "drivers/gpios.hpp" #include "indev/lv_indev.h"
#include "hal/lv_hal_indev.h"
#include "drivers/gpios.hpp"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "drivers/touchwheel.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "input/input_hook.hpp" #include "input/input_hook.hpp"
#include "input/input_trigger.hpp" #include "input/input_trigger.hpp"
#include "drivers/touchwheel.hpp"
namespace input { namespace input {

@ -8,11 +8,10 @@
#include <cstdint> #include <cstdint>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "drivers/touchwheel.hpp" #include "drivers/touchwheel.hpp"
#include "events/event_queue.hpp" #include "events/event_queue.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "input/input_hook_actions.hpp" #include "input/input_hook_actions.hpp"

@ -8,7 +8,7 @@
#include <cstdint> #include <cstdint>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"

@ -9,7 +9,7 @@
#include <cstdint> #include <cstdint>
#include <variant> #include <variant>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "drivers/nvs.hpp" #include "drivers/nvs.hpp"

@ -9,7 +9,7 @@
#include <sys/_stdint.h> #include <sys/_stdint.h>
#include <cstdint> #include <cstdint>
#include "hal/lv_hal_indev.h" #include "indev/lv_indev.h"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"

@ -9,13 +9,11 @@
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
#include "hal/lv_hal_indev.h"
namespace input { namespace input {
const uint16_t kDoubleClickDelayMs = 500; const uint16_t kDoubleClickDelayMs = 500;
const uint16_t kLongPressDelayMs = LV_INDEV_DEF_LONG_PRESS_TIME; const uint16_t kLongPressDelayMs = 400;
const uint16_t kRepeatDelayMs = LV_INDEV_DEF_LONG_PRESS_REP_TIME; const uint16_t kRepeatDelayMs = 100;
class Trigger { class Trigger {
public: public:

@ -8,13 +8,13 @@
#include <cstdint> #include <cstdint>
#include "drivers/gpios.hpp" #include "indev/lv_indev.h"
#include "hal/lv_hal_indev.h"
#include "drivers/gpios.hpp"
#include "drivers/haptics.hpp" #include "drivers/haptics.hpp"
#include "drivers/touchwheel.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "input/input_hook.hpp" #include "input/input_hook.hpp"
#include "drivers/touchwheel.hpp"
namespace input { namespace input {

@ -10,8 +10,8 @@
#include <memory> #include <memory>
#include <variant> #include <variant>
#include "core/lv_event.h" #include "core/lv_group.h"
#include "core/lv_indev.h" #include "indev/lv_indev.h"
#include "lua.hpp" #include "lua.hpp"
#include "lvgl.h" #include "lvgl.h"
@ -25,6 +25,7 @@
#include "input/input_volume_buttons.hpp" #include "input/input_volume_buttons.hpp"
#include "lua/lua_thread.hpp" #include "lua/lua_thread.hpp"
#include "lua/property.hpp" #include "lua/property.hpp"
#include "misc/lv_event.h"
[[maybe_unused]] static constexpr char kTag[] = "input"; [[maybe_unused]] static constexpr char kTag[] = "input";
@ -33,16 +34,22 @@ static constexpr char kLuaOverrideText[] = "lua_callback";
namespace input { namespace input {
static void read_cb(lv_indev_drv_t* drv, lv_indev_data_t* data) { static void read_cb(lv_indev_t* dev, lv_indev_data_t* data) {
LvglInputDriver* instance = LvglInputDriver* instance =
reinterpret_cast<LvglInputDriver*>(drv->user_data); reinterpret_cast<LvglInputDriver*>(lv_indev_get_user_data(dev));
instance->read(data); instance->read(data);
} }
static void feedback_cb(lv_indev_drv_t* drv, uint8_t event) { static void feedback_cb(lv_event_t* ev) {
LvglInputDriver* instance = LvglInputDriver* instance =
reinterpret_cast<LvglInputDriver*>(drv->user_data); reinterpret_cast<LvglInputDriver*>(lv_event_get_user_data(ev));
instance->feedback(event); instance->feedback(lv_event_get_code(ev));
}
static void focus_cb(lv_group_t* group) {
LvglInputDriver* instance =
reinterpret_cast<LvglInputDriver*>(group->user_data);
instance->feedback(LV_EVENT_FOCUSED);
} }
auto intToMode(int raw) -> std::optional<drivers::NvsStorage::InputModes> { auto intToMode(int raw) -> std::optional<drivers::NvsStorage::InputModes> {
@ -77,29 +84,31 @@ LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs,
inputs_ = factory.createInputs(*mode); inputs_ = factory.createInputs(*mode);
return true; return true;
}), }),
driver_(),
registration_(nullptr),
inputs_(factory.createInputs(nvs.PrimaryInput())), inputs_(factory.createInputs(nvs.PrimaryInput())),
feedbacks_(factory.createFeedbacks()), feedbacks_(factory.createFeedbacks()),
is_locked_(false) { is_locked_(false) {
lv_indev_drv_init(&driver_); device_ = lv_indev_create();
driver_.type = LV_INDEV_TYPE_ENCODER; lv_indev_set_type(device_, LV_INDEV_TYPE_ENCODER);
driver_.read_cb = read_cb; lv_indev_set_user_data(device_, this);
driver_.feedback_cb = feedback_cb; lv_indev_set_read_cb(device_, read_cb);
driver_.user_data = this; lv_indev_add_event_cb(device_, feedback_cb, LV_EVENT_ALL, this);
driver_.long_press_time = kLongPressDelayMs;
driver_.long_press_repeat_time = kRepeatDelayMs;
registration_ = lv_indev_drv_register(&driver_);
} }
auto LvglInputDriver::setGroup(lv_group_t* g) -> void { auto LvglInputDriver::setGroup(lv_group_t* g) -> void {
lv_group_t* prev = lv_indev_get_group(device_);
if (prev && prev != g) {
lv_group_set_focus_cb(prev, NULL);
}
if (!g) { if (!g) {
return; return;
} }
lv_indev_set_group(registration_, g); lv_indev_set_group(device_, g);
// Emit a synthetic 'focus' event for the current selection, since otherwise
// our feedback devices won't know that the selection changed. g->user_data = this;
lv_group_set_focus_cb(g, focus_cb);
// Emit a synthetic 'focus' event for the current selection, since
// otherwise our feedback devices won't know that the selection changed.
feedback(LV_EVENT_FOCUSED); feedback(LV_EVENT_FOCUSED);
} }
@ -119,7 +128,7 @@ auto LvglInputDriver::feedback(uint8_t event) -> void {
return; return;
} }
for (auto&& device : feedbacks_) { for (auto&& device : feedbacks_) {
device->feedback(registration_->group, event); device->feedback(lv_indev_get_group(device_), event);
} }
} }

@ -12,13 +12,13 @@
#include <set> #include <set>
#include "core/lv_group.h" #include "core/lv_group.h"
#include "drivers/gpios.hpp" #include "indev/lv_indev.h"
#include "hal/lv_hal_indev.h"
#include "input/device_factory.hpp"
#include "input/feedback_device.hpp"
#include "drivers/gpios.hpp"
#include "drivers/nvs.hpp" #include "drivers/nvs.hpp"
#include "drivers/touchwheel.hpp" #include "drivers/touchwheel.hpp"
#include "input/device_factory.hpp"
#include "input/feedback_device.hpp"
#include "input/input_device.hpp" #include "input/input_device.hpp"
#include "input/input_hook.hpp" #include "input/input_hook.hpp"
#include "lua/lua_thread.hpp" #include "lua/lua_thread.hpp"
@ -50,8 +50,7 @@ class LvglInputDriver {
DeviceFactory& factory_; DeviceFactory& factory_;
lua::Property mode_; lua::Property mode_;
lv_indev_drv_t driver_; lv_indev_t* device_;
lv_indev_t* registration_;
std::vector<std::shared_ptr<IInputDevice>> inputs_; std::vector<std::shared_ptr<IInputDevice>> inputs_;
std::vector<std::shared_ptr<IFeedbackDevice>> feedbacks_; std::vector<std::shared_ptr<IFeedbackDevice>> feedbacks_;

@ -26,7 +26,6 @@
#include "lua/lua_version.hpp" #include "lua/lua_version.hpp"
#include "lvgl.h" #include "lvgl.h"
#include "font/lv_font_loader.h"
#include "luavgl.h" #include "luavgl.h"
#include "events/event_queue.hpp" #include "events/event_queue.hpp"
@ -61,7 +60,7 @@ static auto make_font_cb(const char* name, int size, int weight)
return NULL; return NULL;
} }
static auto delete_font_cb(lv_font_t* font) -> void {} static auto delete_font_cb(const lv_font_t* font) -> void {}
auto Bridge::Get(lua_State* state) -> Bridge* { auto Bridge::Get(lua_State* state) -> Bridge* {
lua_pushstring(state, kBridgeKey); lua_pushstring(state, kBridgeKey);

@ -6,45 +6,27 @@
#include "ui/lvgl_task.hpp" #include "ui/lvgl_task.hpp"
#include <dirent.h>
#include <stdint.h>
#include <stdio.h>
#include <cstddef>
#include <cstdint>
#include <memory>
#include "core/lv_disp.h"
#include "core/lv_group.h" #include "core/lv_group.h"
#include "core/lv_indev.h"
#include "core/lv_obj.h" #include "core/lv_obj.h"
#include "core/lv_obj_pos.h" #include "core/lv_obj_pos.h"
#include "core/lv_obj_tree.h" #include "core/lv_obj_tree.h"
#include "drivers/touchwheel.hpp" #include "core/lv_refr.h"
#include "display/lv_display.h"
#include "esp_log.h" #include "esp_log.h"
#include "events/event_queue.hpp"
#include "extra/themes/basic/lv_theme_basic.h"
#include "font/lv_font.h"
#include "freertos/portmacro.h" #include "freertos/portmacro.h"
#include "freertos/projdefs.h" #include "freertos/projdefs.h"
#include "freertos/timers.h" #include "freertos/timers.h"
#include "hal/gpio_types.h"
#include "hal/lv_hal_indev.h"
#include "hal/spi_types.h"
#include "input/lvgl_input_driver.hpp"
#include "lua.h" #include "lua.h"
#include "lv_api_map.h"
#include "lvgl/lvgl.h" #include "lvgl/lvgl.h"
#include "misc/lv_color.h" #include "misc/lv_color.h"
#include "misc/lv_style.h" #include "misc/lv_style.h"
#include "misc/lv_timer.h" #include "misc/lv_timer.h"
#include "tasks.hpp"
#include "ui/modal.hpp"
#include "ui/ui_fsm.hpp"
#include "widgets/lv_label.h"
#include "drivers/display.hpp" #include "drivers/display.hpp"
#include "drivers/gpios.hpp" #include "events/event_queue.hpp"
#include "input/lvgl_input_driver.hpp"
#include "tasks.hpp"
#include "ui/ui_fsm.hpp"
namespace ui { namespace ui {
@ -66,7 +48,7 @@ auto UiTask::Main() -> void {
std::shared_ptr<Screen> screen = UiState::current_screen(); std::shared_ptr<Screen> screen = UiState::current_screen();
if (screen != current_screen_ && screen != nullptr) { if (screen != current_screen_ && screen != nullptr) {
lv_scr_load(screen->root()); lv_screen_load(screen->root());
if (input_) { if (input_) {
input_->setGroup(screen->group()); input_->setGroup(screen->group());
} }

@ -1,57 +0,0 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "ui/modal.hpp"
#include "misc/lv_color.h"
#include "core/lv_event.h"
#include "esp_log.h"
#include "core/lv_group.h"
#include "core/lv_obj_pos.h"
#include "database/index.hpp"
#include "events/event_queue.hpp"
#include "extra/widgets/list/lv_list.h"
#include "extra/widgets/menu/lv_menu.h"
#include "extra/widgets/spinner/lv_spinner.h"
#include "hal/lv_hal_disp.h"
#include "misc/lv_area.h"
#include "ui/screen.hpp"
#include "ui/themes.hpp"
#include "ui/ui_events.hpp"
#include "ui/ui_fsm.hpp"
#include "widgets/lv_label.h"
namespace ui {
Modal::Modal(Screen* host)
: root_(lv_obj_create(host->modal_content())),
group_(lv_group_create()),
host_(host) {
lv_obj_set_style_bg_opa(host->modal_content(), LV_OPA_40, 0);
lv_obj_set_size(root_, 120, LV_SIZE_CONTENT);
lv_obj_center(root_);
lv_obj_set_style_bg_opa(root_, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(root_, lv_color_white(), 0);
host_->modal_group(group_);
}
Modal::~Modal() {
host_->modal_group(nullptr);
lv_obj_set_style_bg_opa(host_->modal_content(), LV_OPA_TRANSP, 0);
// The group *must* be deleted first. Otherwise, focus events will be
// generated whilst deleting the object tree, which causes a big mess.
lv_group_del(group_);
lv_obj_del(root_);
}
} // namespace ui

@ -1,36 +0,0 @@
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#pragma once
#include <memory>
#include "core/lv_group.h"
#include "core/lv_obj.h"
#include "core/lv_obj_tree.h"
#include "lvgl.h"
#include "ui/screen.hpp"
namespace ui {
class Modal {
public:
Modal(Screen* host);
virtual ~Modal();
auto root() -> lv_obj_t* { return root_; }
auto group() -> lv_group_t* { return group_; }
protected:
lv_obj_t* const root_;
lv_group_t* const group_;
private:
Screen* host_;
};
} // namespace ui

@ -10,7 +10,6 @@
#include "core/lv_obj_pos.h" #include "core/lv_obj_pos.h"
#include "core/lv_obj_tree.h" #include "core/lv_obj_tree.h"
#include "hal/lv_hal_disp.h"
#include "misc/lv_area.h" #include "misc/lv_area.h"
#include "misc/lv_color.h" #include "misc/lv_color.h"
@ -19,20 +18,15 @@ namespace ui {
Screen::Screen() Screen::Screen()
: root_(lv_obj_create(NULL)), : root_(lv_obj_create(NULL)),
content_(lv_obj_create(root_)), content_(lv_obj_create(root_)),
modal_content_(lv_obj_create(root_)),
alert_(lv_obj_create(root_)), alert_(lv_obj_create(root_)),
group_(lv_group_create()), group_(lv_group_create()) {
modal_group_(nullptr) {
lv_obj_set_size(root_, lv_pct(100), lv_pct(100)); lv_obj_set_size(root_, lv_pct(100), lv_pct(100));
lv_obj_set_size(content_, lv_pct(100), lv_pct(100)); lv_obj_set_size(content_, lv_pct(100), lv_pct(100));
lv_obj_set_size(modal_content_, lv_pct(100), lv_pct(100));
lv_obj_set_size(alert_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_set_size(alert_, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_center(root_); lv_obj_center(root_);
lv_obj_center(content_); lv_obj_center(content_);
lv_obj_center(modal_content_);
lv_obj_center(alert_); lv_obj_center(alert_);
lv_obj_set_style_bg_opa(modal_content_, LV_OPA_TRANSP, 0);
lv_obj_set_style_bg_opa(alert_, LV_OPA_TRANSP, 0); lv_obj_set_style_bg_opa(alert_, LV_OPA_TRANSP, 0);
lv_obj_set_scrollbar_mode(root_, LV_SCROLLBAR_MODE_OFF); lv_obj_set_scrollbar_mode(root_, LV_SCROLLBAR_MODE_OFF);

@ -34,25 +34,16 @@ class Screen {
auto content() -> lv_obj_t* { return content_; } auto content() -> lv_obj_t* { return content_; }
auto alert() -> lv_obj_t* { return alert_; } auto alert() -> lv_obj_t* { return alert_; }
auto modal_content() -> lv_obj_t* { return modal_content_; } auto group() -> lv_group_t* { return group_; }
auto modal_group(lv_group_t* g) -> void { modal_group_ = g; }
auto group() -> lv_group_t* {
if (modal_group_) {
return modal_group_;
}
return group_;
}
virtual auto canPop() -> bool = 0; virtual auto canPop() -> bool = 0;
protected: protected:
lv_obj_t* const root_; lv_obj_t* const root_;
lv_obj_t* content_; lv_obj_t* content_;
lv_obj_t* modal_content_;
lv_obj_t* alert_; lv_obj_t* alert_;
lv_group_t* const group_; lv_group_t* const group_;
lv_group_t* modal_group_;
}; };
} // namespace ui } // namespace ui

@ -23,6 +23,8 @@ Splash::Splash() {
lv_obj_set_style_bg_color(root_, lv_color_black(), 0); lv_obj_set_style_bg_color(root_, lv_color_black(), 0);
lv_obj_t* logo = lv_img_create(root_); lv_obj_t* logo = lv_img_create(root_);
lv_obj_set_style_bg_opa(logo, LV_OPA_COVER, 0);
lv_obj_set_style_bg_color(logo, lv_color_black(), 0);
lv_img_set_src(logo, &splash); lv_img_set_src(logo, &splash);
lv_obj_center(logo); lv_obj_center(logo);
} }

@ -1,4 +1,11 @@
/*
* Copyright 2024 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "ui/themes.hpp" #include "ui/themes.hpp"
#include "core/lv_obj.h" #include "core/lv_obj.h"
#include "core/lv_obj_style.h" #include "core/lv_obj_style.h"
#include "core/lv_obj_tree.h" #include "core/lv_obj_tree.h"
@ -6,10 +13,9 @@
#include "esp_log.h" #include "esp_log.h"
#include "misc/lv_color.h" #include "misc/lv_color.h"
#include "misc/lv_style.h" #include "misc/lv_style.h"
#include "widgets/lv_bar.h" #include "widgets/bar/lv_bar.h"
#include "widgets/lv_slider.h" #include "widgets/button/lv_button.h"
#include "widgets/slider/lv_slider.h"
LV_FONT_DECLARE(font_fusion_12);
namespace ui { namespace ui {
namespace themes { namespace themes {
@ -42,9 +48,9 @@ void Theme::Callback(lv_obj_t* obj) {
// Determine class name // Determine class name
std::string class_name; std::string class_name;
if (lv_obj_check_type(obj, &lv_btn_class)) { if (lv_obj_check_type(obj, &lv_button_class)) {
class_name = "button"; class_name = "button";
} else if (lv_obj_check_type(obj, &lv_list_btn_class)) { } else if (lv_obj_check_type(obj, &lv_list_button_class)) {
class_name = "listbutton"; class_name = "listbutton";
} else if (lv_obj_check_type(obj, &lv_bar_class)) { } else if (lv_obj_check_type(obj, &lv_bar_class)) {
class_name = "bar"; class_name = "bar";

@ -7,19 +7,17 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include "tinyfsm.hpp"
#include "database/database.hpp" #include "database/database.hpp"
#include "database/index.hpp" #include "database/index.hpp"
#include "drivers/gpios.hpp" #include "drivers/gpios.hpp"
#include "drivers/nvs.hpp" #include "drivers/nvs.hpp"
#include "tinyfsm.hpp"
#include "ui/screen.hpp" #include "ui/screen.hpp"
namespace ui { namespace ui {
// TODO(jacqueline): is this needed? is this good?
/*
* Event emitted by the main task on heartbeat.
*/
struct OnStorageChange : tinyfsm::Event { struct OnStorageChange : tinyfsm::Event {
bool is_mounted; bool is_mounted;
}; };
@ -44,9 +42,6 @@ struct ReindexDatabase : tinyfsm::Event {};
struct BackPressed : tinyfsm::Event {}; struct BackPressed : tinyfsm::Event {};
struct ShowNowPlaying : tinyfsm::Event {}; struct ShowNowPlaying : tinyfsm::Event {};
struct ModalConfirmPressed : tinyfsm::Event {};
struct ModalCancelPressed : tinyfsm::Event {};
struct DismissAlerts : tinyfsm::Event {}; struct DismissAlerts : tinyfsm::Event {};
} // namespace internal } // namespace internal

@ -5,6 +5,7 @@
*/ */
#include "ui/ui_fsm.hpp" #include "ui/ui_fsm.hpp"
#include <stdint.h>
#include <memory> #include <memory>
#include <memory_resource> #include <memory_resource>
@ -23,9 +24,8 @@
#include "freertos/projdefs.h" #include "freertos/projdefs.h"
#include "lua.hpp" #include "lua.hpp"
#include "luavgl.h" #include "luavgl.h"
#include "misc/lv_gc.h" #include "tick/lv_tick.h"
#include "tinyfsm.hpp" #include "tinyfsm.hpp"
#include "widgets/lv_label.h"
#include "audio/audio_events.hpp" #include "audio/audio_events.hpp"
#include "audio/audio_fsm.hpp" #include "audio/audio_fsm.hpp"
@ -74,7 +74,6 @@ std::unique_ptr<input::DeviceFactory> UiState::sDeviceFactory;
std::stack<std::shared_ptr<Screen>> UiState::sScreens; std::stack<std::shared_ptr<Screen>> UiState::sScreens;
std::shared_ptr<Screen> UiState::sCurrentScreen; std::shared_ptr<Screen> UiState::sCurrentScreen;
std::shared_ptr<Modal> UiState::sCurrentModal;
std::shared_ptr<lua::LuaThread> UiState::sLua; std::shared_ptr<lua::LuaThread> UiState::sLua;
static TimerHandle_t sAlertTimer; static TimerHandle_t sAlertTimer;
@ -84,6 +83,14 @@ static void alert_timer_callback(TimerHandle_t timer) {
events::Ui().Dispatch(internal::DismissAlerts{}); events::Ui().Dispatch(internal::DismissAlerts{});
} }
static auto lvgl_tick_cb() -> uint32_t {
return esp_timer_get_time() / 1000;
}
static auto lvgl_delay_cb(uint32_t ms) -> void {
vTaskDelay(pdMS_TO_TICKS(ms));
}
lua::Property UiState::sBatteryPct{0}; lua::Property UiState::sBatteryPct{0};
lua::Property UiState::sBatteryMv{0}; lua::Property UiState::sBatteryMv{0};
lua::Property UiState::sBatteryCharging{false}; lua::Property UiState::sBatteryCharging{false};
@ -281,6 +288,8 @@ auto UiState::InitBootSplash(drivers::IGpios& gpios, drivers::NvsStorage& nvs)
void UiState::react(const internal::InitDisplay& ev) { void UiState::react(const internal::InitDisplay& ev) {
// Init LVGL first, since the display driver registers itself with LVGL. // Init LVGL first, since the display driver registers itself with LVGL.
lv_init(); lv_init();
lv_tick_set_cb(lvgl_tick_cb);
lv_delay_set_cb(lvgl_delay_cb);
drivers::displays::InitialisationData init_data = drivers::displays::kST7735R; drivers::displays::InitialisationData init_data = drivers::displays::kST7735R;
@ -448,9 +457,12 @@ void UiState::react(const system_fsm::BluetoothEvent& ev) {
default: default:
break; break;
} }
} else if (std::holds_alternative<drivers::bluetooth::RemoteVolumeChanged>(ev.event)) { } else if (std::holds_alternative<drivers::bluetooth::RemoteVolumeChanged>(
ev.event)) {
// Todo: Do something with this (ie, bt volume alert) // Todo: Do something with this (ie, bt volume alert)
ESP_LOGI(kTag, "Recieved volume changed event with new volume: %d", std::get<drivers::bluetooth::RemoteVolumeChanged>(ev.event).new_vol); ESP_LOGI(
kTag, "Recieved volume changed event with new volume: %d",
std::get<drivers::bluetooth::RemoteVolumeChanged>(ev.event).new_vol);
} }
} }
@ -469,7 +481,7 @@ void Splash::react(const system_fsm::BootComplete& ev) {
// The system has finished booting! We now need to prepare to show real UI. // The system has finished booting! We now need to prepare to show real UI.
// This basically just involves reading and applying the user's preferences. // This basically just involves reading and applying the user's preferences.
lv_theme_t* base_theme = lv_theme_basic_init(NULL); lv_theme_t* base_theme = lv_theme_simple_init(NULL);
lv_disp_set_theme(NULL, base_theme); lv_disp_set_theme(NULL, base_theme);
themes::Theme::instance()->Apply(); themes::Theme::instance()->Apply();

@ -32,7 +32,6 @@
#include "system_fsm/service_locator.hpp" #include "system_fsm/service_locator.hpp"
#include "system_fsm/system_events.hpp" #include "system_fsm/system_events.hpp"
#include "ui/lvgl_task.hpp" #include "ui/lvgl_task.hpp"
#include "ui/modal.hpp"
#include "ui/screen.hpp" #include "ui/screen.hpp"
#include "ui/ui_events.hpp" #include "ui/ui_events.hpp"
@ -81,13 +80,6 @@ class UiState : public tinyfsm::Fsm<UiState> {
void react(const system_fsm::BluetoothEvent&); void react(const system_fsm::BluetoothEvent&);
virtual void react(const internal::ModalCancelPressed&) {
sCurrentModal.reset();
}
virtual void react(const internal::ModalConfirmPressed&) {
sCurrentModal.reset();
}
void react(const internal::ReindexDatabase&){}; void react(const internal::ReindexDatabase&){};
protected: protected:
@ -103,7 +95,6 @@ class UiState : public tinyfsm::Fsm<UiState> {
static std::stack<std::shared_ptr<Screen>> sScreens; static std::stack<std::shared_ptr<Screen>> sScreens;
static std::shared_ptr<Screen> sCurrentScreen; static std::shared_ptr<Screen> sCurrentScreen;
static std::shared_ptr<Modal> sCurrentModal;
static std::shared_ptr<lua::LuaThread> sLua; static std::shared_ptr<lua::LuaThread> sLua;
static lua::Property sBatteryPct; static lua::Property sBatteryPct;

Loading…
Cancel
Save