Support for touch/key events in LUA widgets

This commit is contained in:
Raphael Coeffic
2022-06-11 15:38:08 +02:00
committed by Raphael Coeffic
parent 93797a3e14
commit a3424d5bc0
21 changed files with 965 additions and 753 deletions
+68 -500
View File
@@ -29,40 +29,45 @@
#include "api_colorlcd.h"
#include "view_main.h"
#include "lua_widget.h"
#include "lua_widget_factory.h"
#define MAX_INSTRUCTIONS (20000/100)
#define LUA_WARNING_INFO_LEN 64
#if defined(HARDWARE_TOUCH)
#include "touch.h"
#define EVT_TOUCH_SWIPE_LOCK 4
#define EVT_TOUCH_SWIPE_SPEED 60
#define EVT_TOUCH_SWIPE_TIMEOUT 50
#endif
// #if defined(HARDWARE_TOUCH)
// #include "touch.h"
// #define EVT_TOUCH_SWIPE_LOCK 4
// #define EVT_TOUCH_SWIPE_SPEED 60
// #define EVT_TOUCH_SWIPE_TIMEOUT 50
// #endif
lua_State * lsWidgets = NULL;
extern int custom_lua_atpanic(lua_State *L);
#define LUA_WIDGET_FILENAME "/main.lua"
#define LUA_FULLPATH_MAXLEN (LEN_FILE_PATH_MAX + LEN_SCRIPT_FILENAME + LEN_FILE_EXTENSION_MAX) // max length (example: /SCRIPTS/THEMES/mytheme.lua)
#define LUA_WIDGET_FILENAME "/main.lua"
#define LUA_FULLPATH_MAXLEN \
(LEN_FILE_PATH_MAX + LEN_SCRIPT_FILENAME + \
LEN_FILE_EXTENSION_MAX) // max length (example:
// /SCRIPTS/THEMES/mytheme.lua)
static void luaHook(lua_State * L, lua_Debug *ar)
static void luaHook(lua_State *L, lua_Debug *ar)
{
if (ar->event == LUA_HOOKCOUNT) {
instructionsPercent++;
#if defined(DEBUG)
// Disable Lua script instructions limit in DEBUG mode,
// just report max value reached
static uint16_t max = 0;
if (instructionsPercent > 100) {
if (max + 10 < instructionsPercent) {
max = instructionsPercent;
TRACE("LUA instructionsPercent %u%%", (uint32_t)max);
// Disable Lua script instructions limit in DEBUG mode,
// just report max value reached
static uint16_t max = 0;
if (instructionsPercent > 100) {
if (max + 10 < instructionsPercent) {
max = instructionsPercent;
TRACE("LUA instructionsPercent %u%%", (uint32_t)max);
}
} else if (instructionsPercent < 10) {
max = 0;
}
}
else if (instructionsPercent < 10) {
max = 0;
}
#else
if (instructionsPercent > 100) {
// From now on, as soon as a line is executed, error
@@ -75,16 +80,17 @@ static void luaHook(lua_State * L, lua_Debug *ar)
#if defined(LUA_ALLOCATOR_TRACER)
else if (ar->event == LUA_HOOKLINE) {
lua_getinfo(L, "nSl", ar);
LuaMemTracer * tracer = GET_TRACER(L);
LuaMemTracer *tracer = GET_TRACER(L);
if (tracer->alloc || tracer->free) {
TRACE("LT: [+%u,-%u] %s:%d", tracer->alloc, tracer->free, tracer->script, tracer->lineno);
TRACE("LT: [+%u,-%u] %s:%d", tracer->alloc, tracer->free, tracer->script,
tracer->lineno);
}
tracer->script = ar->source;
tracer->lineno = ar->currentline;
tracer->alloc = 0;
tracer->free = 0;
}
#endif // #if defined(LUA_ALLOCATOR_TRACER)
#endif // #if defined(LUA_ALLOCATOR_TRACER)
}
void luaSetInstructionsLimit(lua_State * L, int count)
@@ -97,7 +103,7 @@ void luaSetInstructionsLimit(lua_State * L, int count)
#endif
}
ZoneOption * createOptionsArray(int reference, uint8_t maxOptions)
ZoneOption *createOptionsArray(int reference, uint8_t maxOptions)
{
if (reference == 0) {
// TRACE("createOptionsArray() no options");
@@ -116,30 +122,33 @@ ZoneOption * createOptionsArray(int reference, uint8_t maxOptions)
// TRACE("limited to %d options", count);
}
ZoneOption * options = (ZoneOption *)malloc(sizeof(ZoneOption) * (count+1));
ZoneOption *options = (ZoneOption *)malloc(sizeof(ZoneOption) * (count + 1));
if (!options) {
return NULL;
}
PROTECT_LUA() {
PROTECT_LUA()
{
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference);
ZoneOption * option = options;
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), count-- > 0; lua_pop(lsWidgets, 1)) {
ZoneOption *option = options;
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), count-- > 0;
lua_pop(lsWidgets, 1)) {
// TRACE("parsing option %d", count);
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table
uint8_t field = 0;
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2) && field<5; lua_pop(lsWidgets, 1), field++) {
for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2) && field < 5;
lua_pop(lsWidgets, 1), field++) {
switch (field) {
case 0:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TSTRING); // value is string
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TSTRING); // value is string
option->name = lua_tostring(lsWidgets, -1);
// TRACE("name = %s", option->name);
break;
case 1:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->type = (ZoneOption::Type)lua_tointeger(lsWidgets, -1);
// TRACE("type = %d", option->type);
if (option->type > ZoneOption::Color) {
@@ -154,44 +163,42 @@ ZoneOption * createOptionsArray(int reference, uint8_t maxOptions)
}
break;
case 2:
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
if (option->type == ZoneOption::Integer) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.signedValue = lua_tointeger(lsWidgets, -1);
// TRACE("default signed = %d", option->deflt.signedValue);
}
else if (option->type == ZoneOption::Source ||
option->type == ZoneOption::TextSize) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
} else if (option->type == ZoneOption::Source ||
option->type == ZoneOption::TextSize) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue = lua_tounsigned(lsWidgets, -1);
// TRACE("default unsigned = %u", option->deflt.unsignedValue);
}
else if (option->type == ZoneOption::Color) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue = COLOR_VAL(flagsRGB(lua_tounsigned(lsWidgets, -1)));
} else if (option->type == ZoneOption::Color) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.unsignedValue =
COLOR_VAL(flagsRGB(lua_tounsigned(lsWidgets, -1)));
// TRACE("default unsigned = %u", option->deflt.unsignedValue);
}
else if (option->type == ZoneOption::Bool) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
} else if (option->type == ZoneOption::Bool) {
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->deflt.boolValue = (lua_tounsigned(lsWidgets, -1) != 0);
// TRACE("default bool = %d", (int)(option->deflt.boolValue));
}
else if (option->type == ZoneOption::String) {
strncpy(option->deflt.stringValue, lua_tostring(lsWidgets, -1), LEN_ZONE_OPTION_STRING);
} else if (option->type == ZoneOption::String) {
strncpy(option->deflt.stringValue, lua_tostring(lsWidgets, -1),
LEN_ZONE_OPTION_STRING);
// TRACE("default string = %s", lua_tostring(lsWidgets, -1));
}
break;
case 3:
if (option->type == ZoneOption::Integer) {
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->min.signedValue = lua_tointeger(lsWidgets, -1);
}
break;
case 4:
if (option->type == ZoneOption::Integer) {
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number
luaL_checktype(lsWidgets, -1, LUA_TNUMBER); // value is number
option->max.signedValue = lua_tointeger(lsWidgets, -1);
}
break;
@@ -199,9 +206,10 @@ ZoneOption * createOptionsArray(int reference, uint8_t maxOptions)
}
option++;
}
option->name = NULL; // sentinel
option->name = NULL; // sentinel
}
else {
else
{
TRACE("error in theme/widget options");
free(options);
return NULL;
@@ -210,452 +218,13 @@ ZoneOption * createOptionsArray(int reference, uint8_t maxOptions)
return options;
}
struct eventData {
event_t event;
#if defined(HARDWARE_TOUCH)
coord_t touchX;
coord_t touchY;
coord_t startX;
coord_t startY;
coord_t slideX;
coord_t slideY;
short tapCount;
#endif
};
class LuaWidget: public Widget
{
friend class LuaWidgetFactory;
public:
LuaWidget(const WidgetFactory * factory, Window* parent, const rect_t & rect, WidgetPersistentData * persistentData, int luaWidgetDataRef):
Widget(factory, parent, rect, persistentData),
luaWidgetDataRef(luaWidgetDataRef),
errorMessage(nullptr)
{
}
~LuaWidget() override
{
luaL_unref(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
free(errorMessage);
}
#if defined(DEBUG_WINDOWS)
std::string getName() const override
{
return "LuaWidget";
}
#endif
// Widget interface
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;
protected:
int luaWidgetDataRef;
char * errorMessage;
bool refreshed = false;
static eventData events[EVENT_BUFFER_SIZE];
#if defined(HARDWARE_TOUCH)
static bool fingerDown;
static tmr10ms_t swipeTimeOut;
#endif
void checkEvents() override;
void setErrorMessage(const char * funcName);
private:
eventData* findOpenEventSlot(event_t event = 0);
};
eventData LuaWidget::events[EVENT_BUFFER_SIZE] = { 0 };
#if defined(HARDWARE_TOUCH)
bool LuaWidget::fingerDown = false;
tmr10ms_t LuaWidget::swipeTimeOut = 0;
#endif
static void l_pushtableint(const char * key, int value)
{
lua_pushstring(lsWidgets, key);
lua_pushinteger(lsWidgets, value);
lua_settable(lsWidgets, -3);
}
static 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();
friend class LuaWidget;
public:
LuaWidgetFactory(const char * name, ZoneOption * widgetOptions, int createFunction):
WidgetFactory(name, widgetOptions),
createFunction(createFunction),
updateFunction(0),
refreshFunction(0),
backgroundFunction(0)
{
}
~LuaWidgetFactory()
{
unregisterWidget(this);
}
Widget * create(Window* parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init=true) const override
{
if (lsWidgets == 0) return 0;
initPersistentData(persistentData, init);
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, createFunction);
lua_newtable(lsWidgets);
l_pushtableint("x", 0);
l_pushtableint("y", 0);
l_pushtableint("w", rect.w);
l_pushtableint("h", rect.h);
l_pushtableint("xabs", rect.x);
l_pushtableint("yabs", rect.y);
lua_newtable(lsWidgets);
int i = 0;
for (const ZoneOption * option = options; option->name; option++, i++) {
if (option->type == ZoneOption::String) {
lua_pushstring(lsWidgets, option->name);
char str[LEN_ZONE_OPTION_STRING + 1] = {0}; // Zero-terminated string for Lua
strncpy(str, persistentData->options[i].value.stringValue, LEN_ZONE_OPTION_STRING);
lua_pushstring(lsWidgets, &str[0]);
lua_settable(lsWidgets, -3);
} else if (option->type == ZoneOption::Color) {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, COLOR2FLAGS(value) | RGB_FLAG);
} else {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, value);
}
}
bool err = lua_pcall(lsWidgets, 2, 1, 0);
int widgetData = err ? LUA_NOREF : luaL_ref(lsWidgets, LUA_REGISTRYINDEX);
LuaWidget* lw = new LuaWidget(this, parent, rect, persistentData, widgetData);
if (err)
lw->setErrorMessage("create()");
return lw;
}
protected:
int createFunction;
int updateFunction;
int refreshFunction;
int backgroundFunction;
};
// Look for a slot in the event buffer that is either unused (zero) or matches event
eventData* LuaWidget::findOpenEventSlot(event_t event)
{
for (int i = 0; i < EVENT_BUFFER_SIZE; i++) {
if (events[i].event == event || events[i].event == 0)
return &events[i];
}
return NULL;
}
void LuaWidget::checkEvents()
{
Widget::checkEvents();
// paint has not been called
if (!refreshed) {
background();
refreshed = true;
}
refreshed = false;
invalidate();
#if defined(DEBUG_WINDOWS)
TRACE_WINDOWS("# refresh: %s", getWindowDebugString().c_str());
#endif
}
void LuaWidget::update()
{
Widget::update();
if (lsWidgets == 0 || errorMessage) return;
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
LuaWidgetFactory * factory = (LuaWidgetFactory *)this->factory;
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, factory->updateFunction);
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
lua_newtable(lsWidgets);
int i = 0;
for (const ZoneOption * option = getOptions(); option->name; option++, i++) {
if (option->type == ZoneOption::String) {
lua_pushstring(lsWidgets, option->name);
char str[LEN_ZONE_OPTION_STRING + 1] = {0}; // Zero-terminated string for Lua
strncpy(str, persistentData->options[i].value.stringValue, LEN_ZONE_OPTION_STRING);
lua_pushstring(lsWidgets, &str[0]);
lua_settable(lsWidgets, -3);
} else if (option->type == ZoneOption::Color) {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, COLOR2FLAGS(value) | RGB_FLAG);
} else {
int32_t value = persistentData->options[i].value.signedValue;
l_pushtableint(option->name, value);
}
}
if (lua_pcall(lsWidgets, 2, 0, 0) != 0) {
setErrorMessage("update()");
}
}
void LuaWidget::setErrorMessage(const char * funcName)
{
TRACE("Error in widget %s %s function: %s", factory->getName(), funcName, lua_tostring(lsWidgets, -1));
TRACE("Widget disabled");
size_t needed = snprintf(NULL, 0, "ERROR in %s: %s", funcName, lua_tostring(lsWidgets, -1)) + 1;
errorMessage = (char *)malloc(needed + 1);
if (errorMessage) {
snprintf(errorMessage, needed, "ERROR in %s: %s", funcName, lua_tostring(lsWidgets, -1));
errorMessage[needed] = '\0';
}
}
const char * LuaWidget::getErrorMessage() const
{
return errorMessage;
}
void LuaWidget::refresh(BitmapBuffer* dc)
{
if (lsWidgets == 0) return;
if (errorMessage) {
drawTextLines(dc, 0, 0, fullscreen ? LCD_W : rect.w, fullscreen ? LCD_H : rect.h, errorMessage, FONT(XS) | COLOR_THEME_WARNING);
return;
}
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
LuaWidgetFactory * factory = (LuaWidgetFactory *)this->factory;
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, factory->refreshFunction);
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
// Pass key event to fullscreen Lua widget
eventData* es = &events[0];
if (fullscreen)
lua_pushinteger(lsWidgets, es->event);
else
lua_pushnil(lsWidgets);
#if defined(HARDWARE_TOUCH)
if (fullscreen && IS_TOUCH_EVENT(es->event)) {
lua_newtable(lsWidgets);
l_pushtableint("x", es->touchX);
l_pushtableint("y", es->touchY);
l_pushtableint("tapCount", es->tapCount);
if (es->event == EVT_TOUCH_SLIDE) {
l_pushtableint("startX", es->startX);
l_pushtableint("startY", es->startY);
l_pushtableint("slideX", es->slideX);
l_pushtableint("slideY", es->slideY);
// Do we have a swipe? Only one at a time!
if (get_tmr10ms() > swipeTimeOut) {
coord_t absX = (es->slideX < 0) ? -(es->slideX) : es->slideX;
coord_t absY = (es->slideY < 0) ? -(es->slideY) : es->slideY;
bool swiped = false;
if (absX > EVT_TOUCH_SWIPE_LOCK * absY) {
if ((swiped = (es->slideX > EVT_TOUCH_SWIPE_SPEED)))
l_pushtablebool("swipeRight", true);
else if ((swiped = (es->slideX < -EVT_TOUCH_SWIPE_SPEED)))
l_pushtablebool("swipeLeft", true);
}
else if (absY > EVT_TOUCH_SWIPE_LOCK * absX) {
if ((swiped = (es->slideY > EVT_TOUCH_SWIPE_SPEED)))
l_pushtablebool("swipeDown", true);
else if ((swiped = (es->slideY < -EVT_TOUCH_SWIPE_SPEED)))
l_pushtablebool("swipeUp", true);
}
if (swiped)
swipeTimeOut = get_tmr10ms() + EVT_TOUCH_SWIPE_TIMEOUT;
}
}
} else
#endif
lua_pushnil(lsWidgets);
// Move the event buffer forward
for (int i = 1; i < EVENT_BUFFER_SIZE; i++)
events[i - 1] = events[i];
memclear(&events[EVENT_BUFFER_SIZE - 1], sizeof(eventData));
// Enable drawing into the current LCD buffer
luaLcdBuffer = dc;
// This little hack is needed to not interfere with the LCD usage of preempted scripts
bool lla = luaLcdAllowed;
luaLcdAllowed = true;
runningFS = this;
if (lua_pcall(lsWidgets, 3, 0, 0) != 0) {
setErrorMessage("refresh()");
}
runningFS = nullptr;
// Remove LCD
luaLcdAllowed = lla;
luaLcdBuffer = nullptr;
// mark as refreshed
refreshed = true;
}
void LuaWidget::background()
{
if (lsWidgets == 0 || errorMessage) return;
// TRACE("LuaWidget::background()");
luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS);
LuaWidgetFactory * factory = (LuaWidgetFactory *)this->factory;
if (factory->backgroundFunction) {
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, factory->backgroundFunction);
lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaWidgetDataRef);
runningFS = this;
if (lua_pcall(lsWidgets, 1, 0, 0) != 0) {
setErrorMessage("background()");
}
runningFS = nullptr;
}
}
#if defined(HARDWARE_KEYS)
void LuaWidget::onEvent(event_t event)
{
if (fullscreen) {
if (EVT_KEY_LONG(KEY_EXIT) == event) {
// Clear event buffer on full screen exit
memclear(&events, EVENT_BUFFER_SIZE * sizeof(eventData));
} else {
eventData* es = findOpenEventSlot();
if (es)
es->event = event;
}
}
Widget::onEvent(event);
}
#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);
// Only one EVT_TOUCH_FIRST at a time
if (fullscreen) {
if (!fingerDown) {
eventData* es = findOpenEventSlot();
if (es) {
es->event = EVT_TOUCH_FIRST;
es->touchX = x;
es->touchY = y;
}
fingerDown = true;
}
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) {
eventData* es = findOpenEventSlot();
if (es) {
if (touchState.tapCount > 0) {
es->event = EVT_TOUCH_TAP;
es->tapCount = touchState.tapCount;
} else
es->event = EVT_TOUCH_BREAK;
es->touchX = x;
es->touchY = y;
}
fingerDown = false;
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) {
// If we already have a SLIDE going, then accumulate slide values instead of allocating an empty slot
eventData* es = findOpenEventSlot(EVT_TOUCH_SLIDE);
if (es) {
ViewMain* vm = ViewMain::instance();
es->event = EVT_TOUCH_SLIDE;
// es->touchX = x + vm->getScrollPositionX();
// es->touchY = y + vm->getScrollPositionY();
es->startX = startX;
es->startY = startY;
es->slideX += slideX;
es->slideY += slideY;
}
fingerDown = false;
return true;
}
return Widget::onTouchSlide(x, y, startX, startY, slideX, slideY);
}
#endif
void luaLoadWidgetCallback()
{
TRACE("luaLoadWidgetCallback()");
const char * name=NULL;
int widgetOptions=0, createFunction=0, updateFunction=0, refreshFunction=0, backgroundFunction=0;
int widgetOptions = 0, createFunction = 0, updateFunction = 0,
refreshFunction = 0, backgroundFunction = 0;
luaL_checktype(lsWidgets, -1, LUA_TTABLE);
@@ -798,7 +367,6 @@ void luaInitThemesAndWidgets()
}
UNPROTECT_LUA();
TRACE("lsWidgets %p", lsWidgets);
//luaLoadFiles(THEMES_PATH, luaLoadThemeCallback);
luaLoadFiles(WIDGETS_PATH, luaLoadWidgetCallback);
luaDoGc(lsWidgets, true);
}