diff --git a/radio/src/gui/colorlcd/widget.cpp b/radio/src/gui/colorlcd/widget.cpp index 350762fd8..fdf41062d 100644 --- a/radio/src/gui/colorlcd/widget.cpp +++ b/radio/src/gui/colorlcd/widget.cpp @@ -125,9 +125,9 @@ void Widget::paint(BitmapBuffer * dc) } } +#if defined(HARDWARE_KEYS) void Widget::onEvent(event_t event) { -#if defined(HARDWARE_KEYS) TRACE("### event = 0x%x ###", event); if (!fullscreen) { if (event == EVT_KEY_BREAK(KEY_EXIT)) { @@ -145,8 +145,8 @@ void Widget::onEvent(event_t event) killEvents(event); setFullscreen(false); } -#endif } +#endif void Widget::update() { diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index 7906e1a61..eb76acba5 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -83,11 +83,12 @@ class Widget : public Button // Window interface void checkEvents() override; +#if defined(HARDWARE_KEYS) void onEvent(event_t event) override; +#endif #if defined(HARDWARE_TOUCH) bool onTouchEnd(coord_t x, coord_t y) override; - bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, - coord_t slideX, coord_t slideY) override; + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override; #endif void paint(BitmapBuffer * dc) override; diff --git a/radio/src/keys.h b/radio/src/keys.h index f8d30f1e5..601b0a30f 100644 --- a/radio/src/keys.h +++ b/radio/src/keys.h @@ -72,6 +72,18 @@ constexpr bool IS_VIRTUAL_KEY_EVENT(event_t event) { return (event & 0xF000) == _MSK_VIRTUAL_KEY; } + +// Touch events for Lua widgets - assuming _MSK_KEY_* for PCBHORUS +constexpr event_t EVT_TOUCH = EVT_VIRTUAL_KEY('t'); +constexpr event_t EVT_TOUCH_FIRST = EVT_TOUCH | _MSK_KEY_FIRST; +constexpr event_t EVT_TOUCH_BREAK = EVT_TOUCH | _MSK_KEY_BREAK; +constexpr event_t EVT_TOUCH_SLIDE = EVT_TOUCH | _MSK_KEY_LONG; +constexpr event_t EVT_TOUCH_TAP = EVT_TOUCH | _MSK_KEY_REPT; + +constexpr bool IS_TOUCH_EVENT(event_t event) +{ + return (event & ~_MSK_KEY_FLAGS) == EVT_TOUCH; +} #endif // normal order of events is: FIRST, LONG, REPEAT, REPEAT, ..., BREAK diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 9cd4db639..65322ae05 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -2097,6 +2097,13 @@ const luaR_value_entry opentxConstants[] = { { "EVT_ROT_RIGHT", EVT_ROTARY_RIGHT }, #endif +#if defined(HARDWARE_TOUCH) + { "EVT_TOUCH_FIRST", EVT_TOUCH_FIRST }, + { "EVT_TOUCH_BREAK", EVT_TOUCH_BREAK }, + { "EVT_TOUCH_SLIDE", EVT_TOUCH_SLIDE }, + { "EVT_TOUCH_TAP", EVT_TOUCH_TAP }, +#endif + #if LCD_DEPTH > 1 && !defined(COLORLCD) { "FILL_WHITE", FILL_WHITE }, { "GREY_DEFAULT", GREY_DEFAULT }, diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp index 50fcbb034..e2a514bff 100644 --- a/radio/src/lua/widgets.cpp +++ b/radio/src/lua/widgets.cpp @@ -31,6 +31,12 @@ #define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (20000/100) #define LUA_WARNING_INFO_LEN 64 +#if defined(HARDWARE_TOUCH) +#define EVT_TOUCH_TAP_TIME 25 +#define EVT_TOUCH_SWIPE_LOCK 10 +#define EVT_TOUCH_SWIPE_SPEED 35 +#endif + constexpr int LUA_WIDGET_REFRESH = 1000 / 10; // 10 Hz lua_State * lsWidgets = NULL; @@ -190,7 +196,16 @@ class LuaWidget: public Widget const char * getErrorMessage() const override; void update() override; void background() override; + +#if defined(HARDWARE_KEYS) void onEvent(event_t event) override; +#endif + +#if defined(HARDWARE_TOUCH) + bool onTouchStart(coord_t x, coord_t y) override; + bool onTouchEnd(coord_t x, coord_t y) override; + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override; +#endif // Calls LUA widget 'refresh' method void refresh(BitmapBuffer* dc) override; @@ -200,12 +215,34 @@ class LuaWidget: public Widget char * errorMessage; uint32_t lastRefresh = 0; bool refreshed = false; - event_t event = 0; + + static event_t event; +#if defined(HARDWARE_TOUCH) + static coord_t touchX; + static coord_t touchY; + static coord_t startX; + static coord_t startY; + static coord_t slideX; + static coord_t slideY; + static tmr10ms_t lastTouchDown; +#endif void checkEvents() override; void setErrorMessage(const char * funcName); }; +event_t LuaWidget::event = 0; + +#if defined(HARDWARE_TOUCH) +coord_t LuaWidget::touchX = 0; +coord_t LuaWidget::touchY = 0; +coord_t LuaWidget::startX = 0; +coord_t LuaWidget::startY = 0; +coord_t LuaWidget::slideX = 0; +coord_t LuaWidget::slideY = 0; +tmr10ms_t LuaWidget::lastTouchDown = 0; +#endif + void l_pushtableint(const char * key, int value) { lua_pushstring(lsWidgets, key); @@ -213,6 +250,13 @@ void l_pushtableint(const char * key, int value) lua_settable(lsWidgets, -3); } +void l_pushtablebool(const char * key, bool value) +{ + lua_pushstring(lsWidgets, key); + lua_pushboolean(lsWidgets, value); + lua_settable(lsWidgets, -3); +} + class LuaWidgetFactory: public WidgetFactory { friend void luaLoadWidgetCallback(); @@ -345,18 +389,47 @@ void LuaWidget::refresh(BitmapBuffer* dc) lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef); // Pass key event to fullscreen Lua widget - if (fullscreen) { - event_t event = this->event; - this->event = 0; + if (fullscreen) lua_pushinteger(lsWidgets, event); - } else + else lua_pushnil(lsWidgets); +#if defined(HARDWARE_TOUCH) + if (fullscreen && IS_TOUCH_EVENT(event)) { + lua_newtable(lsWidgets); + l_pushtableint("x", touchX); + l_pushtableint("y", touchY); + + if (LuaWidget::event == EVT_TOUCH_SLIDE) { + l_pushtableint("startX", startX); + l_pushtableint("startY", startY); + l_pushtableint("slideX", slideX); + l_pushtableint("slideY", slideY); + + if (slideY > -EVT_TOUCH_SWIPE_LOCK && slideY < EVT_TOUCH_SWIPE_LOCK) { + if (slideX > EVT_TOUCH_SWIPE_SPEED) + l_pushtablebool("swipeRight", true); + else if (slideX < -EVT_TOUCH_SWIPE_SPEED) + l_pushtablebool("swipeLeft", true); + } + else if (slideX > -EVT_TOUCH_SWIPE_LOCK && slideX < EVT_TOUCH_SWIPE_LOCK) { + if (slideY > EVT_TOUCH_SWIPE_SPEED) + l_pushtablebool("swipeDown", true); + else if (slideY < -EVT_TOUCH_SWIPE_SPEED) + l_pushtablebool("swipeUp", true); + } + } + } else +#endif + lua_pushnil(lsWidgets); + + event = 0; + // Enable drawing into the current LCD buffer luaLcdBuffer = dc; luaLcdAllowed = true; - if (lua_pcall(lsWidgets, 2, 0, 0) != 0) { + if (lua_pcall(lsWidgets, 3, 0, 0) != 0) { setErrorMessage("refresh()"); } // Remove LCD @@ -382,17 +455,76 @@ void LuaWidget::background() } } +#if defined(HARDWARE_KEYS) void LuaWidget::onEvent(event_t event) { -#if defined(HARDWARE_KEYS) if (fullscreen && EVT_KEY_LONG(KEY_EXIT) != event) - this->event = event; + LuaWidget::event = event; else - this->event = 0; + LuaWidget::event = 0; Widget::onEvent(event); -#endif } +#endif + +#if defined(HARDWARE_TOUCH) +bool LuaWidget::onTouchStart(coord_t x, coord_t y) +{ + TRACE_WINDOWS("LuaWidget received touch start (%d) x=%d;y=%d", hasFocus(), x, y); + + if (fullscreen) { + event = EVT_TOUCH_FIRST; + touchX = x; + touchY = y; + + if (lastTouchDown == 0) + lastTouchDown = get_tmr10ms(); + + return true; + } + + return Widget::onTouchStart(x, y); +} + +bool LuaWidget::onTouchEnd(coord_t x, coord_t y) +{ + TRACE_WINDOWS("LuaWidget received touch end (%d) x=%d;y=%d", hasFocus(), x, y); + + if (fullscreen) { + if (get_tmr10ms() - lastTouchDown <= EVT_TOUCH_TAP_TIME) + event = EVT_TOUCH_TAP; + else + event = EVT_TOUCH_BREAK; + + touchX = x; + touchY = y; + lastTouchDown = 0; + + return true; + } + + return Widget::onTouchEnd(x, y); +} + +bool LuaWidget::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) +{ + TRACE_WINDOWS("LuaWidget touch slide"); + if (fullscreen) { + event = EVT_TOUCH_SLIDE; + touchX = x; + touchY = y; + LuaWidget::startX = startX; + LuaWidget::startY = startY; + LuaWidget::slideX = slideX; + LuaWidget::slideY = slideY; + lastTouchDown = 0; + + return true; + } + + return Widget::onTouchSlide(x, y, startX, startY, slideX, slideY); +} +#endif void luaLoadWidgetCallback() {