1 ---------------------------------------------------------------------------
2 -- @author Damien Leone <damien.leone@gmail.com>
3 -- @copyright 2008 Damien Leone
4 -- @release @AWESOME_VERSION@
5 ---------------------------------------------------------------------------
7 -- Grab environment we need
16 local capi
= { screen
= screen
, mouse
= mouse
, client
= client
}
17 local util
= require("awful.util")
18 local tags
= require("awful.tag")
19 local awbeautiful
= require("awful.beautiful")
21 --- Menu module for awful
24 -- Table containing all currently opened menus
27 local function load_theme(custom
)
31 beautiful
= awbeautiful
.get()
33 theme
.fg_focus
= custom
.fg_focus
or beautiful
.menu_fg_focus
or beautiful
.fg_focus
34 theme
.bg_focus
= custom
.bg_focus
or beautiful
.menu_bg_focus
or beautiful
.bg_focus
35 theme
.fg_normal
= custom
.fg_normal
or beautiful
.menu_fg_normal
or beautiful
.fg_normal
36 theme
.bg_normal
= custom
.bg_normal
or beautiful
.menu_bg_normal
or beautiful
.bg_normal
38 theme
.submenu_icon
= custom
.submenu_icon
or beautiful
.menu_submenu_icon
or "@AWESOME_ICON_PATH@/submenu.png"
40 theme
.menu_height
= custom
.height
or beautiful
.menu_height
or 15
41 theme
.menu_width
= custom
.width
or beautiful
.menu_width
or 100
43 theme
.border
= custom
.border_color
or beautiful
.menu_border_color
or beautiful
.border_normal
44 theme
.border_width
= custom
.border_width
or beautiful
.menu_border_width
or beautiful
.border_width
49 local function mouse_enter(w
, theme
)
54 local function mouse_leave(w
, theme
)
55 w
.fg
= theme
.fg_normal
56 w
.bg
= theme
.bg_normal
59 local function destroy(data
)
61 -- Remove items from screen
62 for i
= 1, #data
.items
do
63 data
.items
[i
].screen
= nil
66 -- Clean memory, dirty but I'm lazy
67 for i
= 1, #data
.items
do
68 table.remove(data
.items
)
73 -- Remove menu from menus table
78 local function get_parents(data
)
81 -- Get the elder parent so when you kill
82 -- it he will destroy the whole family
83 while p_data
.parent
do
84 p_data
= p_data
.parent
90 local function exec(data
, action
, num
)
91 if type(action
[2]) == "table" then
93 data
.child
= new({ id
=action
[1], items
=action
[2] }, data
, num
)
94 elseif type(action
[2]) == "string" then
95 destroy(get_parents(data
))
97 elseif type(action
[2]) == "function" then
98 destroy(get_parents(data
))
103 local function add_item(data
, num
, item_info
)
105 name
= data
.id
.. "item" .. num
,
106 position
= "floating",
107 fg
= data
.theme
.fg_normal
,
108 bg
= data
.theme
.bg_normal
,
109 border_color
= data
.theme
.border
,
110 border_width
= data
.theme
.border_width
115 button({}, 1, function () exec(data
, item_info
, num
) end),
116 button({}, 3, function () destroy(data
) end)
119 -- Create the item icon widget
122 icon
= widget({ type = "imagebox", name
= "icon", align
= "left" })
123 if type(item_info
[3]) == "string" then
124 icon
.image
= image(item_info
[3])
126 icon
.image
= item_info
[3]
129 icon
= widget({ type = "textbox", name
= "icon", align
= "left" })
133 icon
:buttons(bindings
)
135 function icon
.mouse_enter() mouse_enter(item
, data
.theme
) end
136 function icon
.mouse_leave() mouse_leave(item
, data
.theme
) end
138 -- Create the item label widget
139 local label
= widget({
141 name
= data
.id
.. "label" .. num
,
144 label
.text
= string.format(" %s", item_info
[1])
145 label
:buttons(bindings
)
147 function label
.mouse_enter() mouse_enter(item
, data
.theme
) end
148 function label
.mouse_leave() mouse_leave(item
, data
.theme
) end
150 -- Create the submenu icon widget
152 if type(item_info
[2]) == "table" then
153 submenu
= widget({ type = "imagebox", name
= "submenu", align
= "right" })
154 submenu
.image
= image(data
.theme
.submenu_icon
)
155 submenu
:buttons(bindings
)
157 function submenu
.mouse_enter() mouse_enter(item
, data
.theme
) end
158 function submenu
.mouse_leave() mouse_leave(item
, data
.theme
) end
161 -- Add widgets to the wibox
162 item
.widgets
= { icon
, label
, submenu
}
168 y
= data
.y
+ (num
- 1)*(data
.h
+ data
.theme
.border_width
)
172 item
.screen
= data
.screen
177 --- Open a popup menu with running clients.
178 -- @param menu Menu table, see new() function for more informations
179 function clients(menu
)
180 local cls
= capi
.client
.get()
182 for k
, c
in pairs(cls
) do
183 cls_t
[#cls_t
+ 1] = { c
.name
,
185 if not c
:isvisible() then
186 tags
.viewmore(c
:tags(), c
.screen
)
188 capi
.client
.focus
= c
203 local function set_coords(data
)
204 local m_coords
= capi
.mouse
.coords()
205 local s_geometry
= capi
.screen
[data
.screen
].workarea
207 local screen_w
= s_geometry
.x
+ s_geometry
.width
208 local screen_h
= s_geometry
.y
+ s_geometry
.height
211 data
.w
= data
.parent
.w
212 data
.h
= data
.parent
.h
214 local p_w
= data
.h
*(data
.num
- 1)
215 local m_h
= data
.theme
.border_width
+ (data
.h
+ data
.theme
.border_width
)*data
.nb_items
216 local m_w
= data
.w
+ data
.theme
.border_width
217 data
.y
= data
.parent
.y
+ p_w
+ m_h
> screen_h
and screen_h
- m_h
or data
.parent
.y
+ p_w
218 data
.x
= data
.parent
.x
+ data
.w
*2 + data
.theme
.border_width
> screen_w
and data
.parent
.x
- m_w
or data
.parent
.x
+ m_w
220 data
.y
= m_coords
.y
< s_geometry
.y
and s_geometry
.y
or m_coords
.y
221 data
.x
= m_coords
.x
< s_geometry
.x
and s_geometry
.x
or m_coords
.x
223 local m_h
= data
.theme
.border_width
+ (data
.h
+ data
.theme
.border_width
)*data
.nb_items
224 local m_w
= data
.w
+ data
.theme
.border_width
*2
225 data
.y
= data
.y
+ m_h
> screen_h
and screen_h
- m_h
or data
.y
226 data
.x
= data
.x
+ m_w
> screen_w
and screen_w
- m_w
or data
.x
230 --- Open a menu popup.
231 -- @param menu Table containing the menu informations. Element id: string naming your menu, only one menu with the same id can be displayed on screen at the same time. Element items: Table containing the displayed items, each element is a tab containing: item name, tiggered action, submenu table or function, item icon (optional). Elements [fg|bg]_[focus|normal], border, border_width, submenu_icon, height and width override the default display for your menu, each of them are optional
232 -- @param parent Specify the parent menu if we want to open a submenu, this value should never be set by the user.
233 -- @param num Specify the parent's clicked item number if we want to open a submenu, this value should never be set by the user.
234 function new(menu
, parent
, num
)
235 -- Close the menu if it was already opened
236 if menus
[menu
.id
] then
237 destroy(menus
[menu
.id
])
240 -- Create a table to store our menu informations
243 data
.screen
= capi
.mouse
.screen
246 data
.nb_items
= #menu
.items
247 data
.num
= num
and num
or 1
248 data
.theme
= parent
and parent
.theme
or load_theme(menu
)
249 data
.parent
= parent
and parent
or nil
250 data
.h
= parent
and parent
.h
or data
.theme
.menu_height
251 data
.w
= parent
and parent
.w
or data
.theme
.menu_width
256 for k
, v
in pairs(menu
.items
) do
257 table.insert(data
.items
, add_item(data
, k
, v
))
260 -- Add menu to menus table
261 menus
[menu
.id
] = data