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