mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-18 10:53:17 +00:00
239 lines
6.4 KiB
C
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
|
|
};
|