diff --git a/lib/awful/menu.lua.in b/lib/awful/menu.lua.in
index de9891d4..b27d42d5 100644
--- a/lib/awful/menu.lua.in
+++ b/lib/awful/menu.lua.in
@@ -1,34 +1,53 @@
----------------------------------------------------------------------------
+--------------------------------------------------------------------------------
-- @author Damien Leone <damien.leone@gmail.com>
-- @author Julien Danjou <julien@danjou.info>
--- @copyright 2008 Damien Leone, Julien Danjou
+-- @author dodo
+-- @copyright 2008, 2011 Damien Leone, Julien Danjou, dodo
-- @release @AWESOME_VERSION@
----------------------------------------------------------------------------
+--------------------------------------------------------------------------------
--- Grab environment we need
-local pairs = pairs
-local table = table
-local string = string
-local type = type
-local setmetatable = setmetatable
-local tonumber = tonumber
-local capi =
-{
- screen = screen,
- mouse = mouse,
- client = client,
- keygrabber = keygrabber,
- oocairo = oocairo
-}
local wibox = require("wibox")
local button = require("awful.button")
local util = require("awful.util")
local tags = require("awful.tag")
-local awbeautiful = require("beautiful")
+local beautiful = require("beautiful")
+local object = require("gears.object")
+local setmetatable = setmetatable
+local tonumber = tonumber
+local string = string
+local ipairs = ipairs
+local pairs = pairs
+local pcall = pcall
+local print = print
+local table = table
+local type = type
+local math = math
+local capi = {
+ timer = timer,
+ screen = screen,
+ mouse = mouse,
+ client = client,
+ keygrabber = keygrabber,
+ oocairo = oocairo }
+
---- Creation of menus.
module("awful.menu")
+
+local table_update = function (t, set)
+ for k, v in pairs(set) do
+ t[k] = v
+ end
+ return t
+end
+
+local table_merge = function (t, set)
+ for _, v in ipairs(set) do
+ table.insert(t, v)
+ end
+end
+
+
local cur_menu
--- Key bindings for menu navigation.
@@ -43,33 +62,256 @@ menu_keys = { up = { "Up" },
back = { "Left" },
close = { "Escape" } }
-local function load_theme(custom)
- local theme = {}
- local beautiful
- beautiful = awbeautiful.get()
-
- theme.fg_focus = custom.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus
- theme.bg_focus = custom.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus
- theme.fg_normal = custom.fg_normal or beautiful.menu_fg_normal or beautiful.fg_normal
- theme.bg_normal = custom.bg_normal or beautiful.menu_bg_normal or beautiful.bg_normal
-
- theme.submenu_icon = custom.submenu_icon or beautiful.menu_submenu_icon
-
- theme.menu_height = custom.height or beautiful.menu_height or 16
- theme.menu_width = custom.width or beautiful.menu_width or 100
-
- theme.border = custom.border_color or beautiful.menu_border_color or beautiful.border_normal
- theme.border_width = custom.border_width or beautiful.menu_border_width or beautiful.border_width
-
- return theme
+local function load_theme(a, b)
+ a = a or {}
+ b = b or {}
+ local ret = {}
+ local fallback = beautiful.get()
+ if a.reset then b = fallback end
+ if a == "reset" then a = fallback end
+ ret.border = a.border_color or b.menu_border_color or b.border_normal or
+ fallback.menu_border_color or fallback.border_normal
+ ret.border_width= a.border_width or b.menu_border_width or b.border_width or
+ fallback.menu_border_width or fallback.border_width
+ ret.fg_focus = a.fg_focus or b.menu_fg_focus or b.fg_focus or
+ fallback.menu_fg_focus or fallback.fg_focus
+ ret.bg_focus = a.bg_focus or b.menu_bg_focus or b.bg_focus or
+ fallback.menu_bg_focus or fallback.bg_focus
+ ret.fg_normal = a.fg_normal or b.menu_fg_normal or b.fg_normal or
+ fallback.menu_fg_normal or fallback.fg_normal
+ ret.bg_normal = a.bg_normal or b.menu_bg_normal or b.bg_normal or
+ fallback.menu_bg_normal or fallback.bg_normal
+ ret.submenu_icon= a.submenu_icon or b.menu_submenu_icon or b.submenu_icon or
+ fallback.menu_submenu_icon or fallback.submenu_icon
+ ret.height = a.height or b.menu_height or b.height or
+ fallback.menu_height or 16
+ ret.width = a.width or b.menu_width or b.width or
+ fallback.menu_width or 100
+ return ret
end
-local function item_leave(menu, num)
- if num > 0 then
- menu.items[num].wibox:set_fg(menu.theme.fg_normal)
- menu.items[num].wibox:set_bg(menu.theme.bg_normal)
+
+local function item_position(menu, child)
+ local in_dir, other, a, b = 0, 0, "height", "width"
+ local dir = menu.layout.get_dir and menu.layout:get_dir() or "y"
+ if dir == "x" then a, b = b, a end
+
+ local in_dir, other = 0, menu[b]
+ local num = util.table.hasitem(menu.child, child)
+ if num then
+ for i = 0, num - 1 do
+ local item = menu.items[i]
+ if item then
+ other = math.max(other, item[b])
+ in_dir = in_dir + item[a]
+ end
+ end
end
+ local w, h = other, in_dir
+ if dir == "x" then w, h = h, w end
+ return w, h
+end
+
+
+local function set_coords(menu, screen_idx, m_coords)
+ local s_geometry = capi.screen[screen_idx].workarea
+ local screen_w = s_geometry.x + s_geometry.width
+ local screen_h = s_geometry.y + s_geometry.height
+
+ menu.width = menu.wibox.width
+ menu.height = menu.wibox.height
+
+ menu.x = menu.wibox.x
+ menu.y = menu.wibox.y
+
+ if menu.parent then
+ local w, h = item_position(menu.parent, menu)
+ w = w + menu.parent.theme.border_width
+ h = h + menu.parent.theme.border_width
+
+ menu.y = menu.parent.y + h + menu.height > screen_h and
+ screen_h - menu.height or menu.parent.y + h
+ menu.x = menu.parent.x + w + menu.width > screen_w and
+ menu.parent.x - menu.width or menu.parent.x + w
+ else
+ if m_coords == nil then
+ m_coords = capi.mouse.coords()
+ m_coords.x = m_coords.x + 1
+ m_coords.y = m_coords.y + 1
+ end
+ menu.y = m_coords.y < s_geometry.y and s_geometry.y or m_coords.y
+ menu.x = m_coords.x < s_geometry.x and s_geometry.x or m_coords.x
+
+ menu.y = menu.y + menu.height > screen_h and
+ screen_h - menu.height or menu.y
+ menu.x = menu.x + menu.width > screen_w and
+ screen_w - menu.width or menu.x
+ end
+
+ menu.wibox.x = menu.x
+ menu.wibox.y = menu.y
+end
+
+
+local function set_size(menu)
+ local in_dir, other, a, b = 0, 0, "height", "width"
+ local dir = menu.layout.get_dir and menu.layout:get_dir() or "y"
+ if dir == "x" then a, b = b, a end
+ for _, item in ipairs(menu.items) do
+ other = math.max(other, item[b])
+ in_dir = in_dir + item[a]
+ end
+ menu[a], menu[b] = in_dir, other
+ if in_dir > 0 and other > 0 then
+ menu.wibox[a] = in_dir
+ menu.wibox[b] = other
+ return true
+ end
+ return false
+end
+
+
+local function check_access_key(menu, key)
+ for i, item in ipairs(menu.items) do
+ if item.akey == key then
+ menu:item_enter(i)
+ menu:exec(i)
+ return
+ end
+ end
+ if menu.parent then
+ check_access_key(menu.parent, key)
+ end
+end
+
+
+local function grabber(mod, key, event)
+ if event == "release" then
+ return true
+ end
+
+ local sel = cur_menu.sel or 0
+ if util.table.hasitem(menu_keys.up, key) then
+ local sel_new = sel-1 < 1 and #cur_menu.items or sel-1
+ cur_menu:item_enter(sel_new)
+ elseif util.table.hasitem(menu_keys.down, key) then
+ local sel_new = sel+1 > #cur_menu.items and 1 or sel+1
+ cur_menu:item_enter(sel_new)
+ elseif sel > 0 and util.table.hasitem(menu_keys.exec, key) then
+ cur_menu:exec(sel)
+ elseif util.table.hasitem(menu_keys.back, key) then
+ cur_menu:hide()
+ elseif util.table.hasitem(menu_keys.close, key) then
+ get_root(cur_menu):hide()
+ else
+ check_access_key(cur_menu, key)
+ end
+
+ return true
+end
+
+
+function exec(menu, num, mouse_event)
+ local item = menu.items[num]
+ if not item then return end
+ local cmd = item.cmd
+ if type(cmd) == "table" then
+ if #cmd == 0 then
+ return
+ end
+ if not menu.child[num] then
+ menu.child[num] = new(cmd, menu)
+ end
+
+ if menu.active_child then
+ menu.active_child:hide()
+ menu.active_child = nil
+ end
+ menu.active_child = menu.child[num]
+ menu.active_child:show()
+ elseif type(cmd) == "string" then
+ get_root(menu):hide()
+ util.spawn(cmd)
+ elseif type(cmd) == "function" then
+ local visible, action = cmd(item, menu)
+ if not visible then
+ get_root(menu):hide()
+ else
+ menu:update()
+ if menu.items[num] then
+ menu:item_enter(num, mouse_event)
+ end
+ end
+ if action and type(action) == "function" then
+ action()
+ end
+ end
+end
+
+function item_enter(menu, num, mouse_event)
+ local item = menu.items[num]
+ if num == nil or menu.sel == num or not item then
+ return
+ elseif menu.sel then
+ menu:item_leave(menu.sel)
+ end
+ --print("sel", num, menu.sel, item.theme.bg_focus)
+ item._background:set_fg(item.theme.fg_focus)
+ item._background:set_bg(item.theme.bg_focus)
+ cur_menu = menu
+ menu.sel = num
+
+ if menu.auto_expand and mouse_event then
+ if menu.active_child then
+ menu.active_child:hide()
+ menu.active_child = nil
+ end
+
+ if type(item.cmd) == "table" then
+ menu:exec(num)
+ end
+ end
+end
+
+
+function item_leave(menu, num)
+ --print("leave", num)
+ local item = menu.items[num]
+ if item then
+ item._background:set_fg(item.theme.fg_normal)
+ item._background:set_bg(item.theme.bg_normal)
+ end
+end
+
+
+--- Show a menu.
+-- @param menu The menu to show.
+-- @param args.keygrabber A boolean enabling or not the keyboard navigation.
+-- @param args.coords Menu position defaulting to mouse.coords()
+function show(menu, args)
+ args = args or {}
+ local coords = args.coords or nil
+ local screen_index = capi.mouse.screen
+ local keygrabber = args.keygrabber or false
+
+ menu.wibox.screen = screen_index
+ if not set_size(menu) then return end
+ set_coords(menu, screen_index, coords)
+
+ if menu.parent then
+ menu.keygrabber = menu.parent.keygrabber
+ elseif keygrabber ~= nil then
+ menu.keygrabber = keygrabber
+ else
+ menu.keygrabber = false
+ end
+
+ if not cur_menu and menu.keygrabber then
+ capi.keygrabber.run(grabber)
+ end
+ cur_menu = menu
+ menu.wibox.visible = true
end
--- Hide a menu popup.
@@ -77,8 +319,7 @@ end
function hide(menu)
-- Remove items from screen
for i = 1, #menu.items do
- item_leave(menu, i)
- menu.items[i].wibox.visible = false
+ menu:item_leave(i)
end
if menu.active_child then
menu.active_child:hide()
@@ -92,176 +333,229 @@ function hide(menu)
if not cur_menu and menu.keygrabber then
capi.keygrabber.stop()
end
+ menu.wibox.visible = false
end
--- Get the elder parent so for example when you kill
--- it, it will destroy the whole family.
-local function get_parents(menu)
- if menu.parent then
- return get_parents(menu.parent)
- end
- return menu
-end
-
-local function exec(menu, num, mouse_event)
- local cmd = menu.items[num].cmd
- if type(cmd) == "table" then
- if #cmd == 0 then
- return
- end
- if not menu.child[num] then
- menu.child[num] = new({ items = cmd }, menu, num)
- end
-
- if menu.active_child then
- menu.active_child:hide()
- menu.active_child = nil
- end
- menu.active_child = menu.child[num]
- menu.active_child:show()
- elseif type(cmd) == "string" then
- get_parents(menu):hide()
- util.spawn(cmd)
- elseif type(cmd) == "function" then
- get_parents(menu):hide()
- cmd(menu.items[num].returned_value)
- end
-end
-
-local function item_enter(menu, num, mouse_event)
- if menu.sel == num then
- return
- elseif menu.sel then
- item_leave(menu, menu.sel)
- end
-
- menu.items[num].wibox:set_fg(menu.theme.fg_focus)
- menu.items[num].wibox:set_bg(menu.theme.bg_focus)
- menu.sel = num
- cur_menu = menu
-
- if menu.auto_expand and mouse_event then
- if menu.active_child then
- menu.active_child:hide()
- menu.active_child = nil
- end
-
- if type(menu.items[num].cmd) == "table" then
- exec(menu, num)
- end
- end
-end
-
-local function check_access_key(menu, key)
- for i, item in pairs(menu.items) do
- if item.akey == key then
- item_enter(menu, i)
- exec(menu, i)
- return
- end
- end
- if menu.parent then
- check_access_key(menu.parent, key)
- end
-end
-
-local function grabber(mod, key, event)
- if event == "release" then
- return true
- end
-
- local sel = cur_menu.sel or 0
- if util.table.hasitem(menu_keys.up, key) then
- local sel_new = sel-1 < 1 and #cur_menu.items or sel-1
- item_enter(cur_menu, sel_new)
- elseif util.table.hasitem(menu_keys.down, key) then
- local sel_new = sel+1 > #cur_menu.items and 1 or sel+1
- item_enter(cur_menu, sel_new)
- elseif sel > 0 and util.table.hasitem(menu_keys.exec, key) then
- exec(cur_menu, sel)
- elseif util.table.hasitem(menu_keys.back, key) then
- cur_menu:hide()
- elseif util.table.hasitem(menu_keys.close, key) then
- get_parents(cur_menu):hide()
+--- Toggle menu visibility.
+-- @param menu The menu to show if it's hidden, or to hide if it's shown.
+-- @param args.keygrabber A boolean enabling or not the keyboard navigation.
+-- @param args.coords Menu position {x,y}
+function toggle(menu, args)
+ if menu.wibox.visible then
+ menu:hide()
else
- check_access_key(cur_menu, key)
+ menu:show(args)
end
-
- return true
end
-local function add_item(data, num, item_info)
- local item = wibox({
- fg = data.theme.fg_normal,
- bg = data.theme.bg_normal,
- border_color = data.theme.border,
- border_width = data.theme.border_width,
- type = "popup_menu"
- })
+--- Update menu content
+-- @param menu The mnenu to update.
+function update(menu)
+ if menu.wibox.visible then
+ menu:show({
+ keygrabber = menu.keygrabber,
+ coords = { x = menu.x, y = menu.y } })
+ end
+end
+
+
+--- Get the elder parent so for example when you kill
+-- it, it will destroy the whole family.
+-- @param menu The sub menu of the menu family.
+function get_root(menu)
+ return menu.parent and get_root(menu.parent) or menu
+end
+
+--- Add a new menu entry
+-- @param menu The parent menu
+-- @param args The item params
+-- @param args.new (Default: awful.menu.entry) The menu entry constructor
+-- @param args.theme (Optional) The menu entry theme
+-- @param args.* params needed for the menu entry constructor
+-- @param index (Optional) the index where the new entry will inserted
+function add(menu, args, index)
+ if not args then return end
+ local theme = load_theme(args.theme or {}, menu.theme)
+ args.theme = theme
+ args.new = args.new or entry
+ local success, item = pcall(args.new, menu, args)
+ if not success then
+ print("Error while creating menu entry: " .. item)
+ return
+ end
+ if not item.widget then
+ print("Error while checking menu entry: no property widget found.")
+ return
+ end
+ item.parent = menu
+ item.theme = item.theme or theme
+ item.width = item.width or theme.width
+ item.height = item.height or theme.height
+ wibox.widget.base.check_widget(item.widget)
+ item._background = wibox.widget.background()
+ item._background:set_widget(item.widget)
+ item._background:set_fg(item.theme.fg_normal)
+ item._background:set_bg(item.theme.bg_normal)
+
-- Create bindings
- local bindings = util.table.join(
- button({}, 1, function () item_enter(data, num); exec(data, num) end),
- button({}, 3, function () data:hide() end)
- )
+ item._background:buttons(util.table.join(
+ button({}, 3, function () menu:hide() end),
+ button({}, 1, function ()
+ local num = util.table.hasitem(menu.items, item)
+ menu:item_enter(num)
+ menu:exec(num)
+ end )))
+
+ item._mouse = function ()
+ local num = util.table.hasitem(menu.items, item)
+ menu:item_enter(num, true)
+ end
+ item.widget:connect_signal("mouse::enter", item._mouse)
+
+ if index then
+ menu.layout:reset()
+ table.insert(menu.items, index, item)
+ for _, i in ipairs(menu.items) do
+ menu.layout:add(i._background)
+ end
+ else
+ table.insert(menu.items, item)
+ menu.layout:add(item._background)
+ end
+ return item
+end
+
+-- Delete menu entry at given position
+-- @param menu The menu
+-- @param num The position in the table of the menu entry to be deleted; can be also the menu entry itself
+function delete(menu, num)
+ if type(num) == "table" then
+ num = util.table.hasitem(menu.items, num)
+ end
+ local item = menu.items[num]
+ if not item then return end
+ item.widget:disconnect_signal("mouse::enter", item._mouse)
+ item.widget.screen = nil
+ table.remove(menu.items, num)
+ if menu.sel == num then
+ menu:item_leave(menu.sel)
+ menu.sel = nil
+ end
+ menu.layout:reset()
+ for _, i in ipairs(menu.items) do
+ menu.layout:add(i._background)
+ end
+ if menu.child[num] then
+ menu.child[num]:hide()
+ if menu.active_child == menu.child[num] then
+ menu.active_child = nil
+ end
+ table.remove(menu.child, num)
+ end
+end
+
+--------------------------------------------------------------------------------
+
+--- Build a popup menu with running clients and shows it.
+-- @param menu Menu table, see new() function for more informations
+-- @param args.keygrabber A boolean enabling or not the keyboard navigation.
+-- @return The menu.
+function clients(menu, args) -- FIXME crude api
+ menu = menu or {}
+ local cls = capi.client.get()
+ local cls_t = {}
+ for k, c in pairs(cls) do
+ cls_t[#cls_t + 1] = {
+ util.escape(c.name) or "",
+ function ()
+ if not c:isvisible() then
+ tags.viewmore(c:tags(), c.screen)
+ end
+ capi.client.focus = c
+ c:raise()
+ end,
+ c.icon }
+ end
+ args = args or {}
+ args.items = args.items or {}
+ table_merge(args.items, cls_t)
+
+ local m = new(args)
+ m:show(args)
+ return m
+end
+
+--------------------------------------------------------------------------------
+
+--- Default awful.menu.entry constructor
+-- @param parent The parent menu
+-- @param args the item params
+-- @return table with 'widget', 'cmd', 'akey' and all the properties the user wants to change
+function entry(parent, args)
+ args = args or {}
+ args.text = args[1] or args.text or ""
+ args.cmd = args[2] or args.cmd
+ args.icon = args[3] or args.icon
+ local ret = {}
-- Create the item label widget
local label = wibox.widget.textbox()
local key = ''
- label:set_markup(string.gsub(util.escape(item_info[1]), "&(%w)",
- function (l)
- key = string.lower(l)
- return ""..l..""
- end, 1))
+ label:set_markup(string.gsub(
+ util.escape(args.text), "&(%w)",
+ function (l)
+ key = string.lower(l)
+ return "" .. l .. ""
+ end, 1))
-- Set icon if needed
- local iconbox
+ local icon, iconbox
local margin = wibox.layout.margin()
margin:set_widget(label)
- if item_info[3] then
- local icon = type(item_info[3]) == "string" and capi.oocairo.image_surface_create_from_png(item_info[3]) or item_info[3]
- local width = icon:get_width()
- local height = icon:get_height()
- if width > data.h or height > data.h then
+ if args.icon then
+ icon = args.icon
+ if type(icon) == "string" then
+ icon = capi.oocairo.image_surface_create_from_png(icon)
+ end
+ end
+ if icon then
+ local iw = icon:get_width()
+ local ih = icon:get_height()
+ if iw > args.theme.width or ih > args.theme.height then
local w, h
- if ((data.h/height) * width) > data.h then
- w, h = data.h, (data.h / width) * height
+ if ((args.theme.height / ih) * iw) > args.theme.width then
+ w, h = args.theme.height, (args.theme.height / iw) * ih
else
- w, h = (data.h / height) * width, data.h
+ w, h = (args.theme.height / ih) * iw, args.theme.height
end
-- We need to scale the image to size w x h
local img = capi.oocairo.image_surface_create("argb32", w, h)
local cr = capi.oocairo.context_create(img)
- cr:scale(w / width, h / height)
+ cr:scale(w / iw, h / ih)
cr:set_source(icon, 0, 0)
cr:paint()
icon = img
end
iconbox = wibox.widget.imagebox()
- margin:set_left(2)
- if not iconbox:set_image(icon) then
- -- Setting the image failed, it must be invalid
+ if iconbox:set_image(icon) then
+ margin:set_left(2)
+ else
iconbox = nil
end
end
if not iconbox then
- margin:set_left(data.h + 2)
+ margin:set_left(args.theme.height + 2)
end
-
- item:buttons(bindings)
-
- local mouse_enter_func = function () item_enter(data, num, true) end
- item:connect_signal("mouse::enter", mouse_enter_func)
-
-- Create the submenu icon widget
- local submenu
- if type(item_info[2]) == "table" then
- submenu = wibox.widget.imagebox()
- if data.theme.submenu_icon then
- submenu:set_image(capi.oocairo.image_surface_create_from_png(data.theme.submenu_icon))
+ local submenu_icon
+ if type(args.cmd) == "table" then
+ submenu_icon = wibox.widget.imagebox()
+ if args.theme.submenu_icon then
+ submenu_icon:set_image(
+ capi.oocairo.image_surface_create_from_png(
+ args.theme.submenu_icon))
end
- submenu:buttons(bindings)
end
-
-- Add widgets to the wibox
local left = wibox.layout.fixed.horizontal()
if iconbox then
@@ -272,136 +566,29 @@ local function add_item(data, num, item_info)
local layout = wibox.layout.align.horizontal()
layout:set_middle(left)
- if submenu then
- layout:set_right(submenu)
+ if submenu_icon then
+ layout:set_right(submenu_icon)
end
- item:set_widget(layout)
-
- local w, h = label:fit(0, 0)
- item.height = h + 2
- item.ontop = true
-
- return { wibox = item, akey= key, cmd = item_info[2], returned_value=item_info[1] }
+ return table_update(ret, {
+ label = label,
+ icon = iconbox,
+ widget = layout,
+ cmd = args.cmd,
+ akey = key,
+ })
end
---- Build a popup menu with running clients and shows it.
--- @param menu Menu table, see new() function for more informations
--- @param args.keygrabber A boolean enabling or not the keyboard navigation.
--- @return The menu.
-function clients(menu, args)
- local cls = capi.client.get()
- local cls_t = {}
- for k, c in pairs(cls) do
- cls_t[#cls_t + 1] = { util.escape(c.name) or "",
- function ()
- if not c:isvisible() then
- tags.viewmore(c:tags(), c.screen)
- end
- capi.client.focus = c
- c:raise()
- end,
- c.icon }
- end
+--------------------------------------------------------------------------------
- if not menu then
- menu = {}
- end
-
- menu.items = cls_t
-
- local m = new(menu)
- m:show(args)
- return m
-end
-
-local function set_coords(menu, screen_idx, m_coords)
- local s_geometry = capi.screen[screen_idx].workarea
- local screen_w = s_geometry.x + s_geometry.width
- local screen_h = s_geometry.y + s_geometry.height
-
- local i_h = menu.h + menu.theme.border_width
- local m_h = (i_h * #menu.items) + menu.theme.border_width
-
- if menu.parent then
- menu.w = menu.parent.w
- menu.h = menu.parent.h
-
- local p_w = i_h * (menu.num - 1)
- local m_w = menu.w - menu.theme.border_width
-
- menu.y = menu.parent.y + p_w + m_h > screen_h and screen_h - m_h or menu.parent.y + p_w
- menu.x = menu.parent.x + m_w*2 > screen_w and menu.parent.x - m_w or menu.parent.x + m_w
- else
- local m_w = menu.w
- if m_coords == nil then
- m_coords = capi.mouse.coords()
- m_coords.x = m_coords.x + 1
- m_coords.y = m_coords.y + 1
- end
-
- menu.y = m_coords.y < s_geometry.y and s_geometry.y or m_coords.y
- menu.x = m_coords.x < s_geometry.x and s_geometry.x or m_coords.x
-
- menu.y = menu.y + m_h > screen_h and screen_h - m_h or menu.y
- menu.x = menu.x + m_w > screen_w and screen_w - m_w or menu.x
- end
-end
-
---- Show a menu.
--- @param menu The menu to show.
--- @param args.keygrabber A boolean enabling or not the keyboard navigation.
--- @param args.coords Menu position defaulting to mouse.coords()
-function show(menu, args)
- args = args or {}
- local screen_index = capi.mouse.screen
- local keygrabber = args.keygrabber or false
- local coords = args.coords or nil
- set_coords(menu, screen_index, coords)
- for num, item in pairs(menu.items) do
- local wibox = item.wibox
- wibox.width = menu.w
- wibox.height = menu.h
- wibox.x = menu.x
- wibox.y = menu.y + (num - 1) * (menu.h + wibox.border_width)
- wibox.visible = true
- end
-
- if menu.parent then
- menu.keygrabber = menu.parent.keygrabber
- elseif keygrabber ~= nil then
- menu.keygrabber = keygrabber
- else
- menu.keygrabber = false
- end
-
- if not cur_menu and menu.keygrabber then
- capi.keygrabber.run(grabber)
- end
- cur_menu = menu
-end
-
---- Toggle menu visibility.
--- @param menu The menu to show if it's hidden, or to hide if it's shown.
--- @param args.keygrabber A boolean enabling or not the keyboard navigation.
--- @param args.coords Menu position {x,y}
-function toggle(menu, args)
- if menu.items[1] and menu.items[1].wibox.visible then
- menu:hide()
- else
- menu:show(args)
- end
-end
-
---- Open a menu popup.
--- @param menu Table containing the menu informations.
+--- Create a menu popup.
+-- @param args Table containing the menu informations.
--