feat: Add long press scrolling for Joystick and upDown Encoder on baseUI frames and menus.

This commit is contained in:
whywilson 2025-09-24 15:27:54 +08:00
parent 5bfd3fe92c
commit 2c76078ac3
4 changed files with 74 additions and 15 deletions

View File

@ -1627,6 +1627,12 @@ int Screen::handleInputEvent(const InputEvent *event)
showPrevFrame(); showPrevFrame();
} else if (event->inputEvent == INPUT_BROKER_RIGHT || event->inputEvent == INPUT_BROKER_USER_PRESS) { } else if (event->inputEvent == INPUT_BROKER_RIGHT || event->inputEvent == INPUT_BROKER_USER_PRESS) {
showNextFrame(); showNextFrame();
} else if (event->inputEvent == INPUT_BROKER_UP_LONG) {
// Long press up button for fast frame switching
showPrevFrame();
} else if (event->inputEvent == INPUT_BROKER_DOWN_LONG) {
// Long press down button for fast frame switching
showNextFrame();
} else if (event->inputEvent == INPUT_BROKER_SELECT) { } else if (event->inputEvent == INPUT_BROKER_SELECT) {
if (this->ui->getUiState()->currentFrame == framesetInfo.positions.home) { if (this->ui->getUiState()->currentFrame == framesetInfo.positions.home) {
menuHandler::homeBaseMenu(); menuHandler::homeBaseMenu();

View File

@ -174,13 +174,15 @@ void NotificationRenderer::drawNumberPicker(OLEDDisplay *display, OLEDDisplayUiS
// modulo to extract // modulo to extract
uint8_t this_digit = (currentNumber % (pow_of_10(numDigits - curSelected))) / (pow_of_10(numDigits - curSelected - 1)); uint8_t this_digit = (currentNumber % (pow_of_10(numDigits - curSelected))) / (pow_of_10(numDigits - curSelected - 1));
// Handle input // Handle input
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) { if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_ALT_PRESS ||
inEvent.inputEvent == INPUT_BROKER_UP_LONG) {
if (this_digit == 9) { if (this_digit == 9) {
currentNumber -= 9 * (pow_of_10(numDigits - curSelected - 1)); currentNumber -= 9 * (pow_of_10(numDigits - curSelected - 1));
} else { } else {
currentNumber += (pow_of_10(numDigits - curSelected - 1)); currentNumber += (pow_of_10(numDigits - curSelected - 1));
} }
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_USER_PRESS) { } else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_USER_PRESS ||
inEvent.inputEvent == INPUT_BROKER_DOWN_LONG) {
if (this_digit == 0) { if (this_digit == 0) {
currentNumber += 9 * (pow_of_10(numDigits - curSelected - 1)); currentNumber += 9 * (pow_of_10(numDigits - curSelected - 1));
} else { } else {
@ -262,10 +264,10 @@ void NotificationRenderer::drawNodePicker(OLEDDisplay *display, OLEDDisplayUiSta
// Handle input // Handle input
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT || if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT ||
inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) { inEvent.inputEvent == INPUT_BROKER_ALT_PRESS || inEvent.inputEvent == INPUT_BROKER_UP_LONG) {
curSelected--; curSelected--;
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT || } else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT ||
inEvent.inputEvent == INPUT_BROKER_USER_PRESS) { inEvent.inputEvent == INPUT_BROKER_USER_PRESS || inEvent.inputEvent == INPUT_BROKER_DOWN_LONG) {
curSelected++; curSelected++;
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) { } else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
alertBannerCallback(selectedNodenum); alertBannerCallback(selectedNodenum);
@ -379,10 +381,10 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
// Handle input // Handle input
if (alertBannerOptions > 0) { if (alertBannerOptions > 0) {
if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT || if (inEvent.inputEvent == INPUT_BROKER_UP || inEvent.inputEvent == INPUT_BROKER_LEFT ||
inEvent.inputEvent == INPUT_BROKER_ALT_PRESS) { inEvent.inputEvent == INPUT_BROKER_ALT_PRESS || inEvent.inputEvent == INPUT_BROKER_UP_LONG) {
curSelected--; curSelected--;
} else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT || } else if (inEvent.inputEvent == INPUT_BROKER_DOWN || inEvent.inputEvent == INPUT_BROKER_RIGHT ||
inEvent.inputEvent == INPUT_BROKER_USER_PRESS) { inEvent.inputEvent == INPUT_BROKER_USER_PRESS || inEvent.inputEvent == INPUT_BROKER_DOWN_LONG) {
curSelected++; curSelected++;
} else if (inEvent.inputEvent == INPUT_BROKER_SELECT) { } else if (inEvent.inputEvent == INPUT_BROKER_SELECT) {
if (optionsEnumPtr != nullptr) { if (optionsEnumPtr != nullptr) {

View File

@ -88,6 +88,48 @@ int32_t TrackballInterruptBase::runOnce()
} }
} }
if (directionDetected && directionStartTime > 0) {
uint32_t directionDuration = millis() - directionStartTime;
uint8_t directionPressedNow = 0;
directionInterval++;
if (!digitalRead(_pinUp)) {
directionPressedNow = TB_ACTION_UP;
} else if (!digitalRead(_pinDown)) {
directionPressedNow = TB_ACTION_DOWN;
} else if (!digitalRead(_pinLeft)) {
directionPressedNow = TB_ACTION_LEFT;
} else if (!digitalRead(_pinRight)) {
directionPressedNow = TB_ACTION_RIGHT;
}
if (directionPressedNow < 3) {
// Reset state
directionDetected = false;
directionStartTime = 0;
directionInterval = 0;
this->action = TB_ACTION_NONE;
} else if (directionDuration >= LONG_PRESS_DURATION && directionPressedNow >= 3 && directionInterval >= 3) {
// repeat event when long press these direction.
switch (directionPressedNow) {
case TB_ACTION_UP:
e.inputEvent = this->_eventUp;
break;
case TB_ACTION_DOWN:
e.inputEvent = this->_eventDown;
break;
case TB_ACTION_LEFT:
e.inputEvent = this->_eventLeft;
break;
case TB_ACTION_RIGHT:
e.inputEvent = this->_eventRight;
break;
}
directionInterval = 0;
}
}
#if defined(T_DECK) // T-deck gets a super-simple debounce on trackball #if defined(T_DECK) // T-deck gets a super-simple debounce on trackball
if (this->action == TB_ACTION_PRESSED && !pressDetected) { if (this->action == TB_ACTION_PRESSED && !pressDetected) {
// Start long press detection // Start long press detection
@ -113,17 +155,22 @@ int32_t TrackballInterruptBase::runOnce()
pressDetected = true; pressDetected = true;
pressStartTime = millis(); pressStartTime = millis();
// Don't send event yet, wait to see if it's a long press // Don't send event yet, wait to see if it's a long press
} else if (this->action == TB_ACTION_UP && !digitalRead(_pinUp)) { } else if (this->action == TB_ACTION_UP && !digitalRead(_pinUp) && !directionDetected) {
// LOG_DEBUG("Trackball event UP"); directionDetected = true;
directionStartTime = millis();
e.inputEvent = this->_eventUp; e.inputEvent = this->_eventUp;
} else if (this->action == TB_ACTION_DOWN && !digitalRead(_pinDown)) { // send event first,will automatically trigger every 50ms * 3 after 500ms
// LOG_DEBUG("Trackball event DOWN"); } else if (this->action == TB_ACTION_DOWN && !digitalRead(_pinDown) && !directionDetected) {
directionDetected = true;
directionStartTime = millis();
e.inputEvent = this->_eventDown; e.inputEvent = this->_eventDown;
} else if (this->action == TB_ACTION_LEFT && !digitalRead(_pinLeft)) { } else if (this->action == TB_ACTION_LEFT && !digitalRead(_pinLeft) && !directionDetected) {
// LOG_DEBUG("Trackball event LEFT"); directionDetected = true;
directionStartTime = millis();
e.inputEvent = this->_eventLeft; e.inputEvent = this->_eventLeft;
} else if (this->action == TB_ACTION_RIGHT && !digitalRead(_pinRight)) { } else if (this->action == TB_ACTION_RIGHT && !digitalRead(_pinRight) && !directionDetected) {
// LOG_DEBUG("Trackball event RIGHT"); directionDetected = true;
directionStartTime = millis();
e.inputEvent = this->_eventRight; e.inputEvent = this->_eventRight;
} }
#endif #endif

View File

@ -49,10 +49,14 @@ class TrackballInterruptBase : public Observable<const InputEvent *>, public con
// Long press detection for press button // Long press detection for press button
uint32_t pressStartTime = 0; uint32_t pressStartTime = 0;
uint32_t directionStartTime = 0;
uint8_t directionInterval = 0;
bool pressDetected = false; bool pressDetected = false;
bool directionDetected = false;
uint32_t lastLongPressEventTime = 0; uint32_t lastLongPressEventTime = 0;
uint32_t lastDirectionPressEventTime = 0;
static const uint32_t LONG_PRESS_DURATION = 500; // ms static const uint32_t LONG_PRESS_DURATION = 500; // ms
static const uint32_t LONG_PRESS_REPEAT_INTERVAL = 500; // ms - interval between repeated long press events static const uint32_t LONG_PRESS_REPEAT_INTERVAL = 300; // ms - interval between repeated long press events
private: private:
input_broker_event _eventDown = INPUT_BROKER_NONE; input_broker_event _eventDown = INPUT_BROKER_NONE;