1 ---------------------------------------------------------------------------
2 -- @author Antonio Terceiro
3 -- @copyright 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev
4 -- @release @AWESOME_VERSION@
5 ---------------------------------------------------------------------------
12 local awful_util
= require("awful.util")
13 local theme
= require("beautiful")
15 -- Utility module for menubar
19 -- NOTE: This icons/desktop files module was written according to the
20 -- following freedesktop.org specifications:
21 -- Icons: http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.11.html
22 -- Desktop files: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
26 --- Terminal which applications that need terminal would open in.
27 utils
.terminal
= 'xterm'
29 -- The default icon for applications that don't provide any icon in
30 -- their .desktop files.
31 local default_icon
= nil
33 --- Name of the WM for the OnlyShownIn entry in the .desktop file.
34 utils
.wm_name
= "awesome"
38 local all_icon_sizes
= {
51 -- List of supported icon formats. Ignore SVG because Awesome doesn't
53 local icon_formats
= { "png", "xpm" }
55 -- Check whether the icon format is supported.
56 -- @param icon_file Filename of the icon.
57 -- @return true if format is supported, false otherwise.
58 local function is_format_supported(icon_file
)
59 for _
, f
in ipairs(icon_formats
) do
60 if icon_file
:match('%.' .. f
) then
67 --- Lookup an icon in different folders of the filesystem.
68 -- @param icon_file Short or full name of the icon.
69 -- @return full name of the icon.
70 function utils
.lookup_icon(icon_file
)
71 if not icon_file
or icon_file
== "" then
75 if icon_file
:sub(1, 1) == '/' and is_format_supported(icon_file
) then
76 -- If the path to the icon is absolute and its format is
77 -- supported, do not perform a lookup.
81 local icon_theme_paths
= {}
82 local icon_theme
= theme
.icon_theme
84 table.insert(icon_theme_paths
, '/usr/share/icons/' .. icon_theme
.. '/')
85 -- TODO also look in parent icon themes, as in freedesktop.org specification
87 table.insert(icon_theme_paths
, '/usr/share/icons/hicolor/') -- fallback theme
89 for i
, icon_theme_directory
in ipairs(icon_theme_paths
) do
90 for j
, size
in ipairs(all_icon_sizes
) do
91 table.insert(icon_path
, icon_theme_directory
.. size
.. '/apps/')
92 table.insert(icon_path
, icon_theme_directory
.. size
.. '/actions/')
93 table.insert(icon_path
, icon_theme_directory
.. size
.. '/devices/')
94 table.insert(icon_path
, icon_theme_directory
.. size
.. '/places/')
95 table.insert(icon_path
, icon_theme_directory
.. size
.. '/categories/')
96 table.insert(icon_path
, icon_theme_directory
.. size
.. '/status/')
99 -- lowest priority fallbacks
100 table.insert(icon_path
, '/usr/share/pixmaps/')
101 table.insert(icon_path
, '/usr/share/icons/')
103 for i
, directory
in ipairs(icon_path
) do
104 if is_format_supported(icon_file
) and awful_util
.file_readable(directory
.. icon_file
) then
105 return directory
.. icon_file
107 -- Icon is probably specified without path and format,
108 -- like 'firefox'. Try to add supported extensions to
109 -- it and see if such file exists.
110 for _
, format in ipairs(icon_formats
) do
111 local possible_file
= directory
.. icon_file
.. "." .. format
112 if awful_util
.file_readable(possible_file
) then
122 --- Parse a .desktop file.
123 -- @param file The .desktop file.
124 -- @return A table with file entries.
125 function utils
.parse(file
)
126 local program
= { show
= true, file
= file
}
127 local desktop_entry
= false
129 -- Parse the .desktop file.
130 -- We are interested in [Desktop Entry] group only.
131 for line
in io
.lines(file
) do
132 if not desktop_entry
and line
== "[Desktop Entry]" then
135 if line
:sub(1, 1) == "[" and line
:sub(-1) == "]" then
136 -- A declaration of new group - stop parsing
141 for key
, value
in line
:gmatch("(%w+)%s*=%s*(.+)") do
147 -- In case [Desktop Entry] was not found
148 if not desktop_entry
then return nil end
150 -- Don't show program if NoDisplay attribute is false
151 if program
.NoDisplay
and string.lower(program
.NoDisplay
) == "true" then
155 -- Only show the program if there is no OnlyShowIn attribute
156 -- or if it's equal to utils.wm_name
157 if program
.OnlyShowIn
~= nil and not program
.OnlyShowIn
:match(utils
.wm_name
) then
161 -- Look up for a icon.
163 program
.icon_path
= utils
.lookup_icon(program
.Icon
)
166 -- Split categories into a table. Categories are written in one
167 -- line separated by semicolon.
168 if program
.Categories
then
169 program
.categories
= {}
170 for category
in program
.Categories
:gmatch('[^;]+') do
171 table.insert(program
.categories
, category
)
176 -- Substitute Exec special codes as specified in
177 -- http://standards.freedesktop.org/desktop-entry-spec/1.1/ar01s06.html
178 local cmdline
= program
.Exec
:gsub('%%c', program
.Name
)
179 cmdline
= cmdline
:gsub('%%[fuFU]', '')
180 cmdline
= cmdline
:gsub('%%k', program
.file
)
181 if program
.icon_path
then
182 cmdline
= cmdline
:gsub('%%i', '--icon ' .. program
.icon_path
)
184 cmdline
= cmdline
:gsub('%%i', '')
186 if program
.Terminal
== "true" then
187 cmdline
= utils
.terminal
.. ' -e ' .. cmdline
189 program
.cmdline
= cmdline
195 --- Parse a directory with .desktop files
196 -- @param dir The directory.
197 -- @param icons_size, The icons sizes, optional.
198 -- @return A table with all .desktop entries.
199 function utils
.parse_dir(dir
)
201 local files
= io
.popen('find '.. dir
..' -maxdepth 1 -name "*.desktop" 2>/dev/null')
202 for file
in files
:lines() do
203 local program
= utils
.parse(file
)
205 table.insert(programs
, program
)
213 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80