diff --git a/event.c b/event.c index bda0cc5a2..6e9af0b39 100644 --- a/event.c +++ b/event.c @@ -160,7 +160,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 */ @@ -170,10 +174,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))) { @@ -342,12 +352,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) { @@ -355,25 +365,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); } } @@ -439,9 +470,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); } diff --git a/wibox.c b/wibox.c index 689c81f2f..e72690fd4 100644 --- a/wibox.c +++ b/wibox.c @@ -49,6 +49,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) { diff --git a/wibox.h b/wibox.h index f642ac663..67035c205 100644 --- a/wibox.h +++ b/wibox.h @@ -99,6 +99,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); diff --git a/widget.c b/widget.c index 4c0d293c8..282e3c97c 100644 --- a/widget.c +++ b/widget.c @@ -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,16 +91,18 @@ 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); lua_pushnil(L); while(luaA_next(L, -2)) - luaA_table2widgets(L, widgets); + luaA_table2widgets(L, table_idx, widgets); /* remove the table */ lua_pop(L, 1); } @@ -120,7 +113,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 @@ -197,17 +190,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++) @@ -297,15 +292,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++) diff --git a/widget.h b/widget.h index 0f13b2960..0c4aface9 100644 --- a/widget.h +++ b/widget.h @@ -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 *);