From 83d02a8861dd43b800ba0ac91041c0a11e6ae0da Mon Sep 17 00:00:00 2001 From: rasmus Date: Fri, 16 Jan 2026 21:09:29 +0100 Subject: [PATCH] Correct keyboard events now work, as well as unsubscriping from even manager --- Desktop_Test/GLOBALS.h | 3 +- Desktop_Test/example_programs.h | 98 ++++++++++++---- Desktop_Test/input_manager.cpp | 196 +++++++++++++++++++++++++------- Desktop_Test/program.h | 2 + Desktop_Test/shell.cpp | 7 +- Desktop_Test/tft_handler.cpp | 1 + 6 files changed, 248 insertions(+), 59 deletions(-) diff --git a/Desktop_Test/GLOBALS.h b/Desktop_Test/GLOBALS.h index 029ce05..53b6587 100644 --- a/Desktop_Test/GLOBALS.h +++ b/Desktop_Test/GLOBALS.h @@ -17,7 +17,8 @@ enum CLICK_EVENTS : uint8_t { NONE = 0, LEFT_CLICK = 1, RIGHT_CLICK = 2, - KEYBOARD = 3, + ENTER = 3, + KEYBOARD = 4, }; struct CLICK_EVENT { diff --git a/Desktop_Test/example_programs.h b/Desktop_Test/example_programs.h index 046197e..12181f8 100644 --- a/Desktop_Test/example_programs.h +++ b/Desktop_Test/example_programs.h @@ -1,3 +1,4 @@ +#include #include "esp32-hal.h" #pragma once #include "program.h" @@ -11,6 +12,10 @@ private: int counter = 0; public: + ~CounterProgram() { + EventManager::getInstance().unsubscribe(this); + } + void run() override { Serial.println("Counter program started!"); @@ -46,11 +51,54 @@ public: class TextEditorProgram : public Program { public: - void run() override { - Serial.println("Text editor started!"); + ~TextEditorProgram() { + EventManager::getInstance().unsubscribe(this); + } + + void on_click_event(CLICK_EVENT event) { + if (_window->minimized) return; + + for (WindowContentText& text : _window->window_content_text) { + if (event.x >= text.x && event.x <= (text.x + text.width) && event.y >= text.y && event.y <= (text.y + text.height) && (event.event == CLICK_EVENTS::LEFT_CLICK || event.event == CLICK_EVENTS::ENTER)) { + if (text.selectable && !text.selected) { + for (WindowContentText& temp : _window->window_content_text) temp.selected = false; + text.selected = true; + } + } else if (event.event == CLICK_EVENTS::LEFT_CLICK || event.event == CLICK_EVENTS::ENTER) { + if (text.selected) text.selected = false; + } + + if (text.selected && event.event == CLICK_EVENTS::KEYBOARD) { + text.text += event.character; + } + } + } + + void run() override { + EventManager::getInstance().subscribe(this); + + _window->x += 100; + _window->width -= 50; + + WindowContentText text; + text.x = _window->x + 5; + text.y = _window->y + 60; + text.width = 50; + text.height = 10; + text.size = 2; + text.selectable = true; + text.selected = false; + text.text = "asddsa"; + + _window->window_content_text.push_back(text); - // You have full access to the window and can draw to it while (_running) { + for (WindowContentText text : _window->window_content_text) { + if (text.selected) { + + } + } + vTaskDelay(pdMS_TO_TICKS(1)); } } @@ -58,9 +106,11 @@ public: class InternetTester : public Program { public: - void run() override { - Serial.println("Text editor started!"); + ~InternetTester() { + EventManager::getInstance().unsubscribe(this); + } + void run() override { // You have full access to the window and can draw to it while (_running) { vTaskDelay(pdMS_TO_TICKS(1)); @@ -70,9 +120,11 @@ public: class CalculatorProgram : public Program { public: + ~CalculatorProgram() { + EventManager::getInstance().unsubscribe(this); + } + void run() override { - Serial.println("Calculator started!"); - while (_running) { // Calculator logic here vTaskDelay(pdMS_TO_TICKS(1)); @@ -82,6 +134,10 @@ public: class Chatty : public Program { public: + ~Chatty() { + EventManager::getInstance().unsubscribe(this); + } + void run() override { Serial.println("Chatty started!"); @@ -98,6 +154,10 @@ private: bool showing_buttons = false; public: + ~SettingsProgram() { + EventManager::getInstance().unsubscribe(this); + } + void on_click_event(CLICK_EVENT event) { if (_window->minimized) return; @@ -191,7 +251,7 @@ public: _window->content_buttons.push_back(show_resources); _window->content_buttons.push_back(show_tasks); - + // Variables for metrics size_t total_ram; size_t total_psram; @@ -202,17 +262,17 @@ public: float ram_percent = 0.0f; float psram_percentage = 0.0f; float cpu_percent = 0.0f; - + // For CPU calculation uint32_t idle_count_last = _calibration_idle.idle_count_last; max_idle_iterations = _calibration_idle.max_idle_iterations; Serial.printf("idle_count_last: %i\n", idle_count_last); uint32_t idle_count_current = 0; - + uint counter = 0; while (_running) { counter++; - + // RAM Calculation (Internal + PSRAM) size_t internal_total = heap_caps_get_total_size(MALLOC_CAP_INTERNAL); size_t internal_free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); @@ -226,33 +286,33 @@ public: used_psram = total_psram - free_psram; ram_percent = (float)used_ram / (float)total_ram * 100.0f; psram_percentage = (float)used_psram / (float)total_psram * 100.0f; - + // CPU Usage - measure idle task iterations idle_count_current = xTaskGetIdleRunTimeCounter(); - + if (idle_count_last > 0 && max_idle_iterations > 0) { uint32_t idle_delta = idle_count_current - idle_count_last; - + // Calculate idle percentage based on baseline // We're measuring over 1ms, so compare to max_idle_iterations float idle_percent = ((float)idle_delta / (float)max_idle_iterations) * 100.0f; - + // Cap at 100% if (idle_percent > 100.0f) idle_percent = 100.0f; - + // CPU usage is inverse of idle cpu_percent = 100.0f - idle_percent; if (cpu_percent < 0) cpu_percent = 0; } else { cpu_percent = 0.0f; } - + idle_count_last = idle_count_current; - + _window->window_content_text[1].text = std::to_string(ram_percent) + "%"; _window->window_content_text[3].text = std::to_string((int)cpu_percent) + "%"; _window->window_content_text[5].text = std::to_string((int)psram_percentage) + "%"; - + vTaskDelay(pdMS_TO_TICKS(1)); if (counter == 1000) { /*Serial.printf("internal_total %i\n", internal_total); diff --git a/Desktop_Test/input_manager.cpp b/Desktop_Test/input_manager.cpp index 94ac43c..bb6b51f 100644 --- a/Desktop_Test/input_manager.cpp +++ b/Desktop_Test/input_manager.cpp @@ -57,77 +57,197 @@ void InputManager::update() { } void InputManager::handle_keyboard_input(char key) { - bool needs_redraw = false; + bool needs_redraw = true; - Serial.printf("key: %x\n", key & 0xff); + //Serial.printf("key: %x\n", key & 0xff); CLICK_EVENT event; switch(key) { - case 'd': // Right arrow alternative - case 'D': - mi.x = (mi.x + 5 > 476) ? 476 : mi.x + 5; - needs_redraw = true; - break; - - case 's': // Down arrow alternative - case 'S': - mi.y = (mi.y + 5 > 316) ? 316 : mi.y + 5; - needs_redraw = true; - break; - - case 'w': // Up arrow alternative - case 'W': - mi.y = (mi.y - 5 < 0) ? 0 : mi.y - 5; - needs_redraw = true; - break; - - case 'a': // Left arrow alternative + case 'a': [[fallthrough]]; case 'A': - mi.x = (mi.x - 5 < 0) ? 0 : mi.x - 5; - needs_redraw = true; + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'b': [[fallthrough]]; + case 'B': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'c': [[fallthrough]]; + case 'C': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'd': [[fallthrough]]; + case 'D': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'e': [[fallthrough]]; + case 'E': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'f': [[fallthrough]]; + case 'F': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'g': [[fallthrough]]; + case 'G': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'h': [[fallthrough]]; + case 'H': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'i': [[fallthrough]]; + case 'I': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'j': [[fallthrough]]; + case 'J': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'k': [[fallthrough]]; + case 'K': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'l': [[fallthrough]]; + case 'L': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'm': [[fallthrough]]; + case 'M': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'n': [[fallthrough]]; + case 'N': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'o': [[fallthrough]]; + case 'O': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'p': [[fallthrough]]; + case 'P': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'q': [[fallthrough]]; + case 'Q': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'r': [[fallthrough]]; + case 'R': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 's': [[fallthrough]]; + case 'S': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 't': [[fallthrough]]; + case 'T': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'u': [[fallthrough]]; + case 'U': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'v': [[fallthrough]]; + case 'V': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'w': [[fallthrough]]; + case 'W': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'x': [[fallthrough]]; + case 'X': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'y': [[fallthrough]]; + case 'Y': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; + break; + + case 'z': [[fallthrough]]; + case 'Z': + event.character = key; + event.event = CLICK_EVENTS::KEYBOARD; break; case 0xB4: // Left arrow key (CardKB sends special codes) mi.x = (mi.x - 5 < 0) ? 0 : mi.x - 5; - needs_redraw = true; break; case 0xB7: // Right arrow key mi.x = (mi.x + 5 > 476) ? 476 : mi.x + 5; - needs_redraw = true; break; case 0xB5: // Up arrow key mi.y = (mi.y - 5 < 0) ? 0 : mi.y - 5; - needs_redraw = true; break; case 0xB6: // Down arrow key mi.y = (mi.y + 5 > 316) ? 316 : mi.y + 5; - needs_redraw = true; break; - case 0xD: // Enter key - left click - case ' ': + case 0xD: // Enter key event.x = mi.x; event.y = mi.y; event.event = CLICK_EVENTS::LEFT_CLICK; break; - case 'r': // 'R' key - right click - case 'R': - event.x = mi.x; - event.y = mi.y; - event.event = CLICK_EVENTS::RIGHT_CLICK; - break; - default: + needs_redraw = false; break; } - - EventManager::getInstance().publish(event); if (needs_redraw) { + EventManager::getInstance().publish(event); _display_state->update_display.store(true); } } diff --git a/Desktop_Test/program.h b/Desktop_Test/program.h index 45606b5..890a265 100644 --- a/Desktop_Test/program.h +++ b/Desktop_Test/program.h @@ -53,6 +53,8 @@ struct WindowContentText { std::string text; short x; short y; + short width; + short height; char size; bool selectable = false; bool selected = false; diff --git a/Desktop_Test/shell.cpp b/Desktop_Test/shell.cpp index d6d3126..0f2d590 100644 --- a/Desktop_Test/shell.cpp +++ b/Desktop_Test/shell.cpp @@ -236,7 +236,12 @@ void Shell::draw_window(const Window& window) { tft->draw_box(window.x + 3, window.y + 35, window.width - 6, window.height - 38, COL_WHITE); for (WindowContentText text : window.window_content_text) { - tft->draw_text(text.x, text.y, text.text, COL_BLACK, text.size); + if (text.selected) { + tft->draw_text(text.x, text.y, text.text, COL_BLACK, text.size); + tft->draw_rect(text.x, text.y, text.width, text.height, 2, COL_BLACK); + } else { + tft->draw_text(text.x, text.y, text.text, COL_BLACK, text.size); + } } for (ContentButton button : window.content_buttons) { diff --git a/Desktop_Test/tft_handler.cpp b/Desktop_Test/tft_handler.cpp index 15cfe4c..26637fe 100644 --- a/Desktop_Test/tft_handler.cpp +++ b/Desktop_Test/tft_handler.cpp @@ -1,5 +1,6 @@ #include "GLOBALS.h" #include "tft_handler.h" +#include void TFT_Handler::init(DISPLAY_STATE* display_state) { _display_state = display_state;