Context menu for sending signals and setting priorities
Base signals and priorities are defined inside the task-manager.h file to be reused as general values inside the interface. The different OS implementations have to do the conversion from the enumeration to real values.
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "process-tree-view.h"
|
#include "process-tree-view.h"
|
||||||
|
#include "task-manager.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -34,9 +35,9 @@ struct _XtmProcessTreeView
|
|||||||
};
|
};
|
||||||
G_DEFINE_TYPE (XtmProcessTreeView, xtm_process_tree_view, GTK_TYPE_TREE_VIEW)
|
G_DEFINE_TYPE (XtmProcessTreeView, xtm_process_tree_view, GTK_TYPE_TREE_VIEW)
|
||||||
|
|
||||||
static gboolean treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event);
|
static gboolean treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event);
|
||||||
static void settings_changed (GObject *object, GParamSpec *pspec, XtmProcessTreeView *treeview);
|
static void settings_changed (GObject *object, GParamSpec *pspec, XtmProcessTreeView *treeview);
|
||||||
static int sort_by_string (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data);
|
static int sort_by_string (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -136,13 +137,144 @@ xtm_process_tree_view_init (XtmProcessTreeView *treeview)
|
|||||||
* Helper functions
|
* Helper functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_send_signal (GtkMenuItem *mi, gpointer user_data)
|
||||||
|
{
|
||||||
|
guint pid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (mi), "pid"));
|
||||||
|
gint signal = GPOINTER_TO_INT (user_data);
|
||||||
|
|
||||||
|
if (!send_signal_to_pid (pid, signal))
|
||||||
|
{
|
||||||
|
GtkWidget *dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
|
||||||
|
_("Error sending signal"));
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("An error was encountered by sending a signal to the PID %d. "
|
||||||
|
"It is likely you don't have the required privileges."), pid);
|
||||||
|
gtk_window_set_title (GTK_WINDOW (dialog), _("Task Manager"));
|
||||||
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cb_set_priority (GtkMenuItem *mi, gpointer user_data)
|
||||||
|
{
|
||||||
|
guint pid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (mi), "pid"));
|
||||||
|
gint priority = GPOINTER_TO_INT (user_data);
|
||||||
|
|
||||||
|
if (!set_priority_to_pid (pid, priority))
|
||||||
|
{
|
||||||
|
GtkWidget *dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
|
||||||
|
_("Error setting priority"));
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("An error was encountered by setting a priority to the PID %d. "
|
||||||
|
"It is likely you don't have the required privileges."), pid);
|
||||||
|
gtk_window_set_title (GTK_WINDOW (dialog), _("Task Manager"));
|
||||||
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget *
|
||||||
|
build_context_menu (guint pid)
|
||||||
|
{
|
||||||
|
GtkWidget *menu, *menu_priority, *mi;
|
||||||
|
|
||||||
|
menu = gtk_menu_new ();
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Terminate"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_send_signal), GINT_TO_POINTER (XTM_SIGNAL_TERMINATE));
|
||||||
|
|
||||||
|
// TODO look up task for building menu with either Stop or Continue and in an OS-independent way
|
||||||
|
// if (pid_is_sleeping (pid))
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Stop"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_send_signal), GINT_TO_POINTER (XTM_SIGNAL_STOP));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Continue"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_send_signal), GINT_TO_POINTER (XTM_SIGNAL_CONTINUE));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Kill"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_send_signal), GINT_TO_POINTER (XTM_SIGNAL_KILL));
|
||||||
|
|
||||||
|
menu_priority = gtk_menu_new ();
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Very low"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu_priority), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_set_priority), GINT_TO_POINTER (XTM_PRIORITY_VERY_LOW));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Low"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu_priority), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_set_priority), GINT_TO_POINTER (XTM_PRIORITY_LOW));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Normal"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu_priority), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_set_priority), GINT_TO_POINTER (XTM_PRIORITY_NORMAL));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("High"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu_priority), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_set_priority), GINT_TO_POINTER (XTM_PRIORITY_HIGH));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Very high"));
|
||||||
|
g_object_set_data (G_OBJECT (mi), "pid", GUINT_TO_POINTER (pid));
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu_priority), mi);
|
||||||
|
g_signal_connect (mi, "activate", G_CALLBACK (cb_set_priority), GINT_TO_POINTER (XTM_PRIORITY_VERY_HIGH));
|
||||||
|
|
||||||
|
mi = gtk_menu_item_new_with_label (_("Priority"));
|
||||||
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu_priority);
|
||||||
|
gtk_container_add (GTK_CONTAINER (menu), mi);
|
||||||
|
|
||||||
|
gtk_widget_show_all (menu);
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event)
|
treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event)
|
||||||
{
|
{
|
||||||
|
static GtkWidget *menu = NULL;
|
||||||
|
guint pid;
|
||||||
|
|
||||||
if (event->button != 3)
|
if (event->button != 3)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_debug ("popup menu");
|
if (menu != NULL)
|
||||||
|
gtk_widget_destroy (menu);
|
||||||
|
|
||||||
|
{
|
||||||
|
GtkTreeModel *model;
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
GtkTreePath *path;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
model = GTK_TREE_MODEL (treeview->model);
|
||||||
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
||||||
|
gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (path == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_tree_model_get_iter (model, &iter, path);
|
||||||
|
gtk_tree_model_get (model, &iter, XTM_PTV_COLUMN_PID, &pid, -1);
|
||||||
|
gtk_tree_selection_select_path (selection, path);
|
||||||
|
gtk_tree_path_free (path);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
g_debug ("Found iter with pid %d", pid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = build_context_menu (pid);
|
||||||
|
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button, event->time);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
@@ -305,3 +307,64 @@ get_task_list (GArray *task_list)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
pid_is_sleeping (guint pid)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
send_signal_to_pid (guint pid, gint signal)
|
||||||
|
{
|
||||||
|
gint sig;
|
||||||
|
gint res;
|
||||||
|
switch (signal)
|
||||||
|
{
|
||||||
|
case XTM_SIGNAL_TERMINATE:
|
||||||
|
sig = SIGTERM;
|
||||||
|
break;
|
||||||
|
case XTM_SIGNAL_STOP:
|
||||||
|
sig = SIGSTOP;
|
||||||
|
break;
|
||||||
|
case XTM_SIGNAL_CONTINUE:
|
||||||
|
sig = SIGCONT;
|
||||||
|
break;
|
||||||
|
case XTM_SIGNAL_KILL:
|
||||||
|
sig = SIGKILL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
res = kill (pid, sig);
|
||||||
|
return (res == 0) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
set_priority_to_pid (guint pid, gint priority)
|
||||||
|
{
|
||||||
|
gint prio;
|
||||||
|
gint res;
|
||||||
|
switch (priority)
|
||||||
|
{
|
||||||
|
case XTM_PRIORITY_VERY_LOW:
|
||||||
|
prio = 15;
|
||||||
|
break;
|
||||||
|
case XTM_PRIORITY_LOW:
|
||||||
|
prio = 5;
|
||||||
|
break;
|
||||||
|
case XTM_PRIORITY_NORMAL:
|
||||||
|
prio = 0;
|
||||||
|
break;
|
||||||
|
case XTM_PRIORITY_HIGH:
|
||||||
|
prio = -5;
|
||||||
|
break;
|
||||||
|
case XTM_PRIORITY_VERY_HIGH:
|
||||||
|
prio = -15;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
res = setpriority (PRIO_PROCESS, pid, prio);
|
||||||
|
return (res == 0) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -352,13 +352,3 @@ xtm_task_manager_update_model (XtmTaskManager *manager)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
xtm_task_manager_send_signal_to_pid (XtmTaskManager *manager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xtm_task_manager_set_priority_to_pid (XtmTaskManager *manager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Task struct used as elements of a task list GArray.
|
* Task struct used as elements of a task list GArray.
|
||||||
@@ -37,6 +38,27 @@ struct _Task
|
|||||||
gshort prio;
|
gshort prio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerations of virtual values between the interface and the OS implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
XTM_SIGNAL_TERMINATE = 0,
|
||||||
|
XTM_SIGNAL_STOP,
|
||||||
|
XTM_SIGNAL_CONTINUE,
|
||||||
|
XTM_SIGNAL_KILL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
XTM_PRIORITY_VERY_LOW = 0,
|
||||||
|
XTM_PRIORITY_LOW,
|
||||||
|
XTM_PRIORITY_NORMAL,
|
||||||
|
XTM_PRIORITY_HIGH,
|
||||||
|
XTM_PRIORITY_VERY_HIGH,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OS specific implementation.
|
* OS specific implementation.
|
||||||
*/
|
*/
|
||||||
@@ -44,8 +66,9 @@ struct _Task
|
|||||||
gboolean get_memory_usage (guint64 *memory_total, guint64 *memory_free, guint64 *memory_cache, guint64 *memory_buffers, guint64 *swap_total, guint64 *swap_free);
|
gboolean get_memory_usage (guint64 *memory_total, guint64 *memory_free, guint64 *memory_cache, guint64 *memory_buffers, guint64 *swap_total, guint64 *swap_free);
|
||||||
gboolean get_cpu_usage (gushort *cpu_count, gfloat *cpu_user, gfloat *cpu_system);
|
gboolean get_cpu_usage (gushort *cpu_count, gfloat *cpu_user, gfloat *cpu_system);
|
||||||
gboolean get_task_list (GArray *task_list);
|
gboolean get_task_list (GArray *task_list);
|
||||||
//void send_signal_to_task (gint task_id, gint signal);
|
gboolean pid_is_sleeping (guint pid);
|
||||||
//void set_priority_to_task (gint task_id, gint prio);
|
gboolean send_signal_to_pid (guint pid, gint signal);
|
||||||
|
gboolean set_priority_to_pid (guint pid, gint priority);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GObject class used to update the graphical widgets.
|
* GObject class used to update the graphical widgets.
|
||||||
@@ -61,7 +84,7 @@ gboolean get_task_list (GArray *task_list);
|
|||||||
typedef struct _XtmTaskManager XtmTaskManager;
|
typedef struct _XtmTaskManager XtmTaskManager;
|
||||||
|
|
||||||
GType xtm_task_manager_get_type (void);
|
GType xtm_task_manager_get_type (void);
|
||||||
XtmTaskManager * xtm_task_manager_new ();
|
XtmTaskManager * xtm_task_manager_new (GtkTreeModel *model);
|
||||||
const gchar * xtm_task_manager_get_username (XtmTaskManager *manager);
|
const gchar * xtm_task_manager_get_username (XtmTaskManager *manager);
|
||||||
const gchar * xtm_task_manager_get_hostname (XtmTaskManager *manager);
|
const gchar * xtm_task_manager_get_hostname (XtmTaskManager *manager);
|
||||||
void xtm_task_manager_get_system_info (XtmTaskManager *manager, guint *num_processes, gfloat *cpu, gfloat *memory, gfloat *swap);
|
void xtm_task_manager_get_system_info (XtmTaskManager *manager, guint *num_processes, gfloat *cpu, gfloat *memory, gfloat *swap);
|
||||||
|
|||||||
Reference in New Issue
Block a user