diff --git a/docs/common/widget.ldoc b/docs/common/widget.ldoc index 51a76a59e..ec215f5b9 100644 --- a/docs/common/widget.ldoc +++ b/docs/common/widget.ldoc @@ -40,6 +40,13 @@ -- @param _buttons The table of buttons that should bind to the widget. -- @function buttons +--- Emit a signal and ensure all parent widgets in the hierarchies also +-- forward the signal. This is useful to track signals when there is a dynamic +-- set of containers and layouts wrapping the widget. +-- @tparam string signal_name +-- @param ... Other arguments +-- @function emit_signal_recursive + --- When the layout (size) change. -- This signal is emited when the previous results of `:layout()` and `:fit()` -- are no longer valid. diff --git a/lib/wibox/hierarchy.lua b/lib/wibox/hierarchy.lua index 6ef800afc..b21885055 100644 --- a/lib/wibox/hierarchy.lua +++ b/lib/wibox/hierarchy.lua @@ -51,6 +51,16 @@ local function hierarchy_new(redraw_callback, layout_callback, callback_arg) end layout_callback(result, callback_arg) end + function result._emit_recursive(widget, name, ...) + local cur = result + assert(widget == cur._widget) + while cur do + if cur._widget then + cur._widget:emit_signal(name, ...) + end + cur = cur._parent + end + end for k, f in pairs(hierarchy) do if type(f) == "function" then @@ -86,6 +96,7 @@ function hierarchy_update(self, context, widget, width, height, region, matrix_t if old_widget and old_widget ~= widget then self._widget:disconnect_signal("widget::redraw_needed", self._redraw) self._widget:disconnect_signal("widget::layout_changed", self._layout) + self._widget:disconnect_signal("widget::emit_recursive", self._emit_recursive) end -- Save the arguments we need to save @@ -99,6 +110,7 @@ function hierarchy_update(self, context, widget, width, height, region, matrix_t if old_widget ~= widget then widget:weak_connect_signal("widget::redraw_needed", self._redraw) widget:weak_connect_signal("widget::layout_changed", self._layout) + widget:weak_connect_signal("widget::emit_recursive", self._emit_recursive) end -- Update children diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 2ed69066c..218f60fee 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -153,6 +153,27 @@ function base.widget:get_all_children() return ret end +--- Emit a signal and ensure all parent widgets in the hierarchies also +-- forward the signal. This is useful to track signals when there is a dynamic +-- set of containers and layouts wrapping the widget. +-- +-- Note that this function has two flaws. First of all, the signal are only +-- forwarded once the widget tree has been built. This happens after all +-- currently scheduled functions have been executed. Therefor, it wont start +-- to work right away. In case the widget is present multiple time in a single +-- widget tree, this function will also forward the signal multiple time (one +-- per upward tree path). +-- +-- @tparam string signal_name +-- @param ... Other arguments +-- @function emit_signal_recursive +function base.widget:emit_signal_recursive(signal_name, ...) + -- This is a convenience wrapper, the real implementation is in the + -- hierarchy. + + self:emit_signal("widget::emit_recursive", signal_name, ...) +end + --- Get a widex index. -- @param widget The widget to look for -- @param[opt] recursive Also check sub-widgets