/* * The functions in this file allow for managing windows * windows are framebuffers that can be moved and rendered * to the primary framebuffer */ #include "include/driver_framebuffer_internal.h" /* Variables */ Window* windows = NULL; /* Private functions */ inline Window* _create_window() { //Create an empty window object Window* window = (Window*) calloc(1, sizeof(Window)); if (!window) return NULL; memset(window, 0, sizeof(Window)); return window; } inline void _add_window(Window* window) { //Add a window to the linked list if (windows == NULL) { windows = window; return; } Window* lastWindow = windows; while (lastWindow->_nextWindow != NULL) { lastWindow = lastWindow->_nextWindow; } lastWindow->_nextWindow = window; } void _debug_windows() { Window* window = windows; printf("Windows: "); while (window != NULL) { printf("%s ", window->name); window = window->_nextWindow; } printf("\n"); } inline void _remove_window_from_linked_list(Window* window) { //Remove a window from the linked list Window* prevWindow = window->_prevWindow; Window* nextWindow = window->_nextWindow; if (prevWindow) prevWindow->_nextWindow = nextWindow; //Link previous to next if (nextWindow) nextWindow->_prevWindow = prevWindow; //Link next to previous if (windows == window) windows = nextWindow; //Change the start window of the linked list } /* Public functions */ Window* driver_framebuffer_window_create(const char* name, uint16_t width, uint16_t height) { if (driver_framebuffer_window_find(name)) return NULL; //If the window already exists do nothing and return. Window* window = _create_window(); /* Set properties */ window->name = strdup(name); window->width = width; window->height = height; window->orientation = landscape; window->enableTransparentColor = false; window->transparentColor = 0xFFFFFF; /* Configure automatic rendering */ window->visible = false; window->hOffset = 0; window->vOffset = 0; window->drawWidth = width; window->drawHeight = height; /* Buffer */ window->buffer = (uint8_t*) heap_caps_malloc(((width*height*PIXEL_SIZE)/8)+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); /* Linked list */ window->_prevWindow = driver_framebuffer_window_last(); window->_nextWindow = NULL; _add_window(window); //Add window to linked list of windows return window; } void driver_framebuffer_window_remove(Window* window) { if (window->buffer) free(window->buffer); _remove_window_from_linked_list(window); free(window); } Window* driver_framebuffer_window_find(const char* name) { Window* currentWindow = windows; while (currentWindow != NULL) { if ((strlen(name) == strlen(currentWindow->name)) && (strcmp(currentWindow->name, name)==0) ) { return currentWindow; } currentWindow = currentWindow->_nextWindow; } return NULL; } Window* driver_framebuffer_window_first() { return windows; } Window* driver_framebuffer_window_next(Window* currentWindow) { if (currentWindow == NULL) return NULL; return currentWindow->_nextWindow; } Window* driver_framebuffer_window_last() { Window* lastWindow = windows; while (lastWindow && lastWindow->_nextWindow != NULL) { lastWindow = lastWindow->_nextWindow; } return lastWindow; } bool driver_framebuffer_window_rename(Window* window, const char* newName) { if (!window) return false; char* newNameBuffer = (char*) malloc(strlen(newName) + 1); if (newNameBuffer == NULL) return false; memset(newNameBuffer, 0, strlen(newName) + 1); strncpy(newNameBuffer, newName, strlen(newName)); free(window->name); window->name = newNameBuffer; return true; } void driver_framebuffer_window_focus(Window* window) { _remove_window_from_linked_list(window); if (windows == window) windows = window->_nextWindow; window->_prevWindow = driver_framebuffer_window_last(); _add_window(window); window->_nextWindow = NULL; } void driver_framebuffer_window_getSize(Window* window, int16_t* width, int16_t* height) { if (window == NULL) { //No window provided, use global context *width = FB_WIDTH; *height = FB_HEIGHT; } else { //Window provided, use window context *width = window->width; *height = window->height; } }