Ken Van Hoeylandt 83ef89cf07 improved NbApp definition
default values added for task priority and stack size
+ other small improvements
2023-12-28 00:07:39 +01:00

239 lines
6.4 KiB
C

#include "gui_i.h"
#include "core_defines.h"
#include "record.h"
#include "check.h"
#define TAG "gui"
// Forward declarations from gui_draw.c
bool gui_redraw_fs(NbGui* gui);
void gui_redraw(NbGui* gui);
ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) {
// Iterating backward
ViewPortArray_it_t it;
ViewPortArray_it_last(it, array);
while(!ViewPortArray_end_p(it)) {
ViewPort* view_port = *ViewPortArray_ref(it);
if(view_port_is_enabled(view_port)) {
return view_port;
}
ViewPortArray_previous(it);
}
return NULL;
}
size_t gui_active_view_port_count(NbGui* gui, GuiLayer layer) {
furi_assert(gui);
furi_check(layer < GuiLayerMAX);
size_t ret = 0;
gui_lock(gui);
ViewPortArray_it_t it;
ViewPortArray_it_last(it, gui->layers[layer]);
while(!ViewPortArray_end_p(it)) {
ViewPort* view_port = *ViewPortArray_ref(it);
if(view_port_is_enabled(view_port)) {
ret++;
}
ViewPortArray_previous(it);
}
gui_unlock(gui);
return ret;
}
void gui_update(NbGui* gui) {
ESP_LOGI(TAG, "gui_update");
furi_assert(gui);
furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_DRAW);
}
void gui_lock(NbGui* gui) {
furi_assert(gui);
furi_check(furi_mutex_acquire(gui->mutex, FuriWaitForever) == FuriStatusOk);
}
void gui_unlock(NbGui* gui) {
furi_assert(gui);
furi_check(furi_mutex_release(gui->mutex) == FuriStatusOk);
}
void gui_add_view_port(NbGui* gui, ViewPort* view_port, GuiLayer layer) {
furi_assert(gui);
furi_assert(view_port);
furi_check(layer < GuiLayerMAX);
gui_lock(gui);
// Verify that view port is not yet added
ViewPortArray_it_t it;
for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_it(it, gui->layers[i]);
while(!ViewPortArray_end_p(it)) {
furi_assert(*ViewPortArray_ref(it) != view_port);
ViewPortArray_next(it);
}
}
// Add view port and link with gui
ViewPortArray_push_back(gui->layers[layer], view_port);
view_port_gui_set(view_port, gui);
gui_unlock(gui);
// Request redraw
gui_update(gui);
}
void gui_remove_view_port(NbGui* gui, ViewPort* view_port) {
furi_assert(gui);
furi_assert(view_port);
gui_lock(gui);
view_port_gui_set(view_port, NULL);
ViewPortArray_it_t it;
for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_it(it, gui->layers[i]);
while(!ViewPortArray_end_p(it)) {
if(*ViewPortArray_ref(it) == view_port) {
ViewPortArray_remove(gui->layers[i], it);
} else {
ViewPortArray_next(it);
}
}
}
// if(gui->ongoing_input_view_port == view_port) {
// gui->ongoing_input_view_port = NULL;
// }
gui_unlock(gui);
// Request redraw
gui_update(gui);
}
void gui_view_port_send_to_front(NbGui* gui, ViewPort* view_port) {
furi_assert(gui);
furi_assert(view_port);
gui_lock(gui);
// Remove
GuiLayer layer = GuiLayerMAX;
ViewPortArray_it_t it;
for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_it(it, gui->layers[i]);
while(!ViewPortArray_end_p(it)) {
if(*ViewPortArray_ref(it) == view_port) {
ViewPortArray_remove(gui->layers[i], it);
furi_assert(layer == GuiLayerMAX);
layer = i;
} else {
ViewPortArray_next(it);
}
}
}
furi_assert(layer != GuiLayerMAX);
// Return to the top
ViewPortArray_push_back(gui->layers[layer], view_port);
gui_unlock(gui);
// Request redraw
gui_update(gui);
}
void gui_view_port_send_to_back(NbGui* gui, ViewPort* view_port) {
furi_assert(gui);
furi_assert(view_port);
gui_lock(gui);
// Remove
GuiLayer layer = GuiLayerMAX;
ViewPortArray_it_t it;
for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_it(it, gui->layers[i]);
while(!ViewPortArray_end_p(it)) {
if(*ViewPortArray_ref(it) == view_port) {
ViewPortArray_remove(gui->layers[i], it);
furi_assert(layer == GuiLayerMAX);
layer = i;
} else {
ViewPortArray_next(it);
}
}
}
furi_assert(layer != GuiLayerMAX);
// Return to the top
ViewPortArray_push_at(gui->layers[layer], 0, view_port);
gui_unlock(gui);
// Request redraw
gui_update(gui);
}
void gui_set_lockdown(NbGui* gui, bool lockdown) {
furi_assert(gui);
gui_lock(gui);
gui->lockdown = lockdown;
gui_unlock(gui);
// Request redraw
gui_update(gui);
}
NbGui* gui_alloc() {
NbGui* gui = malloc(sizeof(NbGui));
gui->thread_id = furi_thread_get_current_id();
gui->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
gui->lvgl_parent = lv_scr_act();
gui->lockdown = false;
furi_check(gui->mutex);
for(size_t i = 0; i < GuiLayerMAX; i++) {
ViewPortArray_init(gui->layers[i]);
}
/*
// Input
gui->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
gui->input_events = furi_record_open(RECORD_INPUT_EVENTS);
furi_check(gui->input_events);
furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui);
*/
return gui;
}
__attribute((__noreturn__)) int32_t prv_gui_main(void* parameter) {
UNUSED(parameter);
NbGui* gui = gui_alloc();
furi_record_create(RECORD_GUI, gui);
while (1) {
uint32_t flags = furi_thread_flags_wait(
GUI_THREAD_FLAG_ALL,
FuriFlagWaitAny,
FuriWaitForever
);
// Process and dispatch input
if (flags & GUI_THREAD_FLAG_INPUT) {
// // Process till queue become empty
// InputEvent input_event;
// while(furi_message_queue_get(gui->input_queue, &input_event, 0) == FuriStatusOk) {
// gui_input(gui, &input_event);
// }
}
// Process and dispatch draw call
if (flags & GUI_THREAD_FLAG_DRAW) {
// Clear flags that arrived on input step
furi_thread_flags_clear(GUI_THREAD_FLAG_DRAW);
gui_redraw(gui);
}
}
}
const NbApp gui_app = {
.id = "gui",
.name = "GUI",
.type = SERVICE,
.entry_point = &prv_gui_main,
.stack_size = NB_TASK_STACK_SIZE_DEFAULT,
.priority = NB_TASK_PRIORITY_DEFAULT
};