luaobject: add and use item system

Now, each object can store items.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-07-28 10:29:30 +02:00
parent 86cfe51540
commit 339fb53d56
19 changed files with 472 additions and 247 deletions

View File

@ -74,6 +74,7 @@ set(AWE_SRCS
${SOURCE_DIR}/common/xutil.c
${SOURCE_DIR}/common/xcursor.c
${SOURCE_DIR}/common/backtrace.c
${SOURCE_DIR}/common/luaobject.c
${SOURCE_DIR}/widgets/graph.c
${SOURCE_DIR}/widgets/progressbar.c
${SOURCE_DIR}/widgets/textbox.c

View File

@ -24,26 +24,6 @@
#include "common/tokenize.h"
DO_LUA_TOSTRING(button_t, button, "button")
LUA_OBJECT_FUNCS(button_t, button, "button")
void
button_unref_simplified(button_t **b)
{
button_unref(globalconf.L, *b);
}
/** Collect a button.
* \param L The Lua VM state.
* \return 0.
*/
static int
luaA_button_gc(lua_State *L)
{
button_t *button = luaL_checkudata(L, 1, "button");
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, button->press);
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, button->release);
return luaA_object_gc(L);
}
/** Create a new mouse button bindings.
* \param L The Lua VM state.
@ -60,7 +40,8 @@ luaA_button_new(lua_State *L)
{
xcb_button_t xbutton;
button_t *button;
luaA_ref press = LUA_REFNIL, release = LUA_REFNIL;
lua_settop(L, 5);
luaA_checktable(L, 2);
/* arg 3 is mouse button */
@ -69,19 +50,13 @@ luaA_button_new(lua_State *L)
/* arg 4 and 5 are callback functions, check they are functions... */
if(!lua_isnil(L, 4))
luaA_checkfunction(L, 4);
if(lua_gettop(L) == 5 && !lua_isnil(L, 5))
if(!lua_isnil(L, 5))
luaA_checkfunction(L, 5);
/* ... then register (can't register before since 5 maybe not nil but not a
* function */
if(!lua_isnil(L, 4))
luaA_registerfct(L, 4, &press);
if(lua_gettop(L) == 5 && !lua_isnil(L, 5))
luaA_registerfct(L, 5, &release);
button = button_new(L);
button->press = press;
button->release = release;
button->press = luaA_object_ref_item(L, -1, 4);
button->release = luaA_object_ref_item(L, -1, 4);
button->button = xbutton;
button->mod = luaA_tomodifiers(L, 2);
@ -90,32 +65,42 @@ luaA_button_new(lua_State *L)
/** Set a button array with a Lua table.
* \param L The Lua VM state.
* \param oidx The index of the object to store items into.
* \param idx The index of the Lua table.
* \param buttons The array button to fill.
*/
void
luaA_button_array_set(lua_State *L, int idx, button_array_t *buttons)
luaA_button_array_set(lua_State *L, int oidx, int idx, button_array_t *buttons)
{
luaA_checktable(L, idx);
foreach(button, *buttons)
luaA_object_unref_item(L, oidx, *button);
button_array_wipe(buttons);
button_array_init(buttons);
lua_pushnil(L);
while(lua_next(L, idx))
button_array_append(buttons, button_ref(L, -1));
if(luaA_toudata(L, -1, "button"))
button_array_append(buttons, luaA_object_ref_item(L, oidx, -1));
else
lua_pop(L, 1);
}
/** Push an array of button as an Lua table onto the stack.
* \param L The Lua VM state.
* \param oidx The index of the object to get items from.
* \param buttons The button array to push.
* \return The number of elements pushed on stack.
*/
int
luaA_button_array_get(lua_State *L, button_array_t *buttons)
luaA_button_array_get(lua_State *L, int oidx, button_array_t *buttons)
{
lua_createtable(L, buttons->len, 0);
for(int i = 0; i < buttons->len; i++)
{
button_push(L, buttons->tab[i]);
luaA_object_push_item(L, oidx, buttons->tab[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
@ -144,17 +129,9 @@ luaA_button_index(lua_State *L)
switch(a_tokenize(attr, len))
{
case A_TK_PRESS:
if(button->press != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, button->press);
else
lua_pushnil(L);
break;
return luaA_object_push_item(L, 1, button->press);
case A_TK_RELEASE:
if(button->release != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, button->release);
else
lua_pushnil(L);
break;
return luaA_object_push_item(L, 1, button->release);
case A_TK_BUTTON:
lua_pushnumber(L, button->button);
break;
@ -186,10 +163,14 @@ luaA_button_newindex(lua_State *L)
switch(a_tokenize(attr, len))
{
case A_TK_PRESS:
luaA_registerfct(L, 3, &button->press);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, button->press);
button->press = luaA_object_ref_item(L, 1, 3);
break;
case A_TK_RELEASE:
luaA_registerfct(L, 3, &button->release);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, button->release);
button->release = luaA_object_ref_item(L, 1, 3);
break;
case A_TK_BUTTON:
button->button = luaL_checknumber(L, 3);
@ -213,7 +194,7 @@ const struct luaL_reg awesome_button_meta[] =
{
{ "__index", luaA_button_index },
{ "__newindex", luaA_button_newindex },
{ "__gc", luaA_button_gc },
{ "__gc", luaA_object_gc },
{ "__tostring", luaA_button_tostring },
{ NULL, NULL }
};

View File

@ -33,16 +33,16 @@ struct button_t
/** Mouse button number */
xcb_button_t button;
/** Lua function to execute on press. */
luaA_ref press;
void *press;
/** Lua function to execute on release. */
luaA_ref release;
void *release;
};
void button_unref_simplified(button_t **);
ARRAY_FUNCS(button_t *, button, button_unref_simplified)
ARRAY_FUNCS(button_t *, button, DO_NOTHING)
LUA_OBJECT_FUNCS(button_t, button, "button")
int luaA_button_array_get(lua_State *, button_array_t *);
void luaA_button_array_set(lua_State *, int idx, button_array_t *);
int luaA_button_array_get(lua_State *, int, button_array_t *);
void luaA_button_array_set(lua_State *, int, int, button_array_t *);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -53,7 +53,6 @@ luaA_client_gc(lua_State *L)
client_t *c = luaL_checkudata(L, 1, "client");
button_array_wipe(&c->buttons);
key_array_wipe(&c->keys);
image_unref(L, c->icon);
xcb_get_wm_protocols_reply_wipe(&c->protocols);
p_delete(&c->class);
p_delete(&c->startup_id);
@ -517,7 +516,11 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, int phys_screen,
client_setborder(c, wgeom->border_width);
if(ewmh_window_icon_get_reply(ewmh_icon_cookie))
c->icon = image_ref(globalconf.L, -1);
{
client_push(globalconf.L, c);
c->icon = luaA_object_ref_item(globalconf.L, -1, -2);
lua_pop(globalconf.L, 1);
}
/* we honor size hints by default */
c->size_hints_honor = true;
@ -1492,9 +1495,9 @@ luaA_client_newindex(lua_State *L)
client_setmaxvert(c, luaA_checkboolean(L, 3));
break;
case A_TK_ICON:
image_unref(L, c->icon);
luaA_object_unref_item(L, 1, c->icon);
c->icon = NULL;
c->icon = image_ref(L, 3);
c->icon = luaA_object_ref_item(L, 1, 3);
/* execute hook */
hook_property(client, c, "icon");
break;
@ -1733,7 +1736,7 @@ luaA_client_index(lua_State *L)
lua_pushboolean(L, c->ismaxvert);
break;
case A_TK_ICON:
image_push(L, c->icon);
luaA_object_push_item(L, 1, c->icon);
break;
case A_TK_OPACITY:
if((d = window_opacity_get(c->win)) >= 0)
@ -1909,11 +1912,11 @@ luaA_client_buttons(lua_State *L)
button_array_t *buttons = &client->buttons;
if(lua_gettop(L) == 2)
luaA_button_array_set(L, 2, buttons);
luaA_button_array_set(L, 1, 2, buttons);
window_buttons_grab(client->win, &client->buttons);
return luaA_button_array_get(L, buttons);
return luaA_button_array_get(L, 1, buttons);
}
/** Get or set keys bindings for a client.
@ -1932,12 +1935,12 @@ luaA_client_keys(lua_State *L)
if(lua_gettop(L) == 2)
{
luaA_key_array_set(L, 2, keys);
luaA_key_array_set(L, 1, 2, keys);
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->win, XCB_BUTTON_MASK_ANY);
window_grabkeys(c->win, keys);
}
return luaA_key_array_get(L, keys);
return luaA_key_array_get(L, 1, keys);
}
/* Client module.

123
common/luaobject.c Normal file
View File

@ -0,0 +1,123 @@
/*
* luaobject.c - useful functions for handling Lua objects
*
* 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.
*
*/
#include "common/luaobject.h"
/** Increment a object reference in its store table.
* \param L The Lua VM state.
* \param tud The table index on the stack.
* \param oud The object index on the stack.
* \return A pointer to the object.
*/
void *
luaA_object_incref(lua_State *L, int tud, int oud)
{
/* Get pointer value of the item */
void *pointer = (void *) lua_topointer(L, oud);
/* Not referencable. */
if(!pointer)
{
lua_remove(L, oud);
return NULL;
}
/* Push the pointer (key) */
lua_pushlightuserdata(L, pointer);
/* Push the data (value) */
lua_pushvalue(L, oud < 0 ? oud - 1 : oud);
/* table.lightudata = data */
lua_rawset(L, tud < 0 ? tud - 2 : tud);
/* refcount++ */
/* Get the metatable */
lua_getmetatable(L, tud);
/* Push the pointer (key) */
lua_pushlightuserdata(L, pointer);
/* Get the number of references */
lua_rawget(L, -2);
/* Get the number of references and increment it */
int count = lua_tonumber(L, -1) + 1;
lua_pop(L, 1);
/* Push the pointer (key) */
lua_pushlightuserdata(L, pointer);
/* Push count (value) */
lua_pushinteger(L, count);
/* Set metatable[pointer] = count */
lua_rawset(L, -3);
/* Pop metatable */
lua_pop(L, 1);
/* Remove referenced item */
lua_remove(L, oud);
return pointer;
}
/** Decrement a object reference in its store table.
* \param L The Lua VM state.
* \param tud The table index on the stack.
* \param oud The object index on the stack.
* \return A pointer to the object.
*/
void
luaA_object_decref(lua_State *L, int tud, void *pointer)
{
if(!pointer)
return;
/* First, refcount-- */
/* Get the metatable */
lua_getmetatable(L, tud);
/* Push the pointer (key) */
lua_pushlightuserdata(L, pointer);
/* Get the number of references */
lua_rawget(L, -2);
/* Get the number of references and decrement it */
int count = lua_tonumber(L, -1) - 1;
lua_pop(L, 1);
/* Push the pointer (key) */
lua_pushlightuserdata(L, pointer);
/* Hasn't the ref reached 0? */
if(count)
lua_pushinteger(L, count);
else
/* Yup, delete it, set nil as value */
lua_pushnil(L);
/* Set meta[pointer] = count/nil */
lua_rawset(L, -3);
/* Pop metatable */
lua_pop(L, 1);
/* Wait, no more ref? */
if(!count)
{
/* Yes? So remove it from table */
lua_pushlightuserdata(L, pointer);
/* Push nil as value */
lua_pushnil(L);
/* table[pointer] = nil */
lua_rawset(L, tud < 0 ? tud - 2 : tud);
}
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View File

@ -25,9 +25,6 @@
#include <lauxlib.h>
#include "common/array.h"
/** Type for Lua references */
typedef int luaA_ref;
static inline int
luaA_settype(lua_State *L, const char *type)
{
@ -36,10 +33,66 @@ luaA_settype(lua_State *L, const char *type)
return 1;
}
DO_ARRAY(luaA_ref, luaA_ref, DO_NOTHING)
void * luaA_object_incref(lua_State *, int, int);
void luaA_object_decref(lua_State *, int, void *);
/** Store an item in the environment table of an object.
* \param L The Lua VM state.
* \param ud The index of the object on the stack.
* \param iud The index of the item on the stack.
* \return The item reference.
*/
static inline void *
luaA_object_ref_item(lua_State *L, int ud, int iud)
{
/* Get the env table from the object */
lua_getfenv(L, ud);
void *pointer = luaA_object_incref(L, -1, iud < 0 ? iud - 1 : iud);
/* Remove env table */
lua_pop(L, 1);
return pointer;
}
/** Unref an item from the environment table of an object.
* \param L The Lua VM state.
* \param ud The index of the object on the stack.
* \param ref item.
*/
static inline void
luaA_object_unref_item(lua_State *L, int ud, void *pointer)
{
/* Get the env table from the object */
lua_getfenv(L, ud);
/* Decrement */
luaA_object_decref(L, -1, pointer);
/* Remove env table */
lua_pop(L, 1);
}
/** Push an object item on the stack.
* \param L The Lua VM state.
* \param ud The object index on the stack.
* \param pointer The item pointer.
* \return The number of element pushed on stack.
*/
static inline int
luaA_object_push_item(lua_State *L, int ud, void *pointer)
{
/* Get env table of the object */
lua_getfenv(L, ud);
/* Push key */
lua_pushlightuserdata(L, pointer);
/* Get env.pointer */
lua_rawget(L, -2);
/* Remove env table */
lua_remove(L, -2);
return 1;
}
DO_ARRAY(int, int, DO_NOTHING)
#define LUA_OBJECT_HEADER \
luaA_ref_array_t refs;
int_array_t refs;
/** Generic type for all objects.
* All Lua objects can be casted to this type.
@ -56,6 +109,10 @@ typedef struct
type *p = lua_newuserdata(L, sizeof(type)); \
p_clear(p, 1); \
luaA_settype(L, lua_type); \
lua_newtable(L); \
lua_newtable(L); \
lua_setmetatable(L, -2); \
lua_setfenv(L, -2); \
return p; \
} \
\
@ -79,7 +136,7 @@ typedef struct
return NULL; \
type *item = luaL_checkudata(L, ud, lua_type); \
lua_pushvalue(L, ud); \
luaA_ref_array_append(&item->refs, luaL_ref(L, LUA_REGISTRYINDEX)); \
int_array_append(&item->refs, luaL_ref(L, LUA_REGISTRYINDEX)); \
lua_remove(L, ud); \
return item; \
} \
@ -91,10 +148,20 @@ typedef struct
{ \
assert(item->refs.len); \
luaL_unref(L, LUA_REGISTRYINDEX, item->refs.tab[0]); \
luaA_ref_array_take(&item->refs, 0); \
int_array_take(&item->refs, 0); \
} \
} \
\
static inline int \
prefix##_push_item(lua_State *L, type *item, void *ref) \
{ \
prefix##_push(L, item); \
luaA_object_push_item(L, -1, ref); \
lua_remove(L, -2); \
return 1; \
}
/** Garbage collect a Lua object.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
@ -103,7 +170,7 @@ static inline int
luaA_object_gc(lua_State *L)
{
lua_object_t *item = lua_touserdata(L, 1);
luaA_ref_array_wipe(&item->refs);
int_array_wipe(&item->refs);
return 0;
}

76
event.c
View File

@ -42,10 +42,11 @@
#include "common/atoms.h"
#include "common/xutil.h"
#define DO_EVENT_HOOK_CALLBACK(xcbtype, xcbeventprefix, type, arraytype, match) \
#define DO_EVENT_HOOK_CALLBACK(type, xcbeventprefix, arraytype, match) \
static void \
event_##xcbtype##_callback(xcb_##xcbtype##_press_event_t *ev, \
event_##type##_callback(xcb_##type##_press_event_t *ev, \
arraytype *arr, \
int oud, \
int nargs, \
void *data) \
{ \
@ -54,19 +55,37 @@
switch(ev->response_type) \
{ \
case xcbeventprefix##_PRESS: \
if((*item)->press != LUA_REFNIL) \
if((*item)->press) \
{ \
for(int i = 0; i < nargs; i++) \
lua_pushvalue(globalconf.L, - nargs); \
luaA_dofunction_from_registry(globalconf.L, (*item)->press, nargs, 0); \
if(oud) \
{ \
luaA_object_push_item(globalconf.L, oud < 0 ? oud - nargs : oud, \
(*item)); \
luaA_object_push_item(globalconf.L, -1, (*item)->press); \
lua_remove(globalconf.L, -2); \
} \
else \
type##_push_item(globalconf.L, *item, (*item)->press); \
luaA_dofunction(globalconf.L, nargs, 0); \
} \
break; \
case xcbeventprefix##_RELEASE: \
if((*item)->release != LUA_REFNIL) \
if((*item)->release) \
{ \
for(int i = 0; i < nargs; i++) \
lua_pushvalue(globalconf.L, - nargs); \
luaA_dofunction_from_registry(globalconf.L, (*item)->release, nargs, 0); \
if(oud) \
{ \
luaA_object_push_item(globalconf.L, oud < 0 ? oud - nargs : oud, \
(*item)); \
luaA_object_push_item(globalconf.L, -1, (*item)->release); \
lua_remove(globalconf.L, -2); \
} \
else \
type##_push_item(globalconf.L, *item, (*item)->release); \
luaA_dofunction(globalconf.L, nargs, 0); \
} \
break; \
} \
@ -90,8 +109,8 @@ event_key_match(xcb_key_press_event_t *ev, keyb_t *k, void *data)
&& (k->mod == XCB_BUTTON_MASK_ANY || k->mod == ev->state));
}
DO_EVENT_HOOK_CALLBACK(button, XCB_BUTTON, button_t, button_array_t, event_button_match)
DO_EVENT_HOOK_CALLBACK(key, XCB_KEY, keyb_t, key_array_t, event_key_match)
DO_EVENT_HOOK_CALLBACK(button, XCB_BUTTON, button_array_t, event_button_match)
DO_EVENT_HOOK_CALLBACK(key, XCB_KEY, key_array_t, event_key_match)
/** Handle an event with mouse grabber if needed
* \param x The x coordinate.
@ -153,7 +172,7 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
}
wibox_push(globalconf.L, wibox);
event_button_callback(ev, &wibox->buttons, 1, NULL);
event_button_callback(ev, &wibox->buttons, -1, 1, NULL);
/* then try to match a widget binding */
widget_t *w = widget_getbycoords(wibox->sw.orientation, &wibox->widgets,
@ -164,13 +183,13 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
{
widget_push(globalconf.L, w);
wibox_push(globalconf.L, wibox);
event_button_callback(ev, &w->buttons, 2, NULL);
event_button_callback(ev, &w->buttons, -2, 2, NULL);
}
}
else if((c = client_getbywin(ev->event)))
{
client_push(globalconf.L, c);
event_button_callback(ev, &c->buttons, 1, NULL);
event_button_callback(ev, &c->buttons, -1, 1, NULL);
xcb_allow_events(globalconf.connection,
XCB_ALLOW_REPLAY_POINTER,
XCB_CURRENT_TIME);
@ -179,7 +198,7 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
for(screen = 0; screen < nb_screen; screen++)
if(xutil_screen_get(connection, screen)->root == ev->event)
{
event_button_callback(ev, &globalconf.buttons, 0, NULL);
event_button_callback(ev, &globalconf.buttons, 0, 0, NULL);
return 0;
}
@ -343,21 +362,23 @@ event_handle_widget_motionnotify(void *object,
{
if(*mouse_over)
{
if((*mouse_over)->mouse_leave != LUA_REFNIL)
if((*mouse_over)->mouse_leave)
{
/* call mouse leave function on old widget */
widget_push(globalconf.L, *mouse_over);
luaA_dofunction_from_registry(globalconf.L, (*mouse_over)->mouse_leave, 1, 0);
widget_push_item(globalconf.L, *mouse_over, (*mouse_over)->mouse_leave);
luaA_dofunction(globalconf.L, 1, 0);
}
}
if(widget)
{
/* call mouse enter function on new widget and register it */
*mouse_over = widget;
if(widget->mouse_enter != LUA_REFNIL)
if(widget->mouse_enter)
{
widget_push(globalconf.L, widget);
luaA_dofunction_from_registry(globalconf.L, widget->mouse_enter, 1, 0);
widget_push_item(globalconf.L, widget, widget->mouse_enter);
luaA_dofunction(globalconf.L, 1, 0);
}
}
}
@ -418,17 +439,21 @@ event_handle_leavenotify(void *data __attribute__ ((unused)),
{
if(wibox->mouse_over)
{
if(wibox->mouse_over->mouse_leave != LUA_REFNIL)
if(wibox->mouse_over->mouse_leave)
{
/* call mouse leave function on widget the mouse was over */
wibox_push(globalconf.L, wibox);
luaA_dofunction_from_registry(globalconf.L, wibox->mouse_over->mouse_leave, 1, 0);
widget_push_item(globalconf.L, wibox->mouse_over, wibox->mouse_over->mouse_leave);
luaA_dofunction(globalconf.L, 1, 0);
}
wibox->mouse_over = NULL;
}
if(wibox->mouse_leave != LUA_REFNIL)
luaA_dofunction_from_registry(globalconf.L, wibox->mouse_leave, 0, 0);
if(wibox->mouse_leave)
{
wibox_push_item(globalconf.L, wibox, wibox->mouse_leave);
luaA_dofunction(globalconf.L, 0, 0);
}
}
return 0;
@ -459,8 +484,11 @@ event_handle_enternotify(void *data __attribute__ ((unused)),
if(w)
event_handle_widget_motionnotify(wibox, &wibox->mouse_over, w);
if(wibox->mouse_enter != LUA_REFNIL)
luaA_dofunction_from_registry(globalconf.L, wibox->mouse_enter, 0, 0);
if(wibox->mouse_enter)
{
wibox_push_item(globalconf.L, wibox, wibox->mouse_enter);
luaA_dofunction(globalconf.L, 0, 0);
}
}
if((c = client_getbytitlebarwin(ev->event))
@ -562,10 +590,10 @@ event_handle_key(void *data __attribute__ ((unused)),
if((c = client_getbywin(ev->event)))
{
client_push(globalconf.L, c);
event_key_callback(ev, &c->keys, 1, &keysym);
event_key_callback(ev, &c->keys, -1, 1, &keysym);
}
else
event_key_callback(ev, &globalconf.keys, 0, &keysym);
event_key_callback(ev, &globalconf.keys, 0, 0, &keysym);
}
return 0;

69
key.c
View File

@ -31,29 +31,8 @@
#include "common/xutil.h"
#include "common/tokenize.h"
LUA_OBJECT_FUNCS(keyb_t, key, "key")
void
key_unref_simplified(keyb_t **b)
{
key_unref(globalconf.L, *b);
}
DO_LUA_TOSTRING(keyb_t, key, "key")
/** Garbage collect a key.
* \param L The Lua VM state.
* \return 0.
*/
static int
luaA_key_gc(lua_State *L)
{
keyb_t *kbp = luaL_checkudata(L, 1, "key");
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, kbp->press);
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, kbp->release);
return luaA_object_gc(L);
}
/** Grab key on a window.
* \param win The window.
* \param k The key.
@ -1026,7 +1005,9 @@ luaA_key_new(lua_State *L)
size_t len;
keyb_t *k;
const char *key;
luaA_ref press = LUA_REFNIL, release = LUA_REFNIL;
/* be sure there's 5 arguments */
lua_settop(L, 5);
/* arg 2 is key mod table */
luaA_checktable(L, 2);
@ -1034,17 +1015,15 @@ luaA_key_new(lua_State *L)
key = luaL_checklstring(L, 3, &len);
if(!lua_isnil(L, 4))
luaA_registerfct(L, 4, &press);
luaA_checkfunction(L, 4);
if(lua_gettop(L) == 5 && !lua_isnil(L, 5))
luaA_registerfct(L, 5, &release);
if(!lua_isnil(L, 5))
luaA_checkfunction(L, 5);
k = key_new(L);
k->press = luaA_object_ref_item(L, -1, 4);
k->release = luaA_object_ref_item(L, -1, 4);
luaA_keystore(k, key, len);
k->press = press;
k->release = release;
k->mod = luaA_tomodifiers(L, 2);
return 1;
@ -1052,34 +1031,42 @@ luaA_key_new(lua_State *L)
/** Set a key array with a Lua table.
* \param L The Lua VM state.
* \param oidx The index of the object to store items into.
* \param idx The index of the Lua table.
* \param keys The array key to fill.
*/
void
luaA_key_array_set(lua_State *L, int idx, key_array_t *keys)
luaA_key_array_set(lua_State *L, int oidx, int idx, key_array_t *keys)
{
luaA_checktable(L, idx);
foreach(key, *keys)
luaA_object_unref_item(L, oidx, *key);
key_array_wipe(keys);
key_array_init(keys);
lua_pushnil(L);
while(lua_next(L, idx))
key_array_append(keys, key_ref(L, -1));
if(luaA_toudata(L, -1, "key"))
key_array_append(keys, luaA_object_ref_item(L, oidx, -1));
else
lua_pop(L, 1);
}
/** Push an array of key as an Lua table onto the stack.
* \param L The Lua VM state.
* \param oidx The index of the object to get items from.
* \param keys The key array to push.
* \return The number of elements pushed on stack.
*/
int
luaA_key_array_get(lua_State *L, key_array_t *keys)
luaA_key_array_get(lua_State *L, int oidx, key_array_t *keys)
{
lua_createtable(L, keys->len, 0);
for(int i = 0; i < keys->len; i++)
{
key_push(L, keys->tab[i]);
luaA_object_push_item(L, oidx, keys->tab[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
@ -1182,11 +1169,9 @@ luaA_key_index(lua_State *L)
luaA_pushmodifiers(L, k->mod);
break;
case A_TK_PRESS:
lua_rawgeti(L, LUA_REGISTRYINDEX, k->press);
break;
return luaA_object_push_item(L, 1, k->press);
case A_TK_RELEASE:
lua_rawgeti(L, LUA_REGISTRYINDEX, k->release);
break;
return luaA_object_push_item(L, 1, k->release);
default:
break;
}
@ -1217,10 +1202,14 @@ luaA_key_newindex(lua_State *L)
k->mod = luaA_tomodifiers(L, 3);
break;
case A_TK_PRESS:
luaA_registerfct(L, 3, &k->press);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, k->press);
k->press = luaA_object_ref_item(L, 1, 3);
break;
case A_TK_RELEASE:
luaA_registerfct(L, 3, &k->release);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, k->release);
k->release = luaA_object_ref_item(L, 1, 3);
break;
default:
break;
@ -1238,7 +1227,7 @@ const struct luaL_reg awesome_key_meta[] =
{ "__tostring", luaA_key_tostring },
{ "__index", luaA_key_index },
{ "__newindex", luaA_key_newindex },
{ "__gc", luaA_key_gc },
{ "__gc", luaA_object_gc },
{ NULL, NULL },
};

13
key.h
View File

@ -34,20 +34,19 @@ typedef struct keyb_t
/** Keycode */
xcb_keycode_t keycode;
/** Lua function to execute on press */
luaA_ref press;
void *press;
/** Lua function to execute on release */
luaA_ref release;
void *release;
} keyb_t;
void key_unref_simplified(keyb_t **);
DO_ARRAY(keyb_t *, key, key_unref_simplified)
DO_ARRAY(keyb_t *, key, DO_NOTHING)
LUA_OBJECT_FUNCS(keyb_t, key, "key")
bool key_press_lookup_string(xcb_keysym_t, char *, ssize_t);
xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
void luaA_key_array_set(lua_State *, int, key_array_t *);
int luaA_key_array_get(lua_State *, key_array_t *);
void luaA_key_array_set(lua_State *, int, int, key_array_t *);
int luaA_key_array_get(lua_State *, int, key_array_t *);
void window_grabkeys(xcb_window_t, key_array_t *);
int luaA_pushmodifiers(lua_State *, uint16_t);

12
luaa.h
View File

@ -198,13 +198,13 @@ luaA_usemetatable(lua_State *L, int idxobj, int idxfield)
/** Register an Lua object.
* \param L The Lua stack.
* \param idx Index of the object in the stack.
* \param ref A luaA_ref address: it will be filled with the luaA_ref
* \param ref A int address: it will be filled with the int
* registered. If the adresse point to an already registered object, it will
* be unregistered.
* \return Always 0.
*/
static inline int
luaA_register(lua_State *L, int idx, luaA_ref *ref)
luaA_register(lua_State *L, int idx, int *ref)
{
lua_pushvalue(L, idx);
if(*ref != LUA_REFNIL)
@ -218,7 +218,7 @@ luaA_register(lua_State *L, int idx, luaA_ref *ref)
* \param ref A reference to an Lua object.
*/
static inline void
luaA_unregister(lua_State *L, luaA_ref *ref)
luaA_unregister(lua_State *L, int *ref)
{
luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = LUA_REFNIL;
@ -227,13 +227,13 @@ luaA_unregister(lua_State *L, luaA_ref *ref)
/** Register a function.
* \param L The Lua stack.
* \param idx Index of the function in the stack.
* \param fct A luaA_ref address: it will be filled with the luaA_ref
* \param fct A int address: it will be filled with the int
* registered. If the adresse point to an already registered function, it will
* be unregistered.
* \return luaA_register value.
*/
static inline int
luaA_registerfct(lua_State *L, int idx, luaA_ref *fct)
luaA_registerfct(lua_State *L, int idx, int *fct)
{
luaA_checkfunction(L, idx);
return luaA_register(L, idx, fct);
@ -268,7 +268,7 @@ luaA_dofunction(lua_State *L, int nargs, int nret)
* \return True on no error, false otherwise.
*/
static inline bool
luaA_dofunction_from_registry(lua_State *L, luaA_ref ref, int nargs, int nret)
luaA_dofunction_from_registry(lua_State *L, int ref, int nargs, int nret)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
return luaA_dofunction(L, nargs, nret);

View File

@ -353,11 +353,14 @@ property_handle_net_wm_icon(void *data,
if(c)
{
image_unref(globalconf.L, c->icon);
client_push(globalconf.L, c);
luaA_object_unref_item(globalconf.L, 1, c->icon);
if(ewmh_window_icon_from_reply(reply))
c->icon = image_ref(globalconf.L, -1);
c->icon = luaA_object_ref_item(globalconf.L, -2, -1);
else
c->icon = NULL;
/* remove client */
lua_pop(globalconf.L, 1);
/* execute hook */
hook_property(client, c, "icon");
}

48
root.c
View File

@ -114,7 +114,17 @@ luaA_root_keys(lua_State *L)
{
if(lua_gettop(L) == 1)
{
luaA_key_array_set(L, 1, &globalconf.keys);
luaA_checktable(L, 1);
foreach(key, globalconf.keys)
key_unref(globalconf.L, *key);
key_array_wipe(&globalconf.keys);
key_array_init(&globalconf.keys);
lua_pushnil(L);
while(lua_next(L, 1))
key_array_append(&globalconf.keys, key_ref(L, -1));
int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
@ -124,9 +134,18 @@ luaA_root_keys(lua_State *L)
xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, s->root, XCB_BUTTON_MASK_ANY);
window_grabkeys(s->root, &globalconf.keys);
}
return 1;
}
return luaA_key_array_get(L, &globalconf.keys);
lua_createtable(L, globalconf.keys.len, 0);
for(int i = 0; i < globalconf.keys.len; i++)
{
key_push(L, globalconf.keys.tab[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
/** Get or set global mouse bindings.
@ -141,9 +160,30 @@ static int
luaA_root_buttons(lua_State *L)
{
if(lua_gettop(L) == 1)
luaA_button_array_set(L, 1, &globalconf.buttons);
{
luaA_checktable(L, 1);
return luaA_button_array_get(L, &globalconf.buttons);
foreach(button, globalconf.buttons)
button_unref(globalconf.L, *button);
button_array_wipe(&globalconf.buttons);
button_array_init(&globalconf.buttons);
lua_pushnil(L);
while(lua_next(L, 1))
button_array_append(&globalconf.buttons, button_ref(L, -1));
return 1;
}
lua_createtable(L, globalconf.buttons.len, 0);
for(int i = 0; i < globalconf.buttons.len; i++)
{
button_push(L, globalconf.buttons.tab[i]);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
/** Set the root cursor.

View File

@ -97,34 +97,34 @@ struct awesome_t
struct
{
/** Command to execute when spawning a new client */
luaA_ref manage;
int manage;
/** Command to execute when unmanaging client */
luaA_ref unmanage;
int unmanage;
/** Command to execute when giving focus to a client */
luaA_ref focus;
int focus;
/** Command to execute when removing focus to a client */
luaA_ref unfocus;
int unfocus;
/** Command to run when mouse enter a client */
luaA_ref mouse_enter;
int mouse_enter;
/** Command to run when mouse leave a client */
luaA_ref mouse_leave;
int mouse_leave;
/** Command to run when client list changes */
luaA_ref clients;
int clients;
/** Command to run on numbers of tag changes */
luaA_ref tags;
int tags;
/** Command to run when client gets (un)tagged */
luaA_ref tagged;
int tagged;
/** Command to run on property change */
luaA_ref property;
int property;
/** Command to run on time */
luaA_ref timer;
int timer;
/** Command to run on awesome exit */
luaA_ref exit;
int exit;
/** Startup notification hooks */
luaA_ref startup_notification;
int startup_notification;
#ifdef WITH_DBUS
/** Command to run on dbus events */
luaA_ref dbus;
int dbus;
#endif
} hooks;
/** The event loop */
@ -132,9 +132,9 @@ struct awesome_t
/** The timeout after which we need to stop select() */
struct ev_timer timer;
/** The key grabber function */
luaA_ref keygrabber;
int keygrabber;
/** The mouse pointer grabber function */
luaA_ref mousegrabber;
int mousegrabber;
/** Focused screen */
screen_t *screen_focus;
/** Need to call client_stack_refresh() */

69
wibox.c
View File

@ -41,10 +41,6 @@ luaA_wibox_gc(lua_State *L)
p_delete(&wibox->cursor);
simplewindow_wipe(&wibox->sw);
button_array_wipe(&wibox->buttons);
image_unref(L, wibox->bg_image);
luaL_unref(L, LUA_REGISTRYINDEX, wibox->widgets_table);
luaL_unref(L, LUA_REGISTRYINDEX, wibox->mouse_enter);
luaL_unref(L, LUA_REGISTRYINDEX, wibox->mouse_leave);
widget_node_array_wipe(&wibox->widgets);
return luaA_object_gc(L);
}
@ -472,7 +468,6 @@ luaA_wibox_new(lua_State *L)
luaA_checktable(L, 2);
w = wibox_new(L);
w->widgets_table = LUA_REFNIL;
w->sw.ctx.fg = globalconf.colors.fg;
if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
@ -498,8 +493,6 @@ luaA_wibox_new(lua_State *L)
w->isvisible = true;
w->cursor = a_strdup("left_ptr");
w->mouse_enter = w->mouse_leave = LUA_REFNIL;
for(i = 0; i <= reqs_nbr; i++)
xcolor_init_reply(reqs[i]);
@ -514,9 +507,11 @@ luaA_wibox_new(lua_State *L)
static bool
luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item)
{
if(wibox->widgets_table != LUA_REFNIL)
if(wibox->widgets_table)
{
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
wibox_push(L, wibox);
luaA_object_push_item(L, -1, wibox->widgets_table);
lua_remove(L, -2);
if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
return true;
}
@ -618,7 +613,7 @@ luaA_wibox_index(lua_State *L)
luaA_pushxcolor(L, &wibox->sw.ctx.bg);
break;
case A_TK_BG_IMAGE:
image_push(L, wibox->bg_image);
luaA_object_push_item(L, 1, wibox->bg_image);
break;
case A_TK_POSITION:
if(wibox->type == WIBOX_TYPE_NORMAL)
@ -632,11 +627,7 @@ luaA_wibox_index(lua_State *L)
lua_pushstring(L, orientation_tostr(wibox->sw.orientation));
break;
case A_TK_WIDGETS:
if(wibox->widgets_table != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->widgets_table);
else
lua_pushnil(L);
break;
return luaA_object_push_item(L, 1, wibox->widgets_table);
case A_TK_CURSOR:
lua_pushstring(L, wibox->cursor);
break;
@ -650,23 +641,13 @@ luaA_wibox_index(lua_State *L)
}
break;
case A_TK_MOUSE_ENTER:
if(wibox->mouse_enter != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->mouse_enter);
else
return 0;
return 1;
return luaA_object_push_item(L, 1, wibox->mouse_enter);
case A_TK_MOUSE_LEAVE:
if(wibox->mouse_leave != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->mouse_leave);
else
return 0;
return 1;
return luaA_object_push_item(L, 1, wibox->mouse_leave);
case A_TK_SHAPE_BOUNDING:
image_push(L, wibox->sw.shape.bounding);
break;
return luaA_object_push_item(L, 1, wibox->sw.shape.bounding);
case A_TK_SHAPE_CLIP:
image_push(L, wibox->sw.shape.clip);
break;
return luaA_object_push_item(L, 1, wibox->sw.shape.clip);
default:
return 0;
}
@ -737,8 +718,8 @@ luaA_wibox_newindex(lua_State *L)
wibox->need_update = true;
break;
case A_TK_BG_IMAGE:
image_unref(L, wibox->bg_image);
wibox->bg_image = image_ref(L, 3);
luaA_object_unref_item(L, 1, wibox->bg_image);
wibox->bg_image = luaA_object_ref_item(L, 1, 3);
wibox->need_update = true;
break;
case A_TK_ALIGN:
@ -850,7 +831,10 @@ luaA_wibox_newindex(lua_State *L)
luaA_warn(L, "table is looping, cannot use this as widget table");
return 0;
}
luaA_register(L, 3, &(wibox->widgets_table));
/* duplicate table because next function will eat it */
lua_pushvalue(L, 3);
/* register object */
wibox->widgets_table = luaA_object_ref_item(L, 1, -1);
wibox_need_update(wibox);
luaA_table2wtable(L);
break;
@ -865,19 +849,23 @@ luaA_wibox_newindex(lua_State *L)
}
break;
case A_TK_MOUSE_ENTER:
luaA_registerfct(L, 3, &wibox->mouse_enter);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, wibox->mouse_enter);
wibox->mouse_enter = luaA_object_ref_item(L, 1, 3);
return 0;
case A_TK_MOUSE_LEAVE:
luaA_registerfct(L, 3, &wibox->mouse_leave);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, wibox->mouse_leave);
wibox->mouse_leave = luaA_object_ref_item(L, 1, 3);
return 0;
case A_TK_SHAPE_BOUNDING:
image_unref(L, wibox->sw.shape.bounding);
wibox->sw.shape.bounding = image_ref(L, 3);
luaA_object_unref_item(L, 1, wibox->sw.shape.bounding);
wibox->sw.shape.bounding = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true;
break;
case A_TK_SHAPE_CLIP:
image_unref(L, wibox->sw.shape.clip);
wibox->sw.shape.clip = image_ref(L, 3);
luaA_object_unref_item(L, 1, wibox->sw.shape.clip);
wibox->sw.shape.clip = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true;
break;
default:
@ -904,15 +892,14 @@ static int
luaA_wibox_buttons(lua_State *L)
{
wibox_t *wibox = luaL_checkudata(L, 1, "wibox");
button_array_t *buttons = &wibox->buttons;
if(lua_gettop(L) == 2)
{
luaA_button_array_set(L, 2, buttons);
luaA_button_array_set(L, 1, 2, &wibox->buttons);
return 1;
}
return luaA_button_array_get(L, buttons);
return luaA_button_array_get(L, 1, &wibox->buttons);
}
const struct luaL_reg awesome_wibox_methods[] =

View File

@ -52,11 +52,11 @@ struct wibox_t
screen_t *screen;
/** Widget list */
widget_node_array_t widgets;
luaA_ref widgets_table;
void *widgets_table;
/** Widget the mouse is over */
widget_t *mouse_over;
/** Mouse over event handler */
luaA_ref mouse_enter, mouse_leave;
void *mouse_enter, *mouse_leave;
/** Need update */
bool need_update;
/** Need shape update */

View File

@ -45,8 +45,6 @@ luaA_widget_gc(lua_State *L)
if(widget->destructor)
widget->destructor(widget);
button_array_wipe(&widget->buttons);
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, widget->mouse_enter);
luaL_unref(globalconf.L, LUA_REGISTRYINDEX, widget->mouse_leave);
return luaA_object_gc(L);
}
@ -139,9 +137,14 @@ bool
widget_geometries(wibox_t *wibox)
{
/* get the layout field of the widget table */
if (wibox->widgets_table != LUA_REFNIL)
if(wibox->widgets_table)
{
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
/* push wibox */
wibox_push(globalconf.L, wibox);
/* push widgets table */
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
/* remove wibox */
lua_remove(globalconf.L, -2);
lua_getfield(globalconf.L, -1, "layout");
}
else
@ -192,7 +195,12 @@ widget_geometries(wibox_t *wibox)
widget_node_array_wipe(widgets);
widget_node_array_init(widgets);
lua_rawgeti(globalconf.L, LUA_REGISTRYINDEX, wibox->widgets_table);
/* push wibox */
wibox_push(globalconf.L, wibox);
/* push widgets table */
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
/* remove wibox */
lua_remove(globalconf.L, -2);
luaA_table2widgets(globalconf.L, widgets);
lua_pop(globalconf.L, 2);
@ -285,7 +293,12 @@ widget_render(wibox_t *wibox)
widget_node_array_wipe(widgets);
widget_node_array_init(widgets);
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->widgets_table);
/* push wibox */
wibox_push(globalconf.L, wibox);
/* push widgets table */
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
/* remove wibox */
lua_remove(globalconf.L, -2);
luaA_table2widgets(L, widgets);
/* get computed geometries */
@ -435,8 +448,6 @@ luaA_widget_new(lua_State *L)
/* Set visible by default. */
w->isvisible = true;
w->mouse_enter = w->mouse_leave = LUA_REFNIL;
return 1;
}
@ -452,15 +463,14 @@ static int
luaA_widget_buttons(lua_State *L)
{
widget_t *widget = luaL_checkudata(L, 1, "widget");
button_array_t *buttons = &widget->buttons;
if(lua_gettop(L) == 2)
{
luaA_button_array_set(L, 2, buttons);
luaA_button_array_set(L, 1, 2, &widget->buttons);
return 1;
}
return luaA_button_array_get(L, buttons);
return luaA_button_array_get(L, 1, &widget->buttons);
}
/** Generic widget.
@ -488,17 +498,9 @@ luaA_widget_index(lua_State *L)
lua_pushboolean(L, widget->isvisible);
return 1;
case A_TK_MOUSE_ENTER:
if(widget->mouse_enter != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, widget->mouse_enter);
else
return 0;
return 1;
return luaA_object_push_item(L, 1, widget->mouse_enter);
case A_TK_MOUSE_LEAVE:
if(widget->mouse_leave != LUA_REFNIL)
lua_rawgeti(L, LUA_REGISTRYINDEX, widget->mouse_leave);
else
return 0;
return 1;
return luaA_object_push_item(L, 1, widget->mouse_leave);
default:
break;
}
@ -524,10 +526,14 @@ luaA_widget_newindex(lua_State *L)
widget->isvisible = luaA_checkboolean(L, 3);
break;
case A_TK_MOUSE_ENTER:
luaA_registerfct(L, 3, &widget->mouse_enter);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, widget->mouse_enter);
widget->mouse_enter = luaA_object_ref_item(L, 1, 3);
return 0;
case A_TK_MOUSE_LEAVE:
luaA_registerfct(L, 3, &widget->mouse_leave);
luaA_checkfunction(L, 3);
luaA_object_unref_item(L, 1, widget->mouse_leave);
widget->mouse_leave = luaA_object_ref_item(L, 1, 3);
return 0;
default:
return widget->newindex ? widget->newindex(L, token) : 0;

View File

@ -47,7 +47,7 @@ struct widget_t
/** Newindex function */
int (*newindex)(lua_State *, awesome_token_t);
/** Mouse over event handler */
luaA_ref mouse_enter, mouse_leave;
void *mouse_enter, *mouse_leave;
/** Misc private data */
void *data;
/** Button bindings */

