From 57faf5b9e61fb137f3cd36f16bba097b9c715b91 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sat, 16 Apr 2016 18:57:50 -0700 Subject: [PATCH] menu-button: show process arguments in process list This parses the \0 out of the cmdline proc entry and makes them visible as both in the list of processes and as tooltips when hovered. --- lib/resources/ui/sp-process-model-row.ui | 11 +++++ lib/sp-process-model-item.c | 51 ++++++++++++++++++++++-- lib/sp-process-model-item.h | 15 +++---- lib/sp-process-model-row.c | 42 +++++++++++++++++++ 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/lib/resources/ui/sp-process-model-row.ui b/lib/resources/ui/sp-process-model-row.ui index 8f65dd8a..48a4c936 100644 --- a/lib/resources/ui/sp-process-model-row.ui +++ b/lib/resources/ui/sp-process-model-row.ui @@ -18,6 +18,17 @@ 0.0 + + + false + true + end + 0.0 + + + false diff --git a/lib/sp-process-model-item.c b/lib/sp-process-model-item.c index 7067dc61..73fe3c49 100644 --- a/lib/sp-process-model-item.c +++ b/lib/sp-process-model-item.c @@ -16,15 +16,18 @@ * along with this program. If not, see . */ +#include + #include "sp-process-model-item.h" #include "sp-proc-source.h" struct _SpProcessModelItem { - GObject parent_instance; - GPid pid; - gchar *command_line; - guint is_kernel : 1; + GObject parent_instance; + GPid pid; + gchar *command_line; /* Short version (first field) */ + gchar **argv; /* Long version (argv as a strv) */ + guint is_kernel : 1; }; G_DEFINE_TYPE (SpProcessModelItem, sp_process_model_item, G_TYPE_OBJECT) @@ -44,6 +47,7 @@ sp_process_model_item_finalize (GObject *object) SpProcessModelItem *self = (SpProcessModelItem *)object; g_clear_pointer (&self->command_line, g_free); + g_clear_pointer (&self->argv, g_strfreev); G_OBJECT_CLASS (sp_process_model_item_parent_class)->finalize (object); } @@ -189,3 +193,42 @@ sp_process_model_item_is_kernel (SpProcessModelItem *self) return self->is_kernel; } + +const gchar const * const * +sp_process_model_item_get_argv (SpProcessModelItem *self) +{ + g_autofree gchar *contents = NULL; + g_autofree gchar *path = NULL; + const gchar *pos; + const gchar *endptr; + GPtrArray *ar; + gsize size = 0; + GPid pid; + + g_return_val_if_fail (SP_IS_PROCESS_MODEL_ITEM (self), NULL); + + if (self->argv) + return (const gchar * const *)self->argv; + + if ((pid = sp_process_model_item_get_pid (self)) < 0) + return NULL; + + path = g_strdup_printf ("/proc/%u/cmdline", (guint)pid); + if (!g_file_get_contents (path, &contents, &size, NULL)) + return NULL; + + ar = g_ptr_array_new (); + + /* Each parameter is followed by \0 */ + for (pos = contents, endptr = contents + size; + pos < endptr; + pos += strlen (pos) + 1) + g_ptr_array_add (ar, g_strdup (pos)); + g_ptr_array_add (ar, NULL); + + g_clear_pointer (&self->argv, g_strfreev); + self->argv = (gchar **)g_ptr_array_free (ar, FALSE); + + return (const gchar * const *)self->argv; +} + diff --git a/lib/sp-process-model-item.h b/lib/sp-process-model-item.h index 850a741a..3db0dfaf 100644 --- a/lib/sp-process-model-item.h +++ b/lib/sp-process-model-item.h @@ -27,13 +27,14 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (SpProcessModelItem, sp_process_model_item, SP, PROCESS_MODEL_ITEM, GObject) -SpProcessModelItem *sp_process_model_item_new (GPid pid); -guint sp_process_model_item_hash (SpProcessModelItem *self); -gboolean sp_process_model_item_equal (SpProcessModelItem *self, - SpProcessModelItem *other); -GPid sp_process_model_item_get_pid (SpProcessModelItem *self); -const gchar *sp_process_model_item_get_command_line (SpProcessModelItem *self); -gboolean sp_process_model_item_is_kernel (SpProcessModelItem *self); +SpProcessModelItem *sp_process_model_item_new (GPid pid); +guint sp_process_model_item_hash (SpProcessModelItem *self); +gboolean sp_process_model_item_equal (SpProcessModelItem *self, + SpProcessModelItem *other); +GPid sp_process_model_item_get_pid (SpProcessModelItem *self); +const gchar *sp_process_model_item_get_command_line (SpProcessModelItem *self); +gboolean sp_process_model_item_is_kernel (SpProcessModelItem *self); +const gchar * const *sp_process_model_item_get_argv (SpProcessModelItem *self); G_END_DECLS diff --git a/lib/sp-process-model-row.c b/lib/sp-process-model-row.c index b8e6e77b..a5b005f3 100644 --- a/lib/sp-process-model-row.c +++ b/lib/sp-process-model-row.c @@ -22,6 +22,7 @@ typedef struct { SpProcessModelItem *item; + GtkLabel *args_label; GtkLabel *label; GtkLabel *pid; GtkImage *image; @@ -71,12 +72,20 @@ sp_process_model_row_set_item (SpProcessModelRow *self, const gchar *command_line; g_auto(GStrv) parts = NULL; g_autofree gchar *pidstr = NULL; + const gchar * const *argv; GPid pid; command_line = sp_process_model_item_get_command_line (item); parts = g_strsplit (command_line ?: "", "\n", 0); gtk_label_set_label (priv->label, parts [0]); + if ((NULL != (argv = sp_process_model_item_get_argv (item))) && (argv[0] != NULL)) + { + g_autofree gchar *argvstr = g_strjoinv (" ", (gchar **)&argv[1]); + + gtk_label_set_label (priv->args_label, argvstr); + } + pid = sp_process_model_item_get_pid (item); pidstr = g_strdup_printf ("%u", pid); gtk_label_set_label (priv->pid, pidstr); @@ -111,6 +120,34 @@ sp_process_model_row_set_selected (SpProcessModelRow *self, } } +static gboolean +sp_process_model_row_query_tooltip (GtkWidget *widget, + gint x, + gint y, + gboolean keyboard_mode, + GtkTooltip *tooltip) +{ + SpProcessModelRow *self = (SpProcessModelRow *)widget; + SpProcessModelRowPrivate *priv = sp_process_model_row_get_instance_private (self); + + g_assert (SP_IS_PROCESS_MODEL_ROW (self)); + g_assert (GTK_IS_TOOLTIP (tooltip)); + + if (priv->item != NULL) + { + const gchar * const *argv = sp_process_model_item_get_argv (priv->item); + + if (argv != NULL) + { + g_autofree gchar *str = g_strjoinv (" ", (gchar **)argv); + gtk_tooltip_set_text (tooltip, str); + return TRUE; + } + } + + return FALSE; +} + static void sp_process_model_row_finalize (GObject *object) { @@ -178,6 +215,8 @@ sp_process_model_row_class_init (SpProcessModelRowClass *klass) object_class->get_property = sp_process_model_row_get_property; object_class->set_property = sp_process_model_row_set_property; + widget_class->query_tooltip = sp_process_model_row_query_tooltip; + properties [PROP_ITEM] = g_param_spec_object ("item", "Item", @@ -196,6 +235,7 @@ sp_process_model_row_class_init (SpProcessModelRowClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sp-process-model-row.ui"); + gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, args_label); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, image); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, label); gtk_widget_class_bind_template_child_private (widget_class, SpProcessModelRow, pid); @@ -206,4 +246,6 @@ static void sp_process_model_row_init (SpProcessModelRow *self) { gtk_widget_init_template (GTK_WIDGET (self)); + + gtk_widget_set_has_tooltip (GTK_WIDGET (self), TRUE); }