luaobject: add signals

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-06-20 14:44:05 +02:00
parent 51dc458fb9
commit eed9864ab0
6 changed files with 236 additions and 37 deletions

68
common/lualib.h Normal file
View File

@ -0,0 +1,68 @@
/*
* lualib.h - useful functions and type for Lua
*
* Copyright © 2009 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef AWESOME_COMMON_LUALIB
#define AWESOME_COMMON_LUALIB
#include <lauxlib.h>
#include "common/util.h"
#define luaA_checkfunction(L, n) \
do { \
if(!lua_isfunction(L, n)) \
luaL_typerror(L, n, "function"); \
} while(0)
/** Convert s stack index to positive.
* \param L The Lua VM state.
* \param ud The index.
* \return A positive index.
*/
static inline int
luaA_absindex(lua_State *L, int ud)
{
return (ud > 0 || ud <= LUA_REGISTRYINDEX) ? ud : lua_gettop(L) + ud + 1;
}
/** Execute an Lua function on top of the stack.
* \param L The Lua stack.
* \param nargs The number of arguments for the Lua function.
* \param nret The number of returned value from the Lua function.
* \return True on no error, false otherwise.
*/
static inline bool
luaA_dofunction(lua_State *L, int nargs, int nret)
{
if(nargs)
lua_insert(L, - (nargs + 1));
if(lua_pcall(L, nargs, nret, 0))
{
warn("error running function: %s",
lua_tostring(L, -1));
lua_pop(L, 1);
return false;
}
return true;
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -139,4 +139,63 @@ luaA_object_decref(lua_State *L, int tud, void *pointer)
} }
} }
/** Add a signal to an object.
* \param L The Lua VM state.
* \param oud The object index on the stack.
* \param name The name of the signal.
* \param ud The index of function to call when signal is emited.
*/
void
luaA_object_add_signal(lua_State *L, int oud,
const char *name, int ud)
{
luaA_checkfunction(L, ud);
lua_object_t *obj = lua_touserdata(L, oud);
signal_add(&obj->signals, name, luaA_object_ref_item(L, oud, ud));
}
/** Remove a signal to an object.
* \param L The Lua VM state.
* \param oud The object index on the stack.
* \param name The name of the signal.
* \param ud The index of function to call when signal is emited.
*/
void
luaA_object_remove_signal(lua_State *L, int oud,
const char *name, int ud)
{
luaA_checkfunction(L, ud);
lua_object_t *obj = lua_touserdata(L, oud);
void *ref = (void *) lua_topointer(L, ud);
signal_remove(&obj->signals, name, ref);
luaA_object_unref_item(L, oud, ref);
lua_remove(L, ud);
}
/** Emit a signal to an object.
* \param L The Lua VM state.
* \param oud The object index on the stack.
* \param name The name of the signal.
* \param nargs The number of arguments to pass to the called functions.
*/
void
luaA_object_emit_signal(lua_State *L, int oud,
const char *name, int nargs)
{
int oud_abs = luaA_absindex(L, oud);
lua_object_t *obj = lua_touserdata(L, oud);
signal_t *sigfound = signal_array_getbyid(&obj->signals,
a_strhash((const unsigned char *) name));
if(sigfound)
foreach(ref, sigfound->sigfuncs)
{
lua_pushvalue(L, oud_abs);
for(int i = 0; i < nargs; i++)
lua_pushvalue(L, - nargs - 1);
luaA_object_push_item(L, oud_abs, (void *) *ref);
luaA_dofunction(L, nargs + 1, 0);
}
lua_pop(L, nargs);
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -22,8 +22,7 @@
#ifndef AWESOME_COMMON_LUAOBJECT #ifndef AWESOME_COMMON_LUAOBJECT
#define AWESOME_COMMON_LUAOBJECT #define AWESOME_COMMON_LUAOBJECT
#include <lauxlib.h> #include "common/signal.h"
#include "common/array.h"
static inline int static inline int
luaA_settype(lua_State *L, const char *type) luaA_settype(lua_State *L, const char *type)
@ -142,7 +141,12 @@ luaA_object_push(lua_State *L, void *pointer)
return 1; return 1;
} }
#define LUA_OBJECT_HEADER void luaA_object_add_signal(lua_State *, int, const char *, int);
void luaA_object_remove_signal(lua_State *, int, const char *, int);
void luaA_object_emit_signal(lua_State *, int, const char *, int);
#define LUA_OBJECT_HEADER \
signal_array_t signals;
/** Generic type for all objects. /** Generic type for all objects.
* All Lua objects can be casted to this type. * All Lua objects can be casted to this type.
@ -201,6 +205,8 @@ typedef struct
static inline int static inline int
luaA_object_gc(lua_State *L) luaA_object_gc(lua_State *L)
{ {
lua_object_t *item = lua_touserdata(L, 1);
signal_array_wipe(&item->signals);
return 0; return 0;
} }

95
common/signal.h Normal file
View File

@ -0,0 +1,95 @@
/*
* common/signal.h - Signal handling functions
*
* Copyright © 2009 Julien Danjou <julien@danjou.info>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef AWESOME_COMMON_SIGNAL
#define AWESOME_COMMON_SIGNAL
#include "common/lualib.h"
#include "common/array.h"
DO_ARRAY(const void *, cptr, DO_NOTHING)
typedef struct
{
unsigned long id;
cptr_array_t sigfuncs;
} signal_t;
static inline int
signal_cmp(const void *a, const void *b)
{
const signal_t *x = a, *y = b;
return x->id > y->id ? 1 : (x->id < y->id ? -1 : 0);
}
DO_BARRAY(signal_t, signal, DO_NOTHING, signal_cmp)
static inline signal_t *
signal_array_getbyid(signal_array_t *arr, unsigned long id)
{
signal_t sig = { .id = id };
return signal_array_lookup(arr, &sig);
}
/** Add a signal inside a signal array.
* You are in charge of reference counting.
* \param arr The signal array.
* \param name The signal name.
* \param ref The reference to add.
*/
static inline void
signal_add(signal_array_t *arr, const char *name, const void *ref)
{
unsigned long tok = a_strhash((const unsigned char *) name);
signal_t *sigfound = signal_array_getbyid(arr, tok);
if(sigfound)
cptr_array_append(&sigfound->sigfuncs, ref);
else
{
signal_t sig = { .id = tok };
cptr_array_append(&sig.sigfuncs, ref);
signal_array_insert(arr, sig);
}
}
/** Remove a signal inside a signal array.
* You are in charge of reference counting.
* \param arr The signal array.
* \param name The signal name.
* \param ref The reference to remove.
*/
static inline void
signal_remove(signal_array_t *arr, const char *name, const void *ref)
{
signal_t *sigfound = signal_array_getbyid(arr,
a_strhash((const unsigned char *) name));
if(sigfound)
foreach(func, sigfound->sigfuncs)
if(ref == *func)
{
cptr_array_remove(&sigfound->sigfuncs, func);
break;
}
}
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

