1 ---------------------------------------------------------------------------
2 -- @author Julien Danjou <julien@danjou.info>
3 -- @copyright 2009 Julien Danjou
4 -- @release @AWESOME_VERSION@
5 ---------------------------------------------------------------------------
7 -- Grab environment we need
14 local setmetatable
= setmetatable
15 local tostring = tostring
19 local wibox
= require("wibox")
20 local beautiful
= require("beautiful")
22 --- Wibox module for awful.
23 -- This module allows you to easily create wibox and attach them to the edge of
26 local awfulwibox
= { mt
= {} }
28 -- Array of table with wiboxes inside.
29 -- It's an array so it is ordered.
32 --- Get a wibox position if it has been set, or return top.
33 -- @param wibox The wibox
34 -- @return The wibox position.
35 function awfulwibox
.get_position(wibox
)
36 for _
, wprop
in ipairs(wiboxes
) do
37 if wprop
.wibox
== wibox
then
44 --- Put a wibox on a screen at this position.
45 -- @param wibox The wibox to attach.
46 -- @param position The position: top, bottom left or right.
47 -- @param screen If the wibox it not attached to a screen, specified on which
48 -- screen the position should be set.
49 function awfulwibox
.set_position(wibox
, position
, screen
)
50 local area
= capi
.screen
[screen
].geometry
52 -- The "length" of a wibox is always chosen to be the optimal size
54 -- The "width" of a wibox is kept if it exists.
55 if position
== "right" then
56 wibox
.x
= area
.x
+ area
.width
- (wibox
.width
+ 2 * wibox
.border_width
)
57 elseif position
== "left" then
59 elseif position
== "bottom" then
60 wibox
.y
= (area
.y
+ area
.height
) - (wibox
.height
+ 2 * wibox
.border_width
)
61 elseif position
== "top" then
65 for _
, wprop
in ipairs(wiboxes
) do
66 if wprop
.wibox
== wibox
then
67 wprop
.position
= position
73 -- Reset all wiboxes positions.
74 local function update_all_wiboxes_position()
75 for _
, wprop
in ipairs(wiboxes
) do
76 awfulwibox
.set_position(wprop
.wibox
, wprop
.position
, wprop
.screen
)
80 local function call_wibox_position_hook_on_prop_update(w
)
81 update_all_wiboxes_position()
84 local function wibox_update_strut(wibox
)
85 for _
, wprop
in ipairs(wiboxes
) do
86 if wprop
.wibox
== wibox
then
87 if not wibox
.visible
then
88 wibox
:struts
{ left
= 0, right
= 0, bottom
= 0, top
= 0 }
89 elseif wprop
.position
== "top" then
90 wibox
:struts
{ left
= 0, right
= 0, bottom
= 0, top
= wibox
.height
+ 2 * wibox
.border_width
}
91 elseif wprop
.position
== "bottom" then
92 wibox
:struts
{ left
= 0, right
= 0, bottom
= wibox
.height
+ 2 * wibox
.border_width
, top
= 0 }
93 elseif wprop
.position
== "left" then
94 wibox
:struts
{ left
= wibox
.width
+ 2 * wibox
.border_width
, right
= 0, bottom
= 0, top
= 0 }
95 elseif wprop
.position
== "right" then
96 wibox
:struts
{ left
= 0, right
= wibox
.width
+ 2 * wibox
.border_width
, bottom
= 0, top
= 0 }
103 --- Attach a wibox to a screen.
104 -- If a wibox is attached, it will be automatically be moved when other wiboxes
106 -- @param wibox The wibox to attach.
107 -- @param position The position of the wibox: top, bottom, left or right.
108 -- @param screen TODO, this seems to be unused
109 function awfulwibox
.attach(wibox
, position
, screen
)
110 -- Store wibox as attached in a weak-valued table
111 local wibox_prop_table
112 -- Start from end since we sometimes remove items
113 for i
= #wiboxes
, 1, -1 do
114 -- Since wiboxes are stored as weak value, they can disappear.
115 -- If they did, remove their entries
116 if wiboxes
[i
].wibox
== nil then
117 table.remove(wiboxes
, i
)
118 elseif wiboxes
[i
].wibox
== wibox
then
119 wibox_prop_table
= wiboxes
[i
]
120 -- We could break here, but well, let's check if there is no other
121 -- table with their wiboxes been garbage collected.
125 if not wibox_prop_table
then
126 table.insert(wiboxes
, setmetatable({ wibox
= wibox
, position
= position
, screen
= screen
}, { __mode
= 'v' }))
128 wibox_prop_table
.position
= position
131 wibox
:connect_signal("property::width", wibox_update_strut
)
132 wibox
:connect_signal("property::height", wibox_update_strut
)
133 wibox
:connect_signal("property::visible", wibox_update_strut
)
135 wibox
:connect_signal("property::width", call_wibox_position_hook_on_prop_update
)
136 wibox
:connect_signal("property::height", call_wibox_position_hook_on_prop_update
)
137 wibox
:connect_signal("property::visible", call_wibox_position_hook_on_prop_update
)
138 wibox
:connect_signal("property::border_width", call_wibox_position_hook_on_prop_update
)
142 -- @param wibox The wibox.
143 -- @param align The alignment: left, right or center.
144 -- @param screen If the wibox is not attached to any screen, you can specify the
145 -- screen where to align. Otherwise 1 is assumed.
146 function awfulwibox
.align(wibox
, align
, screen
)
147 local position
= awfulwibox
.get_position(wibox
)
148 local area
= capi
.screen
[screen
].workarea
150 if position
== "right" then
151 if align
== "right" then
153 elseif align
== "left" then
154 wibox
.y
= area
.y
+ area
.height
- (wibox
.height
+ 2 * wibox
.border_width
)
155 elseif align
== "center" then
156 wibox
.y
= area
.y
+ (area
.height
- wibox
.height
) / 2
158 elseif position
== "left" then
159 if align
== "right" then
160 wibox
.y
= (area
.y
+ area
.height
) - (wibox
.height
+ 2 * wibox
.border_width
)
161 elseif align
== "left" then
163 elseif align
== "center" then
164 wibox
.y
= area
.y
+ (area
.height
- wibox
.height
) / 2
166 elseif position
== "bottom" then
167 if align
== "right" then
168 wibox
.x
= area
.x
+ area
.width
- (wibox
.width
+ 2 * wibox
.border_width
)
169 elseif align
== "left" then
171 elseif align
== "center" then
172 wibox
.x
= area
.x
+ (area
.width
- wibox
.width
) / 2
174 elseif position
== "top" then
175 if align
== "right" then
176 wibox
.x
= area
.x
+ area
.width
- (wibox
.width
+ 2 * wibox
.border_width
)
177 elseif align
== "left" then
179 elseif align
== "center" then
180 wibox
.x
= area
.x
+ (area
.width
- wibox
.width
) / 2
184 -- Update struts regardless of changes
185 wibox_update_strut(wibox
)
188 --- Stretch a wibox so it takes all screen width or height.
189 -- @param wibox The wibox.
190 -- @param screen The screen to stretch on, or the wibox screen.
191 function awfulwibox
.stretch(wibox
, screen
)
193 local position
= awfulwibox
.get_position(wibox
)
194 local area
= capi
.screen
[screen
].workarea
195 if position
== "right" or position
== "left" then
196 wibox
.height
= area
.height
- (2 * wibox
.border_width
)
199 wibox
.width
= area
.width
- (2 * wibox
.border_width
)
205 --- Create a new wibox and attach it to a screen edge.
207 -- @param arg A table with standard arguments to wibox() creator.
208 -- You can add also position key with value top, bottom, left or right.
209 -- You can also use width or height in % and set align to center, right or left.
210 -- You can also set the screen key with a screen number to attach the wibox.
211 -- If not specified, 1 is assumed.
212 -- @return The wibox created.
213 function awfulwibox
.new(arg
)
214 local arg
= arg
or {}
215 local position
= arg
.position
or "top"
216 local has_to_stretch
= true
217 local screen
= arg
.screen
or 1
219 arg
.type = arg
.type or "dock"
221 if position
~= "top" and position
~="bottom"
222 and position
~= "left" and position
~= "right" then
223 error("Invalid position in awful.wibox(), you may only use"
224 .. " 'top', 'bottom', 'left' and 'right'")
228 if position
== "left" or position
== "right" then
229 arg
.width
= arg
.width
or beautiful
.get_font_height(arg
.font
) * 1.5
231 has_to_stretch
= false
233 local hp
= tostring(arg
.height
):match("(%d+)%%")
235 arg
.height
= capi
.screen
[arg
.screen
].geometry
.height
* hp
/ 100
240 arg
.height
= arg
.height
or beautiful
.get_font_height(arg
.font
) * 1.5
242 has_to_stretch
= false
244 local wp
= tostring(arg
.width
):match("(%d+)%%")
246 arg
.width
= capi
.screen
[arg
.screen
].geometry
.width
* wp
/ 100
256 awfulwibox
.attach(w
, position
, screen
)
257 if has_to_stretch
then
258 awfulwibox
.stretch(w
, screen
)
260 awfulwibox
.align(w
, arg
.align
, screen
)
263 awfulwibox
.set_position(w
, position
, screen
)
268 local function update_wiboxes_on_struts(c
)
269 local struts
= c
:struts()
270 if struts
.left
~= 0 or struts
.right
~= 0
271 or struts
.top
~= 0 or struts
.bottom
~= 0 then
272 update_all_wiboxes_position()
276 -- Hook registered to reset all wiboxes position.
277 capi
.client
.connect_signal("property::struts", update_wiboxes_on_struts
)
278 capi
.client
.connect_signal("unmanage", update_wiboxes_on_struts
)
280 function awfulwibox
.mt
:__call(...)
281 return awfulwibox
.new(...)
284 return setmetatable(awfulwibox
, awfulwibox
.mt
)
286 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80