summaryrefslogtreecommitdiff
path: root/multiload/src
diff options
context:
space:
mode:
Diffstat (limited to 'multiload/src')
-rw-r--r--multiload/src/Makefile.am59
-rw-r--r--multiload/src/autoscaler.c53
-rw-r--r--multiload/src/autoscaler.h22
-rw-r--r--multiload/src/global.h220
-rw-r--r--multiload/src/linux-proc.c430
-rw-r--r--multiload/src/linux-proc.h13
-rw-r--r--multiload/src/load-graph.c513
-rw-r--r--multiload/src/load-graph.h24
-rw-r--r--multiload/src/main.c584
-rw-r--r--multiload/src/netspeed.c64
-rw-r--r--multiload/src/netspeed.h15
-rw-r--r--multiload/src/properties.c686
12 files changed, 2683 insertions, 0 deletions
diff --git a/multiload/src/Makefile.am b/multiload/src/Makefile.am
new file mode 100644
index 00000000..6b42871f
--- /dev/null
+++ b/multiload/src/Makefile.am
@@ -0,0 +1,59 @@
+NULL =
+
+AM_CPPFLAGS = \
+ -I$(srcdir) \
+ -DMULTILOAD_RESOURCE_PATH=\""/org/mate/mate-applets/multiload/"\" \
+ $(MATE_APPLETS4_CFLAGS) \
+ $(GTOP_APPLETS_CFLAGS) \
+ $(GIO_CFLAGS) \
+ ${WARN_CFLAGS}
+
+BUILT_SOURCES = \
+ multiload-resources.c \
+ multiload-resources.h \
+ $(NULL)
+APPLET_SOURCES = \
+ global.h \
+ linux-proc.h \
+ load-graph.h \
+ linux-proc.c \
+ load-graph.c \
+ main.c \
+ properties.c \
+ netspeed.c netspeed.h \
+ autoscaler.c \
+ autoscaler.h \
+ $(NULL)
+
+APPLET_LIBS = \
+ $(MATE_APPLETS4_LIBS) \
+ $(GTOP_APPLETS_LIBS) \
+ $(GIO_LIBS) \
+ -lm
+
+if ENABLE_IN_PROCESS
+pkglib_LTLIBRARIES = libmate-multiload-applet.la
+nodist_libmate_multiload_applet_la_SOURCES = $(BUILT_SOURCES)
+libmate_multiload_applet_la_SOURCES = $(APPLET_SOURCES)
+libmate_multiload_applet_la_CFLAGS = $(AM_CFLAGS)
+libmate_multiload_applet_la_LDFLAGS = -module -avoid-version
+libmate_multiload_applet_la_LIBADD = $(APPLET_LIBS)
+else !ENABLE_IN_PROCESS
+libexec_PROGRAMS = mate-multiload-applet
+nodist_mate_multiload_applet_SOURCES = $(BUILT_SOURCES)
+mate_multiload_applet_SOURCES = $(APPLET_SOURCES)
+mate_multiload_applet_CFLAGS = $(AM_CFLAGS)
+mate_multiload_applet_LDADD = $(APPLET_LIBS)
+endif !ENABLE_IN_PROCESS
+
+multiload-resources.c: $(srcdir)/../data/multiload-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data --generate-dependencies $(srcdir)/../data/multiload-resources.gresource.xml)
+ $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data --generate --c-name multiload $<
+
+multiload-resources.h: $(srcdir)/../data/multiload-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data --generate-dependencies $(srcdir)/../data/multiload-resources.gresource.xml)
+ $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data --generate --c-name multiload $<
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/multiload/src/autoscaler.c b/multiload/src/autoscaler.c
new file mode 100644
index 00000000..fb03533f
--- /dev/null
+++ b/multiload/src/autoscaler.c
@@ -0,0 +1,53 @@
+#include <glib.h>
+
+#include "autoscaler.h"
+
+/* i wish i could have used C99 initializers instead of writing this function */
+void
+autoscaler_init (AutoScaler *that,
+ gint64 interval,
+ guint64 floor)
+{
+ that->update_interval = interval;
+ that->floor = floor;
+ that->max = 0;
+ that->count = 0;
+ that->last_update = 0;
+ that->sum = 0;
+ that->last_average = 0.0f;
+}
+
+guint64
+autoscaler_get_max (AutoScaler *that,
+ guint64 current)
+{
+ gint64 now;
+
+ that->sum += current;
+ that->count++;
+ now = g_get_monotonic_time ();
+
+ if ((now - that->last_update) > that->update_interval)
+ {
+ float new_average = (float) that->sum / (float) that->count;
+ float average;
+
+ if (new_average < that->last_average)
+ average = ((that->last_average * 0.5f) + new_average) / 1.5f;
+ else
+ average = new_average;
+
+ that->max = (guint64) (average * 1.2f);
+ that->sum = 0;
+ that->count = 0;
+ that->last_update = now;
+ that->last_average = average;
+ }
+
+ that->max = MAX(that->max, current);
+ that->max = MAX(that->max, that->floor);
+#if 0
+ printf("%p max = %u, current = %u, last_average = %f\n", that, that->max, current, that->last_average);
+#endif
+ return that->max;
+}
diff --git a/multiload/src/autoscaler.h b/multiload/src/autoscaler.h
new file mode 100644
index 00000000..ef4e0946
--- /dev/null
+++ b/multiload/src/autoscaler.h
@@ -0,0 +1,22 @@
+#ifndef MATE_APPLETS_MULTILOAD_AUTOSCALER_H
+#define MATE_APPLETS_MULTILOAD_AUTOSCALER_H
+
+#include <glib.h>
+
+typedef struct _AutoScaler AutoScaler;
+
+struct _AutoScaler
+{
+ gint64 update_interval;
+ gint64 last_update;
+ guint64 floor;
+ guint64 max;
+ guint64 count;
+ guint64 sum;
+ float last_average;
+};
+
+G_GNUC_INTERNAL void autoscaler_init (AutoScaler *that, gint64 interval, guint64 floor);
+G_GNUC_INTERNAL guint64 autoscaler_get_max (AutoScaler *that, guint64 current);
+
+#endif /* MATE_APPLETS_MULTILOAD_AUTOSCALER_H */
diff --git a/multiload/src/global.h b/multiload/src/global.h
new file mode 100644
index 00000000..f40f194a
--- /dev/null
+++ b/multiload/src/global.h
@@ -0,0 +1,220 @@
+#ifndef __GLOBAL_H__
+#define __GLOBAL_H__
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <mate-panel-applet.h>
+
+G_BEGIN_DECLS
+
+#define KEY_CPULOAD_USR_COLOR "cpuload-color0"
+#define KEY_CPULOAD_SYS_COLOR "cpuload-color1"
+#define KEY_CPULOAD_NICE_COLOR "cpuload-color2"
+#define KEY_CPULOAD_IOWAIT_COLOR "cpuload-color3"
+#define KEY_CPULOAD_IDLE_COLOR "cpuload-color4"
+#define KEY_MEMLOAD_USER_COLOR "memload-color0"
+#define KEY_MEMLOAD_SHARED_COLOR "memload-color1"
+#define KEY_MEMLOAD_BUFFER_COLOR "memload-color2"
+#define KEY_MEMLOAD_CACHED_COLOR "memload-color3"
+#define KEY_MEMLOAD_FREE_COLOR "memload-color4"
+#define KEY_NETLOAD2_IN_COLOR "netload2-color0"
+#define KEY_NETLOAD2_OUT_COLOR "netload2-color1"
+#define KEY_NETLOAD2_LOOPBACK_COLOR "netload2-color2"
+#define KEY_NETLOAD2_BACKGROUND_COLOR "netload2-color3"
+#define KEY_NETLOAD2_GRIDLINE_COLOR "netload2-color4"
+#define KEY_NETLOAD2_INDICATOR_COLOR "netload2-color5"
+#define KEY_SWAPLOAD_USED_COLOR "swapload-color0"
+#define KEY_SWAPLOAD_FREE_COLOR "swapload-color1"
+#define KEY_LOADAVG_AVERAGE_COLOR "loadavg-color0"
+#define KEY_LOADAVG_BACKGROUND_COLOR "loadavg-color1"
+#define KEY_LOADAVG_GRIDLINE_COLOR "loadavg-color2"
+#define KEY_DISKLOAD_READ_COLOR "diskload-color0"
+#define KEY_DISKLOAD_WRITE_COLOR "diskload-color1"
+#define KEY_DISKLOAD_FREE_COLOR "diskload-color2"
+
+#define KEY_NET_THRESHOLD1 "netthreshold1"
+#define KEY_NET_THRESHOLD2 "netthreshold2"
+#define KEY_NET_THRESHOLD3 "netthreshold3"
+#define MIN_NET_THRESHOLD1 10
+#define MIN_NET_THRESHOLD2 11
+#define MIN_NET_THRESHOLD3 12
+#define MAX_NET_THRESHOLD1 999999998
+#define MAX_NET_THRESHOLD2 999999999
+#define MAX_NET_THRESHOLD3 1000000000
+
+#define VIEW_CPULOAD_KEY "view-cpuload"
+#define VIEW_MEMLOAD_KEY "view-memload"
+#define VIEW_NETLOAD_KEY "view-netload"
+#define VIEW_SWAPLOAD_KEY "view-swapload"
+#define VIEW_LOADAVG_KEY "view-loadavg"
+#define VIEW_DISKLOAD_KEY "view-diskload"
+
+#define DISKLOAD_NVME_KEY "diskload-nvme-diskstats"
+
+#define REFRESH_RATE_KEY "speed"
+#define REFRESH_RATE_MIN 50
+#define REFRESH_RATE_MAX 60000
+
+#define GRAPH_SIZE_KEY "size"
+#define GRAPH_SIZE_MIN 10
+#define GRAPH_SIZE_MAX 1000
+
+typedef struct _MultiloadApplet MultiloadApplet;
+typedef struct _LoadGraph LoadGraph;
+typedef void (*LoadGraphDataFunc) (guint64, guint64 [], LoadGraph *);
+
+#include "netspeed.h"
+
+typedef enum {
+ graph_cpuload = 0,
+ graph_memload,
+ graph_netload2,
+ graph_swapload,
+ graph_loadavg,
+ graph_diskload,
+ graph_n,
+} E_graph;
+
+typedef enum {
+ cpuload_usr = 0,
+ cpuload_sys,
+ cpuload_nice,
+ cpuload_iowait,
+ cpuload_free,
+ cpuload_n
+} E_cpuload;
+
+typedef enum {
+ memload_user = 0,
+ memload_shared,
+ memload_buffer,
+ memload_cached,
+ memload_free,
+ memload_n
+} E_memload;
+
+typedef enum {
+ netload2_in = 0,
+ netload2_out,
+ netload2_loopback,
+ netload2_background,
+ netload2_gridline,
+ netload2_indicator,
+ netload2_n
+} E_netload2;
+
+typedef enum {
+ swapload_used = 0,
+ swapload_free,
+ swapload_n
+} E_swapload;
+
+typedef enum {
+ loadavg_average = 0,
+ loadavg_background,
+ loadavg_gridline,
+ loadavg_n
+} E_loadavg;
+
+typedef enum {
+ diskload_read = 0,
+ diskload_write,
+ diskload_free,
+ diskload_n
+} E_diskload;
+
+struct _LoadGraph {
+ MultiloadApplet *multiload;
+
+ guint n;
+ gint id;
+ guint speed, size;
+ guint orient, pixel_size;
+ gsize draw_width;
+ guint64 draw_height;
+ LoadGraphDataFunc get_data;
+
+ guint allocated;
+
+ GdkRGBA *colors;
+ guint64 **data;
+ guint64 *pos;
+
+ GtkWidget *main_widget;
+ GtkWidget *frame, *box, *disp;
+ cairo_surface_t *surface;
+ int timer_index;
+
+ gboolean visible;
+ gboolean tooltip_update;
+ const gchar *name;
+};
+
+struct _MultiloadApplet
+{
+ MatePanelApplet *applet;
+
+ GSettings *settings;
+
+ LoadGraph *graphs [graph_n];
+
+ GtkWidget *box;
+
+ gboolean view_cpuload;
+ gboolean view_memload;
+ gboolean view_netload;
+ gboolean view_swapload;
+ gboolean view_loadavg;
+ gboolean view_diskload;
+
+ GtkWidget *about_dialog;
+ GtkWidget *check_boxes [graph_n];
+ GtkWidget *prop_dialog;
+ GtkWidget *notebook;
+ gint last_clicked;
+
+ float cpu_used_ratio;
+ guint64 cpu_time [cpuload_n];
+ guint64 cpu_last [cpuload_n];
+ gboolean cpu_initialized;
+
+ double loadavg1;
+
+ guint64 memload_user;
+ guint64 memload_cache;
+ guint64 memload_total;
+
+ float swapload_used_ratio;
+
+ float diskload_used_ratio;
+ gboolean nvme_diskstats;
+
+ NetSpeed *netspeed_in;
+ NetSpeed *netspeed_out;
+ guint64 net_threshold1;
+ guint64 net_threshold2;
+ guint64 net_threshold3;
+};
+
+#include "load-graph.h"
+#include "linux-proc.h"
+
+/* show properties dialog */
+G_GNUC_INTERNAL void
+multiload_properties_cb (GtkAction *action,
+ MultiloadApplet *ma);
+
+/* remove the old graphs and rebuild them */
+G_GNUC_INTERNAL void
+multiload_applet_refresh (MultiloadApplet *ma);
+
+/* update the tooltip to the graph's current "used" percentage */
+G_GNUC_INTERNAL void
+multiload_applet_tooltip_update (LoadGraph *g);
+
+G_END_DECLS
+
+#endif
diff --git a/multiload/src/linux-proc.c b/multiload/src/linux-proc.c
new file mode 100644
index 00000000..f5549f67
--- /dev/null
+++ b/multiload/src/linux-proc.c
@@ -0,0 +1,430 @@
+/* From wmload.c, v0.9.2, licensed under the GPL. */
+#include <config.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <glibtop.h>
+#include <glibtop/cpu.h>
+#include <glibtop/mem.h>
+#include <glibtop/swap.h>
+#include <glibtop/loadavg.h>
+#include <glibtop/netload.h>
+#include <glibtop/netlist.h>
+#include <glibtop/mountlist.h>
+#include <glibtop/fsusage.h>
+
+#include "linux-proc.h"
+#include "autoscaler.h"
+
+static const unsigned needed_cpu_flags =
+(1 << GLIBTOP_CPU_USER) +
+(1 << GLIBTOP_CPU_IDLE) +
+(1 << GLIBTOP_CPU_SYS) +
+(1 << GLIBTOP_CPU_NICE);
+
+#if 0
+static const unsigned needed_page_flags =
+(1 << GLIBTOP_SWAP_PAGEIN) +
+(1 << GLIBTOP_SWAP_PAGEOUT);
+#endif
+
+static const unsigned needed_mem_flags =
+(1 << GLIBTOP_MEM_USED) +
+(1 << GLIBTOP_MEM_FREE);
+
+static const unsigned needed_swap_flags =
+(1 << GLIBTOP_SWAP_USED) +
+(1 << GLIBTOP_SWAP_FREE);
+
+static const unsigned needed_loadavg_flags =
+(1 << GLIBTOP_LOADAVG_LOADAVG);
+
+static const unsigned needed_netload_flags =
+(1 << GLIBTOP_NETLOAD_IF_FLAGS) +
+(1 << GLIBTOP_NETLOAD_BYTES_TOTAL);
+
+void
+GetLoad (guint64 Maximum,
+ guint64 data [cpuload_n],
+ LoadGraph *g)
+{
+ MultiloadApplet *multiload;
+ glibtop_cpu cpu;
+ guint64 cpu_aux [cpuload_n], used = 0, total = 0;
+ guint64 current_scaled, used_scaled = 0;
+ unsigned i;
+
+ glibtop_get_cpu (&cpu);
+
+ g_return_if_fail ((cpu.flags & needed_cpu_flags) == needed_cpu_flags);
+
+ multiload = g->multiload;
+
+ multiload->cpu_time [cpuload_usr] = cpu.user;
+ multiload->cpu_time [cpuload_nice] = cpu.nice;
+ multiload->cpu_time [cpuload_sys] = cpu.sys;
+ multiload->cpu_time [cpuload_iowait] = cpu.iowait + cpu.irq + cpu.softirq;
+ multiload->cpu_time [cpuload_free] = cpu.idle;
+
+ if (!multiload->cpu_initialized) {
+ memcpy (multiload->cpu_last, multiload->cpu_time, sizeof (multiload->cpu_last));
+ multiload->cpu_initialized = TRUE;
+ }
+
+ for (i = 0; i < cpuload_n; i++) {
+ cpu_aux [i] = multiload->cpu_time [i] - multiload->cpu_last [i];
+ total += cpu_aux [i];
+ }
+
+ for (i = 0; i < cpuload_free; i++) {
+ used += cpu_aux [i];
+ current_scaled = (guint64) ((float)(cpu_aux [i] * Maximum) / (float)total);
+ used_scaled += current_scaled;
+ data [i] = current_scaled;
+ }
+ data [cpuload_free] = Maximum - used_scaled;
+
+ multiload->cpu_used_ratio = (float)(used) / (float)total;
+
+ memcpy (multiload->cpu_last, multiload->cpu_time, sizeof multiload->cpu_last);
+}
+
+void
+GetDiskLoad (guint64 Maximum,
+ guint64 data [diskload_n],
+ LoadGraph *g)
+{
+ static gboolean first_call = TRUE;
+ static guint64 lastread = 0, lastwrite = 0;
+ static AutoScaler scaler;
+
+ guint64 max;
+ guint64 read, write;
+ guint64 readdiff, writediff;
+ guint i;
+
+ MultiloadApplet *multiload;
+
+ multiload = g->multiload;
+
+ if(first_call)
+ {
+ autoscaler_init (&scaler, g->speed, 500);
+ }
+
+ read = write = 0;
+
+ if (multiload->nvme_diskstats)
+ {
+ FILE *fdr;
+ char line[255];
+ guint64 s_read, s_write;
+
+ fdr = fopen("/proc/diskstats", "r");
+ if (!fdr)
+ {
+ multiload->nvme_diskstats = FALSE;
+ g_settings_set_boolean (multiload->settings, "diskload-nvme-diskstats", FALSE);
+ return;
+ }
+
+ while (fgets(line, 255, fdr))
+ {
+ /* Match main device, rather than individual partitions (e.g. nvme0n1) */
+ if (!g_regex_match_simple("\\snvme\\d+\\w+\\d+\\s", line, 0, 0))
+ {
+ continue;
+ }
+
+ /*
+ 6 - sectors read
+ 10 - sectors written
+ */
+ if (sscanf(line, "%*d %*d %*s %*d %*d %ld %*d %*d %*d %ld", &s_read, &s_write) == 2)
+ {
+ read += 512 * s_read;
+ write += 512 * s_write;
+ }
+ }
+ fclose(fdr);
+ }
+ else
+ {
+ glibtop_mountlist mountlist;
+ glibtop_mountentry *mountentries;
+
+ mountentries = glibtop_get_mountlist (&mountlist, FALSE);
+
+ for (i = 0; i < mountlist.number; i++)
+ {
+ struct statvfs statresult;
+ glibtop_fsusage fsusage;
+
+ if (strstr (mountentries[i].devname, "/dev/") == NULL)
+ continue;
+
+ if (strstr (mountentries[i].mountdir, "/media/") != NULL)
+ continue;
+
+ if (statvfs (mountentries[i].mountdir, &statresult) < 0)
+ {
+ g_debug ("Failed to get statistics for mount entry: %s. Reason: %s. Skipping entry.",
+ mountentries[i].mountdir, strerror(errno));
+ continue;
+ }
+
+ glibtop_get_fsusage(&fsusage, mountentries[i].mountdir);
+ read += fsusage.read;
+ write += fsusage.write;
+ }
+
+ g_free(mountentries);
+ }
+
+ readdiff = read - lastread;
+ writediff = write - lastwrite;
+
+ lastread = read;
+ lastwrite = write;
+
+ if(first_call)
+ {
+ first_call = FALSE;
+ memset(data, 0, 3 * sizeof data[0]);
+ return;
+ }
+
+ max = autoscaler_get_max(&scaler, readdiff + writediff);
+
+ multiload->diskload_used_ratio = (float)(readdiff + writediff) / (float)max;
+
+ data [diskload_read] = (guint64) ((float)Maximum * (float)readdiff / (float)max);
+ data [diskload_write] = (guint64) ((float)Maximum * (float)writediff / (float)max);
+ data [diskload_free] = Maximum - (data [0] + data[1]);
+}
+
+/* GNU/Linux:
+ * aux [memload_user] = (mem.total - mem.free) - (mem.cached + mem.buffer)
+ * aux [memload_shared] = mem.shared;
+ * aux [memload_cached] = mem.cached - mem.shared;
+ * aux [memload_buffer] = mem.buffer;
+ *
+ * Other operating systems:
+ * aux [memload_user] = mem.user;
+ * aux [memload_shared] = mem.shared;
+ * aux [memload_cached] = mem.cached;
+ * aux [memload_buffer] = mem.buffer;
+ */
+void
+GetMemory (guint64 Maximum,
+ guint64 data [memload_n],
+ LoadGraph *g)
+{
+ MultiloadApplet *multiload;
+ glibtop_mem mem;
+ guint64 aux [memload_n], cache = 0;
+ guint64 current_scaled, used_scaled = 0;
+ int i;
+
+ glibtop_get_mem (&mem);
+
+ g_return_if_fail ((mem.flags & needed_mem_flags) == needed_mem_flags);
+
+#ifndef __linux__
+ aux [memload_user] = mem.user;
+ aux [memload_cached] = mem.cached;
+#else
+ aux [memload_user] = mem.total - mem.free - mem.buffer - mem.cached;;
+ aux [memload_cached] = mem.cached - mem.shared;
+#endif /* __linux__ */
+ aux [memload_shared] = mem.shared;
+ aux [memload_buffer] = mem.buffer;
+
+ for (i = 0; i < memload_free; i++) {
+ current_scaled = (guint64) ((float)(aux [i] * Maximum) / (float)mem.total);
+ if (i != memload_user) {
+ cache += aux [i];
+ }
+ used_scaled += current_scaled;
+ data [i] = current_scaled;
+ }
+ data [memload_free] = MAX (Maximum - used_scaled, 0);
+
+ multiload = g->multiload;
+ multiload->memload_user = aux [memload_user];
+ multiload->memload_cache = cache;
+ multiload->memload_total = mem.total;
+}
+
+void
+GetSwap (guint64 Maximum,
+ guint64 data [swapload_n],
+ LoadGraph *g)
+{
+ guint64 used;
+ MultiloadApplet *multiload;
+ glibtop_swap swap;
+
+ glibtop_get_swap (&swap);
+ g_return_if_fail ((swap.flags & needed_swap_flags) == needed_swap_flags);
+
+ multiload = g->multiload;
+
+ if (swap.total == 0) {
+ used = 0;
+ multiload->swapload_used_ratio = 0.0f;
+ }
+ else {
+ float ratio;
+
+ ratio = (float)swap.used / (float)swap.total;
+ used = (guint64) ((float) Maximum * ratio);
+ multiload->swapload_used_ratio = ratio;
+ }
+
+ data [0] = used;
+ data [1] = Maximum - used;
+}
+
+void
+GetLoadAvg (guint64 Maximum,
+ guint64 data [2],
+ LoadGraph *g)
+{
+ glibtop_loadavg loadavg;
+ MultiloadApplet *multiload;
+
+ glibtop_get_loadavg (&loadavg);
+
+ g_return_if_fail ((loadavg.flags & needed_loadavg_flags) == needed_loadavg_flags);
+
+ multiload = g->multiload;
+ multiload->loadavg1 = loadavg.loadavg[0];
+
+ data [0] = (guint64) ((float) Maximum * loadavg.loadavg[0]);
+ data [1] = Maximum - data[0];
+}
+
+/*
+ * Return true if a network device (identified by its name) is virtual
+ * (ie: not corresponding to a physical device). In case it is a physical
+ * device or unknown, returns false.
+ */
+static gboolean
+is_net_device_virtual(char *device)
+{
+ /*
+ * There is not definitive way to find out. On some systems (Linux
+ * kernels ≳ 2.19 without option SYSFS_DEPRECATED), there exist a
+ * directory /sys/devices/virtual/net which only contains virtual
+ * devices. It's also possible to detect by the fact that virtual
+ * devices do not have a symlink "device" in
+ * /sys/class/net/name-of-dev/ . This second method is more complex
+ * but more reliable.
+ */
+ gboolean ret = FALSE;
+ char *path = malloc (strlen (device) + strlen ("/sys/class/net//device") + 1);
+
+ if (path == NULL)
+ return FALSE;
+
+ /* Check if /sys/class/net/name-of-dev/ exists (may be old linux kernel
+ * or not linux at all). */
+ do {
+ if (sprintf(path, "/sys/class/net/%s", device) < 0)
+ break;
+ if (access(path, F_OK) != 0)
+ break; /* unknown */
+
+ if (sprintf(path, "/sys/class/net/%s/device", device) < 0)
+ break;
+ if (access(path, F_OK) != 0)
+ ret = TRUE;
+ } while (0);
+
+ free (path);
+ return ret;
+}
+
+void
+GetNet (guint64 Maximum,
+ guint64 data [4],
+ LoadGraph *g)
+{
+ enum Types {
+ IN_COUNT = 0,
+ OUT_COUNT = 1,
+ LOCAL_COUNT = 2,
+ COUNT_TYPES = 3
+ };
+
+ static int ticks = 0;
+ static guint64 past[COUNT_TYPES] = {0};
+
+ guint64 present[COUNT_TYPES] = {0};
+
+ guint i;
+ gchar **devices;
+ glibtop_netlist netlist;
+
+ MultiloadApplet *multiload;
+
+ multiload = g->multiload;
+ devices = glibtop_get_netlist(&netlist);
+
+ for(i = 0; i < netlist.number; ++i)
+ {
+ glibtop_netload netload;
+
+ glibtop_get_netload(&netload, devices[i]);
+
+ g_return_if_fail((netload.flags & needed_netload_flags) == needed_netload_flags);
+
+ if (!(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_UP)))
+ continue;
+
+ if (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_LOOPBACK)) {
+ /* for loopback in and out are identical, so only count in */
+ present[LOCAL_COUNT] += netload.bytes_in;
+ continue;
+ }
+
+ /*
+ * Do not include virtual devices (VPN, PPPOE...) to avoid
+ * counting the same throughput several times.
+ */
+ if (is_net_device_virtual(devices[i]))
+ continue;
+
+ present[IN_COUNT] += netload.bytes_in;
+ present[OUT_COUNT] += netload.bytes_out;
+ }
+
+ g_strfreev(devices);
+ netspeed_add (multiload->netspeed_in, present[IN_COUNT]);
+ netspeed_add (multiload->netspeed_out, present[OUT_COUNT]);
+
+ if(ticks < 2) /* avoid initial spike */
+ {
+ ticks++;
+ memset(data, 0, (COUNT_TYPES + 1) * sizeof data[0]);
+ }
+ else
+ {
+ data[COUNT_TYPES] = 0;
+ float seconds = (float) g->speed / 1000.0f;
+ for (i = 0; i < COUNT_TYPES; i++)
+ {
+ /* protect against weirdness */
+ if (present[i] >= past[i])
+ data[i] = (guint) ((float) (present[i] - past[i]) / seconds);
+ else
+ data[i] = 0;
+ data[COUNT_TYPES] += data[i];
+ }
+ }
+
+ memcpy(past, present, sizeof past);
+}
diff --git a/multiload/src/linux-proc.h b/multiload/src/linux-proc.h
new file mode 100644
index 00000000..fb18ef59
--- /dev/null
+++ b/multiload/src/linux-proc.h
@@ -0,0 +1,13 @@
+#ifndef LINUX_PROC_H__
+#define LINUX_PROC_H__
+
+#include <load-graph.h>
+
+G_GNUC_INTERNAL void GetLoad (guint64 Maximum, guint64 data [cpuload_n], LoadGraph *g);
+G_GNUC_INTERNAL void GetDiskLoad (guint64 Maximum, guint64 data [diskload_n], LoadGraph *g);
+G_GNUC_INTERNAL void GetMemory (guint64 Maximum, guint64 data [memload_n], LoadGraph *g);
+G_GNUC_INTERNAL void GetSwap (guint64 Maximum, guint64 data [swapload_n], LoadGraph *g);
+G_GNUC_INTERNAL void GetLoadAvg (guint64 Maximum, guint64 data [2], LoadGraph *g);
+G_GNUC_INTERNAL void GetNet (guint64 Maximum, guint64 data [4], LoadGraph *g);
+
+#endif
diff --git a/multiload/src/load-graph.c b/multiload/src/load-graph.c
new file mode 100644
index 00000000..e8ca8bd3
--- /dev/null
+++ b/multiload/src/load-graph.c
@@ -0,0 +1,513 @@
+#include <config.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <glib.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-gsettings.h>
+#include <math.h>
+
+#include "global.h"
+
+/*
+ Shifts data right
+
+ data[i+1] = data[i]
+
+ data[i] are int*, so we just move the pointer, not the data.
+ But moving data loses data[n-1], so we save data[n-1] and reuse
+ it as new data[0]. In fact, we rotate data[].
+
+*/
+
+static void
+shift_right(LoadGraph *g)
+{
+ guint64 *last_data;
+ gsize i;
+
+ /* data[g->draw_width - 1] becomes data[0] */
+ last_data = g->data[g->draw_width - 1];
+
+ /* data[i+1] = data[i] */
+ for (i = g->draw_width - 1; i != 0; --i)
+ g->data[i] = g->data[i - 1];
+
+ g->data[0] = last_data;
+}
+
+/* Redraws the backing pixmap for the load graph and updates the window */
+static void
+load_graph_draw (LoadGraph *g)
+{
+ guint i, j, k;
+ cairo_t *cr;
+ MultiloadApplet *multiload;
+
+ multiload = g->multiload;
+
+ /* we might get called before the configure event so that
+ * g->disp->allocation may not have the correct size
+ * (after the user resized the applet in the prop dialog). */
+
+ if (!g->surface)
+ g->surface = gdk_window_create_similar_surface (gtk_widget_get_window (g->disp),
+ CAIRO_CONTENT_COLOR,
+ (int) g->draw_width,
+ (int) g->draw_height);
+
+ cr = cairo_create (g->surface);
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+ /* all graphs except Load and Net go this path */
+ switch (g->id) {
+
+ /* This is for network graph */
+ case graph_netload2: {
+ guint64 maxnet = 1;
+ guint64 segments = 1;
+ guint64 net_threshold;
+ guint level = 0;
+ double ratio;
+ double spacing;
+
+ for (i = 0; i < g->draw_width; i++)
+ {
+ g->pos [i] = g->draw_height - 1;
+ if (g->data[i][3] > maxnet)
+ maxnet = g->data[i][3];
+ }
+ //printf("max = %d ", maxnet);
+ if (maxnet > multiload->net_threshold3) {
+ net_threshold = multiload->net_threshold3;
+ level = 3;
+ }
+ else
+ if (maxnet > multiload->net_threshold2) {
+ net_threshold = multiload->net_threshold2;
+ level = 2;
+ }
+ else {
+ net_threshold = multiload->net_threshold1;
+ if (maxnet >= multiload->net_threshold1)
+ level = 1;
+ }
+
+ //printf("level %d maxnet = %d ", level, maxnet);
+ maxnet = maxnet/net_threshold;
+ segments = MAX (maxnet+1,1);
+ ratio = (double) g->draw_height / (double) (net_threshold*segments);
+ //printf("segments %d ratio = %f t1=%ld t2=%ld t3=%ld t=%ld\n", segments, ratio, multiload->net_threshold1, multiload->net_threshold2, multiload->net_threshold3, multiload->net_threshold);
+
+ for (j = 0; j < g->n-1; j++)
+ {
+ gdk_cairo_set_source_rgba (cr, &(g->colors [j]));
+
+ for (i = 0; i < g->draw_width; i++)
+ {
+ double x = (double) (g->draw_width - i) - 0.5;
+ cairo_move_to (cr, x, (double) g->pos[i] + 0.5);
+ cairo_line_to (cr, x, (double) g->pos[i] - 0.5 - (((double) g->data [i][j] * ratio)));
+ g->pos [i] -= (guint64) ((double) g->data [i][j] * ratio);
+ }
+ cairo_stroke (cr);
+ }
+
+ for (j = g->n-1; j < g->n; j++)
+ {
+ gdk_cairo_set_source_rgba (cr, &(g->colors [j]));
+ for (i = 0; i < g->draw_width; i++)
+ {
+ double x = (double) (g->draw_width - i) - 0.5;
+ cairo_move_to (cr, x, (double) g->pos[i] + 0.5);
+ cairo_line_to (cr, x, 0.5);
+ }
+ cairo_stroke (cr);
+ }
+
+ /* draw grid lines if needed */
+ gdk_cairo_set_source_rgba (cr, &(g->colors [4]));
+ for (k = 0; k < segments -1; k++)
+ {
+ spacing = ((double) g->draw_height / (double) segments) * (k+1);
+ cairo_move_to (cr, 0.5, spacing);
+ cairo_line_to (cr, (double) g->draw_width - 0.5, spacing);
+ }
+ cairo_stroke (cr);
+ /* draw indicator if needed */
+ if (level > 0)
+ {
+ gdk_cairo_set_source_rgba (cr, &(g->colors [5]));
+ for (k = 0; k< level; k++ )
+ cairo_rectangle (cr,
+ 0.5, (double) k * 2.0 * (double) g->draw_height / 5.0,
+ 5.0, (double) g->draw_height / 5.0);
+ cairo_fill(cr);
+ }
+ cairo_stroke (cr);
+ break;
+ }
+
+ /* this is Load graph */
+ case graph_loadavg: {
+ double load;
+ guint64 maxload = 1;
+ for (i = 0; i < g->draw_width; i++)
+ {
+ g->pos [i] = g->draw_height - 1;
+ /* find maximum value */
+ if (g->data[i][0] > maxload)
+ maxload = g->data[i][0];
+ }
+ load = ceil ((double) maxload / (double) g->draw_height) + 1.0;
+
+ for (j = 0; j < g->n; j++)
+ {
+ gdk_cairo_set_source_rgba (cr, &(g->colors [j]));
+
+ for (i = 0; i < g->draw_width; i++)
+ {
+ double x = (double) (g->draw_width - i) - 0.5;
+ cairo_move_to (cr, x, (double) g->pos[i] + 0.5);
+ if (j == 0)
+ {
+ cairo_line_to (cr, x, (double) g->pos[i] - (((double) g->data [i][j] - 0.5)/load));
+ }
+ else
+ {
+ cairo_line_to (cr, x, 0.5);
+ }
+ g->pos [i] -= (guint64) ((double) g->data [i][j] / load);
+ }
+ cairo_stroke (cr);
+ }
+
+ /* draw grid lines in Load graph if needed */
+ gdk_cairo_set_source_rgba (cr, &(g->colors [2]));
+
+ double spacing;
+ for (k = 0; k < load - 1; k++)
+ {
+ spacing = ((double) g->draw_height/load) * (k+1);
+ cairo_move_to (cr, 0.5, spacing);
+ cairo_line_to (cr, (double) g->draw_width - 0.5, spacing);
+ }
+
+ cairo_stroke (cr);
+ break;
+ }
+
+ default:
+ for (i = 0; i < g->draw_width; i++)
+ g->pos [i] = g->draw_height - 1;
+
+ for (j = 0; j < g->n; j++)
+ {
+ gdk_cairo_set_source_rgba (cr, &(g->colors [j]));
+
+ for (i = 0; i < g->draw_width; i++)
+ {
+ if (g->data [i][j] != 0)
+ {
+ double x = (double) (g->draw_width - i) - 0.5;
+ cairo_move_to (cr, x, (double) g->pos[i] + 0.5);
+ cairo_line_to (cr, x, (double) g->pos[i] - (double) g->data [i][j] - 0.5);
+ }
+ g->pos [i] -= g->data [i][j];
+ }
+ cairo_stroke (cr);
+ }
+ }
+
+ gtk_widget_queue_draw (g->disp);
+
+ cairo_destroy (cr);
+}
+
+/* Updates the load graph when the timeout expires */
+static gboolean
+load_graph_update (LoadGraph *g)
+{
+ if (g->data == NULL)
+ return TRUE;
+
+ shift_right(g);
+
+ if (g->tooltip_update)
+ multiload_applet_tooltip_update (g);
+
+ g->get_data (g->draw_height, g->data [0], g);
+
+ load_graph_draw (g);
+ return TRUE;
+}
+
+void
+load_graph_unalloc (LoadGraph *g)
+{
+ gsize i;
+
+ if (!g->allocated)
+ return;
+
+ for (i = 0; i < g->draw_width; i++)
+ {
+ g_free (g->data [i]);
+ }
+
+ g_free (g->data);
+ g_free (g->pos);
+
+ g->pos = NULL;
+ g->data = NULL;
+
+ g->size = CLAMP (g_settings_get_uint (g->multiload->settings, GRAPH_SIZE_KEY),
+ GRAPH_SIZE_MIN,
+ GRAPH_SIZE_MAX);
+
+ if (g->surface) {
+ cairo_surface_destroy (g->surface);
+ g->surface = NULL;
+ }
+
+ g->allocated = FALSE;
+}
+
+static void
+load_graph_alloc (LoadGraph *g)
+{
+ gsize i;
+ gsize data_size;
+
+ if (g->allocated)
+ return;
+
+ g->data = g_new0 (guint64 *, g->draw_width);
+ g->pos = g_new0 (guint64, g->draw_width);
+
+ data_size = sizeof (guint64) * g->n;
+
+ for (i = 0; i < g->draw_width; i++) {
+ g->data [i] = g_malloc0 (data_size);
+ }
+
+ g->allocated = TRUE;
+}
+
+static gint
+load_graph_configure (GtkWidget *widget, GdkEventConfigure *event,
+ gpointer data_ptr)
+{
+ GtkAllocation allocation;
+ LoadGraph *c = (LoadGraph *) data_ptr;
+
+ load_graph_unalloc (c);
+
+ gtk_widget_get_allocation (c->disp, &allocation);
+
+ c->draw_width = (gsize) allocation.width;
+ c->draw_height = (guint64) allocation.height;
+ c->draw_width = MAX (c->draw_width, 1);
+ c->draw_height = MAX (c->draw_height, 1);
+
+ load_graph_alloc (c);
+
+ if (!c->surface)
+ c->surface = gdk_window_create_similar_surface (gtk_widget_get_window (c->disp),
+ CAIRO_CONTENT_COLOR,
+ (int) c->draw_width,
+ (int) c->draw_height);
+ gtk_widget_queue_draw (widget);
+
+ return TRUE;
+}
+
+static gint
+load_graph_expose (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer data_ptr)
+{
+ LoadGraph *g = (LoadGraph *) data_ptr;
+
+ cairo_set_source_surface (cr, g->surface, 0, 0);
+ cairo_paint (cr);
+
+ return FALSE;
+}
+
+static void
+load_graph_destroy (GtkWidget *widget, gpointer data_ptr)
+{
+ LoadGraph *g = (LoadGraph *) data_ptr;
+
+ load_graph_stop (g);
+
+ gtk_widget_destroy(widget);
+}
+
+static gboolean
+load_graph_clicked (GtkWidget *widget, GdkEventButton *event, LoadGraph *load)
+{
+ load->multiload->last_clicked = load->id;
+
+ return FALSE;
+}
+
+static gboolean
+load_graph_enter_cb(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ LoadGraph *graph;
+ graph = (LoadGraph *)data;
+
+ graph->tooltip_update = TRUE;
+ multiload_applet_tooltip_update(graph);
+
+ return TRUE;
+}
+
+static gboolean
+load_graph_leave_cb(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ LoadGraph *graph;
+ graph = (LoadGraph *)data;
+
+ graph->tooltip_update = FALSE;
+
+ return TRUE;
+}
+
+static void
+load_graph_load_config (LoadGraph *g)
+{
+ gchar *name, *temp;
+ guint i;
+
+ if (!g->colors)
+ g->colors = g_new0(GdkRGBA, g->n);
+
+ for (i = 0; i < g->n; i++)
+ {
+ name = g_strdup_printf ("%s-color%u", g->name, i);
+ temp = g_settings_get_string(g->multiload->settings, name);
+ if (!temp)
+ temp = g_strdup ("#000000");
+ gdk_rgba_parse(&(g->colors[i]), temp);
+ g_free(temp);
+ g_free(name);
+ }
+}
+
+LoadGraph *
+load_graph_new (MultiloadApplet *ma, guint n, const gchar *label,
+ gint id, guint speed, guint size, gboolean visible,
+ const gchar *name, LoadGraphDataFunc get_data)
+{
+ LoadGraph *g;
+ MatePanelAppletOrient orient;
+
+ g = g_new0 (LoadGraph, 1);
+ g->visible = visible;
+ g->name = name;
+ g->n = n;
+ g->id = id;
+ g->speed = speed;
+ g->size = size;
+ g->pixel_size = mate_panel_applet_get_size (ma->applet);
+ g->tooltip_update = FALSE;
+ g->multiload = ma;
+
+ g->main_widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+
+ g->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+
+ orient = mate_panel_applet_get_orient (g->multiload->applet);
+ switch (orient)
+ {
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ {
+ g->orient = FALSE;
+ break;
+ }
+ case MATE_PANEL_APPLET_ORIENT_LEFT:
+ case MATE_PANEL_APPLET_ORIENT_RIGHT:
+ {
+ g->orient = TRUE;
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+
+ g->frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (g->frame), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (g->frame), g->box);
+ gtk_box_pack_start (GTK_BOX (g->main_widget), g->frame, TRUE, TRUE, 0);
+
+ load_graph_load_config (g);
+
+ g->get_data = get_data;
+
+ g->timer_index = -1;
+
+ if (g->orient)
+ gtk_widget_set_size_request (g->main_widget, -1, (gint) g->size);
+ else
+ gtk_widget_set_size_request (g->main_widget, (gint) g->size, -1);
+
+ g->disp = gtk_drawing_area_new ();
+ gtk_widget_set_events (g->disp, GDK_EXPOSURE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_BUTTON_PRESS_MASK);
+
+ g_signal_connect (g->disp, "draw",
+ G_CALLBACK (load_graph_expose), g);
+ g_signal_connect (g->disp, "configure-event",
+ G_CALLBACK (load_graph_configure), g);
+ g_signal_connect (g->disp, "destroy",
+ G_CALLBACK (load_graph_destroy), g);
+ g_signal_connect (g->disp, "button-press-event",
+ G_CALLBACK (load_graph_clicked), g);
+ g_signal_connect (g->disp, "enter-notify-event",
+ G_CALLBACK(load_graph_enter_cb), g);
+ g_signal_connect (g->disp, "leave-notify-event",
+ G_CALLBACK(load_graph_leave_cb), g);
+
+ gtk_box_pack_start (GTK_BOX (g->box), g->disp, TRUE, TRUE, 0);
+ gtk_widget_show_all(g->box);
+
+ return g;
+}
+
+void
+load_graph_start (LoadGraph *g)
+{
+ guint event_source_id;
+
+ if (g->timer_index != -1)
+ g_source_remove ((guint) g->timer_index);
+
+ event_source_id = g_timeout_add (g->speed,
+ (GSourceFunc) load_graph_update, g);
+
+ g->timer_index = (gint) event_source_id;
+}
+
+void
+load_graph_stop (LoadGraph *g)
+{
+ if (g->timer_index != -1)
+ g_source_remove ((guint) g->timer_index);
+
+ g->timer_index = -1;
+}
diff --git a/multiload/src/load-graph.h b/multiload/src/load-graph.h
new file mode 100644
index 00000000..1f13a8d0
--- /dev/null
+++ b/multiload/src/load-graph.h
@@ -0,0 +1,24 @@
+#ifndef LOAD_GRAPH_H__
+#define LOAD_GRAPH_H__
+
+#include "global.h"
+
+/* Create new load graph. */
+G_GNUC_INTERNAL LoadGraph *
+load_graph_new (MultiloadApplet *multiload, guint n, const gchar *label,
+ gint id, guint speed, guint size, gboolean visible,
+ const gchar *name, LoadGraphDataFunc get_data);
+
+/* Start load graph. */
+G_GNUC_INTERNAL void
+load_graph_start (LoadGraph *g);
+
+/* Stop load graph. */
+G_GNUC_INTERNAL void
+load_graph_stop (LoadGraph *g);
+
+/* free load graph */
+G_GNUC_INTERNAL void
+load_graph_unalloc (LoadGraph *g);
+
+#endif
diff --git a/multiload/src/main.c b/multiload/src/main.c
new file mode 100644
index 00000000..9439b320
--- /dev/null
+++ b/multiload/src/main.c
@@ -0,0 +1,584 @@
+/* MATE multiload panel applet
+ * (C) 1997 The Free Software Foundation
+ *
+ * Authors: Tim P. Gerla
+ * Martin Baulig
+ * Todd Kulesza
+ *
+ * With code from wmload.c, v0.9.2, apparently by Ryan Land, [email protected].
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <signal.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+
+#include <glibtop.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-gsettings.h>
+
+#include "global.h"
+
+static void
+about_cb (GtkAction *action,
+ MultiloadApplet *ma)
+{
+ const gchar * const authors[] =
+ {
+ "Martin Baulig <[email protected]>",
+ "Todd Kulesza <[email protected]>",
+ "Benoît Dejean <[email protected]>",
+ "Davyd Madeley <[email protected]>",
+ NULL
+ };
+
+ const gchar* documenters[] =
+ {
+ "Chee Bin HOH <[email protected]>",
+ N_("Sun GNOME Documentation Team <[email protected]>"),
+ N_("MATE Documentation Team"),
+ NULL
+ };
+
+#ifdef ENABLE_NLS
+ const char **p;
+ for (p = documenters; *p; ++p)
+ *p = _(*p);
+#endif
+
+ gtk_show_about_dialog (NULL,
+ "title", _("About System Monitor"),
+ "version", VERSION,
+ "copyright", _("Copyright \xc2\xa9 1999-2005 Free Software Foundation and others\n"
+ "Copyright \xc2\xa9 2012-2021 MATE developers"),
+ "comments", _("A system load monitor capable of displaying graphs "
+ "for CPU, ram, and swap space use, plus network "
+ "traffic."),
+ "authors", authors,
+ "documenters", documenters,
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", "utilities-system-monitor",
+ NULL);
+}
+
+static void
+help_cb (GtkAction *action,
+ MultiloadApplet *ma)
+{
+ GError *error = NULL;
+
+ gtk_show_uri_on_window (NULL,
+ "help:mate-multiload",
+ gtk_get_current_event_time (),
+ &error);
+
+ if (error) { /* FIXME: the user needs to see this */
+ g_warning ("help error: %s\n", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+}
+
+/* run the full-scale system process monitor */
+
+static void
+start_procman (MultiloadApplet *ma)
+{
+ GError *error = NULL;
+ GDesktopAppInfo *appinfo;
+ gchar *monitor;
+ GdkAppLaunchContext *launch_context;
+ GdkDisplay *display;
+ GAppInfo *app_info;
+ GdkScreen *screen;
+
+ g_return_if_fail (ma != NULL);
+
+ monitor = g_settings_get_string (ma->settings, "system-monitor");
+ if (monitor == NULL)
+ monitor = g_strdup ("mate-system-monitor.desktop");
+
+ screen = gtk_widget_get_screen (GTK_WIDGET (ma->applet));
+ appinfo = g_desktop_app_info_new (monitor);
+ if (appinfo) {
+ GdkAppLaunchContext *context;
+ display = gdk_screen_get_display (screen);
+ context = gdk_display_get_app_launch_context (display);
+ gdk_app_launch_context_set_screen (context, screen);
+ g_app_info_launch (G_APP_INFO (appinfo), NULL, G_APP_LAUNCH_CONTEXT (context), &error);
+ g_object_unref (context);
+ g_object_unref (appinfo);
+ }
+ else {
+ app_info = g_app_info_create_from_commandline ("mate-system-monitor",
+ _("Start system-monitor"),
+ G_APP_INFO_CREATE_NONE,
+ &error);
+
+ if (!error) {
+ display = gdk_screen_get_display (screen);
+ launch_context = gdk_display_get_app_launch_context (display);
+ gdk_app_launch_context_set_screen (launch_context, screen);
+ g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error);
+
+ g_object_unref (launch_context);
+ }
+ }
+ g_free (monitor);
+
+ if (error) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("There was an error executing '%s': %s"),
+ "mate-system-monitor",
+ error->message);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_window_set_screen (GTK_WINDOW (dialog), screen);
+
+ gtk_widget_show (dialog);
+
+ g_error_free (error);
+ }
+}
+
+static void
+start_procman_cb (GtkAction *action,
+ MultiloadApplet *ma)
+{
+ start_procman (ma);
+}
+
+static void
+multiload_change_size_cb(MatePanelApplet *applet, gint size, gpointer data)
+{
+ MultiloadApplet *ma = (MultiloadApplet *)data;
+
+ multiload_applet_refresh(ma);
+
+ return;
+}
+
+static void
+multiload_change_orient_cb(MatePanelApplet *applet, gint arg1, gpointer data)
+{
+ MultiloadApplet *ma = data;
+ multiload_applet_refresh((MultiloadApplet *)data);
+ gtk_widget_show (GTK_WIDGET (ma->applet));
+ return;
+}
+
+static void
+multiload_destroy_cb(GtkWidget *widget, gpointer data)
+{
+ guint i;
+ MultiloadApplet *ma = data;
+
+ for (i = 0; i < graph_n; i++)
+ {
+ load_graph_stop(ma->graphs[i]);
+ if (ma->graphs[i]->colors)
+ {
+ g_free (ma->graphs[i]->colors);
+ ma->graphs[i]->colors = NULL;
+ }
+ gtk_widget_destroy(ma->graphs[i]->main_widget);
+
+ load_graph_unalloc(ma->graphs[i]);
+ g_free(ma->graphs[i]);
+ }
+
+ netspeed_delete (ma->netspeed_in);
+ netspeed_delete (ma->netspeed_out);
+
+ if (ma->about_dialog)
+ gtk_widget_destroy (ma->about_dialog);
+
+ if (ma->prop_dialog)
+ gtk_widget_destroy (ma->prop_dialog);
+
+ gtk_widget_destroy(GTK_WIDGET(ma->applet));
+
+ g_free (ma);
+
+ return;
+}
+
+static gboolean
+multiload_button_press_event_cb (GtkWidget *widget, GdkEventButton *event, MultiloadApplet *ma)
+{
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (ma != NULL, FALSE);
+
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+ start_procman (ma);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+multiload_key_press_event_cb (GtkWidget *widget, GdkEventKey *event, MultiloadApplet *ma)
+{
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (ma != NULL, FALSE);
+
+ switch (event->keyval) {
+ /* this list of keyvals taken from mixer applet, which seemed to have
+ a good list of keys to use */
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_ISO_Enter:
+ case GDK_KEY_3270_Enter:
+ case GDK_KEY_Return:
+ case GDK_KEY_space:
+ case GDK_KEY_KP_Space:
+ /* activate */
+ start_procman (ma);
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/* update the tooltip to the graph's current "used" percentage */
+void
+multiload_applet_tooltip_update(LoadGraph *g)
+{
+ gchar *tooltip_text;
+ MultiloadApplet *multiload;
+ const char *tooltip_label [graph_n] = {
+ [graph_cpuload] = N_("Processor"),
+ [graph_memload] = N_("Memory"),
+ [graph_netload2] = N_("Network"),
+ [graph_swapload] = N_("Swap Space"),
+ [graph_loadavg] = N_("Load Average"),
+ [graph_diskload] = N_("Disk")
+ };
+ const char *name;
+
+ g_assert(g);
+
+ multiload = g->multiload;
+
+ /* label the tooltip intuitively */
+ name = gettext (tooltip_label [g->id]);
+
+ switch (g->id) {
+ case graph_memload: {
+ float user_percent, cache_percent;
+
+ user_percent = MIN ((float)(100 * multiload->memload_user) / (float)(multiload->memload_total), 100.0f);
+ cache_percent = MIN ((float)(100 * multiload->memload_cache) / (float)(multiload->memload_total), 100.0f);
+ tooltip_text = g_strdup_printf (_("%s:\n"
+ "%.01f%% in use by programs\n"
+ "%.01f%% in use as cache"),
+ name,
+ user_percent,
+ cache_percent);
+ break;
+ }
+ case graph_loadavg: {
+ tooltip_text = g_strdup_printf (_("The system load average is %0.02f"),
+ multiload->loadavg1);
+ break;
+ }
+ case graph_netload2: {
+ char *tx_in, *tx_out;
+
+ tx_in = netspeed_get(multiload->netspeed_in);
+ tx_out = netspeed_get(multiload->netspeed_out);
+ /* xgettext: same as in graphic tab of g-s-m */
+ tooltip_text = g_strdup_printf(_("%s:\n"
+ "Receiving %s\n"
+ "Sending %s"),
+ name, tx_in, tx_out);
+ g_free(tx_in);
+ g_free(tx_out);
+ break;
+ }
+ default: {
+ float ratio;
+ float percent;
+
+ if (g->id == graph_cpuload)
+ ratio = multiload->cpu_used_ratio;
+ else if (g->id == graph_swapload)
+ ratio = multiload->swapload_used_ratio;
+ else if (g->id == graph_diskload)
+ ratio = multiload->diskload_used_ratio;
+ else
+ g_assert_not_reached ();
+
+ percent = CLAMP (ratio * 100.0f, 0.0f, 100.0f);
+ tooltip_text = g_strdup_printf(_("%s:\n"
+ "%.01f%% in use"),
+ name,
+ percent);
+ }
+ }
+
+ gtk_widget_set_tooltip_text(g->disp, tooltip_text);
+
+ g_free(tooltip_text);
+}
+
+static void
+multiload_create_graphs(MultiloadApplet *ma)
+{
+ struct { const char *label;
+ const char *visibility_key;
+ const char *name;
+ guint num_colours;
+ LoadGraphDataFunc callback;
+ } graph_types [graph_n] = {
+ [graph_cpuload] = { _("CPU Load"), VIEW_CPULOAD_KEY, "cpuload", cpuload_n, GetLoad },
+ [graph_memload] = { _("Memory Load"), VIEW_MEMLOAD_KEY, "memload", memload_n, GetMemory },
+ [graph_netload2] = { _("Net Load"), VIEW_NETLOAD_KEY, "netload2", 6, GetNet },
+ [graph_swapload] = { _("Swap Load"), VIEW_SWAPLOAD_KEY, "swapload", swapload_n, GetSwap },
+ [graph_loadavg] = { _("Load Average"), VIEW_LOADAVG_KEY, "loadavg", 3, GetLoadAvg },
+ [graph_diskload] = { _("Disk Load"), VIEW_DISKLOAD_KEY, "diskload", diskload_n, GetDiskLoad }
+ };
+
+ guint size;
+ guint speed;
+ guint64 net_threshold1;
+ guint64 net_threshold2;
+ guint64 net_threshold3;
+ gint i;
+
+ speed = CLAMP (g_settings_get_uint (ma->settings, REFRESH_RATE_KEY), REFRESH_RATE_MIN, REFRESH_RATE_MAX);
+ size = CLAMP (g_settings_get_uint (ma->settings, GRAPH_SIZE_KEY), GRAPH_SIZE_MIN, GRAPH_SIZE_MAX);
+ net_threshold1 = CLAMP (g_settings_get_uint64 (ma->settings, KEY_NET_THRESHOLD1), MIN_NET_THRESHOLD1, MAX_NET_THRESHOLD1);
+ net_threshold2 = CLAMP (g_settings_get_uint64 (ma->settings, KEY_NET_THRESHOLD2), MIN_NET_THRESHOLD2, MAX_NET_THRESHOLD2);
+ net_threshold3 = CLAMP (g_settings_get_uint64 (ma->settings, KEY_NET_THRESHOLD3), MIN_NET_THRESHOLD3, MAX_NET_THRESHOLD3);
+ if (net_threshold1 >= net_threshold2)
+ {
+ net_threshold1 = net_threshold2 - 1;
+ }
+ if (net_threshold2 >= net_threshold3)
+ {
+ net_threshold3 = net_threshold2 + 1;
+ }
+
+ for (i = 0; i < graph_n; i++)
+ {
+ ma->graphs[i] = load_graph_new (ma,
+ graph_types[i].num_colours,
+ graph_types[i].label,
+ i,
+ speed,
+ size,
+ g_settings_get_boolean (ma->settings, graph_types[i].visibility_key),
+ graph_types[i].name,
+ graph_types[i].callback);
+ }
+ ma->nvme_diskstats = g_settings_get_boolean (ma->settings, "diskload-nvme-diskstats");
+ /* for Network graph, colors[4] is grid line color, it should not be used in loop in load-graph.c */
+ /* for Network graph, colors[5] is indicator color, it should not be used in loop in load-graph.c */
+ ma->graphs[graph_netload2]->n = 4;
+ ma->net_threshold1 = net_threshold1;
+ ma->net_threshold2 = net_threshold2;
+ ma->net_threshold3 = net_threshold3;
+ ma->netspeed_in = netspeed_new (ma->graphs [graph_netload2]);
+ ma->netspeed_out = netspeed_new (ma->graphs [graph_netload2]);
+ /* for Load graph, colors[2] is grid line color, it should not be used in loop in load-graph.c */
+ ma->graphs[graph_loadavg]->n = 2;
+}
+
+/* remove the old graphs and rebuild them */
+void
+multiload_applet_refresh(MultiloadApplet *ma)
+{
+ guint i;
+ MatePanelAppletOrient orientation;
+
+ /* stop and free the old graphs */
+ for (i = 0; i < graph_n; i++)
+ {
+ if (!ma->graphs[i])
+ continue;
+
+ load_graph_stop(ma->graphs[i]);
+ gtk_widget_destroy(ma->graphs[i]->main_widget);
+
+ load_graph_unalloc(ma->graphs[i]);
+ g_free(ma->graphs[i]);
+ }
+
+ if (ma->box)
+ gtk_widget_destroy(ma->box);
+
+ orientation = mate_panel_applet_get_orient(ma->applet);
+
+ if ( (orientation == MATE_PANEL_APPLET_ORIENT_UP) ||
+ (orientation == MATE_PANEL_APPLET_ORIENT_DOWN) ) {
+ ma->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ }
+ else
+ ma->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+
+ gtk_container_add(GTK_CONTAINER(ma->applet), ma->box);
+
+ /* create the N graphs, passing in their user-configurable properties with gsettings. */
+ multiload_create_graphs (ma);
+
+ /* only start and display the graphs the user has turned on */
+
+ for (i = 0; i < graph_n; i++) {
+ gtk_box_pack_start(GTK_BOX(ma->box),
+ ma->graphs[i]->main_widget,
+ TRUE, TRUE, 1);
+ if (ma->graphs[i]->visible) {
+ gtk_widget_show_all (ma->graphs[i]->main_widget);
+ load_graph_start(ma->graphs[i]);
+ }
+ }
+ gtk_widget_show (ma->box);
+
+ return;
+}
+
+static const GtkActionEntry multiload_menu_actions [] = {
+ { "MultiLoadProperties", "document-properties", N_("_Preferences"),
+ NULL, NULL,
+ G_CALLBACK (multiload_properties_cb) },
+ { "MultiLoadRunProcman", "system-run", N_("_Open System Monitor"),
+ NULL, NULL,
+ G_CALLBACK (start_procman_cb) },
+ { "MultiLoadHelp", "help-browser", N_("_Help"),
+ NULL, NULL,
+ G_CALLBACK (help_cb) },
+ { "MultiLoadAbout", "help-about", N_("_About"),
+ NULL, NULL,
+ G_CALLBACK (about_cb) }
+};
+
+/* create a box and stuff the load graphs inside of it */
+static gboolean
+multiload_applet_new(MatePanelApplet *applet, const gchar *iid, gpointer data)
+{
+ GtkStyleContext *context;
+ MultiloadApplet *ma;
+ GSettings *lockdown_settings;
+ GtkActionGroup *action_group;
+ AtkObject *atk_obj;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (applet));
+ gtk_style_context_add_class (context, "multiload-applet");
+
+ ma = g_new0(MultiloadApplet, 1);
+
+ ma->applet = applet;
+
+ ma->about_dialog = NULL;
+ ma->prop_dialog = NULL;
+ ma->last_clicked = 0;
+
+#ifndef ENABLE_IN_PROCESS
+ g_set_application_name (_("System Monitor"));
+#endif
+
+ gtk_window_set_default_icon_name ("utilities-system-monitor");
+
+ ma->settings = mate_panel_applet_settings_new (applet, "org.mate.panel.applet.multiload");
+ mate_panel_applet_set_flags (applet, MATE_PANEL_APPLET_EXPAND_MINOR);
+
+ action_group = gtk_action_group_new ("Multiload Applet Actions");
+ gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (action_group,
+ multiload_menu_actions,
+ G_N_ELEMENTS (multiload_menu_actions),
+ ma);
+ mate_panel_applet_setup_menu_from_resource (applet,
+ MULTILOAD_RESOURCE_PATH "multiload-applet-menu.xml",
+ action_group);
+
+ if (mate_panel_applet_get_locked_down (applet)) {
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (action_group, "MultiLoadProperties");
+ gtk_action_set_visible (action, FALSE);
+ }
+
+ lockdown_settings = g_settings_new ("org.mate.lockdown");
+ if (g_settings_get_boolean (lockdown_settings, "disable-command-line") ||
+ mate_panel_applet_get_locked_down (applet)) {
+ GtkAction *action;
+
+ /* When the panel is locked down or when the command line is inhibited,
+ it seems very likely that running the procman would be at least harmful */
+ action = gtk_action_group_get_action (action_group, "MultiLoadRunProcman");
+ gtk_action_set_visible (action, FALSE);
+ }
+ g_object_unref (lockdown_settings);
+
+ g_object_unref (action_group);
+
+ g_signal_connect (applet, "change-size",
+ G_CALLBACK (multiload_change_size_cb), ma);
+ g_signal_connect (applet, "change-orient",
+ G_CALLBACK (multiload_change_orient_cb), ma);
+ g_signal_connect (applet, "destroy",
+ G_CALLBACK (multiload_destroy_cb), ma);
+ g_signal_connect (applet, "button-press-event",
+ G_CALLBACK (multiload_button_press_event_cb), ma);
+ g_signal_connect (applet, "key-press-event",
+ G_CALLBACK (multiload_key_press_event_cb), ma);
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (applet));
+
+ if (GTK_IS_ACCESSIBLE (atk_obj)) {
+ atk_object_set_name (atk_obj, _("System Monitor"));
+ atk_object_set_description (atk_obj,
+ _("A system load monitor capable of displaying graphs "
+ "for CPU, ram, and swap space use, plus network "
+ "traffic."));
+ }
+
+ multiload_applet_refresh (ma);
+
+ gtk_widget_show(GTK_WIDGET(applet));
+
+ return TRUE;
+}
+
+static gboolean
+multiload_factory (MatePanelApplet *applet,
+ const gchar *iid,
+ gpointer data)
+{
+ gboolean retval = FALSE;
+
+ glibtop_init();
+
+ retval = multiload_applet_new(applet, iid, data);
+
+ return retval;
+}
+
+PANEL_APPLET_FACTORY ("MultiLoadAppletFactory",
+ PANEL_TYPE_APPLET,
+ "multiload",
+ multiload_factory,
+ NULL)
diff --git a/multiload/src/netspeed.c b/multiload/src/netspeed.c
new file mode 100644
index 00000000..a61ce04b
--- /dev/null
+++ b/multiload/src/netspeed.c
@@ -0,0 +1,64 @@
+#include <config.h>
+#include <glib.h>
+
+#include "netspeed.h"
+
+enum { N_STATES = 4 };
+
+struct _NetSpeed
+{
+ LoadGraph *graph;
+ guint64 states[N_STATES];
+ size_t cur;
+};
+
+NetSpeed*
+netspeed_new (LoadGraph *g)
+{
+ NetSpeed *ns = g_new0 (NetSpeed, 1);
+ ns->graph = g;
+ return ns;
+}
+
+void netspeed_delete(NetSpeed *ns)
+{
+ g_free(ns);
+}
+
+void
+netspeed_add (NetSpeed *ns,
+ guint64 tx)
+{
+ ns->cur = (ns->cur + 1) % N_STATES;
+ ns->states[ns->cur] = tx;
+}
+
+char*
+netspeed_get (NetSpeed *ns)
+{
+ guint64 older;
+ guint64 newer;
+ guint64 rate;
+ char *bytes;
+ char *text;
+
+ newer = ns->states[ns->cur];
+ older = ns->states[(ns->cur + 1) % N_STATES];
+
+ if ((older != 0) && (newer > older))
+ rate = (newer - older) * 1000 / ((N_STATES - 1) * ns->graph->speed);
+ else
+ /* We end up here if we haven't got enough data yet or the
+ network interface has jumped back (or there has never
+ been any activity on any interface). A value of 0 is
+ likely to be accurate, but if it is wrong it will be
+ clearly wrong. In any event, it should fix itself in a
+ few seconds. */
+ rate = 0;
+
+ bytes = g_format_size (rate);
+ text = g_strdup_printf (_("%s/s"), bytes);
+ g_free (bytes);
+
+ return text;
+}
diff --git a/multiload/src/netspeed.h b/multiload/src/netspeed.h
new file mode 100644
index 00000000..55a2ff75
--- /dev/null
+++ b/multiload/src/netspeed.h
@@ -0,0 +1,15 @@
+#ifndef H_MULTILOAD_NETSPEED_
+#define H_MULTILOAD_NETSPEED_
+
+#include <glib.h>
+
+typedef struct _NetSpeed NetSpeed;
+
+#include "global.h"
+
+NetSpeed* netspeed_new(LoadGraph *graph);
+void netspeed_delete(NetSpeed *ns);
+void netspeed_add(NetSpeed *ns, guint64 tx);
+char* netspeed_get(NetSpeed *ns);
+
+#endif /* H_MULTILOAD_NETSPEED_ */
diff --git a/multiload/src/properties.c b/multiload/src/properties.c
new file mode 100644
index 00000000..e776b7b8
--- /dev/null
+++ b/multiload/src/properties.c
@@ -0,0 +1,686 @@
+/* MATE cpuload/memload panel applet
+ * (C) 2002 The Free Software Foundation
+ *
+ * Authors:
+ * Todd Kulesza
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include <gio/gio.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-gsettings.h>
+
+#include "global.h"
+
+#define NEVER_SENSITIVE "never_sensitive"
+
+/* set sensitive and setup NEVER_SENSITIVE appropriately */
+static void
+hard_set_sensitive (GtkWidget *w, gboolean sensitivity)
+{
+ gtk_widget_set_sensitive (w, sensitivity);
+ g_object_set_data (G_OBJECT (w), NEVER_SENSITIVE,
+ GINT_TO_POINTER ( ! sensitivity));
+}
+
+/* set sensitive, but always insensitive if NEVER_SENSITIVE is set */
+static void
+soft_set_sensitive (GtkWidget *w, gboolean sensitivity)
+{
+ if (g_object_get_data (G_OBJECT (w), NEVER_SENSITIVE))
+ gtk_widget_set_sensitive (w, FALSE);
+ else
+ gtk_widget_set_sensitive (w, sensitivity);
+}
+
+static void
+properties_set_insensitive(MultiloadApplet *ma)
+{
+ guint total_graphs = 0;
+ guint last_graph = 0;
+ guint i;
+
+ for (i = 0; i < graph_n; i++)
+ if (ma->graphs[i]->visible)
+ {
+ last_graph = i;
+ total_graphs++;
+ }
+
+ if (total_graphs < 2)
+ soft_set_sensitive (ma->check_boxes[last_graph], FALSE);
+}
+
+static void
+on_properties_dialog_response (GtkWidget *widget,
+ gint arg,
+ MultiloadApplet *ma)
+{
+ GError *error = NULL;
+
+ switch (arg) {
+ case GTK_RESPONSE_HELP:
+
+ gtk_show_uri_on_window (NULL,
+ "help:mate-multiload/multiload-prefs",
+ gtk_get_current_event_time (),
+ &error);
+
+ if (error) { /* FIXME: the user needs to see this */
+ g_warning ("help error: %s\n", error->message);
+ g_error_free (error);
+ }
+ break;
+
+ case GTK_RESPONSE_CLOSE:
+ default:
+ gtk_widget_destroy (widget);
+ ma->prop_dialog = NULL;
+ }
+}
+
+static void
+on_speed_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ MultiloadApplet *ma = user_data;
+ gint value;
+ guint i;
+
+ value = gtk_spin_button_get_value_as_int (spin_button);
+ g_settings_set_uint (ma->settings, REFRESH_RATE_KEY, (guint) value);
+ for (i = 0; i < graph_n; i++) {
+ load_graph_stop (ma->graphs[i]);
+ ma->graphs[i]->speed = (guint) value;
+ if (ma->graphs[i]->visible)
+ load_graph_start (ma->graphs[i]);
+ }
+}
+
+static void
+on_graph_size_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ MultiloadApplet *ma = user_data;
+ gint value;
+ guint i;
+
+ value = gtk_spin_button_get_value_as_int (spin_button);
+ g_settings_set_uint (ma->settings, GRAPH_SIZE_KEY, (guint) value);
+ for (i = 0; i < graph_n; i++) {
+ ma->graphs[i]->size = (guint) value;
+ if (ma->graphs[i]->orient) {
+ gtk_widget_set_size_request (ma->graphs[i]->main_widget,
+ (gint) ma->graphs[i]->pixel_size,
+ (gint) ma->graphs[i]->size);
+ } else {
+ gtk_widget_set_size_request (ma->graphs[i]->main_widget,
+ (gint) ma->graphs[i]->size,
+ (gint) ma->graphs[i]->pixel_size);
+ }
+ }
+}
+
+static void
+on_net_threshold1_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ MultiloadApplet *ma = user_data;
+ gdouble temp;
+
+ temp = gtk_spin_button_get_value (spin_button);
+ ma->net_threshold1 = (guint64) temp;
+ if (ma->net_threshold1 >= ma->net_threshold2) {
+ ma->net_threshold1 = ma->net_threshold2 - 1;
+ gtk_spin_button_set_value (spin_button, (gdouble) ma->net_threshold1);
+ }
+ g_settings_set_uint64 (ma->settings, KEY_NET_THRESHOLD1, ma->net_threshold1);
+}
+
+static void
+on_net_threshold2_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ MultiloadApplet *ma = user_data;
+ gdouble temp;
+
+ temp = gtk_spin_button_get_value (spin_button);
+ ma->net_threshold2 = (guint64) temp;
+ if (ma->net_threshold2 >= ma->net_threshold3) {
+ ma->net_threshold2 = ma->net_threshold3 - 1;
+ gtk_spin_button_set_value (spin_button, (gdouble) ma->net_threshold2);
+ } else if (ma->net_threshold2 <= ma->net_threshold1) {
+ ma->net_threshold2 = ma->net_threshold1 + 1;
+ gtk_spin_button_set_value (spin_button, (gdouble) ma->net_threshold2);
+ }
+ g_settings_set_uint64 (ma->settings, KEY_NET_THRESHOLD2, ma->net_threshold2);
+}
+
+static void
+on_net_threshold3_spin_button_value_changed (GtkSpinButton *spin_button,
+ gpointer user_data)
+{
+ MultiloadApplet *ma = user_data;
+ gdouble temp;
+
+ temp = gtk_spin_button_get_value (spin_button);
+ ma->net_threshold3 = (guint64) temp;
+ if (ma->net_threshold3 <= ma->net_threshold2) {
+ ma->net_threshold3 = ma->net_threshold2 + 1;
+ gtk_spin_button_set_value (spin_button, (gdouble) ma->net_threshold3);
+ }
+ g_settings_set_uint64 (ma->settings, KEY_NET_THRESHOLD3, ma->net_threshold3);
+}
+
+static void
+color_button_set (GtkColorChooser *button,
+ GSettings *settings,
+ const char *key,
+ GdkRGBA *color)
+{
+ gchar *color_string;
+
+ gtk_color_chooser_get_rgba (button, color);
+ color_string = gdk_rgba_to_string (color);
+ g_settings_set_string (settings, key, color_string);
+ g_free (color_string);
+}
+
+static void
+on_cpuload_usr_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_CPULOAD_USR_COLOR,
+ &(ma->graphs[graph_cpuload]->colors[cpuload_usr]));
+}
+
+static void
+on_cpuload_sys_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_CPULOAD_SYS_COLOR,
+ &(ma->graphs[graph_cpuload]->colors[cpuload_sys]));
+}
+
+static void
+on_cpuload_nice_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_CPULOAD_NICE_COLOR,
+ &(ma->graphs[graph_cpuload]->colors[cpuload_nice]));
+}
+
+static void
+on_cpuload_iowait_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_CPULOAD_IOWAIT_COLOR,
+ &(ma->graphs[graph_cpuload]->colors[cpuload_iowait]));
+}
+
+static void
+on_cpuload_free_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_CPULOAD_IDLE_COLOR,
+ &(ma->graphs[graph_cpuload]->colors[cpuload_free]));
+}
+
+static void
+on_memload_user_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_MEMLOAD_USER_COLOR,
+ &(ma->graphs[graph_memload]->colors[memload_user]));
+}
+
+static void
+on_memload_shared_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_MEMLOAD_SHARED_COLOR,
+ &(ma->graphs[graph_memload]->colors[memload_shared]));
+}
+
+static void
+on_memload_buffer_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_MEMLOAD_BUFFER_COLOR,
+ &(ma->graphs[graph_memload]->colors[memload_buffer]));
+}
+
+static void
+on_memload_cached_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_MEMLOAD_CACHED_COLOR,
+ &(ma->graphs[graph_memload]->colors[memload_cached]));
+}
+
+static void
+on_memload_free_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_MEMLOAD_FREE_COLOR,
+ &(ma->graphs[graph_memload]->colors[memload_free]));
+}
+
+static void
+on_netload2_in_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_IN_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_in]));
+}
+
+static void
+on_netload2_out_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_OUT_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_out]));
+}
+
+static void
+on_netload2_loopback_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_LOOPBACK_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_loopback]));
+}
+
+static void
+on_netload2_background_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_BACKGROUND_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_background]));
+}
+
+static void
+on_netload2_gridline_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_GRIDLINE_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_gridline]));
+}
+
+static void
+on_netload2_indicator_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_NETLOAD2_INDICATOR_COLOR,
+ &(ma->graphs[graph_netload2]->colors[netload2_indicator]));
+}
+
+static void
+on_swapload_used_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_SWAPLOAD_USED_COLOR,
+ &(ma->graphs[graph_swapload]->colors[swapload_used]));
+}
+
+static void
+on_swapload_free_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_SWAPLOAD_FREE_COLOR,
+ &(ma->graphs[graph_swapload]->colors[swapload_free]));
+}
+
+static void
+on_loadavg_average_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_LOADAVG_AVERAGE_COLOR,
+ &(ma->graphs[graph_loadavg]->colors[loadavg_average]));
+}
+
+static void
+on_loadavg_background_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_LOADAVG_BACKGROUND_COLOR,
+ &(ma->graphs[graph_loadavg]->colors[loadavg_background]));
+}
+
+static void
+on_loadavg_gridline_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_LOADAVG_GRIDLINE_COLOR,
+ &(ma->graphs[graph_loadavg]->colors[loadavg_gridline]));
+}
+
+static void
+on_diskload_read_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_DISKLOAD_READ_COLOR,
+ &(ma->graphs[graph_diskload]->colors[diskload_read]));
+}
+
+static void
+on_diskload_write_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_DISKLOAD_WRITE_COLOR,
+ &(ma->graphs[graph_diskload]->colors[diskload_write]));
+}
+
+static void
+on_diskload_free_color_button_color_set (GtkColorButton *button,
+ MultiloadApplet *ma)
+{
+ color_button_set (GTK_COLOR_CHOOSER (button),
+ ma->settings, KEY_DISKLOAD_FREE_COLOR,
+ &(ma->graphs[graph_diskload]->colors[diskload_free]));
+}
+
+static void
+graph_set_active (MultiloadApplet *ma,
+ LoadGraph *graph,
+ gboolean active)
+{
+ graph->visible = active;
+ if (active) {
+ guint i;
+
+ for (i = 0; i < graph_n; i++)
+ soft_set_sensitive(ma->check_boxes[i], TRUE);
+ gtk_widget_show_all (graph->main_widget);
+ load_graph_start (graph);
+ } else {
+ load_graph_stop (graph);
+ gtk_widget_hide (graph->main_widget);
+ properties_set_insensitive (ma);
+ }
+}
+
+#define GRAPH_ACTIVE_SET(x) graph_set_active (ma, ma->graphs[(x)], \
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)))
+
+static void
+on_graph_cpuload_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_cpuload);
+}
+
+static void
+on_graph_memload_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_memload);
+}
+
+static void
+on_graph_netload2_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_netload2);
+}
+
+static void
+on_graph_swapload_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_swapload);
+}
+
+static void
+on_graph_loadavg_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_loadavg);
+}
+
+static void
+on_graph_diskload_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ GRAPH_ACTIVE_SET (graph_diskload);
+}
+
+/* save the checkbox option to gsettings and apply it on the applet */
+static void
+on_nvme_checkbox_toggled (GtkCheckButton *checkbox,
+ MultiloadApplet *ma)
+{
+ ma->nvme_diskstats = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
+}
+
+static void
+read_spin_uint_button (GtkWidget *widget,
+ GSettings *settings,
+ const char *key,
+ guint min,
+ guint max)
+{
+ guint value;
+
+ value = CLAMP (g_settings_get_uint (settings, key), min, max);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) value);
+ if (!g_settings_is_writable (settings, key))
+ hard_set_sensitive (widget, FALSE);
+}
+
+static void
+read_spin_uint64_button (GtkWidget *widget,
+ GSettings *settings,
+ const char *key,
+ guint min,
+ guint max)
+{
+ guint64 value;
+
+ value = CLAMP (g_settings_get_uint64 (settings, key), min, max);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), (gdouble) value);
+
+ if (!g_settings_is_writable (settings, key))
+ hard_set_sensitive (widget, FALSE);
+}
+
+static void
+read_color_button (GtkWidget *widget,
+ GSettings *settings,
+ const char *key)
+{
+ GdkRGBA color;
+ gchar *color_string;
+
+ color_string = g_settings_get_string (settings, key);
+ if (*color_string != '\0') {
+ gdk_rgba_parse (&color, color_string);
+ } else {
+ gdk_rgba_parse (&color, "#000000");
+ }
+ g_free (color_string);
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (widget), &color);
+
+ if (!g_settings_is_writable (settings, key))
+ hard_set_sensitive (widget, FALSE);
+}
+
+/* show properties dialog */
+void
+multiload_properties_cb (GtkAction *action,
+ MultiloadApplet *ma)
+{
+ GtkBuilder *builder;
+ GtkWidget *dialog = NULL;
+ GtkWidget *graph_size_spin_button_label;
+ const char *graph_size_spin_button_label_txt;
+ MatePanelAppletOrient orient;
+
+ if (ma->prop_dialog) {
+ dialog = ma->prop_dialog;
+
+ gtk_window_set_screen (GTK_WINDOW (dialog),
+ gtk_widget_get_screen (GTK_WIDGET (ma->applet)));
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (ma->notebook),
+ ma->last_clicked);
+ gtk_window_present (GTK_WINDOW (dialog));
+ return;
+ }
+
+ builder = gtk_builder_new_from_resource (MULTILOAD_RESOURCE_PATH "properties.ui");
+ gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+
+ #define GET_WIDGET(x) (GTK_WIDGET (gtk_builder_get_object (builder, (x))))
+
+ ma->prop_dialog = GET_WIDGET ("properties_dialog");
+
+ read_color_button (GET_WIDGET ("cpuload_free_color_button"), ma->settings, KEY_CPULOAD_IDLE_COLOR);
+ read_color_button (GET_WIDGET ("cpuload_iowait_color_button"), ma->settings, KEY_CPULOAD_IOWAIT_COLOR);
+ read_color_button (GET_WIDGET ("cpuload_nice_color_button"), ma->settings, KEY_CPULOAD_NICE_COLOR);
+ read_color_button (GET_WIDGET ("cpuload_sys_color_button"), ma->settings, KEY_CPULOAD_SYS_COLOR);
+ read_color_button (GET_WIDGET ("cpuload_usr_color_button"), ma->settings, KEY_CPULOAD_USR_COLOR);
+ read_color_button (GET_WIDGET ("diskload_free_color_button"), ma->settings, KEY_DISKLOAD_FREE_COLOR);
+ read_color_button (GET_WIDGET ("diskload_read_color_button"), ma->settings, KEY_DISKLOAD_READ_COLOR);
+ read_color_button (GET_WIDGET ("diskload_write_color_button"), ma->settings, KEY_DISKLOAD_WRITE_COLOR);
+ read_color_button (GET_WIDGET ("loadavg_average_color_button"), ma->settings, KEY_LOADAVG_AVERAGE_COLOR);
+ read_color_button (GET_WIDGET ("loadavg_background_color_button"), ma->settings, KEY_LOADAVG_BACKGROUND_COLOR);
+ read_color_button (GET_WIDGET ("loadavg_gridline_color_button"), ma->settings, KEY_LOADAVG_GRIDLINE_COLOR);
+ read_color_button (GET_WIDGET ("memload_buffer_color_button"), ma->settings, KEY_MEMLOAD_BUFFER_COLOR);
+ read_color_button (GET_WIDGET ("memload_cached_color_button"), ma->settings, KEY_MEMLOAD_CACHED_COLOR);
+ read_color_button (GET_WIDGET ("memload_free_color_button"), ma->settings, KEY_MEMLOAD_FREE_COLOR);
+ read_color_button (GET_WIDGET ("memload_shared_color_button"), ma->settings, KEY_MEMLOAD_SHARED_COLOR);
+ read_color_button (GET_WIDGET ("memload_user_color_button"), ma->settings, KEY_MEMLOAD_USER_COLOR);
+ read_color_button (GET_WIDGET ("netload2_background_color_button"), ma->settings, KEY_NETLOAD2_BACKGROUND_COLOR);
+ read_color_button (GET_WIDGET ("netload2_gridline_color_button"), ma->settings, KEY_NETLOAD2_GRIDLINE_COLOR);
+ read_color_button (GET_WIDGET ("netload2_in_color_button"), ma->settings, KEY_NETLOAD2_IN_COLOR);
+ read_color_button (GET_WIDGET ("netload2_indicator_color_button"), ma->settings, KEY_NETLOAD2_INDICATOR_COLOR);
+ read_color_button (GET_WIDGET ("netload2_loopback_color_button"), ma->settings, KEY_NETLOAD2_LOOPBACK_COLOR);
+ read_color_button (GET_WIDGET ("netload2_out_color_button"), ma->settings, KEY_NETLOAD2_OUT_COLOR);
+ read_color_button (GET_WIDGET ("swapload_free_color_button"), ma->settings, KEY_SWAPLOAD_FREE_COLOR);
+ read_color_button (GET_WIDGET ("swapload_used_color_button"), ma->settings, KEY_SWAPLOAD_USED_COLOR);
+
+ graph_size_spin_button_label = GET_WIDGET ("graph_size_spin_button_label");
+ orient = mate_panel_applet_get_orient(ma->applet);
+ switch (orient) {
+ case MATE_PANEL_APPLET_ORIENT_UP:
+ case MATE_PANEL_APPLET_ORIENT_DOWN:
+ graph_size_spin_button_label_txt = _("System m_onitor width:");
+ break;
+ default:
+ graph_size_spin_button_label_txt = _("System m_onitor height:");
+ }
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (graph_size_spin_button_label), graph_size_spin_button_label_txt);
+
+ read_spin_uint_button (GET_WIDGET ("graph_size_spin_button"), ma->settings, GRAPH_SIZE_KEY, GRAPH_SIZE_MIN, GRAPH_SIZE_MAX);
+ read_spin_uint_button (GET_WIDGET ("speed_spin_button"), ma->settings, REFRESH_RATE_KEY, REFRESH_RATE_MIN, REFRESH_RATE_MAX);
+
+ read_spin_uint64_button (GET_WIDGET ("net_threshold1_spin_button"), ma->settings, KEY_NET_THRESHOLD1, MIN_NET_THRESHOLD1, MAX_NET_THRESHOLD1);
+ read_spin_uint64_button (GET_WIDGET ("net_threshold2_spin_button"), ma->settings, KEY_NET_THRESHOLD2, MIN_NET_THRESHOLD2, MAX_NET_THRESHOLD2);
+ read_spin_uint64_button (GET_WIDGET ("net_threshold3_spin_button"), ma->settings, KEY_NET_THRESHOLD3, MIN_NET_THRESHOLD3, MAX_NET_THRESHOLD3);
+
+ ma->notebook = GET_WIDGET ("notebook");
+
+ ma->check_boxes[graph_cpuload] = GET_WIDGET ("graph_cpuload_checkbox");
+ ma->check_boxes[graph_memload] = GET_WIDGET ("graph_memload_checkbox");
+ ma->check_boxes[graph_netload2] = GET_WIDGET ("graph_netload2_checkbox");
+ ma->check_boxes[graph_swapload] = GET_WIDGET ("graph_swapload_checkbox");
+ ma->check_boxes[graph_loadavg] = GET_WIDGET ("graph_loadavg_checkbox");
+ ma->check_boxes[graph_diskload] = GET_WIDGET ("graph_diskload_checkbox");
+
+ g_settings_bind (ma->settings, VIEW_CPULOAD_KEY, ma->check_boxes[graph_cpuload], "active", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ma->settings, VIEW_MEMLOAD_KEY, ma->check_boxes[graph_memload], "active", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ma->settings, VIEW_NETLOAD_KEY, ma->check_boxes[graph_netload2], "active", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ma->settings, VIEW_SWAPLOAD_KEY, ma->check_boxes[graph_swapload], "active", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ma->settings, VIEW_LOADAVG_KEY, ma->check_boxes[graph_loadavg], "active", G_SETTINGS_BIND_DEFAULT);
+ g_settings_bind (ma->settings, VIEW_DISKLOAD_KEY, ma->check_boxes[graph_diskload], "active", G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind (ma->settings, DISKLOAD_NVME_KEY, GET_WIDGET ("nvme_checkbox"), "active", G_SETTINGS_BIND_DEFAULT);
+
+ #undef GET_WIDGET
+
+ properties_set_insensitive (ma);
+
+ gtk_builder_add_callback_symbols (builder,
+ "on_cpuload_usr_color_button_color_set", G_CALLBACK (on_cpuload_usr_color_button_color_set),
+ "on_cpuload_sys_color_button_color_set", G_CALLBACK (on_cpuload_sys_color_button_color_set),
+ "on_cpuload_nice_color_button_color_set", G_CALLBACK (on_cpuload_nice_color_button_color_set),
+ "on_cpuload_iowait_color_button_color_set", G_CALLBACK (on_cpuload_iowait_color_button_color_set),
+ "on_cpuload_free_color_button_color_set", G_CALLBACK (on_cpuload_free_color_button_color_set),
+ "on_memload_user_color_button_color_set", G_CALLBACK (on_memload_user_color_button_color_set),
+ "on_memload_shared_color_button_color_set", G_CALLBACK (on_memload_shared_color_button_color_set),
+ "on_memload_buffer_color_button_color_set", G_CALLBACK (on_memload_buffer_color_button_color_set),
+ "on_memload_cached_color_button_color_set", G_CALLBACK (on_memload_cached_color_button_color_set),
+ "on_memload_free_color_button_color_set", G_CALLBACK (on_memload_free_color_button_color_set),
+ "on_netload2_in_color_button_color_set", G_CALLBACK (on_netload2_in_color_button_color_set),
+ "on_netload2_out_color_button_color_set", G_CALLBACK (on_netload2_out_color_button_color_set),
+ "on_netload2_loopback_color_button_color_set", G_CALLBACK (on_netload2_loopback_color_button_color_set),
+ "on_netload2_background_color_button_color_set", G_CALLBACK (on_netload2_background_color_button_color_set),
+ "on_netload2_gridline_color_button_color_set", G_CALLBACK (on_netload2_gridline_color_button_color_set),
+ "on_netload2_indicator_color_button_color_set", G_CALLBACK (on_netload2_indicator_color_button_color_set),
+ "on_swapload_used_color_button_color_set", G_CALLBACK (on_swapload_used_color_button_color_set),
+ "on_swapload_free_color_button_color_set", G_CALLBACK (on_swapload_free_color_button_color_set),
+ "on_loadavg_average_color_button_color_set", G_CALLBACK (on_loadavg_average_color_button_color_set),
+ "on_loadavg_background_color_button_color_set", G_CALLBACK (on_loadavg_background_color_button_color_set),
+ "on_loadavg_gridline_color_button_color_set", G_CALLBACK (on_loadavg_gridline_color_button_color_set),
+ "on_diskload_read_color_button_color_set", G_CALLBACK (on_diskload_read_color_button_color_set),
+ "on_diskload_write_color_button_color_set", G_CALLBACK (on_diskload_write_color_button_color_set),
+ "on_diskload_free_color_button_color_set", G_CALLBACK (on_diskload_free_color_button_color_set),
+ "on_properties_dialog_response", G_CALLBACK (on_properties_dialog_response),
+ "on_graph_cpuload_checkbox_toggled", G_CALLBACK (on_graph_cpuload_checkbox_toggled),
+ "on_graph_memload_checkbox_toggled", G_CALLBACK (on_graph_memload_checkbox_toggled),
+ "on_graph_netload2_checkbox_toggled", G_CALLBACK (on_graph_netload2_checkbox_toggled),
+ "on_graph_swapload_checkbox_toggled", G_CALLBACK (on_graph_swapload_checkbox_toggled),
+ "on_graph_loadavg_checkbox_toggled", G_CALLBACK (on_graph_loadavg_checkbox_toggled),
+ "on_graph_diskload_checkbox_toggled", G_CALLBACK (on_graph_diskload_checkbox_toggled),
+ "on_nvme_checkbox_toggled", G_CALLBACK (on_nvme_checkbox_toggled),
+ "on_graph_size_spin_button_value_changed", G_CALLBACK (on_graph_size_spin_button_value_changed),
+ "on_speed_spin_button_value_changed", G_CALLBACK (on_speed_spin_button_value_changed),
+ "on_net_threshold1_spin_button_value_changed", G_CALLBACK (on_net_threshold1_spin_button_value_changed),
+ "on_net_threshold2_spin_button_value_changed", G_CALLBACK (on_net_threshold2_spin_button_value_changed),
+ "on_net_threshold3_spin_button_value_changed", G_CALLBACK (on_net_threshold3_spin_button_value_changed),
+ NULL);
+
+ gtk_builder_connect_signals (builder, ma);
+
+ g_object_unref (builder);
+
+ gtk_window_set_screen (GTK_WINDOW (ma->prop_dialog),
+ gtk_widget_get_screen (GTK_WIDGET (ma->applet)));
+
+ gtk_widget_show_all (ma->prop_dialog);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (ma->notebook),
+ ma->last_clicked);
+}