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:
parent
b473a6fe66
commit
6a1ce5ce05
70
event.c
70
event.c
|
@ -159,7 +159,11 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
|
|||
ev->event_y -= wibox->geometry.y;
|
||||
}
|
||||
|
||||
/* Push the 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);
|
||||
|
||||
/* then try to match a widget binding */
|
||||
|
@ -169,10 +173,16 @@ event_handle_button(void *data, xcb_connection_t *connection, xcb_button_press_e
|
|||
&ev->event_x, &ev->event_y);
|
||||
if(w)
|
||||
{
|
||||
luaA_object_push(globalconf.L, w);
|
||||
luaA_object_push(globalconf.L, wibox);
|
||||
/* Push widget (the wibox is already on stack) */
|
||||
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);
|
||||
}
|
||||
else
|
||||
/* Remove the wibox, we did not use it */
|
||||
lua_pop(globalconf.L, 1);
|
||||
|
||||
}
|
||||
else if((c = client_getbywin(ev->event)))
|
||||
{
|
||||
|
@ -341,12 +351,12 @@ event_handle_destroynotify(void *data __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
/** 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 widget The new widget the mouse is over.
|
||||
*/
|
||||
static void
|
||||
event_handle_widget_motionnotify(void *object,
|
||||
event_handle_widget_motionnotify(wibox_t *wibox,
|
||||
widget_t **mouse_over,
|
||||
widget_t *widget)
|
||||
{
|
||||
|
@ -354,25 +364,46 @@ event_handle_widget_motionnotify(void *object,
|
|||
{
|
||||
if(*mouse_over)
|
||||
{
|
||||
/* call mouse leave function on old widget */
|
||||
luaA_object_push(globalconf.L, *mouse_over);
|
||||
luaA_object_emit_signal(globalconf.L, -1, "mouse::leave", 0);
|
||||
/* Emit mouse leave signal on old widget:
|
||||
* - Push wibox.*/
|
||||
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);
|
||||
|
||||
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;
|
||||
/* Remove the wibox */
|
||||
lua_pop(globalconf.L, 1);
|
||||
}
|
||||
if(widget)
|
||||
{
|
||||
/* Get a ref on this widget so that it can't be unref'd from
|
||||
* underneath us (-> invalid pointer dereference). */
|
||||
luaA_object_push(globalconf.L, widget);
|
||||
luaA_object_ref(globalconf.L, -1);
|
||||
* underneath us (-> invalid pointer dereference):
|
||||
* - Push the wibox */
|
||||
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;
|
||||
|
||||
/* emit mouse::enter signal on new widget */
|
||||
luaA_object_push(globalconf.L, widget);
|
||||
luaA_object_emit_signal(globalconf.L, -1, "mouse::enter", 0);
|
||||
/* Emit mouse::enter signal on new widget:
|
||||
* - Push the widget */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -433,9 +464,14 @@ event_handle_leavenotify(void *data __attribute__ ((unused)),
|
|||
{
|
||||
if(wibox->mouse_over)
|
||||
{
|
||||
luaA_object_push(globalconf.L, wibox->mouse_over);
|
||||
/* emit mouse::leave signal on widget the mouse was over */
|
||||
luaA_object_emit_signal(globalconf.L, -1, "mouse::leave", 0);
|
||||
/* Push the wibox */
|
||||
luaA_object_push(globalconf.L, wibox);
|
||||
/* 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);
|
||||
wibox_clear_mouse_over(wibox);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,20 @@ luaA_wibox_gc(lua_State *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
|
||||
wibox_unref_simplified(wibox_t **item)
|
||||
{
|
||||
|
|
|
@ -84,6 +84,7 @@ struct wibox_t
|
|||
void wibox_unref_simplified(wibox_t **);
|
||||
|
||||
ARRAY_FUNCS(wibox_t *, wibox, wibox_unref_simplified)
|
||||
void wibox_widget_node_array_wipe(lua_State *, int);
|
||||
|
||||
void wibox_refresh(void);
|
||||
|
||||
|
|
|
@ -49,15 +49,6 @@ luaA_widget_gc(lua_State *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.
|
||||
* \param orientation Wibox orientation.
|
||||
* \param widgets The widget list.
|
||||
|
@ -100,19 +91,21 @@ widget_getbycoords(orientation_t orientation, widget_node_array_t *widgets,
|
|||
|
||||
/** Convert a Lua table to a list of widget nodes.
|
||||
* \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.
|
||||
*/
|
||||
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))
|
||||
{
|
||||
int table_idx = luaA_absindex(L, idx);
|
||||
int i = 1;
|
||||
lua_pushnumber(L, i++);
|
||||
lua_gettable(L, -2);
|
||||
while(!lua_isnil(L, -1))
|
||||
{
|
||||
luaA_table2widgets(L, widgets);
|
||||
luaA_table2widgets(L, table_idx, widgets);
|
||||
lua_pushnumber(L, i++);
|
||||
lua_gettable(L, -2);
|
||||
}
|
||||
|
@ -127,7 +120,7 @@ luaA_table2widgets(lua_State *L, widget_node_array_t *widgets)
|
|||
{
|
||||
widget_node_t w;
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
@ -204,17 +197,19 @@ widget_geometries(wibox_t *wibox)
|
|||
* 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 */
|
||||
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 */
|
||||
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
|
||||
/* Convert widgets table */
|
||||
luaA_table2widgets(globalconf.L, -2, widgets);
|
||||
/* remove wibox */
|
||||
lua_remove(globalconf.L, -2);
|
||||
luaA_table2widgets(globalconf.L, widgets);
|
||||
lua_remove(globalconf.L, -1);
|
||||
|
||||
lua_newtable(globalconf.L);
|
||||
for(int i = 0; i < widgets->len; i++)
|
||||
|
@ -304,15 +299,17 @@ widget_render(wibox_t *wibox)
|
|||
|
||||
widget_node_array_t *widgets = &wibox->widgets;
|
||||
|
||||
widget_node_array_wipe(widgets);
|
||||
widget_node_array_init(widgets);
|
||||
/* push wibox */
|
||||
luaA_object_push(globalconf.L, wibox);
|
||||
|
||||
wibox_widget_node_array_wipe(globalconf.L, -1);
|
||||
widget_node_array_init(widgets);
|
||||
|
||||
/* push widgets table */
|
||||
luaA_object_push_item(globalconf.L, -1, wibox->widgets_table);
|
||||
luaA_table2widgets(L, -2, widgets);
|
||||
/* remove wibox */
|
||||
lua_remove(globalconf.L, -2);
|
||||
luaA_table2widgets(L, widgets);
|
||||
lua_remove(globalconf.L, -1);
|
||||
|
||||
/* get computed geometries */
|
||||
for(unsigned int i = 0; i < lua_objlen(L, -1); i++)
|
||||
|
|
|
@ -54,8 +54,6 @@ struct widget_t
|
|||
bool isvisible;
|
||||
};
|
||||
|
||||
void widget_node_delete(widget_node_t *);
|
||||
|
||||
struct widget_node
|
||||
{
|
||||
/** The widget object */
|
||||
|
@ -63,7 +61,7 @@ struct widget_node
|
|||
/** The geometry where the widget was drawn */
|
||||
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 *);
|
||||
void widget_render(wibox_t *);
|
||||
|
|
Loading…
Reference in New Issue