From 58e338e80ac0e611626f5b2e62a2f32a4059025a Mon Sep 17 00:00:00 2001 From: rbuj Date: Sat, 25 Jul 2020 14:15:59 +0200 Subject: pretty-table: prefer GIO to get application icons --- src/iconthemewrapper.cpp | 28 +++++++++++++++++++++++ src/iconthemewrapper.h | 2 ++ src/prettytable.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- src/prettytable.h | 11 +++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/iconthemewrapper.cpp b/src/iconthemewrapper.cpp index e44bdcd..f5ab4ef 100644 --- a/src/iconthemewrapper.cpp +++ b/src/iconthemewrapper.cpp @@ -27,3 +27,31 @@ procman::IconThemeWrapper::load_icon(const Glib::ustring& icon_name, int size) c } } +Glib::RefPtr +procman::IconThemeWrapper::load_gicon(const Glib::RefPtr& gicon, + int size, Gtk::IconLookupFlags flags) const +{ + Gtk::IconInfo icon_info; + gint scale = gdk_window_get_scale_factor (gdk_get_default_root_window ()); + icon_info = Gtk::IconTheme::get_default()->lookup_icon(gicon, size, scale, flags); + + if (!icon_info) { + return Glib::RefPtr(); + } + + try + { + return icon_info.load_icon(); + } + catch (Gtk::IconThemeError &error) + { + if (error.code() != Gtk::IconThemeError::ICON_THEME_NOT_FOUND) + g_error("Cannot load gicon from theme: %s", error.what().c_str()); + return Glib::RefPtr(); + } + catch (Gio::Error &error) + { + g_debug("Could not load gicon: %s", error.what().c_str()); + return Glib::RefPtr(); + } +} diff --git a/src/iconthemewrapper.h b/src/iconthemewrapper.h index 3a8bde5..81222b9 100644 --- a/src/iconthemewrapper.h +++ b/src/iconthemewrapper.h @@ -14,6 +14,8 @@ namespace procman // returns 0 instead of raising an exception Glib::RefPtr load_icon(const Glib::ustring& icon_name, int size) const; + Glib::RefPtr + load_gicon(const Glib::RefPtr& gicon, int size, Gtk::IconLookupFlags flags) const; const IconThemeWrapper* operator->() const { return this; } diff --git a/src/prettytable.cpp b/src/prettytable.cpp index 7b8bed6..cbc5f0d 100644 --- a/src/prettytable.cpp +++ b/src/prettytable.cpp @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -29,6 +33,20 @@ PrettyTable::PrettyTable() G_CALLBACK(PrettyTable::on_application_opened), this); g_signal_connect(G_OBJECT(screen), "application_closed", G_CALLBACK(PrettyTable::on_application_closed), this); + + // init GIO apps cache + std::vector dirs = Glib::get_system_data_dirs(); + for (std::vector::iterator it = dirs.begin(); it != dirs.end(); ++it) { + std::string path = (*it).append("/applications"); + Glib::RefPtr file = Gio::File::create_for_path(path); + Glib::RefPtr monitor = file->monitor_directory(); + monitor->set_rate_limit(1000); // 1 second + + monitor->signal_changed().connect(sigc::mem_fun(this, &PrettyTable::file_monitor_event)); + monitors[path] = monitor; + } + + this->init_gio_app_cache(); } @@ -87,8 +105,6 @@ PrettyTable::register_application(pid_t pid, Glib::RefPtr icon) } } - - void PrettyTable::on_application_closed(WnckScreen* screen, WnckApplication* app, gpointer data) { @@ -100,7 +116,25 @@ PrettyTable::on_application_closed(WnckScreen* screen, WnckApplication* app, gpo static_cast(data)->unregister_application(pid); } +void PrettyTable::init_gio_app_cache () +{ + this->gio_apps.clear(); + + Glib::ListHandle> registered_apps = Gio::AppInfo::get_all(); + for (Glib::ListHandle>::const_iterator it = registered_apps.begin(); it != registered_apps.end(); ++it) { + Glib::RefPtr app = *it; + std::string executable = app->get_executable(); + if (executable != "sh" && executable != "env") + this->gio_apps[executable] = app; + } +} +void PrettyTable::file_monitor_event(Glib::RefPtr, + Glib::RefPtr, + Gio::FileMonitorEvent) +{ + this->init_gio_app_cache(); +} void PrettyTable::unregister_application(pid_t pid) @@ -159,7 +193,27 @@ PrettyTable::get_icon_from_default(const ProcInfo &info) return pix; } +Glib::RefPtr +PrettyTable::get_icon_from_gio(const ProcInfo &info) +{ + gchar **cmdline = g_strsplit(info.name, " ", 2); + const gchar *executable = cmdline[0]; + Glib::RefPtr icon; + + if (executable) { + Glib::RefPtr app = this->gio_apps[executable]; + Glib::RefPtr gicon; + if (app) + gicon = app->get_icon(); + + if (gicon) + icon = this->theme->load_gicon(gicon, APP_ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN | Gtk::ICON_LOOKUP_FORCE_SIZE); + } + + g_strfreev(cmdline); + return icon; +} Glib::RefPtr PrettyTable::get_icon_from_wnck(const ProcInfo &info) @@ -229,6 +283,7 @@ PrettyTable::set_icon(ProcInfo &info) if (getters.empty()) { + getters.push_back(&PrettyTable::get_icon_from_gio); getters.push_back(&PrettyTable::get_icon_from_wnck); getters.push_back(&PrettyTable::get_icon_from_theme); getters.push_back(&PrettyTable::get_icon_from_default); diff --git a/src/prettytable.h b/src/prettytable.h index 2109121..ac150de 100644 --- a/src/prettytable.h +++ b/src/prettytable.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -43,18 +44,28 @@ private: Glib::RefPtr get_icon_from_theme(const ProcInfo &); Glib::RefPtr get_icon_from_default(const ProcInfo &); + Glib::RefPtr get_icon_from_gio(const ProcInfo &); Glib::RefPtr get_icon_from_wnck(const ProcInfo &); Glib::RefPtr get_icon_from_name(const ProcInfo &); Glib::RefPtr get_icon_for_kernel(const ProcInfo &); Glib::RefPtr get_icon_dummy(const ProcInfo &); bool get_default_icon_name(const string &cmd, string &name); + void file_monitor_event (Glib::RefPtr, + Glib::RefPtr, + Gio::FileMonitorEvent); + void init_gio_app_cache (); + typedef std::map > IconCache; typedef std::map > IconsForPID; + typedef std::map > AppCache; + typedef std::map > DesktopDirMonitors; IconsForPID apps; IconCache defaults; + DesktopDirMonitors monitors; + AppCache gio_apps; procman::IconThemeWrapper theme; }; -- cgit v1.2.1