diff --git a/components/furi/src/app_manifest.h b/components/furi/src/app_manifest.h index 7e30df79..b0e4bec1 100644 --- a/components/furi/src/app_manifest.h +++ b/components/furi/src/app_manifest.h @@ -12,11 +12,16 @@ typedef struct _lv_obj_t lv_obj_t; typedef enum { AppTypeService, AppTypeSystem, + AppTypeDesktop, AppTypeUser } AppType; typedef enum { - AppStackSizeNormal = 2048 + AppStackSizeTiny = 512, + AppStackSizeSmall = 1024, + AppStackSizeNormal = 2048, + AppStackSizeLarge = 4096, + AppStackSizeHuge = 8192, } AppStackSize; typedef void (*AppOnStart)(void _Nonnull* parameter); diff --git a/components/furi/src/app_manifest_registry.c b/components/furi/src/app_manifest_registry.c index e17f9830..e5d626af 100644 --- a/components/furi/src/app_manifest_registry.c +++ b/components/furi/src/app_manifest_registry.c @@ -64,16 +64,16 @@ const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id) { return (manifest != NULL) ? *manifest : NULL; } -void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback) { +void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback) { APP_REGISTRY_FOR_EACH(manifest, { if (manifest->type == type) { - callback(manifest); + callback(manifest, context); } }); } -void app_manifest_registry_for_each(AppManifestCallback callback) { +void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context) { APP_REGISTRY_FOR_EACH(manifest, { - callback(manifest); + callback(manifest, context); }); } diff --git a/components/furi/src/app_manifest_registry.h b/components/furi/src/app_manifest_registry.h index ef98461c..701437f1 100644 --- a/components/furi/src/app_manifest_registry.h +++ b/components/furi/src/app_manifest_registry.h @@ -9,14 +9,14 @@ extern "C" { extern const AppManifest* const INTERNAL_APP_MANIFESTS[]; extern const size_t INTERNAL_APP_COUNT; -typedef void (*AppManifestCallback)(const AppManifest*); +typedef void (*AppManifestCallback)(const AppManifest*, void* context); void app_manifest_registry_init(); void app_manifest_registry_add(const AppManifest _Nonnull* manifest); void app_manifest_registry_remove(const AppManifest _Nonnull* manifest); const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id); -void app_manifest_registry_for_each(AppManifestCallback callback); -void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback); +void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context); +void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback); #ifdef __cplusplus } diff --git a/components/nanobake/assets/wifi-off.png b/components/nanobake/assets/ic_small_wifi_off.png similarity index 100% rename from components/nanobake/assets/wifi-off.png rename to components/nanobake/assets/ic_small_wifi_off.png diff --git a/components/nanobake/assets/wifi-on.png b/components/nanobake/assets/ic_small_wifi_on.png similarity index 100% rename from components/nanobake/assets/wifi-on.png rename to components/nanobake/assets/ic_small_wifi_on.png diff --git a/components/nanobake/src/apps/services/desktop/desktop.c b/components/nanobake/src/apps/services/desktop/desktop.c index f1e5de04..d98a90b7 100644 --- a/components/nanobake/src/apps/services/desktop/desktop.c +++ b/components/nanobake/src/apps/services/desktop/desktop.c @@ -1,18 +1,59 @@ #include "desktop.h" -#include "furi_extra_defines.h" +#include "lvgl.h" +#include "check.h" +#include "record.h" +#include "apps/services/loader/loader.h" +#include "apps/services/gui/gui.h" +#include "apps/services/gui/view_port.h" +#include "app_manifest_registry.h" -static void desktop_start(void* param) { - UNUSED(param); - printf("desktop app init\n"); +static void on_open_app(lv_event_t* e) { + lv_event_code_t code = lv_event_get_code(e); + if (code == LV_EVENT_CLICKED) { + const AppManifest* manifest = lv_event_get_user_data(e); + FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { + loader_start_app_nonblocking(loader, manifest->id, NULL); + }) + } +} + +static void add_app_to_list(const AppManifest* manifest, void* _Nullable parent) { + furi_check(parent); + lv_obj_t* list = (lv_obj_t*)parent; + lv_obj_t* btn = lv_list_add_btn(list, LV_SYMBOL_FILE, manifest->name); + lv_obj_add_event_cb(btn, &on_open_app, LV_EVENT_CLICKED, (void*)manifest); +} + +static void desktop_show(lv_obj_t* parent, void* context) { + lv_obj_t* list = lv_list_create(parent); + lv_obj_set_size(list, LV_PCT(100), LV_PCT(100)); + lv_obj_center(list); + + lv_list_add_text(list, "System"); + app_manifest_registry_for_each_of_type(AppTypeSystem, list, add_app_to_list); + lv_list_add_text(list, "User"); + app_manifest_registry_for_each_of_type(AppTypeUser, list, add_app_to_list); +} + +static void desktop_start() { + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, &desktop_show, NULL); + FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, { + gui_add_view_port(gui, view_port, GuiLayerDesktop); + }) +} + +static void desktop_stop() { + furi_crash("desktop_stop is not implemented"); } const AppManifest desktop_app = { .id = "desktop", .name = "Desktop", .icon = NULL, - .type = AppTypeService, + .type = AppTypeDesktop, .on_start = &desktop_start, - .on_stop = NULL, + .on_stop = &desktop_stop, .on_show = NULL, .stack_size = AppStackSizeNormal }; diff --git a/components/nanobake/src/apps/services/gui/gui_draw.c b/components/nanobake/src/apps/services/gui/gui_draw.c index 5ae9fabb..d72e97ce 100644 --- a/components/nanobake/src/apps/services/gui/gui_draw.c +++ b/components/nanobake/src/apps/services/gui/gui_draw.c @@ -1,176 +1,69 @@ #include "check.h" #include "gui_i.h" +#include "log.h" +#include "record.h" #include "esp_lvgl_port.h" #include "apps/services/gui/widgets/widgets.h" +#include "apps/services/loader/loader.h" -static void gui_redraw_status_bar(Gui* gui, bool need_attention) { - /* - ViewPortArray_it_t it; - uint8_t left_used = 0; - uint8_t right_used = 0; - uint8_t width; +#define TAG "gui" - canvas_frame_set( - gui->lvgl_parent, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); +static lv_obj_t* screen_with_top_bar(lv_obj_t* parent) { + lv_obj_set_style_bg_blacken(parent); - // for support black theme - paint white area and - // draw icon with transparent white color + lv_obj_t* vertical_container = lv_obj_create(parent); + lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); + lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_no_padding(vertical_container); + lv_obj_set_style_bg_blacken(vertical_container); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box(gui->canvas, 1, 1, 9, 7); - canvas_draw_box(gui->canvas, 7, 3, 58, 6); - canvas_draw_box(gui->canvas, 61, 1, 32, 7); - canvas_draw_box(gui->canvas, 89, 3, 38, 6); - canvas_set_color(gui->canvas, ColorBlack); - canvas_set_bitmap_mode(gui->canvas, 1); - canvas_draw_icon(gui->canvas, 0, 0, &I_Background_128x11); - canvas_set_bitmap_mode(gui->canvas, 0); + top_bar(vertical_container); - // Right side - uint8_t x = GUI_DISPLAY_WIDTH - 1; - ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); - while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) { - ViewPort* view_port = *ViewPortArray_ref(it); - if(view_port_is_enabled(view_port)) { - width = view_port_get_width(view_port); - if(!width) width = 8; - // Recalculate next position - right_used += (width + 2); - x -= (width + 2); - // Prepare work area background - canvas_frame_set( - gui->canvas, - x - 1, - GUI_STATUS_BAR_Y + 1, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); - canvas_set_color(gui->canvas, ColorBlack); - // ViewPort draw - canvas_frame_set( - gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); - view_port_draw(view_port, gui->canvas); + lv_obj_t* child_container = lv_obj_create(vertical_container); + lv_obj_set_width(child_container, LV_PCT(100)); + lv_obj_set_flex_grow(child_container, 1); + lv_obj_set_style_no_padding(vertical_container); + lv_obj_set_style_bg_blacken(vertical_container); + + return child_container; +} + +static lv_obj_t* screen_with_top_bar_and_toolbar(lv_obj_t* parent) { + lv_obj_set_style_bg_blacken(parent); + + lv_obj_t* vertical_container = lv_obj_create(parent); + lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); + lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_no_padding(vertical_container); + lv_obj_set_style_bg_blacken(vertical_container); + + top_bar(vertical_container); + + FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { + const AppManifest* manifest = loader_get_current_app(loader); + if (manifest != NULL) { + toolbar(vertical_container, TOP_BAR_HEIGHT, manifest); } - ViewPortArray_next(it); - } - // Draw frame around icons on the right - if(right_used) { - canvas_frame_set( - gui->canvas, - GUI_DISPLAY_WIDTH - 3 - right_used, - GUI_STATUS_BAR_Y, - right_used + 3, - GUI_STATUS_BAR_HEIGHT); - canvas_set_color(gui->canvas, ColorBlack); - canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); - canvas_draw_line( - gui->canvas, - canvas_width(gui->canvas) - 2, - 1, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - canvas_draw_line( - gui->canvas, - 1, - canvas_height(gui->canvas) - 2, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - } + }) - // Left side - x = 2; - ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]); - while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) { - ViewPort* view_port = *ViewPortArray_ref(it); - if(view_port_is_enabled(view_port)) { - width = view_port_get_width(view_port); - if(!width) width = 8; - // Prepare work area background - canvas_frame_set( - gui->canvas, - x - 1, - GUI_STATUS_BAR_Y + 1, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); - canvas_set_color(gui->canvas, ColorBlack); - // ViewPort draw - canvas_frame_set( - gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); - view_port_draw(view_port, gui->canvas); - // Recalculate next position - left_used += (width + 2); - x += (width + 2); - } - ViewPortArray_next(it); - } - // Extra notification - if(need_attention) { - width = icon_get_width(&I_Hidden_window_9x8); - // Prepare work area background - canvas_frame_set( - gui->canvas, - x - 1, - GUI_STATUS_BAR_Y + 1, - width + 2, - GUI_STATUS_BAR_WORKAREA_HEIGHT + 2); - canvas_set_color(gui->canvas, ColorWhite); - canvas_draw_box(gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas)); - canvas_set_color(gui->canvas, ColorBlack); - // Draw Icon - canvas_frame_set( - gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT); - canvas_draw_icon(gui->canvas, 0, 0, &I_Hidden_window_9x8); - // Recalculate next position - left_used += (width + 2); - x += (width + 2); - } - // Draw frame around icons on the left - if(left_used) { - canvas_frame_set(gui->canvas, 0, 0, left_used + 3, GUI_STATUS_BAR_HEIGHT); - canvas_draw_rframe( - gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1); - canvas_draw_line( - gui->canvas, - canvas_width(gui->canvas) - 2, - 1, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - canvas_draw_line( - gui->canvas, - 1, - canvas_height(gui->canvas) - 2, - canvas_width(gui->canvas) - 2, - canvas_height(gui->canvas) - 2); - } - */ + lv_obj_t* spacer = lv_obj_create(vertical_container); + lv_obj_set_size(spacer, 2, 2); + lv_obj_set_style_bg_blacken(spacer); + + lv_obj_t* child_container = lv_obj_create(vertical_container); + lv_obj_set_width(child_container, LV_PCT(100)); + lv_obj_set_flex_grow(child_container, 1); + lv_obj_set_style_no_padding(vertical_container); + lv_obj_set_style_bg_blacken(vertical_container); + + return child_container; } static bool gui_redraw_window(Gui* gui) { ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerWindow]); if (view_port) { - lv_obj_set_style_bg_blacken(gui->lvgl_parent); - - lv_obj_t* vertical_container = lv_obj_create(gui->lvgl_parent); - lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100)); - lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_no_padding(vertical_container); - lv_obj_set_style_bg_blacken(vertical_container); - - top_bar(vertical_container); - - lv_obj_t* window_parent = lv_obj_create(vertical_container); - lv_obj_set_width(window_parent, LV_PCT(100)); - lv_obj_set_flex_grow(window_parent, 1); - lv_obj_set_style_no_padding(vertical_container); - lv_obj_set_style_bg_blacken(vertical_container); - - view_port_draw(view_port, window_parent); + lv_obj_t* container = screen_with_top_bar_and_toolbar(gui->lvgl_parent); + view_port_draw(view_port, container); return true; } else { return false; @@ -178,14 +71,14 @@ static bool gui_redraw_window(Gui* gui) { } static bool gui_redraw_desktop(Gui* gui) { - /* - canvas_frame_set(gui->lvgl_parent, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT); ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerDesktop]); - if(view_port) { - view_port_draw(view_port, gui->lvgl_parent); + if (view_port) { + lv_obj_t* container = screen_with_top_bar(gui->lvgl_parent); + view_port_draw(view_port, container); return true; + } else { + FURI_LOG_E(TAG, "no desktop layer found"); } - */ return false; } @@ -207,12 +100,10 @@ void gui_redraw(Gui* gui) { furi_check(lvgl_port_lock(100)); lv_obj_clean(gui->lvgl_parent); - gui_redraw_desktop(gui); if (!gui_redraw_fs(gui)) { if (!gui_redraw_window(gui)) { gui_redraw_desktop(gui); } - gui_redraw_status_bar(gui, false); } lvgl_port_unlock(); diff --git a/components/nanobake/src/apps/services/gui/view_port.c b/components/nanobake/src/apps/services/gui/view_port.c index 7238643d..b83bfc77 100644 --- a/components/nanobake/src/apps/services/gui/view_port.c +++ b/components/nanobake/src/apps/services/gui/view_port.c @@ -1,8 +1,9 @@ +#include "apps/services/gui/widgets/widgets.h" #include "check.h" +#include "esp_lvgl_port.h" #include "gui.h" #include "gui_i.h" #include "view_port_i.h" -#include "esp_lvgl_port.h" #define TAG "viewport" @@ -90,6 +91,7 @@ void view_port_draw(ViewPort* view_port, lv_obj_t* parent) { if (view_port->draw_callback) { lv_obj_clean(parent); + lv_obj_set_style_no_padding(parent); view_port->draw_callback(parent, view_port->draw_callback_context); } diff --git a/components/nanobake/src/apps/services/gui/widgets/toolbar.c b/components/nanobake/src/apps/services/gui/widgets/toolbar.c new file mode 100644 index 00000000..1a79f13c --- /dev/null +++ b/components/nanobake/src/apps/services/gui/widgets/toolbar.c @@ -0,0 +1,40 @@ +#include "toolbar.h" +#include "record.h" +#include "apps/services/gui/widgets/widgets.h" +#include "apps/services/loader/loader.h" + +static void app_toolbar_close(lv_event_t* event) { + FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { + loader_stop_app(loader); + }) +} + +void toolbar(lv_obj_t* parent, lv_coord_t offset_y, const AppManifest* manifest) { + lv_obj_t* toolbar = lv_obj_create(parent); + lv_obj_set_width(toolbar, LV_PCT(100)); + lv_obj_set_height(toolbar, TOOLBAR_HEIGHT); + lv_obj_set_pos(toolbar, 0, offset_y); + lv_obj_set_style_no_padding(toolbar); + lv_obj_center(toolbar); + lv_obj_set_flex_flow(toolbar, LV_FLEX_FLOW_ROW); + + lv_obj_t* close_button = lv_btn_create(toolbar); + lv_obj_set_size(close_button, TOOLBAR_HEIGHT - 4, TOOLBAR_HEIGHT - 4); + lv_obj_set_style_no_padding(close_button); + lv_obj_add_event_cb(close_button, &app_toolbar_close,LV_EVENT_CLICKED, NULL); + lv_obj_t* close_button_image = lv_img_create(close_button); + lv_img_set_src(close_button_image, LV_SYMBOL_CLOSE); + lv_obj_align(close_button_image, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t* label_container = lv_obj_create(toolbar); + lv_obj_set_style_no_padding(label_container); + lv_obj_set_height(label_container, LV_PCT(100)); + lv_obj_set_flex_grow(label_container, 1); + + lv_obj_t* label = lv_label_create(label_container); + lv_label_set_text(label, manifest->name); + lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0); + lv_obj_set_size(label, LV_PCT(100), TOOLBAR_FONT_HEIGHT); + lv_obj_set_pos(label, 0, (TOOLBAR_HEIGHT - TOOLBAR_FONT_HEIGHT - 10) / 2); + lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); +} diff --git a/components/nanobake/src/apps/services/gui/widgets/toolbar.h b/components/nanobake/src/apps/services/gui/widgets/toolbar.h new file mode 100644 index 00000000..e64138c7 --- /dev/null +++ b/components/nanobake/src/apps/services/gui/widgets/toolbar.h @@ -0,0 +1,17 @@ +#pragma once + +#include "lvgl.h" +#include "app_manifest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TOOLBAR_HEIGHT 40 +#define TOOLBAR_FONT_HEIGHT 18 + +void toolbar(lv_obj_t* parent, lv_coord_t offset_y, const AppManifest* manifest); + +#ifdef __cplusplus +} +#endif diff --git a/components/nanobake/src/apps/services/gui/widgets/top_bar.c b/components/nanobake/src/apps/services/gui/widgets/top_bar.c index 667c180a..5ed49a8c 100644 --- a/components/nanobake/src/apps/services/gui/widgets/top_bar.c +++ b/components/nanobake/src/apps/services/gui/widgets/top_bar.c @@ -22,5 +22,5 @@ void top_bar(lv_obj_t* parent) { lv_obj_set_style_bg_blacken(wifi); lv_obj_set_style_img_recolor(wifi, lv_color_white(), 0); lv_obj_set_style_img_recolor_opa(wifi, 255, 0); - lv_img_set_src(wifi, "A:/assets/wifi-off.png"); + lv_img_set_src(wifi, "A:/assets/ic_small_wifi_off.png"); } \ No newline at end of file diff --git a/components/nanobake/src/apps/services/gui/widgets/top_bar.h b/components/nanobake/src/apps/services/gui/widgets/top_bar.h index 2eee282a..fc6504b5 100644 --- a/components/nanobake/src/apps/services/gui/widgets/top_bar.h +++ b/components/nanobake/src/apps/services/gui/widgets/top_bar.h @@ -2,7 +2,15 @@ #include "lvgl.h" +#ifdef __cplusplus +extern "C" { +#endif + #define TOP_BAR_ICON_SIZE 18 #define TOP_BAR_HEIGHT (TOP_BAR_ICON_SIZE + 2) void top_bar(lv_obj_t* parent); + +#ifdef __cplusplus +} +#endif diff --git a/components/nanobake/src/apps/services/gui/widgets/widgets.h b/components/nanobake/src/apps/services/gui/widgets/widgets.h index 36acbed4..8f2e09b4 100644 --- a/components/nanobake/src/apps/services/gui/widgets/widgets.h +++ b/components/nanobake/src/apps/services/gui/widgets/widgets.h @@ -1,6 +1,15 @@ #pragma once #include "top_bar.h" +#include "toolbar.h" + +#ifdef __cplusplus +extern "C" { +#endif void lv_obj_set_style_bg_blacken(lv_obj_t* obj); void lv_obj_set_style_no_padding(lv_obj_t* obj); + +#ifdef __cplusplus +} +#endif diff --git a/components/nanobake/src/apps/services/loader/loader.c b/components/nanobake/src/apps/services/loader/loader.c index e663d914..f8249dd9 100644 --- a/components/nanobake/src/apps/services/loader/loader.c +++ b/components/nanobake/src/apps/services/loader/loader.c @@ -51,6 +51,15 @@ void loader_stop_app(Loader* loader) { furi_message_queue_put(loader->queue, &message, FuriWaitForever); } +const AppManifest* _Nullable loader_get_current_app(Loader* loader) { + App* app = loader->app_data.app; + if (app != NULL) { + return app->manifest; + } else { + return NULL; + } +} + FuriPubSub* loader_get_pubsub(Loader* loader) { furi_assert(loader); // it's safe to return pubsub without locking @@ -123,6 +132,10 @@ static void loader_start_app_with_manifest( const AppManifest* _Nonnull manifest, const char* args ) { + if (manifest->type != AppTypeUser && manifest->type != AppTypeSystem) { + furi_crash("app type not supported by loader"); + } + App* _Nonnull app = furi_app_alloc(manifest); loader->app_data.app = app; loader->app_data.args = (void*)args; @@ -136,18 +149,9 @@ static void loader_start_app_with_manifest( loader->app_data.view_port = view_port; view_port_draw_callback_set(view_port, manifest->on_show, NULL); - switch (manifest->type) { - case AppTypeService: - furi_crash("service apps cannot have an on_show implementation"); - case AppTypeSystem: - case AppTypeUser: - FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, { - gui_add_view_port(gui, view_port, GuiLayerWindow); - }) - break; - default: - furi_crash("viewport not implemented for app type"); - } + FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, { + gui_add_view_port(gui, view_port, GuiLayerWindow); + }) } else { loader->app_data.view_port = NULL; } diff --git a/components/nanobake/src/apps/services/loader/loader.h b/components/nanobake/src/apps/services/loader/loader.h index 069a629e..5ede7eb1 100644 --- a/components/nanobake/src/apps/services/loader/loader.h +++ b/components/nanobake/src/apps/services/loader/loader.h @@ -2,6 +2,7 @@ #include "furi_core.h" #include "furi_string.h" #include "pubsub.h" +#include "app_manifest.h" #ifdef __cplusplus extern "C" { @@ -47,6 +48,7 @@ void loader_start_app_nonblocking(Loader* loader, const char* id, const char* ar void loader_stop_app(Loader* loader); +const AppManifest* _Nullable loader_get_current_app(Loader* loader); /** * @brief Start application with GUI error message * @param[in] instance loader instance diff --git a/components/nanobake/src/nanobake.c b/components/nanobake/src/nanobake.c index 79488fc4..ad807779 100644 --- a/components/nanobake/src/nanobake.c +++ b/components/nanobake/src/nanobake.c @@ -8,23 +8,27 @@ #define TAG "nanobake" // System services -extern const AppManifest desktop_app; extern const AppManifest gui_app; extern const AppManifest loader_app; +// Desktop +extern const AppManifest desktop_app; + // System apps extern const AppManifest system_info_app; -void start_service(const AppManifest* _Nonnull manifest) { - // TODO: keep track of running services +void start_service(const AppManifest* _Nonnull manifest, void* _Nullable context) { + UNUSED(context); FURI_LOG_I(TAG, "Starting service %s", manifest->name); + furi_check(manifest->on_start, "service must define on_start"); manifest->on_start(NULL); + // TODO: keep track of running services } static void register_apps(Config* _Nonnull config) { FURI_LOG_I(TAG, "Registering core apps"); - app_manifest_registry_add(&desktop_app); app_manifest_registry_add(&gui_app); + app_manifest_registry_add(&desktop_app); app_manifest_registry_add(&loader_app); app_manifest_registry_add(&system_info_app); @@ -36,7 +40,13 @@ static void register_apps(Config* _Nonnull config) { static void start_services() { FURI_LOG_I(TAG, "Starting services"); - app_manifest_registry_for_each_of_type(AppTypeService, start_service); + app_manifest_registry_for_each_of_type(AppTypeService, NULL, start_service); + FURI_LOG_I(TAG, "Startup complete"); +} + +static void start_desktop() { + FURI_LOG_I(TAG, "Starting desktop"); + desktop_app.on_start(NULL); FURI_LOG_I(TAG, "Startup complete"); } @@ -51,4 +61,5 @@ __attribute__((unused)) extern void nanobake_start(Config* _Nonnull config) { register_apps(config); start_services(); + start_desktop(); } diff --git a/main/src/hello_world/hello_world.c b/main/src/hello_world/hello_world.c index 8e0e6e7a..d671ac18 100644 --- a/main/src/hello_world/hello_world.c +++ b/main/src/hello_world/hello_world.c @@ -3,14 +3,6 @@ #include "apps/services/gui/gui.h" #include "apps/services/loader/loader.h" -static void on_button_click(lv_event_t _Nonnull* event) { - UNUSED(event); - - FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { - loader_start_app_nonblocking(loader, "systeminfo", NULL); - }) -} - static void app_show(lv_obj_t* parent, void* context) { UNUSED(context); @@ -19,13 +11,7 @@ static void app_show(lv_obj_t* parent, void* context) { lv_obj_set_width(label, 200); lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0); lv_label_set_text(label, "Hello, world!"); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -30); - - lv_obj_t* btn = lv_btn_create(parent); - label = lv_label_create(btn); - lv_label_set_text_static(label, "System Info"); - lv_obj_align(btn, LV_ALIGN_CENTER, 0, 30); - lv_obj_add_event_cb(btn, on_button_click, LV_EVENT_CLICKED, NULL); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } const AppManifest hello_world_app = { diff --git a/main/src/main.c b/main/src/main.c index 80960deb..5339a463 100644 --- a/main/src/main.c +++ b/main/src/main.c @@ -20,11 +20,11 @@ __attribute__((unused)) void app_main(void) { nanobake_start(&config); - FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { - FuriString* error_message = furi_string_alloc(); - if (loader_start_app(loader, hello_world_app.id, NULL, error_message) != LoaderStatusOk) { - FURI_LOG_E(hello_world_app.id, "%s\r\n", furi_string_get_cstr(error_message)); - } - furi_string_free(error_message); - }); +// FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, { +// FuriString* error_message = furi_string_alloc(); +// if (loader_start_app(loader, hello_world_app.id, NULL, error_message) != LoaderStatusOk) { +// FURI_LOG_E(hello_world_app.id, "%s\r\n", furi_string_get_cstr(error_message)); +// } +// furi_string_free(error_message); +// }); } diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 0bac7a49..1c316681 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,7 +1,13 @@ CONFIG_IDF_TARGET="esp32" CONFIG_LV_COLOR_16_SWAP=y CONFIG_LV_USE_USER_DATA=y +CONFIG_LV_USE_FS_STDIO=y +CONFIG_LV_FS_STDIO_LETTER=65 +CONFIG_LV_FS_STDIO_PATH="" +CONFIG_LV_FS_STDIO_CACHE_SIZE=4096 +CONFIG_LV_USE_PNG=y CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +