diff --git a/docs/common/fixed.ldoc b/docs/common/fixed.ldoc index ce9ea8468..df141eb4c 100644 --- a/docs/common/fixed.ldoc +++ b/docs/common/fixed.ldoc @@ -1,11 +1,15 @@ ---- Set a widget at a specific index, replace the current one +--- Set a widget at a specific index, replace the current one. +-- **Signal:** widget::replaced The argument is the new widget and the old one +-- and the index. -- @tparam number index A widget or a widget index -- @param widget2 The widget to take the place of the first one -- @treturn boolean If the operation is successful -- @name set -- @class function ---- Replace the first instance of `widget` in the layout with `widget2` +--- Replace the first instance of `widget` in the layout with `widget2`. +-- **Signal:** widget::replaced The argument is the new widget and the old one +-- and the index. -- @param widget The widget to replace -- @param widget2 The widget to replace `widget` with -- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. @@ -13,15 +17,18 @@ -- @name replace_widget -- @class function ---- Swap 2 widgets in a layout +--- Swap 2 widgets in a layout. +-- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. -- @tparam number index1 The first widget index -- @tparam number index2 The second widget index -- @treturn boolean If the operation is successful -- @name swap -- @class function ---- Swap 2 widgets in a layout +--- Swap 2 widgets in a layout. -- If widget1 is present multiple time, only the first instance is swapped +-- **Signal:** widget::swapped The arguments are both widgets and both (new) indexes. +-- if the layouts not the same, then only `widget::replaced` will be emitted. -- @param widget1 The first widget -- @param widget2 The second widget -- @tparam[opt=false] boolean recursive Digg in all compatible layouts to find the widget. @@ -34,6 +41,7 @@ -- @property children --- Reset a ratio layout. This removes all widgets from the layout. +-- **Signal:** widget::reset -- @param layout The layout you are modifying. -- @name reset -- @class function diff --git a/docs/common/widget.ldoc b/docs/common/widget.ldoc index 199413977..ec215f5b9 100644 --- a/docs/common/widget.ldoc +++ b/docs/common/widget.ldoc @@ -40,6 +40,12 @@ -- @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()` diff --git a/lib/awful/widget/button.lua b/lib/awful/widget/button.lua index eaaafb288..edded81d8 100644 --- a/lib/awful/widget/button.lua +++ b/lib/awful/widget/button.lua @@ -1,4 +1,12 @@ --------------------------------------------------------------------------- +-- A simple button widget. +-- @usage local button = awful.widget.button() +-- button:buttons(awful.util.table.join( +-- button:buttons(), +-- awful.button({}, 1, nil, function () +-- print("Mouse was clicked") +-- end) +-- )) -- @author Julien Danjou <julien@danjou.info> -- @copyright 2008-2009 Julien Danjou -- @release @AWESOME_VERSION@ @@ -49,6 +57,10 @@ function button.mt:__call(...) return button.new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(button, button.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 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/layout/fixed.lua b/lib/wibox/layout/fixed.lua index 975c366fb..474f09619 100644 --- a/lib/wibox/layout/fixed.lua +++ b/lib/wibox/layout/fixed.lua @@ -144,6 +144,8 @@ function fixed:swap(index1, index2) self:set(index1, widget2) self:set(index2, widget1) + self:emit_signal("widget::swapped", widget1, widget2, index2, index1) + return true end @@ -157,11 +159,17 @@ function fixed:swap_widgets(widget1, widget2, recursive) if idx1 and l1 and idx2 and l2 and (l1.set or l1.set_widget) and (l2.set or l2.set_widget) then if l1.set then l1:set(idx1, widget2) + if l1 == self then + self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1) + end elseif l1.set_widget then l1:set_widget(widget2) end if l2.set then l2:set(idx2, widget1) + if l2 == self then + self:emit_signal("widget::swapped", widget1, widget2, idx2, idx1) + end elseif l2.set_widget then l2:set_widget(widget1) end @@ -177,14 +185,18 @@ function fixed:set(index, widget2) base.check_widget(widget2) + local w = self._private.widgets[index] + self._private.widgets[index] = widget2 self:emit_signal("widget::layout_changed") + self:emit_signal("widget::replaced", widget2, w, index) return true end --- Insert a new widget in the layout at position `index` +-- **Signal:** widget::inserted The arguments are the widget and the index -- @tparam number index The position -- @param widget The widget -- @treturn boolean If the operation is successful @@ -194,6 +206,7 @@ function fixed:insert(index, widget) base.check_widget(widget) table.insert(self._private.widgets, index, widget) self:emit_signal("widget::layout_changed") + self:emit_signal("widget::inserted", widget, #self._private.widgets) return true end @@ -242,6 +255,7 @@ end function fixed:reset() self._private.widgets = {} self:emit_signal("widget::layout_changed") + self:emit_signal("widget::reseted") end --- Set the layout's fill_space property. If this property is true, the last diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index 072b64afc..b6f39dbf6 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -238,6 +238,7 @@ function ratio:ajust_widget_ratio(widget, before, itself, after) end --- Add some widgets to the given fixed layout +-- **Signal:** widget::added The argument are the widgets -- @tparam widget ... Widgets that should be added (must at least be one) function ratio:add(...) -- No table.pack in Lua 5.1 :-( @@ -250,25 +251,31 @@ function ratio:add(...) normalize(self) self:emit_signal("widget::layout_changed") + self:emit_signal("widget::added", ...) end --- Remove a widget from the layout +-- **Signal:** widget::removed The arguments are the widget and the index -- @tparam number index The widget index to remove -- @treturn boolean index If the operation is successful function ratio:remove(index) if not index or not self._private.widgets[index] then return false end + local w = self._private.widgets[index] + table.remove(self._private.ratios, index) table.remove(self._private.widgets, index) normalize(self) self:emit_signal("widget::layout_changed") + self:emit_signal("widget::removed", w, index) return true end --- Insert a new widget in the layout at position `index` +-- **Signal:** widget::inserted The arguments are the widget and the index -- @tparam number index The position -- @param widget The widget function ratio:insert(index, widget) @@ -281,6 +288,7 @@ function ratio:insert(index, widget) normalize(self) self:emit_signal("widget::layout_changed") + self:emit_signal("widget::inserted", widget, #self._private.widgets) end local function get_layout(dir, widget1, ...) 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 diff --git a/tests/test-awful-widget-button.lua b/tests/test-awful-widget-button.lua index ffb84e12c..be99c5653 100644 --- a/tests/test-awful-widget-button.lua +++ b/tests/test-awful-widget-button.lua @@ -9,6 +9,10 @@ local w local img local button +-- Also check recursive signals from events +local layout +local got_called = false + -- create a wibox. table.insert(steps, function() @@ -55,6 +59,21 @@ table.insert(steps, function() img = button._private.image assert(img) + -- Test the click + layout = w.widget + assert(layout) + + button:buttons(awful.util.table.join( + button:buttons(), + awful.button({}, 1, nil, function () + button:emit_signal_recursive("test::recursive") + end) + )) + + layout:connect_signal("test::recursive", function() + got_called = true + end) + return true end) @@ -111,6 +130,9 @@ end) table.insert(steps, function() assert(button._private.image == img) + -- The button had plenty of clicks by now. Make sure everything worked + assert(got_called) + return true end)