From 731d6a250fdd635be53760eaf0065e8db4396a0e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 13 Aug 2008 21:04:41 +0000 Subject: [PATCH] add session information --- gnome-system-monitor.spec | 11 +- session.patch | 928 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 937 insertions(+), 2 deletions(-) create mode 100644 session.patch diff --git a/gnome-system-monitor.spec b/gnome-system-monitor.spec index 20fc5ba..d1a7152 100644 --- a/gnome-system-monitor.spec +++ b/gnome-system-monitor.spec @@ -13,7 +13,7 @@ Summary: Simple process monitor Name: gnome-system-monitor Version: 2.23.6 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv2+ Group: Applications/System URL: http://www.gnome.org/ @@ -42,9 +42,12 @@ BuildRequires: gnome-common # needed for autoreconf BuildRequires: autoconf, automake, libtool -# send upstream: http://bugzilla.gnome.org/show_bug.cgi?id=491462 +# sent upstream: http://bugzilla.gnome.org/show_bug.cgi?id=491462 Patch0: gnome-system-monitor-2.23.2-polkit.patch +# sent upstream: http://bugzilla.gnome.org/show_bug.cgi?id=421912 +Patch1: session.patch + Requires: PolicyKit-gnome >= %{polkit_gnome_version} Requires(pre): GConf2 >= %{gconf_version} Requires(post): GConf2 >= %{gconf_version} @@ -58,6 +61,7 @@ gnome-system-monitor is a simple process and system monitor. %prep %setup -q %patch0 -p1 -b .polkit +%patch1 -p1 -b .session %build autoreconf @@ -122,6 +126,9 @@ scrollkeeper-update -q %changelog +* Wed Aug 13 2008 Matthias Clasen - 2.23.6-2 +- Add session mgmt information in a Session column + * Tue Aug 5 2008 Matthias Clasen - 2.23.6-1 - Update to 2.23.6 diff --git a/session.patch b/session.patch new file mode 100644 index 0000000..e0daa90 --- /dev/null +++ b/session.patch @@ -0,0 +1,928 @@ +--- gnome-system-monitor-2.23.5/src/proctable.cpp 2008-05-31 14:38:57.000000000 -0400 ++++ hacked/src/proctable.cpp 2008-08-07 14:20:34.000000000 -0400 +@@ -51,6 +51,7 @@ + #include "util.h" + #include "interface.h" + #include "selinux.h" ++#include "gsm-session-manager.h" + + + ProcInfo::UserMap ProcInfo::users; +@@ -225,6 +226,7 @@ + N_("Memory"), + /* xgettext: wchan, see ps(1) or top(1) */ + N_("Waiting Channel"), ++ N_("Session"), + NULL, + "POINTER" + }; +@@ -254,9 +256,12 @@ + G_TYPE_STRING, /* Arguments */ + G_TYPE_ULONG, /* Memory */ + G_TYPE_STRING, /* wchan */ ++ G_TYPE_UINT, /* Session state */ ++ G_TYPE_UINT, /* Restart style */ + GDK_TYPE_PIXBUF, /* Icon */ + G_TYPE_POINTER, /* ProcInfo */ +- G_TYPE_STRING /* Sexy tooltip */ ++ G_TYPE_STRING /* Sexy tooltip */ ++ + ); + + proctree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); +@@ -295,7 +300,6 @@ + gtk_tree_view_append_column (GTK_TREE_VIEW (proctree), column); + gtk_tree_view_set_expander_column (GTK_TREE_VIEW (proctree), column); + +- + for (i = COL_USER; i <= COL_WCHAN; i++) { + + GtkCellRenderer *cell; +@@ -385,6 +389,26 @@ + } + } + ++ column = gtk_tree_view_column_new(); ++ gtk_tree_view_column_set_title(column, _(titles[COL_SESSION_STATE])); ++ gtk_tree_view_column_set_resizable(column, FALSE); ++ gtk_tree_view_column_set_reorderable(column, TRUE); ++ gtk_tree_view_column_set_sort_column_id (column, COL_SESSION_STATE); ++ gtk_tree_view_append_column(GTK_TREE_VIEW(proctree), column); ++ cell_renderer = gtk_cell_renderer_pixbuf_new (); ++ gtk_tree_view_column_pack_start (column, cell_renderer, FALSE); ++ gtk_tree_view_column_set_cell_data_func(column, cell_renderer, ++ &procman::session_state_cell_data_func, ++ GUINT_TO_POINTER(COL_SESSION_STATE), ++ NULL); ++ ++ cell_renderer = gtk_cell_renderer_pixbuf_new (); ++ gtk_tree_view_column_pack_start (column, cell_renderer, FALSE); ++ gtk_tree_view_column_set_cell_data_func(column, cell_renderer, ++ &procman::restart_style_cell_data_func, ++ GUINT_TO_POINTER(COL_RESTART_STYLE), ++ NULL); ++ + gtk_container_add (GTK_CONTAINER (scrolled), proctree); + + procdata->tree = proctree; +@@ -834,6 +858,59 @@ + update_info_mutable_cols(it->second); + } + ++static gboolean ++clear_session_data (GtkTreeModel *model, ++ GtkTreePath *path, ++ GtkTreeIter *iter, ++ gpointer data) ++{ ++ gtk_tree_store_set (GTK_TREE_STORE (model), ++ iter, ++ COL_SESSION_STATE, 0, ++ COL_RESTART_STYLE, 0, ++ -1); ++ ++ return FALSE; ++} ++ ++static void ++update_session_data (const char *obj_path, ++ guint pid, ++ guint status, ++ guint restart_style_hint, ++ gpointer data) ++{ ++ GtkTreeModel *model = (GtkTreeModel*)data; ++ GtkTreeIter iter; ++ guint pid2; ++ ++ gtk_tree_model_get_iter_first (model, &iter); ++ do { ++ gtk_tree_model_get (model, &iter, COL_PID, &pid2, -1); ++ if (pid == pid2) { ++ gtk_tree_store_set (GTK_TREE_STORE (model), ++ &iter, ++ COL_SESSION_STATE, status, ++ COL_RESTART_STYLE, restart_style_hint + 1, ++ -1); ++ return; ++ } ++ } while (gtk_tree_model_iter_next (model, &iter)); ++} ++ ++static void ++add_session_data (ProcData * const procdata) ++{ ++ GsmSessionManager *manager; ++ GtkTreeModel *model; ++ ++ model = gtk_tree_view_get_model (GTK_TREE_VIEW (procdata->tree)); ++ gtk_tree_model_foreach (model, clear_session_data, NULL); ++ ++ manager = gsm_session_manager_get (); ++ gsm_session_manager_foreach (manager, update_session_data, model); ++ g_object_unref (manager); ++} + + void + proctable_update_list (ProcData * const procdata) +@@ -880,6 +957,7 @@ + procdata->cpu_total_time_last = cpu.total; + + refresh_list (procdata, pid_list, proclist.number); ++ add_session_data (procdata); + + selection.restore(procdata->tree); + +--- gnome-system-monitor-2.23.5/src/proctable.h 2008-05-24 17:58:27.000000000 -0400 ++++ hacked/src/proctable.h 2008-08-07 13:29:23.000000000 -0400 +@@ -43,6 +43,8 @@ + COL_ARGS, + COL_MEM, + COL_WCHAN, ++ COL_SESSION_STATE, ++ COL_RESTART_STYLE, + COL_PIXBUF, + COL_POINTER, + COL_TOOLTIP, +--- gnome-system-monitor-2.23.5/src/util.h 2008-07-21 12:18:47.000000000 -0400 ++++ hacked/src/util.h 2008-07-29 23:40:25.000000000 -0400 +@@ -94,6 +94,14 @@ + GtkTreeModel *model, GtkTreeIter *iter, + gpointer user_data); + ++ void session_state_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, ++ GtkTreeModel *model, GtkTreeIter *iter, ++ gpointer user_data); ++ ++ void restart_style_cell_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, ++ GtkTreeModel *model, GtkTreeIter *iter, ++ gpointer user_data); ++ + template + void poison(T &t, char c) + { +--- gnome-system-monitor-2.23.5/src/util.cpp 2008-07-21 12:18:47.000000000 -0400 ++++ hacked/src/util.cpp 2008-08-07 13:36:43.000000000 -0400 +@@ -50,7 +50,81 @@ + return status; + } + ++typedef enum { ++ GSM_CLIENT_RESTART_NEVER = 1, ++ GSM_CLIENT_RESTART_IF_RUNNING, ++ GSM_CLIENT_RESTART_ANYWAY, ++ GSM_CLIENT_RESTART_IMMEDIATELY, ++} GsmClientRestartStyle; + ++static const char* ++format_restart_style (guint state) ++{ ++ const char *status; ++ ++ switch (state) ++ { ++ case GSM_CLIENT_RESTART_IF_RUNNING: ++ status = NULL; ++ break; ++ ++ case GSM_CLIENT_RESTART_ANYWAY: ++ status = GTK_STOCK_PREFERENCES; ++ break; ++ ++ case GSM_CLIENT_RESTART_IMMEDIATELY: ++ status = GTK_STOCK_REFRESH; ++ break; ++ ++ case GSM_CLIENT_RESTART_NEVER: ++ status = GTK_STOCK_DELETE; ++ break; ++ ++ default: ++ status = NULL; ++ break; ++ } ++ ++ return status; ++} ++ ++typedef enum { ++ GSM_CLIENT_UNREGISTERED = 0, ++ GSM_CLIENT_REGISTERED, ++ GSM_CLIENT_FINISHED, ++ GSM_CLIENT_FAILED, ++} GsmClientStatus; ++ ++static const char* ++format_session_state (guint state) ++{ ++ const char *status; ++ ++ switch (state) ++ { ++ case GSM_CLIENT_UNREGISTERED: ++ status = NULL; ++ break; ++ ++ case GSM_CLIENT_REGISTERED: ++ status = GTK_STOCK_EXECUTE; ++ break; ++ ++ case GSM_CLIENT_FINISHED: ++ status = GTK_STOCK_QUIT; ++ break; ++ ++ case GSM_CLIENT_FAILED: ++ status = GTK_STOCK_HELP; ++ break; ++ ++ default: ++ status = NULL; ++ break; ++ } ++ ++ return status; ++} + + static char * + mnemonic_safe_process_name(const char *process_name) +@@ -441,6 +515,58 @@ + g_object_set(renderer, "text", str, NULL); + } + ++ void restart_style_cell_data_func(GtkTreeViewColumn *, GtkCellRenderer *renderer, ++ GtkTreeModel *model, GtkTreeIter *iter, ++ gpointer user_data) ++ { ++ const guint index = GPOINTER_TO_UINT(user_data); ++ ++ guint state; ++ GValue value = { 0 }; ++ ++ gtk_tree_model_get_value(model, iter, index, &value); ++ ++ switch (G_VALUE_TYPE(&value)) { ++ case G_TYPE_UINT: ++ state = g_value_get_uint(&value); ++ break; ++ ++ default: ++ g_assert_not_reached(); ++ } ++ ++ g_value_unset(&value); ++ ++ const char *str = format_restart_style(state); ++ g_object_set(renderer, "icon-name", str, NULL); ++ } ++ ++ void session_state_cell_data_func(GtkTreeViewColumn *, GtkCellRenderer *renderer, ++ GtkTreeModel *model, GtkTreeIter *iter, ++ gpointer user_data) ++ { ++ const guint index = GPOINTER_TO_UINT(user_data); ++ ++ guint state; ++ GValue value = { 0 }; ++ ++ gtk_tree_model_get_value(model, iter, index, &value); ++ ++ switch (G_VALUE_TYPE(&value)) { ++ case G_TYPE_UINT: ++ state = g_value_get_uint(&value); ++ break; ++ ++ default: ++ g_assert_not_reached(); ++ } ++ ++ g_value_unset(&value); ++ ++ const char *str = format_session_state(state); ++ g_object_set(renderer, "icon-name", str, NULL); ++ } ++ + + template<> + void tree_store_update(GtkTreeModel* model, GtkTreeIter* iter, int column, const char* new_value) +--- /dev/null 2008-08-07 10:02:05.591005357 -0400 ++++ hacked/src/gsm-session-manager.h 2008-08-07 14:18:33.000000000 -0400 +@@ -0,0 +1,76 @@ ++/* gsm-session-manager.h - functions for monitoring the session ++ * ++ * Copyright (C) 2008 Red Hat, Inc ++ * Author: Matthias Clasen ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++#ifndef GSM_SESSION_MANAGER_H ++#define GSM_SESSION_MANAGER_H ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define GSM_TYPE_SESSION_MANAGER (gsm_session_manager_get_type ()) ++#define GSM_SESSION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SESSION_MANAGER, GsmSessionManager)) ++#define GSM_SESSION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SESSION_MANAGER, GsmSessionManagerClass)) ++#define GSM_IS_SESSION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SESSION_MANAGER)) ++#define GSM_IS_SESSION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SESSION_MANAGER)) ++#define GSM_SESSION_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_SESSION_MANAGER, GsmSessionManagerClass)) ++ ++typedef struct _GsmSessionManager GsmSessionManager; ++typedef struct _GsmSessionManagerClass GsmSessionManagerClass; ++typedef struct _GsmSessionManagerPrivate GsmSessionManagerPrivate; ++ ++struct _GsmSessionManager { ++ GObject parent_instance; ++ ++ GsmSessionManagerPrivate *priv; ++}; ++ ++struct _GsmSessionManagerClass { ++ GObjectClass parent_class; ++ ++ /* signals */ ++ void (* client_added) (GsmSessionManager *manager, ++ const char *obj_path); ++ void (*client_removed) (GsmSessionManager *manager, ++ const char *obj_path); ++}; ++ ++typedef void (*GsmClientDetailsCallback) (const char *obj_path, ++ guint pid, ++ guint status, ++ guint restart_style_hint, ++ gpointer data); ++ ++GType gsm_session_manager_get_type (void); ++ ++GsmSessionManager *gsm_session_manager_new (void) G_GNUC_MALLOC; ++GsmSessionManager *gsm_session_manager_get (void); ++void gsm_session_manager_foreach (GsmSessionManager *manager, ++ GsmClientDetailsCallback callbac, ++ gpointer data); ++gboolean gsm_session_manager_get_details (GsmSessionManager *manager, ++ const char *obj_path, ++ guint *pid, ++ guint *status, ++ guint *restart_style); ++ ++G_END_DECLS ++ ++#endif /* GSM_SESSION_MANAGER_H */ +--- /dev/null 2008-08-07 10:02:05.591005357 -0400 ++++ hacked/src/gsm-session-manager.c 2008-08-07 14:37:00.000000000 -0400 +@@ -0,0 +1,528 @@ ++/* gsm-session-manager.h - functions for monitoring the session ++ * ++ * Copyright (C) 2008 Red Hat, Inc ++ * Author: Matthias Clasen ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++#include ++#include ++#include ++ ++struct _GsmSessionManagerPrivate ++{ ++ DBusGConnection *dbus_connection; ++ DBusGProxy *bus_proxy; ++ DBusGProxy *sm_proxy; ++ guint is_connected :1; ++ ++ GHashTable *clients; ++}; ++ ++static void gsm_session_manager_finalize (GObject *object); ++static void gsm_session_manager_class_install_signals (GsmSessionManagerClass *manager_class); ++ ++static void gsm_session_manager_class_install_properties (GsmSessionManagerClass *manager_class); ++ ++static void gsm_session_manager_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec); ++ ++static gboolean ensure_connection (GsmSessionManager *manager, ++ GError **error); ++static void get_all_clients (GsmSessionManager *manager); ++ ++enum { ++ PROP_0 = 0, ++ PROP_IS_CONNECTED ++}; ++ ++enum { ++ CLIENT_ADDED = 0, ++ CLIENT_REMOVED, ++ LAST_SIGNAL ++}; ++ ++static guint signals[LAST_SIGNAL]; ++ ++G_DEFINE_TYPE (GsmSessionManager, gsm_session_manager, G_TYPE_OBJECT); ++ ++static void ++gsm_session_manager_class_init (GsmSessionManagerClass *manager_class) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (manager_class); ++ ++ object_class->finalize = gsm_session_manager_finalize; ++ ++ gsm_session_manager_class_install_properties (manager_class); ++ gsm_session_manager_class_install_signals (manager_class); ++ ++ g_type_class_add_private (manager_class, ++ sizeof (GsmSessionManagerPrivate)); ++} ++ ++static void ++gsm_session_manager_class_install_signals (GsmSessionManagerClass *manager_class) ++{ ++ GObjectClass *object_class; ++ ++ object_class = G_OBJECT_CLASS (manager_class); ++ ++ signals[CLIENT_ADDED] = ++ g_signal_new ("client-added", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GsmSessionManagerClass, client_added), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, 1, G_TYPE_STRING); ++ signals[CLIENT_REMOVED] = ++ g_signal_new ("client-removed", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GsmSessionManagerClass, client_removed), ++ NULL, NULL, ++ g_cclosure_marshal_VOID__STRING, ++ G_TYPE_NONE, 1, G_TYPE_STRING); ++} ++ ++static void ++gsm_session_manager_class_install_properties (GsmSessionManagerClass *manager_class) ++{ ++ GObjectClass *object_class; ++ GParamSpec *param_spec; ++ ++ object_class = G_OBJECT_CLASS (manager_class); ++ object_class->get_property = gsm_session_manager_get_property; ++ ++ param_spec = g_param_spec_boolean ("is-connected", ++ "Is connected", ++ "Whether we are connected to " ++ "the session manager", ++ FALSE, ++ G_PARAM_READABLE); ++ ++ g_object_class_install_property (object_class, PROP_IS_CONNECTED, ++ param_spec); ++} ++ ++static void ++on_name_owner_changed (DBusGProxy *bus_proxy, ++ const char *name, ++ const char *prev_owner, ++ const char *new_owner, ++ GsmSessionManager *manager) ++{ ++ if (strcmp (name, "org.gnome.SessionManager") != 0) { ++ return; ++ } ++ ++ if (manager->priv->sm_proxy != NULL) { ++ g_object_unref (manager->priv->sm_proxy); ++ manager->priv->sm_proxy = NULL; ++ } ++ ++ g_hash_table_remove_all (manager->priv->clients); ++ ++ if (ensure_connection (manager, NULL)) ++ get_all_clients (manager); ++} ++ ++ ++static void ++get_client_details (GsmSessionManager *manager, ++ const char *obj_path, ++ GsmClientDetailsCallback callback, ++ gpointer data) ++{ ++ DBusGProxy *proxy; ++ GError *error = NULL; ++ gboolean ret; ++ guint status; ++ guint restart_style_hint; ++ guint pid; ++ ++ proxy = dbus_g_proxy_new_for_name (manager->priv->dbus_connection, ++ "org.gnome.SessionManager", ++ obj_path, ++ "org.gnome.SessionManager.Client"); ++ ++ ret = dbus_g_proxy_call (proxy, "GetUnixProcessId", &error, ++ G_TYPE_INVALID, ++ G_TYPE_UINT, &pid, ++ G_TYPE_INVALID); ++ if (error) { ++ g_warning ("ERROR: %s\n", error->message); ++ g_error_free (error); ++ goto cleanup; ++ } ++ if (!ret) { ++ g_warning ("GetUnixProcessId failed\n"); ++ goto cleanup; ++ } ++ ++ ret = dbus_g_proxy_call (proxy, "GetStatus", &error, ++ G_TYPE_INVALID, ++ G_TYPE_UINT, &status, ++ G_TYPE_INVALID); ++ if (error) { ++ g_warning ("ERROR: %s\n", error->message); ++ g_error_free (error); ++ goto cleanup; ++ } ++ if (!ret) { ++ g_warning ("GetStatus failed\n"); ++ goto cleanup; ++ } ++ ++ ret = dbus_g_proxy_call (proxy, "GetRestartStyleHint", &error, ++ G_TYPE_INVALID, ++ G_TYPE_UINT, &restart_style_hint, ++ G_TYPE_INVALID); ++ if (error) { ++ g_warning ("ERROR: %s\n", error->message); ++ g_error_free (error); ++ goto cleanup; ++ } ++ if (!ret) { ++ g_warning ("GetRestartStyleHint failed\n"); ++ goto cleanup; ++ } ++ ++ callback (obj_path, pid, status, restart_style_hint, data); ++ ++cleanup: ++ g_object_unref (proxy); ++} ++ ++ ++typedef struct { ++ guint pid; ++ guint status; ++ guint restart_style_hint; ++} ClientDetails; ++ ++void ++gsm_session_manager_foreach (GsmSessionManager *manager, ++ GsmClientDetailsCallback callback, ++ gpointer data) ++{ ++ GHashTableIter iter; ++ gchar *key; ++ ClientDetails *value; ++ ++ g_hash_table_iter_init (&iter, manager->priv->clients); ++ while (g_hash_table_iter_next (&iter,(gpointer *)&key, (gpointer *)&value)) { ++ callback (key, value->pid, value->status, value->restart_style_hint, data); ++ } ++} ++ ++static void ++add_client (const char *obj_path, ++ guint pid, ++ guint status, ++ guint restart_style_hint, ++ gpointer data) ++{ ++ GsmSessionManager *manager = data; ++ ++ ClientDetails *details; ++ ++ details = g_new (ClientDetails, 1); ++ details->pid = pid; ++ details->status = status; ++ details->restart_style_hint = restart_style_hint; ++ ++ g_hash_table_insert (manager->priv->clients, ++ g_strdup (obj_path), ++ details); ++} ++ ++static void ++get_all_clients (GsmSessionManager *manager) ++{ ++ GError *error = NULL; ++ GPtrArray *array; ++ gboolean ret; ++ gchar *obj_path; ++ guint i; ++ ++ ret = dbus_g_proxy_call (manager->priv->sm_proxy, ++ "GetClients", &error, ++ G_TYPE_INVALID, ++ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &array, ++ G_TYPE_INVALID); ++ ++ if (error) { ++ g_warning ("ERROR: %s\n", error->message); ++ g_error_free (error); ++ return; ++ } ++ if (!ret) { ++ g_warning ("GetClients failed\n"); ++ } ++ ++ for (i = 0; i < array->len; i++) { ++ obj_path = g_ptr_array_index (array, i); ++ get_client_details (manager, obj_path, add_client, manager); ++ } ++ ++ g_ptr_array_foreach (array, (GFunc)g_free, NULL); ++ g_ptr_array_free (array, TRUE); ++} ++ ++ ++ ++static void ++on_client_added (DBusGProxy *sm_proxy, ++ const gchar *obj_path, ++ GsmSessionManager *manager) ++{ ++ get_client_details (manager, obj_path, add_client, manager); ++ ++ g_signal_emit (manager, signals[CLIENT_ADDED], 0, obj_path); ++} ++ ++static void ++on_client_removed (DBusGProxy *sm_proxy, ++ const char *obj_path, ++ GsmSessionManager *manager) ++{ ++ g_signal_emit (manager, signals[CLIENT_REMOVED], 0, obj_path); ++ ++ g_hash_table_remove (manager->priv->clients, obj_path); ++} ++ ++static gboolean ++ensure_connection (GsmSessionManager *manager, ++ GError **error) ++{ ++ GError *connection_error; ++ gboolean is_connected; ++ ++ connection_error = NULL; ++ if (manager->priv->dbus_connection == NULL) { ++ manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SESSION, ++ &connection_error); ++ ++ if (manager->priv->dbus_connection == NULL) { ++ g_propagate_error (error, connection_error); ++ is_connected = FALSE; ++ goto out; ++ } ++ } ++ if (manager->priv->bus_proxy == NULL) { ++ manager->priv->bus_proxy = ++ dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection, ++ DBUS_SERVICE_DBUS, ++ DBUS_PATH_DBUS, ++ DBUS_INTERFACE_DBUS, ++ &connection_error); ++ ++ if (manager->priv->bus_proxy == NULL) { ++ g_propagate_error (error, connection_error); ++ is_connected = FALSE; ++ goto out; ++ } ++ ++ dbus_g_proxy_add_signal (manager->priv->bus_proxy, ++ "NameOwnerChanged", ++ G_TYPE_STRING, ++ G_TYPE_STRING, ++ G_TYPE_STRING, ++ G_TYPE_INVALID); ++ dbus_g_proxy_connect_signal (manager->priv->bus_proxy, ++ "NameOwnerChanged", ++ G_CALLBACK (on_name_owner_changed), ++ manager, NULL); ++ } ++ ++ if (manager->priv->sm_proxy == NULL) { ++ manager->priv->sm_proxy = ++ dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection, ++ "org.gnome.SessionManager", ++ "/org/gnome/SessionManager", ++ "org.gnome.SessionManager", ++ &connection_error); ++ ++ if (manager->priv->sm_proxy == NULL) { ++ g_propagate_error (error, connection_error); ++ is_connected = FALSE; ++ goto out; ++ } ++ ++ dbus_g_proxy_add_signal (manager->priv->sm_proxy, ++ "ClientAdded", ++ DBUS_TYPE_G_OBJECT_PATH, ++ G_TYPE_INVALID); ++ dbus_g_proxy_connect_signal (manager->priv->sm_proxy, ++ "ClientAdded", ++ G_CALLBACK (on_client_added), ++ manager, NULL); ++ ++ dbus_g_proxy_add_signal (manager->priv->sm_proxy, ++ "ClientRemoved", ++ DBUS_TYPE_G_OBJECT_PATH, ++ G_TYPE_INVALID); ++ dbus_g_proxy_connect_signal (manager->priv->sm_proxy, ++ "ClientRemoved", ++ G_CALLBACK (on_client_removed), ++ manager, NULL); ++ } ++ ++ is_connected = TRUE; ++ ++ out: ++ if (manager->priv->is_connected != is_connected) { ++ manager->priv->is_connected = is_connected; ++ g_object_notify (G_OBJECT (manager), "is-connected"); ++ } ++ ++ if (!is_connected) { ++ if (manager->priv->dbus_connection == NULL) { ++ if (manager->priv->bus_proxy != NULL) { ++ g_object_unref (manager->priv->bus_proxy); ++ manager->priv->bus_proxy = NULL; ++ } ++ ++ if (manager->priv->sm_proxy != NULL) { ++ g_object_unref (manager->priv->sm_proxy); ++ manager->priv->sm_proxy = NULL; ++ } ++ } else if (manager->priv->bus_proxy == NULL) { ++ if (manager->priv->sm_proxy != NULL) { ++ g_object_unref (manager->priv->sm_proxy); ++ manager->priv->sm_proxy = NULL; ++ } ++ } ++ } ++ ++ return is_connected; ++} ++ ++ ++static void ++gsm_session_manager_init (GsmSessionManager *manager) ++{ ++ GError *error; ++ ++ manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, GSM_TYPE_SESSION_MANAGER, ++ GsmSessionManagerPrivate); ++ ++ manager->priv->dbus_connection = NULL; ++ manager->priv->bus_proxy = NULL; ++ manager->priv->sm_proxy = NULL; ++ manager->priv->is_connected = FALSE; ++ ++ manager->priv->clients = g_hash_table_new_full (g_str_hash, g_str_equal, ++ g_free, g_free); ++ error = NULL; ++ ++ if (ensure_connection (manager, &error)) { ++ get_all_clients (manager); ++ } ++ else { ++ g_message ("Could not connect to session manager: %s", ++ error->message); ++ g_error_free (error); ++ } ++} ++ ++static void ++gsm_session_manager_finalize (GObject *object) ++{ ++ GsmSessionManager *manager; ++ GObjectClass *parent_class; ++ ++ manager = GSM_SESSION_MANAGER (object); ++ ++ g_hash_table_destroy (manager->priv->clients); ++ ++ parent_class = G_OBJECT_CLASS (gsm_session_manager_parent_class); ++ ++ if (parent_class->finalize != NULL) { ++ parent_class->finalize (object); ++ } ++} ++ ++static void ++gsm_session_manager_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ GsmSessionManager *manager = GSM_SESSION_MANAGER (object); ++ ++ switch (prop_id) { ++ case PROP_IS_CONNECTED: ++ g_value_set_boolean (value, ++ manager->priv->is_connected); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, ++ prop_id, ++ pspec); ++ } ++} ++ ++GsmSessionManager * ++gsm_session_manager_new (void) ++{ ++ GsmSessionManager *manager; ++ ++ manager = g_object_new (GSM_TYPE_SESSION_MANAGER, NULL); ++ ++ return manager; ++} ++ ++GsmSessionManager * ++gsm_session_manager_get (void) ++{ ++ static GsmSessionManager *manager = NULL; ++ ++ if (manager == NULL) { ++ manager = gsm_session_manager_new (); ++ } ++ ++ return g_object_ref (manager); ++} ++ ++gboolean ++gsm_session_manager_get_details (GsmSessionManager *manager, ++ const char *obj_path, ++ guint *pid, ++ guint *status, ++ guint *restart_style_hint) ++{ ++ ClientDetails *details; ++ ++ details = (ClientDetails *)g_hash_table_lookup (manager->priv->clients, obj_path); ++ ++ if (details) { ++ *pid = details->pid; ++ *status = details->status; ++ *restart_style_hint = details->restart_style_hint; ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ +--- gnome-system-monitor-2.23.5/src/Makefile.am 2008-03-18 17:37:00.000000000 -0400 ++++ hacked/src/Makefile.am 2008-08-07 14:41:21.000000000 -0400 +@@ -33,7 +33,8 @@ + gconf-keys.cpp gconf-keys.h \ + iconthemewrapper.cpp iconthemewrapper.h \ + e_date.c e_date.h \ +- gsm_color_button.c gsm_color_button.h ++ gsm_color_button.c gsm_color_button.h \ ++ gsm-session-manager.c gsm-session-manager.h + + + gnome_system_monitor_LDADD = @PROCMAN_LIBS@ libbacon.la