1 /* GKrellM-trayicons
2 
3     Author, current maintainer:
4 
5         Tomas Styblo  <tripie@cpan.org>
6 
7    Copyright (C) 2003
8 
9    This program is free software which I release under the GNU General Public
10    License. You may redistribute and/or modify this program under the terms
11    of that license as published by the Free Software Foundation; either
12    version 2 of the License, or (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    To get a copy of the GNU General Puplic License,  write to the
20    Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 
23 #include <gkrellm2/gkrellm.h>
24 #include <utime.h>
25 #include <dirent.h>
26 #include <errno.h>
27 #include <math.h>
28 
29 #define xstr(s) str(s)
30 #define str(s) #s
31 #define MY_BUFLEN 1024
32 
33 typedef struct
34 {
35     gchar *activation_file;
36     gchar *icon_active_file;
37     gchar *icon_inactive_file;
38     gchar *left_click_active_command;
39     gchar *left_click_inactive_command;
40     gboolean blink;
41     gboolean popup;
42     gboolean activated;
43     gboolean icon_state;
44     time_t activation_file_mtime;
45     gint x;
46     gint y;
47     GkrellmDecalbutton *but;
48     /*
49     GString *buf;
50     */
51 } item_t;
52 
53 enum
54 {
55    ACTIVATION_FILE_COLUMN,
56    ICON_ACTIVE_PIXBUF_COLUMN,
57    ICON_ACTIVE_FILE_COLUMN,
58    ICON_INACTIVE_PIXBUF_COLUMN,
59    ICON_INACTIVE_FILE_COLUMN,
60    LEFT_CLICK_ACTIVE_COMMAND_COLUMN,
61    LEFT_CLICK_INACTIVE_COMMAND_COLUMN,
62    BLINK_COLUMN,
63    POPUP_COLUMN,
64    N_COLUMNS
65 };
66 
67 #ifndef VERSION
68 #error "VERSION is not defined."
69 #endif
70 
71 #define NOTICE_SEPARATOR "\n- - - - - - - - - - - -\n"
72 #define TREE_SIZE_PADDING 300
73 #define TREE_SIZE_MAX 600
74 #define TREE_HEIGHT 150
75 
76 static GkrellmMonitor *monitor;
77 static GArray *trayicons;
78 static GkrellmPanel *panel;
79 static gint icon_size = 16; /* the default */
80 static gint icon_padding = 4; /* the default */
81 static gint popup_timeout = 5; /* the default */
82 static GtkWidget *trayicons_vbox;
83 static GtkWidget *win_bubble;
84 static GdkColor popup_fg_color = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
85 static GdkColor popup_bg_color = { 0, 0xFFFF, 0x0000, 0x0000 };
86 static GtkWidget *active_popup = NULL;
87 static gint active_popup_icon;
88 static gint active_timeout = 0;
89 static gchar *active_popup_str = NULL;
90 
91 void setup_trayicons(gint first_create);
92 static GdkPixbuf *get_pixbuf(const gchar *filename, gint size);
93 static void draw_icon(gint i, gboolean state);
94 static void deactivate_icon(gint icon);
95 
destroy_bubble()96 static void destroy_bubble() {
97     if (active_popup) {
98         gtk_widget_destroy(active_popup);
99         active_popup = NULL;
100         g_free(active_popup_str);
101         active_popup_str = NULL;
102     }
103     if (active_timeout) {
104         gtk_timeout_remove(active_timeout);
105     }
106 }
107 
bubble_timeout(gpointer data)108 static gint bubble_timeout(gpointer data)
109 {
110     destroy_bubble();
111     return 0; /* cancel the timeout */
112 }
113 
bubble_button_press(GtkWidget * widget,GdkEventButton * event,gpointer data)114 static gboolean bubble_button_press(GtkWidget *widget,
115         GdkEventButton *event, gpointer data)
116 {
117     destroy_bubble();
118     deactivate_icon(active_popup_icon);
119     return TRUE;
120 }
121 
bubble_paint_window(gchar * str)122 static gint bubble_paint_window(gchar *str)
123 {
124   gtk_paint_flat_box(win_bubble->style, win_bubble->window,
125 		      GTK_STATE_NORMAL, GTK_SHADOW_OUT,
126 		      NULL, GTK_WIDGET(win_bubble), "tooltip",
127 		      0, 0, -1, -1);
128 
129   return FALSE;
130 }
131 
create_bubble(gchar * str,gint icon)132 static void create_bubble(gchar *str, gint icon)
133 {
134     GtkWidget *label;
135     GtkRequisition requisition;
136     GtkWidget *widget;
137     GtkStyle *style;
138     gint x, y, w, h, scr_w, scr_h;
139     GdkScreen *screen;
140 
141     if (active_popup) {
142         gchar *oldstr = g_strdup(active_popup_str);
143         destroy_bubble();
144         active_popup_str = g_strconcat(oldstr, NOTICE_SEPARATOR, str, NULL);
145         g_free(oldstr);
146     }
147     else {
148         active_popup_str = g_strdup(str);
149     }
150 
151     win_bubble = gtk_window_new(GTK_WINDOW_POPUP);
152     active_popup = win_bubble;
153     active_popup_icon = icon;
154     gtk_widget_set_app_paintable(win_bubble, TRUE);
155     gtk_window_set_resizable(GTK_WINDOW(win_bubble), FALSE);
156     gtk_widget_set_name(win_bubble, "gkrellm-trayicons-buuble");
157     gtk_container_set_border_width(GTK_CONTAINER(win_bubble), 4);
158 
159     g_signal_connect_swapped(win_bubble, "expose_event",
160             G_CALLBACK(bubble_paint_window), NULL);
161 
162     label = gtk_label_new(NULL);
163     gtk_widget_set_events (win_bubble, GDK_BUTTON_PRESS_MASK);
164     g_signal_connect(GTK_OBJECT(win_bubble), "button-press-event",
165             G_CALLBACK(bubble_button_press), NULL);
166     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
167     gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
168     gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &popup_fg_color);
169     gtk_widget_modify_bg(win_bubble, GTK_STATE_NORMAL, &popup_bg_color);
170     gtk_widget_show(label);
171     gtk_container_add(GTK_CONTAINER(win_bubble), label);
172     g_signal_connect (win_bubble, "destroy",
173             G_CALLBACK(gtk_widget_destroyed),
174             &win_bubble);
175 
176     gtk_widget_ensure_style(win_bubble);
177     style = win_bubble->style;
178 
179     screen = gtk_widget_get_screen(win_bubble);
180     scr_w = gdk_screen_get_width(screen);
181     scr_h = gdk_screen_get_height(screen);
182 
183     gtk_label_set_text(GTK_LABEL(label), active_popup_str);
184 
185     gtk_widget_size_request(win_bubble, &requisition);
186     w = requisition.width;
187     h = requisition.height;
188 
189     /*
190     gdk_window_get_pointer(gdk_screen_get_root_window (screen),
191             &x, &y, NULL);
192             */
193 
194     widget = panel->drawing_area;
195 
196     gdk_window_get_origin (widget->window, &x, &y);
197     if (GTK_WIDGET_NO_WINDOW (widget))
198     {
199         x += widget->allocation.x;
200         y += widget->allocation.y;
201     }
202 
203     x -= (w / 2 + 4);
204     if ((x + w) > scr_w)
205         x -= (x + w) - scr_w;
206     else if (x < 0)
207         x = 0;
208 
209     y -= (h + 6);
210     if ((y + h) > scr_h)
211         y -= (y + w) - scr_h;
212     else if (y < 0)
213         y = 0;
214 
215     /* printf("w=%d, h=%d, x=%d, y=%d\n", w, h, x, y); */
216 
217     gtk_window_move(GTK_WINDOW(win_bubble), x, y);
218     gtk_widget_show(win_bubble);
219 
220     if (popup_timeout > 0) {
221         active_timeout = gtk_timeout_add(popup_timeout * 1000, bubble_timeout, NULL);
222     }
223 }
224 
append_file_to_buf(const gchar * filename,GString * gs)225 void append_file_to_buf(const gchar *filename, GString *gs)
226 {
227     FILE *fh;
228     char buf[1024];
229     size_t num;
230 
231     if (! (fh = fopen(filename, "r"))) {
232         fprintf(stderr, "gkrellm-trayicons: cannot read activation file: %s (%s)",
233                 filename, strerror(errno));
234         gkrellm_message_dialog("Error", "Cannot read activation file.");
235         return;
236     }
237 
238     while ((num = fread(buf, sizeof(char), sizeof(buf), fh)) > 0) {
239         if (ferror(fh))
240             break;
241         g_string_append_len(gs, buf, num);
242     }
243 
244     if (ferror(fh)) {
245         fprintf(stderr, "gkrellm-trayicons: cannot read activation file: %s (%s)",
246                 filename, strerror(errno));
247         gkrellm_message_dialog("Error", "Cannot read activation file.");
248     }
249     if (fclose(fh) == EOF) {
250         fprintf(stderr, "gkrellm-trayicons: cannot close activation file: %s (%s)",
251                 filename, strerror(errno));
252         gkrellm_message_dialog("Error", "Cannot close activation file.");
253     }
254 
255     if (gs->str[gs->len - 1] == '\n') {
256         g_string_truncate(gs, gs->len - 1);
257     }
258 }
259 
update_trayicons_real()260 static void update_trayicons_real()
261 {
262     gint i;
263     struct stat st;
264 
265     for (i = 0; i < trayicons->len; i++) {
266         gchar *acfile = g_array_index(trayicons,item_t, i).activation_file;
267         GString *new = g_string_new("");
268 
269         /* check icons that should blink */
270         if (g_array_index(trayicons,item_t, i).activated &&
271                 g_array_index(trayicons,item_t, i).blink) {
272             draw_icon(i, !g_array_index(trayicons,item_t, i).icon_state);
273         }
274 
275         /* check new activations */
276         if (stat(acfile, &st) == -1) {
277             // gkrellm_message_dialog("Error", "Cannot stat activation file.");
278             continue;
279         }
280 
281         if (S_ISDIR(st.st_mode)) {
282             DIR *d;
283             struct dirent *de;
284             gboolean first = TRUE;
285 
286             if (chdir(acfile) == -1) {
287                 fprintf(stderr,
288                    "gkrellm-trayicons: cannot chdir to the activation directory: %s (%s)",
289                         acfile, strerror(errno));
290             }
291 
292             if (! (d = opendir(acfile))) {
293                 fprintf(stderr, "gkrellm-trayicons: cannot open activation directory: %s (%s)", acfile, strerror(errno));
294                 gkrellm_message_dialog("Error", "Cannot open activation directory.");
295                 continue;
296             }
297 
298             while ((de = readdir(d))) {
299                 if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) {
300                     if (! first) {
301                         g_string_append(new, NOTICE_SEPARATOR);
302                     }
303                     first = FALSE;
304                     append_file_to_buf(de->d_name, new);
305                     if (unlink(de->d_name) == -1) {
306                         fprintf(stderr, "gkrellm-trayicons: cannot unlink activation file: %s (%s)", de->d_name, strerror(errno));
307                         gkrellm_message_dialog("Error", "Cannot unlink activation file.");
308                     }
309                 }
310             }
311 
312             if (closedir(d) == -1) {
313                 fprintf(stderr,
314                         "gkrellm-trayicons: cannot close activation directory: %s (%s)",
315                         acfile, strerror(errno));
316                 gkrellm_message_dialog("Error", "Cannot close activation directory.");
317                 continue;
318             }
319 
320             if (first) {
321                 /* no file was read */
322                 continue;
323             }
324             else {
325                 /* activate icon */
326                 draw_icon(i, TRUE);
327                 g_array_index(trayicons,item_t, i).activated = TRUE;
328 
329                 if (g_array_index(trayicons,item_t, i).popup) {
330                     create_bubble(new->str, i);
331                 }
332             }
333         }
334         else {
335             if (g_array_index(trayicons,item_t, i).activation_file_mtime != 0 &&
336                     st.st_mtime != g_array_index(trayicons,item_t, i).activation_file_mtime) {
337                 append_file_to_buf(acfile, new);
338                 /* activate icon */
339                 draw_icon(i, TRUE);
340                 g_array_index(trayicons,item_t, i).activated = TRUE;
341 
342                 if (g_array_index(trayicons,item_t, i).popup) {
343                     create_bubble(new->str, i);
344                 }
345             }
346             g_array_index(trayicons,item_t, i).activation_file_mtime = st.st_mtime;
347         }
348         g_string_free(new, TRUE);
349     }
350     gkrellm_draw_panel_layers(panel);
351 }
352 
update_trayicons()353 static void update_trayicons()
354 {
355     if (GK.second_tick) {
356         update_trayicons_real();
357     }
358 }
359 
panel_expose_event(GtkWidget * widget,GdkEventExpose * ev,GkrellmPanel * p)360 static gint panel_expose_event(GtkWidget *widget, GdkEventExpose *ev, GkrellmPanel *p)
361 {
362     gdk_draw_pixmap(widget->window,
363             widget->style->fg_gc[GTK_WIDGET_STATE (widget)], p->pixmap,
364             ev->area.x, ev->area.y, ev->area.x, ev->area.y,
365             ev->area.width, ev->area.height);
366     return TRUE;
367 }
368 
deactivate_icon(gint icon)369 static void deactivate_icon(gint icon)
370 {
371     g_array_index(trayicons, item_t, icon).activated = FALSE;
372     draw_icon(icon, FALSE);
373     gkrellm_draw_panel_layers(panel);
374     /*
375     if (g_array_index(trayicons, item_t, icon).buf) {
376         g_string_free(g_array_index(trayicons, item_t, icon).buf, TRUE);
377         g_array_index(trayicons, item_t, icon).buf = NULL;
378     }
379     */
380 }
381 
cb_panel_button(GtkWidget * widget,GdkEventButton * ev,gpointer data)382 static gboolean cb_panel_button(GtkWidget *widget, GdkEventButton *ev,
383         gpointer data)
384 {
385     if (ev->button == 2)
386     {
387         gkrellm_open_config_window(monitor);
388         return TRUE;
389     }
390 
391     return FALSE;
392 }
393 
cb_icon_click_left(GkrellmDecalbutton * button,gpointer data)394 static void cb_icon_click_left(GkrellmDecalbutton *button, gpointer data)
395 {
396     gint icon = GPOINTER_TO_INT(data);
397     gchar *cmd;
398 
399     /* printf("left button on icon %d was pressed\n", GPOINTER_TO_INT(data)); */
400     if (g_array_index(trayicons, item_t, icon).activated) {
401         cmd = g_array_index(trayicons, item_t, icon).left_click_active_command;
402     }
403     else {
404         cmd = g_array_index(trayicons, item_t, icon).left_click_inactive_command;
405     }
406 
407     if (cmd) {
408         /* fprintf(stderr, "running command: %s\n", cmd); */
409         g_spawn_command_line_async(cmd, NULL);
410     }
411 
412     deactivate_icon(icon);
413     if (active_popup) {
414         destroy_bubble();
415     }
416 }
417 
cb_icon_click_right(GkrellmDecalbutton * button,gpointer data)418 static void cb_icon_click_right(GkrellmDecalbutton *button, gpointer data)
419 {
420     gint icon = GPOINTER_TO_INT(data);
421     /* printf("right button on icon %d was pressed\n", icon); */
422     if (active_popup) {
423         destroy_bubble();
424     }
425     else {
426         /*
427         if (g_array_index(trayicons, item_t, icon).buf) {
428             create_bubble(g_array_index(trayicons, item_t, icon).buf->str, icon);
429         }
430         */
431     }
432     deactivate_icon(icon);
433 }
434 
draw_icon(gint i,gboolean state)435 static void draw_icon(gint i, gboolean state)
436 {
437     GkrellmPiximage *pix_prim;
438     GkrellmPiximage *pix_sec;
439     gchar *filename_prim;
440     gchar *filename_sec;
441 
442     if (state) {
443         filename_prim = g_array_index(trayicons, item_t, i).icon_active_file;
444         filename_sec = g_array_index(trayicons, item_t, i).icon_inactive_file;
445     }
446     else {
447         filename_prim = g_array_index(trayicons, item_t, i).icon_inactive_file;
448         filename_sec = g_array_index(trayicons, item_t, i).icon_active_file;
449     }
450 
451     if (g_array_index(trayicons, item_t, i).but) {
452         gkrellm_destroy_button(g_array_index(trayicons, item_t, i).but);
453     }
454 
455     if ((pix_prim = gkrellm_piximage_new_from_file(filename_prim)) &&
456          (pix_sec = gkrellm_piximage_new_from_file(filename_sec))) {
457         /*
458         GkrellmDecalbutton *but = gkrellm_make_scaled_button(panel,
459                            pix_prim, cb_icon_click_left, GINT_TO_POINTER(i),
460                            FALSE, FALSE,
461                            0, 0, 1,
462                            g_array_index(trayicons, item_t, i).x,
463                            g_array_index(trayicons, item_t, i).y,
464                            icon_size, icon_size);
465                            */
466         GkrellmDecalbutton *but = gkrellm_make_overlay_button(panel,
467                 cb_icon_click_left, GINT_TO_POINTER(i),
468                 g_array_index(trayicons, item_t, i).x,
469                 g_array_index(trayicons, item_t, i).y,
470                 icon_size, icon_size,
471                 pix_prim,
472                 pix_sec);
473         but->type = 0; /* disable auto hide */
474 
475         gkrellm_destroy_piximage(pix_prim);
476         gkrellm_destroy_piximage(pix_sec);
477 
478         if (but) {
479             g_array_index(trayicons, item_t, i).icon_state = state;
480             g_array_index(trayicons, item_t, i).but = but;
481             gkrellm_decal_button_right_connect(but, cb_icon_click_right, GINT_TO_POINTER(i));
482             gkrellm_show_button(but);
483         }
484         else {
485             gkrellm_message_dialog("Error", "Cannot create button.");
486         }
487     }
488     else {
489         gkrellm_message_dialog("Error", "Cannot load icon.");
490     }
491 }
492 
setup_trayicons(gint first_create)493 void setup_trayicons(gint first_create)
494 {
495     GkrellmStyle *trayicons_style;
496     gint i;
497     GkrellmMargin *margin;
498     gint x, y;
499     GdkPixmap *bg_scaled = NULL;
500     GkrellmDecal *decal_bg = NULL;
501     GkrellmPiximage *bg = NULL;
502 
503     if (panel) {
504         gkrellm_destroy_decal_list(panel);
505         for (i = 0; i < trayicons->len; i++) {
506             g_array_index(trayicons, item_t, i).but = NULL;
507         }
508         gkrellm_panel_destroy(panel);
509     }
510     panel = gkrellm_panel_new0();
511 
512     trayicons_style = gkrellm_meter_style(DEFAULT_STYLE_ID);
513     margin = gkrellm_get_style_margins(trayicons_style);
514 
515     /*
516     fprintf(stderr, "num icons: %d\n", trayicons->len);
517     fprintf(stderr, "chart width: %d\n", gkrellm_chart_width());
518     fprintf(stderr, "margin left: %d\n", margin->left);
519     fprintf(stderr, "margin right: %d\n", margin->right);
520     */
521 
522     /* calculate height so we can create the background first */
523     x = margin->left;
524     y = margin->top;
525     for (i = 0; i < trayicons->len; i++) {
526         if (x + icon_size + margin->right > gkrellm_chart_width()) {
527             x = margin->left;
528             y += icon_size;
529             y += icon_padding;
530         }
531         x += icon_size;
532         x += icon_padding;
533     }
534 
535     /* create the background */
536     if ((bg = gkrellm_bg_meter_piximage(DEFAULT_STYLE_ID))) {
537         gkrellm_scale_piximage_to_pixmap(bg, &bg_scaled, NULL,
538                 gkrellm_chart_width(), y + icon_size + margin->bottom);
539     }
540 
541     if (bg_scaled) {
542         decal_bg = gkrellm_create_decal_pixmap(panel, bg_scaled, NULL, 0, NULL, 0, 0);
543         gkrellm_draw_decal_pixmap(panel, decal_bg, 0);
544     }
545 
546     /* position and draw all the icons */
547     x = margin->left;
548     y = margin->top;
549     for (i = 0; i < trayicons->len; i++) {
550         if (x + icon_size + margin->right > gkrellm_chart_width()) {
551             x = margin->left;
552             y += icon_size;
553             y += icon_padding;
554         }
555         /* fprintf(stderr, "%d, %d, %d\n", i, x, y); */
556         g_array_index(trayicons, item_t, i).x = x;
557         g_array_index(trayicons, item_t, i).y = y;
558         draw_icon(i, FALSE);
559         x += icon_size;
560         x += icon_padding;
561     }
562 
563     /* configure and create the panel */
564     gkrellm_panel_configure(panel, NULL, trayicons_style);
565     if (trayicons->len > 0) {
566         gkrellm_panel_configure_set_height(panel, y + icon_size + margin->bottom);
567     }
568     else {
569         gkrellm_panel_configure_set_height(panel, 1);
570         gkrellm_panel_hide(panel);
571     }
572     gkrellm_panel_create(trayicons_vbox, monitor, panel);
573     gkrellm_draw_panel_layers(panel);
574 
575     g_signal_connect(G_OBJECT(panel->drawing_area), "expose_event",
576         G_CALLBACK(panel_expose_event), panel);
577     g_signal_connect(G_OBJECT(panel->drawing_area), "button_press_event",
578         G_CALLBACK(cb_panel_button), NULL);
579 }
580 
create_trayicons(GtkWidget * vbox,gint first_create)581 void create_trayicons(GtkWidget *vbox, gint first_create)
582 {
583     trayicons_vbox = vbox;
584     setup_trayicons(first_create);
585     update_trayicons_real();
586 }
587 
588 /*
589  *	Configuration page
590  */
591 
592 static GtkWidget                *activation_file_entry;
593 static GtkWidget                *icon_active_file_entry;
594 static GtkWidget                *icon_inactive_file_entry;
595 static GtkWidget                *left_click_active_command_entry;
596 static GtkWidget                *left_click_inactive_command_entry;
597 static GtkListStore             *store_trayicons;
598 static GtkWidget                *tree_trayicons;
599 static gint                     trayicons_item=0;
600 static GtkTreePath              *path_selected = NULL;
601 static GtkWidget                *btn_modify;
602 static GtkWidget                *popup_fg_draw;
603 static GtkWidget                *popup_bg_draw;
604 
error_msg(gchar * message)605 void error_msg(gchar *message)
606 {
607     gkrellm_config_message_dialog("Error", message);
608 }
609 
610 /*
611     static void
612 destroy_item(gpointer data)
613 {
614     g_free(((item_t *)data)->activation_file);
615     g_free(((item_t *)data)->icon_active_file);
616     g_free(((item_t *)data)->icon_inactive_file);
617     g_free(((item_t *)data)->left_click_active_command);
618     g_free(((item_t *)data)->left_click_inactive_command);
619     g_free(data);
620 }
621 */
622 
on_clear_click(GtkButton * button,gpointer * data)623 static void on_clear_click(GtkButton *button, gpointer *data)
624 {
625     gtk_entry_set_text(GTK_ENTRY(activation_file_entry), "");
626     gtk_entry_set_text(GTK_ENTRY(icon_active_file_entry), "");
627     gtk_entry_set_text(GTK_ENTRY(icon_inactive_file_entry), "");
628     gtk_entry_set_text(GTK_ENTRY(left_click_active_command_entry), "");
629     gtk_entry_set_text(GTK_ENTRY(left_click_inactive_command_entry), "");
630 }
631 
632 
on_add_click(GtkButton * button,gpointer * data)633 static void on_add_click(GtkButton *button, gpointer *data)
634 {
635     struct stat st;
636     GtkTreeIter iter;
637     const gchar *activation_file = gtk_entry_get_text(GTK_ENTRY(activation_file_entry));
638     const gchar *icon_active_file = gtk_entry_get_text(GTK_ENTRY(icon_active_file_entry));
639     const gchar *icon_inactive_file = gtk_entry_get_text(GTK_ENTRY(icon_inactive_file_entry));
640     const gchar *left_click_active_command = gtk_entry_get_text(GTK_ENTRY(left_click_active_command_entry));
641     const gchar *left_click_inactive_command = gtk_entry_get_text(GTK_ENTRY(left_click_inactive_command_entry));
642 
643     if (!activation_file[0])
644     {
645         error_msg("Please enter activation file path.");
646         return;
647     }
648 
649     if (!icon_active_file[0]) {
650         error_msg("Please enter active icon path.");
651         return;
652     }
653 
654     if (!icon_inactive_file[0]) {
655         error_msg("Please enter inactive icon path.");
656         return;
657     }
658 
659     if (stat(activation_file, &st) == -1) {
660         error_msg("Activation file/dir doesn't exist.");
661         return;
662     }
663 
664     if (stat(icon_active_file, &st) == -1) {
665         error_msg("Active icon file doesn't exist.");
666         return;
667     }
668 
669     if (stat(icon_inactive_file, &st) == -1) {
670         error_msg("Inactive icon file doesn't exist.");
671         return;
672     }
673 
674     if (GPOINTER_TO_INT(data) == 1) {
675         if (path_selected && gtk_tree_model_get_iter(GTK_TREE_MODEL(store_trayicons), &iter, path_selected)) {
676             gtk_list_store_set(store_trayicons, &iter,
677                         ACTIVATION_FILE_COLUMN, activation_file,
678                         ICON_ACTIVE_FILE_COLUMN, icon_active_file,
679                         ICON_INACTIVE_FILE_COLUMN, icon_inactive_file,
680                         LEFT_CLICK_ACTIVE_COMMAND_COLUMN, left_click_active_command,
681                         LEFT_CLICK_INACTIVE_COMMAND_COLUMN, left_click_inactive_command,
682                         ICON_ACTIVE_PIXBUF_COLUMN, get_pixbuf(icon_active_file, 16),
683                         ICON_INACTIVE_PIXBUF_COLUMN, get_pixbuf(icon_inactive_file, 16),
684                         -1);
685         }
686     }
687     else {
688         gtk_list_store_append(store_trayicons, &iter);
689         gtk_list_store_set(store_trayicons, &iter,
690                     ACTIVATION_FILE_COLUMN, activation_file,
691                     ICON_ACTIVE_FILE_COLUMN, icon_active_file,
692                     ICON_INACTIVE_FILE_COLUMN, icon_inactive_file,
693                     LEFT_CLICK_ACTIVE_COMMAND_COLUMN, left_click_active_command,
694                     LEFT_CLICK_INACTIVE_COMMAND_COLUMN, left_click_inactive_command,
695                     ICON_ACTIVE_PIXBUF_COLUMN, get_pixbuf(icon_active_file, 16),
696                     ICON_INACTIVE_PIXBUF_COLUMN, get_pixbuf(icon_inactive_file, 16),
697                     -1);
698     }
699 
700     return;
701 }
702 
on_del_click(GtkButton * button,gpointer * data)703 static void on_del_click(GtkButton *button, gpointer *data)
704 {
705     GtkTreeSelection *sel;
706     GtkListStore *store;
707     GtkTreeIter iter;
708 
709     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_trayicons));
710     if (gtk_tree_selection_get_selected(sel, (GtkTreeModel **)&store, &iter)) {
711         gtk_list_store_remove(store, &iter);
712     }
713 }
714 
on_up_click(GtkButton * button,gpointer * data)715 static void on_up_click(GtkButton *button, gpointer *data)
716 {
717     GtkTreeSelection *sel;
718     GtkListStore *store;
719     GtkTreeIter iter;
720 
721     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_trayicons));
722     if (gtk_tree_selection_get_selected(sel, (GtkTreeModel **)&store, &iter)) {
723         gchar *path_str;
724         gint path_num;
725 
726         path_str = gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(store), &iter);
727         path_num = atoi(path_str);
728 
729         if (path_num - 2 >= -1) {
730             gchar npath[256];
731             GtkTreeIter iter2;
732             GtkTreePath *path;
733 
734             if (path_num - 2 == -1) {
735                 gtk_list_store_move_after(store, &iter, NULL);
736             }
737             else {
738                 snprintf(npath, sizeof(npath), "%d", path_num - 2);
739                 path = gtk_tree_path_new_from_string(npath);
740                 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter2, path);
741                 gtk_list_store_move_after(store, &iter, &iter2);
742             }
743         }
744 
745         g_free(path_str);
746     }
747 }
748 
on_down_click(GtkButton * button,gpointer * data)749 static void on_down_click(GtkButton *button, gpointer *data)
750 {
751     GtkTreeSelection *sel;
752     GtkListStore *store;
753     GtkTreeIter iter;
754 
755     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_trayicons));
756     if (gtk_tree_selection_get_selected(sel, (GtkTreeModel **)&store, &iter)) {
757         GtkTreeIter iter2;
758         memcpy(&iter2, &iter, sizeof(iter));
759         if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter2)) {
760             gtk_list_store_move_after(store, &iter, &iter2);
761         }
762     }
763 }
764 
on_colorsel_click(GtkButton * button,gpointer * data)765 static void on_colorsel_click(GtkButton *button, gpointer *data)
766 {
767     gint response;
768     GtkColorSelection *cs;
769     GtkWidget *colorseldlg;
770     gboolean fg = (GPOINTER_TO_INT(data) == 1 ? TRUE : FALSE);
771 
772     /* Create color selection dialog */
773     colorseldlg = gtk_color_selection_dialog_new(fg ? "Select foreground color" : "Select background color");
774 
775     /* Get the ColorSelection widget */
776     cs = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel);
777 
778     gtk_color_selection_set_previous_color(cs, fg ? &popup_fg_color : &popup_bg_color);
779     gtk_color_selection_set_current_color(cs, fg ? &popup_fg_color : &popup_bg_color);
780     gtk_color_selection_set_has_palette(cs, TRUE);
781 
782     /* Show the dialog */
783     response = gtk_dialog_run(GTK_DIALOG(colorseldlg));
784 
785     if (response == GTK_RESPONSE_OK) {
786         gtk_color_selection_get_current_color(cs, fg ? &popup_fg_color : &popup_bg_color);
787         gtk_widget_modify_bg(fg ? popup_fg_draw : popup_bg_draw,
788                 GTK_STATE_NORMAL, fg ? &popup_fg_color : &popup_bg_color);
789     }
790 
791     gtk_widget_destroy (colorseldlg);
792 }
793 
cursor_changed(GtkTreeView * tree,gpointer data)794 static void cursor_changed(GtkTreeView *tree, gpointer data)
795 {
796     GtkTreeIter iter;
797     GtkTreePath *path;
798     gchar *activation_file;
799     gchar *icon_active_file;
800     gchar *icon_inactive_file;
801     gchar *left_click_active_command;
802     gchar *left_click_inactive_command;
803 
804     gtk_tree_view_get_cursor(tree, &path, NULL);
805     if (path == NULL) {
806         return;
807     }
808 
809     if (path_selected) gtk_tree_path_free(path_selected);
810     path_selected = gtk_tree_path_copy(path);
811     g_object_set(G_OBJECT(btn_modify), "sensitive", TRUE, NULL);
812 
813     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(store_trayicons), &iter, path)) {
814         gtk_tree_model_get(GTK_TREE_MODEL(store_trayicons), &iter,
815                 ACTIVATION_FILE_COLUMN, &activation_file,
816                 ICON_ACTIVE_FILE_COLUMN, &icon_active_file,
817                 ICON_INACTIVE_FILE_COLUMN, &icon_inactive_file,
818                 LEFT_CLICK_ACTIVE_COMMAND_COLUMN, &left_click_active_command,
819                 LEFT_CLICK_INACTIVE_COMMAND_COLUMN, &left_click_inactive_command,
820                 -1);
821 
822         gtk_entry_set_text(GTK_ENTRY(activation_file_entry), activation_file);
823         gtk_entry_set_text(GTK_ENTRY(icon_active_file_entry), icon_active_file);
824         gtk_entry_set_text(GTK_ENTRY(icon_inactive_file_entry), icon_inactive_file);
825         gtk_entry_set_text(GTK_ENTRY(left_click_active_command_entry), left_click_active_command ?
826                 left_click_active_command : "");
827         gtk_entry_set_text(GTK_ENTRY(left_click_inactive_command_entry),
828             left_click_inactive_command ? left_click_inactive_command : "");
829     }
830 }
831 
832 
row_toggled(GtkCellRendererText * renderer,gchar * row,gpointer data)833 static void row_toggled(GtkCellRendererText *renderer,
834         gchar *row, gpointer data)
835 {
836     GtkTreeIter iter;
837 
838     if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store_trayicons), &iter,
839                 NULL, atoi(row))) {
840         gtk_list_store_set(store_trayicons, &iter, GPOINTER_TO_INT(data),
841                 !gtk_cell_renderer_toggle_get_active(GTK_CELL_RENDERER_TOGGLE(renderer)), -1);
842     }
843 }
844 
cb_icon_size(GtkMenuItem * item,gpointer data)845 static void cb_icon_size(GtkMenuItem *item, gpointer data)
846 {
847     icon_size = GPOINTER_TO_INT(data);
848 }
849 
cb_icon_padding(GtkMenuItem * item,gpointer data)850 static void cb_icon_padding(GtkMenuItem *item, gpointer data)
851 {
852     icon_padding = GPOINTER_TO_INT(data);
853 }
854 
cb_popup_timeout(GtkMenuItem * item,gpointer data)855 static void cb_popup_timeout(GtkMenuItem *item, gpointer data)
856 {
857     popup_timeout = GPOINTER_TO_INT(data);
858 }
859 
860 static GtkWidget *picker;
861 
store_filename(GtkButton * but,gpointer user_data)862 static void store_filename(GtkButton *but, gpointer user_data)
863 {
864    const gchar *selected_filename;
865 
866    selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (picker));
867    gtk_entry_set_text(GTK_ENTRY(user_data), selected_filename);
868 }
869 
config_filepicker(GtkButton * button,gpointer * data)870 static void config_filepicker(GtkButton *button, gpointer *data)
871 {
872     picker = gtk_file_selection_new("Select file");
873     g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(picker)->ok_button),
874                  "clicked", G_CALLBACK(store_filename), data);
875 
876     /* Ensure that the dialog box is destroyed when the user clicks a button. */
877     g_signal_connect_swapped (GTK_OBJECT (GTK_FILE_SELECTION (picker)->ok_button),
878             "clicked",
879             G_CALLBACK (gtk_widget_destroy),
880             (gpointer) picker);
881 
882     g_signal_connect_swapped (GTK_OBJECT (GTK_FILE_SELECTION (picker)->cancel_button),
883             "clicked",
884             G_CALLBACK (gtk_widget_destroy),
885             (gpointer) picker);
886 
887     gtk_widget_show(picker);
888 }
889 
890 /* Create a new hbox with an image and a label packed into it
891  * and return the box. */
button_box(const gchar * label_text,const gchar * stock_id)892 GtkWidget *button_box(const gchar *label_text, const gchar *stock_id)
893 {
894     GtkWidget *box;
895     GtkWidget *label;
896     GtkWidget *image;
897     GtkWidget *button;
898 
899     /* Create box for image and label */
900     box = gtk_hbox_new(FALSE, 0);
901     gtk_container_set_border_width(GTK_CONTAINER (box), 2);
902 
903     /* Now on to the image stuff */
904     image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_SMALL_TOOLBAR);
905 
906     /* Create a label for the button */
907     label = gtk_label_new(label_text);
908 
909     /* Pack the image and label into the box */
910     gtk_box_pack_start(GTK_BOX (box), image, FALSE, FALSE, 3);
911     gtk_box_pack_start(GTK_BOX (box), label, FALSE, FALSE, 3);
912 
913     gtk_widget_show(image);
914     gtk_widget_show(label);
915     gtk_widget_show (box);
916 
917     button = gtk_button_new();
918     gtk_container_add(GTK_CONTAINER(button), box);
919     gtk_widget_show(button);
920 
921     return button;
922 }
923 
create_trayicons_tab(GtkWidget * tab_vbox)924 static void create_trayicons_tab(GtkWidget *tab_vbox)
925 {
926     GtkWidget		        *vbox;
927     GtkWidget		        *tabs;
928     GtkWidget               *btn_hbox;
929     GtkWidget               *table;
930     GtkWidget               *table_set;
931     gint                    i;
932 
933     tabs = gtk_notebook_new();
934     gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
935     gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
936 
937     /* File location tab */
938 
939     vbox = gkrellm_gtk_notebook_page(tabs, "Icons");
940     btn_hbox = gtk_hbox_new(FALSE, 5);
941 
942     /* buttons */
943     {
944         GtkWidget               *btn_add;
945         GtkWidget               *btn_del;
946         GtkWidget               *btn_clear;
947         GtkWidget               *btn_up;
948         GtkWidget               *btn_down;
949 
950         btn_add = button_box("Add", GTK_STOCK_ADD);
951         gtk_signal_connect(GTK_OBJECT(btn_add), "clicked",
952                 GTK_SIGNAL_FUNC(on_add_click), GINT_TO_POINTER(0));
953 
954         btn_del = button_box("Remove", GTK_STOCK_REMOVE);
955         gtk_signal_connect(GTK_OBJECT(btn_del), "clicked",
956                 GTK_SIGNAL_FUNC(on_del_click), NULL);
957 
958         btn_modify = button_box("Modify selected", GTK_STOCK_APPLY);
959         gtk_signal_connect(GTK_OBJECT(btn_modify), "clicked",
960                 GTK_SIGNAL_FUNC(on_add_click), GINT_TO_POINTER(1));
961         g_object_set(G_OBJECT(btn_modify), "sensitive", FALSE, NULL);
962 
963         btn_clear = button_box("Clear", GTK_STOCK_CLEAR);
964         gtk_signal_connect(GTK_OBJECT(btn_clear), "clicked",
965                 GTK_SIGNAL_FUNC(on_clear_click), NULL);
966 
967         btn_up = button_box("Up", GTK_STOCK_GO_UP);
968         gtk_signal_connect(GTK_OBJECT(btn_up), "clicked",
969                 GTK_SIGNAL_FUNC(on_up_click), NULL);
970 
971         btn_down = button_box("Down", GTK_STOCK_GO_DOWN);
972         gtk_signal_connect(GTK_OBJECT(btn_down), "clicked",
973                 GTK_SIGNAL_FUNC(on_down_click), NULL);
974 
975         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_add, TRUE, TRUE, 2);
976         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_del, TRUE, TRUE, 2);
977         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_modify, TRUE, TRUE, 2);
978         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_up, TRUE, TRUE, 2);
979         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_down, TRUE, TRUE, 2);
980         gtk_box_pack_start(GTK_BOX(btn_hbox), btn_clear, TRUE, TRUE, 2);
981     }
982 
983     store_trayicons = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING,
984             GDK_TYPE_PIXBUF, G_TYPE_STRING,
985             GDK_TYPE_PIXBUF, G_TYPE_STRING,
986             G_TYPE_STRING, G_TYPE_STRING,
987             G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
988 
989     for (i = 0; i < trayicons->len; i++)
990     {
991         GtkTreeIter iter;
992         gtk_list_store_append(store_trayicons, &iter);
993         gtk_list_store_set(store_trayicons, &iter,
994                 ACTIVATION_FILE_COLUMN, g_strdup(g_array_index(trayicons,item_t,i).activation_file),
995                 ICON_ACTIVE_PIXBUF_COLUMN, get_pixbuf(g_array_index(trayicons,item_t,i).icon_active_file, 16),
996                 ICON_ACTIVE_FILE_COLUMN, g_strdup(g_array_index(trayicons,item_t,i).icon_active_file),
997                 ICON_INACTIVE_PIXBUF_COLUMN, get_pixbuf(g_array_index(trayicons,item_t,i).icon_inactive_file, 16),
998                 ICON_INACTIVE_FILE_COLUMN, g_strdup(g_array_index(trayicons,item_t,i).icon_inactive_file),
999                 LEFT_CLICK_ACTIVE_COMMAND_COLUMN, g_strdup(g_array_index(trayicons,item_t,i).left_click_active_command),
1000                 LEFT_CLICK_INACTIVE_COMMAND_COLUMN, g_strdup(g_array_index(trayicons,item_t,i).left_click_inactive_command),
1001                 BLINK_COLUMN, g_array_index(trayicons,item_t,i).blink,
1002                 POPUP_COLUMN, g_array_index(trayicons,item_t,i).popup,
1003                 -1
1004 );
1005     }
1006     trayicons_item=0;
1007 
1008     table = gtk_table_new(4, 3, FALSE);
1009 
1010     /* activation file */
1011     {
1012         GtkWidget               *activation_file_picker_but;
1013         GtkWidget               *activation_file_lbl;
1014         GtkWidget               *activation_file_align;
1015         GtkWidget               *warning_lbl;
1016 
1017         activation_file_entry = gtk_entry_new_with_max_length(255);
1018         activation_file_picker_but = button_box("Pick file", GTK_STOCK_OPEN);
1019         g_signal_connect(G_OBJECT(activation_file_picker_but), "clicked",
1020                 G_CALLBACK(config_filepicker), activation_file_entry);
1021         activation_file_align = gtk_alignment_new(0, 0.5, 0, 0);
1022         activation_file_lbl=gtk_label_new("Activation file/dir path:");
1023         gtk_container_add(GTK_CONTAINER(activation_file_align), activation_file_lbl);
1024         gtk_table_attach(GTK_TABLE(table), activation_file_align, 0, 1, 0, 1, GTK_FILL, 0, 5, 5);
1025         gtk_table_attach(GTK_TABLE(table), activation_file_entry, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1026         gtk_table_attach(GTK_TABLE(table), activation_file_picker_but, 2, 3, 0, 1, GTK_FILL, 0, 5, 5);
1027 
1028         /* warning */
1029         warning_lbl=gtk_label_new("WARNING: All files in the specified directory are *deleted*.");
1030         gtk_table_attach(GTK_TABLE(table), warning_lbl, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1031     }
1032 
1033     /* icon active */
1034     {
1035         GtkWidget               *icon_active_file_picker_but;
1036         GtkWidget               *icon_active_file_align;
1037         GtkWidget               *icon_active_file_lbl;
1038 
1039         icon_active_file_entry = gtk_entry_new_with_max_length(255);
1040         icon_active_file_picker_but = button_box("Pick file", GTK_STOCK_OPEN);
1041         g_signal_connect(G_OBJECT(icon_active_file_picker_but), "clicked",
1042                 G_CALLBACK(config_filepicker), icon_active_file_entry);
1043         icon_active_file_align = gtk_alignment_new(0, 0.5, 0, 0);
1044         icon_active_file_lbl=gtk_label_new("Active icon file path:");
1045         gtk_container_add(GTK_CONTAINER(icon_active_file_align), icon_active_file_lbl);
1046         gtk_table_attach(GTK_TABLE(table), icon_active_file_align, 0, 1, 2, 3, GTK_FILL, 0, 5, 5);
1047         gtk_table_attach(GTK_TABLE(table), icon_active_file_entry, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1048         gtk_table_attach(GTK_TABLE(table), icon_active_file_picker_but, 2, 3, 2, 3, GTK_FILL, 0, 5, 5);
1049     }
1050 
1051     /* icon inactive */
1052     {
1053         GtkWidget               *icon_inactive_file_picker_but;
1054         GtkWidget               *icon_inactive_file_align;
1055         GtkWidget               *icon_inactive_file_lbl;
1056 
1057         icon_inactive_file_entry = gtk_entry_new_with_max_length(255);
1058         icon_inactive_file_picker_but = button_box("Pick file", GTK_STOCK_OPEN);
1059         g_signal_connect(G_OBJECT(icon_inactive_file_picker_but), "clicked",
1060                 G_CALLBACK(config_filepicker), icon_inactive_file_entry);
1061         icon_inactive_file_align = gtk_alignment_new(0, 0.5, 0, 0);
1062         icon_inactive_file_lbl=gtk_label_new("Inactive icon file path:");
1063         gtk_container_add(GTK_CONTAINER(icon_inactive_file_align), icon_inactive_file_lbl);
1064         gtk_table_attach(GTK_TABLE(table), icon_inactive_file_align, 0, 1, 3, 4, GTK_FILL, 0, 5, 5);
1065         gtk_table_attach(GTK_TABLE(table), icon_inactive_file_entry, 1, 2, 3, 4, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1066         gtk_table_attach(GTK_TABLE(table), icon_inactive_file_picker_but, 2, 3, 3, 4, GTK_FILL, 0, 5, 5);
1067     }
1068 
1069     /* left click active command */
1070     {
1071         GtkWidget               *left_click_active_command_align;
1072         GtkWidget               *left_click_active_command_lbl;
1073 
1074         left_click_active_command_align = gtk_alignment_new(0, 0.5, 0, 0);
1075         left_click_active_command_lbl=gtk_label_new("Active command:");
1076         gtk_container_add(GTK_CONTAINER(left_click_active_command_align), left_click_active_command_lbl);
1077         left_click_active_command_entry = gtk_entry_new_with_max_length(255);
1078         gtk_table_attach(GTK_TABLE(table), left_click_active_command_align, 0, 1, 4, 5, GTK_FILL, 0, 5, 5);
1079         gtk_table_attach(GTK_TABLE(table), left_click_active_command_entry, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1080     }
1081 
1082     /* left click inactive command */
1083     {
1084         GtkWidget               *left_click_inactive_command_align;
1085         GtkWidget               *left_click_inactive_command_lbl;
1086 
1087         left_click_inactive_command_align = gtk_alignment_new(0, 0.5, 0, 0);
1088         left_click_inactive_command_lbl=gtk_label_new("Inactive command:");
1089         gtk_container_add(GTK_CONTAINER(left_click_inactive_command_align), left_click_inactive_command_lbl);
1090         left_click_inactive_command_entry = gtk_entry_new_with_max_length(255);
1091         gtk_table_attach(GTK_TABLE(table), left_click_inactive_command_align, 0, 1, 5, 6, GTK_FILL, 0, 5, 5);
1092         gtk_table_attach(GTK_TABLE(table), left_click_inactive_command_entry, 1, 2, 5, 6, GTK_FILL | GTK_EXPAND, 0, 5, 5);
1093     }
1094 
1095     gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 2);
1096     gtk_box_pack_start(GTK_BOX(vbox), btn_hbox, FALSE, FALSE, 2);
1097 
1098     /* tree view and its columns */
1099     {
1100         GtkTreeSelection        *select;
1101         GtkCellRenderer         *renderer;
1102         GtkTreeViewColumn       *column;
1103         GdkScreen               *screen;
1104         GtkWidget               *scrolled_window;
1105         gint                    tree_width;
1106 
1107         tree_trayicons = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store_trayicons));
1108         select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_trayicons));
1109         gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
1110 
1111         screen = gtk_widget_get_screen(tree_trayicons);
1112         tree_width = gdk_screen_get_width(screen) - TREE_SIZE_PADDING;
1113         if (tree_width > TREE_SIZE_MAX) tree_width = TREE_SIZE_MAX;
1114 
1115         /* column pixbuf - icon active */
1116         renderer = gtk_cell_renderer_pixbuf_new();
1117         column = gtk_tree_view_column_new_with_attributes ("Active icon", renderer,
1118                                                        "pixbuf", ICON_ACTIVE_PIXBUF_COLUMN, NULL);
1119         g_object_set(G_OBJECT(column), "resizable", FALSE, NULL);
1120         gtk_tree_view_append_column (GTK_TREE_VIEW(tree_trayicons), column);
1121 
1122         /* column pixbuf - icon inactive */
1123         renderer = gtk_cell_renderer_pixbuf_new();
1124         column = gtk_tree_view_column_new_with_attributes ("Inactive icon", renderer,
1125                                                        "pixbuf", ICON_INACTIVE_PIXBUF_COLUMN, NULL);
1126         g_object_set(G_OBJECT(column), "resizable", FALSE, NULL);
1127         gtk_tree_view_append_column (GTK_TREE_VIEW(tree_trayicons), column);
1128 
1129         /* column blink */
1130         renderer = gtk_cell_renderer_toggle_new();
1131         g_object_set(G_OBJECT(renderer), "activatable", TRUE, NULL);
1132         g_signal_connect(G_OBJECT(renderer), "toggled",
1133                       G_CALLBACK(row_toggled), GINT_TO_POINTER(BLINK_COLUMN));
1134         column = gtk_tree_view_column_new_with_attributes ("Blink", renderer,
1135                                                        "active", BLINK_COLUMN,
1136                                                        NULL);
1137         g_object_set(G_OBJECT(column), "resizable", FALSE, NULL);
1138         gtk_tree_view_append_column (GTK_TREE_VIEW(tree_trayicons), column);
1139 
1140         /* column popup */
1141         renderer = gtk_cell_renderer_toggle_new();
1142         g_object_set(G_OBJECT(renderer), "activatable", TRUE, NULL);
1143         g_signal_connect(G_OBJECT(renderer), "toggled",
1144                       G_CALLBACK(row_toggled), GINT_TO_POINTER(POPUP_COLUMN));
1145         column = gtk_tree_view_column_new_with_attributes ("Popup", renderer,
1146                                                        "active", POPUP_COLUMN,
1147                                                        NULL);
1148         g_object_set(G_OBJECT(column), "resizable", FALSE, NULL);
1149         gtk_tree_view_append_column (GTK_TREE_VIEW(tree_trayicons), column);
1150 
1151         /* column activation file */
1152         renderer = gtk_cell_renderer_text_new();
1153         g_object_set(G_OBJECT(renderer), "editable", FALSE, NULL);
1154         column = gtk_tree_view_column_new_with_attributes ("Activation file/dir", renderer,
1155                                                        "text", ACTIVATION_FILE_COLUMN, NULL);
1156         g_object_set(G_OBJECT(column), "resizable", TRUE, NULL);
1157         gtk_tree_view_column_set_max_width(column, 300);
1158         gtk_tree_view_append_column (GTK_TREE_VIEW(tree_trayicons), column);
1159 
1160         /* tree view settings */
1161         g_object_set(G_OBJECT(tree_trayicons), "headers-visible", TRUE, NULL);
1162         gtk_widget_set_size_request(tree_trayicons, tree_width, TREE_HEIGHT);
1163 
1164         gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree_trayicons));
1165         scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1166         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1167         gtk_container_add(GTK_CONTAINER(scrolled_window), tree_trayicons);
1168         gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 12);
1169         g_signal_connect(G_OBJECT(tree_trayicons), "cursor-changed",
1170                       G_CALLBACK(cursor_changed), NULL);
1171     }
1172 
1173     /****************/
1174     /* Settings tab */
1175     /****************/
1176     vbox = gkrellm_gtk_notebook_page(tabs, "Settings");
1177     table_set = gtk_table_new(5, 2, FALSE);
1178 
1179     /* icon size */
1180     {
1181         GtkWidget               *icon_size_lbl;
1182         GtkWidget               *icon_size_align;
1183         GtkWidget               *icon_size_align_optmenu;
1184         GtkWidget               *icon_size_menu;
1185         GtkWidget               *icon_size_optmenu;
1186         gint                    select_icon_size = 0;
1187         static const struct ConfigIconSize {
1188             gchar *title;
1189             gint size;
1190         } config_icon_size[] = {
1191             { "16 x 16", 16 },
1192             { "20 x 20", 20 },
1193             { "24 x 24", 24 },
1194             { "32 x 32", 32 },
1195             { "48 x 48", 48 },
1196             { "64 x 64", 64 },
1197         };
1198 
1199         icon_size_lbl = gtk_label_new("Size at which icons will be displayed:");
1200         icon_size_align = gtk_alignment_new(1, 0, 0, 0);
1201         gtk_container_add(GTK_CONTAINER(icon_size_align), icon_size_lbl);
1202         gtk_table_attach(GTK_TABLE(table_set), icon_size_align, 0, 1, 0, 1, GTK_FILL, 0, 5, 5);
1203 
1204         icon_size_menu = gtk_menu_new();
1205         for (i = 0; i < sizeof(config_icon_size) / sizeof(struct ConfigIconSize); i++) {
1206             GtkWidget *item;
1207             item = gtk_menu_item_new_with_label(config_icon_size[i].title);
1208             g_signal_connect(G_OBJECT(item), "select", G_CALLBACK(cb_icon_size),
1209                     GINT_TO_POINTER(config_icon_size[i].size));
1210             gtk_menu_shell_append(GTK_MENU_SHELL(icon_size_menu), item);
1211             if (config_icon_size[i].size == icon_size) {
1212                 select_icon_size = i;
1213             }
1214         }
1215 
1216         icon_size_optmenu = gtk_option_menu_new();
1217         gtk_option_menu_set_menu(GTK_OPTION_MENU(icon_size_optmenu), icon_size_menu);
1218         gtk_option_menu_set_history(GTK_OPTION_MENU(icon_size_optmenu), select_icon_size);
1219         icon_size_align_optmenu = gtk_alignment_new(0, 0, 0, 0);
1220         gtk_container_add(GTK_CONTAINER(icon_size_align_optmenu), icon_size_optmenu);
1221         gtk_table_attach(GTK_TABLE(table_set), icon_size_align_optmenu, 1, 2, 0, 1, GTK_FILL, 0, 5, 5);
1222     }
1223 
1224     /* icon padding */
1225     {
1226         GtkWidget               *icon_padding_lbl;
1227         GtkWidget               *icon_padding_align;
1228         GtkWidget               *icon_padding_align_optmenu;
1229         GtkWidget               *icon_padding_menu;
1230         GtkWidget               *icon_padding_optmenu;
1231         gint                    select_icon_padding = 0;
1232 
1233         icon_padding_lbl = gtk_label_new("Padding between icons:");
1234         icon_padding_align = gtk_alignment_new(1, 0, 0, 0);
1235         gtk_container_add(GTK_CONTAINER(icon_padding_align), icon_padding_lbl);
1236         gtk_table_attach(GTK_TABLE(table_set), icon_padding_align, 0, 1, 1, 2, GTK_FILL, 0, 5, 5);
1237 
1238         icon_padding_menu = gtk_menu_new();
1239         for (i = 1; i <= 16; i++) {
1240             GtkWidget *item;
1241             gchar label[128];
1242             snprintf(label, sizeof(label), "%d", i);
1243             item = gtk_menu_item_new_with_label(label);
1244             g_signal_connect(G_OBJECT(item), "select", G_CALLBACK(cb_icon_padding),
1245                     GINT_TO_POINTER(i));
1246             gtk_menu_shell_append(GTK_MENU_SHELL(icon_padding_menu), item);
1247             if (i == icon_padding) {
1248                 select_icon_padding = i - 1;
1249             }
1250         }
1251 
1252         icon_padding_optmenu = gtk_option_menu_new();
1253         gtk_option_menu_set_menu(GTK_OPTION_MENU(icon_padding_optmenu), icon_padding_menu);
1254         gtk_option_menu_set_history(GTK_OPTION_MENU(icon_padding_optmenu), select_icon_padding);
1255         icon_padding_align_optmenu = gtk_alignment_new(0, 0, 0, 0);
1256         gtk_container_add(GTK_CONTAINER(icon_padding_align_optmenu), icon_padding_optmenu);
1257         gtk_table_attach(GTK_TABLE(table_set), icon_padding_align_optmenu, 1, 2, 1, 2, GTK_FILL, 0, 5, 5);
1258     }
1259 
1260     /* popup timeout */
1261     {
1262         GtkWidget               *popup_timeout_lbl;
1263         GtkWidget               *popup_timeout_align;
1264         GtkWidget               *popup_timeout_align_optmenu;
1265         GtkWidget               *popup_timeout_menu;
1266         GtkWidget               *popup_timeout_optmenu;
1267         gint                    select_popup_timeout = 0;
1268         static const gint config_popup_timeout[] = {
1269             0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1270             12, 14, 16, 18, 20, 25, 30, 40, 50, 60,
1271             -1 /* end */
1272         };
1273 
1274         popup_timeout_lbl = gtk_label_new("Popup timeout:");
1275         popup_timeout_align = gtk_alignment_new(1, 0, 0, 0);
1276         gtk_container_add(GTK_CONTAINER(popup_timeout_align), popup_timeout_lbl);
1277         gtk_table_attach(GTK_TABLE(table_set), popup_timeout_align, 0, 1, 2, 3, GTK_FILL, 0, 5, 5);
1278 
1279         popup_timeout_menu = gtk_menu_new();
1280         i = 0;
1281         while (config_popup_timeout[i] != -1) {
1282             GtkWidget *item;
1283             gchar label[128];
1284             gint timeout = config_popup_timeout[i];
1285 
1286             snprintf(label, sizeof(label), "%d", timeout);
1287             item = gtk_menu_item_new_with_label(label);
1288             g_signal_connect(G_OBJECT(item), "select", G_CALLBACK(cb_popup_timeout),
1289                     GINT_TO_POINTER(timeout));
1290             gtk_menu_shell_append(GTK_MENU_SHELL(popup_timeout_menu), item);
1291             if (timeout == popup_timeout) {
1292                 select_popup_timeout = i;
1293             }
1294             i++;
1295         }
1296 
1297         popup_timeout_optmenu = gtk_option_menu_new();
1298         gtk_option_menu_set_menu(GTK_OPTION_MENU(popup_timeout_optmenu), popup_timeout_menu);
1299         gtk_option_menu_set_history(GTK_OPTION_MENU(popup_timeout_optmenu), select_popup_timeout);
1300         popup_timeout_align_optmenu = gtk_alignment_new(0, 0, 0, 0);
1301         gtk_container_add(GTK_CONTAINER(popup_timeout_align_optmenu), popup_timeout_optmenu);
1302         gtk_table_attach(GTK_TABLE(table_set), popup_timeout_align_optmenu, 1, 2, 2, 3, GTK_FILL, 0, 5, 5);
1303     }
1304 
1305     /* popup foreground color */
1306     {
1307         GtkWidget               *popup_fg_lbl;
1308         GtkWidget               *popup_fg_align;
1309         GtkWidget               *popup_fg_button;
1310 
1311         popup_fg_lbl = gtk_label_new("Popup foreground color:");
1312         popup_fg_align = gtk_alignment_new(1, 0, 0, 0);
1313         gtk_container_add(GTK_CONTAINER(popup_fg_align), popup_fg_lbl);
1314         gtk_table_attach(GTK_TABLE(table_set), popup_fg_align, 0, 1, 3, 4, GTK_FILL, 0, 5, 5);
1315 
1316         popup_fg_draw = gtk_drawing_area_new();
1317         gtk_widget_modify_bg(popup_fg_draw, GTK_STATE_NORMAL, &popup_fg_color);
1318         gtk_widget_set_size_request(GTK_WIDGET(popup_fg_draw), 40, 15);
1319 
1320         popup_fg_button = gtk_button_new();
1321         gtk_container_add(GTK_CONTAINER(popup_fg_button), popup_fg_draw);
1322         gtk_signal_connect(GTK_OBJECT(popup_fg_button), "clicked",
1323                 GTK_SIGNAL_FUNC(on_colorsel_click), GINT_TO_POINTER(1));
1324 
1325         gtk_table_attach(GTK_TABLE(table_set), popup_fg_button, 1, 2, 3, 4, GTK_FILL, 0, 5, 5);
1326     }
1327 
1328     /* popup background color */
1329     {
1330         GtkWidget               *popup_bg_lbl;
1331         GtkWidget               *popup_bg_align;
1332         GtkWidget               *popup_bg_button;
1333 
1334         popup_bg_lbl = gtk_label_new("Popup background color:");
1335         popup_bg_align = gtk_alignment_new(1, 0, 0, 0);
1336         gtk_container_add(GTK_CONTAINER(popup_bg_align), popup_bg_lbl);
1337         gtk_table_attach(GTK_TABLE(table_set), popup_bg_align, 0, 1, 4, 5, GTK_FILL, 0, 5, 5);
1338 
1339         popup_bg_draw = gtk_drawing_area_new();
1340         gtk_widget_modify_bg(popup_bg_draw, GTK_STATE_NORMAL, &popup_bg_color);
1341         gtk_widget_set_size_request(GTK_WIDGET(popup_bg_draw), 40, 15);
1342 
1343         popup_bg_button = gtk_button_new();
1344         gtk_container_add(GTK_CONTAINER(popup_bg_button), popup_bg_draw);
1345         gtk_signal_connect(GTK_OBJECT(popup_bg_button), "clicked",
1346                 GTK_SIGNAL_FUNC(on_colorsel_click), GINT_TO_POINTER(0));
1347 
1348         gtk_table_attach(GTK_TABLE(table_set), popup_bg_button, 1, 2, 4, 5, GTK_FILL, 0, 5, 5);
1349     }
1350 
1351     gtk_box_pack_start(GTK_BOX(vbox), table_set, FALSE, FALSE, 2);
1352 
1353     /************/
1354     /* Info tab */
1355     /************/
1356     {
1357         GtkWidget *info_text_w;
1358         static const gchar *trayicons_info_text[] = {
1359         "<b>Trayicons plugin " VERSION "\n",
1360         "\n",
1361         "<b>Usage:\n",
1362         "left click - deactivate the icon and run the command\n"
1363         "right click - deactivate the icon\n"
1364         "middle click - open the configuration dialog\n"
1365         "\n",
1366         "<b>Homepage: ",
1367         "http://sweb.cz/tripie/gkrellm/trayicons/\n",
1368         "<b>Author: ",
1369         "Tomas Styblo <tripie@cpan.org>\n"
1370         "\n"
1371         "Copyright (C) 2003\n"
1372         "Distributed under the ",
1373         "<b>GNU General Public License (GPL)\n"
1374         };
1375 
1376         vbox = gkrellm_gtk_notebook_page(tabs, "Info");
1377         info_text_w = gkrellm_gtk_scrolled_text_view(vbox, NULL,
1378                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1379         gkrellm_gtk_text_view_append_strings(info_text_w, (char **)trayicons_info_text,
1380                 sizeof(trayicons_info_text) / sizeof(gchar *));
1381     }
1382 }
1383 
get_pixbuf(const gchar * filename,gint size)1384 static GdkPixbuf *get_pixbuf(const gchar *filename, gint size)
1385 {
1386     GdkPixbuf *px = NULL;
1387 
1388     if (! (px = gdk_pixbuf_new_from_file(filename, NULL))) {
1389         return NULL;
1390     }
1391 
1392     return gdk_pixbuf_scale_simple(px, size, size, GDK_INTERP_BILINEAR);
1393 }
1394 
save_trayicons_config(FILE * f)1395 static void save_trayicons_config(FILE *f)
1396 {
1397     gint i;
1398 
1399     /*
1400     printf("Saving config...\n");
1401     */
1402 
1403     fprintf(f, "trayicons icon_size %i\n", icon_size);
1404     fprintf(f, "trayicons icon_padding %i\n", icon_padding);
1405     fprintf(f, "trayicons popup_timeout %i\n", popup_timeout);
1406     fprintf(f, "trayicons popup_fg_color #%04X%04X%04X\n",
1407             popup_fg_color.red, popup_fg_color.green, popup_fg_color.blue);
1408     fprintf(f, "trayicons popup_bg_color #%04X%04X%04X\n",
1409             popup_bg_color.red, popup_bg_color.green, popup_bg_color.blue);
1410     for (i = 0; i < trayicons->len; i++)
1411     {
1412         fprintf(f,"trayicons activation_file%i %s\n",i,g_array_index(trayicons,item_t,i).activation_file);
1413         fprintf(f,"trayicons icon_active_file%i %s\n",i,g_array_index(trayicons,item_t,i).icon_active_file);
1414         fprintf(f,"trayicons icon_inactive_file%i %s\n",i,g_array_index(trayicons,item_t,i).icon_inactive_file);
1415         if (g_array_index(trayicons,item_t,i).left_click_active_command) {
1416             fprintf(f,"trayicons left_click_active_command%i %s\n",i,g_array_index(trayicons,item_t,i).left_click_active_command);
1417         }
1418         if (g_array_index(trayicons,item_t,i).left_click_inactive_command) {
1419             fprintf(f,"trayicons left_click_inactive_command%i %s\n",i,g_array_index(trayicons,item_t,i).left_click_inactive_command);
1420         }
1421         fprintf(f,"trayicons blink%i %d\n",i,g_array_index(trayicons,item_t,i).blink);
1422 
1423         /* popup must be the last - see load_trayicons_config() */
1424         fprintf(f,"trayicons popup%i %d\n",i,g_array_index(trayicons,item_t,i).popup);
1425     }
1426 }
1427 
1428 static item_t  c;
1429 
load_trayicons_config(gchar * arg)1430 static void load_trayicons_config(gchar *arg)
1431 {
1432     gchar   buf[MY_BUFLEN+1];
1433     gint    i;
1434     gboolean boolean;
1435 
1436     /*
1437     printf("trayicons_config=<%s>\n", arg);
1438     */
1439 
1440     if (sscanf(arg, "icon_size %i",&i) == 1) {
1441         icon_size = i;
1442     }
1443     else if (sscanf(arg, "icon_padding %i",&i) == 1) {
1444         icon_padding = i;
1445     }
1446     else if (sscanf(arg, "popup_timeout %i",&i) == 1) {
1447         popup_timeout = i;
1448     }
1449     else if (sscanf(arg, "popup_fg_color %" xstr(MY_BUFLEN) "s", buf) == 1) {
1450         if (!gdk_color_parse(buf, &popup_fg_color)) {
1451             fprintf(stderr, "gkrellm-trayicons: cannot parse color: %s\n", buf);
1452         }
1453     }
1454     else if (sscanf(arg, "popup_bg_color %" xstr(MY_BUFLEN) "s", buf) == 1) {
1455         if (!gdk_color_parse(buf, &popup_bg_color)) {
1456             fprintf(stderr, "gkrellm-trayicons: cannot parse color: %s\n", buf);
1457         }
1458     }
1459     else if (sscanf(arg, "activation_file%i %" xstr(MY_BUFLEN) "s", &i, buf) == 2) {
1460         c.activation_file = g_strdup(buf);
1461     }
1462     else if (sscanf(arg, "icon_active_file%i %" xstr(MY_BUFLEN) "s", &i, buf) == 2) {
1463         c.icon_active_file = g_strdup(buf);
1464     }
1465     else if (sscanf(arg, "icon_inactive_file%i %" xstr(MY_BUFLEN) "s", &i, buf) == 2) {
1466         c.icon_inactive_file = g_strdup(buf);
1467     }
1468     else if (strncmp(arg, "left_click_active_command", strlen("left_click_active_command")) == 0) {
1469         char *p;
1470         if ((p = strchr(arg, ' '))) {
1471             c.left_click_active_command = g_strdup(p+1);
1472         }
1473     }
1474     else if (strncmp(arg, "left_click_inactive_command", strlen("left_click_inactive_command")) == 0) {
1475         char *p;
1476         if ((p = strchr(arg, ' '))) {
1477             c.left_click_inactive_command = g_strdup(p+1);
1478         }
1479     }
1480     else if (sscanf(arg, "blink%i %i",&i,&boolean) == 2) {
1481         c.blink = boolean;
1482     }
1483     else if (sscanf(arg, "popup%i %i",&i,&boolean) == 2) {
1484         c.popup = boolean;
1485         /* finish the item */
1486         g_array_append_val(trayicons, c);
1487         memset(&c, 0, sizeof(c));
1488     }
1489 }
1490 
apply_trayicons_config()1491 static void apply_trayicons_config()
1492 {
1493     gint i;
1494     GtkTreeIter iter;
1495 
1496     /*
1497     printf("Applying config...\n");
1498     */
1499 
1500     for (i = 0; i < trayicons->len; i++)
1501     {
1502         g_free(g_array_index(trayicons, item_t, i).activation_file);
1503         g_free(g_array_index(trayicons, item_t, i).icon_active_file);
1504         g_free(g_array_index(trayicons, item_t, i).icon_inactive_file);
1505         g_free(g_array_index(trayicons, item_t, i).left_click_active_command);
1506         g_free(g_array_index(trayicons, item_t, i).left_click_inactive_command);
1507         gkrellm_destroy_button(g_array_index(trayicons, item_t, i).but);
1508         /*
1509         if (g_array_index(trayicons, item_t, i).buf) {
1510             g_string_free(g_array_index(trayicons, item_t, i).buf, TRUE);
1511         }
1512         */
1513     }
1514 
1515     g_array_free(trayicons, TRUE);
1516     trayicons=g_array_new(FALSE, TRUE, sizeof(item_t));
1517     if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store_trayicons), &iter)) {
1518         do {
1519             item_t item;
1520             memset(&item, 0, sizeof(item));
1521             gtk_tree_model_get(GTK_TREE_MODEL(store_trayicons), &iter,
1522                     ACTIVATION_FILE_COLUMN, &item.activation_file,
1523                     ICON_ACTIVE_FILE_COLUMN, &item.icon_active_file,
1524                     ICON_INACTIVE_FILE_COLUMN, &item.icon_inactive_file,
1525                     LEFT_CLICK_ACTIVE_COMMAND_COLUMN, &item.left_click_active_command,
1526                     LEFT_CLICK_INACTIVE_COMMAND_COLUMN, &item.left_click_inactive_command,
1527                     BLINK_COLUMN, &item.blink,
1528                     POPUP_COLUMN, &item.popup,
1529                     -1);
1530 
1531             if (item.left_click_active_command != NULL &&
1532                     strlen(item.left_click_active_command) == 0) {
1533                 item.left_click_active_command = NULL;
1534             }
1535             if (item.left_click_inactive_command != NULL &&
1536                     strlen(item.left_click_inactive_command) == 0) {
1537                 item.left_click_inactive_command = NULL;
1538             }
1539             g_array_append_val(trayicons, item);
1540         } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store_trayicons), &iter));
1541     }
1542 
1543     setup_trayicons(0);
1544     update_trayicons_real();
1545 }
1546 
1547 
1548 static GkrellmMonitor plugin_mon =
1549 {
1550     "Trayicons",               	    /* Name, for config tab.    */
1551     0,                                  /* Id,  0 if a plugin       */
1552     create_trayicons,          	    /* The create function      */
1553     update_trayicons,          	    /* The update function      */
1554     create_trayicons_tab,                /* The config tab create function   */
1555     apply_trayicons_config,              /* Apply the config function        */
1556     save_trayicons_config,               /* Save user config */
1557     load_trayicons_config,               /* Load user config */
1558     "trayicons",                         /* config keyword */
1559     NULL,                               /* Undefined 2  */
1560     NULL,                               /* Undefined 1  */
1561     NULL,                               /* Undefined 0  */
1562     MON_APM,                            /* Insert plugin before this monitor */
1563     NULL,                               /* Handle if a plugin, filled in by GKrellM     */
1564     NULL                                /* path if a plugin, filled in by GKrellM       */
1565 };
1566 
gkrellm_init_plugin()1567 GkrellmMonitor * gkrellm_init_plugin()
1568 {
1569     trayicons=g_array_new(FALSE,TRUE,sizeof(item_t));
1570     monitor = &plugin_mon;
1571     return &plugin_mon;
1572 }
1573