1 ---------------------------------------------------------------------------
2 -- @author Damien Leone <damien.leone@gmail.com>
3 -- @author Julien Danjou <julien@danjou.info>
4 -- @copyright 2008 Damien Leone, Julien Danjou
5 -- @release @AWESOME_VERSION@
6 ---------------------------------------------------------------------------
8 -- 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 local function load_theme(custom
)
28 beautiful
= awbeautiful
.get()
30 theme
.fg_focus
= custom
.fg_focus
or beautiful
.menu_fg_focus
or beautiful
.fg_focus
31 theme
.bg_focus
= custom
.bg_focus
or beautiful
.menu_bg_focus
or beautiful
.bg_focus
32 theme
.fg_normal
= custom
.fg_normal
or beautiful
.menu_fg_normal
or beautiful
.fg_normal
33 theme
.bg_normal
= custom
.bg_normal
or beautiful
.menu_bg_normal
or beautiful
.bg_normal
35 theme
.submenu_icon
= custom
.submenu_icon
or beautiful
.menu_submenu_icon
or "@AWESOME_ICON_PATH@/submenu.png"
37 theme
.menu_height
= custom
.height
or beautiful
.menu_height
or 15
38 theme
.menu_width
= custom
.width
or beautiful
.menu_width
or 100
40 theme
.border
= custom
.border_color
or beautiful
.menu_border_color
or beautiful
.border_normal
41 theme
.border_width
= custom
.border_width
or beautiful
.menu_border_width
or beautiful
.border_width
46 local function mouse_enter(w
, theme
)
51 local function mouse_leave(w
, theme
)
52 w
.fg
= theme
.fg_normal
53 w
.bg
= theme
.bg_normal
56 --- Hide a menu popup.
57 -- @param menu The menu to hide.
60 -- Remove items from screen
61 for i
= 1, #menu
.items
do
62 -- Call mouse_leave to clear menu entry
63 for k
, w
in pairs(menu
.items
[i
].widgets
) do
66 menu
.items
[i
].screen
= nil
72 --- Get the elder parent so for example when you kill
73 -- it, it will destroy the whole family.
74 local function get_parents(data
)
76 return get_parents(data
.parent
)
81 local function exec(data
, action
, num
)
82 if type(action
[2]) == "table" then
83 if not data
.child
then
84 data
.child
= new({ items
=action
[2] }, data
, num
)
87 elseif type(action
[2]) == "string" then
88 hide(get_parents(data
))
90 elseif type(action
[2]) == "function" then
91 hide(get_parents(data
))
96 local function add_item(data
, num
, item_info
)
98 position
= "floating",
99 fg
= data
.theme
.fg_normal
,
100 bg
= data
.theme
.bg_normal
,
101 border_color
= data
.theme
.border
,
102 border_width
= data
.theme
.border_width
107 button({}, 1, function () exec(data
, item_info
, num
) end),
108 button({}, 3, function () hide(data
) end)
111 -- Create the item icon widget
112 local icon
= widget({ type = "imagebox", align
= "left" })
114 if type(item_info
[3]) == "string" then
115 icon
.image
= image(item_info
[3])
117 icon
.image
= item_info
[3]
121 icon
:buttons(bindings
)
123 function icon
.mouse_enter() mouse_enter(item
, data
.theme
) end
124 function icon
.mouse_leave() mouse_leave(item
, data
.theme
) end
126 -- Create the item label widget
127 local label
= widget({
131 label
.text
= " " .. item_info
[1]
132 label
:buttons(bindings
)
134 function label
.mouse_enter() mouse_enter(item
, data
.theme
) end
135 function label
.mouse_leave() mouse_leave(item
, data
.theme
) end
137 -- Create the submenu icon widget
139 if type(item_info
[2]) == "table" then
140 submenu
= widget({ type = "imagebox", align
= "right" })
141 submenu
.image
= image(data
.theme
.submenu_icon
)
142 submenu
:buttons(bindings
)
144 function submenu
.mouse_enter() mouse_enter(item
, data
.theme
) end
145 function submenu
.mouse_leave() mouse_leave(item
, data
.theme
) end
148 -- Add widgets to the wibox
149 item
.widgets
= { icon
, label
, submenu
}
156 --- Build a popup menu with running clients and shows it.
157 -- @param menu Menu table, see new() function for more informations
159 function clients(menu
)
160 local cls
= capi
.client
.get()
162 for k
, c
in pairs(cls
) do
163 cls_t
[#cls_t
+ 1] = { util
.escape(c
.name
) or "",
165 if not c
:isvisible() then
166 tags
.viewmore(c
:tags(), c
.screen
)
168 capi
.client
.focus
= c
184 local function set_coords(menu
, screen_idx
)
185 local s_geometry
= capi
.screen
[screen_idx
].workarea
186 local screen_w
= s_geometry
.x
+ s_geometry
.width
187 local screen_h
= s_geometry
.y
+ s_geometry
.height
190 menu
.w
= menu
.parent
.w
191 menu
.h
= menu
.parent
.h
193 local p_w
= (menu
.h
+ menu
.theme
.border_width
) * (menu
.num
- 1)
194 local m_h
= menu
.theme
.border_width
+ (menu
.h
+ menu
.theme
.border_width
) * #menu
.items
195 local m_w
= menu
.w
+ menu
.theme
.border_width
196 menu
.y
= menu
.parent
.y
+ p_w
+ m_h
> screen_h
and screen_h
- m_h
or menu
.parent
.y
+ p_w
197 menu
.x
= menu
.parent
.x
+ menu
.w
*2 + menu
.theme
.border_width
> screen_w
and menu
.parent
.x
- m_w
or menu
.parent
.x
+ m_w
199 local m_coords
= capi
.mouse
.coords()
201 menu
.y
= m_coords
.y
< s_geometry
.y
and s_geometry
.y
or m_coords
.y
202 menu
.x
= m_coords
.x
< s_geometry
.x
and s_geometry
.x
or m_coords
.x
204 local m_h
= menu
.theme
.border_width
+ (menu
.h
+ menu
.theme
.border_width
) * #menu
.items
205 local m_w
= menu
.w
+ menu
.theme
.border_width
*2
206 menu
.y
= menu
.y
+ m_h
> screen_h
and screen_h
- m_h
or menu
.y
207 menu
.x
= menu
.x
+ m_w
> screen_w
and screen_w
- m_w
or menu
.x
212 -- @param menu The menu to show.
214 local screen_index
= capi
.mouse
.screen
215 set_coords(menu
, screen_index
)
216 for num
, item
in pairs(menu
.items
) do
221 y
= menu
.y
+ (num
- 1) * (menu
.h
+ menu
.theme
.border_width
)
223 item
.screen
= screen_index
227 --- Toggle menu visibility.
228 -- @param menu The menu to show if it's hidden, or to hide if it's shown.
229 function toggle(menu
)
230 if menu
.items
[1].screen
then
237 --- Open a menu popup.
238 -- @param menu Table containing the menu informations. Key items: Table containing the displayed items, each element is a tab containing: item name, tiggered action, submenu table or function, item icon (optional). Keys [fg|bg]_[focus|normal], border, border_width, submenu_icon, height and width override the default display for your menu, each of them are optional.
239 -- @param parent Specify the parent menu if we want to open a submenu, this value should never be set by the user.
240 -- @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.
241 function new(menu
, parent
, num
)
242 -- Create a table to store our menu informations
247 data
.theme
= parent
and parent
.theme
or load_theme(menu
)
249 data
.h
= parent
and parent
.h
or data
.theme
.menu_height
250 data
.w
= parent
and parent
.w
or data
.theme
.menu_width
253 for k
, v
in pairs(menu
.items
) do
254 table.insert(data
.items
, add_item(data
, k
, v
))