From 9e254acab3f83f992c3339fdab8af33b9e469072 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 23 Apr 2022 15:32:32 +0100 Subject: [PATCH] touchscreen: Update action system touch event reporting Add a cleaner API for reporting touch events and deprecate the old action_get_touchscreen_press() API. The old API is now emulated by using the new one internally. Change-Id: I001378e66f9c81806f134f011420d671954fcde2 --- apps/action.c | 131 +++++++++++++++++++++------------- apps/action.h | 21 ++---- firmware/export/touchscreen.h | 15 ++++ 3 files changed, 100 insertions(+), 67 deletions(-) diff --git a/apps/action.c b/apps/action.c index 0bae2ba1b2..3bd5d062f1 100644 --- a/apps/action.c +++ b/apps/action.c @@ -101,8 +101,9 @@ typedef struct #endif #ifdef HAVE_TOUCHSCREEN - bool ts_short_press; - int ts_data; + int ts_data; + long ts_start_tick; + struct touchevent touchevent; #endif } action_last_t; @@ -123,8 +124,8 @@ static action_last_t action_last = #endif #ifdef HAVE_TOUCHSCREEN - .ts_data = 0, - .ts_short_press = false, + .ts_data = 0, + .ts_start_tick = 0, #endif #ifdef HAVE_BACKLIGHT @@ -414,12 +415,10 @@ static inline void update_screen_has_lock(action_last_t *last, action_cur_t *cur } /*********************************************** -* get_action_touchscreen allows touchscreen -* presses to have short_press and repeat events +* handles touch event processing */ static inline bool get_action_touchscreen(action_last_t *last, action_cur_t *cur) { - #if !defined(HAVE_TOUCHSCREEN) (void) last; (void) cur; @@ -427,26 +426,53 @@ static inline bool get_action_touchscreen(action_last_t *last, action_cur_t *cur #else if (has_flag(cur->button, BUTTON_TOUCHSCREEN)) { - last->repeated = false; - last->ts_short_press = false; - if (has_flag(last->button, BUTTON_TOUCHSCREEN)) + intptr_t data = button_get_data(); + long now = current_tick; + + if (has_flag(last->button, BUTTON_TOUCHSCREEN) && + !has_flag(last->button, BUTTON_REL)) { - if (has_flag(cur->button, BUTTON_REL) && - !has_flag(last->button, BUTTON_REPEAT)) - { - last->ts_short_press = true; - } - else if (has_flag(cur->button, BUTTON_REPEAT)) - { + /* Only update the coordinates if this is not a release event. + * For release events, we reuse the previous event coordinates. */ + if (!has_flag(cur->button, BUTTON_REL)) + last->ts_data = data; + + /* Historical baggage... may be unnecessary. */ + if (has_flag(cur->button, BUTTON_REPEAT)) last->repeated = true; - } + } + else + { + /* Ignore isolated release events. No good can come of this. */ + if (has_flag(cur->button, BUTTON_REL)) + return false; + + last->ts_data = data; + last->ts_start_tick = now; } last->button = cur->button; - last->tick = current_tick; + last->tick = now; cur->action = ACTION_TOUCHSCREEN; + + /* Update touchevent data */ + if (has_flag(last->button, BUTTON_REL)) + last->touchevent.type = TOUCHEVENT_RELEASE; + else if (has_flag(last->button, BUTTON_REPEAT)) + last->touchevent.type = TOUCHEVENT_CONTACT; + else + last->touchevent.type = TOUCHEVENT_PRESS; + + last->touchevent.x = (last->ts_data >> 16) & 0xffff; + last->touchevent.y = last->ts_data & 0xffff; + last->touchevent.tick = last->tick; + return true; } + else + { + last->touchevent.type = TOUCHEVENT_NONE; + } return false; #endif @@ -1117,54 +1143,59 @@ static int get_action_worker(action_last_t *last, action_cur_t *cur) ******************************************************************************* */ #ifdef HAVE_TOUCHSCREEN +int action_get_touch_event(struct touchevent *ev) +{ + if (ev) + *ev = action_last.touchevent; + + return action_last.touchevent.type; +} + /* return BUTTON_NONE on error * BUTTON_REPEAT if repeated press * BUTTON_REPEAT|BUTTON_REL if release after repeated press * BUTTON_REL if it's a short press = release after press * BUTTON_TOUCHSCREEN if press + * DEPRECATED, do not use it anymore. */ int action_get_touchscreen_press(short *x, short *y) { + /* historical default value */ + const long long_press_time = 30 * HZ / 100; - int data; - int ret = BUTTON_TOUCHSCREEN; - - if (!has_flag(action_last.button, BUTTON_TOUCHSCREEN)) + int ret; + struct touchevent ev; + switch (action_get_touch_event(&ev)) { - return BUTTON_NONE; + case TOUCHEVENT_PRESS: + case TOUCHEVENT_CONTACT: + if (TIME_AFTER(ev.tick, action_last.ts_start_tick + long_press_time)) + ret = BUTTON_REPEAT; + else + ret = BUTTON_TOUCHSCREEN; + break; + + case TOUCHEVENT_RELEASE: + if (TIME_AFTER(ev.tick, action_last.ts_start_tick + long_press_time)) + ret = BUTTON_REPEAT|BUTTON_REL; + else + ret = BUTTON_REL; + break; + + default: + ret = BUTTON_NONE; + break; } - data = button_get_data(); - if (has_flag(action_last.button, BUTTON_REL)) - { - *x = (action_last.ts_data&0xffff0000)>>16; - *y = (action_last.ts_data&0xffff); - } - else - { - *x = (data&0xffff0000)>>16; - *y = (data&0xffff); - } - - action_last.ts_data = data; - - if (action_last.repeated) - { - ret = BUTTON_REPEAT; - } - else if (action_last.ts_short_press) - { - ret = BUTTON_REL; - } - /* This is to return a BUTTON_REL after a BUTTON_REPEAT. */ - else if (has_flag(action_last.button, BUTTON_REL)) - { - ret = BUTTON_REPEAT|BUTTON_REL; + if (ret != BUTTON_NONE) { + *x = ev.x; + *y = ev.y; } return ret; } +/* DEPRECATED, do not use it anymore. */ int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp) { short x, y; diff --git a/apps/action.h b/apps/action.h index d88b9a51a8..d4ceefb3c5 100644 --- a/apps/action.h +++ b/apps/action.h @@ -415,24 +415,11 @@ int get_action_statuscode(int *button); intptr_t get_action_data(void); #ifdef HAVE_TOUCHSCREEN -/* return BUTTON_NONE on error - * BUTTON_REPEAT if repeated press - * BUTTON_REPEAT|BUTTON_REL if release after repeated press - * BUTTON_REL if it's a short press = release after press - * BUTTON_TOUCHSCREEN if press - */ -int action_get_touchscreen_press(short *x, short *y); +/* Return a touch event and screen coordinates of the touch. */ +int action_get_touch_event(struct touchevent *ev); -/* - * wrapper action_get_touchscreen_press() - * to filter the touchscreen coordinates through a viewport - * - * returns the action and x1, y1 relative to the viewport if - * the press was within the viewport, - * ACTION_UNKNOWN (and x1, y1 untouched) if the press was outside - * BUTTON_NONE else - * - **/ +/* DEPRECATED, do not use these anymore */ +int action_get_touchscreen_press(short *x, short *y); int action_get_touchscreen_press_in_vp(short *x1, short *y1, struct viewport *vp); #endif diff --git a/firmware/export/touchscreen.h b/firmware/export/touchscreen.h index 4aecb0310a..f33b043c94 100644 --- a/firmware/export/touchscreen.h +++ b/firmware/export/touchscreen.h @@ -42,6 +42,21 @@ enum touchscreen_mode from button_get_data */ }; +enum touchevent_type +{ + TOUCHEVENT_NONE = 0, + TOUCHEVENT_PRESS, + TOUCHEVENT_CONTACT, + TOUCHEVENT_RELEASE, +}; + +struct touchevent +{ + int type; + short x, y; + long tick; +}; + extern struct touchscreen_parameter calibration_parameters; extern const struct touchscreen_parameter default_calibration_parameters; int touchscreen_calibrate(struct touchscreen_calibration *cal);