Store widgets references as wibox items

This will store the widgets references that the wibox have inside their
environment table, and not in the global registry, avoiding memory leaks.
This should fix FS#771.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2010-05-25 15:43:18 +02:00
parent 1f57213322
commit cfebec085c
5 changed files with 88 additions and 42 deletions

70
event.c
View File

@ -160,7 +160,11 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
ev->event_y -= wibox->geometry.y; ev->event_y -= wibox->geometry.y;
} }
/* Push the wibox */
luaA_object_push(globalconf.L, wibox); luaA_object_push(globalconf.L, wibox);
/* Duplicate the wibox */
lua_pushvalue(globalconf.L, -1);
/* Handle the button event on it */
event_button_callback(ev, &wibox->buttons, -1, 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 */
@ -170,10 +174,16 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
&ev->event_x, &ev->event_y); &ev->event_x, &ev->event_y);
if(w) if(w)
{ {
luaA_object_push(globalconf.L, w); /* Push widget (the wibox is already on stack) */
luaA_object_push(globalconf.L, wibox); luaA_object_push_item(globalconf.L, -1, w);
/* Move widget before wibox */
lua_insert(globalconf.L, -2);
event_button_callback(ev, &w->buttons, -2, 2, NULL); event_button_callback(ev, &w->buttons, -2, 2, NULL);
} }
else
/* Remove the wibox, we did not use it */
lua_pop(globalconf.L, 1);
} }
else if((c = client_getbywin(ev->event))) else if((c = client_getbywin(ev->event)))
{ {
@ -342,12 +352,12 @@ event_handle_destroynotify(void *data __attribute__ ((unused)),
} }
/** Handle a motion notify over widgets. /** Handle a motion notify over widgets.
* \param object The object. * \param wibox The wibox.
* \param mouse_over The pointer to the registered mouse over widget. * \param mouse_over The pointer to the registered mouse over widget.
* \param widget The new widget the mouse is over. * \param widget The new widget the mouse is over.
*/ */
static void static void
event_handle_widget_motionnotify(void *object, event_handle_widget_motionnotify(wibox_t *wibox,
widget_t **mouse_over, widget_t **mouse_over,
widget_t *widget) widget_t *widget)
{ {
@ -355,25 +365,46 @@ event_handle_widget_motionnotify(void *object,
{ {
if(*mouse_over) if(*mouse_over)
{ {
/* call mouse leave function on old widget */ /* Emit mouse leave signal on old widget:
luaA_object_push(globalconf.L, *mouse_over); * - Push wibox.*/
luaA_object_emit_signal(globalconf.L, -1, "mouse::leave", 0); luaA_object_push(globalconf.L, wibox);
/* - Push the widget the mouse was on */
luaA_object_push_item(globalconf.L, -1, *mouse_over);
/* - Emit the signal mouse::leave with the wibox as argument */
luaA_object_emit_signal(globalconf.L, -2, "mouse::leave", 1);
/* - Remove the widget */
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
luaA_object_unref(globalconf.L, *mouse_over); /* Re-push wibox */
luaA_object_push(globalconf.L, wibox);
luaA_object_unref_item(globalconf.L, -1, *mouse_over);
*mouse_over = NULL; *mouse_over = NULL;
/* Remove the wibox */
lua_pop(globalconf.L, 1);
} }
if(widget) if(widget)
{ {
/* Get a ref on this widget so that it can't be unref'd from /* Get a ref on this widget so that it can't be unref'd from
* underneath us (-> invalid pointer dereference). */ * underneath us (-> invalid pointer dereference):
luaA_object_push(globalconf.L, widget); * - Push the wibox */
luaA_object_ref(globalconf.L, -1); luaA_object_push(globalconf.L, wibox);
/* - Push the widget */
luaA_object_push_item(globalconf.L, -1, widget);
/* - Reference the widget into the wibox */
luaA_object_ref_item(globalconf.L, -2, -1);
/* Store that this widget was the one with the mouse over */
*mouse_over = widget; *mouse_over = widget;
/* emit mouse::enter signal on new widget */ /* Emit mouse::enter signal on new widget:
luaA_object_push(globalconf.L, widget); * - Push the widget */
luaA_object_emit_signal(globalconf.L, -1, "mouse::enter", 0); luaA_object_push_item(globalconf.L, -1, widget);
/* - Move the widget before the wibox we pushed just above */
lua_insert(globalconf.L, -2);
/* - Emit the signal with the wibox as argument */
luaA_object_emit_signal(globalconf.L, -2, "mouse::enter", 1);
/* - Remove the widget from the stack */
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
} }
} }
@ -439,9 +470,14 @@ event_handle_leavenotify(void *data __attribute__ ((unused)),
{ {
if(wibox->mouse_over) if(wibox->mouse_over)
{ {
luaA_object_push(globalconf.L, wibox->mouse_over); /* Push the wibox */
/* emit mouse::leave signal on widget the mouse was over */ luaA_object_push(globalconf.L, wibox);
luaA_object_emit_signal(globalconf.L, -1, "mouse::leave", 0); /* Push the widget the mouse is over in this wibox */
luaA_object_push_item(globalconf.L, -1, wibox->mouse_over);
/* Emit mouse::leave signal on widget the mouse was over with
* its wibox as argument */
luaA_object_emit_signal(globalconf.L, -2, "mouse::leave", 1);
/* Remove the widget from the stack */
lua_pop(globalconf.L, 1); lua_pop(globalconf.L, 1);
wibox_clear_mouse_over(wibox); wibox_clear_mouse_over(wibox);
} }

14
wibox.c
View File

@ -49,6 +49,20 @@ luaA_wibox_gc(lua_State *L)
return luaA_object_gc(L); return luaA_object_gc(L);
} }
/** Wipe an array of widget_node. Release references to widgets.
* \param L The Lua VM state.
* \param idx The index of the wibox on the stack.
*/
void
wibox_widget_node_array_wipe(lua_State *L, int idx)
{
wibox_t *wibox = luaA_checkudata(L, idx, &wibox_class);
foreach(widget_node, wibox->widgets)
luaA_object_unref_item(globalconf.L, idx, widget_node);
widget_node_array_wipe(&wibox->widgets);
}
void void
wibox_unref_simplified(wibox_t **item) wibox_unref_simplified(wibox_t **item)
{ {

View File

@ -99,6 +99,7 @@ struct wibox_t
void wibox_unref_simplified(wibox_t **); void wibox_unref_simplified(wibox_t **);
ARRAY_FUNCS(wibox_t *, wibox, wibox_unref_simplified) ARRAY_FUNCS(wibox_t *, wibox, wibox_unref_simplified)
void wibox_widget_node_array_wipe(lua_State *, int);
void wibox_refresh(void); void wibox_refresh(void);

View File

@ -49,15 +49,6 @@ luaA_widget_gc(lua_State *L)
return luaA_object_gc(L); return luaA_object_gc(L);
} }
/** Delete a widget node structure.
* \param node The node to destroy.
*/
void
widget_node_delete(widget_node_t *node)
{
luaA_object_unref(globalconf.L, node->widget);
}
/** Get a widget node from a wibox by coords. /** Get a widget node from a wibox by coords.
* \param orientation Wibox orientation. * \param orientation Wibox orientation.
* \param widgets The widget list. * \param widgets The widget list.
@ -100,16 +91,18 @@ widget_getbycoords(orientation_t orientation, widget_node_array_t *widgets,
/** Convert a Lua table to a list of widget nodes. /** Convert a Lua table to a list of widget nodes.
* \param L The Lua VM state. * \param L The Lua VM state.
* \param idx Index of the table where to store the widgets references.
* \param widgets The linked list of widget node. * \param widgets The linked list of widget node.
*/ */
static void static void
luaA_table2widgets(lua_State *L, widget_node_array_t *widgets) luaA_table2widgets(lua_State *L, int idx, widget_node_array_t *widgets)
{ {
if(lua_istable(L, -1)) if(lua_istable(L, -1))
{ {
int table_idx = luaA_absindex(L, idx);
lua_pushnil(L); lua_pushnil(L);
while(luaA_next(L, -2)) while(luaA_next(L, -2))
luaA_table2widgets(L, widgets); luaA_table2widgets(L, table_idx, widgets);
/* remove the table */ /* remove the table */
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -120,7 +113,7 @@ luaA_table2widgets(lua_State *L, widget_node_array_t *widgets)
{ {
widget_node_t w; widget_node_t w;
p_clear(&w, 1); p_clear(&w, 1);
w.widget = luaA_object_ref(L, -1); w.widget = luaA_object_ref_item(L, idx, -1);
widget_node_array_append(widgets, w); widget_node_array_append(widgets, w);
} }
else else
@ -197,17 +190,19 @@ widget_geometries(wibox_t *wibox)
* or the wibox size, depending on which is less. * or the wibox size, depending on which is less.
*/ */
widget_node_array_t *widgets = &wibox->widgets;
widget_node_array_wipe(widgets);
widget_node_array_init(widgets);
/* push wibox */ /* push wibox */
luaA_object_push(globalconf.L, wibox); luaA_object_push(globalconf.L, wibox);
widget_node_array_t *widgets = &wibox->widgets;
wibox_widget_node_array_wipe(globalconf.L, -1);
widget_node_array_init(widgets);
/* push widgets table */ /* push widgets table */
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table); luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
/* Convert widgets table */
luaA_table2widgets(globalconf.L, -2, widgets);
/* remove wibox */ /* remove wibox */
lua_remove(globalconf.L, -2); lua_remove(globalconf.L, -1);
luaA_table2widgets(globalconf.L, widgets);
lua_newtable(globalconf.L); lua_newtable(globalconf.L);
for(int i = 0; i < widgets->len; i++) for(int i = 0; i < widgets->len; i++)
@ -297,15 +292,17 @@ widget_render(wibox_t *wibox)
widget_node_array_t *widgets = &wibox->widgets; widget_node_array_t *widgets = &wibox->widgets;
widget_node_array_wipe(widgets);
widget_node_array_init(widgets);
/* push wibox */ /* push wibox */
luaA_object_push(globalconf.L, wibox); luaA_object_push(globalconf.L, wibox);
wibox_widget_node_array_wipe(globalconf.L, -1);
widget_node_array_init(widgets);
/* push widgets table */ /* push widgets table */
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table); luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
luaA_table2widgets(L, -2, widgets);
/* remove wibox */ /* remove wibox */
lua_remove(globalconf.L, -2); lua_remove(globalconf.L, -1);
luaA_table2widgets(L, widgets);
/* get computed geometries */ /* get computed geometries */
for(unsigned int i = 0; i < lua_objlen(L, -1); i++) for(unsigned int i = 0; i < lua_objlen(L, -1); i++)

View File

@ -54,8 +54,6 @@ struct widget_t
bool isvisible; bool isvisible;
}; };
void widget_node_delete(widget_node_t *);
struct widget_node struct widget_node
{ {
/** The widget object */ /** The widget object */
@ -63,7 +61,7 @@ struct widget_node
/** The geometry where the widget was drawn */ /** The geometry where the widget was drawn */
area_t geometry; area_t geometry;
}; };
DO_ARRAY(widget_node_t, widget_node, widget_node_delete) DO_ARRAY(widget_node_t, widget_node, DO_NOTHING)
widget_t *widget_getbycoords(orientation_t, widget_node_array_t *, int, int, int16_t *, int16_t *); widget_t *widget_getbycoords(orientation_t, widget_node_array_t *, int, int, int16_t *, int16_t *);
void widget_render(wibox_t *); void widget_render(wibox_t *);