|
Packit |
76ec6a |
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
Packit |
76ec6a |
#include <config.h>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#ifdef HAVE_WNCK
|
|
Packit |
76ec6a |
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
|
|
Packit |
76ec6a |
#include <libwnck/libwnck.h>
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <dirent.h>
|
|
Packit |
76ec6a |
#include <sys/stat.h>
|
|
Packit |
76ec6a |
#include <stdio.h>
|
|
Packit |
76ec6a |
#include <string.h>
|
|
Packit |
76ec6a |
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
Packit |
76ec6a |
#include <glibtop/procstate.h>
|
|
Packit |
76ec6a |
#include <giomm/error.h>
|
|
Packit |
76ec6a |
#include <giomm/file.h>
|
|
Packit |
76ec6a |
#include <glibmm/miscutils.h>
|
|
Packit |
76ec6a |
#include <iostream>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include <vector>
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#include "prettytable.h"
|
|
Packit |
76ec6a |
#include "defaulttable.h"
|
|
Packit |
76ec6a |
#include "proctable.h"
|
|
Packit |
76ec6a |
#include "util.h"
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#ifdef GDK_WINDOWING_X11
|
|
Packit |
76ec6a |
#include <gdk/gdkx.h>
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
namespace
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
const unsigned APP_ICON_SIZE = 16;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
PrettyTable::PrettyTable()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
#ifdef HAVE_WNCK
|
|
Packit |
76ec6a |
#ifdef GDK_WINDOWING_X11
|
|
Packit |
76ec6a |
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) {
|
|
Packit |
76ec6a |
WnckScreen* screen = wnck_screen_get_default();
|
|
Packit |
76ec6a |
g_signal_connect(G_OBJECT(screen), "application_opened",
|
|
Packit |
76ec6a |
G_CALLBACK(PrettyTable::on_application_opened), this);
|
|
Packit |
76ec6a |
g_signal_connect(G_OBJECT(screen), "application_closed",
|
|
Packit |
76ec6a |
G_CALLBACK(PrettyTable::on_application_closed), this);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// init GIO apps cache
|
|
Packit |
76ec6a |
std::vector<std::string> dirs = Glib::get_system_data_dirs();
|
|
Packit |
76ec6a |
for (std::vector<std::string>::iterator it = dirs.begin(); it != dirs.end(); ++it) {
|
|
Packit |
76ec6a |
std::string path = (*it).append("/applications");
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(path);
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::FileMonitor> monitor = file->monitor_directory();
|
|
Packit |
76ec6a |
monitor->set_rate_limit(1000); // 1 second
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
monitor->signal_changed().connect(sigc::mem_fun(this, &PrettyTable::file_monitor_event));
|
|
Packit |
76ec6a |
monitors[path] = monitor;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
this->init_gio_app_cache();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
PrettyTable::~PrettyTable()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#ifdef HAVE_WNCK
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
PrettyTable::on_application_opened(WnckScreen* screen, WnckApplication* app, gpointer data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
PrettyTable * const that = static_cast<PrettyTable*>(data);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
pid_t pid = wnck_application_get_pid(app);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (pid == 0)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
const char* icon_name = wnck_application_get_icon_name(app);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf> icon;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
icon = Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), icon_name, APP_ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (not icon) {
|
|
Packit |
76ec6a |
icon = Glib::wrap(wnck_application_get_icon(app), /* take_copy */ true);
|
|
Packit |
76ec6a |
icon = icon->scale_simple(APP_ICON_SIZE, APP_ICON_SIZE, Gdk::INTERP_HYPER);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (not icon)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
that->register_application(pid, icon);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
PrettyTable::register_application(pid_t pid, Glib::RefPtr<Gdk::Pixbuf> icon)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
/* If process already exists then set the icon. Otherwise put into hash
|
|
Packit |
76ec6a |
** table to be added later */
|
|
Packit |
76ec6a |
if (ProcInfo* info = GsmApplication::get()->processes.find(pid))
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
info->set_icon(icon);
|
|
Packit |
76ec6a |
// move the ref to the map
|
|
Packit |
76ec6a |
this->apps[pid] = icon;
|
|
Packit |
76ec6a |
procman_debug("WNCK OK for %u", unsigned(pid));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
PrettyTable::on_application_closed(WnckScreen* screen, WnckApplication* app, gpointer data)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
pid_t pid = wnck_application_get_pid(app);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (pid == 0)
|
|
Packit |
76ec6a |
return;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static_cast<PrettyTable*>(data)->unregister_application(pid);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
PrettyTable::unregister_application(pid_t pid)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
IconsForPID::iterator it(this->apps.find(pid));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (it != this->apps.end())
|
|
Packit |
76ec6a |
this->apps.erase(it);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
#endif // HAVE_WNCK
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void PrettyTable::init_gio_app_cache ()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
this->gio_apps.clear();
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::ListHandle<Glib::RefPtr<Gio::AppInfo> > apps = Gio::AppInfo::get_all();
|
|
Packit |
76ec6a |
for (Glib::ListHandle<Glib::RefPtr<Gio::AppInfo> >::const_iterator it = apps.begin();
|
|
Packit |
76ec6a |
it != apps.end(); ++it) {
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::AppInfo> app = *it;
|
|
Packit |
76ec6a |
std::string executable = app->get_executable();
|
|
Packit |
76ec6a |
if (executable != "sh" &&
|
|
Packit |
76ec6a |
executable != "env")
|
|
Packit |
76ec6a |
this->gio_apps[executable] = app;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void PrettyTable::file_monitor_event(Glib::RefPtr<Gio::File>,
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::File>,
|
|
Packit |
76ec6a |
Gio::FileMonitorEvent)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
this->init_gio_app_cache();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_from_theme(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), info.name.c_str(), APP_ICON_SIZE, (GtkIconLookupFlags)(GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_FORCE_SIZE), NULL));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
bool PrettyTable::get_default_icon_name(const string &cmd, string &name)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
for (size_t i = 0; i != G_N_ELEMENTS(default_table); ++i) {
|
|
Packit |
76ec6a |
if (default_table[i].command->match(cmd)) {
|
|
Packit |
76ec6a |
name = default_table[i].icon;
|
|
Packit |
76ec6a |
return true;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return false;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
/*
|
|
Packit |
76ec6a |
Try to get an icon from the default_table
|
|
Packit |
76ec6a |
If it's not in defaults, try to load it.
|
|
Packit |
76ec6a |
If there is no default for a command, store NULL in defaults
|
|
Packit |
76ec6a |
so we don't have to lookup again.
|
|
Packit |
76ec6a |
*/
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_from_default(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf> pix;
|
|
Packit |
76ec6a |
string name;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (this->get_default_icon_name(info.name, name)) {
|
|
Packit |
76ec6a |
IconCache::iterator it(this->defaults.find(name));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (it == this->defaults.end()) {
|
|
Packit |
76ec6a |
pix = Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), name.c_str(), APP_ICON_SIZE, (GtkIconLookupFlags)(GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_FORCE_SIZE), NULL));
|
|
Packit |
76ec6a |
if (pix)
|
|
Packit |
76ec6a |
this->defaults[name] = pix;
|
|
Packit |
76ec6a |
} else
|
|
Packit |
76ec6a |
pix = it->second;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return pix;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_from_gio(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
gchar **cmdline = g_strsplit(info.name.c_str(), " ", 2);
|
|
Packit |
76ec6a |
const gchar *executable = cmdline[0];
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf> icon;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (executable) {
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::AppInfo> app = this->gio_apps[executable];
|
|
Packit |
76ec6a |
Glib::RefPtr<Gio::Icon> gicon;
|
|
Packit |
76ec6a |
Gtk::IconInfo info;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (app)
|
|
Packit |
76ec6a |
gicon = app->get_icon();
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (gicon)
|
|
Packit |
76ec6a |
info = Glib::wrap(gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (), gicon->gobj(), APP_ICON_SIZE, (GtkIconLookupFlags)(GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_FORCE_SIZE)));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (info)
|
|
Packit |
76ec6a |
icon = Glib::wrap(gtk_icon_info_load_icon (info.gobj(), NULL));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
g_strfreev(cmdline);
|
|
Packit |
76ec6a |
return icon;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
#ifdef HAVE_WNCK
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_from_wnck(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf> icon;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
IconsForPID::iterator it(this->apps.find(info.pid));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (it != this->apps.end())
|
|
Packit |
76ec6a |
icon = it->second;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return icon;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_from_name(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), info.name.c_str(), APP_ICON_SIZE, (GtkIconLookupFlags)(GTK_ICON_LOOKUP_USE_BUILTIN | GTK_ICON_LOOKUP_FORCE_SIZE), NULL));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_dummy(const ProcInfo &)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "application-x-executable", APP_ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL));
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
namespace
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
bool has_kthreadd()
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
glibtop_proc_state buf;
|
|
Packit |
76ec6a |
glibtop_get_proc_state(&buf, 2);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return buf.cmd == string("kthreadd");
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
// @pre: has_kthreadd
|
|
Packit |
76ec6a |
bool is_kthread(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
return info.pid == 2 or info.ppid == 2;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
PrettyTable::get_icon_for_kernel(const ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
if (is_kthread(info))
|
|
Packit |
76ec6a |
return Glib::wrap(gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "applications-system", APP_ICON_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL));
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
return Glib::RefPtr<Gdk::Pixbuf>();
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
void
|
|
Packit |
76ec6a |
PrettyTable::set_icon(ProcInfo &info)
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
typedef Glib::RefPtr<Gdk::Pixbuf>
|
|
Packit |
76ec6a |
(PrettyTable::*Getter)(const ProcInfo &);
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
static std::vector<Getter> getters;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
if (getters.empty())
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_from_gio);
|
|
Packit |
76ec6a |
#ifdef HAVE_WNCK
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_from_wnck);
|
|
Packit |
76ec6a |
#endif
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_from_theme);
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_from_default);
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_from_name);
|
|
Packit |
76ec6a |
if (has_kthreadd())
|
|
Packit |
76ec6a |
{
|
|
Packit |
76ec6a |
procman_debug("kthreadd is running with PID 2");
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_for_kernel);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
getters.push_back(&PrettyTable::get_icon_dummy);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
Glib::RefPtr<Gdk::Pixbuf> icon;
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
for (size_t i = 0; not icon and i < getters.size(); ++i) {
|
|
Packit |
76ec6a |
try {
|
|
Packit |
76ec6a |
icon = (this->*getters[i])(info);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
catch (std::exception& e) {
|
|
Packit |
76ec6a |
g_warning("Failed to load icon for %s(%u) : %s", info.name.c_str(), info.pid, e.what());
|
|
Packit |
76ec6a |
continue;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
catch (Glib::Exception& e) {
|
|
Packit |
76ec6a |
g_warning("Failed to load icon for %s(%u) : %s", info.name.c_str(), info.pid, e.what().c_str());
|
|
Packit |
76ec6a |
continue;
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|
|
Packit |
76ec6a |
info.set_icon(icon);
|
|
Packit |
76ec6a |
}
|
|
Packit |
76ec6a |
|