Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/graphics/SharedUIDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@ namespace graphics

void determineResolution(int16_t screenheight, int16_t screenwidth)
{

#ifdef FORCE_LOW_RES
isHighResolution = false;
return;
#endif

if (screenwidth > 128) {
isHighResolution = true;
}

if (screenwidth > 128 && screenheight <= 64) {
isHighResolution = false;
}

// Special case for Heltec Wireless Tracker v1.1
if (screenwidth == 160 && screenheight == 80) {
isHighResolution = false;
}
}

// === Shared External State ===
Expand Down
20 changes: 18 additions & 2 deletions src/input/SerialKeyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "configuration.h"
#include <Throttle.h>

SerialKeyboard *globalSerialKeyboard = nullptr;

#ifdef INPUTBROKER_SERIAL_TYPE
#define CANNED_MESSAGE_MODULE_ENABLE 1 // in case it's not set in the variant file

Expand All @@ -25,6 +27,8 @@ unsigned char KeyMap[3][4][10] = {{{'.', 'a', 'd', 'g', 'j', 'm', 'p', 't', 'w',
SerialKeyboard::SerialKeyboard(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;

globalSerialKeyboard = this;
}

void SerialKeyboard::erase()
Expand Down Expand Up @@ -85,9 +89,21 @@ int32_t SerialKeyboard::runOnce()
e.source = this->_originName;
// SELECT OR SEND OR CANCEL EVENT
if (!(shiftRegister2 & (1 << 3))) {
e.inputEvent = INPUT_BROKER_UP;
if (shift > 0) {
e.inputEvent = INPUT_BROKER_ANYKEY; // REQUIRED
e.kbchar = 0x09; // TAB
shift = 0; // reset shift after TAB
} else {
e.inputEvent = INPUT_BROKER_LEFT;
}
} else if (!(shiftRegister2 & (1 << 2))) {
e.inputEvent = INPUT_BROKER_RIGHT;
if (shift > 0) {
e.inputEvent = INPUT_BROKER_ANYKEY; // REQUIRED
e.kbchar = 0x09; // TAB
shift = 0; // reset shift after TAB
} else {
e.inputEvent = INPUT_BROKER_RIGHT;
}
e.kbchar = 0;
} else if (!(shiftRegister2 & (1 << 1))) {
e.inputEvent = INPUT_BROKER_SELECT;
Expand Down
6 changes: 5 additions & 1 deletion src/input/SerialKeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class SerialKeyboard : public Observable<const InputEvent *>, public concurrency
public:
explicit SerialKeyboard(const char *name);

uint8_t getShift() const { return shift; }

protected:
virtual int32_t runOnce() override;
void erase();
Expand All @@ -22,4 +24,6 @@ class SerialKeyboard : public Observable<const InputEvent *>, public concurrency
int lastKeyPressed = 13;
int quickPress = 0;
unsigned long lastPressTime = 0;
};
};

extern SerialKeyboard *globalSerialKeyboard;
84 changes: 83 additions & 1 deletion src/modules/CannedMessageModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "graphics/draw/NotificationRenderer.h"
#include "graphics/emotes.h"
#include "graphics/images.h"
#include "input/SerialKeyboard.h"
#include "main.h" // for cardkb_found
#include "mesh/generated/meshtastic/cannedmessages.pb.h"
#include "modules/AdminModule.h"
Expand Down Expand Up @@ -1848,7 +1849,88 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
}

// --- Draw Free Text input with multi-emote support and proper line wrapping ---
#if INPUTBROKER_SERIAL_TYPE == 1
// Chatter Modifier key mode label (right side)
{
uint8_t mode = globalSerialKeyboard ? globalSerialKeyboard->getShift() : 0;
const char *label = (mode == 0) ? "a" : (mode == 1) ? "A" : "#";

display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_LEFT);

const int16_t th = FONT_HEIGHT_SMALL;
const int16_t tw = display->getStringWidth(label);
const int16_t padX = 3;
const int16_t padY = 2;
const int16_t r = 3;

const int16_t bw = tw + padX * 2;
const int16_t bh = th + padY * 2;

const int16_t bx = x + display->getWidth() - bw - 2;
const int16_t by = y + display->getHeight() - bh - 2;

display->setColor(WHITE);
display->fillRect(bx + r, by, bw - r * 2, bh);
display->fillRect(bx, by + r, r, bh - r * 2);
display->fillRect(bx + bw - r, by + r, r, bh - r * 2);
display->fillCircle(bx + r, by + r, r);
display->fillCircle(bx + bw - r - 1, by + r, r);
display->fillCircle(bx + r, by + bh - r - 1, r);
display->fillCircle(bx + bw - r - 1, by + bh - r - 1, r);

display->setColor(BLACK);
display->drawString(bx + padX, by + padY, label);
}

// LEFT-SIDE DESTINATION-HINT BOX (“Dest: Shift + ◄”)
{
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_LEFT);

const char *label = "Dest: Shift + ";
int16_t labelW = display->getStringWidth(label);

// triangle size visually matches glyph height, not full line height
const int triH = FONT_HEIGHT_SMALL - 3;
const int triW = triH * 0.7;

const int16_t padX = 3;
const int16_t padY = 2;
const int16_t r = 3;

const int16_t bw = labelW + triW + padX * 2 + 2;
const int16_t bh = FONT_HEIGHT_SMALL + padY * 2;

const int16_t bx = x + 2;
const int16_t by = y + display->getHeight() - bh - 2;

// Rounded white box
display->setColor(WHITE);
display->fillRect(bx + r, by, bw - (r * 2), bh);
display->fillRect(bx, by + r, r, bh - (r * 2));
display->fillRect(bx + bw - r, by + r, r, bh - (r * 2));
display->fillCircle(bx + r, by + r, r);
display->fillCircle(bx + bw - r - 1, by + r, r);
display->fillCircle(bx + r, by + bh - r - 1, r);
display->fillCircle(bx + bw - r - 1, by + bh - r - 1, r);

// Draw text
display->setColor(BLACK);
display->drawString(bx + padX, by + padY, label);

// Perfectly center triangle on text baseline
int16_t tx = bx + padX + labelW;
int16_t ty = by + padY + (FONT_HEIGHT_SMALL / 2) - (triH / 2) - 1; // -1 for optical centering

// ◄ Left-pointing triangle
display->fillTriangle(tx + triW, ty, // top-right
tx, ty + triH / 2, // left center
tx + triW, ty + triH // bottom-right
);
}
#endif
// Draw Free Text input with multi-emote support and proper line wrapping
display->setColor(WHITE);
{
int inputY = 0 + y + FONT_HEIGHT_SMALL;
Expand Down
1 change: 1 addition & 0 deletions variants/esp32/chatter2/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#define TFT_OFFSET_X 0
#define TFT_OFFSET_Y 0
#define TFT_INVERT false
#define FORCE_LOW_RES 1
#define SCREEN_ROTATE
#define SCREEN_TRANSITION_FRAMERATE 5 // fps
#define DISPLAY_FORCE_SMALL_FONTS
Expand Down
1 change: 1 addition & 0 deletions variants/esp32s3/heltec_wireless_tracker_V1_0/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
#define DISPLAY_FORCE_SMALL_FONTS
#define FORCE_LOW_RES 1

#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define VEXT_ON_VALUE LOW
Expand Down