summaryrefslogtreecommitdiff
path: root/lib/wibox/layout
diff options
context:
space:
mode:
authorache <ache@ache.one>2017-03-13 23:17:19 +0100
committerache <ache@ache.one>2017-03-13 23:17:19 +0100
commit22d656903563f75678f3634964731ccf93355dfd (patch)
treee3cb6279d95c9764093072d5e946566ea6533799 /lib/wibox/layout
Init commit
Diffstat (limited to 'lib/wibox/layout')
-rw-r--r--lib/wibox/layout/align.lua526
-rw-r--r--lib/wibox/layout/constraint.lua17
-rw-r--r--lib/wibox/layout/fixed.lua585
-rw-r--r--lib/wibox/layout/flex.lua429
-rw-r--r--lib/wibox/layout/init.lua23
-rw-r--r--lib/wibox/layout/margin.lua17
-rw-r--r--lib/wibox/layout/mirror.lua17
-rw-r--r--lib/wibox/layout/ratio.lua583
-rw-r--r--lib/wibox/layout/rotate.lua17
-rw-r--r--lib/wibox/layout/scroll.lua16
-rw-r--r--lib/wibox/layout/stack.lua402
11 files changed, 2632 insertions, 0 deletions
diff --git a/lib/wibox/layout/align.lua b/lib/wibox/layout/align.lua
new file mode 100644
index 0000000..92a5582
--- /dev/null
+++ b/lib/wibox/layout/align.lua
@@ -0,0 +1,526 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_layout_defaults_align.svg)
+--
+-- @usage
+--wibox.widget {
+-- generic_widget( 'first' ),
+-- generic_widget( 'second' ),
+-- generic_widget( 'third' ),
+-- layout = wibox.layout.align.horizontal
+--}
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout.align
+---------------------------------------------------------------------------
+
+local table = table
+local pairs = pairs
+local type = type
+local floor = math.floor
+local util = require("awful.util")
+local base = require("wibox.widget.base")
+
+local align = {}
+
+-- Calculate the layout of an align layout.
+-- @param context The context in which we are drawn.
+-- @param width The available width.
+-- @param height The available height.
+function align:layout(context, width, height)
+ local result = {}
+
+ -- Draw will have to deal with all three align modes and should work in a
+ -- way that makes sense if one or two of the widgets are missing (if they
+ -- are all missing, it won't draw anything.) It should also handle the case
+ -- where the fit something that isn't set to expand (for instance the
+ -- outside widgets when the expand mode is "inside" or any of the widgets
+ -- when the expand mode is "none" wants to take up more space than is
+ -- allowed.
+ local size_first = 0
+ -- start with all the space given by the parent, subtract as we go along
+ local size_remains = self._private.dir == "y" and height or width
+ -- This is only set & used if expand ~= "inside" and we have second width.
+ -- It contains the size allocated to the second widget.
+ local size_second
+
+ -- we will prioritize the middle widget unless the expand mode is "inside"
+ -- if it is, we prioritize the first widget by not doing this block also,
+ -- if the second widget doesn't exist, we will prioritise the first one
+ -- instead
+ if self._private.expand ~= "inside" and self._private.second then
+ local w, h = base.fit_widget(self, context, self._private.second, width, height)
+ size_second = self._private.dir == "y" and h or w
+ -- if all the space is taken, skip the rest, and draw just the middle
+ -- widget
+ if size_second >= size_remains then
+ return { base.place_widget_at(self._private.second, 0, 0, width, height) }
+ else
+ -- the middle widget is sized first, the outside widgets are given
+ -- the remaining space if available we will draw later
+ size_remains = floor((size_remains - size_second) / 2)
+ end
+ end
+ if self._private.first then
+ local w, h, _ = width, height, nil
+ -- we use the fit function for the "inside" and "none" modes, but
+ -- ignore it for the "outside" mode, which will force it to expand
+ -- into the remaining space
+ if self._private.expand ~= "outside" then
+ if self._private.dir == "y" then
+ _, h = base.fit_widget(self, context, self._private.first, width, size_remains)
+ size_first = h
+ -- for "inside", the third widget will get a chance to use the
+ -- remaining space, then the middle widget. For "none" we give
+ -- the third widget the remaining space if there was no second
+ -- widget to take up any space (as the first if block is skipped
+ -- if this is the case)
+ if self._private.expand == "inside" or not self._private.second then
+ size_remains = size_remains - h
+ end
+ else
+ w, _ = base.fit_widget(self, context, self._private.first, size_remains, height)
+ size_first = w
+ if self._private.expand == "inside" or not self._private.second then
+ size_remains = size_remains - w
+ end
+ end
+ else
+ if self._private.dir == "y" then
+ h = size_remains
+ else
+ w = size_remains
+ end
+ end
+ table.insert(result, base.place_widget_at(self._private.first, 0, 0, w, h))
+ end
+ -- size_remains will be <= 0 if first used all the space
+ if self._private.third and size_remains > 0 then
+ local w, h, _ = width, height, nil
+ if self._private.expand ~= "outside" then
+ if self._private.dir == "y" then
+ _, h = base.fit_widget(self, context, self._private.third, width, size_remains)
+ -- give the middle widget the rest of the space for "inside" mode
+ if self._private.expand == "inside" then
+ size_remains = size_remains - h
+ end
+ else
+ w, _ = base.fit_widget(self, context, self._private.third, size_remains, height)
+ if self._private.expand == "inside" then
+ size_remains = size_remains - w
+ end
+ end
+ else
+ if self._private.dir == "y" then
+ h = size_remains
+ else
+ w = size_remains
+ end
+ end
+ local x, y = width - w, height - h
+ table.insert(result, base.place_widget_at(self._private.third, x, y, w, h))
+ end
+ -- here we either draw the second widget in the space set aside for it
+ -- in the beginning, or in the remaining space, if it is "inside"
+ if self._private.second and size_remains > 0 then
+ local x, y, w, h = 0, 0, width, height
+ if self._private.expand == "inside" then
+ if self._private.dir == "y" then
+ h = size_remains
+ x, y = 0, size_first
+ else
+ w = size_remains
+ x, y = size_first, 0
+ end
+ else
+ local _
+ if self._private.dir == "y" then
+ _, h = base.fit_widget(self, context, self._private.second, width, size_second)
+ y = floor( (height - h)/2 )
+ else
+ w, _ = base.fit_widget(self, context, self._private.second, size_second, height)
+ x = floor( (width -w)/2 )
+ end
+ end
+ table.insert(result, base.place_widget_at(self._private.second, x, y, w, h))
+ end
+ return result
+end
+
+--- Set the layout's first widget.
+-- This is the widget that is at the left/top
+-- @property first
+
+function align:set_first(widget)
+ if self._private.first == widget then
+ return
+ end
+ self._private.first = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Set the layout's second widget. This is the centered one.
+-- @property second
+
+function align:set_second(widget)
+ if self._private.second == widget then
+ return
+ end
+ self._private.second = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Set the layout's third widget.
+-- This is the widget that is at the right/bottom
+-- @property third
+
+function align:set_third(widget)
+ if self._private.third == widget then
+ return
+ end
+ self._private.third = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+for _, prop in ipairs {"first", "second", "third", "expand" } do
+ align["get_"..prop] = function(self)
+ return self._private[prop]
+ end
+end
+
+--- All direct children of this layout.
+-- This can be used to replace all 3 widgets at once.
+-- @treturn table a list of all widgets
+-- @property children
+
+function align:get_children()
+ return util.from_sparse {self._private.first, self._private.second, self._private.third}
+end
+
+function align:set_children(children)
+ self:set_first(children[1])
+ self:set_second(children[2])
+ self:set_third(children[3])
+end
+
+-- Fit the align layout into the given space. The align layout will
+-- ask for the sum of the sizes of its sub-widgets in its direction
+-- and the largest sized sub widget in the other direction.
+-- @param context The context in which we are fit.
+-- @param orig_width The available width.
+-- @param orig_height The available height.
+function align:fit(context, orig_width, orig_height)
+ local used_in_dir = 0
+ local used_in_other = 0
+
+ for _, v in pairs{self._private.first, self._private.second, self._private.third} do
+ local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
+
+ local max = self._private.dir == "y" and w or h
+ if max > used_in_other then
+ used_in_other = max
+ end
+
+ used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
+ end
+
+ if self._private.dir == "y" then
+ return used_in_other, used_in_dir
+ end
+ return used_in_dir, used_in_other
+end
+
+--- Set the expand mode which determines how sub widgets expand to take up
+-- unused space.
+--
+-- @tparam[opt=inside] string mode How to use unused space.
+--
+-- * "inside" - Default option. Size of outside widgets is determined using
+-- their fit function. Second, middle, or center widget expands to fill
+-- remaining space.
+-- * "outside" - Center widget is sized using its fit function and placed in
+-- the center of the allowed space. Outside widgets expand (or contract) to
+-- fill remaining space on their side.
+-- * "none" - All widgets are sized using their fit function, drawn to only the
+-- returned space, or remaining space, whichever is smaller. Center widget
+-- gets priority.
+-- @property expand
+
+function align:set_expand(mode)
+ if mode == "none" or mode == "outside" then
+ self._private.expand = mode
+ else
+ self._private.expand = "inside"
+ end
+ self:emit_signal("widget::layout_changed")
+end
+
+function align:reset()
+ for _, v in pairs({ "first", "second", "third" }) do
+ self[v] = nil
+ end
+ self:emit_signal("widget::layout_changed")
+end
+
+local function get_layout(dir, first, second, third)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+ ret._private.dir = dir
+
+ for k, v in pairs(align) do
+ if type(v) == "function" then
+ rawset(ret, k, v)
+ end
+ end
+
+ ret:set_expand("inside")
+ ret:set_first(first)
+ ret:set_second(second)
+ ret:set_third(third)
+
+ -- An align layout allow set_children to have empty entries
+ ret.allow_empty_widget = true
+
+ return ret
+end
+
+--- Returns a new horizontal align layout. An align layout can display up to
+-- three widgets. The widget set via :set_left() is left-aligned. :set_right()
+-- sets a widget which will be right-aligned. The remaining space between those
+-- two will be given to the widget set via :set_middle().
+-- @tparam[opt] widget left Widget to be put to the left.
+-- @tparam[opt] widget middle Widget to be put to the middle.
+-- @tparam[opt] widget right Widget to be put to the right.
+function align.horizontal(left, middle, right)
+ local ret = get_layout("x", left, middle, right)
+
+ rawset(ret, "set_left" , ret.set_first )
+ rawset(ret, "set_middle", ret.set_second )
+ rawset(ret, "set_right" , ret.set_third )
+
+ return ret
+end
+
+--- Returns a new vertical align layout. An align layout can display up to
+-- three widgets. The widget set via :set_top() is top-aligned. :set_bottom()
+-- sets a widget which will be bottom-aligned. The remaining space between those
+-- two will be given to the widget set via :set_middle().
+-- @tparam[opt] widget top Widget to be put to the top.
+-- @tparam[opt] widget middle Widget to be put to the middle.
+-- @tparam[opt] widget bottom Widget to be put to the right.
+function align.vertical(top, middle, bottom)
+ local ret = get_layout("y", top, middle, bottom)
+
+ rawset(ret, "set_top" , ret.set_first )
+ rawset(ret, "set_middle", ret.set_second )
+ rawset(ret, "set_bottom", ret.set_third )
+
+ return ret
+end
+
+--Imported documentation
+
+
+--- Get a widex index.
+-- @param widget The widget to look for
+-- @param[opt] recursive Also check sub-widgets
+-- @param[opt] ... Aditional widgets to add at the end of the \"path\"
+-- @return The index
+-- @return The parent layout
+-- @return The path between \"self\" and \"widget\"
+-- @function index
+
+--- Get all direct and indirect children widgets.
+-- This will scan all containers recursively to find widgets
+-- Warning: This method it prone to stack overflow id the widget, or any of its
+-- children, contain (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+
+--- Set a declarative widget hierarchy description.
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
+-- @param args An array containing the widgets disposition
+-- @function setup
+
+--- Force a widget height.
+-- @property forced_height
+-- @tparam number|nil height The height (`nil` for automatic)
+
+--- Force a widget width.
+-- @property forced_width
+-- @tparam number|nil width The width (`nil` for automatic)
+
+--- The widget opacity (transparency).
+-- @property opacity
+-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
+
+--- The widget visibility.
+-- @property visible
+-- @param boolean
+
+--- Set/get a widget's buttons.
+-- @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 emitted when the previous results of `:layout()` and `:fit()`
+-- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()`
+-- must return the same result when called with the same arguments.
+-- @signal widget::layout_changed
+-- @see widget::redraw_needed
+
+--- When the widget content changed.
+-- This signal is emitted when the content of the widget changes. The widget will
+-- be redrawn, it is not re-layouted. Put differently, it is assumed that
+-- `:layout()` and `:fit()` would still return the same results as before.
+-- @signal widget::redraw_needed
+-- @see widget::layout_changed
+
+--- When a mouse button is pressed over the widget.
+-- @signal button::press
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When a mouse button is released over the widget.
+-- @signal button::release
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse enter a widget.
+-- @signal mouse::enter
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse leave a widget.
+-- @signal mouse::leave
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+
+--Imported documentation
+
+
+--- Disconnect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback that should be disconnected
+-- @function disconnect_signal
+
+--- Emit a signal.
+--
+-- @tparam string name The name of the signal
+-- @param ... Extra arguments for the callback functions. Each connected
+-- function receives the object as first argument and then any extra arguments
+-- that are given to emit_signal()
+-- @function emit_signal
+
+--- Connect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function connect_signal
+
+--- Connect to a signal weakly. This allows the callback function to be garbage
+-- collected and automatically disconnects the signal when that happens.
+--
+-- **Warning:**
+-- Only use this function if you really, really, really know what you
+-- are doing.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function weak_connect_signal
+
+
+return align
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/constraint.lua b/lib/wibox/layout/constraint.lua
new file mode 100644
index 0000000..5333b38
--- /dev/null
+++ b/lib/wibox/layout/constraint.lua
@@ -0,0 +1,17 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.`
+--
+-- @author Lukáš Hrázký
+-- @copyright 2012 Lukáš Hrázký
+-- @classmod wibox.layout.constraint
+---------------------------------------------------------------------------
+
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.constraint"),
+ "wibox.layout.constraint",
+ "wibox.container.constraint"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/fixed.lua b/lib/wibox/layout/fixed.lua
new file mode 100644
index 0000000..7258438
--- /dev/null
+++ b/lib/wibox/layout/fixed.lua
@@ -0,0 +1,585 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_layout_defaults_fixed.svg)
+--
+-- @usage
+--wibox.widget {
+-- generic_widget( 'first' ),
+-- generic_widget( 'second' ),
+-- generic_widget( 'third' ),
+-- layout = wibox.layout.fixed.horizontal
+--}
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout.fixed
+---------------------------------------------------------------------------
+
+local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
+local base = require("wibox.widget.base")
+local table = table
+local pairs = pairs
+local util = require("awful.util")
+
+local fixed = {}
+
+--Imported documentation
+
+--- 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`.
+-- **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.
+-- @treturn boolean If the operation is successful
+-- @name replace_widget
+-- @class function
+
+--- 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.
+-- 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.
+-- @treturn boolean If the operation is successful
+-- @name swap_widgets
+-- @class function
+
+--- Get all direct children of this layout.
+-- @param layout The layout you are modifying.
+-- @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
+
+
+-- Layout a fixed layout. Each widget gets just the space it asks for.
+-- @param context The context in which we are drawn.
+-- @param width The available width.
+-- @param height The available height.
+function fixed:layout(context, width, height)
+ local result = {}
+ local pos,spacing = 0, self._private.spacing
+
+ for k, v in pairs(self._private.widgets) do
+ local x, y, w, h, _
+ if self._private.dir == "y" then
+ x, y = 0, pos
+ w, h = width, height - pos
+ if k ~= #self._private.widgets or not self._private.fill_space then
+ _, h = base.fit_widget(self, context, v, w, h);
+ end
+ pos = pos + h + spacing
+ else
+ x, y = pos, 0
+ w, h = width - pos, height
+ if k ~= #self._private.widgets or not self._private.fill_space then
+ w, _ = base.fit_widget(self, context, v, w, h);
+ end
+ pos = pos + w + spacing
+ end
+
+ if (self._private.dir == "y" and pos-spacing > height) or
+ (self._private.dir ~= "y" and pos-spacing > width) then
+ break
+ end
+ table.insert(result, base.place_widget_at(v, x, y, w, h))
+ end
+ return result
+end
+
+--- Add some widgets to the given fixed layout
+-- @param ... Widgets that should be added (must at least be one)
+function fixed:add(...)
+ -- No table.pack in Lua 5.1 :-(
+ local args = { n=select('#', ...), ... }
+ assert(args.n > 0, "need at least one widget to add")
+ for i=1, args.n do
+ base.check_widget(args[i])
+ table.insert(self._private.widgets, args[i])
+ end
+ self:emit_signal("widget::layout_changed")
+end
+
+
+--- Remove a widget from the layout
+-- @tparam number index The widget index to remove
+-- @treturn boolean index If the operation is successful
+function fixed:remove(index)
+ if not index or index < 1 or index > #self._private.widgets then return false end
+
+ table.remove(self._private.widgets, index)
+
+ self:emit_signal("widget::layout_changed")
+
+ return true
+end
+
+--- Remove one or more widgets from the layout
+-- The last parameter can be a boolean, forcing a recursive seach of the
+-- widget(s) to remove.
+-- @param widget ... Widgets that should be removed (must at least be one)
+-- @treturn boolean If the operation is successful
+function fixed:remove_widgets(...)
+ local args = { ... }
+
+ local recursive = type(args[#args]) == "boolean" and args[#args]
+
+ local ret = true
+ for k, rem_widget in ipairs(args) do
+ if recursive and k == #args then break end
+
+ local idx, l = self:index(rem_widget, recursive)
+
+ if idx and l and l.remove then
+ l:remove(idx, false)
+ else
+ ret = false
+ end
+
+ end
+
+ return #args > (recursive and 1 or 0) and ret
+end
+
+function fixed:get_children()
+ return self._private.widgets
+end
+
+function fixed:set_children(children)
+ self:reset()
+ if #children > 0 then
+ self:add(unpack(children))
+ end
+end
+
+--- Replace the first instance of `widget` in the layout with `widget2`
+-- @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.
+-- @treturn boolean If the operation is successful
+function fixed:replace_widget(widget, widget2, recursive)
+ local idx, l = self:index(widget, recursive)
+
+ if idx and l then
+ l:set(idx, widget2)
+ return true
+ end
+
+ return false
+end
+
+function fixed:swap(index1, index2)
+ if not index1 or not index2 or index1 > #self._private.widgets
+ or index2 > #self._private.widgets then
+ return false
+ end
+
+ local widget1, widget2 = self._private.widgets[index1], self._private.widgets[index2]
+
+ self:set(index1, widget2)
+ self:set(index2, widget1)
+
+ self:emit_signal("widget::swapped", widget1, widget2, index2, index1)
+
+ return true
+end
+
+function fixed:swap_widgets(widget1, widget2, recursive)
+ base.check_widget(widget1)
+ base.check_widget(widget2)
+
+ local idx1, l1 = self:index(widget1, recursive)
+ local idx2, l2 = self:index(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
+
+ return true
+ end
+
+ return false
+end
+
+function fixed:set(index, widget2)
+ if (not widget2) or (not self._private.widgets[index]) then return false end
+
+ 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
+function fixed:insert(index, widget)
+ if not index or index < 1 or index > #self._private.widgets + 1 then return false end
+
+ 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
+
+-- Fit the fixed layout into the given space
+-- @param context The context in which we are fit.
+-- @param orig_width The available width.
+-- @param orig_height The available height.
+function fixed:fit(context, orig_width, orig_height)
+ local width, height = orig_width, orig_height
+ local used_in_dir, used_max = 0, 0
+
+ for _, v in pairs(self._private.widgets) do
+ local w, h = base.fit_widget(self, context, v, width, height)
+ local in_dir, max
+ if self._private.dir == "y" then
+ max, in_dir = w, h
+ height = height - in_dir
+ else
+ in_dir, max = w, h
+ width = width - in_dir
+ end
+ if max > used_max then
+ used_max = max
+ end
+ used_in_dir = used_in_dir + in_dir
+
+ if width <= 0 or height <= 0 then
+ if self._private.dir == "y" then
+ used_in_dir = orig_height
+ else
+ used_in_dir = orig_width
+ end
+ break
+ end
+ end
+
+ local spacing = self._private.spacing * (#self._private.widgets-1)
+
+ if self._private.dir == "y" then
+ return used_max, used_in_dir + spacing
+ end
+ return used_in_dir + spacing, used_max
+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
+-- widget will get all the space that is left. If this is false, the last widget
+-- won't be handled specially and there can be space left unused.
+-- @property fill_space
+
+function fixed:fill_space(val)
+ if self._private.fill_space ~= val then
+ self._private.fill_space = not not val
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+local function get_layout(dir, widget1, ...)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, fixed, true)
+
+ ret._private.dir = dir
+ ret._private.widgets = {}
+ ret:set_spacing(0)
+ ret:fill_space(false)
+
+ if widget1 then
+ ret:add(widget1, ...)
+ end
+
+ return ret
+end
+
+--- Returns a new horizontal fixed layout. Each widget will get as much space as it
+-- asks for and each widget will be drawn next to its neighboring widget.
+-- Widgets can be added via :add() or as arguments to this function.
+-- @tparam widget ... Widgets that should be added to the layout.
+-- @function wibox.layout.fixed.horizontal
+function fixed.horizontal(...)
+ return get_layout("x", ...)
+end
+
+--- Returns a new vertical fixed layout. Each widget will get as much space as it
+-- asks for and each widget will be drawn next to its neighboring widget.
+-- Widgets can be added via :add() or as arguments to this function.
+-- @tparam widget ... Widgets that should be added to the layout.
+-- @function wibox.layout.fixed.vertical
+function fixed.vertical(...)
+ return get_layout("y", ...)
+end
+
+--- Add spacing between each layout widgets
+-- @property spacing
+-- @tparam number spacing Spacing between widgets.
+
+function fixed:set_spacing(spacing)
+ if self._private.spacing ~= spacing then
+ self._private.spacing = spacing
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+function fixed:get_spacing()
+ return self._private.spacing or 0
+end
+
+--Imported documentation
+
+
+--- Get a widex index.
+-- @param widget The widget to look for
+-- @param[opt] recursive Also check sub-widgets
+-- @param[opt] ... Aditional widgets to add at the end of the \"path\"
+-- @return The index
+-- @return The parent layout
+-- @return The path between \"self\" and \"widget\"
+-- @function index
+
+--- Get all direct and indirect children widgets.
+-- This will scan all containers recursively to find widgets
+-- Warning: This method it prone to stack overflow id the widget, or any of its
+-- children, contain (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+
+--- Set a declarative widget hierarchy description.
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
+-- @param args An array containing the widgets disposition
+-- @function setup
+
+--- Force a widget height.
+-- @property forced_height
+-- @tparam number|nil height The height (`nil` for automatic)
+
+--- Force a widget width.
+-- @property forced_width
+-- @tparam number|nil width The width (`nil` for automatic)
+
+--- The widget opacity (transparency).
+-- @property opacity
+-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
+
+--- The widget visibility.
+-- @property visible
+-- @param boolean
+
+--- Set/get a widget's buttons.
+-- @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 emitted when the previous results of `:layout()` and `:fit()`
+-- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()`
+-- must return the same result when called with the same arguments.
+-- @signal widget::layout_changed
+-- @see widget::redraw_needed
+
+--- When the widget content changed.
+-- This signal is emitted when the content of the widget changes. The widget will
+-- be redrawn, it is not re-layouted. Put differently, it is assumed that
+-- `:layout()` and `:fit()` would still return the same results as before.
+-- @signal widget::redraw_needed
+-- @see widget::layout_changed
+
+--- When a mouse button is pressed over the widget.
+-- @signal button::press
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When a mouse button is released over the widget.
+-- @signal button::release
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse enter a widget.
+-- @signal mouse::enter
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse leave a widget.
+-- @signal mouse::leave
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+
+--Imported documentation
+
+
+--- Disconnect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback that should be disconnected
+-- @function disconnect_signal
+
+--- Emit a signal.
+--
+-- @tparam string name The name of the signal
+-- @param ... Extra arguments for the callback functions. Each connected
+-- function receives the object as first argument and then any extra arguments
+-- that are given to emit_signal()
+-- @function emit_signal
+
+--- Connect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function connect_signal
+
+--- Connect to a signal weakly. This allows the callback function to be garbage
+-- collected and automatically disconnects the signal when that happens.
+--
+-- **Warning:**
+-- Only use this function if you really, really, really know what you
+-- are doing.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function weak_connect_signal
+
+
+return fixed
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/flex.lua b/lib/wibox/layout/flex.lua
new file mode 100644
index 0000000..1326f31
--- /dev/null
+++ b/lib/wibox/layout/flex.lua
@@ -0,0 +1,429 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_layout_defaults_flex.svg)
+--
+-- @usage
+--wibox.widget {
+-- generic_widget( 'first' ),
+-- generic_widget( 'second' ),
+-- generic_widget( 'third' ),
+-- layout = wibox.layout.flex.horizontal
+--}
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout.flex
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base")
+local fixed = require("wibox.layout.fixed")
+local table = table
+local pairs = pairs
+local floor = math.floor
+local util = require("awful.util")
+
+local flex = {}
+
+--Imported documentation
+
+--- 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`.
+-- **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.
+-- @treturn boolean If the operation is successful
+-- @name replace_widget
+-- @class function
+
+--- 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.
+-- 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.
+-- @treturn boolean If the operation is successful
+-- @name swap_widgets
+-- @class function
+
+--- Get all direct children of this layout.
+-- @param layout The layout you are modifying.
+-- @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
+
+
+--- Replace the layout children
+-- @tparam table children A table composed of valid widgets
+-- @name set_children
+-- @class function
+
+--- Add some widgets to the given fixed layout
+-- @param layout The layout you are modifying.
+-- @tparam widget ... Widgets that should be added (must at least be one)
+-- @name add
+-- @class function
+
+--- Remove a widget from the layout
+-- @tparam index The widget index to remove
+-- @treturn boolean index If the operation is successful
+-- @name remove
+-- @class function
+
+--- Remove one or more widgets from the layout
+-- The last parameter can be a boolean, forcing a recursive seach of the
+-- widget(s) to remove.
+-- @param widget ... Widgets that should be removed (must at least be one)
+-- @treturn boolean If the operation is successful
+-- @name remove_widgets
+-- @class function
+
+--- Insert a new widget in the layout at position `index`
+-- @tparam number index The position
+-- @param widget The widget
+-- @treturn boolean If the operation is successful
+-- @name insert
+-- @class function
+
+function flex:layout(_, width, height)
+ local result = {}
+ local pos,spacing = 0, self._private.spacing
+ local num = #self._private.widgets
+ local total_spacing = (spacing*(num-1))
+
+ local space_per_item
+ if self._private.dir == "y" then
+ space_per_item = height / num - total_spacing/num
+ else
+ space_per_item = width / num - total_spacing/num
+ end
+
+ if self._private.max_widget_size then
+ space_per_item = math.min(space_per_item, self._private.max_widget_size)
+ end
+
+ for _, v in pairs(self._private.widgets) do
+ local x, y, w, h
+ if self._private.dir == "y" then
+ x, y = 0, util.round(pos)
+ w, h = width, floor(space_per_item)
+ else
+ x, y = util.round(pos), 0
+ w, h = floor(space_per_item), height
+ end
+
+ table.insert(result, base.place_widget_at(v, x, y, w, h))
+
+ pos = pos + space_per_item + spacing
+
+ if (self._private.dir == "y" and pos-spacing >= height) or
+ (self._private.dir ~= "y" and pos-spacing >= width) then
+ break
+ end
+ end
+
+ return result
+end
+
+-- Fit the flex layout into the given space.
+-- @param context The context in which we are fit.
+-- @param orig_width The available width.
+-- @param orig_height The available height.
+function flex:fit(context, orig_width, orig_height)
+ local used_in_dir = 0
+ local used_in_other = 0
+
+ -- Figure out the maximum size we can give out to sub-widgets
+ local sub_height = self._private.dir == "x" and orig_height or orig_height / #self._private.widgets
+ local sub_width = self._private.dir == "y" and orig_width or orig_width / #self._private.widgets
+
+ for _, v in pairs(self._private.widgets) do
+ local w, h = base.fit_widget(self, context, v, sub_width, sub_height)
+
+ local max = self._private.dir == "y" and w or h
+ if max > used_in_other then
+ used_in_other = max
+ end
+
+ used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
+ end
+
+ if self._private.max_widget_size then
+ used_in_dir = math.min(used_in_dir,
+ #self._private.widgets * self._private.max_widget_size)
+ end
+
+ local spacing = self._private.spacing * (#self._private.widgets-1)
+
+ if self._private.dir == "y" then
+ return used_in_other, used_in_dir + spacing
+ end
+ return used_in_dir + spacing, used_in_other
+end
+
+--- Set the maximum size the widgets in this layout will take.
+--That is, maximum width for horizontal and maximum height for vertical.
+-- @property max_widget_size
+-- @param number
+
+function flex:set_max_widget_size(val)
+ if self._private.max_widget_size ~= val then
+ self._private.max_widget_size = val
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+local function get_layout(dir, widget1, ...)
+ local ret = fixed[dir](widget1, ...)
+
+ util.table.crush(ret, flex, true)
+
+ ret._private.fill_space = nil
+
+ return ret
+end
+
+--- Returns a new horizontal flex layout. A flex layout shares the available space
+-- equally among all widgets. Widgets can be added via :add(widget).
+-- @tparam widget ... Widgets that should be added to the layout.
+-- @function wibox.layout.flex.horizontal
+function flex.horizontal(...)
+ return get_layout("horizontal", ...)
+end
+
+--- Returns a new vertical flex layout. A flex layout shares the available space
+-- equally among all widgets. Widgets can be added via :add(widget).
+-- @tparam widget ... Widgets that should be added to the layout.
+-- @function wibox.layout.flex.vertical
+function flex.vertical(...)
+ return get_layout("vertical", ...)
+end
+
+--Imported documentation
+
+
+--- Get a widex index.
+-- @param widget The widget to look for
+-- @param[opt] recursive Also check sub-widgets
+-- @param[opt] ... Aditional widgets to add at the end of the \"path\"
+-- @return The index
+-- @return The parent layout
+-- @return The path between \"self\" and \"widget\"
+-- @function index
+
+--- Get all direct and indirect children widgets.
+-- This will scan all containers recursively to find widgets
+-- Warning: This method it prone to stack overflow id the widget, or any of its
+-- children, contain (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+
+--- Set a declarative widget hierarchy description.
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
+-- @param args An array containing the widgets disposition
+-- @function setup
+
+--- Force a widget height.
+-- @property forced_height
+-- @tparam number|nil height The height (`nil` for automatic)
+
+--- Force a widget width.
+-- @property forced_width
+-- @tparam number|nil width The width (`nil` for automatic)
+
+--- The widget opacity (transparency).
+-- @property opacity
+-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
+
+--- The widget visibility.
+-- @property visible
+-- @param boolean
+
+--- Set/get a widget's buttons.
+-- @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 emitted when the previous results of `:layout()` and `:fit()`
+-- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()`
+-- must return the same result when called with the same arguments.
+-- @signal widget::layout_changed
+-- @see widget::redraw_needed
+
+--- When the widget content changed.
+-- This signal is emitted when the content of the widget changes. The widget will
+-- be redrawn, it is not re-layouted. Put differently, it is assumed that
+-- `:layout()` and `:fit()` would still return the same results as before.
+-- @signal widget::redraw_needed
+-- @see widget::layout_changed
+
+--- When a mouse button is pressed over the widget.
+-- @signal button::press
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When a mouse button is released over the widget.
+-- @signal button::release
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse enter a widget.
+-- @signal mouse::enter
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse leave a widget.
+-- @signal mouse::leave
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+
+--Imported documentation
+
+
+--- Disconnect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback that should be disconnected
+-- @function disconnect_signal
+
+--- Emit a signal.
+--
+-- @tparam string name The name of the signal
+-- @param ... Extra arguments for the callback functions. Each connected
+-- function receives the object as first argument and then any extra arguments
+-- that are given to emit_signal()
+-- @function emit_signal
+
+--- Connect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function connect_signal
+
+--- Connect to a signal weakly. This allows the callback function to be garbage
+-- collected and automatically disconnects the signal when that happens.
+--
+-- **Warning:**
+-- Only use this function if you really, really, really know what you
+-- are doing.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function weak_connect_signal
+
+
+return flex
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/init.lua b/lib/wibox/layout/init.lua
new file mode 100644
index 0000000..4a9b006
--- /dev/null
+++ b/lib/wibox/layout/init.lua
@@ -0,0 +1,23 @@
+---------------------------------------------------------------------------
+--- Collection of layouts that can be used in widget boxes
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout
+---------------------------------------------------------------------------
+local base = require("wibox.widget.base")
+
+return setmetatable({
+ fixed = require("wibox.layout.fixed");
+ align = require("wibox.layout.align");
+ flex = require("wibox.layout.flex");
+ rotate = require("wibox.layout.rotate");
+ margin = require("wibox.layout.margin");
+ mirror = require("wibox.layout.mirror");
+ constraint = require("wibox.layout.constraint");
+ scroll = require("wibox.layout.scroll");
+ ratio = require("wibox.layout.ratio");
+ stack = require("wibox.layout.stack");
+}, {__call = function(_, args) return base.make_widget_declarative(args) end})
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/margin.lua b/lib/wibox/layout/margin.lua
new file mode 100644
index 0000000..8d2eba2
--- /dev/null
+++ b/lib/wibox/layout/margin.lua
@@ -0,0 +1,17 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.margin`
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout.margin
+---------------------------------------------------------------------------
+
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.margin"),
+ "wibox.layout.margin",
+ "wibox.container.margin"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/mirror.lua b/lib/wibox/layout/mirror.lua
new file mode 100644
index 0000000..16be754
--- /dev/null
+++ b/lib/wibox/layout/mirror.lua
@@ -0,0 +1,17 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.mirror`
+--
+-- @author dodo
+-- @copyright 2012 dodo
+-- @classmod wibox.layout.mirror
+---------------------------------------------------------------------------
+
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.mirror"),
+ "wibox.layout.mirror",
+ "wibox.container.mirror"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua
new file mode 100644
index 0000000..bcae443
--- /dev/null
+++ b/lib/wibox/layout/ratio.lua
@@ -0,0 +1,583 @@
+---------------------------------------------------------------------------
+--- A layout filling all the available space. Each widget is assigned a
+-- ratio (percentage) of the total space. Multiple methods are available to
+-- ajust this ratio.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_layout_defaults_ratio.svg)
+--
+-- @usage
+--local w = wibox.widget {
+-- generic_widget( 'first' ),
+-- generic_widget( 'second' ),
+-- generic_widget( 'third' ),
+-- layout = wibox.layout.ratio.horizontal
+--}
+--w:ajust_ratio(2, 0.44, 0.33, 0.22)
+-- @author Emmanuel Lepage Vallee
+-- @copyright 2016 Emmanuel Lepage Vallee
+-- @classmod wibox.layout.ratio
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base" )
+local flex = require("wibox.layout.flex" )
+local table = table
+local pairs = pairs
+local floor = math.floor
+local util = require("awful.util")
+
+local ratio = {}
+
+--Imported documentation
+
+--- 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`.
+-- **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.
+-- @treturn boolean If the operation is successful
+-- @name replace_widget
+-- @class function
+
+--- 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.
+-- 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.
+-- @treturn boolean If the operation is successful
+-- @name swap_widgets
+-- @class function
+
+--- Get all direct children of this layout.
+-- @param layout The layout you are modifying.
+-- @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
+
+
+-- Compute the sum of all ratio (ideally, it should be 1)
+local function gen_sum(self, i_s, i_e)
+ local sum, new_w = 0,0
+
+ for i = i_s or 1, i_e or #self._private.widgets do
+ if self._private.ratios[i] then
+ sum = sum + self._private.ratios[i]
+ else
+ new_w = new_w + 1
+ end
+ end
+
+ return sum, new_w
+end
+
+-- The ratios are expressed as percentages. For this to work, the sum of all
+-- ratio must be 1. This function attempt to ajust them. Space can be taken
+-- from or added to a ratio when widgets are being added or removed. If a
+-- specific ratio must be enforced for a widget, it has to be done with the
+-- `ajust_ratio` method after each insertion or deletion
+local function normalize(self)
+ local count = #self._private.widgets
+ if count == 0 then return end
+
+ -- Instead of adding "if" everywhere, just handle this common case
+ if count == 1 then
+ self._private.ratios = { 1 }
+ return
+ end
+
+ local sum, new_w = gen_sum(self)
+ local old_count = #self._private.widgets - new_w
+
+ local to_add = (sum == 0) and 1 or (sum / old_count)
+
+ -- Make sure all widgets have a ratio
+ for i=1, #self._private.widgets do
+ if not self._private.ratios[i] then
+ self._private.ratios[i] = to_add
+ end
+ end
+
+ sum = sum + to_add*new_w
+
+ local delta, new_sum = (1 - sum) / count,0
+
+ -- Increase or decrease each ratio so it the sum become 1
+ for i=1, #self._private.widgets do
+ self._private.ratios[i] = self._private.ratios[i] + delta
+ new_sum = new_sum + self._private.ratios[i]
+ end
+
+ -- Floating points is not an exact science, but it should still be close
+ -- to 1.00.
+ assert(new_sum > 0.99 and new_sum < 1.01)
+end
+
+function ratio:layout(_, width, height)
+ local result = {}
+ local pos,spacing = 0, self._private.spacing
+
+ for k, v in ipairs(self._private.widgets) do
+ local space
+ local x, y, w, h
+
+ if self._private.dir == "y" then
+ space = height * self._private.ratios[k]
+ x, y = 0, util.round(pos)
+ w, h = width, floor(space)
+ else
+ space = width * self._private.ratios[k]
+ x, y = util.round(pos), 0
+ w, h = floor(space), height
+ end
+
+ table.insert(result, base.place_widget_at(v, x, y, w, h))
+
+ pos = pos + space + spacing
+
+ -- Make sure all widgets fit in the layout, if they aren't, something
+ -- went wrong
+ if (self._private.dir == "y" and util.round(pos) >= height) or
+ (self._private.dir ~= "y" and util.round(pos) >= width) then
+ break
+ end
+ end
+
+ return result
+end
+
+--- Increase the ratio of "widget"
+-- If the increment produce an invalid ratio (not between 0 and 1), the method
+-- do nothing.
+-- @tparam number index The widget index to change
+-- @tparam number increment An floating point value between -1 and 1 where the
+-- end result is within 0 and 1
+function ratio:inc_ratio(index, increment)
+ if #self._private.widgets == 1 or (not index) or (not self._private.ratios[index])
+ or increment < -1 or increment > 1 then
+ return
+ end
+
+ assert(self._private.ratios[index])
+
+ self:set_ratio(index, self._private.ratios[index] + increment)
+end
+
+--- Increment the ratio of the first instance of `widget`
+-- If the increment produce an invalid ratio (not between 0 and 1), the method
+-- do nothing.
+-- @param widget The widget to ajust
+-- @tparam number increment An floating point value between -1 and 1 where the
+-- end result is within 0 and 1
+function ratio:inc_widget_ratio(widget, increment)
+ if not widget or not increment then return end
+
+ local index = self:index(widget)
+
+ self:inc_ratio(index, increment)
+end
+
+--- Set the ratio of the widget at position `index`
+-- @tparam number index The index of the widget to change
+-- @tparam number percent An floating point value between 0 and 1
+function ratio:set_ratio(index, percent)
+ if not percent or #self._private.widgets == 1 or not index or not self._private.widgets[index]
+ or percent < 0 or percent > 1 then
+ return
+ end
+
+ local old = self._private.ratios[index]
+
+ -- Remove what has to be cleared from all widget
+ local delta = ( (percent-old) / (#self._private.widgets-1) )
+
+ for k in pairs(self._private.widgets) do
+ self._private.ratios[k] = self._private.ratios[k] - delta
+ end
+
+ -- Set the new ratio
+ self._private.ratios[index] = percent
+
+ -- As some widgets may now have a slightly negative ratio, normalize again
+ normalize(self)
+
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Get the ratio at `index`.
+-- @tparam number index The widget index to query
+-- @treturn number The index (between 0 and 1)
+function ratio:get_ratio(index)
+ if not index then return end
+ return self._private.ratios[index]
+end
+
+--- Set the ratio of `widget` to `percent`.
+-- @tparam widget widget The widget to ajust.
+-- @tparam number percent A floating point value between 0 and 1.
+function ratio:set_widget_ratio(widget, percent)
+ local index = self:index(widget)
+
+ self:set_ratio(index, percent)
+end
+
+--- Update all widgets to match a set of a ratio.
+-- The sum of before, itself and after must be 1 or nothing will be done
+-- @tparam number index The index of the widget to change
+-- @tparam number before The sum of the ratio before the widget
+-- @tparam number itself The ratio for "widget"
+-- @tparam number after The sum of the ratio after the widget
+function ratio:ajust_ratio(index, before, itself, after)
+ if not self._private.widgets[index] or not before or not itself or not after then
+ return
+ end
+
+ local sum = before + itself + after
+
+ -- As documented, it is the caller job to come up with valid numbers
+ if math.min(before, itself, after) < 0 then return end
+ if sum > 1.01 or sum < -0.99 then return end
+
+ -- Compute the before and after offset to be applied to each widgets
+ local before_count, after_count = index-1, #self._private.widgets - index
+
+ local b, a = gen_sum(self, 1, index-1), gen_sum(self, index+1)
+
+ local db, da = (before - b)/before_count, (after - a)/after_count
+
+ -- Apply the new ratio
+ self._private.ratios[index] = itself
+
+ -- Equality split the delta among widgets before and after
+ for i = 1, index -1 do
+ self._private.ratios[i] = self._private.ratios[i] + db
+ end
+ for i = index+1, #self._private.widgets do
+ self._private.ratios[i] = self._private.ratios[i] + da
+ end
+
+ -- Remove potential negative ratio
+ normalize(self)
+
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Update all widgets to match a set of a ratio
+-- @param widget The widget to ajust
+-- @tparam number before The sum of the ratio before the widget
+-- @tparam number itself The ratio for "widget"
+-- @tparam number after The sum of the ratio after the widget
+function ratio:ajust_widget_ratio(widget, before, itself, after)
+ local index = self:index(widget)
+ self:ajust_ratio(index, 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 :-(
+ local args = { n=select('#', ...), ... }
+ assert(args.n > 0, "need at least one widget to add")
+ for i=1, args.n do
+ base.check_widget(args[i])
+ table.insert(self._private.widgets, args[i])
+ end
+
+ 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)
+ if not index or index < 1 or index > #self._private.widgets + 1 then return false end
+
+ base.check_widget(widget)
+
+ table.insert(self._private.widgets, 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, ...)
+ local ret = flex[dir](widget1, ...)
+
+ util.table.crush(ret, ratio, true)
+
+ ret._private.fill_space = nil
+
+ ret._private.ratios = {}
+
+ return ret
+end
+
+--- Returns a new horizontal ratio layout. A ratio layout shares the available space
+-- equally among all widgets. Widgets can be added via :add(widget).
+-- @tparam widget ... Widgets that should be added to the layout.
+function ratio.horizontal(...)
+ return get_layout("horizontal", ...)
+end
+
+--- Returns a new vertical ratio layout. A ratio layout shares the available space
+-- equally among all widgets. Widgets can be added via :add(widget).
+-- @tparam widget ... Widgets that should be added to the layout.
+function ratio.vertical(...)
+ return get_layout("vertical", ...)
+end
+
+--Imported documentation
+
+
+--- Get a widex index.
+-- @param widget The widget to look for
+-- @param[opt] recursive Also check sub-widgets
+-- @param[opt] ... Aditional widgets to add at the end of the \"path\"
+-- @return The index
+-- @return The parent layout
+-- @return The path between \"self\" and \"widget\"
+-- @function index
+
+--- Get all direct and indirect children widgets.
+-- This will scan all containers recursively to find widgets
+-- Warning: This method it prone to stack overflow id the widget, or any of its
+-- children, contain (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+
+--- Set a declarative widget hierarchy description.
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
+-- @param args An array containing the widgets disposition
+-- @function setup
+
+--- Force a widget height.
+-- @property forced_height
+-- @tparam number|nil height The height (`nil` for automatic)
+
+--- Force a widget width.
+-- @property forced_width
+-- @tparam number|nil width The width (`nil` for automatic)
+
+--- The widget opacity (transparency).
+-- @property opacity
+-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
+
+--- The widget visibility.
+-- @property visible
+-- @param boolean
+
+--- Set/get a widget's buttons.
+-- @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 emitted when the previous results of `:layout()` and `:fit()`
+-- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()`
+-- must return the same result when called with the same arguments.
+-- @signal widget::layout_changed
+-- @see widget::redraw_needed
+
+--- When the widget content changed.
+-- This signal is emitted when the content of the widget changes. The widget will
+-- be redrawn, it is not re-layouted. Put differently, it is assumed that
+-- `:layout()` and `:fit()` would still return the same results as before.
+-- @signal widget::redraw_needed
+-- @see widget::layout_changed
+
+--- When a mouse button is pressed over the widget.
+-- @signal button::press
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When a mouse button is released over the widget.
+-- @signal button::release
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse enter a widget.
+-- @signal mouse::enter
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse leave a widget.
+-- @signal mouse::leave
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+
+--Imported documentation
+
+
+--- Disconnect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback that should be disconnected
+-- @function disconnect_signal
+
+--- Emit a signal.
+--
+-- @tparam string name The name of the signal
+-- @param ... Extra arguments for the callback functions. Each connected
+-- function receives the object as first argument and then any extra arguments
+-- that are given to emit_signal()
+-- @function emit_signal
+
+--- Connect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function connect_signal
+
+--- Connect to a signal weakly. This allows the callback function to be garbage
+-- collected and automatically disconnects the signal when that happens.
+--
+-- **Warning:**
+-- Only use this function if you really, really, really know what you
+-- are doing.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function weak_connect_signal
+
+
+return ratio
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/rotate.lua b/lib/wibox/layout/rotate.lua
new file mode 100644
index 0000000..a6b5d7a
--- /dev/null
+++ b/lib/wibox/layout/rotate.lua
@@ -0,0 +1,17 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.rotate`
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.layout.rotate
+---------------------------------------------------------------------------
+
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.rotate"),
+ "wibox.layout.rotate",
+ "wibox.container.rotate"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/scroll.lua b/lib/wibox/layout/scroll.lua
new file mode 100644
index 0000000..e0be79f
--- /dev/null
+++ b/lib/wibox/layout/scroll.lua
@@ -0,0 +1,16 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.scroll`
+--
+-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
+-- @copyright 2015 Uli Schlachter
+-- @classmod wibox.layout.scroll
+---------------------------------------------------------------------------
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.scroll"),
+ "wibox.layout.scroll",
+ "wibox.container.scroll"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/layout/stack.lua b/lib/wibox/layout/stack.lua
new file mode 100644
index 0000000..bd28703
--- /dev/null
+++ b/lib/wibox/layout/stack.lua
@@ -0,0 +1,402 @@
+---------------------------------------------------------------------------
+-- A stacked layout.
+--
+-- This layout display widgets on top of each other. It can be used to overlay
+-- a `wibox.widget.textbox` on top of a `awful.widget.progressbar` or manage
+-- "pages" where only one is visible at any given moment.
+--
+-- The indices are going from 1 (the bottom of the stack) up to the top of
+-- the stack. The order can be changed either using `:swap` or `:raise`.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_layout_defaults_stack.svg)
+--
+-- @usage
+--wibox.widget {
+-- generic_widget( 'first' ),
+-- generic_widget( 'second' ),
+-- generic_widget( 'third' ),
+-- layout = wibox.layout.stack
+--}
+-- @author Emmanuel Lepage Vallee
+-- @copyright 2016 Emmanuel Lepage Vallee
+-- @classmod wibox.layout.stack
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base" )
+local fixed = require("wibox.layout.fixed")
+local table = table
+local pairs = pairs
+local util = require("awful.util")
+
+local stack = {mt={}}
+
+--Imported documentation
+
+--- 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`.
+-- **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.
+-- @treturn boolean If the operation is successful
+-- @name replace_widget
+-- @class function
+
+--- 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.
+-- 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.
+-- @treturn boolean If the operation is successful
+-- @name swap_widgets
+-- @class function
+
+--- Get all direct children of this layout.
+-- @param layout The layout you are modifying.
+-- @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
+
+
+--- Add some widgets to the given stack layout
+-- @param layout The layout you are modifying.
+-- @tparam widget ... Widgets that should be added (must at least be one)
+-- @name add
+-- @class function
+
+--- Remove a widget from the layout
+-- @tparam index The widget index to remove
+-- @treturn boolean index If the operation is successful
+-- @name remove
+-- @class function
+
+--- Insert a new widget in the layout at position `index`
+-- @tparam number index The position
+-- @param widget The widget
+-- @treturn boolean If the operation is successful
+-- @name insert
+-- @class function
+
+--- Remove one or more widgets from the layout
+-- The last parameter can be a boolean, forcing a recursive seach of the
+-- widget(s) to remove.
+-- @param widget ... Widgets that should be removed (must at least be one)
+-- @treturn boolean If the operation is successful
+-- @name remove_widgets
+-- @class function
+
+--- Add spacing between each layout widgets
+-- @property spacing
+-- @tparam number spacing Spacing between widgets.
+
+function stack:layout(_, width, height)
+ local result = {}
+ local spacing = self._private.spacing
+
+ for _, v in pairs(self._private.widgets) do
+ table.insert(result, base.place_widget_at(v, spacing, spacing, width - 2*spacing, height - 2*spacing))
+ if self._private.top_only then break end
+ end
+
+ return result
+end
+
+function stack:fit(context, orig_width, orig_height)
+ local max_w, max_h = 0,0
+ local spacing = self._private.spacing
+
+ for _, v in pairs(self._private.widgets) do
+ local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
+ max_w, max_h = math.max(max_w, w+2*spacing), math.max(max_h, h+2*spacing)
+ end
+
+ return math.min(max_w, orig_width), math.min(max_h, orig_height)
+end
+
+--- If only the first stack widget is drawn
+-- @property top_only
+
+function stack:get_top_only()
+ return self._private.top_only
+end
+
+function stack:set_top_only(top_only)
+ self._private.top_only = top_only
+end
+
+--- Raise a widget at `index` to the top of the stack
+-- @tparam number index the widget index to raise
+function stack:raise(index)
+ if (not index) or self._private.widgets[index] then return end
+
+ local w = self._private.widgets[index]
+ table.remove(self._private.widgets, index)
+ table.insert(self._private.widgets, w)
+
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Raise the first instance of `widget`
+-- @param widget The widget to raise
+-- @tparam[opt=false] boolean recursive Also look deeper in the hierarchy to
+-- find the widget
+function stack:raise_widget(widget, recursive)
+ local idx, layout = self:index(widget, recursive)
+
+ if not idx or not layout then return end
+
+ -- Bubble up in the stack until the right index is found
+ while layout and layout ~= self do
+ idx, layout = self:index(layout, recursive)
+ end
+
+ if layout == self and idx ~= 1 then
+ self:raise(idx)
+ end
+end
+
+--- Create a new stack layout.
+-- @function wibox.layout.stack
+-- @treturn widget A new stack layout
+
+local function new(...)
+ local ret = fixed.horizontal(...)
+
+ util.table.crush(ret, stack, true)
+
+ return ret
+end
+
+function stack.mt:__call(_, ...)
+ return new(...)
+end
+
+--Imported documentation
+
+
+--- Get a widex index.
+-- @param widget The widget to look for
+-- @param[opt] recursive Also check sub-widgets
+-- @param[opt] ... Aditional widgets to add at the end of the \"path\"
+-- @return The index
+-- @return The parent layout
+-- @return The path between \"self\" and \"widget\"
+-- @function index
+
+--- Get all direct and indirect children widgets.
+-- This will scan all containers recursively to find widgets
+-- Warning: This method it prone to stack overflow id the widget, or any of its
+-- children, contain (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+
+--- Set a declarative widget hierarchy description.
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
+-- @param args An array containing the widgets disposition
+-- @function setup
+
+--- Force a widget height.
+-- @property forced_height
+-- @tparam number|nil height The height (`nil` for automatic)
+
+--- Force a widget width.
+-- @property forced_width
+-- @tparam number|nil width The width (`nil` for automatic)
+
+--- The widget opacity (transparency).
+-- @property opacity
+-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
+
+--- The widget visibility.
+-- @property visible
+-- @param boolean
+
+--- Set/get a widget's buttons.
+-- @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 emitted when the previous results of `:layout()` and `:fit()`
+-- are no longer valid. Unless this signal is emitted, `:layout()` and `:fit()`
+-- must return the same result when called with the same arguments.
+-- @signal widget::layout_changed
+-- @see widget::redraw_needed
+
+--- When the widget content changed.
+-- This signal is emitted when the content of the widget changes. The widget will
+-- be redrawn, it is not re-layouted. Put differently, it is assumed that
+-- `:layout()` and `:fit()` would still return the same results as before.
+-- @signal widget::redraw_needed
+-- @see widget::layout_changed
+
+--- When a mouse button is pressed over the widget.
+-- @signal button::press
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When a mouse button is released over the widget.
+-- @signal button::release
+-- @tparam number lx The horizontal position relative to the (0,0) position in
+-- the widget.
+-- @tparam number ly The vertical position relative to the (0,0) position in the
+-- widget.
+-- @tparam number button The button number.
+-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse enter a widget.
+-- @signal mouse::enter
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+--- When the mouse leave a widget.
+-- @signal mouse::leave
+-- @tparam table find_widgets_result The entry from the result of
+-- @{wibox.drawable:find_widgets} for the position that the mouse hit.
+-- @tparam wibox.drawable find_widgets_result.drawable The drawable containing
+-- the widget.
+-- @tparam widget find_widgets_result.widget The widget being displayed.
+-- @tparam wibox.hierarchy find_widgets_result.hierarchy The hierarchy
+-- managing the widget's geometry.
+-- @tparam number find_widgets_result.x An approximation of the X position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.y An approximation of the Y position that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.width An approximation of the width that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.height An approximation of the height that
+-- the widget is visible at on the surface.
+-- @tparam number find_widgets_result.widget_width The exact width of the widget
+-- in its local coordinate system.
+-- @tparam number find_widgets_result.widget_height The exact height of the widget
+-- in its local coordinate system.
+-- @see mouse
+
+
+--Imported documentation
+
+
+--- Disconnect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback that should be disconnected
+-- @function disconnect_signal
+
+--- Emit a signal.
+--
+-- @tparam string name The name of the signal
+-- @param ... Extra arguments for the callback functions. Each connected
+-- function receives the object as first argument and then any extra arguments
+-- that are given to emit_signal()
+-- @function emit_signal
+
+--- Connect to a signal.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function connect_signal
+
+--- Connect to a signal weakly. This allows the callback function to be garbage
+-- collected and automatically disconnects the signal when that happens.
+--
+-- **Warning:**
+-- Only use this function if you really, really, really know what you
+-- are doing.
+-- @tparam string name The name of the signal
+-- @tparam function func The callback to call when the signal is emitted
+-- @function weak_connect_signal
+
+
+return setmetatable(stack, stack.mt)
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80