1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail    : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <glib.h>
21 #include <dbus/dbus-glib.h>
22 #include <dbus/dbus-glib-bindings.h>
23 
24 #include "applet-dbus.h"
25 #include "interface-applet-methods.h"
26 #include "interface-applet-object.h"
27 #include "interface-applet-signals.h"
28 
29 static guint s_iSignals[NB_SIGNALS] = { 0 };
30 static guint s_iSubSignals[NB_SIGNALS] = { 0 };
31 
32 
cd_dbus_applet_init_signals_once(dbusAppletClass * klass)33 void cd_dbus_applet_init_signals_once (dbusAppletClass *klass)
34 {
35 	static gboolean bFirst = TRUE;
36 	if (! bFirst)
37 		return;
38 	bFirst = FALSE;
39 
40 	// Enregistrement des marshaller specifique aux signaux.
41 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__VALUE,
42 		G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID);  // answer
43 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__INT_VALUE,
44 		G_TYPE_NONE, G_TYPE_INT, G_TYPE_VALUE, G_TYPE_INVALID);  // answer_dialog
45 
46 	// on definit les signaux dont on aura besoin.
47 	s_iSignals[CLIC] =
48 		g_signal_new("on_click",
49 			G_OBJECT_CLASS_TYPE(klass),
50 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
51 			0,
52 			NULL, NULL,
53 			cd_dbus_marshal_VOID__INT,
54 			G_TYPE_NONE, 1, G_TYPE_INT);
55 	s_iSignals[MIDDLE_CLIC] =
56 		g_signal_new("on_middle_click",
57 			G_OBJECT_CLASS_TYPE(klass),
58 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
59 			0,
60 			NULL, NULL,
61 			cd_dbus_marshal_VOID__VOID,
62 			G_TYPE_NONE, 0, G_TYPE_NONE);
63 	s_iSignals[SCROLL] =
64 		g_signal_new("on_scroll",
65 			G_OBJECT_CLASS_TYPE(klass),
66 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
67 			0,
68 			NULL, NULL,
69 			cd_dbus_marshal_VOID__BOOLEAN,
70 			G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
71 	s_iSignals[BUILD_MENU] =
72 		g_signal_new("on_build_menu",
73 			G_OBJECT_CLASS_TYPE(klass),
74 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
75 			0,
76 			NULL, NULL,
77 			cd_dbus_marshal_VOID__VOID,
78 			G_TYPE_NONE, 0, G_TYPE_NONE);
79 	s_iSignals[MENU_SELECT] =
80 		g_signal_new("on_menu_select",
81 			G_OBJECT_CLASS_TYPE(klass),
82 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
83 			0,
84 			NULL, NULL,
85 			cd_dbus_marshal_VOID__INT,
86 			G_TYPE_NONE, 1, G_TYPE_INT);
87 	s_iSignals[DROP_DATA] =
88 		g_signal_new("on_drop_data",
89 			G_OBJECT_CLASS_TYPE(klass),
90 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
91 			0,
92 			NULL, NULL,
93 			cd_dbus_marshal_VOID__STRING,
94 			G_TYPE_NONE, 1, G_TYPE_STRING);
95 	s_iSignals[CHANGE_FOCUS] =
96 		g_signal_new("on_change_focus",
97 			G_OBJECT_CLASS_TYPE(klass),
98 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
99 			0,
100 			NULL, NULL,
101 			cd_dbus_marshal_VOID__BOOLEAN,
102 			G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
103 	s_iSignals[ANSWER] =
104 		g_signal_new("on_answer",
105 			G_OBJECT_CLASS_TYPE(klass),
106 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
107 			0,
108 			NULL, NULL,
109 			cd_dbus_marshal_VOID__VALUE,
110 			G_TYPE_NONE, 1, G_TYPE_VALUE);  // deprecated
111 	s_iSignals[ANSWER_DIALOG] =
112 		g_signal_new("on_answer_dialog",
113 			G_OBJECT_CLASS_TYPE(klass),
114 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
115 			0,
116 			NULL, NULL,
117 			cd_dbus_marshal_VOID__INT_VALUE,
118 			G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_VALUE);
119 	s_iSignals[SHORTKEY] =
120 		g_signal_new("on_shortkey",
121 			G_OBJECT_CLASS_TYPE(klass),
122 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
123 			0,
124 			NULL, NULL,
125 			cd_dbus_marshal_VOID__STRING,
126 			G_TYPE_NONE, 1, G_TYPE_STRING);
127 	s_iSignals[INIT_MODULE] =
128 		g_signal_new("on_init_module",
129 			G_OBJECT_CLASS_TYPE(klass),
130 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
131 			0,
132 			NULL, NULL,
133 			cd_dbus_marshal_VOID__VOID,
134 			G_TYPE_NONE, 0, G_TYPE_NONE);
135 	s_iSignals[STOP_MODULE] =
136 		g_signal_new("on_stop_module",
137 			G_OBJECT_CLASS_TYPE(klass),
138 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
139 			0,
140 			NULL, NULL,
141 			cd_dbus_marshal_VOID__VOID,
142 			G_TYPE_NONE, 0, G_TYPE_NONE);
143 	s_iSignals[RELOAD_MODULE] =
144 		g_signal_new("on_reload_module",
145 			G_OBJECT_CLASS_TYPE(klass),
146 			G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
147 			0,
148 			NULL, NULL,
149 			cd_dbus_marshal_VOID__BOOLEAN,
150 			G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
151 
152 	// Add signals
153 	DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
154 	if (pProxy != NULL)
155 	{
156 		dbus_g_proxy_add_signal(pProxy, "on_click",
157 			G_TYPE_INT, G_TYPE_INVALID);
158 		dbus_g_proxy_add_signal(pProxy, "on_middle_click",
159 			G_TYPE_INVALID);
160 		dbus_g_proxy_add_signal(pProxy, "on_scroll",
161 			G_TYPE_BOOLEAN, G_TYPE_INVALID);
162 		dbus_g_proxy_add_signal(pProxy, "on_build_menu",
163 			G_TYPE_INVALID);
164 		dbus_g_proxy_add_signal(pProxy, "on_menu_select",
165 			G_TYPE_INT, G_TYPE_INVALID);
166 		dbus_g_proxy_add_signal(pProxy, "on_drop_data",
167 			G_TYPE_STRING, G_TYPE_INVALID);
168 		dbus_g_proxy_add_signal(pProxy, "on_change_focus",
169 			G_TYPE_BOOLEAN, G_TYPE_INVALID);
170 		dbus_g_proxy_add_signal(pProxy, "on_answer",
171 			G_TYPE_VALUE, G_TYPE_INVALID);  // deprecated
172 		dbus_g_proxy_add_signal(pProxy, "on_answer_dialog",
173 			G_TYPE_VALUE, G_TYPE_INVALID);
174 		dbus_g_proxy_add_signal(pProxy, "on_shortkey",
175 			G_TYPE_VALUE, G_TYPE_INVALID);
176 		dbus_g_proxy_add_signal(pProxy, "on_init_module",
177 			G_TYPE_INVALID);
178 		dbus_g_proxy_add_signal(pProxy, "on_stop_module",
179 			G_TYPE_INVALID);
180 		dbus_g_proxy_add_signal(pProxy, "on_reload_module",
181 			G_TYPE_BOOLEAN, G_TYPE_INVALID);
182 	}
183 }
184 
cd_dbus_sub_applet_init_signals_once(dbusSubAppletClass * klass)185 void cd_dbus_sub_applet_init_signals_once (dbusSubAppletClass *klass)
186 {
187 	static gboolean bFirst = TRUE;
188 	if (! bFirst)
189 		return;
190 	bFirst = FALSE;
191 
192 	// Enregistrement des marshaller specifique aux signaux.
193 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__INT_STRING,
194 		G_TYPE_NONE, G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);  // clic
195 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__BOOLEAN_STRING,
196 		G_TYPE_NONE, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_INVALID);  // scroll
197 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__STRING_STRING,
198 		G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);  // drop
199 	dbus_g_object_register_marshaller(cd_dbus_marshal_VOID__VALUE_STRING,
200 		G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_STRING, G_TYPE_INVALID);  // answer
201 
202 	// on definit les signaux dont on aura besoin.
203 	s_iSubSignals[CLIC] =
204 		g_signal_new("on_click_sub_icon",
205 			G_OBJECT_CLASS_TYPE(klass),
206 				G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
207 				0,
208 				NULL, NULL,
209 				cd_dbus_marshal_VOID__INT_STRING,
210 				G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
211 	s_iSubSignals[MIDDLE_CLIC] =
212 		g_signal_new("on_middle_click_sub_icon",
213 			G_OBJECT_CLASS_TYPE(klass),
214 				G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
215 				0,
216 				NULL, NULL,
217 				cd_dbus_marshal_VOID__STRING,
218 				G_TYPE_NONE, 1, G_TYPE_STRING);
219 	s_iSubSignals[SCROLL] =
220 		g_signal_new("on_scroll_sub_icon",
221 			G_OBJECT_CLASS_TYPE(klass),
222 				G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
223 				0,
224 				NULL, NULL,
225 				cd_dbus_marshal_VOID__BOOLEAN_STRING,
226 				G_TYPE_NONE, 2, G_TYPE_BOOLEAN, G_TYPE_STRING);
227 	s_iSubSignals[BUILD_MENU] =
228 		g_signal_new("on_build_menu_sub_icon",
229 			G_OBJECT_CLASS_TYPE(klass),
230 				G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
231 				0,
232 				NULL, NULL,
233 				cd_dbus_marshal_VOID__STRING,
234 				G_TYPE_NONE, 1, G_TYPE_STRING);
235 	s_iSubSignals[DROP_DATA] =
236 		g_signal_new("on_drop_data_sub_icon",
237 			G_OBJECT_CLASS_TYPE(klass),
238 				G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
239 				0,
240 				NULL, NULL,
241 				cd_dbus_marshal_VOID__STRING_STRING,
242 				G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
243 
244 	// Add signals
245 	DBusGProxy *pProxy = cairo_dock_get_main_proxy ();
246 	if (pProxy != NULL)
247 	{
248 		dbus_g_proxy_add_signal(pProxy, "on_click_sub_icon",
249 			G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID);
250 		dbus_g_proxy_add_signal(pProxy, "on_middle_click_icon",
251 			G_TYPE_STRING, G_TYPE_INVALID);
252 		dbus_g_proxy_add_signal(pProxy, "on_scroll_sub_icon",
253 			G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_INVALID);
254 		dbus_g_proxy_add_signal(pProxy, "on_build_menu_sub_icon",
255 			G_TYPE_STRING, G_TYPE_INVALID);
256 		dbus_g_proxy_add_signal(pProxy, "on_drop_data_sub_icon",
257 			G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
258 	}
259 }
260 
261 #define CAIRO_DOCK_IS_EXTERNAL_APPLET(pIcon) (CAIRO_DOCK_IS_APPLET (pIcon) && pIcon->pModuleInstance->pModule->pInterface->stopModule == cd_dbus_emit_on_stop_module)
262 
_get_main_icon_from_clicked_icon(Icon * pIcon,GldiContainer * pContainer)263 static inline Icon *_get_main_icon_from_clicked_icon (Icon *pIcon, GldiContainer *pContainer)
264 {
265 	Icon *pMainIcon = NULL;
266 	if (CAIRO_DOCK_IS_DESKLET (pContainer))
267 	{
268 		pMainIcon = CAIRO_DESKLET (pContainer)->pIcon;
269 	}
270 	else if (CAIRO_DOCK_IS_DOCK (pContainer))
271 	{
272 		if (CAIRO_DOCK (pContainer)->iRefCount == 0 || CAIRO_DOCK_IS_APPLET (pIcon))  // gere donc le cas ou l'applet est placee dans un sous-dock.
273 		{
274 			pMainIcon = pIcon;
275 		}
276 		else
277 		{
278 			pMainIcon = cairo_dock_search_icon_pointing_on_dock (CAIRO_DOCK (pContainer), NULL);
279 		}
280 	}
281 	return pMainIcon;
282 }
283 
cd_dbus_applet_emit_on_click_icon(gpointer data,Icon * pClickedIcon,GldiContainer * pClickedContainer,guint iButtonState)284 gboolean cd_dbus_applet_emit_on_click_icon (gpointer data, Icon *pClickedIcon, GldiContainer *pClickedContainer, guint iButtonState)
285 {
286 	if (pClickedIcon == NULL)
287 		return GLDI_NOTIFICATION_LET_PASS;
288 	Icon *pAppletIcon = _get_main_icon_from_clicked_icon (pClickedIcon, pClickedContainer);
289 	if (! CAIRO_DOCK_IS_EXTERNAL_APPLET (pAppletIcon))
290 		return GLDI_NOTIFICATION_LET_PASS;
291 
292 	//g_print ("%s (%s, %d)\n", __func__, pAppletIcon->pModuleInstance->pModule->pVisitCard->cModuleName, iButtonState);
293 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pAppletIcon->pModuleInstance);
294 	g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
295 
296 	if (pClickedIcon == pAppletIcon)
297 	{
298 		//g_print ("emit clic on main icon\n");
299 		g_signal_emit (pDbusApplet, s_iSignals[CLIC], 0, iButtonState);
300 	}
301 	else if (pDbusApplet->pSubApplet != NULL)
302 	{
303 		//g_print ("emit clic on sub icon\n");
304 		g_signal_emit (pDbusApplet->pSubApplet, s_iSubSignals[CLIC], 0, iButtonState, pClickedIcon->cCommand);
305 	}
306 
307 	// if the applet acts as a launcher, assume it launches the program it controls on click
308 	// Note: if one day it poses a problem, we can either make a new attribute, or add a dbus method (or even reuse the "Animate" method with a pseudo "launching" animation).
309 	if (pAppletIcon->pModuleInstance->pModule->pVisitCard->bActAsLauncher
310 	&& pClickedIcon->pAppli == NULL)  // if the icon already controls a window, don't notify; most probably, the action the applet will take is to show/minimize this window
311 		gldi_class_startup_notify (pClickedIcon);
312 	return GLDI_NOTIFICATION_INTERCEPT;
313 }
314 
cd_dbus_applet_emit_on_middle_click_icon(gpointer data,Icon * pClickedIcon,GldiContainer * pClickedContainer)315 gboolean cd_dbus_applet_emit_on_middle_click_icon (gpointer data, Icon *pClickedIcon, GldiContainer *pClickedContainer)
316 {
317 	if (pClickedIcon == NULL)
318 		return GLDI_NOTIFICATION_LET_PASS;
319 	Icon *pAppletIcon = _get_main_icon_from_clicked_icon (pClickedIcon, pClickedContainer);
320 	if (! CAIRO_DOCK_IS_EXTERNAL_APPLET (pAppletIcon))
321 		return GLDI_NOTIFICATION_LET_PASS;
322 
323 	//g_print ("%s (%s)\n", __func__, pAppletIcon->pModuleInstance->pModule->pVisitCard->cModuleName);
324 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pAppletIcon->pModuleInstance);
325 	g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
326 
327 	if (pClickedIcon == pAppletIcon)
328 		g_signal_emit (pDbusApplet, s_iSignals[MIDDLE_CLIC], 0, NULL);
329 	else if (pDbusApplet->pSubApplet != NULL)
330 		g_signal_emit (pDbusApplet->pSubApplet, s_iSubSignals[MIDDLE_CLIC], 0, pClickedIcon->cCommand);
331 	return GLDI_NOTIFICATION_INTERCEPT;
332 }
333 
cd_dbus_applet_emit_on_scroll_icon(gpointer data,Icon * pClickedIcon,GldiContainer * pClickedContainer,int iDirection)334 gboolean cd_dbus_applet_emit_on_scroll_icon (gpointer data, Icon *pClickedIcon, GldiContainer *pClickedContainer, int iDirection)
335 {
336 	if (pClickedIcon == NULL)
337 		return GLDI_NOTIFICATION_LET_PASS;
338 	Icon *pAppletIcon = _get_main_icon_from_clicked_icon (pClickedIcon, pClickedContainer);
339 	if (! CAIRO_DOCK_IS_EXTERNAL_APPLET (pAppletIcon))
340 		return GLDI_NOTIFICATION_LET_PASS;
341 
342 	//g_print ("%s (%s, %d)\n", __func__, pAppletIcon->pModuleInstance->pModule->pVisitCard->cModuleName, iDirection);
343 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pAppletIcon->pModuleInstance);
344 	g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
345 
346 	if (pClickedIcon == pAppletIcon)
347 		g_signal_emit (pDbusApplet, s_iSignals[SCROLL], 0, (iDirection == GDK_SCROLL_UP));
348 	else if (pDbusApplet->pSubApplet != NULL)
349 		g_signal_emit (pDbusApplet->pSubApplet, s_iSubSignals[SCROLL], 0, (iDirection == GDK_SCROLL_UP), pClickedIcon->cCommand);
350 	return GLDI_NOTIFICATION_INTERCEPT;
351 }
352 
_delete_menu(GtkMenuShell * menu,GldiModuleInstance * myApplet)353 static void _delete_menu (GtkMenuShell *menu, GldiModuleInstance *myApplet)
354 {
355 	///myData.pModuleSubMenu = NULL;
356 	myData.pModuleMainMenu = NULL;
357 }
cd_dbus_applet_emit_on_build_menu(gpointer data,Icon * pClickedIcon,GldiContainer * pClickedContainer,GtkWidget * pAppletMenu)358 gboolean cd_dbus_applet_emit_on_build_menu (gpointer data, Icon *pClickedIcon, GldiContainer *pClickedContainer, GtkWidget *pAppletMenu)
359 {
360 	if (pClickedIcon == NULL)
361 		return GLDI_NOTIFICATION_LET_PASS;
362 	Icon *pAppletIcon = _get_main_icon_from_clicked_icon (pClickedIcon, pClickedContainer);
363 	if (! CAIRO_DOCK_IS_EXTERNAL_APPLET (pAppletIcon))
364 		return GLDI_NOTIFICATION_LET_PASS;
365 
366 	myData.pModuleMainMenu = pAppletMenu;
367 	/**myData.pModuleSubMenu = cairo_dock_create_sub_menu (pAppletIcon->pModuleInstance->pModule->pVisitCard->cModuleName,
368 		pAppletMenu,
369 		pAppletIcon->pModuleInstance->pModule->pVisitCard->cIconFilePath);
370 
371 	cairo_dock_add_in_menu_with_stock_and_data (_("Applet's Handbook"),
372 		GLDI_ICON_NAME_ABOUT,
373 		G_CALLBACK (cairo_dock_pop_up_about_applet),
374 		myData.pModuleSubMenu,
375 		pAppletIcon->pModuleInstance);*/
376 
377 	g_signal_connect (G_OBJECT (pAppletMenu),
378 		"deactivate",
379 		G_CALLBACK (_delete_menu),
380 		myApplet);
381 
382 	//g_print ("%s (%s)\n", __func__, pAppletIcon->pModuleInstance->pModule->pVisitCard->cModuleName);
383 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pAppletIcon->pModuleInstance);
384 	g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
385 	myData.pCurrentMenuDbusApplet = pDbusApplet;
386 
387 	GList *pChildren = gtk_container_get_children (GTK_CONTAINER (pAppletMenu));
388 	myData.iMenuPosition = g_list_length (pChildren);
389 	g_list_free (pChildren);
390 
391 	if (pClickedIcon == pAppletIcon)
392 		g_signal_emit (pDbusApplet, s_iSignals[BUILD_MENU], 0);
393 	else if (pDbusApplet->pSubApplet != NULL)
394 		g_signal_emit (pDbusApplet->pSubApplet, s_iSubSignals[BUILD_MENU], 0, pClickedIcon->cCommand);
395 	return (pClickedIcon == pAppletIcon ? GLDI_NOTIFICATION_LET_PASS : GLDI_NOTIFICATION_INTERCEPT);
396 }
397 
cd_dbus_emit_on_menu_select(GtkMenuItem * pMenuItem,gpointer data)398 void cd_dbus_emit_on_menu_select (GtkMenuItem *pMenuItem, gpointer data)
399 {
400 	g_return_if_fail (myData.pCurrentMenuDbusApplet != NULL);
401 	if (GTK_IS_RADIO_MENU_ITEM (pMenuItem))
402 	{
403 		if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
404 			return ;
405 	}
406 
407 	int iNumEntry = GPOINTER_TO_INT (data);
408 	g_signal_emit (myData.pCurrentMenuDbusApplet, s_iSignals[MENU_SELECT], 0, iNumEntry);  // since there can only be 1 menu at once, and the applet knows when the menu is raised, there is no need to pass the icon in the signal: the applet can remember the clicked icon when it received the 'build-menu' event.
409 }
410 
cd_dbus_applet_emit_on_drop_data(G_GNUC_UNUSED gpointer data,const gchar * cReceivedData,Icon * pClickedIcon,double fPosition,GldiContainer * pClickedContainer)411 gboolean cd_dbus_applet_emit_on_drop_data (G_GNUC_UNUSED gpointer data, const gchar *cReceivedData, Icon *pClickedIcon, double fPosition, GldiContainer *pClickedContainer)
412 {
413 	//\________________ On gere le cas d'une applet tierce-partie en provenance de nos depots.
414 	if (cReceivedData && strncmp (cReceivedData, "http://", 7) == 0 && g_str_has_suffix (cReceivedData, ".tar.gz") && (g_strstr_len (cReceivedData, -1, "glxdock") || g_strstr_len (cReceivedData, -1, "glx-dock")))
415 	{
416 		//\________________ On telecharge l'archive de l'applet et on l'installe/la met a jour.
417 		GError *erreur = NULL;
418 		//g_print ("dropped a distant applet\n");
419 		gchar *cExtractTo = g_strdup_printf ("%s/%s", g_cCairoDockDataDir, CD_DBUS_APPLETS_FOLDER);
420 		gchar *cAppletDirPath = cairo_dock_download_archive (cReceivedData, cExtractTo);
421 		if (erreur != NULL)
422 		{
423 			cd_warning (erreur->message);
424 			g_error_free (erreur);
425 		}
426 		if (cAppletDirPath == NULL)
427 		{
428 			gldi_dialog_show_general_message (D_("Sorry, this module couldn't be added."), 10000);
429 		}
430 		else
431 		{
432 			//\________________ On la supprime totalement si elle existe deja (mise a jour).
433 			gchar *cAppletName = g_path_get_basename (cAppletDirPath);
434 			gchar *str = strchr (cAppletName, '_');
435 			if (str)  // on enleve les numeros de version (launchpad, solution temporaire).
436 			{
437 				if (g_ascii_isdigit (*(str+1)))
438 					*str = '\0';
439 			}
440 
441 			GldiModule *pModule = gldi_module_get (cAppletName);
442 			gboolean bUpdate = FALSE;
443 			if (pModule != NULL)  // on va totalement supprimer le module pour le recharger de zero.
444 			{
445 				bUpdate = TRUE;
446 				gldi_object_unref (GLDI_OBJECT(pModule));
447 				pModule = NULL;
448 			}
449 
450 			//\________________ On l'enregistre et on la (re)lance.
451 			cd_dbus_register_module_in_dir (cAppletName, cExtractTo);
452 			pModule = gldi_module_get (cAppletName);
453 
454 			gldi_module_activate (pModule);
455 
456 			//\________________ On balance un petit message a l'utilisateur.
457 			if (!pModule)
458 			{
459 				gldi_dialog_show_general_message (D_("Sorry, this module couldn't be added."), 10000);
460 			}
461 			else if (!pModule->pInstancesList)
462 			{
463 				gldi_dialog_show_general_message (D_("The module has been added, but couldn't be launched."), 10000);
464 			}
465 			else
466 			{
467 				GldiModuleInstance *pInstance = pModule->pInstancesList->data;
468 				if (!pInstance->pIcon || !pInstance->pContainer)
469 					gldi_dialog_show_general_message (D_("The module has been added, but couldn't be launched."), 10000);
470 				else
471 				{
472 					gldi_dialog_show_temporary_with_icon_printf (bUpdate ? D_("The applet '%s' has been succefully updated and automatically reloaded") : D_("The applet '%s' has been succefully installed and automatically launched"),
473 						pInstance->pIcon,
474 						pInstance->pContainer,
475 						10000,
476 						"same icon",
477 						cAppletName);
478 				}
479 			}
480 			g_free (cAppletName);
481 		}
482 		g_free (cExtractTo);
483 		return GLDI_NOTIFICATION_INTERCEPT;
484 	}
485 
486 	//\________________ Sinon on notifie l'applet du drop.
487 	Icon *pAppletIcon = _get_main_icon_from_clicked_icon (pClickedIcon, pClickedContainer);
488 	if (! CAIRO_DOCK_IS_EXTERNAL_APPLET (pAppletIcon))
489 		return GLDI_NOTIFICATION_LET_PASS;
490 
491 	cd_debug (" %s --> sur le bus !", cReceivedData);
492 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pAppletIcon->pModuleInstance);
493 	g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
494 
495 	if (pClickedIcon == pAppletIcon)
496 		g_signal_emit (pDbusApplet, s_iSignals[DROP_DATA], 0, cReceivedData);
497 	else if (pDbusApplet->pSubApplet != NULL)
498 		g_signal_emit (pDbusApplet->pSubApplet, s_iSubSignals[DROP_DATA], 0, cReceivedData, pClickedIcon->cCommand);
499 	return GLDI_NOTIFICATION_INTERCEPT;
500 }
501 
_on_window_destroyed(G_GNUC_UNUSED gpointer data,GldiWindowActor * actor)502 static gboolean _on_window_destroyed (G_GNUC_UNUSED gpointer data, GldiWindowActor *actor)
503 {
504 	if (actor == myData.pActiveWindow)
505 		myData.pActiveWindow = NULL;
506 	return GLDI_NOTIFICATION_LET_PASS;
507 }
cd_dbus_applet_emit_on_change_focus(G_GNUC_UNUSED gpointer data,GldiWindowActor * pNewActiveWindow)508 gboolean cd_dbus_applet_emit_on_change_focus (G_GNUC_UNUSED gpointer data, GldiWindowActor *pNewActiveWindow)
509 {
510 	// on emet le signal sur l'icone qui avait le focus.
511 	if (myData.pActiveWindow != NULL)
512 	{
513 		Icon *pPrevActiveIcon = cairo_dock_get_appli_icon (myData.pActiveWindow);
514 		if (pPrevActiveIcon && pPrevActiveIcon->cParentDockName == NULL)
515 			pPrevActiveIcon = cairo_dock_get_inhibitor (pPrevActiveIcon, FALSE);
516 		if (CAIRO_DOCK_IS_EXTERNAL_APPLET (pPrevActiveIcon))
517 		{
518 			dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pPrevActiveIcon->pModuleInstance);
519 			g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
520 			g_signal_emit (pDbusApplet, s_iSignals[CHANGE_FOCUS], 0, FALSE);
521 		}
522 	}
523 
524 	// on emet le signal sur l'icone qui a desormais le focus.
525 	//g_print ("DBUS : new active window : %ld\n", *xNewActiveWindow);
526 	if (pNewActiveWindow != NULL)
527 	{
528 		Icon *pNewActiveIcon = cairo_dock_get_appli_icon (pNewActiveWindow);
529 		if (pNewActiveIcon && pNewActiveIcon->cParentDockName == NULL)
530 			pNewActiveIcon = cairo_dock_get_inhibitor (pNewActiveIcon, FALSE);
531 		if (CAIRO_DOCK_IS_EXTERNAL_APPLET (pNewActiveIcon))
532 		{
533 			dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pNewActiveIcon->pModuleInstance);
534 			g_return_val_if_fail (pDbusApplet != NULL, GLDI_NOTIFICATION_LET_PASS);
535 			g_signal_emit (pDbusApplet, s_iSignals[CHANGE_FOCUS], 0, TRUE);
536 		}
537 	}
538 
539 	myData.pActiveWindow = pNewActiveWindow;
540 	if (pNewActiveWindow)
541 		gldi_object_register_notification (pNewActiveWindow, NOTIFICATION_DESTROY, (GldiNotificationFunc)_on_window_destroyed, GLDI_RUN_AFTER, NULL);
542 	return GLDI_NOTIFICATION_LET_PASS;
543 }
544 
545 
546 // deprecated
_emit_answer(dbusApplet * pDbusApplet,CairoDialog * pDialog,GValue * v)547 static inline void _emit_answer (dbusApplet *pDbusApplet, CairoDialog *pDialog, GValue *v)
548 {
549 	g_signal_emit (pDbusApplet, s_iSignals[ANSWER], 0, v);  // same remark as for the menu: 1 dialog at once, the applet knows when the dialog is raised, so it can just remember the clicked icon; we don't need to tell it.
550 
551 	pDbusApplet->pDialog = NULL;
552 }
cd_dbus_applet_emit_on_answer_question(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)553 void cd_dbus_applet_emit_on_answer_question (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
554 {
555 	gboolean bYes = (iClickedButton == 0 || iClickedButton == -1);
556 	GValue v = G_VALUE_INIT;
557 	g_value_init (&v, G_TYPE_BOOLEAN);
558 	g_value_set_boolean (&v, bYes);
559 
560 	_emit_answer (pDbusApplet, pDialog, &v);
561 }
562 
cd_dbus_applet_emit_on_answer_value(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)563 void cd_dbus_applet_emit_on_answer_value (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
564 {
565 	double fValue = (iClickedButton == 0 || iClickedButton == -1 ? gtk_range_get_value (GTK_RANGE (pInteractiveWidget)) : -1);
566 	GValue v = G_VALUE_INIT;
567 	g_value_init (&v, G_TYPE_DOUBLE);
568 	g_value_set_double (&v, fValue);
569 
570 	_emit_answer (pDbusApplet, pDialog, &v);
571 }
572 
cd_dbus_applet_emit_on_answer_text(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)573 void cd_dbus_applet_emit_on_answer_text (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
574 {
575 	const gchar *cAnswer = (iClickedButton == 0 || iClickedButton == -1 ? gtk_entry_get_text (GTK_ENTRY (pInteractiveWidget)) : NULL);
576 	GValue v = G_VALUE_INIT;
577 	g_value_init (&v, G_TYPE_STRING);
578 	g_value_set_string (&v, cAnswer);
579 
580 	_emit_answer (pDbusApplet, pDialog, &v);
581 }
582 // end of deprecated
583 
584 
_emit_answer_dialog(dbusApplet * pDbusApplet,CairoDialog * pDialog,int iClickedButton,GValue * v)585 static inline void _emit_answer_dialog (dbusApplet *pDbusApplet, CairoDialog *pDialog, int iClickedButton, GValue *v)
586 {
587 	g_signal_emit (pDbusApplet, s_iSignals[ANSWER_DIALOG], 0, iClickedButton, v);  // same remark as for the menu: 1 dialog at once, the applet knows when the dialog is raised, so it can just remember the clicked icon; we don't need to tell it.
588 
589 	pDbusApplet->pDialog = NULL;
590 }
cd_dbus_applet_emit_on_answer_buttons(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)591 void cd_dbus_applet_emit_on_answer_buttons (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
592 {
593 	GValue v = G_VALUE_INIT;
594 	g_value_init (&v, G_TYPE_INT);
595 	g_value_set_int (&v, iClickedButton);
596 
597 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
598 }
599 
cd_dbus_applet_emit_on_answer_text_entry(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)600 void cd_dbus_applet_emit_on_answer_text_entry (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
601 {
602 	GValue v = G_VALUE_INIT;
603 	g_value_init (&v, G_TYPE_STRING);
604 
605 	GtkWidget *pEntry = g_object_get_data (G_OBJECT (pInteractiveWidget), "cd-widget");
606 	g_return_if_fail (pEntry != NULL);
607 	/**GtkWidget *pEntry;
608 	if (GTK_IS_ENTRY (pInteractiveWidget))
609 	{
610 		pEntry = pInteractiveWidget;
611 	}
612 	else
613 	{
614 		GList *children = gtk_container_get_children (GTK_CONTAINER (pInteractiveWidget));
615 		g_return_if_fail (children != NULL);
616 		pEntry = children->data;
617 	}*/
618 
619 	const gchar *cText = gtk_entry_get_text (GTK_ENTRY (pEntry));
620 	//g_print (" -> %s\n", cText);
621 	g_value_set_string (&v, cText);
622 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
623 }
624 
cd_dbus_applet_emit_on_answer_text_view(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)625 void cd_dbus_applet_emit_on_answer_text_view (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
626 {
627 	GValue v = G_VALUE_INIT;
628 	g_value_init (&v, G_TYPE_STRING);
629 
630 	GtkWidget *pTextView = g_object_get_data (G_OBJECT (pInteractiveWidget), "cd-widget");
631 	g_return_if_fail (pTextView != NULL);
632 	/**if (GTK_IS_TEXT_VIEW (pInteractiveWidget))
633 	{
634 		pTextView = pInteractiveWidget;
635 	}
636 	else
637 	{
638 		GList *children = gtk_container_get_children (GTK_CONTAINER (pInteractiveWidget));
639 		g_return_if_fail (children != NULL);
640 		pTextView = children->data;
641 	}*/
642 	GtkTextBuffer *pBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (pTextView));
643 	GtkTextIter start, end;
644 	gtk_text_buffer_get_start_iter (pBuffer, &start);
645 	gtk_text_buffer_get_end_iter (pBuffer, &end);
646 	gchar *cText = gtk_text_buffer_get_text (pBuffer,
647 		&start,
648 		&end,
649 		FALSE);
650 
651 	g_value_set_string (&v, cText);
652 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
653 	g_free (cText);
654 }
655 
cd_dbus_applet_emit_on_answer_scale(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)656 void cd_dbus_applet_emit_on_answer_scale (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
657 {
658 	GValue v = G_VALUE_INIT;
659 	g_value_init (&v, G_TYPE_DOUBLE);
660 
661 	GtkWidget *pScale = g_object_get_data (G_OBJECT (pInteractiveWidget), "cd-widget");
662 	g_return_if_fail (pScale != NULL);
663 	/**GtkWidget *pScale;
664 	if (GTK_IS_RANGE (pInteractiveWidget))
665 	{
666 		pScale = pInteractiveWidget;
667 	}
668 	else
669 	{
670 		GList *children = gtk_container_get_children (GTK_CONTAINER (pInteractiveWidget));
671 		g_return_if_fail (children != NULL && children->next != NULL);
672 		pScale = children->next->data;
673 	}*/
674 
675 	double x = gtk_range_get_value (GTK_RANGE (pScale));
676 	g_value_set_double (&v, x);
677 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
678 }
679 
cd_dbus_applet_emit_on_answer_combo_entry(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)680 void cd_dbus_applet_emit_on_answer_combo_entry (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
681 {
682 	GValue v = G_VALUE_INIT;
683 	g_value_init (&v, G_TYPE_STRING);
684 
685 	GtkWidget *pEntry = gtk_bin_get_child (GTK_BIN (pInteractiveWidget));
686 	const gchar *cText = gtk_entry_get_text (GTK_ENTRY (pEntry));
687 
688 	g_value_set_string (&v, cText);
689 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
690 }
691 
cd_dbus_applet_emit_on_answer_combo(int iClickedButton,GtkWidget * pInteractiveWidget,dbusApplet * pDbusApplet,CairoDialog * pDialog)692 void cd_dbus_applet_emit_on_answer_combo (int iClickedButton, GtkWidget *pInteractiveWidget, dbusApplet *pDbusApplet, CairoDialog *pDialog)
693 {
694 	GValue v = G_VALUE_INIT;
695 	g_value_init (&v, G_TYPE_INT);
696 
697 	int iSelectedItem = gtk_combo_box_get_active (GTK_COMBO_BOX (pInteractiveWidget));
698 
699 	g_value_set_int (&v, iSelectedItem);
700 	_emit_answer_dialog (pDbusApplet, pDialog, iClickedButton, &v);
701 }
702 
cd_dbus_applet_emit_on_shortkey(const gchar * cShortkey,dbusApplet * pDbusApplet)703 void cd_dbus_applet_emit_on_shortkey (const gchar *cShortkey, dbusApplet *pDbusApplet)
704 {
705 	g_signal_emit (pDbusApplet, s_iSignals[SHORTKEY], 0, cShortkey);
706 }
707 
708 
cd_dbus_action_on_init_module(GldiModuleInstance * pModuleInstance)709 void cd_dbus_action_on_init_module (GldiModuleInstance *pModuleInstance)
710 {
711 	GldiVisitCard *pVisitCard = pModuleInstance->pModule->pVisitCard;
712 	if (pModuleInstance->pDesklet)
713 	{
714 		cairo_dock_set_desklet_renderer_by_name (pModuleInstance->pDesklet,
715 			"Simple",
716 			(CairoDeskletRendererConfigPtr) NULL);
717 	}
718 
719 	Icon *pIcon = pModuleInstance->pIcon;
720 	if (pIcon && pIcon->cFileName == NULL && pIcon->image.pSurface)
721 	{
722 		cairo_t *pDrawContext = cairo_create (pIcon->image.pSurface);
723 		cairo_dock_set_image_on_icon (pDrawContext, pVisitCard->cIconFilePath, pIcon, pModuleInstance->pContainer);
724 		cairo_destroy (pDrawContext);
725 		gtk_widget_queue_draw (pModuleInstance->pContainer->pWidget);
726 	}
727 }
728 
729 
cd_dbus_action_on_stop_module(GldiModuleInstance * pModuleInstance)730 void cd_dbus_action_on_stop_module (GldiModuleInstance *pModuleInstance)
731 {
732 	if (pModuleInstance->pIcon->pSubDock != NULL)
733 	{
734 		gldi_object_unref (GLDI_OBJECT(pModuleInstance->pIcon->pSubDock));
735 		pModuleInstance->pIcon->pSubDock = NULL;
736 	}
737 
738 	cairo_dock_remove_data_renderer_on_icon (pModuleInstance->pIcon);
739 
740 	if (pModuleInstance->pDesklet != NULL && pModuleInstance->pDesklet->icons != NULL)  // idem, version desklet.
741 	{
742 		g_list_foreach (pModuleInstance->pDesklet->icons, (GFunc) gldi_object_unref, NULL);
743 		g_list_free (pModuleInstance->pDesklet->icons);
744 		pModuleInstance->pDesklet->icons = NULL;
745 	}
746 }
747 
cd_dbus_emit_on_stop_module(GldiModuleInstance * pModuleInstance)748 void cd_dbus_emit_on_stop_module (GldiModuleInstance *pModuleInstance)
749 {
750 	//g_print ("%s (%s)\n", __func__, pModuleInstance->pModule->pVisitCard->cModuleName);
751 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pModuleInstance);
752 	if (pDbusApplet != NULL)
753 		g_signal_emit (pDbusApplet,
754 			s_iSignals[STOP_MODULE],
755 			0,
756 			NULL);
757 
758 	cd_dbus_action_on_stop_module (pModuleInstance);
759 
760 	cd_dbus_delete_remote_applet_object (pDbusApplet);
761 }
762 
cd_dbus_emit_on_reload_module(GldiModuleInstance * pModuleInstance,GldiContainer * pOldContainer,GKeyFile * pKeyFile)763 gboolean cd_dbus_emit_on_reload_module (GldiModuleInstance *pModuleInstance, GldiContainer *pOldContainer, GKeyFile *pKeyFile)
764 {
765 	//g_print ("%s ()\n", __func__);
766 	GldiVisitCard *pVisitCard = pModuleInstance->pModule->pVisitCard;
767 	dbusApplet *pDbusApplet = cd_dbus_get_dbus_applet_from_instance (pModuleInstance);
768 	g_return_val_if_fail (pDbusApplet != NULL, FALSE);
769 	g_signal_emit (pDbusApplet,
770 		s_iSignals[RELOAD_MODULE],
771 		0,
772 		pKeyFile != NULL);
773 
774 	if (pModuleInstance->pDesklet)
775 	{
776 		if (pModuleInstance->pDesklet->icons == NULL)
777 		{
778 			cairo_dock_set_desklet_renderer_by_name (pModuleInstance->pDesklet,
779 				"Simple",
780 				(CairoDeskletRendererConfigPtr) NULL);
781 		}
782 		else
783 		{
784 			gpointer data[2] = {GINT_TO_POINTER (TRUE), GINT_TO_POINTER (FALSE)};
785 			cairo_dock_set_desklet_renderer_by_name (pModuleInstance->pDesklet,
786 				"Caroussel",
787 				(CairoDeskletRendererConfigPtr) data);
788 		}
789 	}
790 
791 	Icon *pIcon = pModuleInstance->pIcon;
792 	if (pIcon && pIcon->cFileName == NULL && pIcon->image.pSurface && (pIcon->pDataRenderer == NULL || pIcon->pDataRenderer->bUseOverlay))
793 	{
794 		cairo_t *pDrawContext = cairo_create (pIcon->image.pSurface);
795 		cairo_dock_set_image_on_icon (pDrawContext, pVisitCard->cIconFilePath, pIcon, pModuleInstance->pContainer);
796 		cairo_destroy (pDrawContext);
797 		gtk_widget_queue_draw (pModuleInstance->pContainer->pWidget);
798 	}
799 
800 	if (pKeyFile == NULL)
801 	{
802 		CairoDataRenderer *pDataRenderer = cairo_dock_get_icon_data_renderer (pIcon);
803 		if (pDataRenderer != NULL)
804 		{
805 			CairoDataToRenderer *pData = cairo_data_renderer_get_data (pDataRenderer);
806 			if (pData->iMemorySize > 2)
807 				cairo_dock_resize_data_renderer_history (pIcon, pIcon->fWidth);
808 		}
809 	}
810 
811 	return TRUE;
812 }
813