12
luaa.c
View File

@ -70,8 +70,6 @@ extern const struct luaL_reg awesome_wibox_meta[];
extern const struct luaL_reg awesome_key_methods[]; extern const struct luaL_reg awesome_key_methods[];
extern const struct luaL_reg awesome_key_meta[]; extern const struct luaL_reg awesome_key_meta[];
DO_ARRAY(const void *, void, DO_NOTHING)
/** Quit awesome. /** Quit awesome.
* \param L The Lua VM state. * \param L The Lua VM state.
* \return The number of elements pushed on stack. * \return The number of elements pushed on stack.
@ -501,7 +499,7 @@ luaA_hasitem(lua_State *L, const void *item)
* \return False if we encounter an elements already in list. * \return False if we encounter an elements already in list.
*/ */
static bool static bool
luaA_isloop_check(lua_State *L, void_array_t *elems) luaA_isloop_check(lua_State *L, cptr_array_t *elems)
{ {
if(lua_istable(L, -1)) if(lua_istable(L, -1))
{ {
@ -513,7 +511,7 @@ luaA_isloop_check(lua_State *L, void_array_t *elems)
return false; return false;
/* push the table in the elements list */ /* push the table in the elements list */
void_array_append(elems, object); cptr_array_append(elems, object);
/* look every object in the "table" */ /* look every object in the "table" */
lua_pushnil(L); lua_pushnil(L);
@ -543,9 +541,9 @@ luaA_isloop(lua_State *L, int idx)
{ {
/* elems is an elements array that we will fill with all array we /* elems is an elements array that we will fill with all array we
* encounter while browsing the tables */ * encounter while browsing the tables */
void_array_t elems; cptr_array_t elems;
void_array_init(&elems); cptr_array_init(&elems);
/* push table on top */ /* push table on top */
lua_pushvalue(L, idx); lua_pushvalue(L, idx);
@ -555,7 +553,7 @@ luaA_isloop(lua_State *L, int idx)
/* remove pushed table */ /* remove pushed table */
lua_pop(L, 1); lua_pop(L, 1);
void_array_wipe(&elems); cptr_array_wipe(&elems);
return !ret; return !ret;
} }

27
luaa.h
View File

@ -50,12 +50,6 @@
luaL_typerror(L, n, "table"); \ luaL_typerror(L, n, "table"); \
} while(0) } while(0)
#define luaA_checkfunction(L, n) \
do { \
if(!lua_isfunction(L, n)) \
luaL_typerror(L, n, "function"); \
} while(0)
#define luaA_checkscreen(screen) \ #define luaA_checkscreen(screen) \
do { \ do { \
if(screen < 0 || screen >= globalconf.screens.len) \ if(screen < 0 || screen >= globalconf.screens.len) \
@ -239,27 +233,6 @@ luaA_registerfct(lua_State *L, int idx, int *fct)
return luaA_register(L, idx, fct); return luaA_register(L, idx, fct);
} }
/** Execute an Lua function on top of the stack.
* \param L The Lua stack.
* \param nargs The number of arguments for the Lua function.
* \param nret The number of returned value from the Lua function.
* \return True on no error, false otherwise.
*/
static inline bool
luaA_dofunction(lua_State *L, int nargs, int nret)
{
if(nargs)
lua_insert(L, - (nargs + 1));
if(lua_pcall(L, nargs, nret, 0))
{
warn("error running function: %s",
lua_tostring(L, -1));
lua_pop(L, 1);
return false;
}
return true;
}
/** Grab a function from the registry and execute it. /** Grab a function from the registry and execute it.
* \param L The Lua stack. * \param L The Lua stack.
* \param ref The function reference. * \param ref The function reference.