root/mh-home-sysmon/trunk/mh-home-sysmon.c

Revision 100, 10.7 kB (checked in by inz, 6 months ago)

Fix ugly white rectangles when showing home.

Line 
1 #include <gtk/gtk.h>
2 #include <sys/time.h>
3 #include <time.h>
4 #include <stdlib.h>
5
6 #include <dbus/dbus-glib.h>
7
8 #ifndef GTKDEBUG
9 #include <mce/dbus-names.h>
10 #include <mce/mode-names.h>
11 #include <libhildondesktop/libhildondesktop.h>
12 #endif
13
14 #include "datasource.h"
15 #include "mh-home-sysmon.h"
16
17 #include "mh-cpu-source.h"
18 #include "mh-mem-source.h"
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #define MH_HOME_SYSMON_GET_PRIVATE(x) (G_TYPE_INSTANCE_GET_PRIVATE((x), MH_TYPE_HOME_SYSMON, MhHomeSysmonPrivate))
24
25 typedef struct _MhHomeSysmonPrivate MhHomeSysmonPrivate;
26 struct _MhHomeSysmonPrivate {
27         GQueue *line_data;
28         GQueue *solid_data;
29
30 #ifndef GTKDEBUG
31         DBusGConnection *gconn;
32         DBusGProxy *proxy;
33 #endif
34
35         DataSource *line_source;
36         DataSource *solid_source;
37
38         PangoFontDescription *desc;
39
40         guint datapoints;
41         guint timer_source;
42
43         gboolean foreground;
44 };
45
46 #define TEXT_ALIGN_VMASK 0x3
47 #define TEXT_ALIGN_HMASK 0xc
48 typedef enum _TextAlign TextAlign;
49 enum _TextAlign {
50         TEXT_ALIGN_DEFAULT = 0,
51         TEXT_ALIGN_TOP = 1,
52         TEXT_ALIGN_BOTTOM = 2,
53         TEXT_ALIGN_MIDDLE = 3,
54         TEXT_ALIGN_LEFT = 1 << 2,
55         TEXT_ALIGN_RIGHT = 2 << 2,
56         TEXT_ALIGN_CENTER = 3 << 2
57 };
58
59 static gboolean mh_home_sysmon_expose(GtkWidget *widget,
60                                       GdkEventExpose *event);
61 static void mh_home_sysmon_screen_changed(GtkWidget *widget,
62                                           GdkScreen *old);
63 static gboolean mh_home_sysmon_update(gpointer user_data);
64 static void cairo_draw_text(cairo_t * cr,
65                             PangoFontDescription * desc,
66                             GtkRequisition *req,
67                             gint padding,
68                             const gchar *markup, TextAlign align);
69 static void mh_home_sysmon_foreground(HildonDesktopHomeItem *item);
70 static void mh_home_sysmon_background(HildonDesktopHomeItem *item);
71 static void mh_home_sysmon_display_ind(DBusGProxy *proxy,
72                                        gchar *display_state,
73                                        MhHomeSysmon *sysmon);
74
75 #ifndef GTKDEBUG
76 HD_DEFINE_PLUGIN(MhHomeSysmon, mh_home_sysmon,
77                  HILDON_DESKTOP_TYPE_HOME_ITEM);
78 #else
79 G_DEFINE_TYPE(MhHomeSysmon, mh_home_sysmon, GTK_TYPE_WINDOW);
80 #endif
81
82 static void mh_home_sysmon_finalize(GObject *obj)
83 {
84         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(obj);
85         g_source_remove(priv->timer_source);
86         g_queue_free(priv->line_data);
87         g_queue_free(priv->solid_data);
88
89         g_object_unref(priv->proxy);
90         g_object_unref(priv->gconn);
91 }
92
93 static void mh_home_sysmon_init(MhHomeSysmon * plugin)
94 {
95         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(plugin);
96         priv->line_data = g_queue_new();
97         priv->solid_data = g_queue_new();
98
99         priv->line_source = g_new0(DataSource, 1);
100         priv->solid_source = g_new0(DataSource, 1);
101
102         mh_cpu_source_load(priv->line_source);
103         mh_mem_source_load(priv->solid_source);
104
105         priv->line_source->ds_data =
106                 priv->line_source->init(priv->line_source);
107         priv->solid_source->ds_data =
108                 priv->solid_source->init(priv->solid_source);
109
110         priv->datapoints = 20;
111
112         priv->desc = pango_font_description_from_string("Sans 7");
113
114         priv->timer_source =
115                 g_timeout_add(5000, mh_home_sysmon_update, plugin);
116
117         priv->foreground = TRUE;
118
119         gtk_widget_set_size_request(GTK_WIDGET(plugin), 140, 140);
120 #ifndef GTKDEBUG
121         hildon_desktop_home_item_set_resize_type(HILDON_DESKTOP_HOME_ITEM
122                                                  (plugin),
123                                                  HILDON_DESKTOP_HOME_ITEM_RESIZE_BOTH);
124
125         priv->gconn = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
126         priv->proxy = dbus_g_proxy_new_for_name(priv->gconn,
127                                                 MCE_SERVICE,
128                                                 MCE_SIGNAL_PATH,
129                                                 MCE_SIGNAL_IF);
130         dbus_g_proxy_add_signal(priv->proxy,
131                                 MCE_DISPLAY_SIG,
132                                 G_TYPE_STRING,
133                                 G_TYPE_INVALID);
134         dbus_g_proxy_connect_signal(priv->proxy,
135                                     MCE_DISPLAY_SIG,
136                                     G_CALLBACK(mh_home_sysmon_display_ind),
137                                     plugin,
138                                     NULL);
139 #endif
140
141         gtk_widget_show_all(GTK_WIDGET(plugin));
142 }
143
144 static void mh_home_sysmon_class_init(MhHomeSysmonClass * klass)
145 {
146         GObjectClass *object_class = G_OBJECT_CLASS(klass);
147         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
148         HildonDesktopHomeItemClass *item_class =
149                 HILDON_DESKTOP_HOME_ITEM_CLASS(klass);
150         g_type_class_add_private(klass, sizeof(MhHomeSysmonPrivate));
151
152         object_class->finalize = mh_home_sysmon_finalize;
153
154         widget_class->expose_event = mh_home_sysmon_expose;
155         widget_class->screen_changed = mh_home_sysmon_screen_changed;
156
157         item_class->background = mh_home_sysmon_background;
158         item_class->foreground = mh_home_sysmon_foreground;
159 }
160
161 static gboolean mh_home_sysmon_update(gpointer user_data)
162 {
163         MhHomeSysmon *plugin = user_data;
164         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(plugin);
165
166         if (priv->line_source) {
167                 guint val =
168                         priv->line_source->get_value(priv->line_source->
169                                                      ds_data) * UINT_MAX;
170                 g_queue_push_head(priv->line_data, GUINT_TO_POINTER(val));
171
172         }
173         if (priv->solid_source) {
174                 guint val =
175                         priv->solid_source->get_value(priv->solid_source->
176                                                       ds_data) * UINT_MAX;
177                 g_queue_push_head(priv->solid_data, GUINT_TO_POINTER(val));
178
179         }
180
181         while (g_queue_get_length(priv->line_data) > priv->datapoints) {
182                 g_queue_pop_tail(priv->line_data);
183         }
184         if (g_queue_get_length(priv->solid_data) > priv->datapoints) {
185                 g_queue_pop_tail(priv->solid_data);
186         }
187
188         if (!priv->foreground) {
189                 gtk_widget_queue_draw(GTK_WIDGET(plugin));
190         }
191
192         return TRUE;
193 }
194
195 #ifndef PI
196 #define PI 3.1415926535
197 #endif
198 static gboolean mh_home_sysmon_expose(GtkWidget *widget,
199                                       GdkEventExpose *event)
200 {
201         cairo_t *cr;
202         GtkRequisition req;
203         cairo_path_t *path;
204
205         guint i;
206         GList *list;
207
208         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(widget);
209
210         cairo_pattern_t *pattern;
211
212         (void)event;
213
214         cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
215         req.height = widget->allocation.height;
216         req.width = widget->allocation.width;
217
218         pattern = cairo_pattern_create_linear(0, 0, 0, req.height);
219         cairo_pattern_add_color_stop_rgba(pattern, 0, 1.0, 1.0, 1.0, 0.5);
220         cairo_pattern_add_color_stop_rgba(pattern, 0.58579, 1.0, 1.0, 1.0,
221                                           0.2);
222         cairo_pattern_add_color_stop_rgba(pattern, 0.58579, 0, 0, 0, 0.4);
223         cairo_pattern_add_color_stop_rgba(pattern, 1, 1.0, 1.0, 1.0, 0.5);
224
225         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
226         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
227         cairo_paint(cr);
228
229         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
230         cairo_move_to(cr, 15.5, 5.5);
231         cairo_line_to(cr, req.width - 15.5, 5.5);
232         cairo_arc(cr, req.width - 15.5, 15.5, 10, -PI / 2, 0);
233         cairo_line_to(cr, req.width - 5.5, req.height - 15.5);
234         cairo_arc(cr, req.width - 15.5, req.height - 15.5, 10, 0, PI / 2);
235         cairo_line_to(cr, 15.5, req.height - 5.5);
236         cairo_arc(cr, 15.5, req.height - 15.5, 10, PI / 2, PI);
237         cairo_line_to(cr, 5.5, 15.5);
238         cairo_arc(cr, 15.5, 15.5, 10, -PI, -PI / 2);
239
240         cairo_set_line_width(cr, 2.0);
241         cairo_set_source(cr, pattern);
242         cairo_fill_preserve(cr);
243         path = cairo_copy_path(cr);
244         cairo_clip(cr);
245
246         cairo_pattern_destroy(pattern);
247
248         cairo_move_to(cr, (req.width - 7.5), (req.height - 7.5));
249         for (i = 0, list = g_queue_peek_head_link(priv->solid_data);
250              i < priv->datapoints && list; i++, list = list->next) {
251                 cairo_line_to(cr,
252                               ((req.width - 14) * (priv->datapoints - i -
253                                                    1) / (priv->datapoints -
254                                                          1)) + 7.5,
255                               ((UINT_MAX - GPOINTER_TO_UINT(list->data)) *
256                                (req.height - 14.0) / UINT_MAX) + 7.5);
257         }
258         cairo_line_to(cr,
259                       ((req.width - 14) * (priv->datapoints -
260                                            i) / (priv->datapoints - 1)) +
261                       7.5, (req.height - 7.5));
262         cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 0.7);
263         cairo_fill(cr);
264
265         for (i = 0, list = g_queue_peek_head_link(priv->line_data);
266              i < priv->datapoints && list; i++, list = list->next) {
267                 cairo_line_to(cr,
268                               ((req.width - 14) * (priv->datapoints - i -
269                                                    1) / (priv->datapoints -
270                                                          1)) + 7.5,
271                               ((UINT_MAX - GPOINTER_TO_UINT(list->data)) *
272                                (req.height - 14.0) / UINT_MAX) + 7.5);
273         }
274         cairo_set_source_rgba(cr, 1.0, 0, 0, 0.9);
275         cairo_stroke(cr);
276
277         cairo_append_path(cr, path);
278         cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.9);
279         cairo_stroke(cr);
280         cairo_path_destroy(path);
281
282         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
283 #define TEXT(src, text, valign, halign) \
284         if (priv->src ## _source && priv->src ## _source->text ## _text) \
285                 cairo_draw_text(cr, priv->desc, &req, 9, priv->src ## _source->text ## _text, TEXT_ALIGN_ ## valign | TEXT_ALIGN_ ## halign);
286         TEXT(line, max, TOP, LEFT);
287         TEXT(line, half, MIDDLE, LEFT);
288         TEXT(line, min, BOTTOM, LEFT);
289         TEXT(solid, max, TOP, RIGHT);
290         TEXT(solid, half, MIDDLE, RIGHT);
291         TEXT(solid, min, BOTTOM, RIGHT);
292 #undef TEXT
293
294         cairo_destroy(cr);
295
296         return TRUE;
297 }
298
299 static void mh_home_sysmon_screen_changed(GtkWidget *widget,
300                                           GdkScreen *old)
301 {
302         GdkScreen *screen = gtk_widget_get_screen(widget);
303         GdkColormap *cmap = gdk_screen_get_rgba_colormap(screen);
304
305         (void)old;
306
307         gtk_widget_set_colormap(widget, cmap);
308 }
309
310 static void cairo_draw_text(cairo_t * cr,
311                             PangoFontDescription * desc,
312                             GtkRequisition *req,
313                             gint padding,
314                             const gchar *markup, TextAlign align)
315 {
316         PangoLayout *layout;
317         PangoRectangle rect;
318         gint x;
319         gint y;
320
321         layout = pango_cairo_create_layout(cr);
322         pango_layout_set_font_description(layout, desc);
323         pango_layout_set_markup(layout, markup, -1);
324         pango_layout_get_extents(layout, &rect, NULL);
325
326         switch (align & TEXT_ALIGN_VMASK) {
327         case TEXT_ALIGN_BOTTOM:
328                 y = req->height - padding - PANGO_PIXELS(rect.height);
329                 break;
330         case TEXT_ALIGN_MIDDLE:
331                 y = (req->height - PANGO_PIXELS(rect.height)) / 2;
332                 break;
333         case TEXT_ALIGN_TOP:
334         default:
335                 y = padding;
336                 break;
337         }
338         switch (align & TEXT_ALIGN_HMASK) {
339         case TEXT_ALIGN_RIGHT:
340                 x = req->width - padding - PANGO_PIXELS(rect.width);
341                 break;
342         case TEXT_ALIGN_CENTER:
343                 x = (req->width - PANGO_PIXELS(rect.width)) / 2;
344                 break;
345         case TEXT_ALIGN_LEFT:
346         default:
347                 x = padding;
348                 break;
349         }
350
351         cairo_save(cr);
352         cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
353         cairo_move_to(cr, x - 1, y);
354         pango_cairo_show_layout(cr, layout);
355         cairo_move_to(cr, x + 1, y);
356         pango_cairo_show_layout(cr, layout);
357         cairo_move_to(cr, x, y - 1);
358         pango_cairo_show_layout(cr, layout);
359         cairo_move_to(cr, x, y + 1);
360         pango_cairo_show_layout(cr, layout);
361         cairo_restore(cr);
362         cairo_move_to(cr, x, y);
363         pango_cairo_show_layout(cr, layout);
364
365         g_object_unref(layout);
366 }
367
368 static void mh_home_sysmon_foreground(HildonDesktopHomeItem *item)
369 {
370         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(item);
371
372         priv->foreground = TRUE;
373 }
374
375 static void mh_home_sysmon_background(HildonDesktopHomeItem *item)
376 {
377         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(item);
378
379         priv->foreground = FALSE;
380 }
381
382 #ifndef GTKDEBUG
383 static void mh_home_sysmon_display_ind(DBusGProxy *proxy,
384                                        gchar *display_state,
385                                        MhHomeSysmon *sysmon)
386 {
387         MhHomeSysmonPrivate *priv = MH_HOME_SYSMON_GET_PRIVATE(sysmon);
388
389         (void)proxy;
390
391         if (strcmp(display_state, MCE_DISPLAY_OFF_STRING) == 0)
392         {
393                 if (priv->timer_source) {
394                         g_source_remove(priv->timer_source);
395                         priv->timer_source = 0;
396                 }
397         } else {
398                 if (!priv->timer_source) {
399                         priv->timer_source =
400                                 g_timeout_add(5000,
401                                               mh_home_sysmon_update, sysmon);
402                 }
403         }
404 }
405 #endif
Note: See TracBrowser for help on using the browser.