1 /*
2 
3 Copyright (c) 2002 Jamis Buck
4 Copyright (c) 2003-2007 Michael Terry
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 */
21 
22 #include "../config.h"
23 #include <glib/gi18n.h>
24 #include <gtk/gtk.h>
25 #include "fio.h"
26 #include "xpad-app.h"
27 #include "xpad-pad.h"
28 #include "xpad-pad-group.h"
29 #include "xpad-preferences.h"
30 #include "xpad-tray.h"
31 
32 static void xpad_tray_activate_cb (GtkStatusIcon *icon);
33 static void xpad_tray_popup_menu_cb (GtkStatusIcon *icon, guint button, guint time);
34 
35 static GtkStatusIcon  *docklet = NULL;
36 
37 void
xpad_tray_open(void)38 xpad_tray_open (void)
39 {
40 	GtkIconTheme *theme;
41 
42 	xpad_tray_close ();
43 
44 	theme = gtk_icon_theme_get_default ();
45 	if (!gtk_icon_theme_has_icon (theme, PACKAGE))
46 		return;
47 
48 	docklet = gtk_status_icon_new_from_icon_name (PACKAGE);
49 
50 	if (docklet)
51 	{
52 		g_signal_connect (docklet, "activate", G_CALLBACK (xpad_tray_activate_cb), NULL);
53 		g_signal_connect (docklet, "popup-menu", G_CALLBACK (xpad_tray_popup_menu_cb), NULL);
54 	}
55 }
56 
57 void
xpad_tray_close(void)58 xpad_tray_close (void)
59 {
60 	if (docklet) {
61 		g_object_unref (docklet);
62 		docklet = NULL;
63 	}
64 }
65 
66 gboolean
xpad_tray_is_open(void)67 xpad_tray_is_open (void)
68 {
69 	if (docklet)
70 		return gtk_status_icon_is_embedded (docklet);
71 	else
72 		return FALSE;
73 }
74 
75 static gint
menu_title_compare(GtkWindow * a,GtkWindow * b)76 menu_title_compare (GtkWindow *a, GtkWindow *b)
77 {
78 	gchar *title_a = g_utf8_casefold (gtk_window_get_title (a), -1);
79 	gchar *title_b = g_utf8_casefold (gtk_window_get_title (b), -1);
80 
81 	gint rv = g_utf8_collate (title_a, title_b);
82 
83 	g_free (title_a);
84 	g_free (title_b);
85 
86 	return rv;
87 }
88 
89 static void
menu_show_all(XpadPadGroup * group)90 menu_show_all (XpadPadGroup *group)
91 {
92 	GSList *pads = xpad_pad_group_get_pads (xpad_app_get_pad_group ());
93 	g_slist_foreach (pads, (GFunc) gtk_window_present, NULL);
94 	g_slist_free (pads);
95 }
96 
97 static void
menu_spawn(XpadPadGroup * group)98 menu_spawn (XpadPadGroup *group)
99 {
100 	GtkWidget *pad = xpad_pad_new (group);
101 	gtk_widget_show (pad);
102 }
103 
104 static void
xpad_tray_popup_menu_cb(GtkStatusIcon * icon,guint button,guint time)105 xpad_tray_popup_menu_cb (GtkStatusIcon *icon, guint button, guint time)
106 {
107 	GtkWidget *menu, *item;
108 	GSList *pads, *l;
109 	gint n;
110 
111 	menu = gtk_menu_new ();
112 	pads = xpad_pad_group_get_pads (xpad_app_get_pad_group ());
113 
114 	item = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, NULL);
115 	g_signal_connect_swapped (item, "activate", G_CALLBACK (menu_spawn), xpad_app_get_pad_group ());
116 	gtk_container_add (GTK_CONTAINER (menu), item);
117 	gtk_widget_show (item);
118 
119 	item = gtk_separator_menu_item_new ();
120 	gtk_container_add (GTK_CONTAINER (menu), item);
121 	gtk_widget_show (item);
122 
123 	item = gtk_menu_item_new_with_mnemonic (_("_Show All"));
124 	g_signal_connect_swapped (item, "activate", G_CALLBACK (menu_show_all), xpad_app_get_pad_group ());
125 	gtk_container_add (GTK_CONTAINER (menu), item);
126 	gtk_widget_show (item);
127 	if (!pads)
128 		gtk_widget_set_sensitive (item, FALSE);
129 
130 	item = gtk_image_menu_item_new_with_mnemonic (_("_Close All"));
131 	g_signal_connect_swapped (item, "activate", G_CALLBACK (xpad_pad_group_close_all), xpad_app_get_pad_group ());
132 	gtk_container_add (GTK_CONTAINER (menu), item);
133 	gtk_widget_show (item);
134 	if (!pads)
135 		gtk_widget_set_sensitive (item, FALSE);
136 
137 	item = gtk_separator_menu_item_new ();
138 	gtk_container_add (GTK_CONTAINER (menu), item);
139 	gtk_widget_show (item);
140 
141 	/**
142 	 * Order pads according to title.
143 	 */
144 	pads = g_slist_sort (pads, (GCompareFunc) menu_title_compare);
145 
146 	/**
147 	 * Populate list of windows.
148 	 */
149 	for (l = pads, n = 1; l; l = l->next, n++)
150 	{
151 		gchar *title;
152 		gchar *tmp_title;
153 
154 		tmp_title = g_strdup (gtk_window_get_title (GTK_WINDOW (l->data)));
155 		str_replace_tokens (&tmp_title, '_', "__");
156 		if (n < 10)
157 			title = g_strdup_printf ("_%i. %s", n, tmp_title);
158 		else
159 			title = g_strdup_printf ("%i. %s", n, tmp_title);
160 		g_free (tmp_title);
161 
162 		item = gtk_menu_item_new_with_mnemonic (title);
163 		g_signal_connect_swapped (item, "activate", G_CALLBACK (gtk_window_present), l->data);
164 		gtk_container_add (GTK_CONTAINER (menu), item);
165 		gtk_widget_show (item);
166 
167 		g_free (title);
168 	}
169 	g_slist_free (pads);
170 
171 	if (pads)
172 	{
173 		item = gtk_separator_menu_item_new ();
174 		gtk_container_add (GTK_CONTAINER (menu), item);
175 		gtk_widget_show (item);
176 	}
177 
178 	item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PREFERENCES, NULL);
179 	g_signal_connect (item, "activate", G_CALLBACK (xpad_preferences_open), NULL);
180 	gtk_container_add (GTK_CONTAINER (menu), item);
181 	gtk_widget_show (item);
182 
183 	item = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, NULL);
184 	g_signal_connect (item, "activate", G_CALLBACK (gtk_main_quit), NULL);
185 	gtk_container_add (GTK_CONTAINER (menu), item);
186 	gtk_widget_show (item);
187 
188 	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, gtk_status_icon_position_menu, icon, button, time);
189 }
190 
191 static void
xpad_tray_activate_cb(GtkStatusIcon * icon)192 xpad_tray_activate_cb (GtkStatusIcon *icon)
193 {
194 	GSList *pads = xpad_pad_group_get_pads (xpad_app_get_pad_group ());
195 	g_slist_foreach (pads, (GFunc) gtk_window_present, NULL);
196 	g_slist_free (pads);
197 }
198 
199