diff --git a/common/luaclass.c b/common/luaclass.c index 3f17a3c4..2b16c7ba 100644 --- a/common/luaclass.c +++ b/common/luaclass.c @@ -22,6 +22,53 @@ #include "common/luaclass.h" #include "common/luaobject.h" +typedef struct +{ + int id; + lua_class_t *class; +} lua_class_id_t; + +DO_ARRAY(lua_class_id_t, lua_class_id, DO_NOTHING) + +static lua_class_id_array_t luaA_classes; + +void +luaA_openlib(lua_State *L, const char *name, + const struct luaL_reg methods[], + const struct luaL_reg meta[]) +{ + luaL_newmetatable(L, name); /* 1 */ + lua_pushvalue(L, -1); /* dup metatable 2 */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable 1 */ + + luaL_register(L, NULL, meta); /* 1 */ + luaL_register(L, name, methods); /* 2 */ + lua_pushvalue(L, -1); /* dup self as metatable 3 */ + lua_setmetatable(L, -2); /* set self as metatable 2 */ + lua_pop(L, 2); +} + +void +luaA_class_setup(lua_State *L, lua_class_t *class, + const char *name, + lua_class_allocator_t allocator, + const struct luaL_reg methods[], + const struct luaL_reg meta[]) +{ + static int class_type_counter = LUA_TTHREAD + 1; + + luaA_openlib(L, name, methods, meta); + + class->allocator = allocator; + class->name = name; + + lua_class_id_array_append(&luaA_classes, (lua_class_id_t) + { + .id = ++class_type_counter, + .class = class, + }); +} + void luaA_class_add_signal(lua_State *L, lua_class_t *lua_class, const char *name, int ud) diff --git a/common/luaclass.h b/common/luaclass.h index 029e87a0..f7dd1e1d 100644 --- a/common/luaclass.h +++ b/common/luaclass.h @@ -24,15 +24,36 @@ #include "common/signal.h" +#define LUA_OBJECT_HEADER \ + signal_array_t signals; + +/** Generic type for all objects. + * All Lua objects can be casted to this type. + */ typedef struct { + LUA_OBJECT_HEADER +} lua_object_t; + +typedef lua_object_t *(*lua_class_allocator_t)(lua_State *); + +typedef struct +{ + /** Class name */ + const char *name; signal_array_t signals; + /** Allocator for creating new objects of that class */ + lua_class_allocator_t allocator; } lua_class_t; void luaA_class_add_signal(lua_State *, lua_class_t *, const char *, int); void luaA_class_remove_signal(lua_State *, lua_class_t *, const char *, int); void luaA_class_emit_signal(lua_State *, lua_class_t *, const char *, int); +void luaA_openlib(lua_State *, const char *, const struct luaL_reg[], const struct luaL_reg[]); +void luaA_class_setup(lua_State *, lua_class_t *, const char *, lua_class_allocator_t, + const struct luaL_reg[], const struct luaL_reg[]); + #define LUA_CLASS_FUNCS(prefix, lua_class) \ static inline int \ luaA_##prefix##_class_add_signal(lua_State *L) \ diff --git a/common/luaobject.h b/common/luaobject.h index 8d11c122..db5a83b2 100644 --- a/common/luaobject.h +++ b/common/luaobject.h @@ -149,17 +149,6 @@ int luaA_object_add_signal_simple(lua_State *); int luaA_object_remove_signal_simple(lua_State *); int luaA_object_emit_signal_simple(lua_State *); -#define LUA_OBJECT_HEADER \ - signal_array_t signals; - -/** Generic type for all objects. - * All Lua objects can be casted to this type. - */ -typedef struct -{ - LUA_OBJECT_HEADER -} lua_object_t; - #define LUA_OBJECT_FUNCS(lua_class, type, prefix, lua_type) \ LUA_CLASS_FUNCS(prefix, lua_class) \ static inline type * \ diff --git a/luaa.c b/luaa.c index 93a916c0..25336a11 100644 --- a/luaa.c +++ b/luaa.c @@ -108,22 +108,6 @@ luaA_restart(lua_State *L __attribute__ ((unused))) return 0; } -static void -luaA_openlib(lua_State *L, const char *name, - const struct luaL_reg methods[], - const struct luaL_reg meta[]) -{ - luaL_newmetatable(L, name); /* 1 */ - lua_pushvalue(L, -1); /* dup metatable 2 */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable 1 */ - - luaL_register(L, NULL, meta); /* 1 */ - luaL_register(L, name, methods); /* 2 */ - lua_pushvalue(L, -1); /* dup self as metatable 3 */ - lua_setmetatable(L, -2); /* set self as metatable 2 */ - lua_pop(L, 2); -} - /** UTF-8 aware string length computing. * \param L The Lua VM state. * \return The number of elements pushed on stack. @@ -709,25 +693,32 @@ luaA_init(xdgHandle* xdg) luaA_openlib(L, "mouse", awesome_mouse_methods, awesome_mouse_meta); /* Export button */ - luaA_openlib(L, "button", awesome_button_methods, awesome_button_meta); + luaA_class_setup(L, &button_class, "button", (lua_class_allocator_t) button_new, + awesome_button_methods, awesome_button_meta); /* Export image */ - luaA_openlib(L, "image", awesome_image_methods, awesome_image_meta); + luaA_class_setup(L, &image_class, "image", (lua_class_allocator_t) image_new, + awesome_image_methods, awesome_image_meta); /* Export tag */ - luaA_openlib(L, "tag", awesome_tag_methods, awesome_tag_meta); + luaA_class_setup(L, &tag_class, "tag", (lua_class_allocator_t) tag_new, + awesome_tag_methods, awesome_tag_meta); /* Export wibox */ - luaA_openlib(L, "wibox", awesome_wibox_methods, awesome_wibox_meta); + luaA_class_setup(L, &wibox_class, "wibox", (lua_class_allocator_t) wibox_new, + awesome_wibox_methods, awesome_wibox_meta); /* Export widget */ - luaA_openlib(L, "widget", awesome_widget_methods, awesome_widget_meta); + luaA_class_setup(L, &widget_class, "widget", (lua_class_allocator_t) widget_new, + awesome_widget_methods, awesome_widget_meta); /* Export client */ - luaA_openlib(L, "client", awesome_client_methods, awesome_client_meta); + luaA_class_setup(L, &client_class, "client", (lua_class_allocator_t) client_new, + awesome_client_methods, awesome_client_meta); /* Export keys */ - luaA_openlib(L, "key", awesome_key_methods, awesome_key_meta); + luaA_class_setup(L, &key_class, "key", (lua_class_allocator_t) key_new, + awesome_key_methods, awesome_key_meta); /* init hooks */ globalconf.hooks.manage = LUA_REFNIL;