summaryrefslogtreecommitdiff
path: root/lib/wibox
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
Init commit
Diffstat (limited to 'lib/wibox')
-rw-r--r--lib/wibox/container/arcchart.lua566
-rw-r--r--lib/wibox/container/background.lua626
-rw-r--r--lib/wibox/container/constraint.lua371
-rw-r--r--lib/wibox/container/init.lua21
-rw-r--r--lib/wibox/container/margin.lua419
-rw-r--r--lib/wibox/container/mirror.lua340
-rw-r--r--lib/wibox/container/radialprogressbar.lua481
-rw-r--r--lib/wibox/container/rotate.lua384
-rw-r--r--lib/wibox/container/scroll.lua716
-rw-r--r--lib/wibox/drawable.lua489
-rw-r--r--lib/wibox/hierarchy.lua333
-rw-r--r--lib/wibox/init.lua479
-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
-rw-r--r--lib/wibox/widget/background.lua16
-rw-r--r--lib/wibox/widget/base.lua694
-rw-r--r--lib/wibox/widget/checkbox.lua530
-rw-r--r--lib/wibox/widget/graph.lua575
-rw-r--r--lib/wibox/widget/imagebox.lua395
-rw-r--r--lib/wibox/widget/init.lua22
-rw-r--r--lib/wibox/widget/piechart.lua467
-rw-r--r--lib/wibox/widget/progressbar.lua754
-rw-r--r--lib/wibox/widget/slider.lua709
-rw-r--r--lib/wibox/widget/systray.lua186
-rw-r--r--lib/wibox/widget/textbox.lua507
-rw-r--r--lib/wibox/widget/textclock.lua254
35 files changed, 12966 insertions, 0 deletions
diff --git a/lib/wibox/container/arcchart.lua b/lib/wibox/container/arcchart.lua
new file mode 100644
index 0000000..3794630
--- /dev/null
+++ b/lib/wibox/container/arcchart.lua
@@ -0,0 +1,566 @@
+---------------------------------------------------------------------------
+--
+-- A circular chart (arc chart).
+--
+-- It can contain a central widget (or not) and display multiple values.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_arcchart.svg)
+--
+-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
+-- @copyright 2013 Emmanuel Lepage Vallee
+-- @classmod wibox.container.arcchart
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local base = require("wibox.widget.base")
+local shape = require("gears.shape" )
+local util = require( "awful.util" )
+local color = require( "gears.color" )
+local beautiful = require("beautiful" )
+
+
+local arcchart = { mt = {} }
+
+--- The progressbar border background color.
+-- @beautiful beautiful.arcchart_border_color
+
+--- The progressbar foreground color.
+-- @beautiful beautiful.arcchart_color
+
+--- The progressbar border width.
+-- @beautiful beautiful.arcchart_border_width
+
+--- The padding between the outline and the progressbar.
+-- @beautiful beautiful.arcchart_paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+--- The arc thickness.
+-- @beautiful beautiful.thickness
+-- @param number
+
+local function outline_workarea(width, height)
+ local x, y = 0, 0
+ local size = math.min(width, height)
+
+ return {x=x+(width-size)/2, y=y+(height-size)/2, width=size, height=size}
+end
+
+-- The child widget area
+local function content_workarea(self, width, height)
+ local padding = self._private.paddings or {}
+ local border_width = self:get_border_width() or 0
+ local wa = outline_workarea(width, height)
+ local thickness = math.max(border_width, self:get_thickness() or 5)
+
+ wa.x = wa.x + (padding.left or 0) + thickness + 2*border_width
+ wa.y = wa.y + (padding.top or 0) + thickness + 2*border_width
+ wa.width = wa.width - (padding.left or 0) - (padding.right or 0)
+ - 2*thickness - 4*border_width
+ wa.height = wa.height - (padding.top or 0) - (padding.bottom or 0)
+ - 2*thickness - 4*border_width
+
+ return wa
+end
+
+-- Draw the radial outline and progress
+function arcchart:after_draw_children(_, cr, width, height)
+ cr:restore()
+
+ local values = self:get_values() or {}
+ local border_width = self:get_border_width() or 0
+ local thickness = math.max(border_width, self:get_thickness() or 5)
+
+ local offset = thickness + 2*border_width
+
+ -- Draw a circular background
+ local bg = self:get_bg()
+ if bg then
+ cr:save()
+ cr:translate(offset/2, offset/2)
+ shape.circle(
+ cr,
+ width-offset,
+ height-offset
+ )
+ cr:set_line_width(thickness+2*border_width)
+ cr:set_source(color(bg))
+ cr:stroke()
+ cr:restore()
+ end
+
+ if #values == 0 then
+ return
+ end
+
+ local wa = outline_workarea(width, height)
+ cr:translate(wa.x+border_width/2, wa.y+border_width/2)
+
+
+ -- Get the min and max value
+ --local min_val = self:get_min_value() or 0 --TODO support min_values
+ local max_val = self:get_max_value()
+ local sum = 0
+
+ if not max_val then
+ for _, v in ipairs(values) do
+ sum = sum + v
+ end
+ max_val = sum
+ end
+
+ max_val = math.max(max_val, sum)
+
+ local use_rounded_edges = sum ~= max_val and self:get_rounded_edge()
+
+ -- Fallback to the current foreground color
+ local colors = self:get_colors() or {}
+
+ -- Draw the outline
+ local offset_angle = self:get_start_angle() or math.pi
+ local start_angle, end_angle = offset_angle, offset_angle
+
+ for k, v in ipairs(values) do
+ end_angle = start_angle + (v*2*math.pi) / max_val
+
+ if colors[k] then
+ cr:set_source(color(colors[k]))
+ end
+
+ shape.arc(cr, wa.width-border_width, wa.height-border_width,
+ thickness+border_width, math.pi-end_angle, math.pi-start_angle,
+ (use_rounded_edges and k == 1), (use_rounded_edges and k == #values)
+ )
+
+ cr:fill()
+ start_angle = end_angle
+ end
+
+ if border_width > 0 then
+ local border_color = self:get_border_color()
+
+ cr:set_source(color(border_color))
+ cr:set_line_width(border_width)
+
+ shape.arc(cr, wa.width-border_width, wa.height-border_width,
+ thickness+border_width, math.pi-end_angle, math.pi-offset_angle,
+ use_rounded_edges, use_rounded_edges
+ )
+ cr:stroke()
+ end
+
+end
+
+-- Set the clip
+function arcchart:before_draw_children(_, cr, width, height)
+ cr:save()
+ local wa = content_workarea(self, width, height)
+ cr:translate(wa.x, wa.y)
+ shape.circle(
+ cr,
+ wa.width,
+ wa.height
+ )
+ cr:clip()
+ cr:translate(-wa.x, -wa.y)
+end
+
+-- Layout this layout
+function arcchart:layout(_, width, height)
+ if self._private.widget then
+ local wa = content_workarea(self, width, height)
+
+ return { base.place_widget_at(
+ self._private.widget, wa.x, wa.y, wa.width, wa.height
+ ) }
+ end
+end
+
+-- Fit this layout into the given area
+function arcchart:fit(_, width, height)
+ local size = math.min(width, height)
+ return size, size
+end
+
+--- The widget to wrap in a radial proggressbar.
+-- @property widget
+-- @tparam widget widget The widget
+
+function arcchart:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Get the children elements.
+-- @treturn table The children
+function arcchart:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function arcchart:set_children(children)
+ self._private.widget = children and children[1]
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Reset this layout. The widget will be removed and the rotation reset.
+function arcchart:reset()
+ self:set_widget(nil)
+end
+
+for _,v in ipairs {"left", "right", "top", "bottom"} do
+ arcchart["set_"..v.."_padding"] = function(self, val)
+ self._private.paddings = self._private.paddings or {}
+ self._private.paddings[v] = val
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- The padding between the outline and the progressbar.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_paddings.svg)
+--
+-- @property paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+--- The border background color.
+--
+-- @property border_color
+
+--- The border foreground color.
+--
+-- @property color
+
+--- The border width.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_border_width.svg)
+--
+-- @property border_width
+-- @tparam[opt=3] number border_width
+
+--- The minimum value.
+-- @property min_value
+
+--- The maximum value.
+-- @property max_value
+
+--- The radial background.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_bg.svg)
+--
+-- @property bg
+-- @param color
+-- @see gears.color
+
+--- The value.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_value.svg)
+--
+-- @property value
+-- @tparam number value Between min_value and max_value
+-- @see values
+
+--- The values.
+-- The arcchart is designed to display multiple values at once. Each will be
+-- shown in table order.
+--
+-- @property values
+-- @tparam table values An ordered set if values.
+-- @see value
+
+--- If the chart has rounded edges.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_rounded_edge.svg)
+--
+-- @property rounded_edge
+-- @param[opt=false] boolean
+
+--- The arc thickness.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_thickness.svg)
+--
+-- @property thickness
+-- @param number
+
+--- The (radiant) angle where the first value start.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_arcchart_start_angle.svg)
+--
+-- @property start_angle
+-- @param[opt=math.pi] number A number between 0 and 2*math.pi
+
+for _, prop in ipairs {"border_width", "border_color", "paddings", "colors",
+ "rounded_edge", "bg", "thickness", "values", "min_value", "max_value",
+ "start_angle" } do
+ arcchart["set_"..prop] = function(self, value)
+ self._private[prop] = value
+ self:emit_signal("property::"..prop)
+ self:emit_signal("widget::redraw_needed")
+ end
+ arcchart["get_"..prop] = function(self)
+ return self._private[prop] or beautiful["arcchart_"..prop]
+ end
+end
+
+function arcchart:set_paddings(val)
+ self._private.paddings = type(val) == "number" and {
+ left = val,
+ right = val,
+ top = val,
+ bottom = val,
+ } or val or {}
+ self:emit_signal("property::paddings")
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+end
+
+function arcchart:set_value(value)
+ self:set_values {value}
+end
+
+--- Returns a new arcchart layout.
+-- @param[opt] widget The widget to display.
+-- @function wibox.container.arcchart
+local function new(widget)
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret, arcchart)
+
+ ret:set_widget(widget)
+
+ return ret
+end
+
+function arcchart.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(arcchart, arcchart.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua
new file mode 100644
index 0000000..2fb88c3
--- /dev/null
+++ b/lib/wibox/container/background.lua
@@ -0,0 +1,626 @@
+---------------------------------------------------------------------------
+-- A container capable of changing the background color, foreground color
+-- widget shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_background.svg)
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.container.background
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base")
+local color = require("gears.color")
+local surface = require("gears.surface")
+local beautiful = require("beautiful")
+local cairo = require("lgi").cairo
+local util = require("awful.util")
+local setmetatable = setmetatable
+local type = type
+local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
+
+local background = { mt = {} }
+
+-- Draw this widget
+function background:draw(context, cr, width, height)
+ if not self._private.widget or not self._private.widget:get_visible() then
+ return
+ end
+
+ -- Keep the shape path in case there is a border
+ self._private.path = nil
+
+ if self._private.shape then
+ -- Only add the offset if there is something to draw
+ local offset = ((self._private.shape_border_width and self._private.shape_border_color)
+ and self._private.shape_border_width or 0) / 2
+
+ cr:translate(offset, offset)
+ self._private.shape(cr, width - 2*offset, height - 2*offset, unpack(self._private.shape_args or {}))
+ cr:translate(-offset, -offset)
+ self._private.path = cr:copy_path()
+ cr:clip()
+ end
+
+ if self._private.background then
+ cr:set_source(self._private.background)
+ cr:paint()
+ end
+ if self._private.bgimage then
+ if type(self._private.bgimage) == "function" then
+ self._private.bgimage(context, cr, width, height,unpack(self._private.bgimage_args))
+ else
+ local pattern = cairo.Pattern.create_for_surface(self._private.bgimage)
+ cr:set_source(pattern)
+ cr:paint()
+ end
+ end
+
+end
+
+-- Draw the border
+function background:after_draw_children(_, cr)
+ -- Draw the border
+ if self._private.path and self._private.shape_border_width and self._private.shape_border_width > 0 then
+ cr:append_path(self._private.path)
+ cr:set_source(color(self._private.shape_border_color or self._private.foreground or beautiful.fg_normal))
+
+ cr:set_line_width(self._private.shape_border_width)
+ cr:stroke()
+ self._private.path = nil
+ end
+end
+
+-- Prepare drawing the children of this widget
+function background:before_draw_children(_, cr)
+ if self._private.foreground then
+ cr:set_source(self._private.foreground)
+ end
+
+ -- Clip the shape
+ if self._private.path and self._private.shape_clip then
+ cr:append_path(self._private.path)
+ cr:clip()
+ end
+end
+
+-- Layout this widget
+function background:layout(_, width, height)
+ if self._private.widget then
+ return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
+ end
+end
+
+-- Fit this widget into the given area
+function background:fit(context, width, height)
+ if not self._private.widget then
+ return 0, 0
+ end
+
+ return base.fit_widget(self, context, self._private.widget, width, height)
+end
+
+--- The widget displayed in the background widget.
+-- @property widget
+-- @tparam widget widget The widget to be disaplayed inside of the background
+-- area
+
+function background:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+function background:get_widget()
+ return self._private.widget
+end
+
+-- Get children element
+-- @treturn table The children
+function background:get_children()
+ return {self._private.widget}
+end
+
+-- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function background:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- The background color/pattern/gradient to use.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_background_bg.svg)
+--
+-- @usage
+--local text_widget = {
+-- text = 'Hello world!',
+-- widget = wibox.widget.textbox
+--}
+--parent : setup {
+-- {
+-- text_widget,
+-- bg = '#ff0000',
+-- widget = wibox.container.background
+-- },
+-- {
+-- text_widget,
+-- bg = '#00ff00',
+-- widget = wibox.container.background
+-- },
+-- {
+-- text_widget,
+-- bg = '#0000ff',
+-- widget = wibox.container.background
+-- },
+-- spacing = 10,
+-- layout = wibox.layout.fixed.vertical
+--}
+-- @property bg
+-- @param bg A color string, pattern or gradient
+-- @see gears.color
+
+function background:set_bg(bg)
+ if bg then
+ self._private.background = color(bg)
+ else
+ self._private.background = nil
+ end
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_bg()
+ return self._private.background
+end
+
+--- The foreground (text) color/pattern/gradient to use.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_background_fg.svg)
+--
+-- @usage
+--local text_widget = {
+-- text = 'Hello world!',
+-- widget = wibox.widget.textbox
+--}
+--parent : setup {
+-- {
+-- text_widget,
+-- fg = '#ff0000',
+-- widget = wibox.container.background
+-- },
+-- {
+-- text_widget,
+-- fg = '#00ff00',
+-- widget = wibox.container.background
+-- },
+-- {
+-- text_widget,
+-- fg = '#0000ff',
+-- widget = wibox.container.background
+-- },
+-- spacing = 10,
+-- layout = wibox.layout.fixed.vertical
+--}
+-- @property fg
+-- @param fg A color string, pattern or gradient
+-- @see gears.color
+
+function background:set_fg(fg)
+ if fg then
+ self._private.foreground = color(fg)
+ else
+ self._private.foreground = nil
+ end
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_fg()
+ return self._private.foreground
+end
+
+--- The background shap e.
+--
+-- Use `set_shape` to set additional shape paramaters.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_background_shape.svg)
+--
+-- @usage
+--parent : setup {
+-- {
+-- -- Adding a shape without margin may result in cropped output
+-- {
+-- text = 'Hello world!',
+-- widget = wibox.widget.textbox
+-- },
+-- shape = gears.shape.hexagon,
+-- bg = beautiful.bg_normal,
+-- shape_border_color = beautiful.border_color,
+-- shape_border_width = beautiful.border_width,
+-- widget = wibox.container.background
+-- },
+-- {
+-- -- To solve this, use a margin
+-- {
+-- {
+-- text = 'Hello world!',
+-- widget = wibox.widget.textbox
+-- },
+-- left = 10,
+-- right = 10,
+-- top = 3,
+-- bottom = 3,
+-- widget = wibox.container.margin
+-- },
+-- shape = gears.shape.hexagon,
+-- bg = beautiful.bg_normal,
+-- shape_border_color = beautiful.border_color,
+-- shape_border_width = beautiful.border_width,
+-- widget = wibox.container.background
+-- },
+-- spacing = 10,
+-- layout = wibox.layout.fixed.vertical
+--}
+-- @property shape
+-- @param shape A function taking a context, width and height as arguments
+-- @see gears.shape
+-- @see set_shape
+
+--- Set the background shape.
+--
+-- Any other arguments will be passed to the shape function
+-- @param shape A function taking a context, width and height as arguments
+-- @see gears.shape
+-- @see shape
+function background:set_shape(shape, ...)
+ local args = {...}
+
+ if shape == self._private.shape and #args == 0 then return end
+
+ self._private.shape = shape
+ self._private.shape_args = {...}
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_shape()
+ return self._private.shape
+end
+
+--- When a `shape` is set, also draw a border.
+--
+-- See `wibox.container.background.shape` for an usage example.
+-- @property shape_border_width
+-- @tparam number width The border width
+
+function background:set_shape_border_width(width)
+ if self._private.shape_border_width == width then return end
+
+ self._private.shape_border_width = width
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_shape_border_width()
+ return self._private.shape_border_width
+end
+
+--- When a `shape` is set, also draw a border.
+--
+-- See `wibox.container.background.shape` for an usage example.
+-- @property shape_border_color
+-- @param[opt=self._private.foreground] fg The border color, pattern or gradient
+-- @see gears.color
+
+function background:set_shape_border_color(fg)
+ if self._private.shape_border_color == fg then return end
+
+ self._private.shape_border_color = fg
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_shape_border_color()
+ return self._private.shape_border_color
+end
+
+--- When a `shape` is set, make sure nothing is drawn outside of it.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_background_clip.svg)
+--
+-- @usage
+--parent : setup {
+-- {
+-- -- Some content may be outside of the shape
+-- {
+-- text = 'Hello\nworld!',
+-- widget = wibox.widget.textbox
+-- },
+-- shape = gears.shape.circle,
+-- bg = beautiful.bg_normal,
+-- shape_border_color = beautiful.border_color,
+-- widget = wibox.container.background
+-- },
+-- {
+-- -- To solve this, clip the content
+-- {
+-- text = 'Hello\nworld!',
+-- widget = wibox.widget.textbox
+-- },
+-- shape_clip = true,
+-- shape = gears.shape.circle,
+-- bg = beautiful.bg_normal,
+-- shape_border_color = beautiful.border_color,
+-- widget = wibox.container.background
+-- },
+-- spacing = 10,
+-- layout = wibox.layout.fixed.vertical
+--}
+-- @property shape_clip
+-- @tparam boolean value If the shape clip is enable
+
+function background:set_shape_clip(value)
+ if self._private.shape_clip == value then return end
+
+ self._private.shape_clip = value
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_shape_clip()
+ return self._private.shape_clip or false
+end
+
+--- The background image to use
+-- If `image` is a function, it will be called with `(context, cr, width, height)`
+-- as arguments. Any other arguments passed to this method will be appended.
+-- @property bgimage
+-- @param image A background image or a function
+-- @see gears.surface
+
+function background:set_bgimage(image, ...)
+ self._private.bgimage = type(image) == "function" and image or surface.load(image)
+ self._private.bgimage_args = {...}
+ self:emit_signal("widget::redraw_needed")
+end
+
+function background:get_bgimage()
+ return self._private.bgimage
+end
+
+--- Returns a new background container.
+--
+-- A background container applies a background and foreground color
+-- to another widget.
+-- @param[opt] widget The widget to display.
+-- @param[opt] bg The background to use for that widget.
+-- @param[opt] shape A `gears.shape` compatible shape function
+-- @function wibox.container.background
+local function new(widget, bg, shape)
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret, background, true)
+
+ ret._private.shape = shape
+
+ ret:set_widget(widget)
+ ret:set_bg(bg)
+
+ return ret
+end
+
+function background.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(background, background.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua
new file mode 100644
index 0000000..a210387
--- /dev/null
+++ b/lib/wibox/container/constraint.lua
@@ -0,0 +1,371 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_constraint.svg)
+--
+-- @author Lukáš Hrázký
+-- @copyright 2012 Lukáš Hrázký
+-- @classmod wibox.container.constraint
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local base = require("wibox.widget.base")
+local util = require("awful.util")
+local math = math
+
+local constraint = { mt = {} }
+
+-- Layout a constraint layout
+function constraint:layout(_, width, height)
+ if self._private.widget then
+ return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
+ end
+end
+
+-- Fit a constraint layout into the given space
+function constraint:fit(context, width, height)
+ local w, h
+ if self._private.widget then
+ w = self._private.strategy(width, self._private.width)
+ h = self._private.strategy(height, self._private.height)
+
+ w, h = base.fit_widget(self, context, self._private.widget, w, h)
+ else
+ w, h = 0, 0
+ end
+
+ w = self._private.strategy(w, self._private.width)
+ h = self._private.strategy(h, self._private.height)
+
+ return w, h
+end
+
+--- The widget to be constrained.
+-- @property widget
+-- @tparam widget widget The widget
+
+function constraint:set_widget(widget)
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+function constraint:get_widget()
+ return self._private.widget
+end
+
+--- Get the number of children element
+-- @treturn table The children
+function constraint:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function constraint:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- Set the strategy to use for the constraining. Valid values are 'max',
+-- 'min' or 'exact'. Throws an error on invalid values.
+-- @property strategy
+
+function constraint:set_strategy(val)
+ local func = {
+ min = function(real_size, limit)
+ return limit and math.max(limit, real_size) or real_size
+ end,
+ max = function(real_size, limit)
+ return limit and math.min(limit, real_size) or real_size
+ end,
+ exact = function(real_size, limit)
+ return limit or real_size
+ end
+ }
+
+ if not func[val] then
+ error("Invalid strategy for constraint layout: " .. tostring(val))
+ end
+
+ self._private.strategy = func[val]
+ self:emit_signal("widget::layout_changed")
+end
+
+function constraint:get_strategy()
+ return self._private.strategy
+end
+
+--- Set the maximum width to val. nil for no width limit.
+-- @property height
+-- @param number
+
+function constraint:set_width(val)
+ self._private.width = val
+ self:emit_signal("widget::layout_changed")
+end
+
+function constraint:get_width()
+ return self._private.width
+end
+
+--- Set the maximum height to val. nil for no height limit.
+-- @property width
+-- @param number
+
+function constraint:set_height(val)
+ self._private.height = val
+ self:emit_signal("widget::layout_changed")
+end
+
+function constraint:get_height()
+ return self._private.height
+end
+
+--- Reset this layout. The widget will be unreferenced, strategy set to "max"
+-- and the constraints set to nil.
+function constraint:reset()
+ self._private.width = nil
+ self._private.height = nil
+ self:set_strategy("max")
+ self:set_widget(nil)
+end
+
+--- Returns a new constraint container.
+-- This container will constraint the size of a
+-- widget according to the strategy. Note that this will only work for layouts
+-- that respect the widget's size, eg. fixed layout. In layouts that don't
+-- (fully) respect widget's requested size, the inner widget still might get
+-- drawn with a size that does not fit the constraint, eg. in flex layout.
+-- @param[opt] widget A widget to use.
+-- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or
+-- 'exact'.
+-- @param[opt] width The maximum width of the widget. nil for no limit.
+-- @param[opt] height The maximum height of the widget. nil for no limit.
+-- @treturn table A new constraint container
+-- @function wibox.container.constraint
+local function new(widget, strategy, width, height)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, constraint, true)
+
+ ret:set_strategy(strategy or "max")
+ ret:set_width(width)
+ ret:set_height(height)
+
+ if widget then
+ ret:set_widget(widget)
+ end
+
+ return ret
+end
+
+function constraint.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(constraint, constraint.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/init.lua b/lib/wibox/container/init.lua
new file mode 100644
index 0000000..93158ab
--- /dev/null
+++ b/lib/wibox/container/init.lua
@@ -0,0 +1,21 @@
+---------------------------------------------------------------------------
+--- Collection of containers that can be used in widget boxes
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.container
+---------------------------------------------------------------------------
+local base = require("wibox.widget.base")
+
+return setmetatable({
+ rotate = require("wibox.container.rotate");
+ margin = require("wibox.container.margin");
+ mirror = require("wibox.container.mirror");
+ constraint = require("wibox.container.constraint");
+ scroll = require("wibox.container.scroll");
+ background = require("wibox.container.background");
+ radialprogressbar = require("wibox.container.radialprogressbar");
+ arcchart = require("wibox.container.arcchart");
+}, {__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/container/margin.lua b/lib/wibox/container/margin.lua
new file mode 100644
index 0000000..edf9673
--- /dev/null
+++ b/lib/wibox/container/margin.lua
@@ -0,0 +1,419 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_margin.svg)
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.container.margin
+---------------------------------------------------------------------------
+
+local pairs = pairs
+local setmetatable = setmetatable
+local base = require("wibox.widget.base")
+local gcolor = require("gears.color")
+local cairo = require("lgi").cairo
+local util = require("awful.util")
+
+local margin = { mt = {} }
+
+-- Draw a margin layout
+function margin:draw(_, cr, width, height)
+ local x = self._private.left
+ local y = self._private.top
+ local w = self._private.right
+ local h = self._private.bottom
+ local color = self._private.color
+
+ if not self._private.widget or width <= x + w or height <= y + h then
+ return
+ end
+
+ if color then
+ cr:set_source(color)
+ cr:rectangle(0, 0, width, height)
+ cr:rectangle(x, y, width - x - w, height - y - h)
+ cr:set_fill_rule(cairo.FillRule.EVEN_ODD)
+ cr:fill()
+ end
+end
+
+-- Layout a margin layout
+function margin:layout(_, width, height)
+ if self._private.widget then
+ local x = self._private.left
+ local y = self._private.top
+ local w = self._private.right
+ local h = self._private.bottom
+
+ return { base.place_widget_at(self._private.widget, x, y, width - x - w, height - y - h) }
+ end
+end
+
+-- Fit a margin layout into the given space
+function margin:fit(context, width, height)
+ local extra_w = self._private.left + self._private.right
+ local extra_h = self._private.top + self._private.bottom
+ local w, h = 0, 0
+ if self._private.widget then
+ w, h = base.fit_widget(self, context, self._private.widget, width - extra_w, height - extra_h)
+ end
+
+ if self._private.draw_empty == false and (w == 0 or h == 0) then
+ return 0, 0
+ end
+
+ return w + extra_w, h + extra_h
+end
+
+--- The widget to be wrapped the the margins.
+-- @property widget
+-- @tparam widget widget The widget
+
+function margin:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+function margin:get_widget()
+ return self._private.widget
+end
+
+-- Get the number of children element
+-- @treturn table The children
+function margin:get_children()
+ return {self._private.widget}
+end
+
+-- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function margin:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- Set all the margins to val.
+-- @property margins
+-- @tparam number val The margin value
+
+function margin:set_margins(val)
+ if self._private.left == val and
+ self._private.right == val and
+ self._private.top == val and
+ self._private.bottom == val then
+ return
+ end
+
+ self._private.left = val
+ self._private.right = val
+ self._private.top = val
+ self._private.bottom = val
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Set the margins color to create a border.
+-- @property color
+-- @param color A color used to fill the margin.
+
+function margin:set_color(color)
+ self._private.color = color and gcolor(color)
+ self:emit_signal("widget::redraw_needed")
+end
+
+function margin:get_color()
+ return self._private.color
+end
+
+--- Draw the margin even if the content size is 0x0 (default: true)
+-- @function draw_empty
+-- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway
+
+function margin:set_draw_empty(draw_empty)
+ self._private.draw_empty = draw_empty
+ self:emit_signal("widget::layout_changed")
+end
+
+function margin:get_draw_empty()
+ return self._private.draw_empty
+end
+
+--- Reset this layout. The widget will be unreferenced, the margins set to 0
+-- and the color erased
+function margin:reset()
+ self:set_widget(nil)
+ self:set_margins(0)
+ self:set_color(nil)
+end
+
+--- Set the left margin that this layout adds to its widget.
+-- @param margin The new margin to use.
+-- @property left
+
+--- Set the right margin that this layout adds to its widget.
+-- @param margin The new margin to use.
+-- @property right
+
+--- Set the top margin that this layout adds to its widget.
+-- @param margin The new margin to use.
+-- @property top
+
+--- Set the bottom margin that this layout adds to its widget.
+-- @param margin The new margin to use.
+-- @property bottom
+
+-- Create setters for each direction
+for _, v in pairs({ "left", "right", "top", "bottom" }) do
+ margin["set_" .. v] = function(layout, val)
+ if layout._private[v] == val then return end
+ layout._private[v] = val
+ layout:emit_signal("widget::layout_changed")
+ end
+
+ margin["get_" .. v] = function(layout)
+ return layout._private[v]
+ end
+end
+
+--- Returns a new margin container.
+-- @param[opt] widget A widget to use.
+-- @param[opt] left A margin to use on the left side of the widget.
+-- @param[opt] right A margin to use on the right side of the widget.
+-- @param[opt] top A margin to use on the top side of the widget.
+-- @param[opt] bottom A margin to use on the bottom side of the widget.
+-- @param[opt] color A color for the margins.
+-- @param[opt] draw_empty whether or not to draw the margin when the content is empty
+-- @treturn table A new margin container
+-- @function wibox.container.margin
+local function new(widget, left, right, top, bottom, color, draw_empty)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, margin, true)
+
+ ret:set_left(left or 0)
+ ret:set_right(right or 0)
+ ret:set_top(top or 0)
+ ret:set_bottom(bottom or 0)
+ ret:set_draw_empty(draw_empty)
+
+ ret:set_color(color)
+
+ if widget then
+ ret:set_widget(widget)
+ end
+
+ return ret
+end
+
+function margin.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(margin, margin.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua
new file mode 100644
index 0000000..fc275cf
--- /dev/null
+++ b/lib/wibox/container/mirror.lua
@@ -0,0 +1,340 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_mirror.svg)
+--
+-- @author dodo
+-- @copyright 2012 dodo
+-- @classmod wibox.container.mirror
+---------------------------------------------------------------------------
+
+local type = type
+local error = error
+local ipairs = ipairs
+local setmetatable = setmetatable
+local base = require("wibox.widget.base")
+local matrix = require("gears.matrix")
+local util = require("awful.util")
+
+local mirror = { mt = {} }
+
+-- Layout this layout
+function mirror:layout(_, width, height)
+ if not self._private.widget then return end
+
+ local m = matrix.identity
+ local t = { x = 0, y = 0 } -- translation
+ local s = { x = 1, y = 1 } -- scale
+ if self._private.horizontal then
+ t.x = width
+ s.x = -1
+ end
+ if self._private.vertical then
+ t.y = height
+ s.y = -1
+ end
+ m = m:translate(t.x, t.y)
+ m = m:scale(s.x, s.y)
+
+ return { base.place_widget_via_matrix(self._private.widget, m, width, height) }
+end
+
+-- Fit this layout into the given area
+function mirror:fit(context, ...)
+ if not self._private.widget then
+ return 0, 0
+ end
+ return base.fit_widget(self, context, self._private.widget, ...)
+end
+
+--- The widget to be reflected.
+-- @property widget
+-- @tparam widget widget The widget
+
+function mirror:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+function mirror:get_widget()
+ return self._private.widget
+end
+
+--- Get the number of children element
+-- @treturn table The children
+function mirror:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function mirror:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- Reset this layout. The widget will be removed and the axes reset.
+function mirror:reset()
+ self._private.horizontal = false
+ self._private.vertical = false
+ self:set_widget(nil)
+end
+
+function mirror:set_reflection(reflection)
+ if type(reflection) ~= 'table' then
+ error("Invalid type of reflection for mirror layout: " ..
+ type(reflection) .. " (should be a table)")
+ end
+ for _, ref in ipairs({"horizontal", "vertical"}) do
+ if reflection[ref] ~= nil then
+ self._private[ref] = reflection[ref]
+ end
+ end
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Get the reflection of this mirror layout.
+-- @property reflection
+-- @param table reflection A table of booleans with the keys "horizontal", "vertical".
+-- @param boolean reflection.horizontal
+-- @param boolean reflection.vertical
+
+function mirror:get_reflection()
+ return { horizontal = self._private.horizontal, vertical = self._private.vertical }
+end
+
+--- Returns a new mirror container.
+-- A mirror container mirrors a given widget. Use
+-- `:set_widget()` to set the widget and
+-- `:set_horizontal()` and `:set_vertical()` for the direction.
+-- horizontal and vertical are by default false which doesn't change anything.
+-- @param[opt] widget The widget to display.
+-- @param[opt] reflection A table describing the reflection to apply.
+-- @treturn table A new mirror container
+-- @function wibox.container.mirror
+local function new(widget, reflection)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+ ret._private.horizontal = false
+ ret._private.vertical = false
+
+ util.table.crush(ret, mirror, true)
+
+ ret:set_widget(widget)
+ ret:set_reflection(reflection or {})
+
+ return ret
+end
+
+function mirror.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(mirror, mirror.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/radialprogressbar.lua b/lib/wibox/container/radialprogressbar.lua
new file mode 100644
index 0000000..7c67906
--- /dev/null
+++ b/lib/wibox/container/radialprogressbar.lua
@@ -0,0 +1,481 @@
+---------------------------------------------------------------------------
+--
+-- A circular progressbar wrapper.
+--
+-- If no child `widget` is set, then the radialprogressbar will take all the
+-- available size. Use a `wibox.container.constraint` to prevent this.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_radialprogressbar.svg)
+--
+-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
+-- @copyright 2013 Emmanuel Lepage Vallee
+-- @classmod wibox.container.radialprogressbar
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local base = require("wibox.widget.base")
+local shape = require("gears.shape" )
+local util = require( "awful.util" )
+local color = require( "gears.color" )
+local beautiful = require("beautiful" )
+
+local default_outline_width = 2
+
+local radialprogressbar = { mt = {} }
+
+--- The progressbar border background color.
+-- @beautiful beautiful.radialprogressbar_border_color
+
+--- The progressbar foreground color.
+-- @beautiful beautiful.radialprogressbar_color
+
+--- The progressbar border width.
+-- @beautiful beautiful.radialprogressbar_border_width
+
+--- The padding between the outline and the progressbar.
+-- @beautiful beautiful.radialprogressbar_paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+local function outline_workarea(self, width, height)
+ local border_width = self._private.border_width or
+ beautiful.radialprogressbar_border_width or default_outline_width
+
+ local x, y = 0, 0
+
+ -- Make sure the border fit in the clip area
+ local offset = border_width/2
+ x, y = x + offset, y+offset
+ width, height = width-2*offset, height-2*offset
+
+ return {x=x, y=y, width=width, height=height}, offset
+end
+
+-- The child widget area
+local function content_workarea(self, width, height)
+ local padding = self._private.paddings or {}
+ local wa = outline_workarea(self, width, height)
+
+ wa.x = wa.x + (padding.left or 0)
+ wa.y = wa.y + (padding.top or 0)
+ wa.width = wa.width - (padding.left or 0) - (padding.right or 0)
+ wa.height = wa.height - (padding.top or 0) - (padding.bottom or 0)
+
+ return wa
+end
+
+-- Draw the radial outline and progress
+function radialprogressbar:after_draw_children(_, cr, width, height)
+ cr:restore()
+
+ local border_width = self._private.border_width or
+ beautiful.radialprogressbar_border_width or default_outline_width
+
+ local wa = outline_workarea(self, width, height)
+ cr:translate(wa.x, wa.y)
+
+ -- Draw the outline
+ shape.rounded_bar(cr, wa.width, wa.height)
+ cr:set_source(color(self:get_border_color() or "#0000ff"))
+ cr:set_line_width(border_width)
+ cr:stroke()
+
+ -- Draw the progress
+ cr:set_source(color(self:get_color() or "#ff00ff"))
+ shape.radial_progress(cr, wa.width, wa.height, self._percent or 0)
+ cr:set_line_width(border_width)
+ cr:stroke()
+
+end
+
+-- Set the clip
+function radialprogressbar:before_draw_children(_, cr, width, height)
+ cr:save()
+ local wa = content_workarea(self, width, height)
+ cr:translate(wa.x, wa.y)
+ shape.rounded_bar(cr, wa.width, wa.height)
+ cr:clip()
+ cr:translate(-wa.x, -wa.y)
+end
+
+-- Layout this layout
+function radialprogressbar:layout(_, width, height)
+ if self._private.widget then
+ local wa = content_workarea(self, width, height)
+
+ return { base.place_widget_at(
+ self._private.widget, wa.x, wa.y, wa.width, wa.height
+ ) }
+ end
+end
+
+-- Fit this layout into the given area
+function radialprogressbar:fit(context, width, height)
+ if self._private.widget then
+ local wa = content_workarea(self, width, height)
+ local w, h = base.fit_widget(self, context, self._private.widget, wa.width, wa.height)
+ return wa.x + w, wa.y + h
+ end
+
+ return width, height
+end
+
+--- The widget to wrap in a radial proggressbar.
+-- @property widget
+-- @tparam widget widget The widget
+
+function radialprogressbar:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Get the children elements
+-- @treturn table The children
+function radialprogressbar:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function radialprogressbar:set_children(children)
+ self._private.widget = children and children[1]
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Reset this container.
+function radialprogressbar:reset()
+ self:set_widget(nil)
+end
+
+for _,v in ipairs {"left", "right", "top", "bottom"} do
+ radialprogressbar["set_"..v.."_padding"] = function(self, val)
+ self._private.paddings = self._private.paddings or {}
+ self._private.paddings[v] = val
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- The padding between the outline and the progressbar.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_padding.svg)
+--
+-- @property paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+--- The progressbar value.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_value.svg)
+--
+-- @property value
+-- @tparam number value Between min_value and max_value
+
+function radialprogressbar:set_value(val)
+ if not val then self._percent = 0; return end
+
+ if val > self._private.max_value then
+ self:set_max_value(val)
+ elseif val < self._private.min_value then
+ self:set_min_value(val)
+ end
+
+ local delta = self._private.max_value - self._private.min_value
+
+ self._percent = val/delta
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- The border background color.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_border_color.svg)
+--
+-- @property border_color
+
+--- The border foreground color.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_color.svg)
+--
+-- @property color
+
+--- The border width.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_radialprogressbar_border_width.svg)
+--
+-- @property border_width
+-- @tparam[opt=3] number border_width
+
+--- The minimum value.
+-- @property min_value
+
+--- The maximum value.
+-- @property max_value
+
+for _, prop in ipairs {"max_value", "min_value", "border_color", "color",
+ "border_width", "paddings"} do
+ radialprogressbar["set_"..prop] = function(self, value)
+ self._private[prop] = value
+ self:emit_signal("property::"..prop)
+ self:emit_signal("widget::redraw_needed")
+ end
+ radialprogressbar["get_"..prop] = function(self)
+ return self._private[prop] or beautiful["radialprogressbar_"..prop]
+ end
+end
+
+function radialprogressbar:set_paddings(val)
+ self._private.paddings = type(val) == "number" and {
+ left = val,
+ right = val,
+ top = val,
+ bottom = val,
+ } or val or {}
+ self:emit_signal("property::paddings")
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Returns a new radialprogressbar layout. A radialprogressbar layout
+-- radialprogressbars a given widget. Use `.widget` to set the widget.
+-- @param[opt] widget The widget to display.
+-- @function wibox.container.radialprogressbar
+local function new(widget)
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret, radialprogressbar)
+ ret._private.max_value = 1
+ ret._private.min_value = 0
+
+ ret:set_widget(widget)
+
+ return ret
+end
+
+function radialprogressbar.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(radialprogressbar, radialprogressbar.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua
new file mode 100644
index 0000000..5fe4a8e
--- /dev/null
+++ b/lib/wibox/container/rotate.lua
@@ -0,0 +1,384 @@
+---------------------------------------------------------------------------
+-- A container rotating the conained widget by 90 degrees.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_defaults_rotate.svg)
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.container.rotate
+---------------------------------------------------------------------------
+
+local error = error
+local pi = math.pi
+local setmetatable = setmetatable
+local tostring = tostring
+local base = require("wibox.widget.base")
+local matrix = require("gears.matrix")
+local util = require("awful.util")
+
+local rotate = { mt = {} }
+
+local function transform(layout, width, height)
+ local dir = layout:get_direction()
+ if dir == "east" or dir == "west" then
+ return height, width
+ end
+ return width, height
+end
+
+-- Layout this layout
+function rotate:layout(_, width, height)
+ if not self._private.widget or not self._private.widget._private.visible then
+ return
+ end
+
+ local dir = self:get_direction()
+
+ local m = matrix.identity
+ if dir == "west" then
+ m = m:rotate(pi / 2)
+ m = m:translate(0, -width)
+ elseif dir == "south" then
+ m = m:rotate(pi)
+ m = m:translate(-width, -height)
+ elseif dir == "east" then
+ m = m:rotate(3 * pi / 2)
+ m = m:translate(-height, 0)
+ end
+
+ -- Since we rotated, we might have to swap width and height.
+ -- transform() does that for us.
+ return { base.place_widget_via_matrix(self._private.widget, m, transform(self, width, height)) }
+end
+
+-- Fit this layout into the given area
+function rotate:fit(context, width, height)
+ if not self._private.widget then
+ return 0, 0
+ end
+ return transform(self, base.fit_widget(self, context, self._private.widget, transform(self, width, height)))
+end
+
+--- The widget to be rotated.
+-- @property widget
+-- @tparam widget widget The widget
+
+function rotate:set_widget(widget)
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+end
+
+function rotate:get_widget()
+ return self._private.widget
+end
+
+--- Get the number of children element
+-- @treturn table The children
+function rotate:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function rotate:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- Reset this layout. The widget will be removed and the rotation reset.
+function rotate:reset()
+ self._private.direction = nil
+ self:set_widget(nil)
+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
+
+
+--- The direction of this rotating container.
+-- Valid values are:
+--
+-- * *north*
+-- * *east*
+-- * *south*
+-- * *north*
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_container_rotate_angle.svg)
+--
+-- @usage
+--local normal = create_arrow('Normal')
+--local north = wibox.container {
+-- create_arrow('North'),
+-- direction = 'north',
+-- widget = wibox.container.rotate
+--}
+--local south = wibox.container {
+-- create_arrow('South'),
+-- direction = 'south',
+-- widget = wibox.container.rotate
+--}
+--local east = wibox.container {
+-- create_arrow('East'),
+-- direction = 'east',
+-- widget = wibox.container.rotate
+--}
+--local west = wibox.container {
+-- create_arrow('West'),
+-- direction = 'west',
+-- widget = wibox.container.rotate
+--}
+-- @property direction
+-- @tparam string dir The direction
+
+function rotate:set_direction(dir)
+ local allowed = {
+ north = true,
+ east = true,
+ south = true,
+ west = true
+ }
+
+ if not allowed[dir] then
+ error("Invalid direction for rotate layout: " .. tostring(dir))
+ end
+
+ self._private.direction = dir
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Get the direction of this rotating layout
+function rotate:get_direction()
+ return self._private.direction or "north"
+end
+
+--- Returns a new rotate container.
+-- A rotate container rotates a given widget. Use
+-- :set_widget() to set the widget and :set_direction() for the direction.
+-- The default direction is "north" which doesn't change anything.
+-- @param[opt] widget The widget to display.
+-- @param[opt] dir The direction to rotate to.
+-- @treturn table A new rotate container.
+-- @function wibox.container.rotate
+local function new(widget, dir)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, rotate, true)
+
+ ret:set_widget(widget)
+ ret:set_direction(dir or "north")
+
+ return ret
+end
+
+function rotate.mt:__call(...)
+ return new(...)
+end
+
+return setmetatable(rotate, rotate.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/container/scroll.lua b/lib/wibox/container/scroll.lua
new file mode 100644
index 0000000..0fb2ad5
--- /dev/null
+++ b/lib/wibox/container/scroll.lua
@@ -0,0 +1,716 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
+-- @copyright 2015 Uli Schlachter
+-- @classmod wibox.container.scroll
+---------------------------------------------------------------------------
+
+local cache = require("gears.cache")
+local timer = require("gears.timer")
+local hierarchy = require("wibox.hierarchy")
+local base = require("wibox.widget.base")
+local lgi = require("lgi")
+local GLib = lgi.GLib
+
+local scroll = {}
+local scroll_mt = { __index = scroll }
+local _need_scroll_redraw
+
+-- "Strip" a context so that we can use it for our own drawing
+local function cleanup_context(context)
+ local skip = { wibox = true, drawable = true, client = true, position = true }
+ local res = {}
+ for k, v in pairs(context) do
+ if not skip[k] then
+ res[k] = v
+ end
+ end
+ return res
+end
+
+-- Create a hierarchy (and some more stuff) for drawing the given widget. This
+-- allows "some stuff" to be re-used instead of re-created all the time.
+local hierarchy_cache = cache.new(function(context, widget, width, height)
+ context = cleanup_context(context)
+ local layouts = setmetatable({}, { __mode = "k" })
+
+ -- Create a widget hierarchy and update when needed
+ local hier
+ local function do_pending_updates(layout)
+ layouts[layout] = true
+ hier:update(context, widget, width, height, nil)
+ end
+ local function emit(signal)
+ -- Make the scroll layouts redraw
+ for w in pairs(layouts) do
+ w:emit_signal(signal)
+ end
+ end
+ local function redraw_callback()
+ emit("widget::redraw_needed")
+ end
+ local function layout_callback()
+ emit("widget::redraw_needed")
+ emit("widget::layout_changed")
+ end
+ hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil)
+
+ return hier, do_pending_updates, context
+end)
+
+--- Calculate all the information needed for scrolling.
+-- @param self The instance of the scrolling layout.
+-- @param context A widget context under which we are fit/drawn.
+-- @param width The available width
+-- @param height The available height
+-- @return A table with the following entries
+-- @field fit_width The width that should be returned from :fit
+-- @field fit_height The height that should be returned from :fit
+-- @field surface_width The width for showing the child widget
+-- @field surface_height The height for showing the child widget
+-- @field first_x The x offset for drawing the child the first time
+-- @field first_y The y offset for drawing the child the first time
+-- @field[opt] second_x The x offset for drawing the child the second time
+-- @field[opt] second_y The y offset for drawing the child the second time
+-- @field hierarchy The wibox.hierarchy instance representing "everything"
+-- @field context The widget context for drawing the hierarchy
+local function calculate_info(self, context, width, height)
+ local result = {}
+ assert(self._private.widget)
+
+ -- First, get the size of the widget (and the size of extra space)
+ local surface_width, surface_height = width, height
+ local extra_width, extra_height, extra = 0, 0, self._private.expand and self._private.extra_space or 0
+ local w, h
+ if self._private.dir == "h" then
+ w, h = base.fit_widget(self, context, self._private.widget, self._private.space_for_scrolling, height)
+ surface_width = w
+ extra_width = extra
+ else
+ w, h = base.fit_widget(self, context, self._private.widget, width, self._private.space_for_scrolling)
+ surface_height = h
+ extra_height = extra
+ end
+ result.fit_width, result.fit_height = w, h
+ if self._private.dir == "h" then
+ if self._private.max_size then
+ result.fit_width = math.min(w, self._private.max_size)
+ end
+ else
+ if self._private.max_size then
+ result.fit_height = math.min(h, self._private.max_size)
+ end
+ end
+ if w > width or h > height then
+ -- There is less space available than we need, we have to scroll
+ _need_scroll_redraw(self)
+
+ surface_width, surface_height = surface_width + extra_width, surface_height + extra_height
+
+ local x, y = 0, 0
+ local function get_scroll_offset(size, visible_size)
+ return self._private.step_function(self._private.timer:elapsed(), size, visible_size, self._private.speed, self._private.extra_space)
+ end
+ if self._private.dir == "h" then
+ x = -get_scroll_offset(surface_width - extra, width)
+ else
+ y = -get_scroll_offset(surface_height - extra, height)
+ end
+ result.first_x, result.first_y = x, y
+ -- Was the extra space already included elsewhere?
+ local extra_spacer = self._private.expand and 0 or self._private.extra_space
+ if self._private.dir == "h" then
+ x = x + surface_width + extra_spacer
+ else
+ y = y + surface_height + extra_spacer
+ end
+ result.second_x, result.second_y = x, y
+ else
+ result.first_x, result.first_y = 0, 0
+ end
+ result.surface_width, result.surface_height = surface_width, surface_height
+
+ -- Get the hierarchy and subscribe ourselves to updates
+ local hier, do_pending_updates, ctx = hierarchy_cache:get(context,
+ self._private.widget, surface_width, surface_height)
+ result.hierarchy = hier
+ result.context = ctx
+ do_pending_updates(self)
+
+ return result
+end
+
+-- Draw this scrolling layout.
+-- @param context The context in which we are drawn.
+-- @param cr The cairo context to draw to.
+-- @param width The available width.
+-- @param height The available height.
+function scroll:draw(context, cr, width, height)
+ if not self._private.widget then
+ return
+ end
+
+ local info = calculate_info(self, context, width, height)
+
+ -- Draw the first instance of the child
+ cr:save()
+ cr:translate(info.first_x, info.first_y)
+ cr:rectangle(0, 0, info.surface_width, info.surface_height)
+ cr:clip()
+ info.hierarchy:draw(info.context, cr)
+ cr:restore()
+
+ -- If there is one, draw the second instance (same code as above, minus the
+ -- clip)
+ if info.second_x and info.second_y then
+ cr:translate(info.second_x, info.second_y)
+ cr:rectangle(0, 0, info.surface_width, info.surface_height)
+ cr:clip()
+ info.hierarchy:draw(info.context, cr)
+ end
+end
+
+-- Fit the scroll layout into the given space.
+-- @param context The context in which we are fit.
+-- @param width The available width.
+-- @param height The available height.
+function scroll:fit(context, width, height)
+ if not self._private.widget then
+ return 0, 0
+ end
+ local info = calculate_info(self, context, width, height)
+ return info.fit_width, info.fit_height
+end
+
+-- Internal function used for triggering redraws for scrolling.
+-- The purpose is to start a timer for redrawing the widget for scrolling.
+-- Redrawing works by simply emitting the `widget::redraw_needed` signal.
+-- Pausing is implemented in this function: We just don't start a timer.
+-- This function must be idempotent (calling it multiple times right after
+-- another does not make a difference).
+_need_scroll_redraw = function(self)
+ if not self._private.paused and not self._private.scroll_timer then
+ self._private.scroll_timer = timer.start_new(1 / self._private.fps, function()
+ self._private.scroll_timer = nil
+ self:emit_signal("widget::redraw_needed")
+ end)
+ end
+end
+
+--- Pause the scrolling animation.
+-- @see continue
+function scroll:pause()
+ if self._private.paused then
+ return
+ end
+ self._private.paused = true
+ self._private.timer:stop()
+end
+
+--- Continue the scrolling animation.
+-- @see pause
+function scroll:continue()
+ if not self._private.paused then
+ return
+ end
+ self._private.paused = false
+ self._private.timer:continue()
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Reset the scrolling state to its initial condition.
+-- For must scroll step functions, the effect of this function should be to
+-- display the widget without any scrolling applied.
+-- This function does not undo the effect of @{pause}.
+function scroll:reset_scrolling()
+ self._private.timer:start()
+ if self._private.paused then
+ self._private.timer:stop()
+ end
+end
+
+--- Set the direction in which this widget scroll.
+-- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling
+function scroll:set_direction(dir)
+ if dir == self._private.dir then
+ return
+ end
+ if dir ~= "h" and dir ~= "v" then
+ error("Invalid direction, can only be 'h' or 'v'")
+ end
+ self._private.dir = dir
+ self:emit_signal("widget::layout_changed")
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- The widget to be scrolled.
+-- @property widget
+-- @tparam widget widget The widget
+
+function scroll:set_widget(widget)
+ if widget == self._private.widget then
+ return
+ end
+ if widget then
+ base.check_widget(widget)
+ end
+ self._private.widget = widget
+ self:emit_signal("widget::layout_changed")
+ self:emit_signal("widget::redraw_needed")
+end
+
+function scroll:get_widget()
+ return self._private.widget
+end
+
+--- Get the number of children element
+-- @treturn table The children
+function scroll:get_children()
+ return {self._private.widget}
+end
+
+--- Replace the layout children
+-- This layout only accept one children, all others will be ignored
+-- @tparam table children A table composed of valid widgets
+function scroll:set_children(children)
+ self:set_widget(children[1])
+end
+
+--- Specify the expand mode that is used for extra space.
+-- @tparam boolean expand If true, the widget is expanded to include the extra
+-- space. If false, the extra space is simply left empty.
+-- @see set_extra_space
+function scroll:set_expand(expand)
+ if expand == self._private.expand then
+ return
+ end
+ self._private.expand = expand
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Set the number of frames per second that this widget should draw.
+-- @tparam number fps The number of frames per second
+function scroll:set_fps(fps)
+ if fps == self._private.fps then
+ return
+ end
+ self._private.fps = fps
+ -- No signal needed: If we are scrolling, the next redraw will apply the new
+ -- FPS, else it obviously doesn't make a difference.
+end
+
+--- Set the amount of extra space that should be included in the scrolling. This
+-- extra space will likely be left empty between repetitions of the widgets.
+-- @tparam number extra_space The amount of extra space
+-- @see set_expand
+function scroll:set_extra_space(extra_space)
+ if extra_space == self._private.extra_space then
+ return
+ end
+ self._private.extra_space = extra_space
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Set the speed of the scrolling animation. The exact meaning depends on the
+-- step function that is used, but for the simplest step functions, this will be
+-- in pixels per second.
+-- @tparam number speed The speed for the animation
+function scroll:set_speed(speed)
+ if speed == self._private.speed then
+ return
+ end
+ self._private.speed = speed
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Set the maximum size of this widget in the direction set by
+-- @{set_direction}. If the child widget is smaller than this size, no scrolling
+-- is done. If the child widget is larger, then only this size will be visible
+-- and the rest is made visible via scrolling.
+-- @tparam number max_size The maximum size of this widget or nil for unlimited.
+function scroll:set_max_size(max_size)
+ if max_size == self._private.max_size then
+ return
+ end
+ self._private.max_size = max_size
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Set the step function that determines the exact behaviour of the scrolling
+-- animation.
+-- The step function is called with five arguments:
+--
+-- * The time in seconds since the state of the animation
+-- * The size of the child widget
+-- * The size of the visible part of the widget
+-- * The speed of the animation. This should have a linear effect on this
+-- function's behaviour.
+-- * The extra space configured by @{set_extra_space}. This was not yet added to
+-- the size of the child widget, but should likely be added to it in most
+-- cases.
+--
+-- The step function should return a single number. This number is the offset at
+-- which the widget is drawn and should be between 0 and `size+extra_space`.
+-- @tparam function step_function A step function.
+-- @see step_functions
+function scroll:set_step_function(step_function)
+ -- Call the step functions once to see if it works
+ step_function(0, 42, 10, 10, 5)
+ if step_function == self._private.step_function then
+ return
+ end
+ self._private.step_function = step_function
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Set an upper limit for the space for scrolling.
+-- This restricts the child widget's maximal size.
+-- @tparam number space_for_scrolling The space for scrolling
+function scroll:set_space_for_scrolling(space_for_scrolling)
+ if space_for_scrolling == self._private.space_for_scrolling then
+ return
+ end
+ self._private.space_for_scrolling = space_for_scrolling
+ self:emit_signal("widget::layout_changed")
+end
+
+local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ ret._private.paused = false
+ ret._private.timer = GLib.Timer()
+ ret._private.scroll_timer = nil
+
+ setmetatable(ret, scroll_mt)
+
+ ret:set_direction(dir)
+ ret:set_widget(widget)
+ ret:set_fps(fps or 20)
+ ret:set_speed(speed or 10)
+ ret:set_extra_space(extra_space or 0)
+ ret:set_expand(expand)
+ ret:set_max_size(max_size)
+ ret:set_step_function(step_function or scroll.step_functions.linear_increase)
+ ret:set_space_for_scrolling(space_for_scrolling or 2^1024)
+
+ return ret
+end
+
+--- Get a new horizontal scrolling container.
+-- @param[opt] widget The widget that should be scrolled
+-- @param[opt=20] fps The number of frames per second
+-- @param[opt=10] speed The speed of the animation
+-- @param[opt=0] extra_space The amount of extra space to include
+-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
+-- extra space?
+-- @param[opt] max_size The maximum size of the child widget
+-- @param[opt=step_functions.linear_increase] step_function The step function to be used
+-- @param[opt=2^1024] space_for_scrolling The space for scrolling
+function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
+ return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
+end
+
+--- Get a new vertical scrolling container.
+-- @param[opt] widget The widget that should be scrolled
+-- @param[opt=20] fps The number of frames per second
+-- @param[opt=10] speed The speed of the animation
+-- @param[opt=0] extra_space The amount of extra space to include
+-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
+-- extra space?
+-- @param[opt] max_size The maximum size of the child widget
+-- @param[opt=step_functions.linear_increase] step_function The step function to be used
+-- @param[opt=2^1024] space_for_scrolling The space for scrolling
+function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
+ return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
+end
+
+--- A selection of step functions
+-- @see set_step_function
+scroll.step_functions = {}
+
+--- A step function that scrolls the widget in an increasing direction with
+-- constant speed.
+function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space)
+ return (elapsed * speed) % (size + extra_space)
+end
+
+--- A step function that scrolls the widget in an decreasing direction with
+-- constant speed.
+function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space)
+ return (-elapsed * speed) % (size + extra_space)
+end
+
+--- A step function that scrolls the widget to its end and back to its
+-- beginning, then back to its end, etc. The speed is constant.
+function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed)
+ local state = ((elapsed * speed) % (2 * size)) / size
+ state = state <= 1 and state or 2 - state
+ return (size - visible_size) * state
+end
+
+--- A step function that scrolls the widget to its end and back to its
+-- beginning, then back to its end, etc. The speed is null at the ends and
+-- maximal in the middle.
+function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed)
+ local state = ((elapsed * speed) % (2 * size)) / size
+ local negate = false
+ if state > 1 then
+ negate = true
+ state = state - 1
+ end
+ if state < 1/3 then
+ -- In the first 1/3rd of time, do a quadratic increase in speed
+ state = 2 * state * state
+ elseif state < 2/3 then
+ -- In the center, do a linear increase. That means we need:
+ -- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
+ -- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
+ state = 5/3*state - 3/9
+ else
+ -- In the last 1/3rd of time, do a quadratic decrease in speed
+ state = 1 - 2 * (1 - state) * (1 - state)
+ end
+ if negate then
+ state = 1 - state
+ end
+ return (size - visible_size) * state
+end
+
+--- A step function that scrolls the widget to its end and back to its
+-- beginning, then back to its end, etc. The speed is null at the ends and
+-- maximal in the middle. At both ends the widget stands still for a moment.
+function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed)
+ local state = ((elapsed * speed) % (2 * size)) / size
+ local negate = false
+ if state > 1 then
+ negate = true
+ state = state - 1
+ end
+ if state < 1/5 or state > 4/5 then
+ -- One fifth of time, nothing moves
+ state = state < 1/5 and 0 or 1
+ else
+ state = (state - 1/5) * 5/3
+ if state < 1/3 then
+ -- In the first 1/3rd of time, do a quadratic increase in speed
+ state = 2 * state * state
+ elseif state < 2/3 then
+ -- In the center, do a linear increase. That means we need:
+ -- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
+ -- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
+ state = 5/3*state - 3/9
+ else
+ -- In the last 1/3rd of time, do a quadratic decrease in speed
+ state = 1 - 2 * (1 - state) * (1 - state)
+ end
+ end
+ if negate then
+ state = 1 - state
+ end
+ return (size - visible_size) * state
+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 scroll
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/drawable.lua b/lib/wibox/drawable.lua
new file mode 100644
index 0000000..330edc3
--- /dev/null
+++ b/lib/wibox/drawable.lua
@@ -0,0 +1,489 @@
+---------------------------------------------------------------------------
+--- Handling of drawables. A drawable is something that can be drawn to.
+--
+-- @author Uli Schlachter
+-- @copyright 2012 Uli Schlachter
+-- @classmod wibox.drawable
+---------------------------------------------------------------------------
+
+local drawable = {}
+local capi = {
+ awesome = awesome,
+ root = root,
+ screen = screen
+}
+local beautiful = require("beautiful")
+local cairo = require("lgi").cairo
+local color = require("gears.color")
+local object = require("gears.object")
+local surface = require("gears.surface")
+local timer = require("gears.timer")
+local grect = require("gears.geometry").rectangle
+local matrix = require("gears.matrix")
+local hierarchy = require("wibox.hierarchy")
+local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
+
+local visible_drawables = {}
+
+-- Get the widget context. This should always return the same table (if
+-- possible), so that our draw and fit caches can work efficiently.
+local function get_widget_context(self)
+ local geom = self.drawable:geometry()
+
+ local s = self._forced_screen
+ if not s then
+ local sgeos = {}
+
+ for scr in capi.screen do
+ sgeos[scr] = scr.geometry
+ end
+
+ s = grect.get_by_coord(sgeos, geom.x, geom.y) or capi.screen.primary
+ end
+
+ local context = self._widget_context
+ local dpi = beautiful.xresources.get_dpi(s)
+ if (not context) or context.screen ~= s or context.dpi ~= dpi then
+ context = {
+ screen = s,
+ dpi = dpi,
+ drawable = self,
+ }
+ for k, v in pairs(self._widget_context_skeleton) do
+ context[k] = v
+ end
+ self._widget_context = context
+
+ -- Give widgets a chance to react to the new context
+ self._need_complete_repaint = true
+ end
+ return context
+end
+
+local function do_redraw(self)
+ if not self.drawable.valid then return end
+ if self._forced_screen and not self._forced_screen.valid then return end
+
+ local surf = surface.load_silently(self.drawable.surface, false)
+ -- The surface can be nil if the drawable's parent was already finalized
+ if not surf then return end
+ local cr = cairo.Context(surf)
+ local geom = self.drawable:geometry();
+ local x, y, width, height = geom.x, geom.y, geom.width, geom.height
+ local context = get_widget_context(self)
+
+ -- Relayout
+ if self._need_relayout or self._need_complete_repaint then
+ self._need_relayout = false
+ if self._widget_hierarchy and self.widget then
+ self._widget_hierarchy:update(context,
+ self.widget, width, height, self._dirty_area)
+ else
+ self._need_complete_repaint = true
+ if self.widget then
+ self._widget_hierarchy_callback_arg = {}
+ self._widget_hierarchy = hierarchy.new(context, self.widget, width, height,
+ self._redraw_callback, self._layout_callback, self._widget_hierarchy_callback_arg)
+ else
+ self._widget_hierarchy = nil
+ end
+ end
+
+ if self._need_complete_repaint then
+ self._need_complete_repaint = false
+ self._dirty_area:union_rectangle(cairo.RectangleInt{
+ x = 0, y = 0, width = width, height = height
+ })
+ end
+ end
+
+ -- Clip to the dirty area
+ if self._dirty_area:is_empty() then
+ return
+ end
+ for i = 0, self._dirty_area:num_rectangles() - 1 do
+ local rect = self._dirty_area:get_rectangle(i)
+ cr:rectangle(rect.x, rect.y, rect.width, rect.height)
+ end
+ self._dirty_area = cairo.Region.create()
+ cr:clip()
+
+ -- Draw the background
+ cr:save()
+
+ if not capi.awesome.composite_manager_running then
+ -- This is pseudo-transparency: We draw the wallpaper in the background
+ local wallpaper = surface.load_silently(capi.root.wallpaper(), false)
+ if wallpaper then
+ cr.operator = cairo.Operator.SOURCE
+ cr:set_source_surface(wallpaper, -x, -y)
+ cr:paint()
+ end
+ cr.operator = cairo.Operator.OVER
+ else
+ -- This is true transparency: We draw a translucent background
+ cr.operator = cairo.Operator.SOURCE
+ end
+
+ cr:set_source(self.background_color)
+ cr:paint()
+
+ cr:restore()
+
+ -- Paint the background image
+ if self.background_image then
+ cr:save()
+ if type(self.background_image) == "function" then
+ self.background_image(context, cr, width, height, unpack(self.background_image_args))
+ else
+ local pattern = cairo.Pattern.create_for_surface(self.background_image)
+ cr:set_source(pattern)
+ cr:paint()
+ end
+ cr:restore()
+ end
+
+ -- Draw the widget
+ if self._widget_hierarchy then
+ cr:set_source(self.foreground_color)
+ self._widget_hierarchy:draw(context, cr)
+ end
+
+ self.drawable:refresh()
+
+ assert(cr.status == "SUCCESS", "Cairo context entered error state: " .. cr.status)
+end
+
+local function find_widgets(_drawable, result, _hierarchy, x, y)
+ local m = _hierarchy:get_matrix_from_device()
+
+ -- Is (x,y) inside of this hierarchy or any child (aka the draw extents)
+ local x1, y1 = m:transform_point(x, y)
+ local x2, y2, w2, h2 = _hierarchy:get_draw_extents()
+ if x1 < x2 or x1 >= x2 + w2 then
+ return
+ end
+ if y1 < y2 or y1 >= y2 + h2 then
+ return
+ end
+
+ -- Is (x,y) inside of this widget?
+ local width, height = _hierarchy:get_size()
+ if x1 >= 0 and y1 >= 0 and x1 <= width and y1 <= height then
+ -- Get the extents of this widget in the device space
+ local x3, y3, w3, h3 = matrix.transform_rectangle(_hierarchy:get_matrix_to_device(),
+ 0, 0, width, height)
+ table.insert(result, {
+ x = x3, y = y3, width = w3, height = h3,
+ widget_width = width,
+ widget_height = height,
+ drawable = _drawable,
+ widget = _hierarchy:get_widget(),
+ hierarchy = _hierarchy
+ })
+ end
+ for _, child in ipairs(_hierarchy:get_children()) do
+ find_widgets(_drawable, result, child, x, y)
+ end
+end
+
+--- Find a widget by a point.
+-- The drawable must have drawn itself at least once for this to work.
+-- @param x X coordinate of the point
+-- @param y Y coordinate of the point
+-- @treturn table A table containing a description of all the widgets that
+-- contain the given point. Each entry is a table containing this drawable as
+-- its `.drawable` entry, the widget under `.widget` and the instance of
+-- `wibox.hierarchy` describing the size and position of the widget under
+-- `.hierarchy`. For convenience, `.x`, `.y`, `.width` and `.height` contain an
+-- approximation of the widget's extents on the surface. `widget_width` and
+-- `widget_height` contain the exact size of the widget in its own, local
+-- coordinate system (which may e.g. be rotated and scaled).
+function drawable:find_widgets(x, y)
+ local result = {}
+ if self._widget_hierarchy then
+ find_widgets(self, result, self._widget_hierarchy, x, y)
+ end
+ return result
+end
+
+
+--- Set the widget that the drawable displays
+function drawable:set_widget(widget)
+ self.widget = widget
+
+ -- Make sure the widget gets drawn
+ self._need_relayout = true
+ self.draw()
+end
+
+--- Set the background of the drawable
+-- @param c The background to use. This must either be a cairo pattern object,
+-- nil or a string that gears.color() understands.
+-- @see gears.color
+function drawable:set_bg(c)
+ c = c or "#000000"
+ local t = type(c)
+
+ if t == "string" or t == "table" then
+ c = color(c)
+ end
+
+ -- If the background is completely opaque, we don't need to redraw when
+ -- the drawable is moved
+ -- XXX: This isn't needed when awesome.composite_manager_running is true,
+ -- but a compositing manager could stop/start and we'd have to properly
+ -- handle this. So for now we choose the lazy approach.
+ local redraw_on_move = not color.create_opaque_pattern(c)
+ if self._redraw_on_move ~= redraw_on_move then
+ self._redraw_on_move = redraw_on_move
+ if redraw_on_move then
+ self.drawable:connect_signal("property::x", self._do_complete_repaint)
+ self.drawable:connect_signal("property::y", self._do_complete_repaint)
+ else
+ self.drawable:disconnect_signal("property::x", self._do_complete_repaint)
+ self.drawable:disconnect_signal("property::y", self._do_complete_repaint)
+ end
+ end
+
+ self.background_color = c
+ self._do_complete_repaint()
+end
+
+--- Set the background image of the drawable
+-- If `image` is a function, it will be called with `(context, cr, width, height)`
+-- as arguments. Any other arguments passed to this method will be appended.
+-- @param image A background image or a function
+function drawable:set_bgimage(image, ...)
+ if type(image) ~= "function" then
+ image = surface(image)
+ end
+
+ self.background_image = image
+ self.background_image_args = {...}
+
+ self._do_complete_repaint()
+end
+
+--- Set the foreground of the drawable
+-- @param c The foreground to use. This must either be a cairo pattern object,
+-- nil or a string that gears.color() understands.
+-- @see gears.color
+function drawable:set_fg(c)
+ c = c or "#FFFFFF"
+ if type(c) == "string" or type(c) == "table" then
+ c = color(c)
+ end
+ self.foreground_color = c
+ self._do_complete_repaint()
+end
+
+function drawable:_force_screen(s)
+ self._forced_screen = s
+end
+
+function drawable:_inform_visible(visible)
+ self._visible = visible
+ if visible then
+ visible_drawables[self] = true
+ -- The wallpaper or widgets might have changed
+ self:_do_complete_repaint()
+ else
+ visible_drawables[self] = nil
+ end
+end
+
+local function emit_difference(name, list, skip)
+ local function in_table(table, val)
+ for _, v in pairs(table) do
+ if v.widget == val.widget then
+ return true
+ end
+ end
+ return false
+ end
+
+ for _, v in pairs(list) do
+ if not in_table(skip, v) then
+ v.widget:emit_signal(name,v)
+ end
+ end
+end
+
+local function handle_leave(_drawable)
+ emit_difference("mouse::leave", _drawable._widgets_under_mouse, {})
+ _drawable._widgets_under_mouse = {}
+end
+
+local function handle_motion(_drawable, x, y)
+ if x < 0 or y < 0 or x > _drawable.drawable:geometry().width or y > _drawable.drawable:geometry().height then
+ return handle_leave(_drawable)
+ end
+
+ -- Build a plain list of all widgets on that point
+ local widgets_list = _drawable:find_widgets(x, y)
+
+ -- First, "leave" all widgets that were left
+ emit_difference("mouse::leave", _drawable._widgets_under_mouse, widgets_list)
+ -- Then enter some widgets
+ emit_difference("mouse::enter", widgets_list, _drawable._widgets_under_mouse)
+
+ _drawable._widgets_under_mouse = widgets_list
+end
+
+local function setup_signals(_drawable)
+ local d = _drawable.drawable
+
+ local function clone_signal(name)
+ -- When "name" is emitted on wibox.drawin, also emit it on wibox
+ d:connect_signal(name, function(_, ...)
+ _drawable:emit_signal(name, ...)
+ end)
+ end
+ clone_signal("button::press")
+ clone_signal("button::release")
+ clone_signal("mouse::enter")
+ clone_signal("mouse::leave")
+ clone_signal("mouse::move")
+ clone_signal("property::surface")
+ clone_signal("property::width")
+ clone_signal("property::height")
+ clone_signal("property::x")
+ clone_signal("property::y")
+end
+
+function drawable.new(d, widget_context_skeleton, drawable_name)
+ local ret = object()
+ ret.drawable = d
+ ret._widget_context_skeleton = widget_context_skeleton
+ ret._need_complete_repaint = true
+ ret._need_relayout = true
+ ret._dirty_area = cairo.Region.create()
+ setup_signals(ret)
+
+ for k, v in pairs(drawable) do
+ if type(v) == "function" then
+ ret[k] = v
+ end
+ end
+
+ -- Only redraw a drawable once, even when we get told to do so multiple times.
+ ret._redraw_pending = false
+ ret._do_redraw = function()
+ ret._redraw_pending = false
+ do_redraw(ret)
+ end
+
+ -- Connect our signal when we need a redraw
+ ret.draw = function()
+ if not ret._redraw_pending then
+ timer.delayed_call(ret._do_redraw)
+ ret._redraw_pending = true
+ end
+ end
+ ret._do_complete_repaint = function()
+ ret._need_complete_repaint = true
+ ret:draw()
+ end
+
+ -- Do a full redraw if the surface changes (the new surface has no content yet)
+ d:connect_signal("property::surface", ret._do_complete_repaint)
+
+ -- Do a normal redraw when the drawable moves. This will likely do nothing
+ -- in most cases, but it makes us do a complete repaint when we are moved to
+ -- a different screen.
+ d:connect_signal("property::x", ret.draw)
+ d:connect_signal("property::y", ret.draw)
+
+ -- Currently we aren't redrawing on move (signals not connected).
+ -- :set_bg() will later recompute this.
+ ret._redraw_on_move = false
+
+ -- Set the default background
+ ret:set_bg(beautiful.bg_normal)
+ ret:set_fg(beautiful.fg_normal)
+
+ -- Initialize internals
+ ret._widgets_under_mouse = {}
+
+ local function button_signal(name)
+ d:connect_signal(name, function(_, x, y, button, modifiers)
+ local widgets = ret:find_widgets(x, y)
+ for _, v in pairs(widgets) do
+ -- Calculate x/y inside of the widget
+ local lx, ly = v.hierarchy:get_matrix_from_device():transform_point(x, y)
+ v.widget:emit_signal(name, lx, ly, button, modifiers,v)
+ end
+ end)
+ end
+ button_signal("button::press")
+ button_signal("button::release")
+
+ d:connect_signal("mouse::move", function(_, x, y) handle_motion(ret, x, y) end)
+ d:connect_signal("mouse::leave", function() handle_leave(ret) end)
+
+ -- Set up our callbacks for repaints
+ ret._redraw_callback = function(hierar, arg)
+ -- Avoid crashes when a drawable was partly finalized and dirty_area is broken.
+ if not ret._visible then
+ return
+ end
+ if ret._widget_hierarchy_callback_arg ~= arg then
+ return
+ end
+ local m = hierar:get_matrix_to_device()
+ local x, y, width, height = matrix.transform_rectangle(m, hierar:get_draw_extents())
+ local x1, y1 = math.floor(x), math.floor(y)
+ local x2, y2 = math.ceil(x + width), math.ceil(y + height)
+ ret._dirty_area:union_rectangle(cairo.RectangleInt{
+ x = x1, y = y1, width = x2 - x1, height = y2 - y1
+ })
+ ret:draw()
+ end
+ ret._layout_callback = function(_, arg)
+ if ret._widget_hierarchy_callback_arg ~= arg then
+ return
+ end
+ ret._need_relayout = true
+ -- When not visible, we will be redrawn when we become visible. In the
+ -- mean-time, the layout does not matter much.
+ if ret._visible then
+ ret:draw()
+ end
+ end
+
+ -- Add __tostring method to metatable.
+ ret.drawable_name = drawable_name or object.modulename(3)
+ local mt = {}
+ local orig_string = tostring(ret)
+ mt.__tostring = function()
+ return string.format("%s (%s)", ret.drawable_name, orig_string)
+ end
+ ret = setmetatable(ret, mt)
+
+ -- Make sure the drawable is drawn at least once
+ ret._do_complete_repaint()
+
+ return ret
+end
+
+-- Redraw all drawables when the wallpaper changes
+capi.awesome.connect_signal("wallpaper_changed", function()
+ for d in pairs(visible_drawables) do
+ d:_do_complete_repaint()
+ end
+end)
+
+-- Give drawables a chance to react to screen changes
+local function draw_all()
+ for d in pairs(visible_drawables) do
+ d:draw()
+ end
+end
+screen.connect_signal("property::geometry", draw_all)
+screen.connect_signal("added", draw_all)
+screen.connect_signal("removed", draw_all)
+
+return setmetatable(drawable, { __call = function(_, ...) return drawable.new(...) end })
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/hierarchy.lua b/lib/wibox/hierarchy.lua
new file mode 100644
index 0000000..6bf2167
--- /dev/null
+++ b/lib/wibox/hierarchy.lua
@@ -0,0 +1,333 @@
+---------------------------------------------------------------------------
+-- Management of widget hierarchies. Each widget hierarchy object has a widget
+-- for which it saves e.g. size and transformation in its parent. Also, each
+-- widget has a number of children.
+--
+-- @author Uli Schlachter
+-- @copyright 2015 Uli Schlachter
+-- @module wibox.hierarchy
+---------------------------------------------------------------------------
+
+local matrix = require("gears.matrix")
+local protected_call = require("gears.protected_call")
+local cairo = require("lgi").cairo
+local base = require("wibox.widget.base")
+local no_parent = base.no_parent_I_know_what_I_am_doing
+
+local hierarchy = {}
+
+local function hierarchy_new(redraw_callback, layout_callback, callback_arg)
+ local result = {
+ _matrix = matrix.identity,
+ _matrix_to_device = matrix.identity,
+ _need_update = true,
+ _widget = nil,
+ _context = nil,
+ _redraw_callback = redraw_callback,
+ _layout_callback = layout_callback,
+ _callback_arg = callback_arg,
+ _size = {
+ width = nil,
+ height = nil
+ },
+ _draw_extents = {
+ x = 0,
+ y = 0,
+ width = 0,
+ height = 0
+ },
+ _parent = nil,
+ _children = {}
+ }
+
+ function result._redraw()
+ redraw_callback(result, callback_arg)
+ end
+ function result._layout()
+ local h = result
+ while h do
+ h._need_update = true
+ h = h._parent
+ end
+ layout_callback(result, callback_arg)
+ end
+ function result._emit_recursive(widget, name, ...)
+ local cur = result
+ assert(widget == cur._widget)
+ while cur do
+ if cur._widget then
+ cur._widget:emit_signal(name, ...)
+ end
+ cur = cur._parent
+ end
+ end
+
+ for k, f in pairs(hierarchy) do
+ if type(f) == "function" then
+ result[k] = f
+ end
+ end
+ return result
+end
+
+local hierarchy_update
+function hierarchy_update(self, context, widget, width, height, region, matrix_to_parent, matrix_to_device)
+ if (not self._need_update) and self._widget == widget and
+ self._context == context and
+ self._size.width == width and self._size.height == height and
+ matrix.equals(self._matrix, matrix_to_parent) and
+ matrix.equals(self._matrix_to_device, matrix_to_device) then
+ -- Nothing changed
+ return
+ end
+
+ self._need_update = false
+
+ local old_x, old_y, old_width, old_height
+ local old_widget = self._widget
+ if self._size.width and self._size.height then
+ local x, y, w, h = matrix.transform_rectangle(self._matrix_to_device, 0, 0, self._size.width, self._size.height)
+ old_x, old_y = math.floor(x), math.floor(y)
+ old_width, old_height = math.ceil(x + w) - old_x, math.ceil(y + h) - old_y
+ else
+ old_x, old_y, old_width, old_height = 0, 0, 0, 0
+ end
+
+ -- Disconnect old signals
+ if old_widget and old_widget ~= widget then
+ self._widget:disconnect_signal("widget::redraw_needed", self._redraw)
+ self._widget:disconnect_signal("widget::layout_changed", self._layout)
+ self._widget:disconnect_signal("widget::emit_recursive", self._emit_recursive)
+ end
+
+ -- Save the arguments we need to save
+ self._widget = widget
+ self._context = context
+ self._size.width = width
+ self._size.height = height
+ self._matrix = matrix_to_parent
+ self._matrix_to_device = matrix_to_device
+
+ -- Connect signals
+ if old_widget ~= widget then
+ widget:weak_connect_signal("widget::redraw_needed", self._redraw)
+ widget:weak_connect_signal("widget::layout_changed", self._layout)
+ widget:weak_connect_signal("widget::emit_recursive", self._emit_recursive)
+ end
+
+ -- Update children
+ local old_children = self._children
+ local layout_result = base.layout_widget(no_parent, context, widget, width, height)
+ self._children = {}
+ for _, w in ipairs(layout_result or {}) do
+ local r = table.remove(old_children, 1)
+ if not r then
+ r = hierarchy_new(self._redraw_callback, self._layout_callback, self._callback_arg)
+ r._parent = self
+ end
+ hierarchy_update(r, context, w._widget, w._width, w._height, region, w._matrix, w._matrix * matrix_to_device)
+ table.insert(self._children, r)
+ end
+
+ -- Calculate the draw extents
+ local x1, y1, x2, y2 = 0, 0, width, height
+ for _, h in ipairs(self._children) do
+ local px, py, pwidth, pheight = matrix.transform_rectangle(h._matrix, h:get_draw_extents())
+ x1 = math.min(x1, px)
+ y1 = math.min(y1, py)
+ x2 = math.max(x2, px + pwidth)
+ y2 = math.max(y2, py + pheight)
+ end
+ self._draw_extents = {
+ x = x1, y = y1,
+ width = x2 - x1,
+ height = y2 - y1
+ }
+
+ -- Check which part needs to be redrawn
+
+ -- Are there any children which were removed? Their area needs a redraw.
+ for _, child in ipairs(old_children) do
+ local x, y, w, h = matrix.transform_rectangle(child._matrix_to_device, child:get_draw_extents())
+ region:union_rectangle(cairo.RectangleInt{
+ x = x, y = y, width = w, height = h
+ })
+ child._parent = nil
+ end
+
+ -- Did we change and need to be redrawn?
+ local x, y, w, h = matrix.transform_rectangle(self._matrix_to_device, 0, 0, self._size.width, self._size.height)
+ local new_x, new_y = math.floor(x), math.floor(y)
+ local new_width, new_height = math.ceil(x + w) - new_x, math.ceil(y + h) - new_y
+ if new_x ~= old_x or new_y ~= old_y or new_width ~= old_width or new_height ~= old_height or
+ widget ~= old_widget then
+ region:union_rectangle(cairo.RectangleInt{
+ x = old_x, y = old_y, width = old_width, height = old_height
+ })
+ region:union_rectangle(cairo.RectangleInt{
+ x = new_x, y = new_y, width = new_width, height = new_height
+ })
+ end
+end
+
+--- Create a new widget hierarchy that has no parent.
+-- @param context The context in which we are laid out.
+-- @param widget The widget that is at the base of the hierarchy.
+-- @param width The available width for this hierarchy.
+-- @param height The available height for this hierarchy.
+-- @param redraw_callback Callback that is called with the corresponding widget
+-- hierarchy on widget::redraw_needed on some widget.
+-- @param layout_callback Callback that is called with the corresponding widget
+-- hierarchy on widget::layout_changed on some widget.
+-- @param callback_arg A second argument that is given to the above callbacks.
+-- @return A new widget hierarchy
+function hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, callback_arg)
+ local result = hierarchy_new(redraw_callback, layout_callback, callback_arg)
+ result:update(context, widget, width, height)
+ return result
+end
+
+--- Update a widget hierarchy with some new state.
+-- @param context The context in which we are laid out.
+-- @param widget The widget that is at the base of the hierarchy.
+-- @param width The available width for this hierarchy.
+-- @param height The available height for this hierarchy.
+-- @param[opt] region A region to use for accumulating changed parts
+-- @return A cairo region describing the changed parts (either the `region`
+-- argument or a new, internally created region).
+function hierarchy:update(context, widget, width, height, region)
+ region = region or cairo.Region.create()
+ hierarchy_update(self, context, widget, width, height, region, self._matrix, self._matrix_to_device)
+ return region
+end
+
+--- Get the widget that this hierarchy manages.
+function hierarchy:get_widget()
+ return self._widget
+end
+
+--- Get a matrix that transforms to the parent's coordinate space from this
+-- hierarchy's coordinate system.
+-- @return A matrix describing the transformation.
+function hierarchy:get_matrix_to_parent()
+ return self._matrix
+end
+
+--- Get a matrix that transforms to the base of this hierarchy's coordinate
+-- system (aka the coordinate system of the device that this
+-- hierarchy is applied upon) from this hierarchy's coordinate system.
+-- @return A matrix describing the transformation.
+function hierarchy:get_matrix_to_device()
+ return self._matrix_to_device
+end
+
+--- Get a matrix that transforms from the parent's coordinate space into this
+-- hierarchy's coordinate system.
+-- @return A matrix describing the transformation.
+function hierarchy:get_matrix_from_parent()
+ local m = self:get_matrix_to_parent()
+ return m:invert()
+end
+
+--- Get a matrix that transforms from the base of this hierarchy's coordinate
+-- system (aka the coordinate system of the device that this
+-- hierarchy is applied upon) into this hierarchy's coordinate system.
+-- @return A matrix describing the transformation.
+function hierarchy:get_matrix_from_device()
+ local m = self:get_matrix_to_device()
+ return m:invert()
+end
+
+--- Get the extents that this hierarchy possibly draws to (in the current coordinate space).
+-- This includes the size of this element plus the size of all children
+-- (after applying the corresponding transformation).
+-- @return x, y, width, height
+function hierarchy:get_draw_extents()
+ local ext = self._draw_extents
+ return ext.x, ext.y, ext.width, ext.height
+end
+
+--- Get the size that this hierarchy logically covers (in the current coordinate space).
+-- @return width, height
+function hierarchy:get_size()
+ local ext = self._size
+ return ext.width, ext.height
+end
+
+--- Get a list of all children.
+-- @return List of all children hierarchies.
+function hierarchy:get_children()
+ return self._children
+end
+
+--- Does the given cairo context have an empty clip (aka "no drawing possible")?
+local function empty_clip(cr)
+ local _, _, width, height = cr:clip_extents()
+ return width == 0 or height == 0
+end
+
+--- Draw a hierarchy to some cairo context.
+-- This function draws the widgets in this widget hierarchy to the given cairo
+-- context. The context's clip is used to skip parts that aren't visible.
+-- @param context The context in which widgets are drawn.
+-- @param cr The cairo context that is used for drawing.
+function hierarchy:draw(context, cr)
+ local widget = self:get_widget()
+ if not widget._private.visible then
+ return
+ end
+
+ cr:save()
+ cr:transform(self:get_matrix_to_parent():to_cairo_matrix())
+
+ -- Clip to the draw extents
+ cr:rectangle(self:get_draw_extents())
+ cr:clip()
+
+ -- Draw if needed
+ if not empty_clip(cr) then
+ local opacity = widget:get_opacity()
+ local function call(func, extra_arg1, extra_arg2)
+ if not func then return end
+ if not extra_arg2 then
+ protected_call(func, widget, context, cr, self:get_size())
+ else
+ protected_call(func, widget, context, extra_arg1, extra_arg2, cr, self:get_size())
+ end
+ end
+
+ -- Prepare opacity handling
+ if opacity ~= 1 then
+ cr:push_group()
+ end
+
+ -- Draw the widget
+ cr:save()
+ cr:rectangle(0, 0, self:get_size())
+ cr:clip()
+ call(widget.draw)
+ cr:restore()
+
+ -- Draw its children (We already clipped to the draw extents above)
+ call(widget.before_draw_children)
+ for i, wi in ipairs(self:get_children()) do
+ call(widget.before_draw_child, i, wi:get_widget())
+ wi:draw(context, cr)
+ call(widget.after_draw_child, i, wi:get_widget())
+ end
+ call(widget.after_draw_children)
+
+ -- Apply opacity
+ if opacity ~= 1 then
+ cr:pop_group_to_source()
+ cr.operator = cairo.Operator.OVER
+ cr:paint_with_alpha(opacity)
+ end
+ end
+
+ cr:restore()
+end
+
+return hierarchy
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/init.lua b/lib/wibox/init.lua
new file mode 100644
index 0000000..3fc89ce
--- /dev/null
+++ b/lib/wibox/init.lua
@@ -0,0 +1,479 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox
+---------------------------------------------------------------------------
+
+local capi = {
+ drawin = drawin,
+ root = root,
+ awesome = awesome,
+ screen = screen
+}
+local setmetatable = setmetatable
+local pairs = pairs
+local type = type
+local object = require("gears.object")
+local grect = require("gears.geometry").rectangle
+local beautiful = require("beautiful")
+local base = require("wibox.widget.base")
+
+--- This provides widget box windows. Every wibox can also be used as if it were
+-- a drawin. All drawin functions and properties are also available on wiboxes!
+-- wibox
+local wibox = { mt = {}, object = {} }
+wibox.layout = require("wibox.layout")
+wibox.container = require("wibox.container")
+wibox.widget = require("wibox.widget")
+wibox.drawable = require("wibox.drawable")
+wibox.hierarchy = require("wibox.hierarchy")
+
+local force_forward = {
+ shape_bounding = true,
+ shape_clip = true,
+}
+
+--Imported documentation
+
+--- Border width.
+--
+-- **Signal:**
+--
+-- * *property::border_width*
+--
+-- @property border_width
+-- @param integer
+
+--- Border color.
+--
+-- Please note that this property only support string based 24 bit or 32 bit
+-- colors:
+--
+-- Red Blue
+-- _| _|
+-- #FF00FF
+-- T‾
+-- Green
+--
+--
+-- Red Blue
+-- _| _|
+-- #FF00FF00
+-- T‾ ‾T
+-- Green Alpha
+--
+-- **Signal:**
+--
+-- * *property::border_color*
+--
+-- @property border_color
+-- @param string
+
+--- On top of other windows.
+--
+-- **Signal:**
+--
+-- * *property::ontop*
+--
+-- @property ontop
+-- @param boolean
+
+--- The mouse cursor.
+--
+-- **Signal:**
+--
+-- * *property::cursor*
+--
+-- @property cursor
+-- @param string
+-- @see mouse
+
+--- Visibility.
+--
+-- **Signal:**
+--
+-- * *property::visible*
+--
+-- @property visible
+-- @param boolean
+
+--- The opacity of the wibox, between 0 and 1.
+--
+-- **Signal:**
+--
+-- * *property::opacity*
+--
+-- @property opacity
+-- @tparam number opacity (between 0 and 1)
+
+--- The window type (desktop, normal, dock, ...).
+--
+-- **Signal:**
+--
+-- * *property::type*
+--
+-- @property type
+-- @param string
+-- @see client.type
+
+--- The x coordinates.
+--
+-- **Signal:**
+--
+-- * *property::x*
+--
+-- @property x
+-- @param integer
+
+--- The y coordinates.
+--
+-- **Signal:**
+--
+-- * *property::y*
+--
+-- @property y
+-- @param integer
+
+--- The width of the wibox.
+--
+-- **Signal:**
+--
+-- * *property::width*
+--
+-- @property width
+-- @param width
+
+--- The height of the wibox.
+--
+-- **Signal:**
+--
+-- * *property::height*
+--
+-- @property height
+-- @param height
+
+--- The wibox screen.
+--
+-- @property screen
+-- @param screen
+
+--- The wibox's `drawable`.
+--
+-- **Signal:**
+--
+-- * *property::drawable*
+--
+-- @property drawable
+-- @tparam drawable drawable
+
+--- The widget that the `wibox` displays.
+-- @property widget
+-- @param widget
+
+--- The X window id.
+--
+-- **Signal:**
+--
+-- * *property::window*
+--
+-- @property window
+-- @param string
+-- @see client.window
+
+--- The wibox's bounding shape as a (native) cairo surface.
+--
+-- **Signal:**
+--
+-- * *property::shape_bounding*
+--
+-- @property shape_bounding
+-- @param surface._native
+
+--- The wibox's clip shape as a (native) cairo surface.
+--
+-- **Signal:**
+--
+-- * *property::shape_clip*
+--
+-- @property shape_clip
+-- @param surface._native
+
+--- Get or set mouse buttons bindings to a wibox.
+--
+-- @param buttons_table A table of buttons objects, or nothing.
+-- @function buttons
+
+--- Get or set wibox geometry. That's the same as accessing or setting the x,
+-- y, width or height properties of a wibox.
+--
+-- @param A table with coordinates to modify.
+-- @return A table with wibox coordinates and geometry.
+-- @function geometry
+
+--- Get or set wibox struts.
+--
+-- @param strut A table with new strut, or nothing
+-- @return The wibox strut in a table.
+-- @function struts
+-- @see client.struts
+
+--- The default background color.
+-- @beautiful beautiful.bg_normal
+-- @see bg
+
+--- The default foreground (text) color.
+-- @beautiful beautiful.fg_normal
+-- @see fg
+
+--- 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
+-- @name setup
+-- @class function
+
+--- The background of the wibox.
+-- @param c The background to use. This must either be a cairo pattern object,
+-- nil or a string that gears.color() understands.
+-- @property bg
+-- @see gears.color
+
+--- The background image of the drawable.
+-- If `image` is a function, it will be called with `(context, cr, width, height)`
+-- as arguments. Any other arguments passed to this method will be appended.
+-- @param image A background image or a function
+-- @property bgimage
+-- @see gears.surface
+
+--- The foreground (text) of the wibox.
+-- @param c The foreground to use. This must either be a cairo pattern object,
+-- nil or a string that gears.color() understands.
+-- @property fg
+-- @see gears.color
+
+--- Find a widget by a point.
+-- The wibox must have drawn itself at least once for this to work.
+-- @tparam number x X coordinate of the point
+-- @tparam number y Y coordinate of the point
+-- @treturn table A sorted table of widgets positions. The first element is the biggest
+-- container while the last is the topmost widget. The table contains *x*, *y*,
+-- *width*, *height* and *widget*.
+-- @name find_widgets
+-- @class function
+
+
+function wibox:set_widget(widget)
+ self._drawable:set_widget(widget)
+end
+
+function wibox:get_widget()
+ return self._drawable.widget
+end
+
+wibox.setup = base.widget.setup
+
+function wibox:set_bg(c)
+ self._drawable:set_bg(c)
+end
+
+function wibox:set_bgimage(image, ...)
+ self._drawable:set_bgimage(image, ...)
+end
+
+function wibox:set_fg(c)
+ self._drawable:set_fg(c)
+end
+
+function wibox:find_widgets(x, y)
+ return self._drawable:find_widgets(x, y)
+end
+
+function wibox:get_screen()
+ if self.screen_assigned and self.screen_assigned.valid then
+ return self.screen_assigned
+ else
+ self.screen_assigned = nil
+ end
+ local sgeos = {}
+
+ for s in capi.screen do
+ sgeos[s] = s.geometry
+ end
+
+ return grect.get_closest_by_coord(sgeos, self.x, self.y)
+end
+
+function wibox:set_screen(s)
+ s = capi.screen[s or 1]
+ if s ~= self:get_screen() then
+ self.x = s.geometry.x
+ self.y = s.geometry.y
+ end
+
+ -- Remember this screen so things work correctly if screens overlap and
+ -- (x,y) is not enough to figure out the correct screen.
+ self.screen_assigned = s
+ self._drawable:_force_screen(s)
+end
+
+for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do
+ wibox[k] = function(self, ...)
+ return self.drawin[k](self.drawin, ...)
+ end
+end
+
+local function setup_signals(_wibox)
+ local obj
+ local function clone_signal(name)
+ -- When "name" is emitted on wibox.drawin, also emit it on wibox
+ obj:connect_signal(name, function(_, ...)
+ _wibox:emit_signal(name, ...)
+ end)
+ end
+
+ obj = _wibox.drawin
+ clone_signal("property::border_color")
+ clone_signal("property::border_width")
+ clone_signal("property::buttons")
+ clone_signal("property::cursor")
+ clone_signal("property::height")
+ clone_signal("property::ontop")
+ clone_signal("property::opacity")
+ clone_signal("property::struts")
+ clone_signal("property::visible")
+ clone_signal("property::width")
+ clone_signal("property::x")
+ clone_signal("property::y")
+ clone_signal("property::geometry")
+ clone_signal("property::shape_bounding")
+ clone_signal("property::shape_clip")
+
+ obj = _wibox._drawable
+ clone_signal("button::press")
+ clone_signal("button::release")
+ clone_signal("mouse::enter")
+ clone_signal("mouse::leave")
+ clone_signal("mouse::move")
+ clone_signal("property::surface")
+end
+
+--- Create a wibox.
+-- @tparam[opt=nil] table args
+-- @tparam integer args.border_width Border width.
+-- @tparam string args.border_color Border color.
+-- @tparam boolean args.ontop On top of other windows.
+-- @tparam string args.cursor The mouse cursor.
+-- @tparam boolean args.visible Visibility.
+-- @tparam number args.opacity The opacity of the wibox, between 0 and 1.
+-- @tparam string args.type The window type (desktop, normal, dock, …).
+-- @tparam integer args.x The x coordinates.
+-- @tparam integer args.y The y coordinates.
+-- @tparam integer args.width The width of the wibox.
+-- @tparam integer args.height The height of the wibox.
+-- @tparam screen args.screen The wibox screen.
+-- @tparam wibox.widget args.widget The widget that the wibox displays.
+-- @param args.shape_bounding The wibox’s bounding shape as a (native) cairo surface.
+-- @param args.shape_clip The wibox’s clip shape as a (native) cairo surface.
+-- @tparam color args.bg The background of the wibox.
+-- @tparam surface args.bgimage The background image of the drawable.
+-- @tparam color args.fg The foreground (text) of the wibox.
+-- @treturn wibox The new wibox
+-- @function .wibox
+
+local function new(args)
+ args = args or {}
+ local ret = object()
+ local w = capi.drawin(args)
+
+ function w.get_wibox()
+ return ret
+ end
+
+ ret.drawin = w
+ ret._drawable = wibox.drawable(w.drawable, { wibox = ret },
+ "wibox drawable (" .. object.modulename(3) .. ")")
+
+ ret._drawable:_inform_visible(w.visible)
+ w:connect_signal("property::visible", function()
+ ret._drawable:_inform_visible(w.visible)
+ end)
+
+ for k, v in pairs(wibox) do
+ if type(v) == "function" then
+ ret[k] = v
+ end
+ end
+
+ setup_signals(ret)
+ ret.draw = ret._drawable.draw
+
+ -- Set the default background
+ ret:set_bg(args.bg or beautiful.bg_normal)
+ ret:set_fg(args.fg or beautiful.fg_normal)
+
+ -- Add __tostring method to metatable.
+ local mt = {}
+ local orig_string = tostring(ret)
+ mt.__tostring = function()
+ return string.format("wibox: %s (%s)",
+ tostring(ret._drawable), orig_string)
+ end
+ ret = setmetatable(ret, mt)
+
+ -- Make sure the wibox is drawn at least once
+ ret.draw()
+
+ -- If a value is not found, look in the drawin
+ setmetatable(ret, {
+ __index = function(self, k)
+ if rawget(self, "get_"..k) then
+ return self["get_"..k](self)
+ else
+ return w[k]
+ end
+ end,
+ __newindex = function(self, k,v)
+ if rawget(self, "set_"..k) then
+ self["set_"..k](self, v)
+ elseif w[k] ~= nil or force_forward[k] then
+ w[k] = v
+ else
+ rawset(self, k, v)
+ end
+ end
+ })
+
+ -- Set other wibox specific arguments
+ if args.bgimage then
+ ret:set_bgimage( args.bgimage )
+ end
+
+ if args.widget then
+ ret:set_widget ( args.widget )
+ end
+
+ if args.screen then
+ ret:set_screen ( args.screen )
+ end
+
+ return ret
+end
+
+--- Redraw a wibox. You should never have to call this explicitely because it is
+-- automatically called when needed.
+-- @param wibox
+-- @function draw
+
+function wibox.mt:__call(...)
+ return new(...)
+end
+
+-- Extend the luaobject
+object.properties(capi.drawin, {
+ getter_class = wibox.object,
+ setter_class = wibox.object,
+ auto_emit = true,
+})
+
+return setmetatable(wibox, wibox.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
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
diff --git a/lib/wibox/widget/background.lua b/lib/wibox/widget/background.lua
new file mode 100644
index 0000000..3c35a0b
--- /dev/null
+++ b/lib/wibox/widget/background.lua
@@ -0,0 +1,16 @@
+---------------------------------------------------------------------------
+-- This class has been moved to `wibox.container.background`
+--
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.widget.background
+---------------------------------------------------------------------------
+local util = require("awful.util")
+
+return util.deprecate_class(
+ require("wibox.container.background"),
+ "wibox.widget.background",
+ "wibox.container.background"
+)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua
new file mode 100644
index 0000000..dd80ec7
--- /dev/null
+++ b/lib/wibox/widget/base.lua
@@ -0,0 +1,694 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.widget.base
+---------------------------------------------------------------------------
+
+local object = require("gears.object")
+local cache = require("gears.cache")
+local matrix = require("gears.matrix")
+local protected_call = require("gears.protected_call")
+local util = require("awful.util")
+local setmetatable = setmetatable
+local pairs = pairs
+local type = type
+local table = table
+
+local base = {}
+
+-- {{{ Functions on widgets
+
+--- Functions available on all widgets.
+base.widget = {}
+
+--- Set/get a widget's buttons.
+-- @tab _buttons The table of buttons that is bound to the widget.
+-- @function buttons
+function base.widget:buttons(_buttons)
+ if _buttons then
+ self._private.widget_buttons = _buttons
+ end
+ return self._private.widget_buttons
+end
+
+--- Set a widget's visibility.
+-- @tparam boolean b Whether the widget is visible.
+-- @function set_visible
+function base.widget:set_visible(b)
+ if b ~= self._private.visible then
+ self._private.visible = b
+ self:emit_signal("widget::layout_changed")
+ -- In case something ignored fit and drew the widget anyway.
+ self:emit_signal("widget::redraw_needed")
+ end
+end
+
+--- Is the widget visible?
+-- @treturn boolean
+-- @function get_visible
+function base.widget:get_visible()
+ return self._private.visible or false
+end
+
+--- Set a widget's opacity.
+-- @tparam number o The opacity to use (a number from 0 (transparent) to 1
+-- (opaque)).
+-- @function set_opacity
+function base.widget:set_opacity(o)
+ if o ~= self._private.opacity then
+ self._private.opacity = o
+ self:emit_signal("widget::redraw")
+ end
+end
+
+--- Get the widget's opacity.
+-- @treturn number The opacity (between 0 (transparent) and 1 (opaque)).
+-- @function get_opacity
+function base.widget:get_opacity()
+ return self._private.opacity
+end
+
+--- Set the widget's forced width.
+-- @tparam[opt] number width With `nil` the default mechanism of calling the
+-- `:fit` method is used.
+-- @see fit_widget
+-- @function set_forced_width
+function base.widget:set_forced_width(width)
+ if width ~= self._private.forced_width then
+ self._private.forced_width = width
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Get the widget's forced width.
+--
+-- Note that widget instances can be used in different places simultaneously,
+-- and therefore can have multiple dimensions.
+-- If there is no forced width/height, then the only way to get the widget's
+-- actual size is during a `mouse::enter`, `mouse::leave` or button event.
+-- @treturn[opt] number The forced width (nil if automatic).
+-- @see fit_widget
+-- @function get_forced_width
+function base.widget:get_forced_width()
+ return self._private.forced_width
+end
+
+--- Set the widget's forced height.
+-- @tparam[opt] number height With `nil` the default mechanism of calling the
+-- `:fit` method is used.
+-- @see fit_widget
+-- @function set_height
+function base.widget:set_forced_height(height)
+ if height ~= self._private.forced_height then
+ self._private.forced_height = height
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Get the widget's forced height.
+--
+-- Note that widget instances can be used in different places simultaneously,
+-- and therefore can have multiple dimensions.
+-- If there is no forced width/height, then the only way to get the widget's
+-- actual size is during a `mouse::enter`, `mouse::leave` or button event.
+-- @treturn[opt] number The forced height (nil if automatic).
+-- @function get_forced_height
+function base.widget:get_forced_height()
+ return self._private.forced_height
+end
+
+--- Get the widget's direct children widgets.
+--
+-- This method should be re-implemented by the relevant widgets.
+-- @treturn table The children
+-- @function get_children
+function base.widget:get_children()
+ return {}
+end
+
+--- Replace the layout children.
+--
+-- The default implementation does nothing, this must be re-implemented by
+-- all layout and container widgets.
+-- @tab children A table composed of valid widgets.
+-- @function set_children
+function base.widget:set_children(children) -- luacheck: no unused
+ -- Nothing on purpose
+end
+
+-- It could have been merged into `get_all_children`, but it's not necessary.
+local function digg_children(ret, tlw)
+ for _, w in ipairs(tlw:get_children()) do
+ table.insert(ret, w)
+ digg_children(ret, w)
+ end
+end
+
+--- Get all direct and indirect children widgets.
+--
+-- This will scan all containers recursively to find widgets.
+--
+-- *Warning*: This method it prone to stack overflow if the widget, or any of
+-- its children, contains (directly or indirectly) itself.
+-- @treturn table The children
+-- @function get_all_children
+function base.widget:get_all_children()
+ local ret = {}
+ digg_children(ret, self)
+ return ret
+end
+
+--- Emit a signal and ensure all parent widgets in the hierarchies also
+-- forward the signal. This is useful to track signals when there is a dynamic
+-- set of containers and layouts wrapping the widget.
+--
+-- Note that this function has two flaws:
+--
+-- 1. The signal is only forwarded once the widget tree has been built. This
+-- happens after all currently scheduled functions have been executed.
+-- Therefore, it will not start to work right away.
+-- 2. In case the widget is present multiple times in a single widget tree,
+-- this function will also forward the signal multiple time (one per upward
+-- tree path).
+--
+-- @tparam string signal_name
+-- @param ... Other arguments
+-- @function emit_signal_recursive
+function base.widget:emit_signal_recursive(signal_name, ...)
+ -- This is a convenience wrapper, the real implementation is in the
+ -- hierarchy.
+
+ self:emit_signal("widget::emit_recursive", signal_name, ...)
+end
+
+--- Get the index of a widget.
+-- @tparam widget widget The widget to look for.
+-- @tparam[opt] boolean recursive Also check sub-widgets?
+-- @tparam[opt] widget ... Additional widgets to add at the end of the "path"
+-- @treturn number The index.
+-- @treturn widget The parent widget.
+-- @treturn table The path between "self" and "widget".
+-- @function index
+function base.widget:index(widget, recursive, ...)
+ local widgets = self:get_children()
+ for idx, w in ipairs(widgets) do
+ if w == widget then
+ return idx, self, {...}
+ elseif recursive then
+ local child_idx, l, path = w:index(widget, true, self, ...)
+ if child_idx and l then
+ return child_idx, l, path
+ end
+ end
+ end
+ return nil, self, {}
+end
+-- }}}
+
+-- {{{ Caches
+
+-- Indexes are widgets, allow them to be garbage-collected.
+local widget_dependencies = setmetatable({}, { __mode = "kv" })
+
+-- Get the cache of the given kind for this widget. This returns a gears.cache
+-- that calls the callback of kind `kind` on the widget.
+local function get_cache(widget, kind)
+ if not widget._private.widget_caches[kind] then
+ widget._private.widget_caches[kind] = cache.new(function(...)
+ return protected_call(widget[kind], widget, ...)
+ end)
+ end
+ return widget._private.widget_caches[kind]
+end
+
+-- Special value to skip the dependency recording that is normally done by
+-- base.fit_widget() and base.layout_widget(). The caller must ensure that no
+-- caches depend on the result of the call and/or must handle the children's
+-- widget::layout_changed signal correctly when using this.
+base.no_parent_I_know_what_I_am_doing = {}
+
+-- Record a dependency from parent to child: The layout of `parent` depends on
+-- the layout of `child`.
+local function record_dependency(parent, child)
+ if parent == base.no_parent_I_know_what_I_am_doing then
+ return
+ end
+
+ base.check_widget(parent)
+ base.check_widget(child)
+
+ local deps = widget_dependencies[child] or {}
+ deps[parent] = true
+ widget_dependencies[child] = deps
+end
+
+-- Clear the caches for `widget` and all widgets that depend on it.
+local clear_caches
+function clear_caches(widget)
+ local deps = widget_dependencies[widget] or {}
+ widget_dependencies[widget] = {}
+ widget._private.widget_caches = {}
+ for w in pairs(deps) do
+ clear_caches(w)
+ end
+end
+
+-- }}}
+
+--- Figure out the geometry in the device coordinate space.
+--
+-- This gives only tight bounds if no rotations by non-multiples of 90° are
+-- used.
+-- @function wibox.widget.base.rect_to_device_geometry
+function base.rect_to_device_geometry(cr, x, y, width, height)
+ return matrix.transform_rectangle(cr.matrix, x, y, width, height)
+end
+
+--- Fit a widget for the given available width and height.
+--
+-- This calls the widget's `:fit` callback and caches the result for later use.
+-- Never call `:fit` directly, but always through this function!
+-- @tparam widget parent The parent widget which requests this information.
+-- @tab context The context in which we are fit.
+-- @tparam widget widget The widget to fit (this uses
+-- `widget:fit(context, width, height)`).
+-- @tparam number width The available width for the widget.
+-- @tparam number height The available height for the widget.
+-- @treturn number The width that the widget wants to use.
+-- @treturn number The height that the widget wants to use.
+-- @function wibox.widget.base.fit_widget
+function base.fit_widget(parent, context, widget, width, height)
+ record_dependency(parent, widget)
+
+ if not widget._private.visible then
+ return 0, 0
+ end
+
+ -- Sanitize the input. This also filters out e.g. NaN.
+ width = math.max(0, width)
+ height = math.max(0, height)
+
+ local w, h = 0, 0
+ if widget.fit then
+ w, h = get_cache(widget, "fit"):get(context, width, height)
+ else
+ -- If it has no fit method, calculate based on the size of children
+ local children = base.layout_widget(parent, context, widget, width, height)
+ for _, info in ipairs(children or {}) do
+ local x, y, w2, h2 = matrix.transform_rectangle(info._matrix,
+ 0, 0, info._width, info._height)
+ w, h = math.max(w, x + w2), math.max(h, y + h2)
+ end
+ end
+
+ -- Apply forced size and handle nil's
+ w = widget._private.forced_width or w or 0
+ h = widget._private.forced_height or h or 0
+
+ -- Also sanitize the output.
+ w = math.max(0, math.min(w, width))
+ h = math.max(0, math.min(h, height))
+ return w, h
+end
+
+--- Lay out a widget for the given available width and height.
+--
+-- This calls the widget's `:layout` callback and caches the result for later
+-- use. Never call `:layout` directly, but always through this function!
+-- However, normally there shouldn't be any reason why you need to use this
+-- function.
+-- @tparam widget parent The parent widget which requests this information.
+-- @tab context The context in which we are laid out.
+-- @tparam widget widget The widget to layout (this uses
+-- `widget:layout(context, width, height)`).
+-- @tparam number width The available width for the widget.
+-- @tparam number height The available height for the widget.
+-- @treturn[opt] table The result from the widget's `:layout` callback.
+-- @function wibox.widget.base.layout_widget
+function base.layout_widget(parent, context, widget, width, height)
+ record_dependency(parent, widget)
+
+ if not widget._private.visible then
+ return
+ end
+
+ -- Sanitize the input. This also filters out e.g. NaN.
+ width = math.max(0, width)
+ height = math.max(0, height)
+
+ if widget.layout then
+ return get_cache(widget, "layout"):get(context, width, height)
+ end
+end
+
+--- Handle a button event on a widget.
+--
+-- This is used internally and should not be called directly.
+-- @function wibox.widget.base.handle_button
+function base.handle_button(event, widget, x, y, button, modifiers, geometry)
+ x = x or y -- luacheck: no unused
+ local function is_any(mod)
+ return #mod == 1 and mod[1] == "Any"
+ end
+
+ local function tables_equal(a, b)
+ if #a ~= #b then
+ return false
+ end
+ for k, v in pairs(b) do
+ if a[k] ~= v then
+ return false
+ end
+ end
+ return true
+ end
+
+ -- Find all matching button objects.
+ local matches = {}
+ for _, v in pairs(widget._private.widget_buttons) do
+ local match = true
+ -- Is it the right button?
+ if v.button ~= 0 and v.button ~= button then match = false end
+ -- Are the correct modifiers pressed?
+ if (not is_any(v.modifiers)) and (not tables_equal(v.modifiers, modifiers)) then match = false end
+ if match then
+ table.insert(matches, v)
+ end
+ end
+
+ -- Emit the signals.
+ for _, v in pairs(matches) do
+ v:emit_signal(event,geometry)
+ end
+end
+
+--- Create widget placement information. This should be used in a widget's
+-- `:layout()` callback.
+-- @tparam widget widget The widget that should be placed.
+-- @param mat A matrix transforming from the parent widget's coordinate
+-- system. For example, use matrix.create_translate(1, 2) to draw a
+-- widget at position (1, 2) relative to the parent widget.
+-- @tparam number width The width of the widget in its own coordinate system.
+-- That is, after applying the transformation matrix.
+-- @tparam number height The height of the widget in its own coordinate system.
+-- That is, after applying the transformation matrix.
+-- @treturn table An opaque object that can be returned from `:layout()`.
+-- @function wibox.widget.base.place_widget_via_matrix
+function base.place_widget_via_matrix(widget, mat, width, height)
+ return {
+ _widget = widget,
+ _width = width,
+ _height = height,
+ _matrix = mat
+ }
+end
+
+--- Create widget placement information. This should be used for a widget's
+-- `:layout()` callback.
+-- @tparam widget widget The widget that should be placed.
+-- @tparam number x The x coordinate for the widget.
+-- @tparam number y The y coordinate for the widget.
+-- @tparam number width The width of the widget in its own coordinate system.
+-- That is, after applying the transformation matrix.
+-- @tparam number height The height of the widget in its own coordinate system.
+-- That is, after applying the transformation matrix.
+-- @treturn table An opaque object that can be returned from `:layout()`.
+-- @function wibox.widget.base.place_widget_at
+function base.place_widget_at(widget, x, y, width, height)
+ return base.place_widget_via_matrix(widget, matrix.create_translate(x, y), width, height)
+end
+
+-- Read the table, separate attributes from widgets.
+local function parse_table(t, leave_empty)
+ local max = 0
+ local attributes, widgets = {}, {}
+ for k,v in pairs(t) do
+ if type(k) == "number" then
+ if v then
+ -- Since `ipairs` doesn't always work on sparse tables, update
+ -- the maximum.
+ if k > max then
+ max = k
+ end
+
+ widgets[k] = v
+ end
+ else
+ attributes[k] = v
+ end
+ end
+
+ -- Pack the sparse table, if the container doesn't support sparse tables.
+ if not leave_empty then
+ widgets = util.table.from_sparse(widgets)
+ max = #widgets
+ end
+
+ return max, attributes, widgets
+end
+
+-- Recursively build a container from a declarative table.
+local function drill(ids, content)
+ if not content then return end
+
+ -- Alias `widget` to `layout` as they are handled the same way.
+ content.layout = content.layout or content.widget
+
+ -- Make sure the layout is not indexed on a function.
+ local layout = type(content.layout) == "function" and content.layout() or content.layout
+
+ -- Create layouts based on metatable's __call.
+ local l = layout.is_widget and layout or layout()
+
+ -- Get the number of children widgets (including nil widgets).
+ local max, attributes, widgets = parse_table(content, l.allow_empty_widget)
+
+ -- Get the optional identifier to create a virtual widget tree to place
+ -- in an "access table" to be able to retrieve the widget.
+ local id = attributes.id
+
+ -- Clear the internal attributes.
+ attributes.id, attributes.layout, attributes.widget = nil, nil, nil
+
+ -- Set layout attributes.
+ -- This has to be done before the widgets are added because it might affect
+ -- the output.
+ for attr, val in pairs(attributes) do
+ if l["set_"..attr] then
+ l["set_"..attr](l, val)
+ elseif type(l[attr]) == "function" then
+ l[attr](l, val)
+ else
+ l[attr] = val
+ end
+ end
+
+ -- Add all widgets.
+ for k = 1, max do
+ -- ipairs cannot be used on sparse tables.
+ local v, id2, e = widgets[k], id, nil
+ if v then
+ -- It is another declarative container, parse it.
+ if not v.is_widget then
+ e, id2 = drill(ids, v)
+ widgets[k] = e
+ end
+ base.check_widget(widgets[k])
+
+ -- Place the widget in the access table.
+ if id2 then
+ l [id2] = e
+ ids[id2] = ids[id2] or {}
+ table.insert(ids[id2], e)
+ end
+ end
+ end
+ -- Replace all children (if any) with the new ones.
+ l:set_children(widgets)
+ return l, id
+end
+
+-- Only available when the declarative system is used.
+local function get_children_by_id(self, name)
+ if rawget(self, "_private") then
+ return self._private.by_id[name] or {}
+ else
+ return rawget(self, "_by_id")[name] or {}
+ end
+end
+
+--- Set a declarative widget hierarchy description.
+--
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html).
+-- @tab args A table containing the widget's disposition.
+-- @function setup
+function base.widget:setup(args)
+ local f,ids = self.set_widget or self.add or self.set_first,{}
+ local w, id = drill(ids, args)
+ f(self,w)
+ if id then
+ -- Avoid being dropped by wibox metatable -> drawin
+ rawset(self, id, w)
+ ids[id] = ids[id] or {}
+ table.insert(ids[id], 1, w)
+ end
+
+ if rawget(self, "_private") then
+ self._private.by_id = ids
+ else
+ rawset(self, "_by_id", ids)
+ end
+
+ rawset(self, "get_children_by_id", get_children_by_id)
+end
+
+--- Create a widget from a declarative description.
+--
+-- See [The declarative layout system](../documentation/03-declarative-layout.md.html).
+-- @tab args A table containing the widgets disposition.
+-- @function wibox.widget.base.make_widget_declarative
+function base.make_widget_declarative(args)
+ local ids = {}
+
+ if (not args.layout) and (not args.widget) then
+ args.widget = base.make_widget(nil, args.id)
+ end
+
+ local w, id = drill(ids, args)
+
+ local mt = getmetatable(w) or {}
+ local orig_string = tostring(w)
+
+ -- Add the main id (if any)
+ if id then
+ ids[id] = ids[id] or {}
+ table.insert(ids[id], 1, w)
+ end
+
+ if rawget(w, "_private") then
+ w._private.by_id = ids
+ else
+ rawset(w, "_by_id", ids)
+ end
+
+ rawset(w, "get_children_by_id", get_children_by_id)
+
+ mt.__tostring = function()
+ return string.format("%s (%s)", id or w.widget_name or "N/A", orig_string)
+ end
+
+ return setmetatable(w, mt)
+end
+
+--- Create an empty widget skeleton.
+--
+-- See [Creating new widgets](../documentation/04-new-widget.md.html).
+-- @tparam[opt] widget proxy If this is set, the returned widget will be a
+-- proxy for this widget. It will be equivalent to this widget.
+-- This means it looks the same on the screen.
+-- @tparam[opt] string widget_name Name of the widget. If not set, it will be
+-- set automatically via @{gears.object.modulename}.
+-- @tparam[opt={}] table args Widget settings
+-- @tparam[opt=false] boolean args.enable_properties Enable automatic getter
+-- and setter methods.
+-- @tparam[opt=nil] table args.class The widget class
+-- @see fit_widget
+-- @function wibox.widget.base.make_widget
+function base.make_widget(proxy, widget_name, args)
+ args = args or {}
+ local ret = object {
+ enable_properties = args.enable_properties,
+ class = args.class,
+ }
+
+ -- Backwards compatibility.
+ -- TODO: Remove this
+ ret:connect_signal("widget::updated", function()
+ ret:emit_signal("widget::layout_changed")
+ ret:emit_signal("widget::redraw_needed")
+ end)
+
+ -- Create a table used to store the widgets internal data.
+ rawset(ret, "_private", {})
+
+ -- No buttons yet.
+ ret._private.widget_buttons = {}
+
+ -- Widget is visible.
+ ret._private.visible = true
+
+ -- Widget is fully opaque.
+ ret._private.opacity = 1
+
+ -- Differentiate tables from widgets.
+ rawset(ret, "is_widget", true)
+
+ -- Size is not restricted/forced.
+ ret._private.forced_width = nil
+ ret._private.forced_height = nil
+
+ -- Make buttons work.
+ ret:connect_signal("button::press", function(...)
+ return base.handle_button("press", ...)
+ end)
+ ret:connect_signal("button::release", function(...)
+ return base.handle_button("release", ...)
+ end)
+
+ if proxy then
+ rawset(ret, "fit", function(_, context, width, height)
+ return base.fit_widget(ret, context, proxy, width, height)
+ end)
+ rawset(ret, "layout", function(_, _, width, height)
+ return { base.place_widget_at(proxy, 0, 0, width, height) }
+ end)
+ proxy:connect_signal("widget::layout_changed", function()
+ ret:emit_signal("widget::layout_changed")
+ end)
+ proxy:connect_signal("widget::redraw_needed", function()
+ ret:emit_signal("widget::redraw_needed")
+ end)
+ end
+
+ -- Set up caches.
+ clear_caches(ret)
+ ret:connect_signal("widget::layout_changed", function()
+ clear_caches(ret)
+ end)
+
+ -- Add functions.
+ for k, v in pairs(base.widget) do
+ rawset(ret, k, v)
+ end
+
+ -- Add __tostring method to metatable.
+ rawset(ret, "widget_name", widget_name or object.modulename(3))
+ local mt = getmetatable(ret) or {}
+ local orig_string = tostring(ret)
+ mt.__tostring = function()
+ return string.format("%s (%s)", ret.widget_name, orig_string)
+ end
+ return setmetatable(ret, mt)
+end
+
+--- Generate an empty widget which takes no space and displays nothing.
+-- @function wibox.widget.base.empty_widget
+function base.empty_widget()
+ return base.make_widget()
+end
+
+--- Do some sanity checking on a widget.
+--
+-- This function raises an error if the widget is not valid.
+-- @function wibox.widget.base.check_widget
+function base.check_widget(widget)
+ assert(type(widget) == "table", "Type should be table, but is " .. tostring(type(widget)))
+ assert(widget.is_widget, "Argument is not a widget!")
+ for _, func in pairs({ "connect_signal", "disconnect_signal" }) do
+ assert(type(widget[func]) == "function", func .. " is not a function")
+ end
+end
+
+return base
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/checkbox.lua b/lib/wibox/widget/checkbox.lua
new file mode 100644
index 0000000..57bdaa3
--- /dev/null
+++ b/lib/wibox/widget/checkbox.lua
@@ -0,0 +1,530 @@
+---------------------------------------------------------------------------
+-- A boolean display widget.
+--
+-- If necessary, themes can implement custom shape:
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_checkbox_custom.svg)
+--
+--
+-- wibox.widget {
+-- checked = true,
+-- color = beautiful.bg_normal,
+-- paddings = 2,
+-- check_shape = function(cr, width, height)
+-- local rs = math.min(width, height)
+-- cr:move_to( 0 , 0 )
+-- cr:line_to( rs , 0 )
+-- cr:move_to( 0 , 0 )
+-- cr:line_to( 0 , rs )
+-- cr:move_to( 0 , rs )
+-- cr:line_to( rs , rs )
+-- cr:move_to( rs , 0 )
+-- cr:line_to( rs , rs )
+-- cr:move_to( 0 , 0 )
+-- cr:line_to( rs , rs )
+-- cr:move_to( 0 , rs )
+-- cr:line_to( rs , 0 )
+-- end,
+-- check_border_color = '#ff0000',
+-- check_color = '#00000000',
+-- check_border_width = 1,
+-- widget = wibox.widget.checkbox
+-- }
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_checkbox.svg)
+--
+-- @usage
+--wibox.widget {
+-- checked = true,
+-- color = beautiful.bg_normal,
+-- paddings = 2,
+-- shape = gears.shape.circle,
+-- widget = wibox.widget.checkbox
+--}
+-- @author Emmanuel Lepage Valle
+-- @copyright 2010 Emmanuel Lepage Vallee
+-- @classmod wibox.widget.checkbox
+---------------------------------------------------------------------------
+
+local color = require( "gears.color" )
+local base = require( "wibox.widget.base" )
+local beautiful = require( "beautiful" )
+local shape = require( "gears.shape" )
+local util = require( "awful.util" )
+
+local checkbox = {}
+
+--- The outer (unchecked area) border width.
+-- @beautiful beautiful.checkbox_border_width
+
+--- The outer (unchecked area) background color, pattern or gradient.
+-- @beautiful beautiful.checkbox_bg
+
+--- The outer (unchecked area) border color.
+-- @beautiful beautiful.checkbox_border_color
+
+--- The checked part border color.
+-- @beautiful beautiful.checkbox_check_border_color
+
+--- The checked part border width.
+-- @beautiful beautiful.checkbox_check_border_width
+
+--- The checked part filling color.
+-- @beautiful beautiful.checkbox_check_color
+
+--- The outer (unchecked area) shape.
+-- @beautiful beautiful.checkbox_shape
+-- @see gears.shape
+
+--- The checked part shape.
+-- If none is set, then the `shape` property will be used.
+-- @beautiful beautiful.checkbox_check_shape
+-- @see gears.shape
+
+--- The padding between the outline and the progressbar.
+-- @beautiful beautiful.checkbox_paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+--- The checkbox color.
+-- This will be used for the unchecked part border color and the checked part
+-- filling color. Note that `check_color` and `border_color` have priority
+-- over this property.
+-- @beautiful beautiful.checkbox_color
+
+--- The outer (unchecked area) border width.
+-- @property border_width
+
+--- The outer (unchecked area) background color, pattern or gradient.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_checkbox_bg.svg)
+--
+-- @usage
+--wibox.widget {
+-- checked = true,
+-- color = beautiful.bg_normal,
+-- bg = '#ff00ff',
+-- border_width = 3,
+-- paddings = 4,
+-- border_color = '#0000ff',
+-- check_color = '#ff0000',
+-- check_border_color = '#ffff00',
+-- check_border_width = 1,
+-- widget = wibox.widget.checkbox
+--}
+-- @property bg
+
+--- The outer (unchecked area) border color.
+-- @property border_color
+
+--- The checked part border color.
+-- @property check_border_color
+
+--- The checked part border width.
+-- @property check_border_width
+
+--- The checked part filling color.
+-- @property check_color
+
+--- The outer (unchecked area) shape.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_checkbox_shape.svg)
+--
+-- @usage
+--for _, s in ipairs {'rectangle', 'circle', 'losange', 'octogon'} do
+-- wibox.widget {
+-- checked = true,
+-- color = beautiful.bg_normal,
+-- paddings = 2,
+-- shape = gears.shape[s],
+-- widget = wibox.widget.checkbox
+-- }
+--end
+-- @property shape
+-- @see gears.shape
+
+--- The checked part shape.
+-- If none is set, then the `shape` property will be used.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_checkbox_check_shape.svg)
+--
+-- @usage
+--for _, s in ipairs {'rectangle', 'circle', 'losange', 'octogon'} do
+-- wibox.widget {
+-- checked = true,
+-- color = beautiful.bg_normal,
+-- paddings = 2,
+-- check_shape = gears.shape[s],
+-- widget = wibox.widget.checkbox
+-- }
+--end
+-- @property check_shape
+-- @see gears.shape
+
+--- The padding between the outline and the progressbar.
+-- @property paddings
+-- @tparam[opt=0] table|number paddings A number or a table
+-- @tparam[opt=0] number paddings.top
+-- @tparam[opt=0] number paddings.bottom
+-- @tparam[opt=0] number paddings.left
+-- @tparam[opt=0] number paddings.right
+
+--- The checkbox color.
+-- This will be used for the unchecked part border color and the checked part
+-- filling color. Note that `check_color` and `border_color` have priority
+-- over this property.
+-- @property color
+
+local function outline_workarea(self, width, height)
+ local offset = (self._private.border_width or
+ beautiful.checkbox_border_width or 1)/2
+
+ return {
+ x = offset,
+ y = offset,
+ width = width-2*offset,
+ height = height-2*offset
+ }
+end
+
+-- The child widget area
+local function content_workarea(self, width, height)
+ local padding = self._private.paddings or {}
+ local offset = self:get_check_border_width() or 0
+ local wa = outline_workarea(self, width, height)
+
+ wa.x = offset + wa.x + (padding.left or 1)
+ wa.y = offset + wa.y + (padding.top or 1)
+ wa.width = wa.width - (padding.left or 1) - (padding.right or 1) - 2*offset
+ wa.height = wa.height - (padding.top or 1) - (padding.bottom or 1) - 2*offset
+
+ return wa
+end
+
+local function draw(self, _, cr, width, height)
+ local size = math.min(width, height)
+
+ local background_shape = self:get_shape() or shape.rectangle
+ local border_width = self:get_border_width() or 1
+
+ local main_color = self:get_color()
+ local bg = self:get_bg()
+ local border_color = self:get_border_color()
+
+ -- If no color is set, it will fallback to the default one
+ if border_color or main_color then
+ cr:set_source(color(border_color or main_color))
+ end
+
+ local wa = outline_workarea(self, size, size)
+ cr:translate(wa.x, wa.y)
+ background_shape(cr, wa.width, wa.height)
+ cr:set_line_width(border_width)
+
+ if bg then
+ cr:save()
+ cr:set_source(color(bg))
+ cr:fill_preserve()
+ cr:restore()
+ end
+
+ cr:stroke()
+
+ cr:translate(-wa.x, -wa.y)
+
+ -- Draw the checked part
+ if self._private.checked then
+ local col = self:get_check_color() or main_color
+ border_color = self:get_check_border_color()
+ border_width = self:get_check_border_width() or 0
+ local check_shape = self:get_check_shape() or background_shape
+
+ wa = content_workarea(self, size, size)
+ cr:translate(wa.x, wa.y)
+
+ check_shape(cr, wa.width, wa.height)
+
+ if col then
+ cr:set_source(color(col))
+ end
+
+ if border_width > 0 then
+ cr:fill_preserve()
+ cr:set_line_width(border_width)
+ cr:set_source(color(border_color))
+ cr:stroke()
+ else
+ cr:fill()
+ end
+ end
+end
+
+local function fit(_, _, w, h)
+ local size = math.min(w, h)
+ return size, size
+end
+
+--- If the checkbox is checked.
+-- @property checked
+-- @param boolean
+
+for _, prop in ipairs {"border_width", "bg", "border_color", "check_border_color",
+ "check_border_width", "check_color", "shape", "check_shape", "paddings",
+ "checked", "color" } do
+ checkbox["set_"..prop] = function(self, value)
+ self._private[prop] = value
+ self:emit_signal("property::"..prop)
+ self:emit_signal("widget::redraw_needed")
+ end
+ checkbox["get_"..prop] = function(self)
+ return self._private[prop] or beautiful["checkbox_"..prop]
+ end
+end
+
+--- The checkbox color.
+-- @property color
+
+function checkbox:set_paddings(val)
+ self._private.paddings = type(val) == "number" and {
+ left = val,
+ right = val,
+ top = val,
+ bottom = val,
+ } or val or {}
+ self:emit_signal("property::paddings")
+ self:emit_signal("widget::redraw_needed")
+end
+
+local function new(checked, args)
+ checked, args = checked or false, args or {}
+
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret, checkbox)
+
+ ret._private.checked = checked
+ ret._private.color = args.color and color(args.color) or nil
+
+ rawset(ret, "fit" , fit )
+ rawset(ret, "draw", draw)
+
+ 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 setmetatable({}, { __call = function(_, ...) return new(...) end})
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua
new file mode 100644
index 0000000..c03c726
--- /dev/null
+++ b/lib/wibox/widget/graph.lua
@@ -0,0 +1,575 @@
+---------------------------------------------------------------------------
+--- A graph widget.
+--
+-- The graph goes from left to right. To change this to right to left, use
+-- a `wibox.container.mirror` widget. This can also be used to have data
+-- shown from top to bottom.
+--
+-- To add text on top of the graph, use a `wibox.layout.stack` and a
+-- `wibox.container.align` widgets.
+--
+-- To display the graph vertically, use a `wibox.container.rotate` widget.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_graph.svg)
+--
+-- @usage
+--wibox.widget {
+-- max_value = 29,
+-- widget = wibox.widget.graph
+--}
+-- @author Julien Danjou &lt;julien@danjou.info&gt;
+-- @copyright 2009 Julien Danjou
+-- @classmod wibox.widget.graph
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local ipairs = ipairs
+local math = math
+local table = table
+local type = type
+local color = require("gears.color")
+local base = require("wibox.widget.base")
+local beautiful = require("beautiful")
+
+local graph = { mt = {} }
+
+--- Set the graph border color.
+-- If the value is nil, no border will be drawn.
+--
+-- @property border_color
+-- @tparam gears.color border_color The border color to set.
+-- @see gears.color
+
+--- Set the graph foreground color.
+--
+-- @property color
+-- @tparam color color The graph color.
+-- @see gears.color
+
+--- Set the graph background color.
+--
+-- @property background_color
+-- @tparam gears.color background_color The graph background color.
+-- @see gears.color
+
+--- Set the maximum value the graph should handle.
+-- If "scale" is also set, the graph never scales up below this value, but it
+-- automatically scales down to make all data fit.
+--
+-- @property max_value
+-- @param number
+
+--- The minimum value.
+-- Note that the min_value is not supported when used along with the stack
+-- property.
+-- @property min_value
+-- @param number
+
+--- Set the graph to automatically scale its values. Default is false.
+--
+-- @property scale
+-- @param boolean
+
+--- Set the width or the individual steps.
+--
+-- Note that it isn't supported when used along with stacked graphs.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_graph_step.svg)
+--
+-- @usage
+--wibox.widget {
+-- max_value = 29,
+-- step_width = 3,
+-- step_spacing = 1,
+-- step_shape = function(cr, width, height)
+-- gears.shape.rounded_rect(cr, width, height, 2)
+-- end,
+-- widget = wibox.widget.graph
+--}
+--
+-- @property step_width
+-- @param[opt=1] number
+
+--- Set the spacing between the steps.
+--
+-- Note that it isn't supported when used along with stacked graphs.
+--
+-- @property step_spacing
+-- @param[opt=0] number
+
+--- The step shape.
+-- @property step_shape
+-- @param[opt=rectangle] shape
+-- @see gears.shape
+
+--- Set the graph to draw stacks. Default is false.
+--
+-- @property stack
+-- @param boolean
+
+--- Set the graph stacking colors. Order matters.
+--
+-- @property stack_colors
+-- @param stack_colors A table with stacking colors.
+
+--- The graph background color.
+-- @beautiful beautiful.graph_bg
+
+--- The graph foreground color.
+-- @beautiful beautiful.graph_fg
+
+--- The graph border color.
+-- @beautiful beautiful.graph_border_color
+
+local properties = { "width", "height", "border_color", "stack",
+ "stack_colors", "color", "background_color",
+ "max_value", "scale", "min_value", "step_shape",
+ "step_spacing", "step_width" }
+
+function graph.draw(_graph, _, cr, width, height)
+ local max_value = _graph._private.max_value
+ local min_value = _graph._private.min_value or (
+ _graph._private.scale and math.huge or 0)
+ local values = _graph._private.values
+
+ local step_shape = _graph._private.step_shape
+ local step_spacing = _graph._private.step_spacing or 0
+ local step_width = _graph._private.step_width or 1
+
+ cr:set_line_width(1)
+
+ -- Draw the background first
+ cr:set_source(color(_graph._private.background_color or beautiful.graph_bg or "#000000aa"))
+ cr:paint()
+
+ -- Account for the border width
+ cr:save()
+ if _graph._private.border_color then
+ cr:translate(1, 1)
+ width, height = width - 2, height - 2
+ end
+
+ -- Draw a stacked graph
+ if _graph._private.stack then
+
+ if _graph._private.scale then
+ for _, v in ipairs(values) do
+ for _, sv in ipairs(v) do
+ if sv > max_value then
+ max_value = sv
+ end
+ if min_value > sv then
+ min_value = sv
+ end
+ end
+ end
+ end
+
+ for i = 0, width do
+ local rel_i = 0
+ local rel_x = i + 0.5
+
+ if _graph._private.stack_colors then
+ for idx, col in ipairs(_graph._private.stack_colors) do
+ local stack_values = values[idx]
+ if stack_values and i < #stack_values then
+ local value = stack_values[#stack_values - i] + rel_i
+ cr:move_to(rel_x, height * (1 - (rel_i / max_value)))
+ cr:line_to(rel_x, height * (1 - (value / max_value)))
+ cr:set_source(color(col or beautiful.graph_fg or "#ff0000"))
+ cr:stroke()
+ rel_i = value
+ end
+ end
+ end
+ end
+ else
+ if _graph._private.scale then
+ for _, v in ipairs(values) do
+ if v > max_value then
+ max_value = v
+ end
+ if min_value > v then
+ min_value = v
+ end
+ end
+ end
+
+ -- Draw the background on no value
+ if #values ~= 0 then
+ -- Draw reverse
+ for i = 0, #values - 1 do
+ local value = values[#values - i]
+ if value >= 0 then
+ local x = i*step_width + ((i-1)*step_spacing) + 0.5
+ value = (value - min_value) / max_value
+ cr:move_to(x, height * (1 - value))
+
+ if step_shape then
+ cr:translate(step_width + (i>1 and step_spacing or 0), height * (1 - value))
+ step_shape(cr, step_width, height)
+ cr:translate(0, -(height * (1 - value)))
+ elseif step_width > 1 then
+ cr:rectangle(x, height * (1 - value), step_width, height)
+ else
+ cr:line_to(x, height)
+ end
+ end
+ end
+ cr:set_source(color(_graph._private.color or beautiful.graph_fg or "#ff0000"))
+
+ if step_shape or step_width > 1 then
+ cr:fill()
+ else
+ cr:stroke()
+ end
+ end
+
+ end
+
+ -- Undo the cr:translate() for the border and step shapes
+ cr:restore()
+
+ -- Draw the border last so that it overlaps already drawn values
+ if _graph._private.border_color then
+ -- We decremented these by two above
+ width, height = width + 2, height + 2
+
+ -- Draw the border
+ cr:rectangle(0.5, 0.5, width - 1, height - 1)
+ cr:set_source(color(_graph._private.border_color or beautiful.graph_border_color or "#ffffff"))
+ cr:stroke()
+ end
+end
+
+function graph.fit(_graph)
+ return _graph._private.width, _graph._private.height
+end
+
+--- Add a value to the graph
+--
+-- @param value The value to be added to the graph
+-- @param group The stack color group index.
+function graph:add_value(value, group)
+ value = value or 0
+ local values = self._private.values
+ local max_value = self._private.max_value
+ value = math.max(0, value)
+ if not self._private.scale then
+ value = math.min(max_value, value)
+ end
+
+ if self._private.stack and group then
+ if not self._private.values[group]
+ or type(self._private.values[group]) ~= "table"
+ then
+ self._private.values[group] = {}
+ end
+ values = self._private.values[group]
+ end
+ table.insert(values, value)
+
+ local border_width = 0
+ if self._private.border_color then border_width = 2 end
+
+ -- Ensure we never have more data than we can draw
+ while #values > self._private.width - border_width do
+ table.remove(values, 1)
+ end
+
+ self:emit_signal("widget::redraw_needed")
+ return self
+end
+
+--- Clear the graph.
+function graph:clear()
+ self._private.values = {}
+ self:emit_signal("widget::redraw_needed")
+ return self
+end
+
+--- Set the graph height.
+-- @param height The height to set.
+function graph:set_height(height)
+ if height >= 5 then
+ self._private.height = height
+ self:emit_signal("widget::layout_changed")
+ end
+ return self
+end
+
+--- Set the graph width.
+-- @param width The width to set.
+function graph:set_width(width)
+ if width >= 5 then
+ self._private.width = width
+ self:emit_signal("widget::layout_changed")
+ end
+ return self
+end
+
+-- Build properties function
+for _, prop in ipairs(properties) do
+ if not graph["set_" .. prop] then
+ graph["set_" .. prop] = function(_graph, value)
+ if _graph._private[prop] ~= value then
+ _graph._private[prop] = value
+ _graph:emit_signal("widget::redraw_needed")
+ end
+ return _graph
+ end
+ end
+ if not graph["get_" .. prop] then
+ graph["get_" .. prop] = function(_graph)
+ return _graph._private[prop]
+ end
+ end
+end
+
+--- Create a graph widget.
+-- @param args Standard widget() arguments. You should add width and height
+-- key to set graph geometry.
+-- @return A new graph widget.
+-- @function wibox.widget.graph
+function graph.new(args)
+ args = args or {}
+
+ local width = args.width or 100
+ local height = args.height or 20
+
+ if width < 5 or height < 5 then return end
+
+ local _graph = base.make_widget(nil, nil, {enable_properties = true})
+
+ _graph._private.width = width
+ _graph._private.height = height
+ _graph._private.values = {}
+ _graph._private.max_value = 1
+
+ -- Set methods
+ _graph.add_value = graph["add_value"]
+ _graph.clear = graph["clear"]
+ _graph.draw = graph.draw
+ _graph.fit = graph.fit
+
+ for _, prop in ipairs(properties) do
+ _graph["set_" .. prop] = graph["set_" .. prop]
+ _graph["get_" .. prop] = graph["get_" .. prop]
+ end
+
+ return _graph
+end
+
+function graph.mt:__call(...)
+ return graph.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(graph, graph.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/imagebox.lua b/lib/wibox/widget/imagebox.lua
new file mode 100644
index 0000000..bdfa499
--- /dev/null
+++ b/lib/wibox/widget/imagebox.lua
@@ -0,0 +1,395 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_imagebox.svg)
+--
+-- @usage
+--wibox.widget {
+-- image = beautiful.awesome_icon,
+-- resize = false,
+-- widget = wibox.widget.imagebox
+--}
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.widget.imagebox
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base")
+local surface = require("gears.surface")
+local util = require("awful.util")
+local setmetatable = setmetatable
+local type = type
+local print = print
+local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
+
+local imagebox = { mt = {} }
+
+-- Draw an imagebox with the given cairo context in the given geometry.
+function imagebox:draw(_, cr, width, height)
+ if not self._private.image then return end
+ if width == 0 or height == 0 then return end
+
+ if not self._private.resize_forbidden then
+ -- Let's scale the image so that it fits into (width, height)
+ local w = self._private.image:get_width()
+ local h = self._private.image:get_height()
+ local aspect = width / w
+ local aspect_h = height / h
+ if aspect > aspect_h then aspect = aspect_h end
+
+ cr:scale(aspect, aspect)
+ end
+
+ -- Set the clip
+ if self._private.clip_shape then
+ cr:clip(self._private.clip_shape(cr, width, height, unpack(self._private.clip_args)))
+ end
+
+ cr:set_source_surface(self._private.image, 0, 0)
+ cr:paint()
+end
+
+-- Fit the imagebox into the given geometry
+function imagebox:fit(_, width, height)
+ if not self._private.image then
+ return 0, 0
+ end
+
+ local w = self._private.image:get_width()
+ local h = self._private.image:get_height()
+
+ if w > width then
+ h = h * width / w
+ w = width
+ end
+ if h > height then
+ w = w * height / h
+ h = height
+ end
+
+ if h == 0 or w == 0 then
+ return 0, 0
+ end
+
+ if not self._private.resize_forbidden then
+ local aspect = width / w
+ local aspect_h = height / h
+
+ -- Use the smaller one of the two aspect ratios.
+ if aspect > aspect_h then aspect = aspect_h end
+
+ w, h = w * aspect, h * aspect
+ end
+
+ return w, h
+end
+
+--- Set an imagebox' image
+-- @property image
+-- @param image Either a string or a cairo image surface. A string is
+-- interpreted as the path to a png image file.
+-- @return true on success, false if the image cannot be used
+
+function imagebox:set_image(image)
+ if type(image) == "string" then
+ image = surface.load(image)
+ if not image then
+ print(debug.traceback())
+ return false
+ end
+ end
+
+ image = surface.load(image)
+
+ if image then
+ local w = image.width
+ local h = image.height
+ if w <= 0 or h <= 0 then
+ return false
+ end
+ end
+
+ if self._private.image == image then
+ -- The image could have been modified, so better redraw
+ self:emit_signal("widget::redraw_needed")
+ return
+ end
+
+ self._private.image = image
+
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ return true
+end
+
+--- Set a clip shape for this imagebox
+-- A clip shape define an area where the content is displayed and one where it
+-- is trimmed.
+--
+-- @property clip_shape
+-- @param clip_shape A `gears_shape` compatible shape function
+-- @see gears.shape
+-- @see set_clip_shape
+
+--- Set a clip shape for this imagebox
+-- A clip shape define an area where the content is displayed and one where it
+-- is trimmed.
+--
+-- Any other parameters will be passed to the clip shape function
+--
+-- @param clip_shape A `gears_shape` compatible shape function
+-- @see gears.shape
+-- @see clip_shape
+function imagebox:set_clip_shape(clip_shape, ...)
+ self._private.clip_shape = clip_shape
+ self._private.clip_args = {...}
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Should the image be resized to fit into the available space?
+-- @property resize
+-- @param allowed If false, the image will be clipped, else it will be resized
+-- to fit into the available space.
+
+function imagebox:set_resize(allowed)
+ self._private.resize_forbidden = not allowed
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Returns a new imagebox.
+-- Any other arguments will be passed to the clip shape function
+-- @param image the image to display, may be nil
+-- @param resize_allowed If false, the image will be clipped, else it will be resized
+-- to fit into the available space.
+-- @param clip_shape A `gears.shape` compatible function
+-- @treturn table A new `imagebox`
+-- @function wibox.widget.imagebox
+local function new(image, resize_allowed, clip_shape)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, imagebox, true)
+
+ if image then
+ ret:set_image(image)
+ end
+ if resize_allowed ~= nil then
+ ret:set_resize(resize_allowed)
+ end
+
+ ret._private.clip_shape = clip_shape
+ ret._private.clip_args = {}
+
+ return ret
+end
+
+function imagebox.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(imagebox, imagebox.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/init.lua b/lib/wibox/widget/init.lua
new file mode 100644
index 0000000..43c6fc0
--- /dev/null
+++ b/lib/wibox/widget/init.lua
@@ -0,0 +1,22 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.widget
+---------------------------------------------------------------------------
+local base = require("wibox.widget.base")
+
+return setmetatable({
+ base = base;
+ textbox = require("wibox.widget.textbox");
+ imagebox = require("wibox.widget.imagebox");
+ background = require("wibox.widget.background");
+ systray = require("wibox.widget.systray");
+ textclock = require("wibox.widget.textclock");
+ progressbar = require("wibox.widget.progressbar");
+ graph = require("wibox.widget.graph");
+ checkbox = require("wibox.widget.checkbox");
+ piechart = require("wibox.widget.piechart");
+ slider = require("wibox.widget.slider");
+}, {__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/widget/piechart.lua b/lib/wibox/widget/piechart.lua
new file mode 100644
index 0000000..5a1c185
--- /dev/null
+++ b/lib/wibox/widget/piechart.lua
@@ -0,0 +1,467 @@
+---------------------------------------------------------------------------
+-- Display percentage in a circle.
+--
+-- Note that this widget makes no attempts to prevent overlapping labels or
+-- labels drawn outside of the widget boundaries.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_piechart.svg)
+--
+-- @usage
+--wibox.widget {
+-- data_list = {
+-- { 'L1', 100 },
+-- { 'L2', 200 },
+-- { 'L3', 300 },
+-- },
+-- border_width = 1,
+-- colors = {
+-- beautiful.bg_normal,
+-- beautiful.bg_highlight,
+-- beautiful.border_color,
+-- },
+-- widget = wibox.widget.piechart
+--}
+-- @author Emmanuel Lepage Valle
+-- @copyright 2012 Emmanuel Lepage Vallee
+-- @classmod wibox.widget.piechart
+---------------------------------------------------------------------------
+
+local color = require( "gears.color" )
+local base = require( "wibox.widget.base" )
+local beautiful = require( "beautiful" )
+local util = require( "awful.util" )
+local pie = require( "gears.shape" ).pie
+local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
+
+local module = {}
+
+local piechart = {}
+
+local function draw_label(cr,angle,radius,center_x,center_y,text)
+ local edge_x = center_x+(radius/2)*math.cos(angle)
+ local edge_y = center_y+(radius/2)*math.sin(angle)
+
+ cr:move_to(edge_x, edge_y)
+
+ cr:rel_line_to(radius*math.cos(angle), radius*math.sin(angle))
+
+ local x,y = cr:get_current_point()
+
+ cr:rel_line_to(x > center_x and radius/2 or -radius/2, 0)
+
+ local ext = cr:text_extents(text)
+
+ cr:rel_move_to(
+ (x>center_x and radius/2.5 or (-radius/2.5 - ext.width)),
+ ext.height/2
+ )
+
+ cr:show_text(text) --TODO eventually port away from the toy API
+ cr:stroke()
+
+ cr:arc(edge_x, edge_y,2,0,2*math.pi)
+ cr:arc(x+(x>center_x and radius/2 or -radius/2),y,2,0,2*math.pi)
+
+ cr:fill()
+end
+
+local function compute_sum(data)
+ local ret = 0
+ for _, entry in ipairs(data) do
+ ret = ret + entry[2]
+ end
+
+ return ret
+end
+
+local function draw(self, _, cr, width, height)
+ if not self._private.data_list then return end
+
+ local radius = (height > width and width or height) / 4
+ local sum, start, count = compute_sum(self._private.data_list),0,0
+ local has_label = self._private.display_labels ~= false
+
+ -- Labels need to be drawn later so the original source is kept
+ -- use get_source() wont work are the reference cannot be set from Lua(?)
+ local labels = {}
+
+ local border_width = self:get_border_width() or 1
+ local border_color = self:get_border_color()
+ border_color = border_color and color(border_color)
+
+ -- Draw the pies
+ cr:save()
+ cr:set_line_width(border_width)
+
+ -- Alternate from a given sets or colors
+ local colors = self:get_colors()
+ local col_count = colors and #colors or 0
+
+ for _, entry in ipairs(self._private.data_list) do
+ local k, v = entry[1], entry[2]
+ local end_angle = start + 2*math.pi*(v/sum)
+
+ local col = colors and color(colors[math.fmod(count,col_count)+1]) or nil
+
+ pie(cr, width, height, start, end_angle, radius)
+
+ if col then
+ cr:save()
+ cr:set_source(color(col))
+ end
+
+ if border_width > 0 then
+ if col then
+ cr:fill_preserve()
+ cr:restore()
+ end
+
+ -- By default, it uses the fg color
+ if border_color then
+ cr:set_source(border_color)
+ end
+ cr:stroke()
+ elseif col then
+ cr:fill()
+ cr:restore()
+ end
+
+ -- Store the label position for later
+ if has_label then
+ table.insert(labels, {
+ --[[angle ]] start+(end_angle-start)/2,
+ --[[radius ]] radius,
+ --[[center_x]] width/2,
+ --[[center_y]] height/2,
+ --[[text ]] k,
+ })
+ end
+ start,count = end_angle,count+1
+ end
+ cr:restore()
+
+ -- Draw the labels
+ if has_label then
+ for _, v in ipairs(labels) do
+ draw_label(cr, unpack(v))
+ end
+ end
+end
+
+local function fit(_, _, width, height)
+ return width, height
+end
+
+--- The pie chart data list.
+-- @property data_list
+-- @tparam table data_list Sorted table where each entry has a label as its
+-- first value and a number as its second value.
+
+--- The pie chart data.
+-- @property data
+-- @tparam table data Labels as keys and number as value.
+
+--- The border color.
+-- If none is set, it will use current foreground (text) color.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_piechart_border_color.svg)
+--
+-- @property border_color
+-- @param color
+-- @see gears.color
+
+--- The pie elements border width.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_piechart_border_width.svg)
+--
+-- @property border_width
+-- @tparam[opt=1] number border_width
+
+--- The pie chart colors.
+-- If no color is set, only the border will be drawn. If less colors than
+-- required are set, colors will be re-used in order.
+-- @property colors
+-- @tparam table colors A table of colors, one for each elements
+-- @see gears.color
+
+--- The border color.
+-- If none is set, it will use current foreground (text) color.
+-- @beautiful beautiful.piechart_border_color
+-- @param color
+-- @see gears.color
+
+--- If the pie chart has labels.
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_piechart_label.svg)
+--
+-- @property display_labels
+-- @param[opt=true] boolean
+
+--- The pie elements border width.
+-- @beautiful beautiful.piechart_border_width
+-- @tparam[opt=1] number border_width
+
+--- The pie chart colors.
+-- If no color is set, only the border will be drawn. If less colors than
+-- required are set, colors will be re-used in order.
+-- @beautiful beautiful.piechart_colors
+-- @tparam table colors A table of colors, one for each elements
+-- @see gears.color
+
+for _, prop in ipairs {"data_list", "border_color", "border_width", "colors",
+ "display_labels"
+ } do
+ piechart["set_"..prop] = function(self, value)
+ self._private[prop] = value
+ self:emit_signal("property::"..prop)
+ if prop == "data_list" then
+ self:emit_signal("property::data")
+ end
+ self:emit_signal("widget::redraw_needed")
+ end
+ piechart["get_"..prop] = function(self)
+ return self._private[prop] or beautiful["piechart_"..prop]
+ end
+end
+
+function piechart:set_data(value)
+ local list = {}
+ for k, v in pairs(value) do
+ table.insert(list, { k, v })
+ end
+ self:set_data_list(list)
+end
+
+function piechart:get_data()
+ local list = {}
+ for _, entry in ipairs(self:get_data_list()) do
+ list[entry[1]] = entry[2]
+ end
+ return list
+end
+
+local function new(data_list)
+
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret, piechart)
+
+ rawset(ret, "fit" , fit )
+ rawset(ret, "draw", draw)
+
+ ret:set_data_list(data_list)
+
+ 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 setmetatable(module, { __call = function(_, ...) return new(...) end })
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/progressbar.lua b/lib/wibox/widget/progressbar.lua
new file mode 100644
index 0000000..943c49f
--- /dev/null
+++ b/lib/wibox/widget/progressbar.lua
@@ -0,0 +1,754 @@
+---------------------------------------------------------------------------
+--- A progressbar widget.
+--
+-- To add text on top of the progressbar, a `wibox.layout.stack` can be used:
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_progressbar_text.svg)
+--
+--
+-- wibox.widget {
+-- {
+-- max_value = 1,
+-- value = 0.5,
+-- forced_height = 20,
+-- forced_width = 100,
+-- paddings = 1,
+-- border_width = 1,
+-- border_color = beautiful.border_color,
+-- widget = wibox.widget.progressbar,
+-- },
+-- {
+-- text = '50%',
+-- widget = wibox.widget.textbox,
+-- },
+-- layout = wibox.layout.stack
+-- }
+--
+-- To display the progressbar vertically, use a `wibox.container.rotate` widget:
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_progressbar_vertical.svg)
+--
+--
+-- wibox.widget {
+-- {
+-- max_value = 1,
+-- value = 0.33,
+-- widget = wibox.widget.progressbar,
+-- },
+-- forced_height = 100,
+-- forced_width = 20,
+-- direction = 'east',
+-- layout = wibox.container.rotate,
+-- }
+--
+-- By default, this widget will take all the available size. To prevent this,
+-- a `wibox.container.constraint` widget or the `forced_width`/`forced_height`
+-- properties have to be used.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_progressbar.svg)
+--
+-- @usage
+--wibox.widget {
+-- max_value = 1,
+-- value = 0.33,
+-- forced_height = 20,
+-- forced_width = 100,
+-- shape = gears.shape.rounded_bar,
+-- border_width = 2,
+-- border_color = beautiful.border_color,
+-- widget = wibox.widget.progressbar,
+--}
+--
+-- @author Julien Danjou &lt;julien@danjou.info&gt;
+-- @copyright 2009 Julien Danjou
+-- @classmod wibox.widget.progressbar
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local ipairs = ipairs
+local math = math
+local util = require("awful.util")
+local base = require("wibox.widget.base")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+local shape = require("gears.shape")
+
+local progressbar = { mt = {} }
+
+--- The progressbar border color.
+-- If the value is nil, no border will be drawn.
+--
+-- @property border_color
+-- @tparam gears.color color The border color to set.
+-- @see gears.color
+
+--- The progressbar border width.
+-- @property border_width
+
+--- The progressbar inner border color.
+-- If the value is nil, no border will be drawn.
+--
+-- @property bar_border_color
+-- @tparam gears.color color The border color to set.
+-- @see gears.color
+
+--- The progressbar inner border width.
+-- @property bar_border_width
+
+--- The progressbar foreground color.
+--
+-- @property color
+-- @tparam gears.color color The progressbar color.
+-- @see gears.color
+
+--- The progressbar background color.
+--
+-- @property background_color
+-- @tparam gears.color color The progressbar background color.
+-- @see gears.color
+
+--- The progressbar inner shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_progressbar_bar_shape.svg)
+--
+-- @usage
+--for _, shape in ipairs {'rounded_bar', 'octogon', 'hexagon', 'powerline' } do
+-- l:add(wibox.widget {
+-- value = 0.33,
+-- bar_shape = gears.shape[shape],
+-- bar_border_color = beautiful.border_color,
+-- bar_border_width = 1,
+-- border_width = 2,
+-- border_color = beautiful.border_color,
+-- paddings = 1,
+-- widget = wibox.widget.progressbar,
+-- })
+--end
+--
+-- @property bar_shape
+-- @tparam[opt=gears.shape.rectangle] gears.shape shape
+-- @see gears.shape
+
+--- The progressbar shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_progressbar_shape.svg)
+--
+-- @usage
+--for _, shape in ipairs {'rounded_bar', 'octogon', 'hexagon', 'powerline' } do
+-- l:add(wibox.widget {
+-- value = 0.33,
+-- shape = gears.shape[shape],
+-- border_width = 2,
+-- border_color = beautiful.border_color,
+-- widget = wibox.widget.progressbar,
+-- })
+--end
+--
+-- @property shape
+-- @tparam[opt=gears.shape.rectangle] gears.shape shape
+-- @see gears.shape
+
+--- Set the progressbar to draw vertically.
+-- This doesn't do anything anymore, use a `wibox.container.rotate` widget.
+-- @deprecated set_vertical
+-- @tparam boolean vertical
+
+--- Force the inner part (the bar) to fit in the background shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_progressbar_clip.svg)
+--
+-- @usage
+--wibox.widget {
+-- value = 75,
+-- max_value = 100,
+-- border_width = 2,
+-- border_color = beautiful.border_color,
+-- color = beautiful.border_color,
+-- shape = gears.shape.rounded_bar,
+-- bar_shape = gears.shape.rounded_bar,
+-- clip = false,
+-- forced_height = 30,
+-- forced_width = 100,
+-- paddings = 5,
+-- margins = {
+-- top = 12,
+-- bottom = 12,
+-- },
+-- widget = wibox.widget.progressbar,
+--}
+--
+-- @property clip
+-- @tparam[opt=true] boolean clip
+
+--- The progressbar to draw ticks. Default is false.
+--
+-- @property ticks
+-- @param boolean
+
+--- The progressbar ticks gap.
+--
+-- @property ticks_gap
+-- @param number
+
+--- The progressbar ticks size.
+--
+-- @property ticks_size
+-- @param number
+
+--- The maximum value the progressbar should handle.
+--
+-- @property max_value
+-- @param number
+
+--- The progressbar background color.
+-- @beautiful beautiful.progressbar_bg
+
+--- The progressbar foreground color.
+-- @beautiful beautiful.progressbar_fg
+
+--- The progressbar shape.
+-- @beautiful beautiful.progressbar_shape
+-- @see gears.shape
+
+--- The progressbar border color.
+-- @beautiful beautiful.progressbar_border_color
+
+--- The progressbar outer border width.
+-- @beautiful beautiful.progressbar_border_width
+
+--- The progressbar inner shape.
+-- @beautiful beautiful.progressbar_bar_shape
+-- @see gears.shape
+
+--- The progressbar bar border width.
+-- @beautiful beautiful.progressbar_bar_border_width
+
+--- The progressbar bar border color.
+-- @beautiful beautiful.progressbar_bar_border_color
+
+--- The progressbar margins.
+-- Note that if the `clip` is disabled, this allows the background to be smaller
+-- than the bar.
+--
+-- See the `clip` example.
+--
+-- @tparam[opt=0] (table|number|nil) margins A table for each side or a number
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @property margins
+-- @see clip
+
+--- The progressbar padding.
+-- Note that if the `clip` is disabled, this allows the bar to be taller
+-- than the background.
+--
+-- See the `clip` example.
+--
+-- @tparam[opt=0] (table|number|nil) padding A table for each side or a number
+-- @tparam[opt=0] number padding.top
+-- @tparam[opt=0] number padding.bottom
+-- @tparam[opt=0] number padding.left
+-- @tparam[opt=0] number padding.right
+-- @property paddings
+-- @see clip
+
+--- The progressbar margins.
+-- Note that if the `clip` is disabled, this allows the background to be smaller
+-- than the bar.
+-- @tparam[opt=0] (table|number|nil) margins A table for each side or a number
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @beautiful beautiful.progressbar_margins
+-- @see clip
+
+--- The progressbar padding.
+-- Note that if the `clip` is disabled, this allows the bar to be taller
+-- than the background.
+-- @tparam[opt=0] (table|number|nil) padding A table for each side or a number
+-- @tparam[opt=0] number padding.top
+-- @tparam[opt=0] number padding.bottom
+-- @tparam[opt=0] number padding.left
+-- @tparam[opt=0] number padding.right
+-- @beautiful beautiful.progressbar_paddings
+-- @see clip
+
+local properties = { "border_color", "color" , "background_color",
+ "value" , "max_value" , "ticks",
+ "ticks_gap" , "ticks_size", "border_width",
+ "shape" , "bar_shape" , "bar_border_width",
+ "clip" , "margins" , "bar_border_color",
+ "paddings",
+ }
+
+function progressbar.draw(pbar, _, cr, width, height)
+ local ticks_gap = pbar._private.ticks_gap or 1
+ local ticks_size = pbar._private.ticks_size or 4
+
+ -- We want one pixel wide lines
+ cr:set_line_width(1)
+
+ local max_value = pbar._private.max_value
+
+ local value = math.min(max_value, math.max(0, pbar._private.value))
+
+ if value >= 0 then
+ value = value / max_value
+ end
+ local border_width = pbar._private.border_width
+ or beautiful.progressbar_border_width or 0
+
+ local bcol = pbar._private.border_color or beautiful.progressbar_border_color
+
+ border_width = bcol and border_width or 0
+
+ local bg = pbar._private.background_color or
+ beautiful.progressbar_bg or "#ff0000aa"
+
+ local bg_width, bg_height = width, height
+
+ local clip = pbar._private.clip ~= false and beautiful.progressbar_clip ~= false
+
+ -- Apply the margins
+ local margin = pbar._private.margins or beautiful.progressbar_margins
+
+ if margin then
+ if type(margin) == "number" then
+ cr:translate(margin, margin)
+ bg_width, bg_height = bg_width - 2*margin, bg_height - 2*margin
+ else
+ cr:translate(margin.left or 0, margin.top or 0)
+ bg_height = bg_height -
+ (margin.top or 0) - (margin.bottom or 0)
+ bg_width = bg_width -
+ (margin.left or 0) - (margin.right or 0)
+ end
+ end
+
+ -- Draw the background shape
+ if border_width > 0 then
+ -- Cairo draw half of the border outside of the path area
+ cr:translate(border_width/2, border_width/2)
+ bg_width, bg_height = bg_width - border_width, bg_height - border_width
+ cr:set_line_width(border_width)
+ end
+
+ local background_shape = pbar._private.shape or
+ beautiful.progressbar_shape or shape.rectangle
+
+ background_shape(cr, bg_width, bg_height)
+
+ cr:set_source(color(bg))
+
+ local over_drawn_width = bg_width + border_width
+ local over_drawn_height = bg_height + border_width
+
+ if border_width > 0 then
+ cr:fill_preserve()
+
+ -- Draw the border
+ cr:set_source(color(bcol))
+
+ cr:stroke()
+
+ over_drawn_width = over_drawn_width - 2*border_width
+ over_drawn_height = over_drawn_height - 2*border_width
+ else
+ cr:fill()
+ end
+
+ -- Undo the translation
+ cr:translate(-border_width/2, -border_width/2)
+
+ -- Make sure the bar stay in the shape
+ if clip then
+ background_shape(cr, bg_width, bg_height)
+ cr:clip()
+ cr:translate(border_width, border_width)
+ else
+ -- Assume the background size is irrelevant to the bar itself
+ if type(margin) == "number" then
+ cr:translate(-margin, -margin)
+ else
+ cr:translate(-(margin.left or 0), -(margin.top or 0))
+ end
+
+ over_drawn_height = height
+ over_drawn_width = width
+ end
+
+ -- Apply the padding
+ local padding = pbar._private.paddings or beautiful.progressbar_paddings
+
+ if padding then
+ if type(padding) == "number" then
+ cr:translate(padding, padding)
+ over_drawn_height = over_drawn_height - 2*padding
+ over_drawn_width = over_drawn_width - 2*padding
+ else
+ cr:translate(padding.left or 0, padding.top or 0)
+
+ over_drawn_height = over_drawn_height -
+ (padding.top or 0) - (padding.bottom or 0)
+ over_drawn_width = over_drawn_width -
+ (padding.left or 0) - (padding.right or 0)
+ end
+ end
+
+ over_drawn_width = math.max(over_drawn_width , 0)
+ over_drawn_height = math.max(over_drawn_height, 0)
+
+ local rel_x = over_drawn_width * value
+
+
+ -- Draw the progressbar shape
+
+ local bar_shape = pbar._private.bar_shape or
+ beautiful.progressbar_bar_shape or shape.rectangle
+
+ local bar_border_width = pbar._private.bar_border_width or
+ beautiful.progressbar_bar_border_width or pbar._private.border_width or
+ beautiful.progressbar_border_width or 0
+
+ local bar_border_color = pbar._private.bar_border_color or
+ beautiful.progressbar_bar_border_color
+
+ bar_border_width = bar_border_color and bar_border_width or 0
+
+ over_drawn_width = over_drawn_width - bar_border_width
+ over_drawn_height = over_drawn_height - bar_border_width
+ cr:translate(bar_border_width/2, bar_border_width/2)
+
+ bar_shape(cr, rel_x, over_drawn_height)
+
+ cr:set_source(color(pbar._private.color or beautiful.progressbar_fg or "#ff0000"))
+
+ if bar_border_width > 0 then
+ cr:fill_preserve()
+ cr:set_source(color(bar_border_color))
+ cr:set_line_width(bar_border_width)
+ cr:stroke()
+ else
+ cr:fill()
+ end
+
+ if pbar._private.ticks then
+ for i=0, width / (ticks_size+ticks_gap)-border_width do
+ local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i
+
+ if rel_offset <= rel_x then
+ cr:rectangle(rel_offset,
+ border_width,
+ ticks_gap,
+ over_drawn_height)
+ end
+ end
+ cr:set_source(color(pbar._private.background_color or "#000000aa"))
+ cr:fill()
+ end
+end
+
+function progressbar:fit(_, width, height)
+ return width, height
+end
+
+--- Set the progressbar value.
+-- @param value The progress bar value between 0 and 1.
+function progressbar:set_value(value)
+ value = value or 0
+
+ self._private.value = value
+
+ self:emit_signal("widget::redraw_needed")
+ return self
+end
+
+function progressbar:set_max_value(max_value)
+
+ self._private.max_value = max_value
+
+ self:emit_signal("widget::redraw_needed")
+end
+
+--- Set the progressbar height.
+-- This method is deprecated. Use a `wibox.container.constraint` widget or
+-- `forced_height`.
+-- @param height The height to set.
+-- @deprecated set_height
+function progressbar:set_height(height)
+ util.deprecate("Use a `wibox.container.constraint` widget or `forced_height`")
+ self:set_forced_height(height)
+end
+
+--- Set the progressbar width.
+-- This method is deprecated. Use a `wibox.container.constraint` widget or
+-- `forced_width`.
+-- @param width The width to set.
+-- @deprecated set_width
+function progressbar:set_width(width)
+ util.deprecate("Use a `wibox.container.constraint` widget or `forced_width`")
+ self:set_forced_width(width)
+end
+
+-- Build properties function
+for _, prop in ipairs(properties) do
+ if not progressbar["set_" .. prop] then
+ progressbar["set_" .. prop] = function(pbar, value)
+ pbar._private[prop] = value
+ pbar:emit_signal("widget::redraw_needed")
+ return pbar
+ end
+ end
+end
+
+function progressbar:set_vertical(value) --luacheck: no unused_args
+ util.deprecate("Use a `wibox.container.rotate` widget")
+end
+
+
+--- Create a progressbar widget.
+-- @param args Standard widget() arguments. You should add width and height
+-- key to set progressbar geometry.
+-- @return A progressbar widget.
+-- @function wibox.widget.progressbar
+function progressbar.new(args)
+ args = args or {}
+
+ local pbar = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ pbar._private.width = args.width or 100
+ pbar._private.height = args.height or 20
+ pbar._private.value = 0
+ pbar._private.max_value = 1
+
+ util.table.crush(pbar, progressbar, true)
+
+ return pbar
+end
+
+function progressbar.mt:__call(...)
+ return progressbar.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(progressbar, progressbar.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/slider.lua b/lib/wibox/widget/slider.lua
new file mode 100644
index 0000000..fd590c6
--- /dev/null
+++ b/lib/wibox/widget/slider.lua
@@ -0,0 +1,709 @@
+---------------------------------------------------------------------------
+-- An interactive mouse based slider widget.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_slider.svg)
+--
+-- @usage
+--wibox.widget {
+-- bar_shape = gears.shape.rounded_rect,
+-- bar_height = 3,
+-- bar_color = beautiful.border_color,
+-- handle_color = beautiful.bg_normal,
+-- handle_shape = gears.shape.circle,
+-- handle_border_color = beautiful.border_color,
+-- handle_border_width = 1,
+-- value = 25,
+-- widget = wibox.widget.slider,
+--}
+--
+-- @author Grigory Mishchenko &lt;grishkokot@gmail.com&gt;
+-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
+-- @copyright 2015 Grigory Mishchenko, 2016 Emmanuel Lepage Vallee
+-- @classmod wibox.widget.slider
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local type = type
+local color = require("gears.color")
+local util = require("awful.util")
+local beautiful = require("beautiful")
+local base = require("wibox.widget.base")
+local shape = require("gears.shape")
+local capi = {
+ mouse = mouse,
+ mousegrabber = mousegrabber,
+ root = root,
+}
+
+local slider = {mt={}}
+
+--- The slider handle shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_shape.svg)
+--
+--
+-- @property handle_shape
+-- @tparam[opt=gears shape rectangle] gears.shape shape
+-- @see gears.shape
+
+--- The slider handle color.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_color.svg)
+--
+--
+-- @property handle_color
+-- @param color
+
+--- The slider handle margins.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_margins.svg)
+--
+--
+-- @property handle_margins
+-- @tparam[opt={}] table margins
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+
+--- The slider handle width.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_width.svg)
+--
+--
+-- @property handle_width
+-- @param number
+
+--- The handle border_color.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_handle_border.svg)
+--
+--
+-- @property handle_border_color
+-- @param color
+
+--- The handle border width.
+-- @property handle_border_width
+-- @param[opt=0] number
+
+--- The bar (background) shape.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_shape.svg)
+--
+--
+-- @property bar_shape
+-- @tparam[opt=gears shape rectangle] gears.shape shape
+-- @see gears.shape
+
+--- The bar (background) height.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_height.svg)
+--
+--
+-- @property bar_height
+-- @param number
+
+--- The bar (background) color.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_color.svg)
+--
+--
+-- @property bar_color
+-- @param color
+
+--- The bar (background) margins.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_margins.svg)
+--
+--
+-- @property bar_margins
+-- @tparam[opt={}] table margins
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+
+--- The bar (background) border width.
+-- @property bar_border_width
+-- @param[opt=0] numbergb
+
+--- The bar (background) border_color.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_bar_border.svg)
+--
+--
+-- @property bar_border_color
+-- @param color
+
+--- The slider value.
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_slider_value.svg)
+--
+--
+-- @property value
+-- @param[opt=0] number
+
+--- The slider minimum value.
+-- @property minimum
+-- @param[opt=0] number
+
+--- The slider maximum value.
+-- @property maximum
+-- @param[opt=100] number
+
+--- The bar (background) border width.
+-- @beautiful beautiful.slider_bar_border_width
+-- @param number
+
+--- The bar (background) border color.
+-- @beautiful beautiful.slider_bar_border_color
+-- @param color
+
+--- The handle border_color.
+-- @beautiful beautiful.slider_handle_border_color
+-- @param color
+
+--- The handle border width.
+-- @beautiful beautiful.slider_handle_border_width
+-- @param number
+
+--- The handle .
+-- @beautiful beautiful.slider_handle_width
+-- @param number
+
+-- @beautiful beautiful.slider_handle_color
+-- @param color
+
+--- The handle shape.
+-- @beautiful beautiful.slider_handle_shape
+-- @tparam[opt=gears shape rectangle] gears.shape shape
+-- @see gears.shape
+
+--- The bar (background) shape.
+-- @beautiful beautiful.slider_bar_shape
+-- @tparam[opt=gears shape rectangle] gears.shape shape
+-- @see gears.shape
+
+--- The bar (background) height.
+-- @beautiful beautiful.slider_bar_height
+-- @param number
+
+--- The bar (background) margins.
+-- @beautiful beautiful.slider_bar_margins
+-- @tparam[opt={}] table margins
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+
+--- The slider handle margins.
+-- @beautiful beautiful.slider_handle_margins
+-- @tparam[opt={}] table margins
+-- @tparam[opt=0] number margins.left
+-- @tparam[opt=0] number margins.right
+-- @tparam[opt=0] number margins.top
+-- @tparam[opt=0] number margins.bottom
+
+--- The bar (background) color.
+-- @beautiful beautiful.slider_bar_color
+-- @param color
+
+local properties = {
+ -- Handle
+ handle_shape = shape.rectangle,
+ handle_color = false,
+ handle_margins = {},
+ handle_width = false,
+ handle_border_width = 0,
+ handle_border_color = false,
+
+ -- Bar
+ bar_shape = shape.rectangle,
+ bar_height = false,
+ bar_color = false,
+ bar_margins = {},
+ bar_border_width = 0,
+ bar_border_color = false,
+
+ -- Content
+ value = 0,
+ minimum = 0,
+ maximum = 100,
+}
+
+-- Create the accessors
+for prop in pairs(properties) do
+ slider["set_"..prop] = function(self, value)
+ local changed = self._private[prop] ~= value
+ self._private[prop] = value
+
+ if changed then
+ self:emit_signal("property::"..prop)
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ slider["get_"..prop] = function(self)
+ -- Ignoring the false's is on purpose
+ return self._private[prop] == nil
+ and properties[prop]
+ or self._private[prop]
+ end
+end
+
+-- Add some validation to set_value
+function slider:set_value(value)
+ value = math.min(value, self:get_maximum())
+ value = math.max(value, self:get_minimum())
+ local changed = self._private.value ~= value
+
+ self._private.value = value
+
+ if changed then
+ self:emit_signal( "property::value" )
+ self:emit_signal( "widget::redraw_needed" )
+ end
+end
+
+local function get_extremums(self)
+ local min = self._private.minimum or properties.minimum
+ local max = self._private.maximum or properties.maximum
+ local interval = max - min
+
+ return min, max, interval
+end
+
+function slider:draw(_, cr, width, height)
+ local bar_height = self._private.bar_height
+
+ -- If there is no background, then skip this
+ local bar_color = self._private.bar_color
+ or beautiful.slider_bar_color
+
+ if bar_color then
+ cr:set_source(color(bar_color))
+ end
+
+ local margins = self._private.bar_margins
+ or beautiful.slider_bar_margins
+
+ local x_offset, right_margin, y_offset = 0, 0
+
+ if margins then
+ if type(margins) == "number" then
+ bar_height = bar_height or (height - 2*margins)
+ x_offset, y_offset = margins, margins
+ right_margin = margins
+ else
+ bar_height = bar_height or (
+ height - (margins.top or 0) - (margins.bottom or 0)
+ )
+ x_offset, y_offset = margins.left or 0, margins.top or 0
+ right_margin = margins.right or 0
+ end
+ else
+ bar_height = bar_height or beautiful.slider_bar_height or height
+ y_offset = (height - bar_height)/2
+ end
+
+
+ cr:translate(x_offset, y_offset)
+
+ local bar_shape = self._private.bar_shape
+ or beautiful.slider_bar_shape
+ or properties.bar_shape
+
+ local bar_border_width = self._private.bar_border_width
+ or beautiful.slider_bar_border_width
+ or properties.bar_border_width
+
+ bar_shape(cr, width - x_offset - right_margin, bar_height or height)
+
+ if bar_color then
+ if bar_border_width == 0 then
+ cr:fill()
+ else
+ cr:fill_preserve()
+ end
+ end
+
+ -- Draw the bar border
+ if bar_border_width > 0 then
+ local bar_border_color = self._private.bar_border_color
+ or beautiful.slider_bar_border_color
+ or properties.bar_border_color
+
+ cr:set_line_width(bar_border_width)
+
+ if bar_border_color then
+ cr:save()
+ cr:set_source(color(bar_border_color))
+ cr:stroke()
+ cr:restore()
+ else
+ cr:stroke()
+ end
+ end
+
+ cr:translate(-x_offset, -y_offset)
+
+ -- Paint the handle
+ local handle_color = self._private.handle_color
+ or beautiful.slider_handle_color
+
+ -- It is ok if there is no color, it will be inherited
+ if handle_color then
+ cr:set_source(color(handle_color))
+ end
+
+ local handle_height, handle_width = height, self._private.handle_width
+ or beautiful.slider_handle_width
+ or height/2
+
+ local handle_shape = self._private.handle_shape
+ or beautiful.slider_handle_shape
+ or properties.handle_shape
+
+ -- Lets get the margins for the handle
+ margins = self._private.handle_margins
+ or beautiful.slider_handle_margins
+
+ x_offset, y_offset = 0, 0
+
+ if margins then
+ if type(margins) == "number" then
+ x_offset, y_offset = margins, margins
+ handle_width = handle_width - 2*margins
+ handle_height = handle_height - 2*margins
+ else
+ x_offset, y_offset = margins.left or 0, margins.top or 0
+ handle_width = handle_width -
+ (margins.left or 0) - (margins.right or 0)
+ handle_height = handle_height -
+ (margins.top or 0) - (margins.bottom or 0)
+ end
+ end
+
+ local value = self._private.value or self._private.min or 0
+
+ -- Get the widget size back to it's non-transfored value
+ local min, _, interval = get_extremums(self)
+ local rel_value = ((value-min)/interval) * (width-handle_width)
+
+ cr:translate(x_offset + rel_value, y_offset)
+
+ local handle_border_width = self._private.handle_border_width
+ or beautiful.slider_handle_border_width
+ or properties.handle_border_width or 0
+
+ handle_shape(cr, handle_width, handle_height)
+
+ if handle_border_width > 0 then
+ cr:fill_preserve()
+ else
+ cr:fill()
+ end
+
+ -- Draw the handle border
+ if handle_border_width > 0 then
+ local handle_border_color = self._private.handle_border_color
+ or beautiful.slider_handle_border_color
+ or properties.handle_border_color
+
+ if handle_border_color then
+ cr:set_source(color(handle_border_color))
+ end
+
+ cr:set_line_width(handle_border_width)
+ cr:stroke()
+ end
+end
+
+function slider:fit(_, width, height)
+ -- Use all the space, this should be used with a constraint widget
+ return width, height
+end
+
+-- Move the handle to the correct location
+local function move_handle(self, width, x, _)
+ local _, _, interval = get_extremums(self)
+ self:set_value(math.floor((x*interval)/width))
+end
+
+local function mouse_press(self, x, y, button_id, _, geo)
+ if button_id ~= 1 then return end
+
+ local matrix_from_device = geo.hierarchy:get_matrix_from_device()
+
+ -- Sigh. geo.width/geo.height is in device space. We need it in our own
+ -- coordinate system
+ local width = geo.widget_width
+
+ move_handle(self, width, x, y)
+
+ -- Calculate a matrix transforming from screen coordinates into widget coordinates
+ local wgeo = geo.drawable.drawable:geometry()
+ local matrix = matrix_from_device:translate(-wgeo.x, -wgeo.y)
+
+ capi.mousegrabber.run(function(mouse)
+ if not mouse.buttons[1] then
+ return false
+ end
+
+ -- Calculate the point relative to the widget
+ move_handle(self, width, matrix:transform_point(mouse.x, mouse.y))
+
+ return true
+ end,"fleur")
+end
+
+--- Create a slider widget.
+-- @tparam[opt={}] table args
+-- @function wibox.widget.slider
+local function new(args)
+ local ret = base.make_widget(nil, nil, {
+ enable_properties = true,
+ })
+
+ util.table.crush(ret._private, args or {})
+
+ util.table.crush(ret, slider, true)
+
+ ret:connect_signal("button::press", mouse_press)
+
+ return ret
+end
+
+function slider.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(slider, slider.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/systray.lua b/lib/wibox/widget/systray.lua
new file mode 100644
index 0000000..e83347c
--- /dev/null
+++ b/lib/wibox/widget/systray.lua
@@ -0,0 +1,186 @@
+---------------------------------------------------------------------------
+-- @author Uli Schlachter
+-- @copyright 2010 Uli Schlachter
+-- @classmod wibox.widget.systray
+---------------------------------------------------------------------------
+
+local wbase = require("wibox.widget.base")
+local beautiful = require("beautiful")
+local util = require("awful.util")
+local capi = {
+ awesome = awesome,
+ screen = screen
+}
+local setmetatable = setmetatable
+local error = error
+local abs = math.abs
+
+local systray = { mt = {} }
+
+local instance = nil
+local horizontal = true
+local base_size = nil
+local reverse = false
+local display_on_screen = "primary"
+
+--- The systray background color.
+-- @beautiful beautiful.bg_systray
+-- @param string The color (string like "#ff0000" only)
+
+--- The systray icon spacing.
+-- @beautiful beautiful.systray_icon_spacing
+-- @tparam[opt=0] integer The icon spacing
+
+local function should_display_on(s)
+ if display_on_screen == "primary" then
+ return s == capi.screen.primary
+ end
+ return s == display_on_screen
+end
+
+function systray:draw(context, cr, width, height)
+ if not should_display_on(context.screen) then
+ return
+ end
+
+ local x, y, _, _ = wbase.rect_to_device_geometry(cr, 0, 0, width, height)
+ local num_entries = capi.awesome.systray()
+ local bg = beautiful.bg_systray or beautiful.bg_normal or "#000000"
+ local spacing = beautiful.systray_icon_spacing or 0
+
+ if context and not context.wibox then
+ error("The systray widget can only be placed inside a wibox.")
+ end
+
+ -- Figure out if the cairo context is rotated
+ local dir_x, dir_y = cr:user_to_device_distance(1, 0)
+ local is_rotated = abs(dir_x) < abs(dir_y)
+
+ local in_dir, ortho, base
+ if horizontal then
+ in_dir, ortho = width, height
+ is_rotated = not is_rotated
+ else
+ ortho, in_dir = width, height
+ end
+ if ortho * num_entries <= in_dir then
+ base = ortho
+ else
+ base = in_dir / num_entries
+ end
+ capi.awesome.systray(context.wibox.drawin, math.ceil(x), math.ceil(y),
+ base, is_rotated, bg, reverse, spacing)
+end
+
+function systray:fit(context, width, height)
+ if not should_display_on(context.screen) then
+ return 0, 0
+ end
+
+ local num_entries = capi.awesome.systray()
+ local base = base_size
+ local spacing = beautiful.systray_icon_spacing or 0
+ if num_entries == 0 then
+ return 0, 0
+ end
+ if base == nil then
+ if width < height then
+ base = width
+ else
+ base = height
+ end
+ end
+ base = base + spacing
+ if horizontal then
+ return base * num_entries - spacing, base
+ end
+ return base, base * num_entries - spacing
+end
+
+-- Check if the function was called like :foo() or .foo() and do the right thing
+local function get_args(self, ...)
+ if self == instance then
+ return ...
+ end
+ return self, ...
+end
+
+--- Set the size of a single icon.
+-- If this is set to nil, then the size is picked dynamically based on the
+-- available space. Otherwise, any single icon has a size of `size`x`size`.
+-- @tparam integer|nil size The base size
+function systray:set_base_size(size)
+ base_size = get_args(self, size)
+ if instance then
+ instance:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Decide between horizontal or vertical display.
+-- @tparam boolean horiz Use horizontal mode?
+function systray:set_horizontal(horiz)
+ horizontal = get_args(self, horiz)
+ if instance then
+ instance:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Should the systray icons be displayed in reverse order?
+-- @tparam boolean rev Display in reverse order
+function systray:set_reverse(rev)
+ reverse = get_args(self, rev)
+ if instance then
+ instance:emit_signal("widget::redraw_needed")
+ end
+end
+
+--- Set the screen that the systray should be displayed on.
+-- This can either be a screen, in which case the systray will be displayed on
+-- exactly that screen, or the string `"primary"`, in which case it will be
+-- visible on the primary screen. The default value is "primary".
+-- @tparam screen|"primary" s The screen to display on.
+function systray:set_screen(s)
+ display_on_screen = get_args(self, s)
+ if instance then
+ instance:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Create the systray widget.
+-- Note that this widget can only exist once.
+-- @tparam boolean revers Show in the opposite direction
+-- @treturn table The new `systray` widget
+-- @function wibox.widget.systray
+
+local function new(revers)
+ local ret = wbase.make_widget()
+
+ util.table.crush(ret, systray, true)
+
+ if revers then
+ ret:set_reverse(true)
+ end
+
+ capi.awesome.connect_signal("systray::update", function()
+ ret:emit_signal("widget::layout_changed")
+ ret:emit_signal("widget::redraw_needed")
+ end)
+ capi.screen.connect_signal("primary_changed", function()
+ if display_on_screen == "primary" then
+ ret:emit_signal("widget::layout_changed")
+ end
+ end)
+
+ return ret
+end
+
+function systray.mt:__call(...)
+ if not instance then
+ instance = new(...)
+ end
+ return instance
+end
+
+return setmetatable(systray, systray.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua
new file mode 100644
index 0000000..add35e9
--- /dev/null
+++ b/lib/wibox/widget/textbox.lua
@@ -0,0 +1,507 @@
+---------------------------------------------------------------------------
+--
+--
+--
+--![Usage example](../images/AUTOGEN_wibox_widget_defaults_textbox.svg)
+--
+-- @usage
+--wibox.widget{
+-- markup = 'This <i>is</i> a <b>textbox</b>!!!',
+-- align = 'center',
+-- valign = 'center',
+-- widget = wibox.widget.textbox
+--}
+-- @author Uli Schlachter
+-- @author dodo
+-- @copyright 2010, 2011 Uli Schlachter, dodo
+-- @classmod wibox.widget.textbox
+---------------------------------------------------------------------------
+
+local base = require("wibox.widget.base")
+local gdebug = require("gears.debug")
+local beautiful = require("beautiful")
+local lgi = require("lgi")
+local util = require("awful.util")
+local Pango = lgi.Pango
+local PangoCairo = lgi.PangoCairo
+local setmetatable = setmetatable
+
+local textbox = { mt = {} }
+
+--- The textbox font.
+-- @beautiful beautiful.font
+
+--- Set the DPI of a Pango layout
+local function setup_dpi(box, dpi)
+ if box._private.dpi ~= dpi then
+ box._private.dpi = dpi
+ box._private.ctx:set_resolution(dpi)
+ box._private.layout:context_changed()
+ end
+end
+
+--- Setup a pango layout for the given textbox and dpi
+local function setup_layout(box, width, height, dpi)
+ box._private.layout.width = Pango.units_from_double(width)
+ box._private.layout.height = Pango.units_from_double(height)
+ setup_dpi(box, dpi)
+end
+
+-- Draw the given textbox on the given cairo context in the given geometry
+function textbox:draw(context, cr, width, height)
+ setup_layout(self, width, height, context.dpi)
+ cr:update_layout(self._private.layout)
+ local _, logical = self._private.layout:get_pixel_extents()
+ local offset = 0
+ if self._private.valign == "center" then
+ offset = (height - logical.height) / 2
+ elseif self._private.valign == "bottom" then
+ offset = height - logical.height
+ end
+ cr:move_to(0, offset)
+ cr:show_layout(self._private.layout)
+end
+
+local function do_fit_return(self)
+ local _, logical = self._private.layout:get_pixel_extents()
+ if logical.width == 0 or logical.height == 0 then
+ return 0, 0
+ end
+ return logical.width, logical.height
+end
+
+-- Fit the given textbox
+function textbox:fit(context, width, height)
+ setup_layout(self, width, height, context.dpi)
+ return do_fit_return(self)
+end
+
+--- Get the preferred size of a textbox.
+-- This returns the size that the textbox would use if infinite space were
+-- available.
+-- @tparam integer|screen s The screen on which the textbox will be displayed.
+-- @treturn number The preferred width.
+-- @treturn number The preferred height.
+function textbox:get_preferred_size(s)
+ return self:get_preferred_size_at_dpi(beautiful.xresources.get_dpi(s))
+end
+
+--- Get the preferred height of a textbox at a given width.
+-- This returns the height that the textbox would use when it is limited to the
+-- given width.
+-- @tparam number width The available width.
+-- @tparam integer|screen s The screen on which the textbox will be displayed.
+-- @treturn number The needed height.
+function textbox:get_height_for_width(width, s)
+ return self:get_height_for_width_at_dpi(width, beautiful.xresources.get_dpi(s))
+end
+
+--- Get the preferred size of a textbox.
+-- This returns the size that the textbox would use if infinite space were
+-- available.
+-- @tparam number dpi The DPI value to render at.
+-- @treturn number The preferred width.
+-- @treturn number The preferred height.
+function textbox:get_preferred_size_at_dpi(dpi)
+ local max_lines = 2^20
+ setup_dpi(self, dpi)
+ self._private.layout.width = -1 -- no width set
+ self._private.layout.height = -max_lines -- show this many lines per paragraph
+ return do_fit_return(self)
+end
+
+--- Get the preferred height of a textbox at a given width.
+-- This returns the height that the textbox would use when it is limited to the
+-- given width.
+-- @tparam number width The available width.
+-- @tparam number dpi The DPI value to render at.
+-- @treturn number The needed height.
+function textbox:get_height_for_width_at_dpi(width, dpi)
+ local max_lines = 2^20
+ setup_dpi(self, dpi)
+ self._private.layout.width = Pango.units_from_double(width)
+ self._private.layout.height = -max_lines -- show this many lines per paragraph
+ local _, h = do_fit_return(self)
+ return h
+end
+
+--- Set the text of the textbox (with
+-- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)).
+-- @tparam string text The text to set. This can contain pango markup (e.g.
+-- `<b>bold</b>`). You can use `awful.util.escape` to escape
+-- parts of it.
+-- @treturn[1] boolean true
+-- @treturn[2] boolean false
+-- @treturn[2] string Error message explaining why the markup was invalid.
+function textbox:set_markup_silently(text)
+ if self._private.markup == text then
+ return true
+ end
+
+ local attr, parsed = Pango.parse_markup(text, -1, 0)
+ -- In case of error, attr is false and parsed is a GLib.Error instance.
+ if not attr then
+ return false, parsed.message or tostring(parsed)
+ end
+
+ self._private.markup = text
+ self._private.layout.text = parsed
+ self._private.layout.attributes = attr
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ return true
+end
+
+--- Set the text of the textbox (with
+-- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)).
+-- @property markup
+-- @tparam string text The text to set. This can contain pango markup (e.g.
+-- `<b>bold</b>`). You can use `awful.util.escape` to escape
+-- parts of it.
+-- @see text
+
+function textbox:set_markup(text)
+ local success, message = self:set_markup_silently(text)
+ if not success then
+ gdebug.print_error(message)
+ end
+end
+
+function textbox:get_markup()
+ return self._private.markup
+end
+
+--- Set a textbox' text.
+-- @property text
+-- @param text The text to display. Pango markup is ignored and shown as-is.
+-- @see markup
+
+function textbox:set_text(text)
+ if self._private.layout.text == text and self._private.layout.attributes == nil then
+ return
+ end
+ self._private.markup = nil
+ self._private.layout.text = text
+ self._private.layout.attributes = nil
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+end
+
+function textbox:get_text()
+ return self._private.layout.text
+end
+
+--- Set a textbox' ellipsize mode.
+-- @property ellipsize
+-- @param mode Where should long lines be shortened? "start", "middle" or "end"
+
+function textbox:set_ellipsize(mode)
+ local allowed = { none = "NONE", start = "START", middle = "MIDDLE", ["end"] = "END" }
+ if allowed[mode] then
+ if self._private.layout:get_ellipsize() == allowed[mode] then
+ return
+ end
+ self._private.layout:set_ellipsize(allowed[mode])
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Set a textbox' wrap mode.
+-- @property wrap
+-- @param mode Where to wrap? After "word", "char" or "word_char"
+
+function textbox:set_wrap(mode)
+ local allowed = { word = "WORD", char = "CHAR", word_char = "WORD_CHAR" }
+ if allowed[mode] then
+ if self._private.layout:get_wrap() == allowed[mode] then
+ return
+ end
+ self._private.layout:set_wrap(allowed[mode])
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- The textbox' vertical alignment
+-- @property valign
+-- @param mode Where should the textbox be drawn? "top", "center" or "bottom"
+
+function textbox:set_valign(mode)
+ local allowed = { top = true, center = true, bottom = true }
+ if allowed[mode] then
+ if self._private.valign == mode then
+ return
+ end
+ self._private.valign = mode
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Set a textbox' horizontal alignment.
+-- @property align
+-- @param mode Where should the textbox be drawn? "left", "center" or "right"
+
+function textbox:set_align(mode)
+ local allowed = { left = "LEFT", center = "CENTER", right = "RIGHT" }
+ if allowed[mode] then
+ if self._private.layout:get_alignment() == allowed[mode] then
+ return
+ end
+ self._private.layout:set_alignment(allowed[mode])
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+ end
+end
+
+--- Set a textbox' font
+-- @property font
+-- @param font The font description as string
+
+function textbox:set_font(font)
+ self._private.layout:set_font_description(beautiful.get_font(font))
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("widget::layout_changed")
+end
+
+--- Create a new textbox.
+-- @tparam[opt=""] string text The textbox content
+-- @tparam[opt=false] boolean ignore_markup Ignore the pango/HTML markup
+-- @treturn table A new textbox widget
+-- @function wibox.widget.textbox
+local function new(text, ignore_markup)
+ local ret = base.make_widget(nil, nil, {enable_properties = true})
+
+ util.table.crush(ret, textbox, true)
+
+ ret._private.dpi = -1
+ ret._private.ctx = PangoCairo.font_map_get_default():create_context()
+ ret._private.layout = Pango.Layout.new(ret._private.ctx)
+
+ ret:set_ellipsize("end")
+ ret:set_wrap("word_char")
+ ret:set_valign("center")
+ ret:set_align("left")
+ ret:set_font(beautiful and beautiful.font)
+
+ if text then
+ if ignore_markup then
+ ret:set_text(text)
+ else
+ ret:set_markup(text)
+ end
+ end
+
+ return ret
+end
+
+function textbox.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(textbox, textbox.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/lib/wibox/widget/textclock.lua b/lib/wibox/widget/textclock.lua
new file mode 100644
index 0000000..c688028
--- /dev/null
+++ b/lib/wibox/widget/textclock.lua
@@ -0,0 +1,254 @@
+---------------------------------------------------------------------------
+--- Text clock widget.
+--
+-- @author Julien Danjou &lt;julien@danjou.info&gt;
+-- @copyright 2009 Julien Danjou
+-- @classmod wibox.widget.textclock
+---------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local os = os
+local textbox = require("wibox.widget.textbox")
+local timer = require("gears.timer")
+local DateTime = require("lgi").GLib.DateTime
+
+local textclock = { mt = {} }
+
+--- This lowers the timeout so that it occurs "correctly". For example, a timeout
+-- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds".
+local function calc_timeout(real_timeout)
+ return real_timeout - os.time() % real_timeout
+end
+
+--- Create a textclock widget. It draws the time it is in a textbox.
+--
+-- @tparam[opt=" %a %b %d, %H:%M "] string format The time format.
+-- @tparam[opt=60] number timeout How often update the time (in seconds).
+-- @treturn table A textbox widget.
+-- @function wibox.widget.textclock
+function textclock.new(format, timeout)
+ format = format or " %a %b %d, %H:%M "
+ timeout = timeout or 60
+
+ local w = textbox()
+ local t
+ function w._private.textclock_update_cb()
+ w:set_markup(DateTime.new_now_local():format(format))
+ t.timeout = calc_timeout(timeout)
+ t:again()
+ return true -- Continue the timer
+ end
+ t = timer.weak_start_new(timeout, w._private.textclock_update_cb)
+ t:emit_signal("timeout")
+ return w
+end
+
+function textclock.mt:__call(...)
+ return textclock.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(textclock, textclock.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80