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/xutil.c
${SOURCE_DIR}/common/xcursor.c ${SOURCE_DIR}/common/xcursor.c
${SOURCE_DIR}/common/backtrace.c ${SOURCE_DIR}/common/backtrace.c
${SOURCE_DIR}/common/luaobject.c
${SOURCE_DIR}/widgets/graph.c ${SOURCE_DIR}/widgets/graph.c
${SOURCE_DIR}/widgets/progressbar.c ${SOURCE_DIR}/widgets/progressbar.c
${SOURCE_DIR}/widgets/textbox.c ${SOURCE_DIR}/widgets/textbox.c

View File

@ -24,26 +24,6 @@
#include "common/tokenize.h" #include "common/tokenize.h"
DO_LUA_TOSTRING(button_t, button, "button") 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. /** Create a new mouse button bindings.
* \param L The Lua VM state. * \param L The Lua VM state.
@ -60,7 +40,8 @@ luaA_button_new(lua_State *L)
{ {
xcb_button_t xbutton; xcb_button_t xbutton;
button_t *button; button_t *button;
luaA_ref press = LUA_REFNIL, release = LUA_REFNIL;
lua_settop(L, 5);
luaA_checktable(L, 2); luaA_checktable(L, 2);
/* arg 3 is mouse button */ /* 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... */ /* arg 4 and 5 are callback functions, check they are functions... */
if(!lua_isnil(L, 4)) if(!lua_isnil(L, 4))
luaA_checkfunction(L, 4); luaA_checkfunction(L, 4);
if(lua_gettop(L) == 5 && !lua_isnil(L, 5)) if(!lua_isnil(L, 5))
luaA_checkfunction(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 = 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->button = xbutton;
button->mod = luaA_tomodifiers(L, 2); button->mod = luaA_tomodifiers(L, 2);
@ -90,32 +65,42 @@ luaA_button_new(lua_State *L)
/** Set a button array with a Lua table. /** Set a button array with a Lua table.
* \param L The Lua VM state. * \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 idx The index of the Lua table.
* \param buttons The array button to fill. * \param buttons The array button to fill.
*/ */
void 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); luaA_checktable(L, idx);
foreach(button, *buttons)
luaA_object_unref_item(L, oidx, *button);
button_array_wipe(buttons); button_array_wipe(buttons);
button_array_init(buttons); button_array_init(buttons);
lua_pushnil(L); lua_pushnil(L);
while(lua_next(L, idx)) 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. /** Push an array of button as an Lua table onto the stack.
* \param L The Lua VM state. * \param L The Lua VM state.
* \param oidx The index of the object to get items from.
* \param buttons The button array to push. * \param buttons The button array to push.
* \return The number of elements pushed on stack. * \return The number of elements pushed on stack.
*/ */
int 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); lua_createtable(L, buttons->len, 0);
for(int i = 0; i < buttons->len; i++) 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); lua_rawseti(L, -2, i + 1);
} }
return 1; return 1;
@ -144,17 +129,9 @@ luaA_button_index(lua_State *L)
switch(a_tokenize(attr, len)) switch(a_tokenize(attr, len))
{ {
case A_TK_PRESS: case A_TK_PRESS:
if(button->press != LUA_REFNIL) return luaA_object_push_item(L, 1, button->press);
lua_rawgeti(L, LUA_REGISTRYINDEX, button->press);
else
lua_pushnil(L);
break;
case A_TK_RELEASE: case A_TK_RELEASE:
if(button->release != LUA_REFNIL) return luaA_object_push_item(L, 1, button->release);
lua_rawgeti(L, LUA_REGISTRYINDEX, button->release);
else
lua_pushnil(L);
break;
case A_TK_BUTTON: case A_TK_BUTTON:
lua_pushnumber(L, button->button); lua_pushnumber(L, button->button);
break; break;
@ -186,10 +163,14 @@ luaA_button_newindex(lua_State *L)
switch(a_tokenize(attr, len)) switch(a_tokenize(attr, len))
{ {
case A_TK_PRESS: 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; break;
case A_TK_RELEASE: 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; break;
case A_TK_BUTTON: case A_TK_BUTTON:
button->button = luaL_checknumber(L, 3); button->button = luaL_checknumber(L, 3);
@ -213,7 +194,7 @@ const struct luaL_reg awesome_button_meta[] =
{ {
{ "__index", luaA_button_index }, { "__index", luaA_button_index },
{ "__newindex", luaA_button_newindex }, { "__newindex", luaA_button_newindex },
{ "__gc", luaA_button_gc }, { "__gc", luaA_object_gc },
{ "__tostring", luaA_button_tostring }, { "__tostring", luaA_button_tostring },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -33,16 +33,16 @@ struct button_t
/** Mouse button number */ /** Mouse button number */
xcb_button_t button; xcb_button_t button;
/** Lua function to execute on press. */ /** Lua function to execute on press. */
luaA_ref press; void *press;
/** Lua function to execute on release. */ /** Lua function to execute on release. */
luaA_ref release; void *release;
}; };
void button_unref_simplified(button_t **); ARRAY_FUNCS(button_t *, button, DO_NOTHING)
ARRAY_FUNCS(button_t *, button, button_unref_simplified) LUA_OBJECT_FUNCS(button_t, button, "button")
int luaA_button_array_get(lua_State *, button_array_t *); int luaA_button_array_get(lua_State *, int, button_array_t *);
void luaA_button_array_set(lua_State *, int idx, button_array_t *); void luaA_button_array_set(lua_State *, int, int, button_array_t *);
#endif #endif
// 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

@ -53,7 +53,6 @@ luaA_client_gc(lua_State *L)
client_t *c = luaL_checkudata(L, 1, "client"); client_t *c = luaL_checkudata(L, 1, "client");
button_array_wipe(&c->buttons); button_array_wipe(&c->buttons);
key_array_wipe(&c->keys); key_array_wipe(&c->keys);
image_unref(L, c->icon);
xcb_get_wm_protocols_reply_wipe(&c->protocols); xcb_get_wm_protocols_reply_wipe(&c->protocols);
p_delete(&c->class); p_delete(&c->class);
p_delete(&c->startup_id); 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); client_setborder(c, wgeom->border_width);
if(ewmh_window_icon_get_reply(ewmh_icon_cookie)) 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 */ /* we honor size hints by default */
c->size_hints_honor = true; c->size_hints_honor = true;
@ -1492,9 +1495,9 @@ luaA_client_newindex(lua_State *L)
client_setmaxvert(c, luaA_checkboolean(L, 3)); client_setmaxvert(c, luaA_checkboolean(L, 3));
break; break;
case A_TK_ICON: case A_TK_ICON:
image_unref(L, c->icon); luaA_object_unref_item(L, 1, c->icon);
c->icon = NULL; c->icon = NULL;
c->icon = image_ref(L, 3); c->icon = luaA_object_ref_item(L, 1, 3);
/* execute hook */ /* execute hook */
hook_property(client, c, "icon"); hook_property(client, c, "icon");
break; break;
@ -1733,7 +1736,7 @@ luaA_client_index(lua_State *L)
lua_pushboolean(L, c->ismaxvert); lua_pushboolean(L, c->ismaxvert);
break; break;
case A_TK_ICON: case A_TK_ICON:
image_push(L, c->icon); luaA_object_push_item(L, 1, c->icon);
break; break;
case A_TK_OPACITY: case A_TK_OPACITY:
if((d = window_opacity_get(c->win)) >= 0) if((d = window_opacity_get(c->win)) >= 0)
@ -1909,11 +1912,11 @@ luaA_client_buttons(lua_State *L)
button_array_t *buttons = &client->buttons; button_array_t *buttons = &client->buttons;
if(lua_gettop(L) == 2) 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); 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. /** Get or set keys bindings for a client.
@ -1932,12 +1935,12 @@ luaA_client_keys(lua_State *L)
if(lua_gettop(L) == 2) 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); xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, c->win, XCB_BUTTON_MASK_ANY);
window_grabkeys(c->win, keys); window_grabkeys(c->win, keys);
} }
return luaA_key_array_get(L, keys); return luaA_key_array_get(L, 1, keys);
} }
/* Client module. /* 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 <lauxlib.h>
#include "common/array.h" #include "common/array.h"
/** Type for Lua references */
typedef int luaA_ref;
static inline int static inline int
luaA_settype(lua_State *L, const char *type) luaA_settype(lua_State *L, const char *type)
{ {
@ -36,10 +33,66 @@ luaA_settype(lua_State *L, const char *type)
return 1; 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 \ #define LUA_OBJECT_HEADER \
luaA_ref_array_t refs; int_array_t refs;
/** 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.
@ -56,6 +109,10 @@ typedef struct
type *p = lua_newuserdata(L, sizeof(type)); \ type *p = lua_newuserdata(L, sizeof(type)); \
p_clear(p, 1); \ p_clear(p, 1); \
luaA_settype(L, lua_type); \ luaA_settype(L, lua_type); \
lua_newtable(L); \
lua_newtable(L); \
lua_setmetatable(L, -2); \
lua_setfenv(L, -2); \
return p; \ return p; \
} \ } \
\ \
@ -79,7 +136,7 @@ typedef struct
return NULL; \ return NULL; \
type *item = luaL_checkudata(L, ud, lua_type); \ type *item = luaL_checkudata(L, ud, lua_type); \
lua_pushvalue(L, ud); \ 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); \ lua_remove(L, ud); \
return item; \ return item; \
} \ } \
@ -91,10 +148,20 @@ typedef struct
{ \ { \
assert(item->refs.len); \ assert(item->refs.len); \
luaL_unref(L, LUA_REGISTRYINDEX, item->refs.tab[0]); \ 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. /** Garbage collect a Lua object.
* \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.
@ -103,7 +170,7 @@ static inline int
luaA_object_gc(lua_State *L) luaA_object_gc(lua_State *L)
{ {
lua_object_t *item = lua_touserdata(L, 1); lua_object_t *item = lua_touserdata(L, 1);
luaA_ref_array_wipe(&item->refs); int_array_wipe(&item->refs);
return 0; return 0;
} }

82
event.c
View File

@ -42,31 +42,50 @@
#include "common/atoms.h" #include "common/atoms.h"
#include "common/xutil.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 \ static void \
event_##xcbtype##_callback(xcb_##xcbtype##_press_event_t *ev, \ event_##type##_callback(xcb_##type##_press_event_t *ev, \
arraytype *arr, \ arraytype *arr, \
int nargs, \ int oud, \
void *data) \ int nargs, \
void *data) \
{ \ { \
foreach(item, *arr) \ foreach(item, *arr) \
if(match(ev, *item, data)) \ if(match(ev, *item, data)) \
switch(ev->response_type) \ switch(ev->response_type) \
{ \ { \
case xcbeventprefix##_PRESS: \ case xcbeventprefix##_PRESS: \
if((*item)->press != LUA_REFNIL) \ if((*item)->press) \
{ \ { \
for(int i = 0; i < nargs; i++) \ for(int i = 0; i < nargs; i++) \
lua_pushvalue(globalconf.L, - nargs); \ 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; \ break; \
case xcbeventprefix##_RELEASE: \ case xcbeventprefix##_RELEASE: \
if((*item)->release != LUA_REFNIL) \ if((*item)->release) \
{ \ { \
for(int i = 0; i < nargs; i++) \ for(int i = 0; i < nargs; i++) \
lua_pushvalue(globalconf.L, - nargs); \ 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; \ 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)); && (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(button, XCB_BUTTON, 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(key, XCB_KEY, key_array_t, event_key_match)
/** Handle an event with mouse grabber if needed /** Handle an event with mouse grabber if needed
* \param x The x coordinate. * \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); 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 */ /* then try to match a widget binding */
widget_t *w = widget_getbycoords(wibox->sw.orientation, &wibox->widgets, 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); widget_push(globalconf.L, w);
wibox_push(globalconf.L, wibox); 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))) else if((c = client_getbywin(ev->event)))
{ {
client_push(globalconf.L, c); 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_events(globalconf.connection,
XCB_ALLOW_REPLAY_POINTER, XCB_ALLOW_REPLAY_POINTER,
XCB_CURRENT_TIME); 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++) for(screen = 0; screen < nb_screen; screen++)
if(xutil_screen_get(connection, screen)->root == ev->event) 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; return 0;
} }
@ -343,21 +362,23 @@ event_handle_widget_motionnotify(void *object,
{ {
if(*mouse_over) if(*mouse_over)
{ {
if((*mouse_over)->mouse_leave != LUA_REFNIL) if((*mouse_over)->mouse_leave)
{ {
/* call mouse leave function on old widget */ /* call mouse leave function on old widget */
widget_push(globalconf.L, *mouse_over); 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) if(widget)
{ {
/* call mouse enter function on new widget and register it */ /* call mouse enter function on new widget and register it */
*mouse_over = widget; *mouse_over = widget;
if(widget->mouse_enter != LUA_REFNIL) if(widget->mouse_enter)
{ {
widget_push(globalconf.L, widget); 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)
{ {
if(wibox->mouse_over->mouse_leave != LUA_REFNIL) if(wibox->mouse_over->mouse_leave)
{ {
/* call mouse leave function on widget the mouse was over */ /* call mouse leave function on widget the mouse was over */
wibox_push(globalconf.L, wibox); 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; wibox->mouse_over = NULL;
} }
if(wibox->mouse_leave != LUA_REFNIL) if(wibox->mouse_leave)
luaA_dofunction_from_registry(globalconf.L, wibox->mouse_leave, 0, 0); {
wibox_push_item(globalconf.L, wibox, wibox->mouse_leave);
luaA_dofunction(globalconf.L, 0, 0);
}
} }
return 0; return 0;
@ -459,8 +484,11 @@ event_handle_enternotify(void *data __attribute__ ((unused)),
if(w) if(w)
event_handle_widget_motionnotify(wibox, &wibox->mouse_over, w); event_handle_widget_motionnotify(wibox, &wibox->mouse_over, w);
if(wibox->mouse_enter != LUA_REFNIL) if(wibox->mouse_enter)
luaA_dofunction_from_registry(globalconf.L, wibox->mouse_enter, 0, 0); {
wibox_push_item(globalconf.L, wibox, wibox->mouse_enter);
luaA_dofunction(globalconf.L, 0, 0);
}
} }
if((c = client_getbytitlebarwin(ev->event)) if((c = client_getbytitlebarwin(ev->event))
@ -562,10 +590,10 @@ event_handle_key(void *data __attribute__ ((unused)),
if((c = client_getbywin(ev->event))) if((c = client_getbywin(ev->event)))
{ {
client_push(globalconf.L, c); client_push(globalconf.L, c);
event_key_callback(ev, &c->keys, 1, &keysym); event_key_callback(ev, &c->keys, -1, 1, &keysym);
} }
else else
event_key_callback(ev, &globalconf.keys, 0, &keysym); event_key_callback(ev, &globalconf.keys, 0, 0, &keysym);
} }
return 0; return 0;

69
key.c
View File

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

13
key.h
View File

@ -34,20 +34,19 @@ typedef struct keyb_t
/** Keycode */ /** Keycode */
xcb_keycode_t keycode; xcb_keycode_t keycode;
/** Lua function to execute on press */ /** Lua function to execute on press */
luaA_ref press; void *press;
/** Lua function to execute on release */ /** Lua function to execute on release */
luaA_ref release; void *release;
} keyb_t; } keyb_t;
void key_unref_simplified(keyb_t **); DO_ARRAY(keyb_t *, key, DO_NOTHING)
LUA_OBJECT_FUNCS(keyb_t, key, "key")
DO_ARRAY(keyb_t *, key, key_unref_simplified)
bool key_press_lookup_string(xcb_keysym_t, char *, ssize_t); bool key_press_lookup_string(xcb_keysym_t, char *, ssize_t);
xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t); xcb_keysym_t key_getkeysym(xcb_keycode_t, uint16_t);
void luaA_key_array_set(lua_State *, int, key_array_t *); void luaA_key_array_set(lua_State *, int, int, key_array_t *);
int luaA_key_array_get(lua_State *, key_array_t *); int luaA_key_array_get(lua_State *, int, key_array_t *);
void window_grabkeys(xcb_window_t, key_array_t *); void window_grabkeys(xcb_window_t, key_array_t *);
int luaA_pushmodifiers(lua_State *, uint16_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. /** Register an Lua object.
* \param L The Lua stack. * \param L The Lua stack.
* \param idx Index of the object in the 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 * registered. If the adresse point to an already registered object, it will
* be unregistered. * be unregistered.
* \return Always 0. * \return Always 0.
*/ */
static inline int 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); lua_pushvalue(L, idx);
if(*ref != LUA_REFNIL) 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. * \param ref A reference to an Lua object.
*/ */
static inline void static inline void
luaA_unregister(lua_State *L, luaA_ref *ref) luaA_unregister(lua_State *L, int *ref)
{ {
luaL_unref(L, LUA_REGISTRYINDEX, *ref); luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = LUA_REFNIL; *ref = LUA_REFNIL;
@ -227,13 +227,13 @@ luaA_unregister(lua_State *L, luaA_ref *ref)
/** Register a function. /** Register a function.
* \param L The Lua stack. * \param L The Lua stack.
* \param idx Index of the function in the 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 * registered. If the adresse point to an already registered function, it will
* be unregistered. * be unregistered.
* \return luaA_register value. * \return luaA_register value.
*/ */
static inline int 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); luaA_checkfunction(L, idx);
return luaA_register(L, idx, fct); 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. * \return True on no error, false otherwise.
*/ */
static inline bool 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); lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
return luaA_dofunction(L, nargs, nret); return luaA_dofunction(L, nargs, nret);

View File

@ -353,11 +353,14 @@ property_handle_net_wm_icon(void *data,
if(c) 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)) 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 else
c->icon = NULL; c->icon = NULL;
/* remove client */
lua_pop(globalconf.L, 1);
/* execute hook */ /* execute hook */
hook_property(client, c, "icon"); 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) 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)); 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); xcb_ungrab_key(globalconf.connection, XCB_GRAB_ANY, s->root, XCB_BUTTON_MASK_ANY);
window_grabkeys(s->root, &globalconf.keys); 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. /** Get or set global mouse bindings.
@ -141,9 +160,30 @@ static int
luaA_root_buttons(lua_State *L) luaA_root_buttons(lua_State *L)
{ {
if(lua_gettop(L) == 1) 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. /** Set the root cursor.

View File

@ -97,34 +97,34 @@ struct awesome_t
struct struct
{ {
/** Command to execute when spawning a new client */ /** Command to execute when spawning a new client */
luaA_ref manage; int manage;
/** Command to execute when unmanaging client */ /** Command to execute when unmanaging client */
luaA_ref unmanage; int unmanage;
/** Command to execute when giving focus to a client */ /** Command to execute when giving focus to a client */
luaA_ref focus; int focus;
/** Command to execute when removing focus to a client */ /** Command to execute when removing focus to a client */
luaA_ref unfocus; int unfocus;
/** Command to run when mouse enter a client */ /** Command to run when mouse enter a client */
luaA_ref mouse_enter; int mouse_enter;
/** Command to run when mouse leave a client */ /** Command to run when mouse leave a client */
luaA_ref mouse_leave; int mouse_leave;
/** Command to run when client list changes */ /** Command to run when client list changes */
luaA_ref clients; int clients;
/** Command to run on numbers of tag changes */ /** Command to run on numbers of tag changes */
luaA_ref tags; int tags;
/** Command to run when client gets (un)tagged */ /** Command to run when client gets (un)tagged */
luaA_ref tagged; int tagged;
/** Command to run on property change */ /** Command to run on property change */
luaA_ref property; int property;
/** Command to run on time */ /** Command to run on time */
luaA_ref timer; int timer;
/** Command to run on awesome exit */ /** Command to run on awesome exit */
luaA_ref exit; int exit;
/** Startup notification hooks */ /** Startup notification hooks */
luaA_ref startup_notification; int startup_notification;
#ifdef WITH_DBUS #ifdef WITH_DBUS
/** Command to run on dbus events */ /** Command to run on dbus events */
luaA_ref dbus; int dbus;
#endif #endif
} hooks; } hooks;
/** The event loop */ /** The event loop */
@ -132,9 +132,9 @@ struct awesome_t
/** The timeout after which we need to stop select() */ /** The timeout after which we need to stop select() */
struct ev_timer timer; struct ev_timer timer;
/** The key grabber function */ /** The key grabber function */
luaA_ref keygrabber; int keygrabber;
/** The mouse pointer grabber function */ /** The mouse pointer grabber function */
luaA_ref mousegrabber; int mousegrabber;
/** Focused screen */ /** Focused screen */
screen_t *screen_focus; screen_t *screen_focus;
/** Need to call client_stack_refresh() */ /** 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); p_delete(&wibox->cursor);
simplewindow_wipe(&wibox->sw); simplewindow_wipe(&wibox->sw);
button_array_wipe(&wibox->buttons); 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); widget_node_array_wipe(&wibox->widgets);
return luaA_object_gc(L); return luaA_object_gc(L);
} }
@ -472,7 +468,6 @@ luaA_wibox_new(lua_State *L)
luaA_checktable(L, 2); luaA_checktable(L, 2);
w = wibox_new(L); w = wibox_new(L);
w->widgets_table = LUA_REFNIL;
w->sw.ctx.fg = globalconf.colors.fg; w->sw.ctx.fg = globalconf.colors.fg;
if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len))) if((buf = luaA_getopt_lstring(L, 2, "fg", NULL, &len)))
@ -498,8 +493,6 @@ luaA_wibox_new(lua_State *L)
w->isvisible = true; w->isvisible = true;
w->cursor = a_strdup("left_ptr"); w->cursor = a_strdup("left_ptr");
w->mouse_enter = w->mouse_leave = LUA_REFNIL;
for(i = 0; i <= reqs_nbr; i++) for(i = 0; i <= reqs_nbr; i++)
xcolor_init_reply(reqs[i]); xcolor_init_reply(reqs[i]);
@ -514,9 +507,11 @@ luaA_wibox_new(lua_State *L)
static bool static bool
luaA_wibox_hasitem(lua_State *L, wibox_t *wibox, const void *item) 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)) if(lua_topointer(L, -1) == item || luaA_hasitem(L, item))
return true; return true;
} }
@ -618,7 +613,7 @@ luaA_wibox_index(lua_State *L)
luaA_pushxcolor(L, &wibox->sw.ctx.bg); luaA_pushxcolor(L, &wibox->sw.ctx.bg);
break; break;
case A_TK_BG_IMAGE: case A_TK_BG_IMAGE:
image_push(L, wibox->bg_image); luaA_object_push_item(L, 1, wibox->bg_image);
break; break;
case A_TK_POSITION: case A_TK_POSITION:
if(wibox->type == WIBOX_TYPE_NORMAL) if(wibox->type == WIBOX_TYPE_NORMAL)
@ -632,11 +627,7 @@ luaA_wibox_index(lua_State *L)
lua_pushstring(L, orientation_tostr(wibox->sw.orientation)); lua_pushstring(L, orientation_tostr(wibox->sw.orientation));
break; break;
case A_TK_WIDGETS: case A_TK_WIDGETS:
if(wibox->widgets_table != LUA_REFNIL) return luaA_object_push_item(L, 1, wibox->widgets_table);
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->widgets_table);
else
lua_pushnil(L);
break;
case A_TK_CURSOR: case A_TK_CURSOR:
lua_pushstring(L, wibox->cursor); lua_pushstring(L, wibox->cursor);
break; break;
@ -650,23 +641,13 @@ luaA_wibox_index(lua_State *L)
} }
break; break;
case A_TK_MOUSE_ENTER: case A_TK_MOUSE_ENTER:
if(wibox->mouse_enter != LUA_REFNIL) return luaA_object_push_item(L, 1, wibox->mouse_enter);
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->mouse_enter);
else
return 0;
return 1;
case A_TK_MOUSE_LEAVE: case A_TK_MOUSE_LEAVE:
if(wibox->mouse_leave != LUA_REFNIL) return luaA_object_push_item(L, 1, wibox->mouse_leave);
lua_rawgeti(L, LUA_REGISTRYINDEX, wibox->mouse_leave);
else
return 0;
return 1;
case A_TK_SHAPE_BOUNDING: case A_TK_SHAPE_BOUNDING:
image_push(L, wibox->sw.shape.bounding); return luaA_object_push_item(L, 1, wibox->sw.shape.bounding);
break;
case A_TK_SHAPE_CLIP: case A_TK_SHAPE_CLIP:
image_push(L, wibox->sw.shape.clip); return luaA_object_push_item(L, 1, wibox->sw.shape.clip);
break;
default: default:
return 0; return 0;
} }
@ -737,8 +718,8 @@ luaA_wibox_newindex(lua_State *L)
wibox->need_update = true; wibox->need_update = true;
break; break;
case A_TK_BG_IMAGE: case A_TK_BG_IMAGE:
image_unref(L, wibox->bg_image); luaA_object_unref_item(L, 1, wibox->bg_image);
wibox->bg_image = image_ref(L, 3); wibox->bg_image = luaA_object_ref_item(L, 1, 3);
wibox->need_update = true; wibox->need_update = true;
break; break;
case A_TK_ALIGN: 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"); luaA_warn(L, "table is looping, cannot use this as widget table");
return 0; 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); wibox_need_update(wibox);
luaA_table2wtable(L); luaA_table2wtable(L);
break; break;
@ -865,19 +849,23 @@ luaA_wibox_newindex(lua_State *L)
} }
break; break;
case A_TK_MOUSE_ENTER: 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; return 0;
case A_TK_MOUSE_LEAVE: 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; return 0;
case A_TK_SHAPE_BOUNDING: case A_TK_SHAPE_BOUNDING:
image_unref(L, wibox->sw.shape.bounding); luaA_object_unref_item(L, 1, wibox->sw.shape.bounding);
wibox->sw.shape.bounding = image_ref(L, 3); wibox->sw.shape.bounding = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true; wibox->need_shape_update = true;
break; break;
case A_TK_SHAPE_CLIP: case A_TK_SHAPE_CLIP:
image_unref(L, wibox->sw.shape.clip); luaA_object_unref_item(L, 1, wibox->sw.shape.clip);
wibox->sw.shape.clip = image_ref(L, 3); wibox->sw.shape.clip = luaA_object_ref_item(L, 1, 3);
wibox->need_shape_update = true; wibox->need_shape_update = true;
break; break;
default: default:
@ -904,15 +892,14 @@ static int
luaA_wibox_buttons(lua_State *L) luaA_wibox_buttons(lua_State *L)
{ {
wibox_t *wibox = luaL_checkudata(L, 1, "wibox"); wibox_t *wibox = luaL_checkudata(L, 1, "wibox");
button_array_t *buttons = &wibox->buttons;
if(lua_gettop(L) == 2) if(lua_gettop(L) == 2)
{ {
luaA_button_array_set(L, 2, buttons); luaA_button_array_set(L, 1, 2, &wibox->buttons);
return 1; 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[] = const struct luaL_reg awesome_wibox_methods[] =

View File

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

View File

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

View File

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

View File

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

View File

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