Adding upstream version 0.3.5.2+svn20080509.
[debian/lxpanel.git] / src / plugins / cpu / cpu.c
1 /*
2 * CPU usage plugin to lxpanel
3 *
4 * Copyright (C) 2004 by Alexandre Pereira da Silva <alexandre.pereira@poli.usp.br>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 /*A little bug fixed by Mykola <mykola@2ka.mipt.ru>:) */
22
23
24 #include <string.h>
25 #include <sys/time.h>
26 #include <time.h>
27 #include <sys/sysinfo.h>
28 #include <stdlib.h>
29 #include <glib/gi18n.h>
30
31 #include "plugin.h"
32 #include "panel.h"
33 #include "misc.h"
34
35 #define KILOBYTE 1024
36 #define MAX_WGSIZE 100
37
38 #include "dbg.h"
39 typedef unsigned long tick;
40
41 struct cpu_stat {
42 tick u, n, s, i;
43 };
44
45
46 typedef struct {
47 GdkGC *gc_cpu;
48 GdkColor *ccpu;
49 GtkWidget *da;
50 GtkWidget *evbox;
51 GdkPixmap *pixmap;
52 /* GtkTooltips *tip; */
53
54 int timer;
55 tick *stats_cpu;
56 unsigned int ini_stats;
57 int Wwg;
58 int Hwg;
59 struct cpu_stat cpu_anterior;
60 } cpu_t;
61
62
63 static int
64 cpu_update(cpu_t *c)
65 {
66 int cpu_u=0, cpu_s=0, cpu_n=0, cpu_i=100;
67 unsigned int i;
68 struct cpu_stat cpu, cpu_r;
69 FILE *stat;
70 float total;
71
72 ENTER;
73 if(!c->pixmap)
74 RET(TRUE);
75
76 stat = fopen("/proc/stat", "r");
77 if(!stat)
78 RET(TRUE);
79 fscanf(stat, "cpu %lu %lu %lu %lu", &cpu.u, &cpu.n, &cpu.s, &cpu.i);
80 fclose(stat);
81
82 cpu_r.u = cpu.u - c->cpu_anterior.u;
83 cpu_r.n = cpu.n - c->cpu_anterior.n;
84 cpu_r.s = cpu.s - c->cpu_anterior.s;
85 cpu_r.i = cpu.i - c->cpu_anterior.i;
86
87 total = cpu_r.u + cpu_r.n + cpu_r.s + cpu_r.i;
88 cpu_u = cpu_r.u * c->Hwg / total;
89 cpu_s = cpu_r.n * c->Hwg / total;
90 cpu_n = cpu_r.s * c->Hwg / total;
91 cpu_i = cpu_r.i * c->Hwg / total;
92
93 c->cpu_anterior = cpu;
94
95 c->stats_cpu[c->ini_stats++] = cpu_u + cpu_s + cpu_n;
96 c->ini_stats %= c->Wwg;
97
98 gdk_draw_rectangle(c->pixmap, c->da->style->black_gc, TRUE, 0, 0, c->Wwg, c->Hwg);
99 for (i = 0; i < c->Wwg; i++) {
100 int val;
101
102 val = c->stats_cpu[(i + c->ini_stats) % c->Wwg];
103 if (val)
104 gdk_draw_line(c->pixmap, c->gc_cpu, i, c->Hwg, i, c->Hwg - val);
105 }
106 gtk_widget_queue_draw(c->da);
107 RET(TRUE);
108 }
109
110 static gint
111 configure_event(GtkWidget *widget, GdkEventConfigure *event, cpu_t *c)
112 {
113 ENTER;
114 if (c->pixmap)
115 g_object_unref(c->pixmap);
116 c->Wwg = widget->allocation.width;
117 c->Hwg = widget->allocation.height;
118 if (c->stats_cpu)
119 g_free(c->stats_cpu);
120 c->stats_cpu = g_new0( typeof(*c->stats_cpu), c->Wwg);
121 c->pixmap = gdk_pixmap_new (widget->window,
122 widget->allocation.width,
123 widget->allocation.height,
124 -1);
125 gdk_draw_rectangle (c->pixmap,
126 widget->style->black_gc,
127 TRUE,
128 0, 0,
129 widget->allocation.width,
130 widget->allocation.height);
131
132 RET(TRUE);
133 }
134
135
136 static gint
137 expose_event(GtkWidget *widget, GdkEventExpose *event, cpu_t *c)
138 {
139 ENTER;
140 gdk_draw_drawable (widget->window,
141 c->da->style->black_gc,
142 c->pixmap,
143 event->area.x, event->area.y,
144 event->area.x, event->area.y,
145 event->area.width, event->area.height);
146
147 RET(FALSE);
148 }
149
150 static gboolean on_button_press(GtkWidget* w, GdkEventButton* evt, Plugin* plugin)
151 {
152 if( evt->button == 3 ) /* right button */
153 {
154 GtkMenu* popup = lxpanel_get_panel_menu( plugin->panel, plugin, FALSE );
155 gtk_menu_popup( popup, NULL, NULL, NULL, NULL, evt->button, evt->time );
156 return TRUE;
157 }
158 return FALSE;
159 }
160
161 static int
162 cpu_constructor(Plugin *p, char **fp)
163 {
164 cpu_t *c;
165
166 ENTER;
167 c = g_new0(cpu_t, 1);
168 p->priv = c;
169
170 p->pwid = gtk_event_box_new();
171 GTK_WIDGET_SET_FLAGS( p->pwid, GTK_NO_WINDOW );
172
173 c->da = gtk_drawing_area_new();
174 gtk_widget_set_size_request(c->da, 40, 20);
175 gtk_widget_add_events( c->da, GDK_BUTTON_PRESS_MASK );
176
177 gtk_widget_show(c->da);
178
179 c->gc_cpu = gdk_gc_new(p->panel->topgwin->window);
180
181 c->ccpu = (GdkColor *)malloc(sizeof(GdkColor));
182 gdk_color_parse("green", c->ccpu);
183 gdk_colormap_alloc_color(gdk_drawable_get_colormap(p->panel->topgwin->window), c->ccpu, FALSE, TRUE);
184 gdk_gc_set_foreground(c->gc_cpu, c->ccpu);
185
186 gtk_container_add(GTK_CONTAINER(p->pwid), c->da);
187 gtk_container_set_border_width (GTK_CONTAINER (p->pwid), 1);
188
189 g_signal_connect (G_OBJECT (c->da),"configure_event",
190 G_CALLBACK (configure_event), (gpointer) c);
191 g_signal_connect (G_OBJECT (c->da), "expose_event",
192 G_CALLBACK (expose_event), (gpointer) c);
193 g_signal_connect( c->da, "button-press-event",
194 G_CALLBACK(on_button_press), p );
195
196 c->timer = g_timeout_add(1000, (GSourceFunc) cpu_update, (gpointer) c);
197 RET(1);
198 }
199
200 static void
201 cpu_destructor(Plugin *p)
202 {
203 cpu_t *c = (cpu_t *) p->priv;
204
205 ENTER;
206 g_object_unref(c->pixmap);
207 g_object_unref(c->gc_cpu);
208 g_free(c->stats_cpu);
209 g_free(c->ccpu);
210 g_source_remove(c->timer);
211 /* g_object_unref( c->tip ); */
212 g_free(p->priv);
213 RET();
214 }
215
216
217 PluginClass cpu_plugin_class = {
218 fname: NULL,
219 count: 0,
220
221 type : "cpu",
222 name : N_("CPU Usage Monitor"),
223 version: "1.0",
224 description : N_("Display CPU usage"),
225
226 constructor : cpu_constructor,
227 destructor : cpu_destructor,
228 config : NULL,
229 save : NULL
230 };