implemented basic desktop
This commit is contained in:
parent
f6c547ad45
commit
48d2fd6c2d
@ -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);
|
||||
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
|
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 224 B |
@ -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
|
||||
};
|
||||
|
||||
@ -1,162 +1,17 @@
|
||||
#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
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
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_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);
|
||||
@ -164,13 +19,51 @@ static bool gui_redraw_window(Gui* gui) {
|
||||
|
||||
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_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);
|
||||
|
||||
view_port_draw(view_port, window_parent);
|
||||
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);
|
||||
}
|
||||
})
|
||||
|
||||
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_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);
|
||||
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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
40
components/nanobake/src/apps/services/gui/widgets/toolbar.c
Normal file
40
components/nanobake/src/apps/services/gui/widgets/toolbar.c
Normal file
@ -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);
|
||||
}
|
||||
17
components/nanobake/src/apps/services/gui/widgets/toolbar.h
Normal file
17
components/nanobake/src/apps/services/gui/widgets/toolbar.h
Normal file
@ -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
|
||||
@ -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");
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
}
|
||||
} else {
|
||||
loader->app_data.view_port = NULL;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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);
|
||||
// });
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user