Improved icon theme helper (#144)

* Small refactor for the get_client_icon_path function

* Try to match first by icon name and then by class

* Formatting

* It's dashes

* Use methods

* Why check it every loop?

* Try to get icon by the retriving the command from the pid

* Split into multiple functions

* No newline at eof

* Remove empty line

* Gets only the process name instead of the full command

* Double quotes everywhere

* I don't need pattern matching

* I want the executable

* Check if pid is nil

* Use client icon if not found

* Class can be nil for some clients too?

* Check for nil values

* Lgi doesn't work with gtk 4.0

* Fix class being nil

* client.icon can be nil as well
This commit is contained in:
Kasper 2022-05-11 18:28:32 +03:00 committed by GitHub
parent c20aa6daea
commit 6e4ecb334c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 65 additions and 57 deletions

View File

@ -1,64 +1,87 @@
local Gio = require("lgi").Gio local lgi = require("lgi")
local Gtk = require("lgi").Gtk local Gio = lgi.Gio
local Gtk = lgi.require("Gtk", "3.0")
local gobject = require("gears.object") local gobject = require("gears.object")
local gtable = require("gears.table") local gtable = require("gears.table")
local helpers = require("helpers")
local setmetatable = setmetatable local setmetatable = setmetatable
local ipairs = ipairs local ipairs = ipairs
local icon_theme = { mt = {} } local icon_theme = { mt = {} }
function icon_theme:get_client_icon_path(client) local name_lookup =
local function find_icon(class) {
if self._private.client_icon_cache[class] ~= nil then ["jetbrains-studio"] = "android-studio"
return self._private.client_icon_cache[class] }
end
for _, app in ipairs(Gio.AppInfo.get_all()) do local function get_icon_by_pid_command(self, client, apps)
local id = Gio.AppInfo.get_id(app) local pid = client.pid
if id:match(helpers.misc.case_insensitive_pattern(class)) then if pid ~= nil then
self._private.client_icon_cache[class] = self:get_gicon_path(Gio.AppInfo.get_icon(app)) local handle = io.popen(string.format("ps -p %d -o comm=", pid))
return self._private.client_icon_cache[class] local pid_command = handle:read("*a"):gsub("^%s*(.-)%s*$", "%1")
handle:close()
for _, app in ipairs(apps) do
local executable = app:get_executable()
if executable and executable:find(pid_command, 1, true) then
return self:get_gicon_path(app:get_icon())
end end
end end
return nil
end end
end
local class = client.class local function get_icon_by_icon_name(self, client, apps)
if class == "jetbrains-studio" then local icon_name = client.icon_name and client.icon_name:lower() or nil
class = "android-studio" if icon_name ~= nil then
for _, app in ipairs(apps) do
local name = app:get_name():lower()
if name and name:find(icon_name, 1, true) then
return self:get_gicon_path(app:get_icon())
end
end
end end
end
local icon = self:get_icon_path("gnome-window-manager") local function get_icon_by_class(self, client, apps)
if client.class ~= nil then
local class = name_lookup[client.class] or client.class:lower()
if class ~= nil then -- Try to remove dashes
class = class:gsub("[%-]", "%%%0") local class_1 = class:gsub("[%-]", "")
icon = find_icon(class) or icon
class = client.class -- Try to replace dashes with dot
class = class:gsub("[%-]", "") local class_2 = class:gsub("[%-]", ".")
icon = find_icon(class) or icon
class = client.class -- Try to match only the first word
class = class:gsub("[%-]", ".") local class_3 = class:match("(.-)-") or class
icon = find_icon(class) or icon class_3 = class_3:match("(.-)%.") or class_3
class_3 = class_3:match("(.-)%s+") or class_3
class = client.class local possible_icon_names = { class, class_3, class_2, class_1 }
class = class:match("(.-)-") or class for _, app in ipairs(apps) do
class = class:match("(.-)%.") or class local id = app:get_id():lower()
class = class:match("(.-)%s+") or class for _, possible_icon_name in ipairs(possible_icon_names) do
class = class:gsub("[%-]", "%%%0") if id and id:find(possible_icon_name, 1, true) then
icon = find_icon(class) or icon return self:get_gicon_path(app:get_icon())
end
end
end
end end
end
return icon function icon_theme:get_client_icon_path(client)
local apps = Gio.AppInfo.get_all()
return get_icon_by_pid_command(self, client, apps) or
get_icon_by_icon_name(self, client, apps) or
get_icon_by_class(self, client, apps) or
client.icon or
self:choose_icon({"window", "window-manager", "xfwm4-default", "window_list" })
end end
function icon_theme:choose_icon(icons_names) function icon_theme:choose_icon(icons_names)
local icon_info = Gtk.IconTheme.choose_icon(self.gtk_theme, icons_names, self.icon_size, 0); local icon_info = self.gtk_theme:choose_icon(icons_names, self.icon_size, 0);
if icon_info then if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info) local icon_path = icon_info:get_filename()
if icon_path then if icon_path then
return icon_path return icon_path
end end
@ -67,21 +90,15 @@ function icon_theme:choose_icon(icons_names)
return "" return ""
end end
function icon_theme:get_gicon_path(gicon) function icon_theme:get_gicon_path(gicon)
if gicon == nil then if gicon == nil then
return "" return ""
end end
if self._private.icon_cache[gicon] ~= nil then local icon_info = self.gtk_theme:lookup_by_gicon(gicon, self.icon_size, 0);
return self._private.icon_cache[gicon]
end
local icon_info = Gtk.IconTheme.lookup_by_gicon(self.gtk_theme, gicon, self.icon_size, 0);
if icon_info then if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info) local icon_path = icon_info:get_filename()
if icon_path then if icon_path then
self._private.icon_cache[gicon] = icon_path
return icon_path return icon_path
end end
end end
@ -90,15 +107,10 @@ function icon_theme:get_gicon_path(gicon)
end end
function icon_theme:get_icon_path(icon_name) function icon_theme:get_icon_path(icon_name)
if self._private.icon_cache[icon_name] ~= nil then local icon_info = self.gtk_theme:lookup_icon(icon_name, self.icon_size, 0)
return self._private.icon_cache[icon_name]
end
local icon_info = Gtk.IconTheme.lookup_icon(self.gtk_theme, icon_name, self.icon_size, 0);
if icon_info then if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info) local icon_path = icon_info:get_filename()
if icon_path then if icon_path then
self._private.icon_cache[icon_name] = icon_path
return icon_path return icon_path
end end
end end
@ -110,10 +122,6 @@ local function new(theme_name, icon_size)
local ret = gobject{} local ret = gobject{}
gtable.crush(ret, icon_theme, true) gtable.crush(ret, icon_theme, true)
ret._private = {}
ret._private.client_icon_cache = {}
ret._private.icon_cache = {}
ret.name = theme_name or nil ret.name = theme_name or nil
ret.icon_size = icon_size or 48 ret.icon_size = icon_size or 48
@ -131,4 +139,4 @@ function icon_theme.mt:__call(...)
return new(...) return new(...)
end end
return setmetatable(icon_theme, icon_theme.mt) return setmetatable(icon_theme, icon_theme.mt)