luaobject: add signals
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
51dc458fb9
commit
eed9864ab0
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#ifndef AWESOME_COMMON_LUAOBJECT
|
||||
#define AWESOME_COMMON_LUAOBJECT
|
||||
|
||||
#include <lauxlib.h>
|
||||
#include "common/array.h"
|
||||
#include "common/signal.h"
|
||||
|
||||
static inline int
|
||||
luaA_settype(lua_State *L, const char *type)
|
||||
|
@ -142,7 +141,12 @@ luaA_object_push(lua_State *L, void *pointer)
|
|||
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.
|
||||
* All Lua objects can be casted to this type.
|
||||
|
@ -201,6 +205,8 @@ typedef struct
|
|||
static inline int
|
||||
luaA_object_gc(lua_State *L)
|
||||
{
|
||||
lua_object_t *item = lua_touserdata(L, 1);
|
||||
signal_array_wipe(&item->signals);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
12
luaa.c
|
@ -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_meta[];
|
||||
|
||||
DO_ARRAY(const void *, void, DO_NOTHING)
|
||||
|
||||
/** Quit awesome.
|
||||
* \param L The Lua VM state.
|
||||
* \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.
|
||||
*/
|
||||
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))
|
||||
{
|
||||
|
@ -513,7 +511,7 @@ luaA_isloop_check(lua_State *L, void_array_t *elems)
|
|||
return false;
|
||||
|
||||
/* push the table in the elements list */
|
||||
void_array_append(elems, object);
|
||||
cptr_array_append(elems, object);
|
||||
|
||||
/* look every object in the "table" */
|
||||
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
|
||||
* 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 */
|
||||
lua_pushvalue(L, idx);
|
||||
|
@ -555,7 +553,7 @@ luaA_isloop(lua_State *L, int idx)
|
|||
/* remove pushed table */
|
||||
lua_pop(L, 1);
|
||||
|
||||
void_array_wipe(&elems);
|
||||
cptr_array_wipe(&elems);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
|
27
luaa.h
27
luaa.h
|
@ -50,12 +50,6 @@
|
|||
luaL_typerror(L, n, "table"); \
|
||||
} while(0)
|
||||
|
||||
#define luaA_checkfunction(L, n) \
|
||||
do { \
|
||||
if(!lua_isfunction(L, n)) \
|
||||
luaL_typerror(L, n, "function"); \
|
||||
} while(0)
|
||||
|
||||
#define luaA_checkscreen(screen) \
|
||||
do { \
|
||||
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);
|
||||
}
|
||||
|
||||
/** 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.
|
||||
* \param L The Lua stack.
|
||||
* \param ref The function reference.
|
||||
|
|
Loading…
Reference in New Issue