diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 40ec51757..731d1140f 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -775,33 +775,6 @@ void Screen::setFrames(FrameFocus focus) size_t numframes = 0; - moduleFrames = MeshModule::GetMeshModulesWithUIFrames(); - LOG_DEBUG("Show %d module frames", moduleFrames.size()); - - // put all of the module frames first. - // this is a little bit of a dirty hack; since we're going to call - // the same drawModuleFrame handler here for all of these module frames - // and then we'll just assume that the state->currentFrame value - // is the same offset into the moduleFrames vector - // so that we can invoke the module's callback - for (auto i = moduleFrames.begin(); i != moduleFrames.end(); ++i) { - // Draw the module frame, using the hack described above - normalFrames[numframes] = drawModuleFrame; - - // Check if the module being drawn has requested focus - // We will honor this request later, if setFrames was triggered by a UIFrameEvent - MeshModule *m = *i; - if (m->isRequestingFocus()) - fsi.positions.focusedModule = numframes; - if (m == waypointModule) - fsi.positions.waypoint = numframes; - - indicatorIcons.push_back(icon_module); - numframes++; - } - - LOG_DEBUG("Added modules. numframes: %d", numframes); - // If we have a critical fault, show it first fsi.positions.fault = numframes; if (error_code) { @@ -898,6 +871,36 @@ void Screen::setFrames(FrameFocus focus) } #endif + // Beware of what changes you make in this code! + // We pass numfames into GetMeshModulesWithUIFrames() which is highly important! + // Inside of that callback, goes over to MeshModule.cpp and we run + // modulesWithUIFrames.resize(startIndex, nullptr), to insert nullptr + // entries until we're ready to start building the matching entries. + // We are doing our best to keep the normalFrames vector + // and the moduleFrames vector in lock step. + moduleFrames = MeshModule::GetMeshModulesWithUIFrames(numframes); + LOG_DEBUG("Show %d module frames", moduleFrames.size()); + + for (auto i = moduleFrames.begin(); i != moduleFrames.end(); ++i) { + // Draw the module frame, using the hack described above + if (*i != nullptr) { + normalFrames[numframes] = drawModuleFrame; + + // Check if the module being drawn has requested focus + // We will honor this request later, if setFrames was triggered by a UIFrameEvent + MeshModule *m = *i; + if (m && m->isRequestingFocus()) + fsi.positions.focusedModule = numframes; + if (m && m == waypointModule) + fsi.positions.waypoint = numframes; + + indicatorIcons.push_back(icon_module); + numframes++; + } + } + + LOG_DEBUG("Added modules. numframes: %d", numframes); + fsi.frameCount = numframes; // Total framecount is used to apply FOCUS_PRESERVE this->frameCount = numframes; // ✅ Save frame count for use in custom overlay LOG_DEBUG("Finished build frames. numframes: %d", numframes); @@ -1249,7 +1252,7 @@ int Screen::handleInputEvent(const InputEvent *event) // Ask any MeshModules if they're handling keyboard input right now bool inputIntercepted = false; for (MeshModule *module : moduleFrames) { - if (module->interceptingKeyboardInput()) + if (module && module->interceptingKeyboardInput()) inputIntercepted = true; } diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index b5aa1f7f4..c5748a560 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -244,9 +244,13 @@ void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to) p->decoded.request_id = to.id; } -std::vector MeshModule::GetMeshModulesWithUIFrames() +std::vector MeshModule::GetMeshModulesWithUIFrames(int startIndex) { std::vector modulesWithUIFrames; + + // Fill with nullptr up to startIndex + modulesWithUIFrames.resize(startIndex, nullptr); + if (modules) { for (auto i = modules->begin(); i != modules->end(); ++i) { auto &pi = **i; diff --git a/src/mesh/MeshModule.h b/src/mesh/MeshModule.h index f08b8f49c..eda3f8881 100644 --- a/src/mesh/MeshModule.h +++ b/src/mesh/MeshModule.h @@ -75,7 +75,7 @@ class MeshModule */ static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO); - static std::vector GetMeshModulesWithUIFrames(); + static std::vector GetMeshModulesWithUIFrames(int startIndex); static void observeUIEvents(Observer *observer); static AdminMessageHandleResult handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index dd37f0dec..ebca9e676 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -334,13 +334,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event) } // Printable char (ASCII) opens free text compose if (event->kbchar >= 32 && event->kbchar <= 126) { - runState = CANNED_MESSAGE_RUN_STATE_FREETEXT; - requestFocus(); - UIFrameEvent e; - e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; - notifyObservers(&e); - // Immediately process the input in the new state (freetext) - return handleFreeTextInput(event); + LaunchFreetextWithDestination(NODENUM_BROADCAST); + return 1; } break;