diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 19b20e8dc..f8a64cc61 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -48,6 +48,7 @@ along with this program. If not, see .
#include "modules/AdminModule.h"
#include "modules/ExternalNotificationModule.h"
#include "modules/TextMessageModule.h"
+#include "modules/WaypointModule.h"
#include "sleep.h"
#include "target_specific.h"
@@ -2112,8 +2113,13 @@ void Screen::setFrames(FrameFocus focus)
// 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())
+ if (m->isRequestingFocus()) {
fsi.positions.focusedModule = numframes;
+ }
+
+ // Identify the position of specific modules, if we need to know this later
+ if (m == waypointModule)
+ fsi.positions.waypoint = numframes;
numframes++;
}
@@ -2132,8 +2138,8 @@ void Screen::setFrames(FrameFocus focus)
#endif
// If we have a text message - show it next, unless it's a phone message and we aren't using any special modules
- fsi.positions.textMessage = numframes;
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
+ fsi.positions.textMessage = numframes;
normalFrames[numframes++] = drawTextMessageFrame;
}
@@ -2235,6 +2241,31 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
setFastFramerate();
}
+// Dismisses the currently displayed screen frame, if possible
+// Relevant for text message, waypoint, others in future?
+// Triggered with a CardKB keycombo
+void Screen::dismissCurrentFrame()
+{
+ uint8_t currentFrame = ui->getUiState()->currentFrame;
+ bool dismissed = false;
+
+ if (currentFrame == framesetInfo.positions.textMessage && devicestate.has_rx_text_message) {
+ LOG_INFO("Dismissing Text Message\n");
+ devicestate.has_rx_text_message = false;
+ dismissed = true;
+ }
+
+ else if (currentFrame == framesetInfo.positions.waypoint && devicestate.has_rx_waypoint) {
+ LOG_DEBUG("Dismissing Waypoint\n");
+ devicestate.has_rx_waypoint = false;
+ dismissed = true;
+ }
+
+ // If we did make changes to dismiss, we now need to regenerate the frameset
+ if (dismissed)
+ setFrames();
+}
+
void Screen::handleStartFirmwareUpdateScreen()
{
LOG_DEBUG("showing firmware screen\n");
@@ -2747,12 +2778,23 @@ int Screen::handleInputEvent(const InputEvent *event)
}
#endif
- if (showingNormalScreen && moduleFrames.size() == 0) {
- // LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
- if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
- showPrevFrame();
- } else if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
- showNextFrame();
+ // Use left or right input from a keyboard to move between frames,
+ // so long as a mesh module isn't using these events for some other purpose
+ if (showingNormalScreen) {
+
+ // Ask any MeshModules if they're handling keyboard input right now
+ bool inputIntercepted = false;
+ for (MeshModule *module : moduleFrames) {
+ if (module->interceptingKeyboardInput())
+ inputIntercepted = true;
+ }
+
+ // If no modules are using the input, move between frames
+ if (!inputIntercepted) {
+ if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT))
+ showPrevFrame();
+ else if (event->inputEvent == static_cast(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))
+ showNextFrame();
}
}
diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h
index 021b11bda..b2e6e905b 100644
--- a/src/graphics/Screen.h
+++ b/src/graphics/Screen.h
@@ -454,6 +454,9 @@ class Screen : public concurrency::OSThread
void setWelcomeFrames();
+ // Dismiss the currently focussed frame, if possible (e.g. text message, waypoint)
+ void dismissCurrentFrame();
+
#ifdef USE_EINK
/// Draw an image to remain on E-Ink display after screen off
void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
@@ -503,11 +506,14 @@ class Screen : public concurrency::OSThread
void handleStartFirmwareUpdateScreen();
// Info collected by setFrames method.
- // Index location of specific frames. Used to apply the FrameFocus parameter of setFrames
+ // Index location of specific frames.
+ // - Used to apply the FrameFocus parameter of setFrames
+ // - Used to dismiss the currently shown frame (txt; waypoint) by CardKB combo
struct FramesetInfo {
struct FramePositions {
uint8_t fault = 0;
uint8_t textMessage = 0;
+ uint8_t waypoint = 0;
uint8_t focusedModule = 0;
uint8_t log = 0;
uint8_t settings = 0;
diff --git a/src/input/InputBroker.h b/src/input/InputBroker.h
index 082268f0a..17c621c8a 100644
--- a/src/input/InputBroker.h
+++ b/src/input/InputBroker.h
@@ -11,6 +11,7 @@
#define INPUT_BROKER_MSG_GPS_TOGGLE 0x9e
#define INPUT_BROKER_MSG_MUTE_TOGGLE 0xac
#define INPUT_BROKER_MSG_SEND_PING 0xaf
+#define INPUT_BROKER_MSG_DISMISS_FRAME 0x8b
#define INPUT_BROKER_MSG_LEFT 0xb4
#define INPUT_BROKER_MSG_UP 0xb5
#define INPUT_BROKER_MSG_DOWN 0xb6
diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp
index 1d8154bcf..4fbca76e5 100644
--- a/src/input/kbI2cBase.cpp
+++ b/src/input/kbI2cBase.cpp
@@ -296,6 +296,7 @@ int32_t KbI2cBase::runOnce()
case 0xac: // fn+m INPUT_BROKER_MSG_MUTE_TOGGLE
case 0x9e: // fn+g INPUT_BROKER_MSG_GPS_TOGGLE
case 0xaf: // fn+space INPUT_BROKER_MSG_SEND_PING
+ case 0x8b: // fn+del INPUT_BROKEN_MSG_DISMISS_FRAME
// just pass those unmodified
e.inputEvent = ANYKEY;
e.kbchar = c;
diff --git a/src/mesh/MeshModule.h b/src/mesh/MeshModule.h
index c341b301a..7929ba972 100644
--- a/src/mesh/MeshModule.h
+++ b/src/mesh/MeshModule.h
@@ -79,7 +79,8 @@ class MeshModule
meshtastic_AdminMessage *response);
#if HAS_SCREEN
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
- virtual bool isRequestingFocus(); // Checked by screen, when regenerating frameset
+ virtual bool isRequestingFocus(); // Checked by screen, when regenerating frameset
+ virtual bool interceptingKeyboardInput() { return false; } // Can screen use keyboard for nav, or is module handling input?
#endif
protected:
const char *name;
diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp
index a1b9c4dc0..d4d112f90 100644
--- a/src/modules/CannedMessageModule.cpp
+++ b/src/modules/CannedMessageModule.cpp
@@ -276,6 +276,13 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
showTemporaryMessage("Node Info \nUpdate Sent");
}
break;
+ case INPUT_BROKER_MSG_DISMISS_FRAME: // fn+del: dismiss screen frames like text or waypoint
+ // Avoid opening the canned message screen frame
+ // We're only handling the keypress here by convention, this has nothing to do with canned messages
+ this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
+ // Attempt to close whatever frame is currently shown on display
+ screen->dismissCurrentFrame();
+ return 0;
default:
// pass the pressed key
// LOG_DEBUG("Canned message ANYKEY (%x)\n", event->kbchar);
@@ -935,6 +942,19 @@ void CannedMessageModule::drawEnterIcon(OLEDDisplay *display, int x, int y, floa
#endif
+// Indicate to screen class that module is handling keyboard input specially (at certain times)
+// This prevents the left & right keys being used for nav. between screen frames during text entry.
+bool CannedMessageModule::interceptingKeyboardInput()
+{
+ switch (runState) {
+ case CANNED_MESSAGE_RUN_STATE_DISABLED:
+ case CANNED_MESSAGE_RUN_STATE_INACTIVE:
+ return false;
+ default:
+ return true;
+ }
+}
+
void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
char buffer[50];
diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h
index 368574c40..e9dc2bda0 100644
--- a/src/modules/CannedMessageModule.h
+++ b/src/modules/CannedMessageModule.h
@@ -114,6 +114,7 @@ class CannedMessageModule : public SinglePortModule, public ObservableshouldDraw(); }
virtual Observable *getUIFrameObservable() override { return this; }
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) override;
+ virtual bool interceptingKeyboardInput() override;
virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response) override;