GTK+2 panel 

GTK+2 panel Git Source Tree

Root/libgpwidgets/gpw-cpu.c

1/* Gtk2Panel - A bleeding edge Gtk+2 panel
2 * Copyright (C) 2009 Nicola Fontana <ntd at entidi.it>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20
21/**
22 * SECTION:gpw-cpu
23 * @title: GpwCpu
24 * @short_description: A simple CPU graph
25 *
26 * The CPU status is shown throught subsequent vertical bars
27 * with one pixel width. These bars are drawn using three different
28 * colors to highlight the difference between user / nice / system
29 * CPU usages. The colors are fully modificable throught .gtkrc.
30 **/
31
32/**
33 * GpwCpu:
34 *
35 * All fields are private and should not be used directly.
36 * Use its public methods instead.
37 **/
38
39
40#include "gpw-cpu.h"
41#include "gpw-cpu-private.h"
42
43
44static void dispose (GObject *object);
45static void finalize (GObject *object);
46static void size_request (GtkWidget *widget,
47 GtkRequisition *requisition);
48static gboolean configure_event (GtkWidget *widget,
49 GdkEventConfigure *event);
50static gboolean expose_event (GtkWidget *widget,
51 GdkEventExpose *event);
52static gboolean update (GpwCpu *cpu);
53
54
55
56
57G_DEFINE_TYPE(GpwCpu, gpw_cpu, GTK_TYPE_DRAWING_AREA);
58
59
60static void
61gpw_cpu_class_init(GpwCpuClass *klass)
62{
63 GObjectClass *gobject_class;
64 GtkWidgetClass *widget_class;
65
66 gobject_class = (GObjectClass *) klass;
67 widget_class = (GtkWidgetClass *) klass;
68
69 g_type_class_add_private(klass, sizeof(GpwCpuPrivate));
70
71 gobject_class->dispose = dispose;
72 gobject_class->finalize = finalize;
73
74 widget_class->size_request = size_request;
75 widget_class->configure_event = configure_event;
76 widget_class->expose_event = expose_event;
77}
78
79static void
80gpw_cpu_init(GpwCpu *cpu)
81{
82 GpwCpuPrivate *data;
83
84 data = G_TYPE_INSTANCE_GET_PRIVATE(cpu, GPW_TYPE_CPU, GpwCpuPrivate);
85
86 data->poll = 0;
87 data->offscreen = NULL;
88 data->width = 40;
89 data->height = -1;
90 data->user = 0;
91 data->nice = 0;
92 data->system = 0;
93 data->idle = 0;
94
95 cpu->data = data;
96}
97
98static void
99dispose(GObject *object)
100{
101 GpwCpuPrivate *data = GPW_CPU_GET_DATA(object);
102
103 if (data->offscreen != NULL) {
104g_object_unref(data->offscreen);
105 data->offscreen = NULL;
106 }
107
108 G_OBJECT_CLASS(gpw_cpu_parent_class)->dispose(object);
109}
110
111static void
112finalize(GObject *object)
113{
114 GpwCpuPrivate *data = GPW_CPU_GET_DATA(object);
115
116 if (data->poll > 0) {
117g_source_remove(data->poll);
118 data->poll = 0;
119 }
120
121 G_OBJECT_CLASS(gpw_cpu_parent_class)->finalize(object);
122}
123
124static void
125size_request(GtkWidget *widget, GtkRequisition *requisition)
126{
127 if (requisition != NULL)
128 requisition->width = 40;
129
130 ((GtkWidgetClass *) gpw_cpu_parent_class)->size_request(widget, requisition);
131}
132
133static gboolean
134configure_event(GtkWidget *widget, GdkEventConfigure *event)
135{
136 GpwCpuPrivate *data;
137 gint width, height;
138
139 data = GPW_CPU_GET_DATA(widget);
140 width = widget->allocation.width;
141 height = widget->allocation.height;
142
143 if (data->offscreen) {
144if (data->width == width && data->height == height)
145 return TRUE;
146
147/* TODO: the widget size is changed, so I have to recreate
148 * the offscreen buffer. Now, the old offscreen content is
149 * discarded ... this is not the better solution! */
150g_object_unref(data->offscreen);
151 }
152
153 data->offscreen = gdk_pixmap_new(widget->window, width, height, -1);
154 data->width = width;
155 data->height = height;
156 gdk_draw_rectangle(data->offscreen,
157 widget->style->bg_gc[GTK_STATE_ACTIVE],
158 TRUE, 0, 0, width, height);
159
160 return TRUE;
161}
162
163static gboolean
164expose_event(GtkWidget *widget, GdkEventExpose *event)
165{
166 GpwCpuPrivate *data;
167
168 data = GPW_CPU_GET_DATA(widget);
169
170 /* Activate the polling, if needed */
171 if (data->poll == 0)
172 data->poll = g_timeout_add(1000, (GSourceFunc) update, widget);
173
174 gdk_draw_drawable(widget->window,
175 widget->style->bg_gc[GTK_STATE_ACTIVE],
176 data->offscreen,
177 event->area.x, event->area.y,
178 event->area.x, event->area.y,
179 event->area.width, event->area.height);
180
181 return FALSE;
182}
183
184static gboolean
185update(GpwCpu *cpu)
186{
187 GtkWidget *widget;
188 GpwCpuPrivate *data;
189 FILE *stream;
190 int result;
191 unsigned long user, nice, system, idle;
192 unsigned long d_user, d_nice, d_system, d_idle, d_total;
193 unsigned long quotient, error;
194 unsigned long l_user, l_nice, l_system;
195 GtkStyle *style;
196 gint y;
197
198 widget = (GtkWidget *) cpu;
199 data = GPW_CPU_GET_DATA(cpu);
200 stream = fopen("/proc/stat", "r");
201 if (stream == NULL)
202return FALSE;
203
204 result = fscanf(stream, "cpu %lu %lu %lu %lu",
205 &user, &nice, &system, &idle);
206 fclose(stream);
207
208 /* Read failed: try next time */
209 if (result == EOF)
210return TRUE;
211
212 d_user = user - data->user;
213 d_nice = nice - data->nice;
214 d_system = system - data->system;
215 d_idle = idle - data->idle;
216 d_total = d_user + d_nice + d_system + d_idle;
217
218 /* Better to check d_total validity ... */
219 if (d_total <= 0)
220return TRUE;
221
222 quotient = d_user * data->height;
223 l_user = quotient / d_total;
224 error = quotient % d_total;
225
226 quotient = d_nice * data->height + error;
227 l_nice = quotient / d_total;
228 error = quotient % d_total;
229
230 quotient = d_system * data->height + error;
231 l_system = quotient / d_total;
232 error = quotient % d_total;
233
234 style = widget->style;
235 gdk_draw_drawable(data->offscreen,
236 style->bg_gc[GTK_STATE_ACTIVE],
237 data->offscreen,
238 0, 0, 1, 0, data->width - 1, -1);
239
240 y = (gint) data->height;
241 if (l_user) {
242gdk_draw_line(data->offscreen,
243 style->fg_gc[GTK_STATE_ACTIVE],
244 0, y, 0, y - l_user - 1);
245y -= l_user;
246 }
247 if (l_nice) {
248gdk_draw_line(data->offscreen,
249 style->fg_gc[GTK_STATE_PRELIGHT],
250 0, y, 0, y - l_nice - 1);
251y -= l_nice;
252 }
253 if (l_system) {
254gdk_draw_line(data->offscreen,
255 style->fg_gc[GTK_STATE_SELECTED],
256 0, y, 0, y - l_system - 1);
257y -= l_system;
258 }
259 if (y > 0)
260gdk_draw_line(data->offscreen,
261 style->bg_gc[GTK_STATE_ACTIVE], 0, y, 0, 0);
262
263 data->user = user;
264 data->nice = nice;
265 data->system = system;
266 data->idle = idle;
267
268 gtk_widget_queue_draw(widget);
269 return TRUE;
270}

Archive Download this file

Branches

Tags