mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-28 04:31:58 +00:00
InkHUD refactoring (#6216)
* chore: todo.txt * chore: comments * fix: no fast refresh on VME290 Reverts a line of code which was accidentally committed * refactor: god class Divide the behavior from the old WindowManager class into several subclasses which each have a clear role. * refactor: cppcheck medium warnings Enough to pass github CI for now * refactor: updateType selection * refactor: don't use a setter for the shared AppletFonts * fix: update prioritization forceUpdate calls weren't being prioritized * refactor: remove unhelpful logging getTimeString is used for parsing our own time, but also the timestamps of messages. The "one time only" log printing will likely fire in unhelpful situations. * fix: " " * refactor: get rid of types.h file for enums * Keep that sneaky todo file out of commits
This commit is contained in:
@@ -4,10 +4,10 @@
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
void InkHUD::BatteryIconApplet::onActivate()
|
||||
InkHUD::BatteryIconApplet::BatteryIconApplet()
|
||||
{
|
||||
// Show at boot, if user has previously enabled the feature
|
||||
if (settings.optionalFeatures.batteryIcon)
|
||||
if (settings->optionalFeatures.batteryIcon)
|
||||
bringToForeground();
|
||||
|
||||
// Register to our have BatteryIconApplet::onPowerStatusUpdate method called when new power info is available
|
||||
@@ -15,12 +15,6 @@ void InkHUD::BatteryIconApplet::onActivate()
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
}
|
||||
|
||||
void InkHUD::BatteryIconApplet::onDeactivate()
|
||||
{
|
||||
// Stop having onPowerStatusUpdate called
|
||||
powerStatusObserver.unobserve(&powerStatus->onNewStatus);
|
||||
}
|
||||
|
||||
// We handle power status' even when the feature is disabled,
|
||||
// so that we have up to date data ready if the feature is enabled later.
|
||||
// Otherwise could be 30s before new status update, with weird battery value displayed
|
||||
@@ -41,7 +35,7 @@ int InkHUD::BatteryIconApplet::onPowerStatusUpdate(const meshtastic::Status *sta
|
||||
// If rounded value has changed, trigger a display update
|
||||
// It's okay to requestUpdate before we store the new value, as the update won't run until next loop()
|
||||
// Don't trigger an update if the feature is disabled
|
||||
if (this->socRounded != newSocRounded && settings.optionalFeatures.batteryIcon)
|
||||
if (this->socRounded != newSocRounded && settings->optionalFeatures.batteryIcon)
|
||||
requestUpdate();
|
||||
|
||||
// Store the new value
|
||||
|
||||
@@ -11,24 +11,22 @@ It should be optional, enabled by the on-screen menu
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
#include "PowerStatus.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class BatteryIconApplet : public Applet
|
||||
class BatteryIconApplet : public SystemApplet
|
||||
{
|
||||
public:
|
||||
BatteryIconApplet();
|
||||
|
||||
void onRender() override;
|
||||
|
||||
void onActivate() override;
|
||||
void onDeactivate() override;
|
||||
|
||||
int onPowerStatusUpdate(const meshtastic::Status *status); // Called when new info about battery is available
|
||||
|
||||
protected:
|
||||
private:
|
||||
// Get informed when new information about the battery is available (via onPowerStatusUpdate method)
|
||||
CallbackObserver<BatteryIconApplet, const meshtastic::Status *> powerStatusObserver =
|
||||
CallbackObserver<BatteryIconApplet, const meshtastic::Status *>(this, &BatteryIconApplet::onPowerStatusUpdate);
|
||||
|
||||
@@ -2,15 +2,22 @@
|
||||
|
||||
#include "./LogoApplet.h"
|
||||
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
InkHUD::LogoApplet::LogoApplet() : concurrency::OSThread("LogoApplet")
|
||||
{
|
||||
// Don't autostart the runOnce() timer
|
||||
OSThread::disable();
|
||||
OSThread::setIntervalFromNow(8 * 1000UL);
|
||||
OSThread::enabled = true;
|
||||
|
||||
// Grab the WindowManager singleton, for convenience
|
||||
windowManager = WindowManager::getInstance();
|
||||
textLeft = "";
|
||||
textRight = "";
|
||||
textTitle = xstr(APP_VERSION_SHORT);
|
||||
fontTitle = fontSmall;
|
||||
|
||||
bringToForeground();
|
||||
// This is then drawn with a FULL refresh by Renderer::begin
|
||||
}
|
||||
|
||||
void InkHUD::LogoApplet::onRender()
|
||||
@@ -48,53 +55,24 @@ void InkHUD::LogoApplet::onRender()
|
||||
|
||||
void InkHUD::LogoApplet::onForeground()
|
||||
{
|
||||
// If another applet has locked the display, ask it to exit
|
||||
Applet *other = windowManager->whoLocked();
|
||||
if (other != nullptr)
|
||||
other->sendToBackground();
|
||||
|
||||
windowManager->claimFullscreen(this); // Take ownership of fullscreen tile
|
||||
windowManager->lock(this); // Prevent other applets from requesting updates
|
||||
SystemApplet::lockRendering = true;
|
||||
SystemApplet::lockRequests = true;
|
||||
SystemApplet::handleInput = true; // We don't actually use this input. Just blocking other applets from using it.
|
||||
}
|
||||
|
||||
void InkHUD::LogoApplet::onBackground()
|
||||
{
|
||||
OSThread::disable(); // Disable auto-dismiss timer, in case applet was dismissed early (sendToBackground from outside class)
|
||||
|
||||
windowManager->releaseFullscreen(); // Relinquish ownership of fullscreen tile
|
||||
windowManager->unlock(this); // Allow normal user applet update requests to resume
|
||||
SystemApplet::lockRendering = false;
|
||||
SystemApplet::lockRequests = false;
|
||||
SystemApplet::handleInput = false;
|
||||
|
||||
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
|
||||
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
|
||||
windowManager->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
int32_t InkHUD::LogoApplet::runOnce()
|
||||
{
|
||||
LOG_DEBUG("Sent to background by timer");
|
||||
sendToBackground();
|
||||
return OSThread::disable();
|
||||
}
|
||||
|
||||
// Begin displaying the screen which is shown at startup
|
||||
// Suggest EInk::await after calling this method
|
||||
void InkHUD::LogoApplet::showBootScreen()
|
||||
{
|
||||
OSThread::setIntervalFromNow(8 * 1000UL);
|
||||
OSThread::enabled = true;
|
||||
|
||||
textLeft = "";
|
||||
textRight = "";
|
||||
textTitle = xstr(APP_VERSION_SHORT);
|
||||
fontTitle = fontSmall;
|
||||
|
||||
bringToForeground();
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FULL); // Already requested, just upgrading to FULL
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
// Begin displaying the screen which is shown at shutdown
|
||||
// Needs EInk::await after calling this method, to ensure display updates before shutdown
|
||||
void InkHUD::LogoApplet::showShutdownScreen()
|
||||
void InkHUD::LogoApplet::onShutdown()
|
||||
{
|
||||
textLeft = "";
|
||||
textRight = "";
|
||||
@@ -102,7 +80,13 @@ void InkHUD::LogoApplet::showShutdownScreen()
|
||||
fontTitle = fontLarge;
|
||||
|
||||
bringToForeground();
|
||||
requestUpdate(Drivers::EInk::UpdateTypes::FULL); // Already requested, just upgrading to FULL
|
||||
// This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update
|
||||
}
|
||||
|
||||
int32_t InkHUD::LogoApplet::runOnce()
|
||||
{
|
||||
sendToBackground();
|
||||
return OSThread::disable();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -12,24 +12,19 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class LogoApplet : public Applet, public concurrency::OSThread
|
||||
class LogoApplet : public SystemApplet, public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
LogoApplet();
|
||||
void onRender() override;
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
|
||||
// Note: interacting directly with an applet like this is non-standard
|
||||
// Only permitted because this is a "system applet", which has special behavior and interacts directly with WindowManager
|
||||
|
||||
void showBootScreen();
|
||||
void showShutdownScreen();
|
||||
void onShutdown() override;
|
||||
|
||||
protected:
|
||||
int32_t runOnce() override;
|
||||
@@ -38,8 +33,6 @@ class LogoApplet : public Applet, public concurrency::OSThread
|
||||
std::string textRight;
|
||||
std::string textTitle;
|
||||
AppletFont fontTitle;
|
||||
|
||||
WindowManager *windowManager = nullptr; // For convenience
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
#include "./MenuApplet.h"
|
||||
|
||||
#include "PowerStatus.h"
|
||||
#include "RTC.h"
|
||||
|
||||
#include "airtime.h"
|
||||
#include "power.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
static constexpr uint8_t MENU_TIMEOUT_SEC = 60; // How many seconds before menu auto-closes
|
||||
@@ -17,23 +19,16 @@ InkHUD::MenuApplet::MenuApplet() : concurrency::OSThread("MenuApplet")
|
||||
{
|
||||
// No timer tasks at boot
|
||||
OSThread::disable();
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onActivate()
|
||||
{
|
||||
// Grab pointers to some singleton components which the menu interacts with
|
||||
// We could do this every time we needed them, in place,
|
||||
// but this just makes the code tidier
|
||||
|
||||
this->windowManager = WindowManager::getInstance();
|
||||
|
||||
// Note: don't get instance if we're not actually using the backlight,
|
||||
// or else you will unintentionally instantiate it
|
||||
if (settings.optionalMenuItems.backlight) {
|
||||
if (settings->optionalMenuItems.backlight) {
|
||||
backlight = Drivers::LatchingBacklight::getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onActivate() {}
|
||||
|
||||
void InkHUD::MenuApplet::onForeground()
|
||||
{
|
||||
// We do need this before we render, but we can optimize by just calculating it once now
|
||||
@@ -45,21 +40,23 @@ void InkHUD::MenuApplet::onForeground()
|
||||
// If device has a backlight which isn't controlled by aux button:
|
||||
// backlight on always when menu opens.
|
||||
// Courtesy to T-Echo users who removed the capacitive touch button
|
||||
if (settings.optionalMenuItems.backlight) {
|
||||
if (settings->optionalMenuItems.backlight) {
|
||||
assert(backlight);
|
||||
if (!backlight->isOn())
|
||||
backlight->peek();
|
||||
}
|
||||
|
||||
// Prevent user applets requested update while menu is open
|
||||
windowManager->lock(this);
|
||||
// Prevent user applets requesting update while menu is open
|
||||
// Handle button input with this applet
|
||||
SystemApplet::lockRequests = true;
|
||||
SystemApplet::handleInput = true;
|
||||
|
||||
// Begin the auto-close timeout
|
||||
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
|
||||
OSThread::enabled = true;
|
||||
|
||||
// Upgrade the refresh to FAST, for guaranteed responsiveness
|
||||
windowManager->forceUpdate(EInk::UpdateTypes::FAST);
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
void InkHUD::MenuApplet::onBackground()
|
||||
@@ -67,7 +64,7 @@ void InkHUD::MenuApplet::onBackground()
|
||||
// If device has a backlight which isn't controlled by aux button:
|
||||
// Item in options submenu allows keeping backlight on after menu is closed
|
||||
// If this item is deselected we will turn backlight off again, now that menu is closing
|
||||
if (settings.optionalMenuItems.backlight) {
|
||||
if (settings->optionalMenuItems.backlight) {
|
||||
assert(backlight);
|
||||
if (!backlight->isLatched())
|
||||
backlight->off();
|
||||
@@ -77,7 +74,8 @@ void InkHUD::MenuApplet::onBackground()
|
||||
OSThread::disable();
|
||||
|
||||
// Resume normal rendering and button behavior of user applets
|
||||
windowManager->unlock(this);
|
||||
SystemApplet::lockRequests = false;
|
||||
SystemApplet::handleInput = false;
|
||||
|
||||
// Restore the user applet whose tile we borrowed
|
||||
if (borrowedTileOwner)
|
||||
@@ -87,8 +85,8 @@ void InkHUD::MenuApplet::onBackground()
|
||||
borrowedTileOwner = nullptr;
|
||||
|
||||
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
|
||||
// We're only updating here to ugrade from UNSPECIFIED to FAST, to ensure responsiveness when exiting menu
|
||||
windowManager->forceUpdate(EInk::UpdateTypes::FAST);
|
||||
// We're only updating here to upgrade from UNSPECIFIED to FAST, to ensure responsiveness when exiting menu
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FAST);
|
||||
}
|
||||
|
||||
// Open the menu
|
||||
@@ -140,43 +138,35 @@ void InkHUD::MenuApplet::execute(MenuItem item)
|
||||
break;
|
||||
|
||||
case NEXT_TILE:
|
||||
// Note performed manually;
|
||||
// WindowManager::nextTile is raised by aux button press only, and will interact poorly with the menu
|
||||
settings.userTiles.focused = (settings.userTiles.focused + 1) % settings.userTiles.count;
|
||||
windowManager->changeLayout();
|
||||
cursor = 0; // No menu item selected, for quick exit after tile swap
|
||||
cursorShown = false;
|
||||
inkhud->nextTile();
|
||||
break;
|
||||
|
||||
case ROTATE:
|
||||
settings.rotation = (settings.rotation + 1) % 4;
|
||||
windowManager->changeLayout();
|
||||
// requestUpdate(Drivers::EInk::UpdateTypes::FULL); // Would update regardless; just selecting FULL
|
||||
inkhud->rotate();
|
||||
break;
|
||||
|
||||
case LAYOUT:
|
||||
// Todo: smarter incrementing of tile count
|
||||
settings.userTiles.count++;
|
||||
settings->userTiles.count++;
|
||||
|
||||
if (settings.userTiles.count == 3) // Skip 3 tiles: not done yet
|
||||
settings.userTiles.count++;
|
||||
if (settings->userTiles.count == 3) // Skip 3 tiles: not done yet
|
||||
settings->userTiles.count++;
|
||||
|
||||
if (settings.userTiles.count > settings.userTiles.maxCount) // Loop around if tile count now too high
|
||||
settings.userTiles.count = 1;
|
||||
if (settings->userTiles.count > settings->userTiles.maxCount) // Loop around if tile count now too high
|
||||
settings->userTiles.count = 1;
|
||||
|
||||
windowManager->changeLayout();
|
||||
// requestUpdate(Drivers::EInk::UpdateTypes::FULL); // Would update regardless; just selecting FULL
|
||||
inkhud->updateLayout();
|
||||
break;
|
||||
|
||||
case TOGGLE_APPLET:
|
||||
settings.userApplets.active[cursor] = !settings.userApplets.active[cursor];
|
||||
windowManager->changeActivatedApplets();
|
||||
settings->userApplets.active[cursor] = !settings->userApplets.active[cursor];
|
||||
inkhud->updateAppletSelection();
|
||||
// requestUpdate(Drivers::EInk::UpdateTypes::FULL); // Select FULL, seeing how this action doesn't auto exit
|
||||
break;
|
||||
|
||||
case ACTIVATE_APPLETS:
|
||||
// Todo: remove this action? Already handled by TOGGLE_APPLET?
|
||||
windowManager->changeActivatedApplets();
|
||||
inkhud->updateAppletSelection();
|
||||
break;
|
||||
|
||||
case TOGGLE_AUTOSHOW_APPLET:
|
||||
@@ -185,14 +175,14 @@ void InkHUD::MenuApplet::execute(MenuItem item)
|
||||
break;
|
||||
|
||||
case TOGGLE_NOTIFICATIONS:
|
||||
settings.optionalFeatures.notifications = !settings.optionalFeatures.notifications;
|
||||
settings->optionalFeatures.notifications = !settings->optionalFeatures.notifications;
|
||||
break;
|
||||
|
||||
case SET_RECENTS:
|
||||
// Set value of settings.recentlyActiveSeconds
|
||||
// Uses menu cursor to read RECENTS_OPTIONS_MINUTES array (defined at top of this file)
|
||||
assert(cursor < sizeof(RECENTS_OPTIONS_MINUTES) / sizeof(RECENTS_OPTIONS_MINUTES[0]));
|
||||
settings.recentlyActiveSeconds = RECENTS_OPTIONS_MINUTES[cursor] * 60; // Menu items are in minutes
|
||||
settings->recentlyActiveSeconds = RECENTS_OPTIONS_MINUTES[cursor] * 60; // Menu items are in minutes
|
||||
break;
|
||||
|
||||
case SHUTDOWN:
|
||||
@@ -202,7 +192,7 @@ void InkHUD::MenuApplet::execute(MenuItem item)
|
||||
break;
|
||||
|
||||
case TOGGLE_BATTERY_ICON:
|
||||
windowManager->toggleBatteryIcon();
|
||||
inkhud->toggleBatteryIcon();
|
||||
break;
|
||||
|
||||
case TOGGLE_BACKLIGHT:
|
||||
@@ -233,13 +223,13 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
switch (page) {
|
||||
case ROOT:
|
||||
// Optional: next applet
|
||||
if (settings.optionalMenuItems.nextTile && settings.userTiles.count > 1)
|
||||
if (settings->optionalMenuItems.nextTile && settings->userTiles.count > 1)
|
||||
items.push_back(MenuItem("Next Tile", MenuAction::NEXT_TILE, MenuPage::ROOT)); // Only if multiple applets shown
|
||||
|
||||
// items.push_back(MenuItem("Send", MenuPage::SEND)); // TODO
|
||||
items.push_back(MenuItem("Options", MenuPage::OPTIONS));
|
||||
// items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO
|
||||
items.push_back(MenuItem("Save & Shutdown", MenuAction::SHUTDOWN));
|
||||
items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN));
|
||||
items.push_back(MenuItem("Exit", MenuPage::EXIT));
|
||||
break;
|
||||
|
||||
@@ -252,7 +242,7 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
|
||||
case OPTIONS:
|
||||
// Optional: backlight
|
||||
if (settings.optionalMenuItems.backlight) {
|
||||
if (settings->optionalMenuItems.backlight) {
|
||||
assert(backlight);
|
||||
items.push_back(MenuItem(backlight->isLatched() ? "Backlight Off" : "Keep Backlight On", // Label
|
||||
MenuAction::TOGGLE_BACKLIGHT, // Action
|
||||
@@ -263,13 +253,13 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
|
||||
items.push_back(MenuItem("Applets", MenuPage::APPLETS));
|
||||
items.push_back(MenuItem("Auto-show", MenuPage::AUTOSHOW));
|
||||
items.push_back(MenuItem("Recents Duration", MenuPage::RECENTS));
|
||||
if (settings.userTiles.maxCount > 1)
|
||||
if (settings->userTiles.maxCount > 1)
|
||||
items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS));
|
||||
items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS));
|
||||
items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS,
|
||||
&settings.optionalFeatures.notifications));
|
||||
items.push_back(
|
||||
MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS, &settings.optionalFeatures.batteryIcon));
|
||||
&settings->optionalFeatures.notifications));
|
||||
items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS,
|
||||
&settings->optionalFeatures.batteryIcon));
|
||||
|
||||
// TODO - GPS and Wifi switches
|
||||
/*
|
||||
@@ -329,9 +319,6 @@ void InkHUD::MenuApplet::onRender()
|
||||
if (items.size() == 0)
|
||||
LOG_ERROR("Empty Menu");
|
||||
|
||||
// Testing only
|
||||
setFont(fontSmall);
|
||||
|
||||
// Dimensions for the slots where we will draw menuItems
|
||||
const float padding = 0.05;
|
||||
const uint16_t itemH = fontSmall.lineHeight() * 2;
|
||||
@@ -397,7 +384,7 @@ void InkHUD::MenuApplet::onRender()
|
||||
|
||||
// Testing only: circle instead of check box
|
||||
if (item.checkState) {
|
||||
const uint16_t cbWH = fontSmall.lineHeight(); // Checbox: width / height
|
||||
const uint16_t cbWH = fontSmall.lineHeight(); // Checkbox: width / height
|
||||
const int16_t cbL = itemR - X(padding) - cbWH; // Checkbox: left
|
||||
const int16_t cbT = center - (cbWH / 2); // Checkbox : top
|
||||
// Checkbox ticked
|
||||
@@ -463,9 +450,9 @@ void InkHUD::MenuApplet::populateAppletPage()
|
||||
{
|
||||
assert(items.size() == 0);
|
||||
|
||||
for (uint8_t i = 0; i < windowManager->getAppletCount(); i++) {
|
||||
const char *name = windowManager->getAppletName(i);
|
||||
bool *isActive = &(settings.userApplets.active[i]);
|
||||
for (uint8_t i = 0; i < inkhud->userApplets.size(); i++) {
|
||||
const char *name = inkhud->userApplets.at(i)->name;
|
||||
bool *isActive = &(settings->userApplets.active[i]);
|
||||
items.push_back(MenuItem(name, MenuAction::TOGGLE_APPLET, MenuPage::APPLETS, isActive));
|
||||
}
|
||||
}
|
||||
@@ -477,11 +464,11 @@ void InkHUD::MenuApplet::populateAutoshowPage()
|
||||
{
|
||||
assert(items.size() == 0);
|
||||
|
||||
for (uint8_t i = 0; i < windowManager->getAppletCount(); i++) {
|
||||
for (uint8_t i = 0; i < inkhud->userApplets.size(); i++) {
|
||||
// Only add a menu item if applet is active
|
||||
if (settings.userApplets.active[i]) {
|
||||
const char *name = windowManager->getAppletName(i);
|
||||
bool *isActive = &(settings.userApplets.autoshow[i]);
|
||||
if (settings->userApplets.active[i]) {
|
||||
const char *name = inkhud->userApplets.at(i)->name;
|
||||
bool *isActive = &(settings->userApplets.autoshow[i]);
|
||||
items.push_back(MenuItem(name, MenuAction::TOGGLE_AUTOSHOW_APPLET, MenuPage::AUTOSHOW, isActive));
|
||||
}
|
||||
}
|
||||
@@ -599,10 +586,10 @@ void InkHUD::MenuApplet::drawSystemInfoPanel(int16_t left, int16_t top, uint16_t
|
||||
|
||||
// Get the height of the the panel drawn at the top of the menu
|
||||
// This is inefficient, as we do actually have to render the panel to determine the height
|
||||
// It solves a catch-22 situtation, where slotCount needs to know panel height, and panel height needs to know slotCount
|
||||
// It solves a catch-22 situation, where slotCount needs to know panel height, and panel height needs to know slotCount
|
||||
uint16_t InkHUD::MenuApplet::getSystemInfoPanelHeight()
|
||||
{
|
||||
// Render *waay* off screen
|
||||
// Render *far* off screen
|
||||
uint16_t height = 0;
|
||||
drawSystemInfoPanel(INT16_MIN, INT16_MIN, 1, &height);
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/Drivers/Backlight/LatchingBacklight.h"
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/WindowManager.h"
|
||||
#include "graphics/niche/InkHUD/InkHUD.h"
|
||||
#include "graphics/niche/InkHUD/Persistence.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
#include "./MenuItem.h"
|
||||
#include "./MenuPage.h"
|
||||
@@ -16,7 +17,7 @@ namespace NicheGraphics::InkHUD
|
||||
|
||||
class Applet;
|
||||
|
||||
class MenuApplet : public Applet, public concurrency::OSThread
|
||||
class MenuApplet : public SystemApplet, public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
MenuApplet();
|
||||
@@ -30,6 +31,8 @@ class MenuApplet : public Applet, public concurrency::OSThread
|
||||
void show(Tile *t); // Open the menu, onto a user tile
|
||||
|
||||
protected:
|
||||
Drivers::LatchingBacklight *backlight = nullptr; // Convenient access to the backlight singleton
|
||||
|
||||
int32_t runOnce() override;
|
||||
|
||||
void execute(MenuItem item); // Perform the MenuAction associated with a MenuItem, if any
|
||||
@@ -41,7 +44,7 @@ class MenuApplet : public Applet, public concurrency::OSThread
|
||||
void drawSystemInfoPanel(int16_t left, int16_t top, uint16_t width,
|
||||
uint16_t *height = nullptr); // Info panel at top of root menu
|
||||
|
||||
MenuPage currentPage;
|
||||
MenuPage currentPage = MenuPage::ROOT;
|
||||
uint8_t cursor = 0; // Which menu item is currently highlighted
|
||||
bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection)
|
||||
|
||||
@@ -50,9 +53,6 @@ class MenuApplet : public Applet, public concurrency::OSThread
|
||||
std::vector<MenuItem> items; // MenuItems for the current page. Filled by ShowPage
|
||||
|
||||
Applet *borrowedTileOwner = nullptr; // Which applet we have temporarily replaced while displaying menu
|
||||
|
||||
WindowManager *windowManager = nullptr; // Convenient access to the InkHUD::WindowManager singleton
|
||||
Drivers::LatchingBacklight *backlight = nullptr; // Convenient access to the backlight singleton
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -3,22 +3,20 @@
|
||||
#include "./NotificationApplet.h"
|
||||
|
||||
#include "./Notification.h"
|
||||
#include "graphics/niche/InkHUD/Persistence.h"
|
||||
|
||||
#include "meshUtils.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
|
||||
#include "RTC.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
void InkHUD::NotificationApplet::onActivate()
|
||||
InkHUD::NotificationApplet::NotificationApplet()
|
||||
{
|
||||
textMessageObserver.observe(textMessageModule);
|
||||
}
|
||||
|
||||
// Note: This applet probably won't ever be deactivated
|
||||
void InkHUD::NotificationApplet::onDeactivate()
|
||||
{
|
||||
textMessageObserver.unobserve(textMessageModule);
|
||||
}
|
||||
|
||||
// Collect meta-info about the text message, and ask for approval for the notification
|
||||
// No need to save the message itself; we can use the cached InkHUD::latestMessage data during render()
|
||||
int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket *p)
|
||||
@@ -28,7 +26,7 @@ int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket
|
||||
|
||||
// Abort if feature disabled
|
||||
// This is a bit clumsy, but avoids complicated handling when the feature is enabled / disabled
|
||||
if (!settings.optionalFeatures.notifications)
|
||||
if (!settings->optionalFeatures.notifications)
|
||||
return 0;
|
||||
|
||||
// Abort if this is an outgoing message
|
||||
@@ -36,7 +34,7 @@ int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket
|
||||
return 0;
|
||||
|
||||
// Abort if message was only an "emoji reaction"
|
||||
// Possibly some implemetation of this in future?
|
||||
// Possibly some implementation of this in future?
|
||||
if (p->decoded.emoji)
|
||||
return 0;
|
||||
|
||||
@@ -55,13 +53,16 @@ int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket
|
||||
n.sender = p->from;
|
||||
}
|
||||
|
||||
// Close an old notification, if shown
|
||||
dismiss();
|
||||
|
||||
// Check if we should display the notification
|
||||
// A foreground applet might already be displaying this info
|
||||
hasNotification = true;
|
||||
currentNotification = n;
|
||||
if (isApproved()) {
|
||||
bringToForeground();
|
||||
WindowManager::getInstance()->forceUpdate();
|
||||
inkhud->forceUpdate();
|
||||
} else
|
||||
hasNotification = false; // Clear the pending notification: it was rejected
|
||||
|
||||
@@ -76,8 +77,6 @@ void InkHUD::NotificationApplet::onRender()
|
||||
// We do need to do this with the battery though, as it is an "overlay"
|
||||
fillRect(0, 0, width(), height(), WHITE);
|
||||
|
||||
setFont(fontSmall);
|
||||
|
||||
// Padding (horizontal)
|
||||
const uint16_t padW = 4;
|
||||
|
||||
@@ -137,6 +136,28 @@ void InkHUD::NotificationApplet::onRender()
|
||||
printThick(textM, height() / 2, text, 2, 1);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onForeground()
|
||||
{
|
||||
handleInput = true; // Intercept the button input for our applet, so we can dismiss the notification
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onBackground()
|
||||
{
|
||||
handleInput = false;
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onButtonShortPress()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::NotificationApplet::onButtonLongPress()
|
||||
{
|
||||
dismiss();
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
// Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification
|
||||
// Called internally when we first get a "notifiable event", and then again before render,
|
||||
// in case autoshow swapped which applet was displayed
|
||||
@@ -148,7 +169,13 @@ bool InkHUD::NotificationApplet::isApproved()
|
||||
return false;
|
||||
}
|
||||
|
||||
return WindowManager::getInstance()->approveNotification(currentNotification);
|
||||
// Ask all visible user applets for approval
|
||||
for (Applet *ua : inkhud->userApplets) {
|
||||
if (ua->isForeground() && !ua->approveNotification(currentNotification))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mark that the notification should no-longer be rendered
|
||||
@@ -180,7 +207,8 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila
|
||||
bool isBroadcast = currentNotification.type == Notification::Type::NOTIFICATION_MESSAGE_BROADCAST;
|
||||
|
||||
// Pick source of message
|
||||
MessageStore::Message *message = isBroadcast ? &latestMessage.broadcast : &latestMessage.dm;
|
||||
MessageStore::Message *message =
|
||||
isBroadcast ? &inkhud->persistence->latestMessage.broadcast : &inkhud->persistence->latestMessage.dm;
|
||||
|
||||
// Find info about the sender
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(message->sender);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
|
||||
Pop-up notification bar, on screen top edge
|
||||
Displays information we feel is important, but which is not shown on currently focussed applet(s)
|
||||
Displays information we feel is important, but which is not shown on currently focused applet(s)
|
||||
E.g.: messages, while viewing map, etc
|
||||
|
||||
Feature should be optional; enable disable via on-screen menu
|
||||
@@ -16,17 +16,21 @@ Feature should be optional; enable disable via on-screen menu
|
||||
|
||||
#include "concurrency/OSThread.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class NotificationApplet : public Applet
|
||||
class NotificationApplet : public SystemApplet
|
||||
{
|
||||
public:
|
||||
NotificationApplet();
|
||||
|
||||
void onRender() override;
|
||||
void onActivate() override;
|
||||
void onDeactivate() override;
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
void onButtonShortPress() override;
|
||||
void onButtonLongPress() override;
|
||||
|
||||
int onReceiveTextMessage(const meshtastic_MeshPacket *p);
|
||||
|
||||
@@ -40,8 +44,8 @@ class NotificationApplet : public Applet
|
||||
|
||||
std::string getNotificationText(uint16_t widthAvailable); // Get text for notification, to suit screen width
|
||||
|
||||
bool hasNotification = false; // Only used for assert. Todo: remove?
|
||||
Notification currentNotification; // Set when something notification-worthy happens. Used by render()
|
||||
bool hasNotification = false; // Only used for assert. Todo: remove?
|
||||
Notification currentNotification = Notification(); // Set when something notification-worthy happens. Used by render()
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -6,8 +6,7 @@ using namespace NicheGraphics;
|
||||
|
||||
InkHUD::PairingApplet::PairingApplet()
|
||||
{
|
||||
// Grab the window manager singleton, for convenience
|
||||
windowManager = WindowManager::getInstance();
|
||||
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
|
||||
}
|
||||
|
||||
void InkHUD::PairingApplet::onRender()
|
||||
@@ -31,34 +30,22 @@ void InkHUD::PairingApplet::onRender()
|
||||
printAt(X(0.5), Y(0.75), name, CENTER, MIDDLE);
|
||||
}
|
||||
|
||||
void InkHUD::PairingApplet::onActivate()
|
||||
{
|
||||
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
|
||||
}
|
||||
|
||||
void InkHUD::PairingApplet::onDeactivate()
|
||||
{
|
||||
bluetoothStatusObserver.unobserve(&bluetoothStatus->onNewStatus);
|
||||
}
|
||||
|
||||
void InkHUD::PairingApplet::onForeground()
|
||||
{
|
||||
// If another applet has locked the display, ask it to exit
|
||||
Applet *other = windowManager->whoLocked();
|
||||
if (other != nullptr)
|
||||
other->sendToBackground();
|
||||
|
||||
windowManager->claimFullscreen(this); // Take ownership of the fullscreen tile
|
||||
windowManager->lock(this); // Prevent user applets from requesting update
|
||||
// Prevent most other applets from requesting update, and skip their rendering entirely
|
||||
// Another system applet with a higher precedence can potentially ignore this
|
||||
SystemApplet::lockRendering = true;
|
||||
SystemApplet::lockRequests = true;
|
||||
}
|
||||
void InkHUD::PairingApplet::onBackground()
|
||||
{
|
||||
windowManager->releaseFullscreen(); // Relinquish ownership of the fullscreen tile
|
||||
windowManager->unlock(this); // Allow normal user applet update requests to resume
|
||||
// Allow normal update behavior to resume
|
||||
SystemApplet::lockRendering = false;
|
||||
SystemApplet::lockRequests = false;
|
||||
|
||||
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
|
||||
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
|
||||
windowManager->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
int InkHUD::PairingApplet::onBluetoothStatusUpdate(const meshtastic::Status *status)
|
||||
@@ -75,12 +62,6 @@ int InkHUD::PairingApplet::onBluetoothStatusUpdate(const meshtastic::Status *sta
|
||||
// Store the passkey for rendering
|
||||
passkey = bluetoothStatus->getPasskey();
|
||||
|
||||
// Make sure no other system applets have a lock on the display
|
||||
// Boot screen, menu, etc
|
||||
Applet *lockOwner = windowManager->whoLocked();
|
||||
if (lockOwner)
|
||||
lockOwner->sendToBackground();
|
||||
|
||||
// Show pairing screen
|
||||
bringToForeground();
|
||||
}
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class PairingApplet : public Applet
|
||||
class PairingApplet : public SystemApplet
|
||||
{
|
||||
public:
|
||||
PairingApplet();
|
||||
|
||||
void onRender() override;
|
||||
void onActivate() override;
|
||||
void onDeactivate() override;
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
|
||||
@@ -34,8 +34,6 @@ class PairingApplet : public Applet
|
||||
CallbackObserver<PairingApplet, const meshtastic::Status *>(this, &PairingApplet::onBluetoothStatusUpdate);
|
||||
|
||||
std::string passkey = ""; // Passkey. Six digits, possibly with leading zeros
|
||||
|
||||
WindowManager *windowManager = nullptr; // For convenience. Set in constructor.
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -4,14 +4,6 @@
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
InkHUD::PlaceholderApplet::PlaceholderApplet()
|
||||
{
|
||||
// Because this applet sometimes gets processed as if it were a bonafide user applet,
|
||||
// it's probably better that we do give it a human readable name, just in case it comes up later.
|
||||
// For genuine user applets, this is set by WindowManager::addApplet
|
||||
Applet::name = "Placeholder";
|
||||
}
|
||||
|
||||
void InkHUD::PlaceholderApplet::onRender()
|
||||
{
|
||||
// This placeholder applet fills its area with sparse diagonal lines
|
||||
|
||||
@@ -9,20 +9,19 @@ Fills the area with diagonal lines
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class PlaceholderApplet : public Applet
|
||||
class PlaceholderApplet : public SystemApplet
|
||||
{
|
||||
public:
|
||||
PlaceholderApplet();
|
||||
void onRender() override;
|
||||
|
||||
// Note: onForeground, onBackground, and wantsToRender are not meaningful for this applet.
|
||||
// The window manager decides when and where it should be rendered
|
||||
// It may be drawn to several different tiles during on WindowManager::render call
|
||||
// It may be drawn to several different tiles during an Renderer::render call
|
||||
};
|
||||
|
||||
} // namespace NicheGraphics::InkHUD
|
||||
|
||||
@@ -2,12 +2,44 @@
|
||||
|
||||
#include "./TipsApplet.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Persistence.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
using namespace NicheGraphics;
|
||||
|
||||
InkHUD::TipsApplet::TipsApplet()
|
||||
{
|
||||
// Grab the window manager singleton, for convenience
|
||||
windowManager = WindowManager::getInstance();
|
||||
// Decide which tips (if any) should be shown to user after the boot screen
|
||||
|
||||
// Welcome screen
|
||||
if (settings->tips.firstBoot)
|
||||
tipQueue.push_back(Tip::WELCOME);
|
||||
|
||||
// Antenna, region, timezone
|
||||
// Shown at boot if region not yet set
|
||||
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET)
|
||||
tipQueue.push_back(Tip::FINISH_SETUP);
|
||||
|
||||
// Shutdown info
|
||||
// Shown until user performs one valid shutdown
|
||||
if (!settings->tips.safeShutdownSeen)
|
||||
tipQueue.push_back(Tip::SAFE_SHUTDOWN);
|
||||
|
||||
// Using the UI
|
||||
if (settings->tips.firstBoot) {
|
||||
tipQueue.push_back(Tip::CUSTOMIZATION);
|
||||
tipQueue.push_back(Tip::BUTTONS);
|
||||
}
|
||||
|
||||
// Catch an incorrect attempt at rotating display
|
||||
if (config.display.flip_screen)
|
||||
tipQueue.push_back(Tip::ROTATION);
|
||||
|
||||
// Applet is foreground immediately at boot, but is obscured by LogoApplet, which is also foreground
|
||||
// LogoApplet can be considered to have a higher Z-index, because it is placed before TipsApplet in the systemApplets vector
|
||||
if (!tipQueue.empty())
|
||||
bringToForeground();
|
||||
}
|
||||
|
||||
void InkHUD::TipsApplet::onRender()
|
||||
@@ -53,7 +85,7 @@ void InkHUD::TipsApplet::onRender()
|
||||
|
||||
setFont(fontSmall);
|
||||
std::string shutdown;
|
||||
shutdown += "Before removing power, please shutdown from InkHUD menu, or a client app. \n";
|
||||
shutdown += "Before removing power, please shut down from InkHUD menu, or a client app. \n";
|
||||
shutdown += "\n";
|
||||
shutdown += "This ensures data is saved.";
|
||||
printWrapped(0, fontLarge.lineHeight() * 1.5, width(), shutdown);
|
||||
@@ -153,51 +185,31 @@ void InkHUD::TipsApplet::renderWelcome()
|
||||
printAt(X(0.5), Y(1), "Press button to continue", CENTER, BOTTOM);
|
||||
}
|
||||
|
||||
// Grab fullscreen tile, and lock the window manager, when applet is shown
|
||||
void InkHUD::TipsApplet::onForeground()
|
||||
{
|
||||
windowManager->lock(this);
|
||||
windowManager->claimFullscreen(this);
|
||||
// Prevent most other applets from requesting update, and skip their rendering entirely
|
||||
// Another system applet with a higher precedence can potentially ignore this
|
||||
SystemApplet::lockRendering = true;
|
||||
SystemApplet::lockRequests = true;
|
||||
|
||||
SystemApplet::handleInput = true; // Our applet should handle button input (unless another system applet grabs it first)
|
||||
}
|
||||
|
||||
void InkHUD::TipsApplet::onBackground()
|
||||
{
|
||||
windowManager->releaseFullscreen();
|
||||
windowManager->unlock(this);
|
||||
// Allow normal update behavior to resume
|
||||
SystemApplet::lockRendering = false;
|
||||
SystemApplet::lockRequests = false;
|
||||
SystemApplet::handleInput = false;
|
||||
|
||||
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
|
||||
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
void InkHUD::TipsApplet::onActivate()
|
||||
{
|
||||
// Decide which tips (if any) should be shown to user after the boot screen
|
||||
void InkHUD::TipsApplet::onActivate() {}
|
||||
|
||||
// Welcome screen
|
||||
if (settings.tips.firstBoot)
|
||||
tipQueue.push_back(Tip::WELCOME);
|
||||
|
||||
// Antenna, region, timezone
|
||||
// Shown at boot if region not yet set
|
||||
if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET)
|
||||
tipQueue.push_back(Tip::FINISH_SETUP);
|
||||
|
||||
// Shutdown info
|
||||
// Shown until user performs one valid shutdown
|
||||
if (!settings.tips.safeShutdownSeen)
|
||||
tipQueue.push_back(Tip::SAFE_SHUTDOWN);
|
||||
|
||||
// Using the UI
|
||||
if (settings.tips.firstBoot) {
|
||||
tipQueue.push_back(Tip::CUSTOMIZATION);
|
||||
tipQueue.push_back(Tip::BUTTONS);
|
||||
}
|
||||
|
||||
// Catch an incorrect attempt at rotating display
|
||||
if (config.display.flip_screen)
|
||||
tipQueue.push_back(Tip::ROTATION);
|
||||
|
||||
// Applet will be brought to foreground when boot screen closes, via TipsApplet::onLockAvailable
|
||||
}
|
||||
|
||||
// While our applet has the window manager locked, we will receive the button input
|
||||
// While our SystemApplet::handleInput flag is true
|
||||
void InkHUD::TipsApplet::onButtonShortPress()
|
||||
{
|
||||
tipQueue.pop_front();
|
||||
@@ -206,15 +218,15 @@ void InkHUD::TipsApplet::onButtonShortPress()
|
||||
if (tipQueue.empty()) {
|
||||
// Record that user has now seen the "tutorial" set of tips
|
||||
// Don't show them on subsequent boots
|
||||
if (settings.tips.firstBoot) {
|
||||
settings.tips.firstBoot = false;
|
||||
saveDataToFlash();
|
||||
if (settings->tips.firstBoot) {
|
||||
settings->tips.firstBoot = false;
|
||||
inkhud->persistence->saveSettings();
|
||||
}
|
||||
|
||||
// Close applet, and full refresh to clean the screen
|
||||
// Need to force update, because our request would be ignored otherwise, as we are now background
|
||||
sendToBackground();
|
||||
windowManager->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
|
||||
}
|
||||
|
||||
// More tips left
|
||||
@@ -222,13 +234,4 @@ void InkHUD::TipsApplet::onButtonShortPress()
|
||||
requestUpdate();
|
||||
}
|
||||
|
||||
// If the wm lock has just become availale (rendering, input), and we've still got tips, grab it!
|
||||
// This situation would arise if bluetooth pairing occurs while TipsApplet was already shown (after pairing)
|
||||
// Note: this event is only raised when *other* applets unlock the window manager
|
||||
void InkHUD::TipsApplet::onLockAvailable()
|
||||
{
|
||||
if (!tipQueue.empty())
|
||||
bringToForeground();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#include "graphics/niche/InkHUD/Applet.h"
|
||||
#include "graphics/niche/InkHUD/SystemApplet.h"
|
||||
|
||||
namespace NicheGraphics::InkHUD
|
||||
{
|
||||
|
||||
class TipsApplet : public Applet
|
||||
class TipsApplet : public SystemApplet
|
||||
{
|
||||
protected:
|
||||
enum class Tip {
|
||||
@@ -37,7 +37,6 @@ class TipsApplet : public Applet
|
||||
void onForeground() override;
|
||||
void onBackground() override;
|
||||
void onButtonShortPress() override;
|
||||
void onLockAvailable() override; // Reopen if interrupted by bluetooth pairing
|
||||
|
||||
protected:
|
||||
void renderWelcome(); // Very first screen of tutorial
|
||||
|
||||
Reference in New Issue
Block a user