Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
74bf36e
feat(screen): stream framebuffer to the client as FromRadio display_f…
jamesarich Aug 31, 2026
270bf00
fix(screen): harden mirror from adversarial review
jamesarich Aug 31, 2026
1ed930e
feat(screen): stream the TFT color-region palette for color-accurate …
jamesarich Aug 31, 2026
8a86083
fix(screen): capture the mirror palette at paint time, not after the …
jamesarich Aug 31, 2026
a678905
fix(screen): pre-PR review fixes for the mirror
jamesarich Aug 31, 2026
457eada
feat(screen): stream MUI dirty rects as RGB565 DisplayFrames
jamesarich Aug 31, 2026
ea4a349
fix(screen): size the MUI rect pool for a full repaint
jamesarich Aug 31, 2026
8ae4173
fix(screen): gate the MUI flush-observer registration on MESHTASTIC_M…
jamesarich Aug 31, 2026
b12e933
feat(screen): bridge InputBroker events into MUI
jamesarich Aug 31, 2026
7653316
fix(screen): route remote input to MUI directly, not through the Inpu…
jamesarich Aug 31, 2026
00812e8
feat(metadata): report DisplayInfo on MUI builds
jamesarich Aug 31, 2026
0a5acba
fix(screen): map remote directions onto MUI's trackball semantics
jamesarich Aug 31, 2026
13beda5
fix(screen): repair MUI mirror lifetime, ownership, and backpressure
jamesarich Aug 31, 2026
418843f
fix(screen): drop the spike-local device-ui override from the branch
jamesarich Sep 1, 2026
2d384a9
fix(screen): compile the MUI mirror out unless it is opted into
jamesarich Sep 1, 2026
774fb9d
fix(screen): report the real panel class, not TFT for everything
jamesarich Sep 1, 2026
7e5a6b1
Follow device-ui's new DisplayMirror API
jamesarich Sep 9, 2026
d4c1cb8
fix(screen): copy MUI rects by stride and undo the panel byte swap
jamesarich Oct 2, 2026
12952c8
fix(screen): subscribe per connection and fix palette and lifetime bugs
jamesarich Oct 2, 2026
faf7561
fix(screen): let DisplayMirror time MUI long-presses and map SELECT_LONG
jamesarich Oct 2, 2026
852b671
Bump protobufs to the rebased screen-mirror head and regenerate
jamesarich Oct 7, 2026
7a24a73
Include lvgl.h where the MUI mirror calls LVGL directly
jamesarich Oct 16, 2026
382752f
Keep mirror state off PhoneAPI and latch capture failures
jamesarich Oct 16, 2026
9cb8c42
Arm the MUI mirror on Portduino too
jamesarich Oct 20, 2026
6c5557d
Add a temporary native-tft-mirror env for testing the MUI mirror with…
jamesarich Oct 20, 2026
fb7967b
Never send palette signature 0, which frames reserve for monochrome
jamesarich Oct 21, 2026
dd67f9e
Send mirrored arrows to MUI as D-pad keys
jamesarich Nov 2, 2026
788f3a7
Pin native-tft-mirror to device-ui with mirrored input following focu…
jamesarich Nov 2, 2026
1b4333a
Pin native-tft-mirror to device-ui following the view-managed input g…
jamesarich Nov 2, 2026
00e272b
Size the MUI mirror rect pool from the panel
jamesarich Nov 2, 2026
1e60b0f
Pin native-tft-mirror to device-ui holding input until a slept panel …
jamesarich Nov 2, 2026
8641961
Pin protobufs to master, which now carries the display messages
jamesarich Nov 3, 2026
d3f7b76
Retry failed mirror captures and reuse the MUI rect pool as a ring
jamesarich Nov 3, 2026
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
14 changes: 14 additions & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#endif

// Display mirroring to local clients (FromRadio.display_frame).
#if HAS_SCREEN && !(MESHTASTIC_EXCLUDE_SCREEN_MIRROR)
#define HAS_SCREEN_MIRROR 1
#else
#define HAS_SCREEN_MIRROR 0
#endif

// MUI streams RGB565 dirty rects and needs a device-ui carrying DisplayMirror, so it is opt-in.
#if HAS_SCREEN_MIRROR && HAS_TFT && defined(MESHTASTIC_MUI_MIRROR)
#define HAS_MUI_MIRROR 1
#else
#define HAS_MUI_MIRROR 0
#endif

#ifndef USE_ETHERNET_DEFAULT
#define USE_ETHERNET_DEFAULT 0
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/graphics/HUB75Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#if defined(USE_HUB75)

#include "HUB75Display.h"
#include "ScreenMirror.h"
#include "TFTColorRegions.h"
#include "TFTPalette.h"
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
Expand Down Expand Up @@ -121,6 +122,9 @@ void HUB75Display::display()
firstFrame = false;
#if GRAPHICS_TFT_COLORING_ENABLED
lastColorSig = colorSig;
#if HAS_SCREEN_MIRROR
graphics::screenMirror.capturePalette(colorSig, onBe, offBe, graphics::colorRegions, graphics::getTFTColorRegionCount());
#endif
// Regions are re-registered every frame by the renderers; clear so they
// don't accumulate across frames.
graphics::clearTFTColorRegions();
Expand Down
17 changes: 17 additions & 0 deletions src/graphics/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "Screen.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "ScreenMirror.h"
#include "Throttle.h"
#include "UptimeClock.h"
#include "configuration.h"
Expand Down Expand Up @@ -182,6 +183,15 @@ static void drawLockdownLockScreen(OLEDDisplay *display)
}
#endif

// Hands ScreenMirror the committed framebuffer; a no-op unless a client is armed.
static inline void screenMirrorCapture()
{
#if HAS_SCREEN_MIRROR
if (screen)
screenMirror.onRendered(screen->getDisplayDevice());
#endif
}

static inline void updateUiFrame(OLEDDisplayUi *ui)
{
#ifdef MESHTASTIC_LOCKDOWN
Expand Down Expand Up @@ -209,13 +219,15 @@ static inline void updateUiFrame(OLEDDisplayUi *ui)
NotificationRenderer::drawBannercallback(display, ui->getUiState());
}
display->display();
screenMirrorCapture(); // the locked frame, matching the panel's redaction
return;
}
#endif
#if GRAPHICS_TFT_COLORING_ENABLED
prepareFrameColorRegions();
#endif
ui->update();
screenMirrorCapture();
}
// Global variables for alert banner - explicitly define with extern "C" linkage to prevent optimization

Expand Down Expand Up @@ -1230,6 +1242,11 @@ int32_t Screen::runOnce()

if (!screenOn) { // If we didn't just wake and the screen is still off, then
// stop updating until it is on again
#ifdef MESHTASTIC_LOCKDOWN
// the last committed frame may predate the lock
if (!meshtastic_security::shouldRedactDisplay())
#endif
screenMirrorCapture(); // a request while off still gets the last committed frame
textMessageFrameShown = false;
enabled = false;
return 0;
Expand Down
3 changes: 3 additions & 0 deletions src/graphics/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,9 @@ class Screen : public concurrency::OSThread
enqueueCmd(ScreenCmd{.cmd = Cmd::NOOP});
}

/// Runs the screen thread once without touching the display; safe from any task.
void kick() { enqueueCmd(ScreenCmd{.cmd = Cmd::NOOP}); }

/// Overrides the default utf8 character conversion, to replace empty space with question marks
static char customFontTableLookup(const uint8_t ch)
{
Expand Down
Loading
Loading