Skip to content

Commit

Permalink
Use different touch contexts for App & UX
Browse files Browse the repository at this point in the history
  • Loading branch information
nroggeman-ledger committed Oct 2, 2024
1 parent 1f177df commit 621b9be
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 54 deletions.
1 change: 1 addition & 0 deletions lib_nbgl/include/nbgl_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@ void nbgl_objInit(void);
void nbgl_objDraw(nbgl_obj_t *obj);
void nbgl_objAllowDrawing(bool enable);
uint8_t *nbgl_objGetRAMBuffer(void);
bool nbgl_objIsUx(nbgl_obj_t *obj);

void nbgl_objPoolRelease(uint8_t layer);
nbgl_obj_t *nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer);
Expand Down
11 changes: 6 additions & 5 deletions lib_nbgl/include/nbgl_touch.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@ extern "C" {
// duration of a short touch on touch panel (in ms)
#define SHORT_TOUCH_DURATION 0
// duration of a long touch on touch panel (in ms)
#define LONG_TOUCH_DURATION 1500
#define LONG_TOUCH_DURATION 3000
/**********************
* TYPEDEFS
**********************/

/**********************
* GLOBAL PROTOTYPES
**********************/
void nbgl_touchHandler(nbgl_touchStatePosition_t *touchEvent, uint32_t currentTimeMs);
bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj,
nbgl_touchStatePosition_t **firstPos,
nbgl_touchStatePosition_t **lastPos);
void nbgl_touchInit(bool fromUx);
void nbgl_touchHandler(bool fromUx, nbgl_touchStatePosition_t *touchEvent, uint32_t currentTimeMs);
bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj,
nbgl_touchStatePosition_t **firstPos,
nbgl_touchStatePosition_t **lastPos);
uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj);
nbgl_obj_t *nbgl_touchGetObjectFromId(nbgl_obj_t *obj, uint8_t id);

Expand Down
5 changes: 3 additions & 2 deletions lib_nbgl/src/nbgl_fonts.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ static const LANGUAGE_PACK *language_pack;
#include "nbgl_font_open_sans_light_16.inc"
#endif // SCREEN_SIZE_WALLET

