1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15 *
16 * Copyright (C) 2006-2016 XNeur Team
17 *
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <gtk/gtk.h>
25
26 #include <stdlib.h>
27 #include <ctype.h>
28 #include <string.h>
29
30 #include "support.h"
31
32 #include "xkb.h"
33 #include "misc.h"
34
35 #include <xneur/xnconfig.h>
36
37 #include "trayicon.h"
38
39 #include "configuration.h"
40
41 extern const char* arg_show_in_the_tray;
42 extern const char* arg_rendering_engine;
43 extern const char* arg_icons_directory;
44
45 extern struct _xneur_config *xconfig;
46
47 struct _tray_icon *tray;
48
49 gchar *show_in_the_tray = NULL;
50 gchar *rendering_engine = NULL;
51
52 Display *dpy = NULL;
53
54 static int xneur_old_pid = -1;
55 static int xneur_old_state = -1;
56 static int xneur_old_group = -1;
57 static char *xneur_old_symbol = NULL;
58
59 static int force_update = FALSE;
60
61 //#define ICON_SIZE 24
62
exec_user_action(char * cmd)63 static void exec_user_action(char *cmd)
64 {
65 printf("%s\n", cmd);
66 char *command = malloc ((strlen(cmd) + strlen(" 2> /dev/stdout") + 1) * sizeof(char));
67 command[0] = '\0';
68 strcat(command, cmd);
69 strcat(command, " 2> /dev/stdout");
70
71 FILE *fp = popen(command, "r");
72 if (command != NULL)
73 g_free(command);
74 if (fp == NULL)
75 return;
76
77 char buffer[NAME_MAX];
78 if (fgets(buffer, NAME_MAX, fp) == NULL)
79 {
80 pclose(fp);
81 return;
82 }
83
84 pclose(fp);
85
86 error_msg(buffer);
87 }
88
create_menu(struct _tray_icon * tray,int state)89 GtkMenu* create_menu(struct _tray_icon *tray, int state)
90 {
91 if (state) {};
92 GtkMenu *menu = GTK_MENU(gtk_menu_new());
93 GtkWidget *menuitem;
94 GtkWidget *image;
95
96 // Start/stop
97 gchar *status_text;
98 int xneur_pid = xconfig->get_pid(xconfig);
99 if (xneur_pid != -1)
100 {
101 status_text = g_strdup_printf("%s", _("Stop daemon"));
102 }
103 else
104 {
105 status_text = g_strdup_printf("%s", _("Start daemon"));
106 }
107 xneur_old_pid = xneur_pid;
108
109 if (tray->status == NULL)
110 {
111 tray->status = gtk_menu_item_new_with_mnemonic(status_text);
112 gtk_widget_show(tray->status);
113 gtk_container_add(GTK_CONTAINER(menu), tray->status);
114 g_signal_connect(G_OBJECT(tray->status), "activate", G_CALLBACK(xneur_start_stop), tray);
115 }
116 else
117 {
118 gtk_menu_item_set_label(GTK_MENU_ITEM(tray->status), status_text);
119 }
120
121 if (status_text != NULL)
122 g_free(status_text);
123
124 // Separator
125 menuitem = gtk_separator_menu_item_new();
126 gtk_widget_show(menuitem);
127 gtk_container_add(GTK_CONTAINER(menu), menuitem);
128 gtk_widget_set_sensitive(menuitem, FALSE);
129
130 // User Actions Submenu
131 GtkWidget *action_submenu = gtk_menu_new();
132
133 for (int action = 0; action < xconfig->user_actions_count; action++)
134 {
135 menuitem = gtk_menu_item_new_with_mnemonic(xconfig->user_actions[action].name);
136 gtk_widget_show(menuitem);
137 g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(exec_user_action), xconfig->user_actions[action].command);
138 gtk_container_add(GTK_CONTAINER(action_submenu), menuitem);
139 }
140 menuitem = gtk_image_menu_item_new_with_mnemonic(_("User action"));
141
142 image = gtk_image_new_from_stock("gtk-execute", GTK_ICON_SIZE_MENU);
143 gtk_widget_set_name(image, "image");
144 gtk_widget_show(image);
145 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
146 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), action_submenu);
147 gtk_widget_show(menuitem);
148 gtk_container_add(GTK_CONTAINER(menu), menuitem);
149 if (xconfig->actions_count < 1)
150 gtk_widget_set_sensitive(menuitem, FALSE);
151
152 // View log
153 menuitem = gtk_menu_item_new_with_mnemonic(_("View log..."));
154 gtk_widget_show(menuitem);
155 gtk_container_add(GTK_CONTAINER(menu), menuitem);
156 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(xneur_get_logfile), tray);
157
158 // Separator
159 menuitem = gtk_separator_menu_item_new();
160 gtk_widget_show(menuitem);
161 gtk_container_add(GTK_CONTAINER(menu), menuitem);
162 gtk_widget_set_sensitive(menuitem, FALSE);
163
164 // Preference
165 menuitem = gtk_image_menu_item_new_from_stock("gtk-preferences", NULL);
166 gtk_widget_show(menuitem);
167 gtk_container_add(GTK_CONTAINER(menu), menuitem);
168 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(xneur_preference), tray);
169
170 // Keyboard Preference
171 menuitem = gtk_menu_item_new_with_mnemonic(_("Keyboard Properties"));
172 gtk_widget_show(menuitem);
173 gtk_container_add(GTK_CONTAINER(menu), menuitem);
174 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(xneur_kb_preference), tray);
175
176 // About
177 menuitem = gtk_image_menu_item_new_from_stock("gtk-about", NULL);
178 gtk_widget_show(menuitem);
179 gtk_container_add(GTK_CONTAINER(menu), menuitem);
180 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(xneur_about), tray);
181
182 // Exit
183 menuitem = gtk_image_menu_item_new_from_stock("gtk-quit", NULL);
184 gtk_widget_show(menuitem);
185 gtk_container_add(GTK_CONTAINER(menu), menuitem);
186 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(xneur_exit), tray);
187
188
189 //gtk_widget_show (GTK_WIDGET(menu));
190 return GTK_MENU(menu);
191 }
192
tray_icon_press(GtkWidget * widget,GdkEventButton * event)193 gboolean tray_icon_press(GtkWidget *widget, GdkEventButton *event)
194 {
195 if (widget){};
196
197 if (event->button == 2)
198 {
199 xneur_start_stop();
200 return FALSE;
201 }
202
203 if (event->button == 1)
204 {
205 set_next_kbd_group(dpy);
206 return FALSE;
207 }
208
209 gtk_menu_popup(GTK_MENU(tray->menu), NULL, NULL, NULL, NULL, event->button, event->time);
210
211 return FALSE;
212 }
213
status_icon_on_click(GtkStatusIcon * status_icon,gpointer user_data)214 void status_icon_on_click(GtkStatusIcon *status_icon,
215 gpointer user_data)
216 {
217 if (status_icon || user_data){};
218 set_next_kbd_group(dpy);
219 }
220
status_icon_on_menu(GtkStatusIcon * status_icon,guint button,guint activate_time,gpointer user_data)221 void status_icon_on_menu(GtkStatusIcon *status_icon, guint button,
222 guint activate_time, gpointer user_data)
223 {
224 if (status_icon || user_data){};
225
226 gtk_menu_popup(GTK_MENU(tray->menu), NULL, NULL, NULL, NULL, button, activate_time);
227 }
228
text_to_gtk_pixbuf(gchar * text)229 GdkPixbuf *text_to_gtk_pixbuf (gchar *text)
230 {
231 GtkWidget *scratch = gtk_window_new (GTK_WINDOW_TOPLEVEL);
232 gtk_widget_realize (scratch);
233 //GtkStyle *style = gtk_widget_get_style(scratch);
234 //gchar *bgcolor = gdk_color_to_string(&style->bg[GTK_STATE_NORMAL]);
235 //gchar *textcolor = gdk_color_to_string(&style->text[GTK_STATE_NORMAL]);
236 PangoLayout *layout = gtk_widget_create_pango_layout (scratch, NULL);
237 //g_object_unref(style);
238 gtk_widget_destroy (scratch);
239
240 //gchar *markup = g_strdup_printf ("<span bgcolor='%s' color='%s'>%s</span>", bgcolor, textcolor, text);
241 //gchar *markup = g_strdup_printf ("<span color='%s'>%s</span>", textcolor, text);
242 gchar *markup = g_strdup_printf ("%s", text);
243 pango_layout_set_markup (layout, markup, -1);
244 if (markup != NULL)
245 g_free (markup);
246 //g_free (bgcolor);
247 //g_free (textcolor);
248
249 int width = 0;
250 int heigth = 0;
251 pango_layout_get_size (layout, &width, &heigth);
252 width = width/PANGO_SCALE;
253 heigth = heigth/PANGO_SCALE;
254
255 GdkPixbuf *pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, heigth);
256 gdk_pixbuf_fill(pb, 0xffffffff);
257
258 GdkPixmap *pm = gdk_pixmap_new (NULL, width, heigth, 24);
259 GdkGC *gc = gdk_gc_new (pm);
260 gdk_draw_pixbuf (pm, gc, pb, 0, 0, 0, 0, width, heigth, GDK_RGB_DITHER_NONE, 0, 0);
261
262 gdk_draw_layout (pm, gc, 0, 0, layout);
263
264
265 g_object_unref(layout);
266 g_object_unref(gc);
267
268 GdkPixbuf *ret = gdk_pixbuf_get_from_drawable (NULL, pm, NULL, 0, 0, 0, 0, width, heigth);
269 g_object_unref(pb);
270 return ret;
271 }
272
get_tray_icon_name(char * name)273 static const char *get_tray_icon_name (char *name)
274 {
275 const char * icon_name;
276 char *full_name = g_strdup_printf("%s-%s", PACKAGE, name);
277
278 if (strcasecmp(show_in_the_tray, "Icon") == 0)
279 {
280 icon_name = PACKAGE;
281 return icon_name;
282 }
283
284 if (strcasecmp(show_in_the_tray, "Directory") == 0)
285 {
286 gchar *string_value = NULL;
287 gxneur_config_read_str("icons_directory", &string_value);
288 if (string_value != NULL)
289 {
290 icon_name = g_strdup_printf ("%s%s%s.png", string_value,
291 G_DIR_SEPARATOR_S, name);
292 printf("Icons '%s'\n",icon_name);
293 if (g_file_test (icon_name, G_FILE_TEST_EXISTS))
294 return icon_name;
295 icon_name = g_strdup_printf ("%s%s%s.png", string_value,
296 G_DIR_SEPARATOR_S, full_name);
297 if (g_file_test (icon_name, G_FILE_TEST_EXISTS))
298 return icon_name;
299 icon_name = g_strdup_printf ("%s%s%s.png", string_value,
300 G_DIR_SEPARATOR_S, PACKAGE);
301 if (g_file_test (icon_name, G_FILE_TEST_EXISTS))
302 return icon_name;
303 }
304 if (string_value != NULL)
305 g_free (string_value);
306 icon_name = PACKAGE;
307 return icon_name;
308 }
309
310 //return "/home/crew/develop/xneur-devel/gxneur/pixmaps/all pixmaps/switcher/gxneur.png";
311
312 GtkIconTheme * theme = gtk_icon_theme_get_default( );
313
314 // if the tray's icon is a 48x48 file, use it;
315 // otherwise, use the fallback builtin icon
316 if (!gtk_icon_theme_has_icon (theme, full_name))
317 {
318 icon_name = PACKAGE;
319 }
320 else
321 {
322 GtkIconInfo * icon_info = gtk_icon_theme_lookup_icon (theme, full_name, 48, GTK_ICON_LOOKUP_USE_BUILTIN);
323 const gboolean icon_is_builtin = gtk_icon_info_get_filename (icon_info) == NULL;
324 gtk_icon_info_free (icon_info);
325 icon_name = icon_is_builtin ? PACKAGE : full_name;
326 }
327
328 return icon_name;
329 }
330
clock_check(gpointer dummy)331 gboolean clock_check(gpointer dummy)
332 {
333 if (dummy) {};
334
335 int xneur_pid = -1;
336 char *ps_command = (char *) malloc(1024 * sizeof(char));
337 if (xneur_old_pid == -1)
338 xneur_old_pid = 1;
339 snprintf(ps_command, 1024, "ps -p %d | grep xneur", xneur_old_pid);
340 FILE *fp = popen(ps_command, "r");
341 if (ps_command != NULL)
342 g_free (ps_command);
343 if (fp != NULL)
344 {
345 char buffer[NAME_MAX];
346 if (fgets(buffer, NAME_MAX, fp) != NULL)
347 xneur_pid = xneur_old_pid;
348
349 pclose(fp);
350 }
351 if (xneur_pid == -1)
352 xneur_pid = xconfig->get_pid(xconfig);
353
354 int xneur_state = xconfig->manual_mode;
355 int xneur_group = get_active_kbd_group(dpy);
356 char *xneur_symbol = get_active_kbd_symbol(dpy);
357
358 /*if (get_kbd_group_count(dpy) != xconfig->handle->total_languages)
359 {
360 gtk_widget_destroy(GTK_WIDGET(tray->menu));
361 tray->menu = NULL;
362
363 g_spawn_command_line_async(PACKAGE, NULL);
364
365 gtk_main_quit();
366 }*/
367
368
369 if (xneur_pid == xneur_old_pid &&
370 xneur_state == xneur_old_state &&
371 xneur_group == xneur_old_group &&
372 strcmp(xneur_old_symbol, xneur_symbol) == 0 &&
373 force_update == FALSE)
374 {
375 if (xneur_symbol != NULL)
376 g_free(xneur_symbol);
377 return TRUE;
378 }
379 force_update = FALSE;
380
381 xneur_old_pid = xneur_pid;
382 xneur_old_state = xneur_state;
383 xneur_old_group = xneur_group;
384 if (xneur_old_symbol != NULL)
385 {
386 g_free(xneur_old_symbol);
387 }
388 xneur_old_symbol = xneur_symbol;
389
390 gchar *hint;
391 gchar *status_text;
392 //float saturation = 1.0;
393 if (xneur_pid != -1)
394 {
395 //saturation = 1.0;
396 hint = g_strdup_printf("%s%s%s", _("X Neural Switcher running ("), xneur_symbol, ")");
397 status_text = g_strdup_printf("%s", _("Stop daemon"));
398 }
399 else
400 {
401 //saturation = 0.25;
402 hint = g_strdup_printf("%s%s%s", _("X Neural Switcher stopped ("), xneur_symbol, ")");
403 status_text = g_strdup_printf("%s", _("Start daemon"));
404 }
405
406 gtk_menu_item_set_label(GTK_MENU_ITEM(tray->status), status_text);
407
408 const char *icon_name = get_tray_icon_name(xneur_symbol);
409 if (tray->tray_icon)
410 {
411 gtk_widget_hide_all(GTK_WIDGET(tray->tray_icon));
412 gtk_widget_destroy (tray->image);
413 if (strcasecmp(show_in_the_tray, "Text") == 0)
414 {
415 char *layout_name = get_active_kbd_symbol(dpy);
416 for (unsigned int i=0; i < strlen(layout_name); i++)
417 layout_name[i] = toupper(layout_name[i]);
418 tray->image = gtk_label_new ((const gchar *)layout_name);
419 gtk_label_set_justify (GTK_LABEL(tray->image), GTK_JUSTIFY_CENTER);
420 if (layout_name != NULL)
421 g_free(layout_name);
422 }
423 else
424 {
425 if ((strcasecmp(show_in_the_tray, "Directory") != 0))
426 tray->image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
427 else
428 tray->image = gtk_image_new_from_file(icon_name);
429 }
430 gtk_container_add(GTK_CONTAINER(tray->evbox), tray->image);
431 gtk_widget_show_all(GTK_WIDGET(tray->tray_icon));
432 }
433 else if (tray->status_icon)
434 {
435 if (gtk_status_icon_is_embedded(tray->status_icon))
436 {
437 if (strcasecmp(show_in_the_tray, "Text") == 0)
438 {
439 char *layout_name = get_active_kbd_symbol(dpy);
440 for (unsigned int i=0; i < strlen(layout_name); i++)
441 layout_name[i] = toupper(layout_name[i]);
442 GdkPixbuf *pb = text_to_gtk_pixbuf (layout_name);
443 if (layout_name != NULL)
444 g_free(layout_name);
445 pb = gdk_pixbuf_add_alpha(pb, TRUE, 255, 255, 255);
446 gtk_status_icon_set_from_pixbuf(tray->status_icon, pb);
447 g_object_unref(pb);
448 }
449 else
450 {
451 if ((strcasecmp(show_in_the_tray, "Directory") != 0))
452 gtk_status_icon_set_from_icon_name(tray->status_icon, icon_name);
453 else
454 gtk_status_icon_set_from_file(tray->status_icon, icon_name);
455 }
456
457 gtk_status_icon_set_tooltip(tray->status_icon, hint);
458 }
459 }
460 #ifdef HAVE_APP_INDICATOR
461 else if (tray->app_indicator)
462 {
463 if (strcasecmp(show_in_the_tray, "Text") == 0)
464 {
465 #ifdef HAVE_DEPREC_APP_INDICATOR
466 app_indicator_set_icon (tray->app_indicator, icon_name);
467 #else
468 char *layout_name = get_active_kbd_symbol(dpy);
469 for (unsigned int i=0; i < strlen(layout_name); i++)
470 layout_name[i] = toupper(layout_name[i]);
471 app_indicator_set_label (tray->app_indicator, layout_name, layout_name);
472 if (layout_name != NULL)
473 g_free(layout_name);
474 app_indicator_set_icon_full (tray->app_indicator, "", "");
475 #endif
476 }
477 else
478 {
479 #ifdef HAVE_DEPREC_APP_INDICATOR
480 app_indicator_set_icon (tray->app_indicator, icon_name);
481 #else
482 app_indicator_set_icon_full (tray->app_indicator, icon_name, icon_name);
483 app_indicator_set_label (tray->app_indicator,"", "");
484 #endif
485 }
486 }
487 #endif
488
489 if (hint != NULL)
490 g_free (hint);
491 if (status_text != NULL)
492 g_free (status_text);
493
494 return TRUE;
495 }
496
xneur_start_stop(void)497 void xneur_start_stop(void)
498 {
499 if (xconfig->kill(xconfig) == TRUE)
500 {
501 clock_check(0);
502 return;
503 }
504
505 xneur_start();
506 clock_check(0);
507 }
508
xneur_exit(void)509 void xneur_exit(void)
510 {
511 /*for (int i = 0; i < MAX_LAYOUTS; i++)
512 {
513 if (tray->images[i] != NULL)
514 g_free(tray->images[i]);
515 }*/
516
517 gtk_widget_destroy(GTK_WIDGET(tray->menu));
518 tray->menu = NULL;
519
520 xconfig->kill(xconfig);
521 XCloseDisplay(dpy);
522 gtk_main_quit();
523 }
524
525 static
show_in_the_tray_callback(gpointer user_data)526 void show_in_the_tray_callback(gpointer user_data)
527 {
528 if (user_data) {};
529
530 if (arg_show_in_the_tray)
531 return;
532
533 gxneur_config_read_str("show_in_the_tray", &show_in_the_tray);
534
535 force_update = TRUE;
536 }
537
538 static
rendering_engine_callback(gpointer user_data)539 void rendering_engine_callback(gpointer user_data)
540 {
541 if (user_data) {};
542
543 if (arg_rendering_engine)
544 return;
545
546 gchar *new_engine = g_strdup(rendering_engine);
547 gxneur_config_read_str("rendering_engine", &new_engine);
548
549 if (strcasecmp(new_engine, rendering_engine) == 0)
550 return;
551
552 /*for (int i = 0; i < MAX_LAYOUTS; i++)
553 {
554 if (tray->images[i] != NULL)
555 g_free(tray->images[i]);
556 }*/
557
558 gtk_widget_destroy(GTK_WIDGET(tray->menu));
559 tray->menu = NULL;
560
561 g_spawn_command_line_async(PACKAGE, NULL);
562
563 gtk_main_quit();
564 }
565
create_tray_icon(void)566 void create_tray_icon (void)
567 {
568 dpy = XOpenDisplay(NULL);
569
570 gxneur_config_read_str("show_in_the_tray", &show_in_the_tray);
571 gxneur_config_read_str("rendering_engine", &rendering_engine);
572
573 gxneur_config_add_notify("show_in_the_tray", show_in_the_tray_callback, NULL);
574 gxneur_config_add_notify("rendering_engine", rendering_engine_callback, NULL);
575
576 if (arg_show_in_the_tray)
577 {
578 if (show_in_the_tray != NULL)
579 g_free(show_in_the_tray);
580 show_in_the_tray = g_strdup(arg_show_in_the_tray);
581 }
582 if (arg_rendering_engine)
583 {
584 if (rendering_engine != NULL)
585 g_free(rendering_engine);
586 rendering_engine = g_strdup(arg_rendering_engine);
587 }
588
589 if (!show_in_the_tray)
590 show_in_the_tray = g_strdup(DEFAULT_SHOW_IN_THE_TRAY);
591 if (!rendering_engine)
592 rendering_engine = g_strdup(DEFAULT_RENDERING_ENGINE);
593
594
595 tray = g_new0(struct _tray_icon, 1);
596 #ifdef HAVE_APP_INDICATOR
597 tray->app_indicator = NULL;
598 #endif
599 tray->status_icon = NULL;
600 tray->tray_icon = NULL;
601
602 // Init pixbuf array
603 /*for (int i = 0; i < MAX_LAYOUTS; i++)
604 {
605 tray->images[i] = NULL;
606 }*/
607
608 // Load images names
609 /*for (int i = 0; i < xconfig->handle->total_languages; i++)
610 {
611 char *layout_name = strdup(xconfig->handle->languages[i].dir);
612 tray->images[i] = g_strdup_printf("%s-%s", PACKAGE, layout_name);
613 free(layout_name);
614 }*/
615
616 tray->menu = create_menu(tray, xconfig->manual_mode);
617
618 int tray_icon_created = 0;
619 int tray_icon_failed = 0;
620
621 if (strcasecmp(rendering_engine, "AppIndicator") == 0)
622 {
623 #ifdef HAVE_APP_INDICATOR
624 // App indicator
625 tray->app_indicator = app_indicator_new ("X Neural Switcher",
626 PACKAGE,
627 APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
628
629 if (tray->app_indicator)
630 {
631 app_indicator_set_status (tray->app_indicator, APP_INDICATOR_STATUS_ACTIVE);
632 app_indicator_set_menu (tray->app_indicator, tray->menu);
633
634 tray_icon_created = 1;
635 tray_icon_failed = 0;
636 }
637 else
638 {
639 tray_icon_failed = 1;
640 }
641 #else
642 tray_icon_failed = 1;
643 #endif
644 }
645
646
647 // Tray icon
648 if (strcasecmp(rendering_engine, "Built-in") == 0 /*|| tray_icon_failed*/)
649 {
650 tray->tray_icon = _gtk_tray_icon_new(_("X Neural Switcher"));
651
652 if (tray->tray_icon)
653 {
654
655 g_signal_connect(G_OBJECT(tray->tray_icon), "button_press_event", G_CALLBACK(tray_icon_press), NULL);
656
657 tray->evbox = gtk_event_box_new();
658 gtk_event_box_set_visible_window(GTK_EVENT_BOX(tray->evbox), 0);
659 if (strcasecmp(show_in_the_tray, "Text") == 0)
660 {
661 char *layout_name = get_active_kbd_symbol (dpy);
662 for (unsigned int i=0; i < strlen(layout_name); i++)
663 layout_name[i] = toupper(layout_name[i]);
664 tray->image = gtk_label_new ((const gchar *)layout_name);
665 gtk_label_set_justify (GTK_LABEL(tray->image), GTK_JUSTIFY_CENTER);
666 if (layout_name != NULL)
667 g_free(layout_name);
668 }
669 else
670 {
671 char *layout_name = get_active_kbd_symbol (dpy);
672 tray->image = gtk_image_new_from_icon_name(layout_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
673 //tray->image = gtk_image_new_from_icon_name(tray->images[kbd_gr], GTK_ICON_SIZE_LARGE_TOOLBAR);
674 if (layout_name != NULL)
675 g_free(layout_name);
676 }
677 gtk_container_add(GTK_CONTAINER(tray->evbox), tray->image);
678 gtk_container_add(GTK_CONTAINER(tray->tray_icon), tray->evbox);
679
680 gtk_widget_show_all(GTK_WIDGET(tray->tray_icon));
681
682 tray_icon_created = 1;
683 tray_icon_failed = 0;
684 }
685 else
686 {
687 tray_icon_failed = 1;
688 }
689 }
690
691 // Status Icon
692 if (tray_icon_failed || !tray_icon_created || strcasecmp(rendering_engine, "StatusIcon") == 0 )
693 {
694 tray->status_icon = gtk_status_icon_new();
695
696 g_signal_connect(G_OBJECT(tray->status_icon), "activate", G_CALLBACK(status_icon_on_click), NULL);
697 g_signal_connect(G_OBJECT(tray->status_icon), "popup-menu", G_CALLBACK(status_icon_on_menu), NULL);
698
699 gtk_status_icon_set_from_icon_name(tray->status_icon, PACKAGE);
700 gtk_status_icon_set_tooltip_text(tray->status_icon, "X Neural Switcher");
701 gtk_status_icon_set_visible(tray->status_icon, TRUE);
702
703 if (strcasecmp(show_in_the_tray, "Text") == 0)
704 {
705 char *layout_name = get_active_kbd_symbol (dpy);
706 for (unsigned int i=0; i < strlen(layout_name); i++)
707 layout_name[i] = toupper(layout_name[i]);
708
709 GdkPixbuf *pb = text_to_gtk_pixbuf (layout_name);
710 if (layout_name != NULL)
711 g_free(layout_name);
712 pb = gdk_pixbuf_add_alpha(pb, TRUE, 255, 255, 255);
713 gtk_status_icon_set_from_pixbuf(tray->status_icon, pb);
714 g_object_unref(pb);
715 }
716 else
717 {
718 char *layout_name = get_active_kbd_symbol (dpy);
719 //gtk_status_icon_set_from_icon_name(tray->status_icon, tray->images[kbd_gr]);
720 gtk_status_icon_set_from_icon_name(tray->status_icon, layout_name);
721 if (layout_name != NULL)
722 g_free(layout_name);
723 }
724 }
725
726 force_update = TRUE;
727
728 g_timeout_add(1000, clock_check, 0);
729 }
730