From 7afd8e3179fb4ca9cb081876f047d9f4fb4c6cb0 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 11 Oct 2015 19:53:00 +0200 Subject: [PATCH 1/6] get_icon_lookup_path: only return readable/existing dirs --- lib/menubar/utils.lua | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/menubar/utils.lua b/lib/menubar/utils.lua index 16a65f8a9..e56c72275 100644 --- a/lib/menubar/utils.lua +++ b/lib/menubar/utils.lua @@ -67,29 +67,48 @@ local function is_format_supported(icon_file) end local icon_lookup_path = nil +--- Get a list of icon lookup paths. +-- @treturn table A list of directories, without trailing slash. local function get_icon_lookup_path() if not icon_lookup_path then + local add_if_readable = function(t, path) + if awful_util.dir_readable(path) then + table.insert(t, path) + end + end icon_lookup_path = {} local icon_theme_paths = {} local icon_theme = theme.icon_theme local paths = glib.get_system_data_dirs() table.insert(paths, 1, glib.get_user_data_dir()) - table.insert(paths, 1, glib.get_home_dir() .. '/.icons') - for k,dir in ipairs(paths)do - if icon_theme then - table.insert(icon_theme_paths, dir..'/icons/' .. icon_theme .. '/') + table.insert(paths, 1, glib.build_filenamev({glib.get_home_dir(), + '.icons'})) + for k,dir in ipairs(paths) do + local icons_dir = glib.build_filenamev({dir, 'icons'}) + if awful_util.dir_readable(icons_dir) then + if icon_theme then + add_if_readable(icon_theme_paths, + glib.build_filenamev({icons_dir, + icon_theme})) + end + -- Fallback theme. + add_if_readable(icon_theme_paths, + glib.build_filenamev({icons_dir, 'hicolor'})) end - table.insert(icon_theme_paths, dir..'/icons/hicolor/') -- fallback theme end for i, icon_theme_directory in ipairs(icon_theme_paths) do for j, size in ipairs(all_icon_sizes) do - table.insert(icon_lookup_path, icon_theme_directory .. size .. '/apps/') + add_if_readable(icon_lookup_path, + glib.build_filenamev({icon_theme_directory, + size, 'apps'})) end end for k,dir in ipairs(paths)do -- lowest priority fallbacks - table.insert(icon_lookup_path, dir..'/pixmaps/') - table.insert(icon_lookup_path, dir..'/icons/') + add_if_readable(icon_lookup_path, + glib.build_filenamev({dir, 'pixmaps'})) + add_if_readable(icon_lookup_path, + glib.build_filenamev({dir, 'icons'})) end end return icon_lookup_path @@ -109,14 +128,15 @@ function utils.lookup_icon(icon_file) return awful_util.file_readable(icon_file) and icon_file or nil else for i, directory in ipairs(get_icon_lookup_path()) do - if is_format_supported(icon_file) and awful_util.file_readable(directory .. icon_file) then - return directory .. icon_file + if is_format_supported(icon_file) and + awful_util.file_readable(directory .. "/" .. icon_file) then + return directory .. "/" .. icon_file else -- Icon is probably specified without path and format, -- like 'firefox'. Try to add supported extensions to -- it and see if such file exists. for _, format in ipairs(icon_formats) do - local possible_file = directory .. icon_file .. "." .. format + local possible_file = directory .. "/" .. icon_file .. "." .. format if awful_util.file_readable(possible_file) then return possible_file end From 7fa3dc97c8494c0c9d17c5e1dd64ef89bc0486e5 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 12 Oct 2015 00:18:28 +0200 Subject: [PATCH 2/6] Optimize menubar.icon_theme.lookup_icon: do not look twice --- lib/menubar/icon_theme.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/menubar/icon_theme.lua b/lib/menubar/icon_theme.lua index e21e0d699..d8d3e740d 100644 --- a/lib/menubar/icon_theme.lua +++ b/lib/menubar/icon_theme.lua @@ -147,6 +147,7 @@ local directory_size_distance = function(self, subdirectory, icon_size) end local lookup_icon = function(self, icon_name, icon_size) + local checked_already = {} for _, subdir in ipairs(self.index_theme:get_subdirectories()) do for _, basedir in ipairs(self.base_directories) do for _, ext in ipairs(self.extensions) do @@ -156,6 +157,8 @@ local lookup_icon = function(self, icon_name, icon_size) icon_name, ext) if awful.util.file_readable(filename) then return filename + else + checked_already[filename] = true end end end @@ -170,19 +173,17 @@ local lookup_icon = function(self, icon_name, icon_size) local filename = string.format("%s/%s/%s/%s.%s", basedir, self.icon_theme_name, subdir, icon_name, ext) - local dist = directory_size_distance(self, subdir, icon_size) - if awful.util.file_readable(filename) and dist < minimal_size then - closest_filename = filename - minimal_size = dist + if not checked_already[filename] then + local dist = directory_size_distance(self, subdir, icon_size) + if awful.util.file_readable(filename) and dist < minimal_size then + closest_filename = filename + minimal_size = dist + end end end end end - if closest_filename then - return closest_filename - end - - return nil + return closest_filename end local find_icon_path_helper -- Gets called recursively. From efbddb587587a13d8ffebe51807ec4c9450efa41 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 12 Oct 2015 00:25:39 +0200 Subject: [PATCH 3/6] Add cache for menubar.utils.lookup_icon I have tried to use `utils.icon_cache = require("gears.cache").new(utils.lookup_icon_uncached)`, but that appears to get garbage-collected too much?! --- lib/menubar/utils.lua | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/menubar/utils.lua b/lib/menubar/utils.lua index e56c72275..57868ee78 100644 --- a/lib/menubar/utils.lua +++ b/lib/menubar/utils.lua @@ -115,11 +115,11 @@ local function get_icon_lookup_path() end --- Lookup an icon in different folders of the filesystem. --- @param icon_file Short or full name of the icon. --- @return full name of the icon. -function utils.lookup_icon(icon_file) +-- @tparam string icon_file Short or full name of the icon. +-- @treturn string|boolean Full name of the icon, or false on failure. +function utils.lookup_icon_uncached(icon_file) if not icon_file or icon_file == "" then - return default_icon + return false end if icon_file:sub(1, 1) == '/' and is_format_supported(icon_file) then @@ -143,10 +143,21 @@ function utils.lookup_icon(icon_file) end end end - return default_icon + return false end end +local lookup_icon_cache = {} +--- Lookup an icon in different folders of the filesystem (cached). +-- @param icon_file Short or full name of the icon. +-- @return full name of the icon. +function utils.lookup_icon(icon) + if not lookup_icon_cache[icon] and lookup_icon_cache[icon] ~= false then + lookup_icon_cache[icon] = utils.lookup_icon_uncached(icon) + end + return lookup_icon_cache[icon] or default_icon +end + --- Parse a .desktop file. -- @param file The .desktop file. -- @return A table with file entries. From 75341d9e38ebc5385ab8aa72b6c09395510080eb Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 12 Oct 2015 00:29:18 +0200 Subject: [PATCH 4/6] menubar.menu_gen.generate: do not call lookup_icon again `menubar.utils.lookup_icon` gets called via `menubar.utils.parse` already. --- lib/menubar/menu_gen.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/menubar/menu_gen.lua b/lib/menubar/menu_gen.lua index 630cfa111..86fda43d4 100644 --- a/lib/menubar/menu_gen.lua +++ b/lib/menubar/menu_gen.lua @@ -112,7 +112,7 @@ function menu_gen.generate() if target_category then local name = trim(program.Name) or "" local cmdline = trim(program.cmdline) or "" - local icon = utils.lookup_icon(trim(program.icon_path)) or nil + local icon = program.icon_path or nil table.insert(result, { name = name, cmdline = cmdline, icon = icon, From 7d9b78c13c7ae502855c937b0e74a292f8c74a2f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 12 Oct 2015 01:01:04 +0200 Subject: [PATCH 5/6] menubar.icon_theme.lookup_icon: check for dist in outer loop --- lib/menubar/icon_theme.lua | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/menubar/icon_theme.lua b/lib/menubar/icon_theme.lua index d8d3e740d..d4f1bba95 100644 --- a/lib/menubar/icon_theme.lua +++ b/lib/menubar/icon_theme.lua @@ -168,16 +168,18 @@ local lookup_icon = function(self, icon_name, icon_size) local minimal_size = 0xffffffff -- Any large number will do. local closest_filename = nil for _, subdir in ipairs(self.index_theme:get_subdirectories()) do - for _, basedir in ipairs(self.base_directories) do - for _, ext in ipairs(self.extensions) do - local filename = string.format("%s/%s/%s/%s.%s", - basedir, self.icon_theme_name, subdir, - icon_name, ext) - if not checked_already[filename] then - local dist = directory_size_distance(self, subdir, icon_size) - if awful.util.file_readable(filename) and dist < minimal_size then - closest_filename = filename - minimal_size = dist + local dist = directory_size_distance(self, subdir, icon_size) + if dist < minimal_size then + for _, basedir in ipairs(self.base_directories) do + for _, ext in ipairs(self.extensions) do + local filename = string.format("%s/%s/%s/%s.%s", + basedir, self.icon_theme_name, subdir, + icon_name, ext) + if not checked_already[filename] then + if awful.util.file_readable(filename) then + closest_filename = filename + minimal_size = dist + end end end end From a648b27af66f95b160100912c833432b6372e726 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 13 Oct 2015 11:11:45 +0200 Subject: [PATCH 6/6] menubar.icon_theme: cache index_theme instances Ref: https://github.com/awesomeWM/awesome/pull/523#commitcomment-13716821 --- lib/menubar/icon_theme.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/menubar/icon_theme.lua b/lib/menubar/icon_theme.lua index d4f1bba95..e7d1b8a2b 100644 --- a/lib/menubar/icon_theme.lua +++ b/lib/menubar/icon_theme.lua @@ -91,6 +91,8 @@ end local icon_theme = { mt = {} } +local index_theme_cache = {} + --- Class constructor of `icon_theme` -- @tparam string icon_theme_name Internal name of icon theme -- @tparam table base_directories Paths used for lookup @@ -103,7 +105,18 @@ icon_theme.new = function(icon_theme_name, base_directories) self.icon_theme_name = icon_theme_name self.base_directories = base_directories self.extensions = { "png", "svg", "xpm" } - self.index_theme = index_theme(self.icon_theme_name, self.base_directories) + + -- Instantiate index_theme (cached). + if not index_theme_cache[self.icon_theme_name] then + index_theme_cache[self.icon_theme_name] = {} + end + local cache_key = table.concat(self.base_directories, ':') + if not index_theme_cache[self.icon_theme_name][cache_key] then + index_theme_cache[self.icon_theme_name][cache_key] = index_theme( + self.icon_theme_name, + self.base_directories) + end + self.index_theme = index_theme_cache[self.icon_theme_name][cache_key] return setmetatable(self, { __index = icon_theme }) end