const nbgl_font_t *const C_nbgl_fonts[] = {
__attribute__((section("._nbgl_fonts_"))) const nbgl_font_t *const C_nbgl_fonts[] = {

#include "nbgl_font_rom_struct.inc"

};
const unsigned int C_nbgl_fonts_count = sizeof(C_nbgl_fonts) / sizeof(C_nbgl_fonts[0]);
__attribute__((section("._nbgl_fonts_"))) const unsigned int C_nbgl_fonts_count
= sizeof(C_nbgl_fonts) / sizeof(C_nbgl_fonts[0]);

#if (defined(HAVE_BOLOS) && !defined(BOLOS_OS_UPGRADER_APP))
#if !defined(HAVE_LANGUAGE_PACK)
Expand Down
29 changes: 28 additions & 1 deletion lib_nbgl/src/nbgl_obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "nbgl_front.h"
#include "nbgl_debug.h"
#include "nbgl_screen.h"
#include "nbgl_touch.h"
#include "os_print.h"
#include "os_helpers.h"
#include "os_pic.h"
Expand Down Expand Up @@ -1629,12 +1630,17 @@ void nbgl_refreshReset(void)

/**
* @brief This functions inits all internal of nbgl objects layer
* @note it is supposed to be called only from App
*
*/
void nbgl_objInit(void)
{
// init area to the smallest size
nbgl_refreshReset();
objDrawingDisabled = false;
#ifdef HAVE_SE_TOUCH
nbgl_touchInit(false);
#endif
}

/**
Expand All @@ -1650,9 +1656,30 @@ void nbgl_objAllowDrawing(bool enable)
/**
* @brief This function is used to get the all purpose RAM buffer
*
* @param enable if true, enables drawing/refresh, otherwise disables
* @return a pointer to the all purpose RAM buffer
*/
uint8_t *nbgl_objGetRAMBuffer(void)
{
return ramBuffer;
}

/**
* @brief This function returns true if the object belongs to a UxScreen
*
* @return true if the object belongs to a UxScreen
*/
bool nbgl_objIsUx(nbgl_obj_t *obj)
{
nbgl_obj_t *parent = obj;
// search screen in parenthood
while (parent->parent != NULL) {
parent = parent->parent;
}
if (parent->type == SCREEN) {
return (((nbgl_screen_t *) parent)->isUxScreen);
}
else {
// should never happen
return true;
}
}
2 changes: 1 addition & 1 deletion lib_nbgl/src/nbgl_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ int nbgl_screenPush(nbgl_obj_t ***elements,
nbgl_touchStatePosition_t touchStatePosition = {.state = RELEASED, .x = 0, .y = 0};
// make a fake touch release for the current top-of-stack to avoid issue
// (for example in long-touch press)
nbgl_touchHandler(&touchStatePosition, 0);
nbgl_touchHandler(topOfStack->isUxScreen, &touchStatePosition, 0);
#endif // HAVE_SE_TOUCH
// new top of stack
topOfStack = &screenStack[screenIndex];
Expand Down
109 changes: 67 additions & 42 deletions lib_nbgl/src/nbgl_touch.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,23 @@
/*********************
* DEFINES
*********************/
enum {
UX_CTX = 0,
APP_CTX,
NB_CTXS
};

/**********************
* TYPEDEFS
**********************/
typedef struct nbgl_touchCtx_s {
nbgl_touchState_t lastState;
uint32_t lastPressedTime;
uint32_t lastCurrentTime;
nbgl_obj_t *lastPressedObj;
nbgl_touchStatePosition_t firstTouchedPosition;
nbgl_touchStatePosition_t lastTouchedPosition;
} nbgl_touchCtx_t;

/**********************
* STATIC PROTOTYPES
Expand All @@ -32,10 +45,7 @@
/**********************
* STATIC VARIABLES
**********************/
static uint32_t lastPressedTime = 0;
static uint32_t lastCurrentTime = 0;
static nbgl_obj_t *lastPressedObj = NULL;
static nbgl_touchStatePosition_t firstTouchedPosition, lastTouchedPosition;
static nbgl_touchCtx_t touchCtxs[NB_CTXS];

/**********************
* VARIABLES
Expand Down Expand Up @@ -255,29 +265,41 @@ static nbgl_touchType_t nbgl_detectSwipe(nbgl_touchStatePosition_t *last,
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* @brief Function to initialize the touch context
* @param fromUx if true, means to initialize the UX context, otherwise App one
*/
void nbgl_touchInit(bool fromUx)
{
nbgl_touchCtx_t *ctx = fromUx ? &touchCtxs[UX_CTX] : &touchCtxs[APP_CTX];
memset(ctx, 0, sizeof(nbgl_touchCtx_t));
}

/**
* @brief Function to be called periodically to check touchscreen state
* and coordinates
* @param fromUx if true, means this is called from the UX, not the App
* @param touchStatePosition state and position read from touch screen
* @param currentTime current time in ms
*/
void nbgl_touchHandler(nbgl_touchStatePosition_t *touchStatePosition, uint32_t currentTime)
void nbgl_touchHandler(bool fromUx,
nbgl_touchStatePosition_t *touchStatePosition,
uint32_t currentTime)
{
static nbgl_touchState_t lastState = RELEASED;
nbgl_obj_t *foundObj;
nbgl_obj_t *foundObj;
nbgl_touchCtx_t *ctx = fromUx ? &touchCtxs[UX_CTX] : &touchCtxs[APP_CTX];

// save last received currentTime
lastCurrentTime = currentTime;
ctx->lastCurrentTime = currentTime;

if (lastState == RELEASED) {
if (ctx->lastState == RELEASED) {
// filter out not realistic cases (successive RELEASE events)
if (RELEASED == touchStatePosition->state) {
lastState = touchStatePosition->state;
ctx->lastState = touchStatePosition->state;
return;
}
// memorize first touched position
memcpy(&firstTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t));
memcpy(&ctx->firstTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t));
}
// LOG_DEBUG(TOUCH_LOGGER,"state = %s, x = %d, y=%d\n",(touchStatePosition->state ==
// RELEASED)?"RELEASED":"PRESSED",touchStatePosition->x,touchStatePosition->y);
Expand All @@ -289,95 +311,98 @@ void nbgl_touchHandler(nbgl_touchStatePosition_t *touchStatePosition, uint32_t c
// foundObj->type);
if (foundObj == NULL) {
LOG_DEBUG(TOUCH_LOGGER, "nbgl_touchHandler: no found obj\n");
if ((touchStatePosition->state == PRESSED) && (lastState == PRESSED)
&& (lastPressedObj != NULL)) {
if ((touchStatePosition->state == PRESSED) && (ctx->lastState == PRESSED)
&& (ctx->lastPressedObj != NULL)) {
// finger has moved out of an object
// make sure lastPressedObj still belongs to current screen before warning it
if (nbgl_screenContainsObj(lastPressedObj)) {
applytouchStatePosition(lastPressedObj, OUT_OF_TOUCH);
if (nbgl_screenContainsObj(ctx->lastPressedObj)) {
applytouchStatePosition(ctx->lastPressedObj, OUT_OF_TOUCH);
}
}
// Released event has been handled, forget lastPressedObj
lastPressedObj = NULL;
ctx->lastPressedObj = NULL;
}

// memorize last touched position
memcpy(&lastTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t));
memcpy(&ctx->lastTouchedPosition, touchStatePosition, sizeof(nbgl_touchStatePosition_t));

if (touchStatePosition->state == RELEASED) {
nbgl_touchType_t swipe = nbgl_detectSwipe(touchStatePosition, &firstTouchedPosition);
nbgl_touchType_t swipe = nbgl_detectSwipe(touchStatePosition, &ctx->firstTouchedPosition);
bool consumed = false;

if (swipe != NB_TOUCH_TYPES) {
// Swipe detected
nbgl_obj_t *swipedObj = getSwipableObject(
nbgl_screenGetTop(), &firstTouchedPosition, &lastTouchedPosition, swipe);
nbgl_screenGetTop(), &ctx->firstTouchedPosition, &ctx->lastTouchedPosition, swipe);
// if a swipable object has been found
if (swipedObj) {
applytouchStatePosition(swipedObj, swipe);
consumed = true;
}
}
if (!consumed && (lastPressedObj != NULL)
&& ((foundObj == lastPressedObj) || (nbgl_screenContainsObj(lastPressedObj)))) {
if (!consumed && (ctx->lastPressedObj != NULL)
&& ((foundObj == ctx->lastPressedObj)
|| (nbgl_screenContainsObj(ctx->lastPressedObj)))) {
// very strange if lastPressedObj != foundObj, let's consider that it's a normal release
// on lastPressedObj make sure lastPressedObj still belongs to current screen before
// "releasing" it
applytouchStatePosition(lastPressedObj, TOUCH_RELEASED);
if (currentTime >= (lastPressedTime + LONG_TOUCH_DURATION)) {
applytouchStatePosition(lastPressedObj, LONG_TOUCHED);
applytouchStatePosition(ctx->lastPressedObj, TOUCH_RELEASED);
if (currentTime >= (ctx->lastPressedTime + LONG_TOUCH_DURATION)) {
applytouchStatePosition(ctx->lastPressedObj, LONG_TOUCHED);
}
else if (currentTime >= (lastPressedTime + SHORT_TOUCH_DURATION)) {
applytouchStatePosition(lastPressedObj, TOUCHED);
else if (currentTime >= (ctx->lastPressedTime + SHORT_TOUCH_DURATION)) {
applytouchStatePosition(ctx->lastPressedObj, TOUCHED);
}
}
// Released event has been handled, forget lastPressedObj
lastPressedObj = NULL;
ctx->lastPressedObj = NULL;
}
else { // PRESSED
if ((lastState == PRESSED) && (lastPressedObj != NULL)) {
if (foundObj != lastPressedObj) {
if ((ctx->lastState == PRESSED) && (ctx->lastPressedObj != NULL)) {
if (foundObj != ctx->lastPressedObj) {
// finger has moved out of an object
// make sure lastPressedObj still belongs to current screen before warning it
if (nbgl_screenContainsObj(lastPressedObj)) {
applytouchStatePosition(lastPressedObj, OUT_OF_TOUCH);
if (nbgl_screenContainsObj(ctx->lastPressedObj)) {
applytouchStatePosition(ctx->lastPressedObj, OUT_OF_TOUCH);
}
lastPressedObj = NULL;
ctx->lastPressedObj = NULL;
}
else {
// warn the concerned object that it is still touched
applytouchStatePosition(foundObj, TOUCHING);
}
}
else if (lastState == RELEASED) {
else if (ctx->lastState == RELEASED) {
// newly touched object
lastPressedObj = foundObj;
lastPressedTime = currentTime;
ctx->lastPressedObj = foundObj;
ctx->lastPressedTime = currentTime;
applytouchStatePosition(foundObj, TOUCH_PRESSED);
applytouchStatePosition(foundObj, TOUCHING);
}
}

lastState = touchStatePosition->state;
ctx->lastState = touchStatePosition->state;
}

bool nbgl_touchGetTouchedPosition(nbgl_obj_t *obj,
nbgl_touchStatePosition_t **firstPos,
nbgl_touchStatePosition_t **lastPos)
{
LOG_DEBUG(TOUCH_LOGGER, "nbgl_touchGetTouchedPosition: %p %p\n", obj, lastPressedObj);
if (obj == lastPressedObj) {
*firstPos = &firstTouchedPosition;
*lastPos = &lastTouchedPosition;
nbgl_touchCtx_t *ctx = nbgl_objIsUx(obj) ? &touchCtxs[UX_CTX] : &touchCtxs[APP_CTX];
LOG_DEBUG(TOUCH_LOGGER, "nbgl_touchGetTouchedPosition: %p %p\n", obj, ctx->lastPressedObj);
if (obj == ctx->lastPressedObj) {
*firstPos = &ctx->firstTouchedPosition;
*lastPos = &ctx->lastTouchedPosition;
return true;
}
return false;
}

uint32_t nbgl_touchGetTouchDuration(nbgl_obj_t *obj)
{
if (obj == lastPressedObj) {
return (lastCurrentTime - lastPressedTime);
nbgl_touchCtx_t *ctx = nbgl_objIsUx(obj) ? &touchCtxs[UX_CTX] : &touchCtxs[APP_CTX];
if (obj == ctx->lastPressedObj) {
return (ctx->lastCurrentTime - ctx->lastPressedTime);
}
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions lib_ux_nbgl/ux.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void ux_process_finger_event(uint8_t seph_packet[])
#ifdef HAVE_HW_TOUCH_SWIPE
pos.swipe = seph_packet[10];
#endif // HAVE_HW_TOUCH_SWIPE
nbgl_touchHandler(&pos, nbTicks * 100);
nbgl_touchHandler(false, &pos, nbTicks * 100);
nbgl_refresh();
}
}
Expand Down Expand Up @@ -131,7 +131,7 @@ void ux_process_ticker_event(void)
pos.x = touch_info.x;
pos.y = touch_info.y;
// Send current touch position to nbgl
nbgl_touchHandler(&pos, nbTicks * 100);
nbgl_touchHandler(false, &pos, nbTicks * 100);
}
#endif // HAVE_SE_TOUCH
nbgl_refresh();
Expand Down
3 changes: 2 additions & 1 deletion unit-tests/lib_nbgl/test_nbgl_obj.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,9 @@ void nbgl_screen_reinit(void)
{
return;
}

#ifdef HAVE_SE_TOUCH
void nbgl_touchInit(void) {}

static void test_draw_obj(void **state __attribute__((unused)))
{
nbgl_image_t *image;
Expand Down

0 comments on commit 621b9be

Please sign in to comment.