View File

@ -88,7 +88,6 @@ static void
imagebox_destructor(widget_t *w)
{
imagebox_data_t *d = w->data;
image_unref(globalconf.L, d->image);
p_delete(&d);
}
@ -111,7 +110,7 @@ luaA_imagebox_index(lua_State *L, awesome_token_t token)
switch(token)
{
case A_TK_IMAGE:
image_push(L, d->image);
luaA_object_push_item(L, 1, d->image);
break;
case A_TK_BG:
luaA_pushcolor(L, &d->bg);
@ -146,8 +145,8 @@ luaA_imagebox_newindex(lua_State *L, awesome_token_t token)
size_t len;
case A_TK_IMAGE:
image_unref(L, d->image);
d->image = image_ref(L, 3);
luaA_object_unref_item(L, 1, d->image);
d->image = luaA_object_ref_item(L, 1, 3);
break;
case A_TK_BG:
if(lua_isnil(L, 3))

View File

@ -138,7 +138,6 @@ static void
textbox_destructor(widget_t *w)
{
textbox_data_t *d = w->data;
image_unref(globalconf.L, d->bg_image);
draw_text_context_wipe(&d->data);
p_delete(&d);
}
@ -272,8 +271,8 @@ luaA_textbox_newindex(lua_State *L, awesome_token_t token)
d->bg_resize = luaA_checkboolean(L, 3);
break;
case A_TK_BG_IMAGE:
image_unref(L, d->bg_image);
d->bg_image = image_ref(L, 3);
luaA_object_unref_item(L, 1, d->bg_image);
d->bg_image = luaA_object_ref_item(L, 1, 3);
break;
case A_TK_BG:
if(lua_isnil(L, 3))