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 <math.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #define __USE_POSIX 1
24 #include <time.h>
25 #include <glib.h>
26 #include <glib/gi18n.h>
27 #include <cairo.h>
28 #include <gtk/gtk.h>
29 #include <glib/gstdio.h>  // g_mkdir/g_remove
30 
31 #include "config.h"
32 #include "gldi-icon-names.h"
33 #include "cairo-dock-animations.h"  // cairo_dock_trigger_icon_removal_from_dock
34 #include "cairo-dock-icon-facility.h"
35 #include "cairo-dock-applications-manager.h"
36 #include "cairo-dock-stack-icon-manager.h"
37 #include "cairo-dock-separator-manager.h"
38 #include "cairo-dock-applet-manager.h"
39 #include "cairo-dock-class-icon-manager.h"
40 #include "cairo-dock-launcher-manager.h"
41 #include "cairo-dock-module-manager.h"
42 #include "cairo-dock-module-instance-manager.h"
43 #include "cairo-dock-dock-factory.h"
44 #include "cairo-dock-dock-facility.h"
45 #include "cairo-dock-themes-manager.h"  // cairo_dock_update_conf_file
46 #include "cairo-dock-file-manager.h"  // cairo_dock_copy_file
47 #include "cairo-dock-log.h"
48 #include "cairo-dock-utils.h"  // cairo_dock_launch_command_sync
49 #include "cairo-dock-desklet-manager.h"
50 #include "cairo-dock-dock-manager.h"
51 #include "cairo-dock-class-manager.h"
52 #include "cairo-dock-container.h"
53 #include "cairo-dock-dialog-factory.h"  // gldi_dialog_show_*
54 #include "cairo-dock-desktop-manager.h"
55 #include "cairo-dock-windows-manager.h"
56 #include "cairo-dock-user-interaction.h"  // set_custom_icon_on_appli
57 #include "cairo-dock-gui-backend.h"
58 #include "cairo-dock-gui-commons.h"
59 #include "cairo-dock-applet-facility.h"  // cairo_dock_pop_up_about_applet
60 #include "cairo-dock-menu.h"
61 #include "cairo-dock-user-menu.h"
62 
63 #define CAIRO_DOCK_CONF_PANEL_WIDTH 1000
64 #define CAIRO_DOCK_CONF_PANEL_HEIGHT 600
65 #define CAIRO_DOCK_ABOUT_WIDTH 400
66 #define CAIRO_DOCK_ABOUT_HEIGHT 500
67 #define CAIRO_DOCK_FILE_HOST_URL "https://launchpad.net/cairo-dock"  // https://developer.berlios.de/project/showfiles.php?group_id=8724
68 #define CAIRO_DOCK_SITE_URL "http://glx-dock.org"  // http://cairo-dock.vef.fr
69 #define CAIRO_DOCK_FORUM_URL "http://forum.glx-dock.org"  // http://cairo-dock.vef.fr/bg_forumlist.php
70 #define CAIRO_DOCK_PAYPAL_URL "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=UWQ3VVRB2ZTZS&lc=GB&item_name=Support%20Cairo%2dDock&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted"
71 #define CAIRO_DOCK_FLATTR_URL "http://flattr.com/thing/370779/Support-Cairo-Dock-development"
72 
73 extern CairoDock *g_pMainDock;
74 extern GldiDesktopGeometry g_desktopGeometry;
75 
76 extern gchar *g_cConfFile;
77 extern gchar *g_cCurrentLaunchersPath;
78 extern gchar *g_cCurrentThemePath;
79 extern gchar *g_cCurrentIconsPath;
80 
81 extern gboolean g_bLocked;
82 extern gboolean g_bForceCairo;
83 extern gboolean g_bEasterEggs;
84 
85 #define cairo_dock_icons_are_locked(...) (myDocksParam.bLockIcons || myDocksParam.bLockAll || g_bLocked)
86 #define cairo_dock_is_locked(...) (myDocksParam.bLockAll || g_bLocked)
87 
88 #define _add_entry_in_menu(cLabel, gtkStock, pCallBack, pSubMenu) cairo_dock_add_in_menu_with_stock_and_data (cLabel, gtkStock, G_CALLBACK (pCallBack), pSubMenu, data)
89 
90 
91   //////////////////////////////////////////////
92  /////////// CAIRO-DOCK SUB-MENU //////////////
93 //////////////////////////////////////////////
94 
_cairo_dock_edit_and_reload_conf(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)95 static void _cairo_dock_edit_and_reload_conf (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
96 {
97 	cairo_dock_show_main_gui ();
98 }
99 
_cairo_dock_configure_root_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,CairoDock * pDock)100 static void _cairo_dock_configure_root_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, CairoDock *pDock)
101 {
102 	g_return_if_fail (pDock->iRefCount == 0 && ! pDock->bIsMainDock);
103 
104 	cairo_dock_show_items_gui (NULL, CAIRO_CONTAINER (pDock), NULL, 0);
105 }
_on_answer_delete_dock(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,CairoDock * pDock,G_GNUC_UNUSED CairoDialog * pDialog)106 static void _on_answer_delete_dock (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, CairoDock *pDock, G_GNUC_UNUSED CairoDialog *pDialog)
107 {
108 	if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
109 	{
110 		gldi_object_delete (GLDI_OBJECT(pDock));
111 	}
112 }
_cairo_dock_delete_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,CairoDock * pDock)113 static void _cairo_dock_delete_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, CairoDock *pDock)
114 {
115 	g_return_if_fail (pDock->iRefCount == 0 && ! pDock->bIsMainDock);
116 
117 	Icon *pIcon = cairo_dock_get_pointed_icon (pDock->icons);
118 
119 	gldi_dialog_show_with_question (_("Delete this dock?"),
120 		pIcon, CAIRO_CONTAINER (pDock),
121 		CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
122 		(CairoDockActionOnAnswerFunc)_on_answer_delete_dock, pDock, (GFreeFunc)NULL);
123 }
_cairo_dock_initiate_theme_management(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)124 static void _cairo_dock_initiate_theme_management (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
125 {
126 	cairo_dock_show_themes ();
127 }
128 
_cairo_dock_add_about_page(GtkWidget * pNoteBook,const gchar * cPageLabel,const gchar * cAboutText)129 static void _cairo_dock_add_about_page (GtkWidget *pNoteBook, const gchar *cPageLabel, const gchar *cAboutText)
130 {
131 	GtkWidget *pVBox, *pScrolledWindow;
132 	GtkWidget *pPageLabel, *pAboutLabel;
133 
134 	pPageLabel = gtk_label_new (cPageLabel);
135 	pVBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
136 	pScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
137 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (pScrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
138 	#if GTK_CHECK_VERSION (3, 8, 0)
139 	gtk_container_add (GTK_CONTAINER (pScrolledWindow), pVBox);
140 	#else
141 	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (pScrolledWindow), pVBox);
142 	#endif
143 	gtk_notebook_append_page (GTK_NOTEBOOK (pNoteBook), pScrolledWindow, pPageLabel);
144 
145 	pAboutLabel = gtk_label_new (NULL);
146 	gtk_label_set_use_markup (GTK_LABEL (pAboutLabel), TRUE);
147 	gtk_misc_set_alignment (GTK_MISC (pAboutLabel), 0.0, 0.0);
148 	gtk_misc_set_padding (GTK_MISC (pAboutLabel), 30, 0);
149 	gtk_box_pack_start (GTK_BOX (pVBox),
150 		pAboutLabel,
151 		FALSE,
152 		FALSE,
153 		15);
154 	gtk_label_set_markup (GTK_LABEL (pAboutLabel), cAboutText);
155 }
_cairo_dock_lock_icons(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)156 static void _cairo_dock_lock_icons (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
157 {
158 	myDocksParam.bLockIcons = ! myDocksParam.bLockIcons;
159 	cairo_dock_update_conf_file (g_cConfFile,
160 		G_TYPE_BOOLEAN, "Accessibility", "lock icons", myDocksParam.bLockIcons,
161 		G_TYPE_INVALID);
162 }
163 
164 /* Not used
165 static void _cairo_dock_lock_all (GtkMenuItem *pMenuItem, gpointer data)
166 {
167 	myDocksParam.bLockAll = ! myDocksParam.bLockAll;
168 	cairo_dock_update_conf_file (g_cConfFile,
169 		G_TYPE_BOOLEAN, "Accessibility", "lock all", myDocksParam.bLockAll,
170 		G_TYPE_INVALID);
171 }
172 */
_cairo_dock_about(G_GNUC_UNUSED GtkMenuItem * pMenuItem,GldiContainer * pContainer)173 static void _cairo_dock_about (G_GNUC_UNUSED GtkMenuItem *pMenuItem, GldiContainer *pContainer)
174 {
175 	// build dialog
176 	GtkWidget *pDialog = gtk_dialog_new_with_buttons (_("About Cairo-Dock"),
177 		GTK_WINDOW (pContainer->pWidget),
178 		GTK_DIALOG_DESTROY_WITH_PARENT,
179 		GLDI_ICON_NAME_CLOSE,
180 		GTK_RESPONSE_CLOSE,
181 		NULL);
182 
183 	// the dialog box is destroyed when the user responds
184 	g_signal_connect_swapped (pDialog,
185 		"response",
186 		G_CALLBACK (gtk_widget_destroy),
187 		pDialog);
188 
189 	GtkWidget *pContentBox = gtk_dialog_get_content_area (GTK_DIALOG(pDialog));
190 
191 	// logo + links
192 	GtkWidget *pHBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
193 	gtk_box_pack_start (GTK_BOX (pContentBox), pHBox, FALSE, FALSE, 0);
194 
195 	const gchar *cImagePath = CAIRO_DOCK_SHARE_DATA_DIR"/images/"CAIRO_DOCK_LOGO;
196 	GtkWidget *pImage = gtk_image_new_from_file (cImagePath);
197 	gtk_box_pack_start (GTK_BOX (pHBox), pImage, FALSE, FALSE, 0);
198 
199 	GtkWidget *pVBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
200 	gtk_box_pack_start (GTK_BOX (pHBox), pVBox, FALSE, FALSE, 0);
201 
202 	GtkWidget *pLink = gtk_link_button_new_with_label (CAIRO_DOCK_SITE_URL, "Cairo-Dock (2007-2014)\n version "CAIRO_DOCK_VERSION);
203 	gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
204 
205 	//~ pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FORUM_URL, _("Community site"));
206 	//~ gtk_widget_set_tooltip_text (pLink, _("Problems? Suggestions? Just want to talk to us? Come on over!"));
207 	//~ gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
208 
209 	pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FILE_HOST_URL, _("Development site"));
210 	gtk_widget_set_tooltip_text (pLink, _("Find the latest version of Cairo-Dock here !"));
211 	gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
212 
213 	gchar *cLink = cairo_dock_get_third_party_applets_link ();
214 	pLink = gtk_link_button_new_with_label (cLink, _("Get more applets!"));
215 	g_free (cLink);
216 	gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
217 
218 	gchar *cLabel = g_strdup_printf ("%s (Flattr)", _("Donate"));
219 	pLink = gtk_link_button_new_with_label (CAIRO_DOCK_FLATTR_URL, cLabel);
220 	g_free (cLabel);
221 	gtk_widget_set_tooltip_text (pLink, _("Support the people who spend countless hours to bring you the best dock ever."));
222 	gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
223 
224 	cLabel = g_strdup_printf ("%s (Paypal)", _("Donate"));
225 	pLink = gtk_link_button_new_with_label (CAIRO_DOCK_PAYPAL_URL, cLabel);
226 	g_free (cLabel);
227 	gtk_widget_set_tooltip_text (pLink, _("Support the people who spend countless hours to bring you the best dock ever."));
228 	gtk_box_pack_start (GTK_BOX (pVBox), pLink, FALSE, FALSE, 0);
229 
230 
231 	// notebook
232 	GtkWidget *pNoteBook = gtk_notebook_new ();
233 	gtk_notebook_set_scrollable (GTK_NOTEBOOK (pNoteBook), TRUE);
234 	gtk_notebook_popup_enable (GTK_NOTEBOOK (pNoteBook));
235 	gtk_box_pack_start (GTK_BOX (pContentBox), pNoteBook, TRUE, TRUE, 0);
236 
237 	// About
238 	/* gchar *text = g_strdup_printf ("\n\n<b>%s</b>\n\n\n"
239 		"<a href=\"http://glx-dock.org\">http://glx-dock.org</a>",
240 		_("<b>Cairo-Dock is a pretty, light and convenient interface\n"
241 			" to your desktop, able to replace advantageously your system panel!</b>"));
242 	_cairo_dock_add_about_page (pNoteBook,
243 		_("About"),
244 		text);*/
245 	// Development
246 	gchar *text = g_strdup_printf ("%s\n\n"
247 	"<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
248 		"  Fabounet (Fabrice Rey)\n"
249 		"\t<span size=\"smaller\">%s</span>\n\n"
250 		"  Matttbe (Matthieu Baerts)\n"
251 		"\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
252 		"  Eduardo Mucelli\n"
253 		"  Jesuisbenjamin\n"
254 		"  SQP\n",
255 		_("Here is a list of the current developers and contributors"),
256 		_("Developers"),
257 		_("Main developer and project leader"),
258 		_("Contributors / Hackers"));
259 	_cairo_dock_add_about_page (pNoteBook,
260 		_("Development"),
261 		text);
262 	// Support
263 		text = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
264 		"  Matttbe\n"
265 		"  Mav\n"
266 		"  Necropotame\n"
267 		"\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
268 		"  BobH\n"
269 		"  Franksuse64\n"
270 		"  Lylambda\n"
271 		"  Ppmt\n"
272 		"  Taiebot65\n"
273 		"\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
274 		"%s",
275 		_("Website"),
276 		_("Beta-testing / Suggestions / Forum animation"),
277 		_("Translators for this language"),
278 		_("translator-credits"));
279 	_cairo_dock_add_about_page (pNoteBook,
280 		_("Support"),
281 		text);
282 	// Thanks
283 		text = g_strdup_printf ("%s\n"
284 		"<a href=\"http://glx-dock.org/ww_page.php?p=How to help us\">%s</a>: %s\n\n"
285 		"\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
286 		"  Augur\n"
287 		"  ChAnGFu\n"
288 		"  Ctaf\n"
289 		"  Mav\n"
290 		"  Necropotame\n"
291 		"  Nochka85\n"
292 		"  Paradoxxx_Zero\n"
293 		"  Rom1\n"
294 		"  Tofe\n"
295 		"  Mac Slow (original idea)\n"
296 		"\t<span size=\"smaller\">%s</span>\n"
297 		"\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
298 		"\t<a href=\"http://glx-dock.org/userlist_messages.php\">%s</a>\n"
299 		"\n\n<span size=\"larger\" weight=\"bold\">%s</span>\n\n"
300 		"  Benoit2600\n"
301 		"  Coz\n"
302 		"  Fabounet\n"
303 		"  Lord Northam\n"
304 		"  Lylambda\n"
305 		"  MastroPino\n"
306 		"  Matttbe\n"
307 		"  Nochka85\n"
308 		"  Paradoxxx_Zero\n"
309 		"  Taiebot65\n",
310 		_("Thanks to all people that help us to improve the Cairo-Dock project.\n"
311 			"Thanks to all current, former and future contributors."),
312 		_("How to help us?"),
313 		_("Don't hesitate to join the project, we need you ;)"),
314 		_("Former contributors"),
315 		_("For a complete list, please have a look to BZR logs"),
316 		_("Users of our forum"),
317 		_("List of our forum's members"),
318 		_("Artwork"));
319 	_cairo_dock_add_about_page (pNoteBook,
320 		_("Thanks"),
321 		text);
322 	g_free (text);
323 
324 	gtk_window_resize (GTK_WINDOW (pDialog),
325 		MIN (CAIRO_DOCK_ABOUT_WIDTH, gldi_desktop_get_width()),
326 		MIN (CAIRO_DOCK_ABOUT_HEIGHT, gldi_desktop_get_height() - (g_pMainDock && g_pMainDock->container.bIsHorizontal ? g_pMainDock->iMaxDockHeight : 0)));
327 
328 	gtk_widget_show_all (pDialog);
329 
330 	gtk_window_set_keep_above (GTK_WINDOW (pDialog), TRUE);
331 	//don't use gtk_dialog_run(), as we don't want to block the dock
332 }
333 
_launch_url(const gchar * cURL)334 static void _launch_url (const gchar *cURL)
335 {
336 	if  (! cairo_dock_fm_launch_uri (cURL))
337 	{
338 		gchar *cCommand = g_strdup_printf ("\
339 which xdg-open > /dev/null && xdg-open %s || \
340 which firefox > /dev/null && firefox %s || \
341 which konqueror > /dev/null && konqueror %s || \
342 which iceweasel > /dev/null && konqueror %s || \
343 which opera > /dev/null && opera %s ",
344 			cURL,
345 			cURL,
346 			cURL,
347 			cURL,
348 			cURL);  // pas super beau mais efficace ^_^
349 		int r = system (cCommand);
350 		if (r < 0)
351 			cd_warning ("Not able to launch this command: %s", cCommand);
352 		g_free (cCommand);
353 	}
354 }
_cairo_dock_show_third_party_applets(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)355 static void _cairo_dock_show_third_party_applets (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
356 {
357 	gchar *cLink = cairo_dock_get_third_party_applets_link ();
358 	_launch_url (cLink);
359 	g_free (cLink);
360 }
361 
_cairo_dock_present_help(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)362 static void _cairo_dock_present_help (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
363 {
364 	int iMode = cairo_dock_gui_backend_get_mode ();
365 	if (iMode == 0)
366 		cairo_dock_load_user_gui_backend (1); // load the advanced mode (it seems it's currently not possible to open the Help with the Simple mode)
367 	cairo_dock_show_module_gui ("Help");
368 	if (iMode == 0)
369 		cairo_dock_load_user_gui_backend (0);
370 }
371 
_cairo_dock_quick_hide(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED CairoDock * pDock)372 static void _cairo_dock_quick_hide (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED CairoDock *pDock)
373 {
374 	//g_print ("%s ()\n", __func__);
375 	///pDock->bHasModalWindow = FALSE;
376 	cairo_dock_quick_hide_all_docks ();
377 }
378 
_cairo_dock_add_autostart(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer data)379 static void _cairo_dock_add_autostart (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer data)
380 {
381 	gchar *cCairoAutoStartDirPath = g_strdup_printf ("%s/.config/autostart", g_getenv ("HOME"));
382 	if (! g_file_test (cCairoAutoStartDirPath, G_FILE_TEST_IS_DIR))
383 	{
384 		if (g_mkdir (cCairoAutoStartDirPath, 7*8*8+5*8+5) != 0)
385 		{
386 			cd_warning ("couldn't create directory %s", cCairoAutoStartDirPath);
387 			g_free (cCairoAutoStartDirPath);
388 			return ;
389 		}
390 	}
391 	cairo_dock_copy_file ("/usr/local/share/applications/cairo-dock.desktop", cCairoAutoStartDirPath);
392 	g_free (cCairoAutoStartDirPath);
393 }
394 
_on_answer_quit(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,G_GNUC_UNUSED gpointer data,G_GNUC_UNUSED CairoDialog * pDialog)395 static void _on_answer_quit (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, G_GNUC_UNUSED gpointer data, G_GNUC_UNUSED CairoDialog *pDialog)
396 {
397 	if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
398 	{
399 		gtk_main_quit ();
400 	}
401 }
_cairo_dock_quit(G_GNUC_UNUSED GtkMenuItem * pMenuItem,GldiContainer * pContainer)402 static void _cairo_dock_quit (G_GNUC_UNUSED GtkMenuItem *pMenuItem, GldiContainer *pContainer)
403 {
404 	Icon *pIcon = NULL;
405 	if (CAIRO_DOCK_IS_DOCK (pContainer))
406 		pIcon = cairo_dock_get_pointed_icon (CAIRO_DOCK (pContainer)->icons);
407 	else if (CAIRO_DOCK_IS_DESKLET (pContainer))
408 		pIcon = CAIRO_DESKLET (pContainer)->pIcon;
409 
410 	gldi_dialog_show_with_question (_("Quit Cairo-Dock?"),
411 		pIcon, pContainer,
412 		CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON,
413 		(CairoDockActionOnAnswerFunc) _on_answer_quit, NULL, (GFreeFunc)NULL);
414 }
415 
416 
417   ////////////////////////////////////////
418  /////////// ITEM SUB-MENU //////////////
419 ////////////////////////////////////////
420 
_add_item_sub_menu(Icon * icon,GtkWidget * pMenu)421 GtkWidget *_add_item_sub_menu (Icon *icon, GtkWidget *pMenu)
422 {
423 	const gchar *cName = NULL;
424 	if (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (icon) || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (icon))
425 	{
426 		cName = (icon->cInitialName ? icon->cInitialName : icon->cName);
427 	}
428 	else if (CAIRO_DOCK_ICON_TYPE_IS_APPLI (icon) || CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (icon))
429 	{
430 		cName = cairo_dock_get_class_name (icon->cClass);  // better than the current window title.
431 		if (cName == NULL)
432 			cName = icon->cClass;
433 	}
434 	else if (CAIRO_DOCK_IS_APPLET (icon))
435 	{
436 		cName = icon->pModuleInstance->pModule->pVisitCard->cTitle;
437 	}
438 	else if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
439 	{
440 		cName = _("Separator");
441 	}
442 	else
443 		cName = icon->cName;
444 
445 	gchar *cIconFile = NULL;
446 	if (CAIRO_DOCK_IS_APPLET (icon))
447 	{
448 		if (icon->cFileName != NULL)  // if possible, use the actual icon
449 			cIconFile = cairo_dock_search_icon_s_path (icon->cFileName, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
450 		if (!cIconFile)  // else, use the default applet's icon.
451 			cIconFile = cairo_dock_search_icon_s_path (icon->pModuleInstance->pModule->pVisitCard->cIconFilePath, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
452 	}
453 	else if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
454 	{
455 		if (myIconsParam.cSeparatorImage)
456 			cIconFile = cairo_dock_search_image_s_path (myIconsParam.cSeparatorImage);
457 	}
458 	else if (icon->cFileName != NULL)
459 	{
460 		cIconFile = cairo_dock_search_icon_s_path (icon->cFileName, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
461 	}
462 	if (cIconFile == NULL && icon->cClass != NULL)
463 	{
464 		const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
465 		if (cClassIcon)
466 			cIconFile = cairo_dock_search_icon_s_path (cClassIcon, cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR));
467 	}
468 
469 	GtkWidget *pItemSubMenu;
470 	GdkPixbuf *pixbuf = NULL;
471 
472 	if (!cIconFile)  // no icon file (for instance a class that has no icon defined in its desktop file, like gnome-setting-daemon) => use its buffer directly.
473 	{
474 		pixbuf = cairo_dock_icon_buffer_to_pixbuf (icon);
475 	}
476 
477 	if (pixbuf)
478 	{
479 		GtkWidget *pMenuItem = NULL;
480 		pItemSubMenu = gldi_menu_add_sub_menu_full (pMenu, cName, "", &pMenuItem);
481 
482 		GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
483 		gldi_menu_item_set_image (pMenuItem, image);
484 		g_object_unref (pixbuf);
485 	}
486 	else
487 	{
488 		pItemSubMenu = cairo_dock_create_sub_menu (cName, pMenu, cIconFile);
489 	}
490 
491 	g_free (cIconFile);
492 	return pItemSubMenu;
493 }
494 
495 
_get_next_order(Icon * icon,CairoDock * pDock)496 static double _get_next_order (Icon *icon, CairoDock *pDock)
497 {
498 	double fOrder;
499 	if (icon != NULL)
500 	{
501 		if (pDock->container.iMouseX < icon->fDrawX + icon->fWidth * icon->fScale / 2)  // a gauche.
502 		{
503 			Icon *prev_icon = cairo_dock_get_previous_icon (pDock->icons, icon);
504 			fOrder = (prev_icon != NULL ? (icon->fOrder + prev_icon->fOrder) / 2 : icon->fOrder - 1);
505 		}
506 		else
507 		{
508 			Icon *next_icon = cairo_dock_get_next_icon (pDock->icons, icon);
509 			fOrder = (next_icon != NULL ? (icon->fOrder + next_icon->fOrder) / 2 : icon->fOrder + 1);
510 		}
511 	}
512 	else
513 		fOrder = CAIRO_DOCK_LAST_ORDER;
514 	return fOrder;
515 }
516 
cairo_dock_add_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)517 static void cairo_dock_add_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
518 {
519 	Icon *icon = data[0];
520 	CairoDock *pDock = data[1];
521 	double fOrder = _get_next_order (icon, pDock);
522 	Icon *pNewIcon = gldi_launcher_add_new (NULL, pDock, fOrder);
523 	if (pNewIcon == NULL)
524 		cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
525 	else
526 		cairo_dock_show_items_gui (pNewIcon, NULL, NULL, -1);  // open the config so that the user can complete its fields
527 }
528 
cairo_dock_add_sub_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)529 static void cairo_dock_add_sub_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
530 {
531 	Icon *icon = data[0];
532 	CairoDock *pDock = data[1];
533 	double fOrder = _get_next_order (icon, pDock);
534 	Icon *pNewIcon = gldi_stack_icon_add_new (pDock, fOrder);
535 	if (pNewIcon == NULL)
536 		cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
537 }
538 
_show_new_dock_msg(gchar * cDockName)539 static gboolean _show_new_dock_msg (gchar *cDockName)
540 {
541 	CairoDock *pDock = gldi_dock_get (cDockName);
542 	if (pDock)
543 		gldi_dialog_show_temporary_with_default_icon (_("The new dock has been created.\nNow move some launchers or applets into it by right-clicking on the icon -> move to another dock"), NULL, CAIRO_CONTAINER (pDock), 10000);
544 	g_free (cDockName);
545 	return FALSE;
546 }
cairo_dock_add_main_dock(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer * data)547 static void cairo_dock_add_main_dock (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer *data)
548 {
549 	gchar *cDockName = gldi_dock_add_conf_file ();
550 	gldi_dock_new (cDockName);
551 
552 	cairo_dock_gui_trigger_reload_items ();  // we could also connect to the signal "new-object" on docks...
553 
554 	g_timeout_add_seconds (1, (GSourceFunc)_show_new_dock_msg, cDockName);  // delai, car sa fenetre n'est pas encore bien placee (0,0).
555 }
556 
cairo_dock_add_separator(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)557 static void cairo_dock_add_separator (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
558 {
559 	Icon *icon = data[0];
560 	CairoDock *pDock = data[1];
561 	double fOrder = _get_next_order (icon, pDock);
562 	Icon *pNewIcon = gldi_separator_icon_add_new (pDock, fOrder);
563 	if (pNewIcon == NULL)
564 		cd_warning ("Couldn't create create the icon.\nCheck that you have writing permissions on ~/.config/cairo-dock and its sub-folders");
565 }
566 
cairo_dock_add_applet(G_GNUC_UNUSED GtkMenuItem * pMenuItem,G_GNUC_UNUSED gpointer * data)567 static void cairo_dock_add_applet (G_GNUC_UNUSED GtkMenuItem *pMenuItem, G_GNUC_UNUSED gpointer *data)
568 {
569 	cairo_dock_show_addons ();
570 }
571 
_add_add_entry(GtkWidget * pMenu,gpointer * data)572 static void _add_add_entry (GtkWidget *pMenu, gpointer *data)
573 {
574 	GtkWidget *pSubMenuAdd = cairo_dock_create_sub_menu (_("Add"), pMenu, GLDI_ICON_NAME_ADD);
575 
576 	_add_entry_in_menu (_("Sub-dock"), GLDI_ICON_NAME_ADD, cairo_dock_add_sub_dock, pSubMenuAdd);
577 
578 	_add_entry_in_menu (_("Main dock"), GLDI_ICON_NAME_ADD, cairo_dock_add_main_dock, pSubMenuAdd);
579 
580 	_add_entry_in_menu (_("Separator"), GLDI_ICON_NAME_ADD, cairo_dock_add_separator, pSubMenuAdd);
581 
582 	GtkWidget *pMenuItem = _add_entry_in_menu (_("Custom launcher"), GLDI_ICON_NAME_ADD, cairo_dock_add_launcher, pSubMenuAdd);
583 	gtk_widget_set_tooltip_text (pMenuItem, _("Usually you would drag a launcher from the menu and drop it on the dock."));
584 
585 	_add_entry_in_menu (_("Applet"), GLDI_ICON_NAME_ADD, cairo_dock_add_applet, pSubMenuAdd);
586 }
587 
588 
589   ///////////////////////////////////////////
590  /////////// LAUNCHER ACTIONS //////////////
591 ///////////////////////////////////////////
592 
_on_answer_remove_icon(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,Icon * icon,G_GNUC_UNUSED CairoDialog * pDialog)593 static void _on_answer_remove_icon (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, Icon *icon, G_GNUC_UNUSED CairoDialog *pDialog)
594 {
595 	if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
596 	{
597 		if (CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (icon)
598 		&& icon->pSubDock != NULL)  // remove the sub-dock's content from the theme or dispatch it in the main dock.
599 		{
600 			if (icon->pSubDock->icons != NULL)  // on propose de repartir les icones de son sous-dock dans le dock principal.
601 			{
602 				int iClickedButton = gldi_dialog_show_and_wait (_("Do you want to re-dispatch the icons contained inside this container into the dock?\n(otherwise they will be destroyed)"),
603 					icon, CAIRO_CONTAINER (icon->pContainer),
604 					CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON, NULL);
605 				if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
606 				{
607 					CairoDock *pDock = CAIRO_DOCK (icon->pContainer);
608 					cairo_dock_remove_icons_from_dock (icon->pSubDock, pDock);
609 				}
610 			}
611 		}
612 		cairo_dock_trigger_icon_removal_from_dock (icon);
613 	}
614 }
_cairo_dock_remove_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)615 static void _cairo_dock_remove_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
616 {
617 	Icon *icon = data[0];
618 	CairoDock *pDock = data[1];
619 
620 	const gchar *cName = (icon->cInitialName != NULL ? icon->cInitialName : icon->cName);
621 	if (cName == NULL)
622 	{
623 		if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
624 			cName = _("separator");
625 		else
626 			cName = "no name";
627 	}
628 	gchar *question = g_strdup_printf (_("You're about to remove this icon (%s) from the dock. Are you sure?"), cName);
629 	gldi_dialog_show_with_question (question,
630 			icon, CAIRO_CONTAINER (pDock),
631 			"same icon",
632 			(CairoDockActionOnAnswerFunc) _on_answer_remove_icon, icon, (GFreeFunc)NULL);
633 	g_free (question);
634 }
635 
_cairo_dock_modify_launcher(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)636 static void _cairo_dock_modify_launcher (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
637 {
638 	Icon *icon = data[0];
639 	CairoDock *pDock = data[1];
640 
641 	if (icon->cDesktopFileName == NULL || strcmp (icon->cDesktopFileName, "none") == 0)
642 	{
643 		gldi_dialog_show_temporary_with_icon (_("Sorry, this icon doesn't have a configuration file."), icon, CAIRO_CONTAINER (pDock), 4000, "same icon");
644 		return ;
645 	}
646 
647 	cairo_dock_show_items_gui (icon, NULL, NULL, -1);
648 }
649 
_cairo_dock_move_launcher_to_dock(GtkMenuItem * pMenuItem,const gchar * cDockName)650 static void _cairo_dock_move_launcher_to_dock (GtkMenuItem *pMenuItem, const gchar *cDockName)
651 {
652 	Icon *pIcon = g_object_get_data (G_OBJECT (pMenuItem), "icon-item");
653 
654 	//\_________________________ on cree si besoin le fichier de conf d'un nouveau dock racine.
655 	gchar *cValidDockName;
656 	if (cDockName == NULL)  // nouveau dock
657 	{
658 		cValidDockName = gldi_dock_add_conf_file ();
659 	}
660 	else
661 	{
662 		cValidDockName = g_strdup (cDockName);
663 	}
664 
665 	//\_________________________ on met a jour le fichier de conf de l'icone.
666 	gldi_theme_icon_write_container_name_in_conf_file (pIcon, cValidDockName);
667 
668 	//\_________________________ on recharge l'icone, ce qui va creer le dock.
669 	if ((CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
670 		|| CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
671 		|| CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
672 	&& pIcon->cDesktopFileName != NULL)  // user icon.
673 	{
674 		gldi_object_reload (GLDI_OBJECT(pIcon), TRUE);  // TRUE <=> reload config.
675 	}
676 	else if (CAIRO_DOCK_IS_APPLET (pIcon))
677 	{
678 		gldi_object_reload (GLDI_OBJECT(pIcon->pModuleInstance), TRUE);  // TRUE <=> reload config.
679 	}
680 
681 	CairoDock *pNewDock = gldi_dock_get (cValidDockName);
682 	if (pNewDock && pNewDock->iRefCount == 0 && pNewDock->icons && pNewDock->icons->next == NULL)  // le dock vient d'etre cree avec cette icone.
683 		gldi_dialog_show_general_message (_("The new dock has been created.\nYou can customize it by right-clicking on it -> cairo-dock -> configure this dock."), 8000);  // on le place pas sur le nouveau dock, car sa fenetre n'est pas encore bien placee (0,0).
684 	g_free (cValidDockName);
685 }
686 
_cairo_dock_add_docks_sub_menu(GtkWidget * pMenu,Icon * pIcon)687 static void _cairo_dock_add_docks_sub_menu (GtkWidget *pMenu, Icon *pIcon)
688 {
689 	GtkWidget *pSubMenuDocks = cairo_dock_create_sub_menu (_("Move to another dock"), pMenu, GLDI_ICON_NAME_JUMP_TO);
690 	g_object_set_data (G_OBJECT (pSubMenuDocks), "icon-item", pIcon);
691 	GtkWidget *pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("New main dock"), GLDI_ICON_NAME_NEW, G_CALLBACK (_cairo_dock_move_launcher_to_dock), pSubMenuDocks, NULL);
692 	g_object_set_data (G_OBJECT (pMenuItem), "icon-item", pIcon);
693 
694 	GList *pDocks = cairo_dock_get_available_docks_for_icon (pIcon);
695 	const gchar *cName;
696 	gchar *cUserName;
697 	CairoDock *pDock;
698 	GList *d;
699 	for (d = pDocks; d != NULL; d = d->next)
700 	{
701 		pDock = d->data;
702 		cName = gldi_dock_get_name (pDock);
703 		cUserName = gldi_dock_get_readable_name (pDock);
704 
705 		GtkWidget *pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (cUserName ? cUserName : cName, NULL, G_CALLBACK (_cairo_dock_move_launcher_to_dock), pSubMenuDocks, (gpointer)cName);
706 		g_object_set_data (G_OBJECT (pMenuItem), "icon-item", pIcon);
707 		g_free (cUserName);
708 	}
709 	g_list_free (pDocks);
710 }
711 
_cairo_dock_make_launcher_from_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)712 static void _cairo_dock_make_launcher_from_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
713 {
714 	Icon *icon = data[0];
715 	CairoDock *pDock = data[1];
716 	g_return_if_fail (icon->cClass != NULL);
717 
718 	// look for the .desktop file of the program
719 	cd_debug ("%s (%s)", __func__, icon->cClass);
720 	gchar *cDesktopFilePath = g_strdup (cairo_dock_get_class_desktop_file (icon->cClass));
721 	if (cDesktopFilePath == NULL)  // empty class
722 	{
723 		gchar *cCommand = g_strdup_printf ("find /usr/local/share/applications /usr/local/share/applications -iname \"*%s*.desktop\"", icon->cClass);  // look for a desktop file from their file name
724 		gchar *cResult = cairo_dock_launch_command_sync (cCommand);
725 		if (cResult == NULL || *cResult == '\0')  // no luck, search harder
726 		{
727 			g_free (cCommand);
728 			cCommand = g_strdup_printf ("find /usr/local/share/applications /usr/local/share/applications -name \"*.desktop\" -exec grep -qi '%s' {} \\; -print", icon->cClass);  // look for a desktop file from their content
729 			cResult = cairo_dock_launch_command_sync (cCommand);
730 		}
731 		if (cResult != NULL && *cResult != '\0')
732 		{
733 			gchar *str = strchr (cResult, '\n');  // remove the trailing linefeed, and only take the first result
734 			if (str)
735 				*str = '\0';
736 			cDesktopFilePath = cResult;
737 		}
738 		g_free (cCommand);
739 	}
740 
741 	// make a new launcher from this desktop file
742 	if (cDesktopFilePath != NULL)
743 	{
744 		cd_message ("found desktop file : %s", cDesktopFilePath);
745 		// place it after the last launcher, since the user will probably want to move this new launcher amongst the already existing ones.
746 		double fOrder = CAIRO_DOCK_LAST_ORDER;
747 		Icon *pIcon;
748 		GList *ic, *last_launcher_ic = NULL;
749 		for (ic = g_pMainDock->icons; ic != NULL; ic = ic->next)
750 		{
751 			pIcon = ic->data;
752 			if (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
753 			|| CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon))
754 			{
755 				last_launcher_ic = ic;
756 			}
757 		}
758 		if (last_launcher_ic != NULL)
759 		{
760 			ic = last_launcher_ic;
761 			pIcon = ic->data;
762 			Icon *next_icon = (ic->next ? ic->next->data : NULL);
763 			if (next_icon != NULL && cairo_dock_get_icon_order (next_icon) == cairo_dock_get_icon_order (pIcon))
764 				fOrder = (pIcon->fOrder + next_icon->fOrder) / 2;
765 			else
766 				fOrder = pIcon->fOrder + 1;
767 		}
768 		gldi_launcher_add_new (cDesktopFilePath, g_pMainDock, fOrder);  // add in the main dock
769 	}
770 	else
771 	{
772 		gldi_dialog_show_temporary_with_default_icon (_("Sorry, couldn't find the corresponding description file.\nConsider dragging and dropping the launcher from the Applications Menu."), icon, CAIRO_CONTAINER (pDock), 8000);
773 	}
774 	g_free (cDesktopFilePath);
775 }
776 
777   //////////////////////////////////////////////////////////////////
778  /////////// LES OPERATIONS SUR LES APPLETS ///////////////////////
779 //////////////////////////////////////////////////////////////////
780 
_cairo_dock_initiate_config_module(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)781 static void _cairo_dock_initiate_config_module (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
782 {
783 	cd_debug ("%s ()", __func__);
784 	Icon *icon = data[0];
785 	GldiContainer *pContainer= data[1];
786 	if (CAIRO_DOCK_IS_DESKLET (pContainer))
787 		icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module.
788 	g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
789 
790 	cairo_dock_show_items_gui (icon, NULL, NULL, -1);
791 }
792 
_cairo_dock_detach_module(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)793 static void _cairo_dock_detach_module (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
794 {
795 	Icon *icon = data[0];
796 	GldiContainer *pContainer= data[1];
797 	if (CAIRO_DOCK_IS_DESKLET (pContainer))
798 		icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
799 	g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
800 
801 	gldi_module_instance_detach (icon->pModuleInstance);
802 }
803 
_on_answer_remove_module_instance(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,Icon * icon,G_GNUC_UNUSED CairoDialog * pDialog)804 static void _on_answer_remove_module_instance (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, Icon *icon, G_GNUC_UNUSED CairoDialog *pDialog)
805 {
806 	if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
807 	{
808 		gldi_object_delete (GLDI_OBJECT(icon->pModuleInstance));
809 	}
810 }
_cairo_dock_remove_module_instance(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)811 static void _cairo_dock_remove_module_instance (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
812 {
813 	Icon *icon = data[0];
814 	GldiContainer *pContainer= data[1];
815 	if (CAIRO_DOCK_IS_DESKLET (pContainer))
816 		icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
817 	g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
818 
819 	gchar *question = g_strdup_printf (_("You're about to remove this applet (%s) from the dock. Are you sure?"), icon->pModuleInstance->pModule->pVisitCard->cTitle);
820 	gldi_dialog_show_with_question (question,
821 		icon, CAIRO_CONTAINER (pContainer),
822 		"same icon",
823 		(CairoDockActionOnAnswerFunc) _on_answer_remove_module_instance, icon, (GFreeFunc)NULL);
824 	g_free (question);
825 }
826 
_cairo_dock_add_module_instance(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)827 static void _cairo_dock_add_module_instance (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
828 {
829 	Icon *icon = data[0];
830 	GldiContainer *pContainer= data[1];
831 	if (CAIRO_DOCK_IS_DESKLET (pContainer))
832 		icon = (CAIRO_DESKLET (pContainer))->pIcon;  // l'icone cliquee du desklet n'est pas forcement celle qui contient le module !
833 	g_return_if_fail (CAIRO_DOCK_IS_APPLET (icon));
834 
835 	gldi_module_add_instance (icon->pModuleInstance->pModule);
836 }
837 
_cairo_dock_set_sensitive_quit_menu(G_GNUC_UNUSED GtkWidget * pMenuItem,GdkEventKey * pKey,GtkWidget * pQuitEntry)838 static void _cairo_dock_set_sensitive_quit_menu (G_GNUC_UNUSED GtkWidget *pMenuItem, GdkEventKey *pKey, GtkWidget *pQuitEntry)
839 {
840 	// pMenuItem not used because we want to only modify one entry
841 	if (pKey->type == GDK_KEY_PRESS &&
842 		(pKey->keyval == GDK_KEY_Shift_L ||
843 		pKey->keyval == GDK_KEY_Shift_R)) // pressed
844 		gtk_widget_set_sensitive (pQuitEntry, TRUE); // unlocked
845 	else if (pKey->state & GDK_SHIFT_MASK) // released
846 		gtk_widget_set_sensitive (pQuitEntry, FALSE); // locked)
847 }
848 
_cairo_dock_launch_new(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)849 static void _cairo_dock_launch_new (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
850 {
851 	Icon *icon = data[0];
852 	CairoDock *pDock = data[1];
853 	if (icon->cCommand != NULL)
854 	{
855 		gldi_object_notify (CAIRO_CONTAINER (pDock), NOTIFICATION_CLICK_ICON, icon, pDock, GDK_SHIFT_MASK);  // on emule un shift+clic gauche .
856 	}
857 }
858 
859 
860   /////////////////////////////////////////
861  /// BUILD CONTAINER MENU NOTIFICATION ///
862 /////////////////////////////////////////
863 
_show_image_preview(GtkFileChooser * pFileChooser,GtkImage * pPreviewImage)864 static void _show_image_preview (GtkFileChooser *pFileChooser, GtkImage *pPreviewImage)
865 {
866 	gchar *cFileName = gtk_file_chooser_get_preview_filename (pFileChooser);
867 	if (cFileName == NULL)
868 		return ;
869 	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (cFileName, 64, 64, NULL);
870 	g_free (cFileName);
871 	if (pixbuf != NULL)
872 	{
873 		gtk_image_set_from_pixbuf (pPreviewImage, pixbuf);
874 		g_object_unref (pixbuf);
875 		gtk_file_chooser_set_preview_widget_active (pFileChooser, TRUE);
876 	}
877 	else
878 		gtk_file_chooser_set_preview_widget_active (pFileChooser, FALSE);
879 }
_cairo_dock_set_custom_appli_icon(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)880 static void _cairo_dock_set_custom_appli_icon (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
881 {
882 	Icon *icon = data[0];
883 	CairoDock *pDock = data[1];
884 	if (! CAIRO_DOCK_IS_APPLI (icon))
885 		return;
886 
887 	GtkWidget* pFileChooserDialog = gtk_file_chooser_dialog_new (
888 		_("Pick up an image"),
889 		GTK_WINDOW (pDock->container.pWidget),
890 		GTK_FILE_CHOOSER_ACTION_OPEN,
891 		_("Ok"),
892 		GTK_RESPONSE_OK,
893 		_("Cancel"),
894 		GTK_RESPONSE_CANCEL,
895 		NULL);
896 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (pFileChooserDialog), "/usr/local/share/icons");  // we could also use 'xdg-user-dir PICTURES' or /usr/local/share/icons or ~/.icons, but actually we have no idea where the user will want to pick the image, so let's not try to be smart.
897 	gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (pFileChooserDialog), FALSE);
898 
899 	GtkWidget *pPreviewImage = gtk_image_new ();
900 	gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (pFileChooserDialog), pPreviewImage);
901 	g_signal_connect (GTK_FILE_CHOOSER (pFileChooserDialog), "update-preview", G_CALLBACK (_show_image_preview), pPreviewImage);
902 
903 	// a filter
904 	GtkFileFilter *pFilter = gtk_file_filter_new ();
905 	gtk_file_filter_set_name (pFilter, _("Image"));
906 	gtk_file_filter_add_pixbuf_formats (pFilter);
907 	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (pFileChooserDialog), pFilter);
908 
909 	gtk_widget_show (pFileChooserDialog);
910 	int answer = gtk_dialog_run (GTK_DIALOG (pFileChooserDialog));
911 	if (answer == GTK_RESPONSE_OK)
912 	{
913 		if (myTaskbarParam.cOverwriteException != NULL && icon->cClass != NULL)  // si cette classe etait definie pour ne pas ecraser l'icone X, on le change, sinon l'action utilisateur n'aura aucun impact, ce sera troublant.
914 		{
915 			gchar **pExceptions = g_strsplit (myTaskbarParam.cOverwriteException, ";", -1);
916 
917 			int i, j = -1;
918 			for (i = 0; pExceptions[i] != NULL; i ++)
919 			{
920 				if (j == -1 && strcmp (pExceptions[i], icon->cClass) == 0)
921 				{
922 					g_free (pExceptions[i]);
923 					pExceptions[i] = NULL;
924 					j = i;
925 				}
926 			}  // apres la boucle, i = nbre d'elements, j = l'element qui a ete enleve.
927 			if (j != -1)  // un element a ete enleve.
928 			{
929 				cd_warning ("The class '%s' was explicitely set up to use the X icon, we'll change this behavior automatically.", icon->cClass);
930 				if (j < i - 1)  // ce n'est pas le dernier
931 				{
932 					pExceptions[j] = pExceptions[i-1];
933 					pExceptions[i-1] = NULL;
934 				}
935 
936 				myTaskbarParam.cOverwriteException = g_strjoinv (";", pExceptions);
937 				cairo_dock_set_overwrite_exceptions (myTaskbarParam.cOverwriteException);
938 
939 				cairo_dock_update_conf_file (g_cConfFile,
940 					G_TYPE_STRING, "TaskBar", "overwrite exception", myTaskbarParam.cOverwriteException,
941 					G_TYPE_INVALID);
942 			}
943 			g_strfreev (pExceptions);
944 		}
945 
946 		gchar *cFilePath = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pFileChooserDialog));
947 		cairo_dock_set_custom_icon_on_appli (cFilePath, icon, CAIRO_CONTAINER (pDock));
948 		g_free (cFilePath);
949 	}
950 	gtk_widget_destroy (pFileChooserDialog);
951 }
_cairo_dock_remove_custom_appli_icon(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)952 static void _cairo_dock_remove_custom_appli_icon (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
953 {
954 	Icon *icon = data[0];
955 	CairoDock *pDock = data[1];
956 	if (! CAIRO_DOCK_IS_APPLI (icon))
957 		return;
958 
959 	const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
960 	if (cClassIcon == NULL)
961 		cClassIcon = icon->cClass;
962 
963 	gchar *cCustomIcon = g_strdup_printf ("%s/%s.png", g_cCurrentIconsPath, cClassIcon);
964 	if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
965 	{
966 		g_free (cCustomIcon);
967 		cCustomIcon = g_strdup_printf ("%s/%s.svg", g_cCurrentIconsPath, cClassIcon);
968 		if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
969 		{
970 			g_free (cCustomIcon);
971 			cCustomIcon = NULL;
972 		}
973 	}
974 	if (cCustomIcon != NULL)
975 	{
976 		g_remove (cCustomIcon);
977 		cairo_dock_reload_icon_image (icon, CAIRO_CONTAINER (pDock));
978 		cairo_dock_redraw_icon (icon);
979 	}
980 }
981 
cairo_dock_notification_build_container_menu(G_GNUC_UNUSED gpointer * pUserData,Icon * icon,GldiContainer * pContainer,GtkWidget * menu,G_GNUC_UNUSED gboolean * bDiscardMenu)982 gboolean cairo_dock_notification_build_container_menu (G_GNUC_UNUSED gpointer *pUserData, Icon *icon, GldiContainer *pContainer, GtkWidget *menu, G_GNUC_UNUSED gboolean *bDiscardMenu)
983 {
984 	static gpointer data[3];
985 
986 	if (CAIRO_DOCK_IS_DESKLET (pContainer) && icon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // not on the icons of a desklet, except the applet icon (on a desklet, it's easy to click out of any icon).
987 		return GLDI_NOTIFICATION_LET_PASS;
988 
989 	if (CAIRO_DOCK_IS_DOCK (pContainer) && CAIRO_DOCK (pContainer)->iRefCount > 0)  // not on the sub-docks, except user sub-docks.
990 	{
991 		Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (CAIRO_DOCK (pContainer), NULL);
992 		if (pPointingIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pPointingIcon))
993 			return GLDI_NOTIFICATION_LET_PASS;
994 	}
995 
996 	GtkWidget *pMenuItem;
997 
998 	//\_________________________ First item is the Cairo-Dock sub-menu.
999 	GtkWidget *pSubMenu = cairo_dock_create_sub_menu ("Cairo-Dock", menu, CAIRO_DOCK_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON);
1000 
1001 	// theme settings
1002 	if (! cairo_dock_is_locked ())
1003 	{
1004 		// global settings
1005 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Configure"),
1006 			GLDI_ICON_NAME_PREFERENCES,
1007 			G_CALLBACK (_cairo_dock_edit_and_reload_conf),
1008 			pSubMenu,
1009 			NULL);
1010 		gtk_widget_set_tooltip_text (pMenuItem, _("Configure behaviour, appearance, and applets."));
1011 
1012 		// root dock settings
1013 		if (CAIRO_DOCK_IS_DOCK (pContainer) && ! CAIRO_DOCK (pContainer)->bIsMainDock && CAIRO_DOCK (pContainer)->iRefCount == 0)
1014 		{
1015 			pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Configure this dock"),
1016 				GLDI_ICON_NAME_EXECUTE,
1017 				G_CALLBACK (_cairo_dock_configure_root_dock),
1018 				pSubMenu,
1019 				CAIRO_DOCK (pContainer));
1020 			gtk_widget_set_tooltip_text (pMenuItem, _("Customize the position, visibility and appearance of this main dock."));
1021 
1022 			cairo_dock_add_in_menu_with_stock_and_data (_("Delete this dock"),
1023 				GLDI_ICON_NAME_DELETE,
1024 				G_CALLBACK (_cairo_dock_delete_dock),
1025 				pSubMenu,
1026 				CAIRO_DOCK (pContainer));
1027 		}
1028 
1029 		// themes
1030 		if (cairo_dock_can_manage_themes ())
1031 		{
1032 			pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Manage themes"),
1033 				CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-appearance.svg",
1034 				G_CALLBACK (_cairo_dock_initiate_theme_management),
1035 				pSubMenu,
1036 				NULL);
1037 			gtk_widget_set_tooltip_text (pMenuItem, _("Choose from amongst many themes on the server or save your current theme."));
1038 		}
1039 
1040 		// add new item
1041 		if (CAIRO_DOCK_IS_DOCK (pContainer))
1042 		{
1043 			_add_add_entry (pSubMenu, data);
1044 		}
1045 
1046 		gldi_menu_add_separator (pSubMenu);
1047 
1048 		// lock icons position
1049 		pMenuItem = gtk_check_menu_item_new_with_label (_("Lock icons position"));
1050 		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (pMenuItem), myDocksParam.bLockIcons);
1051 		gtk_menu_shell_append  (GTK_MENU_SHELL (pSubMenu), pMenuItem);
1052 		g_signal_connect (G_OBJECT (pMenuItem), "toggled", G_CALLBACK (_cairo_dock_lock_icons), NULL);
1053 		gtk_widget_set_tooltip_text (pMenuItem, _("This will (un)lock the position of the icons."));
1054 	}
1055 
1056 	// quick-hide
1057 	if (CAIRO_DOCK_IS_DOCK (pContainer) && ! CAIRO_DOCK (pContainer)->bAutoHide)
1058 	{
1059 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Quick-Hide"),
1060 			GLDI_ICON_NAME_GOTO_BOTTOM,
1061 			G_CALLBACK (_cairo_dock_quick_hide),
1062 			pSubMenu,
1063 			CAIRO_DOCK (pContainer));
1064 		gtk_widget_set_tooltip_text (pMenuItem, _("This will hide the dock until you hover over it with the mouse."));
1065 	}
1066 
1067 	const gchar *cDesktopSession = g_getenv ("DESKTOP_SESSION");
1068 	gboolean bIsCairoDockSession = cDesktopSession && g_str_has_prefix (cDesktopSession, "cairo-dock");
1069 	if (! g_bLocked)
1070 	{
1071 		// auto-start
1072 		gchar *cCairoAutoStartDirPath = g_strdup_printf ("%s/.config/autostart", g_getenv ("HOME"));
1073 		gchar *cCairoAutoStartEntryPath = g_strdup_printf ("%s/cairo-dock.desktop", cCairoAutoStartDirPath);
1074 		gchar *cCairoAutoStartEntryPath2 = g_strdup_printf ("%s/cairo-dock-cairo.desktop", cCairoAutoStartDirPath);
1075 		if (! bIsCairoDockSession && ! g_file_test (cCairoAutoStartEntryPath, G_FILE_TEST_EXISTS) && ! g_file_test (cCairoAutoStartEntryPath2, G_FILE_TEST_EXISTS))
1076 		{
1077 			cairo_dock_add_in_menu_with_stock_and_data (_("Launch Cairo-Dock on startup"),
1078 				GLDI_ICON_NAME_ADD,
1079 				G_CALLBACK (_cairo_dock_add_autostart),
1080 				pSubMenu,
1081 				NULL);
1082 		}
1083 		g_free (cCairoAutoStartEntryPath);
1084 		g_free (cCairoAutoStartEntryPath2);
1085 		g_free (cCairoAutoStartDirPath);
1086 
1087 		// third-party applets (are here to give them more visibility).
1088 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Get more applets!"),
1089 			GLDI_ICON_NAME_ADD,
1090 			G_CALLBACK (_cairo_dock_show_third_party_applets),
1091 			pSubMenu,
1092 			NULL);
1093 		gtk_widget_set_tooltip_text (pMenuItem, _("Third-party applets provide integration with many programs, like Pidgin"));
1094 
1095 		// Help (we don't present the help if locked, because it would open the configuration window).
1096 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Help"),
1097 			GLDI_ICON_NAME_HELP,
1098 			G_CALLBACK (_cairo_dock_present_help),
1099 			pSubMenu,
1100 			NULL);
1101 		gtk_widget_set_tooltip_text (pMenuItem, _("There are no problems, only solutions (and a lot of useful hints!)"));
1102 	}
1103 
1104 	// About
1105 	cairo_dock_add_in_menu_with_stock_and_data (_("About"),
1106 		GLDI_ICON_NAME_ABOUT,
1107 		G_CALLBACK (_cairo_dock_about),
1108 		pSubMenu,
1109 		pContainer);
1110 
1111 	// quit
1112 	if (! g_bLocked)
1113 	{
1114 		pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (_("Quit"),
1115 			GLDI_ICON_NAME_QUIT,
1116 			G_CALLBACK (_cairo_dock_quit),
1117 			pSubMenu,
1118 			pContainer);
1119 		// if we're using a Cairo-Dock session and we quit the dock we have... nothing to relaunch it!
1120 		if (bIsCairoDockSession)
1121 		{
1122 			gtk_widget_set_sensitive (pMenuItem, FALSE); // locked
1123 			gtk_widget_set_tooltip_text (pMenuItem, _("You're using a Cairo-Dock Session!\nIt's not advised to quit the dock but you can press Shift to unlock this menu entry."));
1124 			// signal to unlock the entry (signal monitored only in the submenu)
1125 			g_signal_connect (pSubMenu, "key-press-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
1126 			g_signal_connect (pSubMenu, "key-release-event", G_CALLBACK (_cairo_dock_set_sensitive_quit_menu), pMenuItem);
1127 		}
1128 	}
1129 
1130 	//\_________________________ Second item is the Icon sub-menu.
1131 	Icon *pIcon = icon;
1132 	if (pIcon == NULL && CAIRO_DOCK_IS_DESKLET (pContainer))  // on a desklet, the main applet icon may not be drawn; therefore we add the applet sub-menu if we clicked outside of an icon.
1133 	{
1134 		pIcon = CAIRO_DESKLET (pContainer)->pIcon;
1135 	}
1136 	data[0] = pIcon;
1137 	data[1] = pContainer;
1138 	data[2] = menu;
1139 
1140 	if (pIcon != NULL && ! CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (pIcon))
1141 	{
1142 		GtkWidget *pItemSubMenu = _add_item_sub_menu (pIcon, menu);
1143 
1144 		if (cairo_dock_is_locked ())
1145 		{
1146 			gboolean bSensitive = FALSE;
1147 			if (CAIRO_DOCK_IS_APPLI (icon) && icon->cCommand != NULL)
1148 			{
1149 				_add_entry_in_menu (_("Launch a new (Shift+clic)"), GLDI_ICON_NAME_ADD, _cairo_dock_launch_new, pItemSubMenu);
1150 				bSensitive = TRUE;
1151 			}
1152 			if (CAIRO_DOCK_IS_APPLET (pIcon))
1153 			{
1154 				cairo_dock_add_in_menu_with_stock_and_data (_("Applet's handbook"), GLDI_ICON_NAME_ABOUT, G_CALLBACK (cairo_dock_pop_up_about_applet), pItemSubMenu, pIcon->pModuleInstance);
1155 				bSensitive = TRUE;
1156 			}
1157 			gtk_widget_set_sensitive (pItemSubMenu, bSensitive);
1158 		}
1159 		else
1160 		{
1161 			if (CAIRO_DOCK_IS_APPLI (icon) && icon->cCommand != NULL)
1162 				_add_entry_in_menu (_("Launch a new (Shift+clic)"), GLDI_ICON_NAME_ADD, _cairo_dock_launch_new, pItemSubMenu);
1163 
1164 			if ((CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (pIcon)
1165 				 || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pIcon)
1166 				 || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
1167 				&& icon->cDesktopFileName != NULL)  // user icon
1168 			{
1169 				_add_entry_in_menu (_("Edit"), GLDI_ICON_NAME_EDIT, _cairo_dock_modify_launcher, pItemSubMenu);
1170 
1171 				pMenuItem = _add_entry_in_menu (_("Remove"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_launcher, pItemSubMenu);
1172 				gtk_widget_set_tooltip_text (pMenuItem, _("You can remove a launcher by dragging it out of the dock with the mouse ."));
1173 
1174 				_cairo_dock_add_docks_sub_menu (pItemSubMenu, pIcon);
1175 			}
1176 			else if (CAIRO_DOCK_ICON_TYPE_IS_APPLI (pIcon)
1177 				|| CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (pIcon))  // appli with no launcher
1178 			{
1179 				if (! cairo_dock_class_is_inhibited (pIcon->cClass))  // if the class doesn't already have an inhibator somewhere.
1180 				{
1181 					_add_entry_in_menu (_("Make it a launcher"), GLDI_ICON_NAME_NEW, _cairo_dock_make_launcher_from_appli, pItemSubMenu);
1182 
1183 					if (!myDocksParam.bLockAll && CAIRO_DOCK_ICON_TYPE_IS_APPLI (icon))
1184 					{
1185 						if (myTaskbarParam.bOverWriteXIcons)
1186 						{
1187 							const gchar *cClassIcon = cairo_dock_get_class_icon (icon->cClass);
1188 							if (cClassIcon == NULL)
1189 								cClassIcon = icon->cClass;
1190 
1191 							gchar *cCustomIcon = g_strdup_printf ("%s/%s.png", g_cCurrentIconsPath, cClassIcon);
1192 							if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
1193 							{
1194 								g_free (cCustomIcon);
1195 								cCustomIcon = g_strdup_printf ("%s/%s.svg", g_cCurrentIconsPath, cClassIcon);
1196 								if (!g_file_test (cCustomIcon, G_FILE_TEST_EXISTS))
1197 								{
1198 									g_free (cCustomIcon);
1199 									cCustomIcon = NULL;
1200 								}
1201 							}
1202 							if (cCustomIcon != NULL)
1203 							{
1204 								_add_entry_in_menu (_("Remove custom icon"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_custom_appli_icon, pItemSubMenu);
1205 							}
1206 						}
1207 
1208 						_add_entry_in_menu (_("Set a custom icon"), GLDI_ICON_NAME_SELECT_COLOR, _cairo_dock_set_custom_appli_icon, pItemSubMenu);
1209 					}
1210 				}
1211 			}
1212 			else if (CAIRO_DOCK_IS_APPLET (pIcon))  // applet (icon or desklet) (the sub-icons have been filtered before and won't have this menu).
1213 			{
1214 				_add_entry_in_menu (_("Edit"), GLDI_ICON_NAME_EDIT, _cairo_dock_initiate_config_module, pItemSubMenu);
1215 
1216 				if (CAIRO_DOCK_IS_DETACHABLE_APPLET (pIcon))
1217 				{
1218 					_add_entry_in_menu (CAIRO_DOCK_IS_DOCK (pContainer) ? _("Detach") : _("Return to the dock"), CAIRO_DOCK_IS_DOCK (pContainer) ? GLDI_ICON_NAME_GOTO_TOP : GLDI_ICON_NAME_GOTO_BOTTOM, _cairo_dock_detach_module, pItemSubMenu);
1219 				}
1220 
1221 				_add_entry_in_menu (_("Remove"), GLDI_ICON_NAME_REMOVE, _cairo_dock_remove_module_instance, pItemSubMenu);
1222 
1223 				if (pIcon->pModuleInstance->pModule->pVisitCard->bMultiInstance)
1224 				{
1225 					_add_entry_in_menu (_("Duplicate"), GLDI_ICON_NAME_ADD, _cairo_dock_add_module_instance, pItemSubMenu);  // Launch another instance of this applet
1226 				}
1227 
1228 				if (CAIRO_DOCK_IS_DOCK (pContainer) && cairo_dock_get_icon_container(pIcon) != NULL)  // sinon bien sur ca n'est pas la peine de presenter l'option (Cairo-Penguin par exemple)
1229 				{
1230 					_cairo_dock_add_docks_sub_menu (pItemSubMenu, pIcon);
1231 				}
1232 
1233 				gldi_menu_add_separator (pItemSubMenu);
1234 
1235 				cairo_dock_add_in_menu_with_stock_and_data (_("Applet's handbook"), GLDI_ICON_NAME_ABOUT, G_CALLBACK (cairo_dock_pop_up_about_applet), pItemSubMenu, pIcon->pModuleInstance);
1236 			}
1237 		}
1238 	}
1239 
1240 	return GLDI_NOTIFICATION_LET_PASS;
1241 }
1242 
1243 
1244 
1245   /////////////////////////////////////////////////////////////////
1246  /////////// LES OPERATIONS SUR LES APPLIS ///////////////////////
1247 /////////////////////////////////////////////////////////////////
1248 
_cairo_dock_close_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1249 static void _cairo_dock_close_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1250 {
1251 	Icon *icon = data[0];
1252 	// CairoDock *pDock = data[1];
1253 	if (CAIRO_DOCK_IS_APPLI (icon))
1254 		gldi_window_close (icon->pAppli);
1255 }
_cairo_dock_kill_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1256 static void _cairo_dock_kill_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1257 {
1258 	Icon *icon = data[0];
1259 	// CairoDock *pDock = data[1];
1260 	if (CAIRO_DOCK_IS_APPLI (icon))
1261 		gldi_window_kill (icon->pAppli);
1262 }
_cairo_dock_minimize_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1263 static void _cairo_dock_minimize_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1264 {
1265 	Icon *icon = data[0];
1266 	// CairoDock *pDock = data[1];
1267 	if (CAIRO_DOCK_IS_APPLI (icon))
1268 	{
1269 		gldi_window_minimize (icon->pAppli);
1270 	}
1271 }
_cairo_dock_lower_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1272 static void _cairo_dock_lower_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1273 {
1274 	Icon *icon = data[0];
1275 	// CairoDock *pDock = data[1];
1276 	if (CAIRO_DOCK_IS_APPLI (icon))
1277 	{
1278 		gldi_window_lower (icon->pAppli);
1279 	}
1280 }
1281 
_cairo_dock_show_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1282 static void _cairo_dock_show_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1283 {
1284 	Icon *icon = data[0];
1285 	// CairoDock *pDock = data[1];
1286 	if (CAIRO_DOCK_IS_APPLI (icon))
1287 	{
1288 		gldi_window_show (icon->pAppli);
1289 	}
1290 }
1291 
_cairo_dock_maximize_appli(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1292 static void _cairo_dock_maximize_appli (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1293 {
1294 	Icon *icon = data[0];
1295 	// CairoDock *pDock = data[1];
1296 	if (CAIRO_DOCK_IS_APPLI (icon))
1297 	{
1298 		gldi_window_maximize (icon->pAppli, ! icon->pAppli->bIsMaximized);
1299 	}
1300 }
1301 
_cairo_dock_set_appli_fullscreen(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1302 static void _cairo_dock_set_appli_fullscreen (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1303 {
1304 	Icon *icon = data[0];
1305 	// CairoDock *pDock = data[1];
1306 	if (CAIRO_DOCK_IS_APPLI (icon))
1307 	{
1308 		gldi_window_set_fullscreen (icon->pAppli, ! icon->pAppli->bIsFullScreen);
1309 	}
1310 }
1311 
_cairo_dock_move_appli_to_current_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1312 static void _cairo_dock_move_appli_to_current_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1313 {
1314 	Icon *icon = data[0];
1315 	// CairoDock *pDock = data[1];
1316 	if (CAIRO_DOCK_IS_APPLI (icon))
1317 	{
1318 		gldi_window_move_to_current_desktop (icon->pAppli);
1319 		if (!icon->pAppli->bIsHidden)
1320 			gldi_window_show (icon->pAppli);
1321 	}
1322 }
1323 
_cairo_dock_move_appli_to_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * user_data)1324 static void _cairo_dock_move_appli_to_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *user_data)
1325 {
1326 	gpointer *data = user_data[0];
1327 	Icon *icon = data[0];
1328 	// CairoDock *pDock = data[1];
1329 	int iDesktopNumber = GPOINTER_TO_INT (user_data[1]);
1330 	int iViewPortNumberY = GPOINTER_TO_INT (user_data[2]);
1331 	int iViewPortNumberX = GPOINTER_TO_INT (user_data[3]);
1332 	cd_message ("%s (%d;%d;%d)", __func__, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1333 	if (CAIRO_DOCK_IS_APPLI (icon))
1334 	{
1335 		gldi_window_move_to_desktop (icon->pAppli, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1336 	}
1337 }
1338 
_cairo_dock_change_window_above(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1339 static void _cairo_dock_change_window_above (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1340 {
1341 	Icon *icon = data[0];
1342 	// CairoDock *pDock = data[1];
1343 	if (CAIRO_DOCK_IS_APPLI (icon))
1344 	{
1345 		gboolean bIsAbove=FALSE, bIsBelow=FALSE;
1346 		gldi_window_is_above_or_below (icon->pAppli, &bIsAbove, &bIsBelow);
1347 		gldi_window_set_above (icon->pAppli, ! bIsAbove);
1348 	}
1349 }
1350 
_cairo_dock_change_window_sticky(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1351 static void _cairo_dock_change_window_sticky (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1352 {
1353 	Icon *icon = data[0];
1354 	// CairoDock *pDock = data[1];
1355 	if (CAIRO_DOCK_IS_APPLI (icon))
1356 	{
1357 		gboolean bIsSticky = gldi_window_is_sticky (icon->pAppli);
1358 		gldi_window_set_sticky (icon->pAppli, ! bIsSticky);
1359 	}
1360 }
1361 
_cairo_dock_move_class_to_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * user_data)1362 static void _cairo_dock_move_class_to_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *user_data)
1363 {
1364 	gpointer *data = user_data[0];
1365 	Icon *icon = data[0];
1366 	// CairoDock *pDock = data[1];
1367 	g_return_if_fail (icon->pSubDock != NULL);
1368 	int iDesktopNumber = GPOINTER_TO_INT (user_data[1]);
1369 	int iViewPortNumberY = GPOINTER_TO_INT (user_data[2]);
1370 	int iViewPortNumberX = GPOINTER_TO_INT (user_data[3]);
1371 	cd_message ("%s (%d;%d;%d)", __func__, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1372 
1373 	Icon *pIcon;
1374 	GList *ic;
1375 	for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1376 	{
1377 		pIcon = ic->data;
1378 		if (CAIRO_DOCK_IS_APPLI (pIcon))
1379 		{
1380 			gldi_window_move_to_desktop (pIcon->pAppli, iDesktopNumber, iViewPortNumberX, iViewPortNumberY);
1381 		}
1382 	}
1383 }
1384 
_add_desktops_entry(GtkWidget * pMenu,gboolean bAll,gpointer * data)1385 static void _add_desktops_entry (GtkWidget *pMenu, gboolean bAll, gpointer *data)
1386 {
1387 	static gpointer *s_pDesktopData = NULL;
1388 	GtkWidget *pMenuItem;
1389 
1390 	if (g_desktopGeometry.iNbDesktops > 1 || g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1)
1391 	{
1392 		// add separator
1393 		pMenuItem = gtk_separator_menu_item_new ();
1394 		gtk_menu_shell_append (GTK_MENU_SHELL (pMenu), pMenuItem);
1395 
1396 		int i, j, k, iDesktopCode;
1397 		const gchar *cLabel;
1398 		if (g_desktopGeometry.iNbDesktops > 1 && (g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1))
1399 			cLabel = bAll ? _("Move all to desktop %d - face %d") : _("Move to desktop %d - face %d");
1400 		else if (g_desktopGeometry.iNbDesktops > 1)
1401 			cLabel = bAll ? _("Move all to desktop %d") : _("Move to desktop %d");
1402 		else
1403 			cLabel = bAll ? _("Move all to face %d") : _("Move to face %d");
1404 		GString *sDesktop = g_string_new ("");
1405 		g_free (s_pDesktopData);
1406 		s_pDesktopData = g_new0 (gpointer, 4 * g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY);
1407 		gpointer *user_data;
1408 		Icon *icon = data[0];
1409 		GldiWindowActor *pAppli = icon->pAppli;
1410 
1411 		for (i = 0; i < g_desktopGeometry.iNbDesktops; i ++)  // on range par bureau.
1412 		{
1413 			for (j = 0; j < g_desktopGeometry.iNbViewportY; j ++)  // puis par rangee.
1414 			{
1415 				for (k = 0; k < g_desktopGeometry.iNbViewportX; k ++)
1416 				{
1417 					if (g_desktopGeometry.iNbDesktops > 1 && (g_desktopGeometry.iNbViewportX > 1 || g_desktopGeometry.iNbViewportY > 1))
1418 						g_string_printf (sDesktop, cLabel, i+1, j*g_desktopGeometry.iNbViewportX+k+1);
1419 					else if (g_desktopGeometry.iNbDesktops > 1)
1420 						g_string_printf (sDesktop, cLabel, i+1);
1421 					else
1422 						g_string_printf (sDesktop, cLabel, j*g_desktopGeometry.iNbViewportX+k+1);
1423 					iDesktopCode = i * g_desktopGeometry.iNbViewportY * g_desktopGeometry.iNbViewportX + j * g_desktopGeometry.iNbViewportX + k;
1424 					user_data = &s_pDesktopData[4*iDesktopCode];
1425 					user_data[0] = data;
1426 					user_data[1] = GINT_TO_POINTER (i);
1427 					user_data[2] = GINT_TO_POINTER (j);
1428 					user_data[3] = GINT_TO_POINTER (k);
1429 
1430 					pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (sDesktop->str, NULL, G_CALLBACK (bAll ? _cairo_dock_move_class_to_desktop : _cairo_dock_move_appli_to_desktop), pMenu, user_data);
1431 					if (pAppli && gldi_window_is_on_desktop (pAppli, i, k, j))
1432 						gtk_widget_set_sensitive (pMenuItem, FALSE);
1433 				}
1434 			}
1435 		}
1436 		g_string_free (sDesktop, TRUE);
1437 	}
1438 }
1439 
1440 
1441   ///////////////////////////////////////////////////////////////
1442  ///////////// LES OPERATIONS SUR LES CLASSES //////////////////
1443 ///////////////////////////////////////////////////////////////
1444 
_cairo_dock_launch_class_action(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gchar * cCommand)1445 static void _cairo_dock_launch_class_action (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gchar *cCommand)
1446 {
1447 	cairo_dock_launch_command (cCommand);
1448 }
1449 
_cairo_dock_show_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1450 static void _cairo_dock_show_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1451 {
1452 	Icon *icon = data[0];
1453 	// CairoDock *pDock = data[1];
1454 	g_return_if_fail (icon->pSubDock != NULL);
1455 
1456 	Icon *pIcon;
1457 	GList *ic;
1458 	for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1459 	{
1460 		pIcon = ic->data;
1461 		if (CAIRO_DOCK_IS_APPLI (pIcon))
1462 		{
1463 			gldi_window_show (pIcon->pAppli);
1464 		}
1465 	}
1466 }
1467 
_cairo_dock_minimize_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1468 static void _cairo_dock_minimize_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1469 {
1470 	Icon *icon = data[0];
1471 	// CairoDock *pDock = data[1];
1472 	g_return_if_fail (icon->pSubDock != NULL);
1473 
1474 	Icon *pIcon;
1475 	GList *ic;
1476 	for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1477 	{
1478 		pIcon = ic->data;
1479 		if (CAIRO_DOCK_IS_APPLI (pIcon))
1480 		{
1481 			gldi_window_minimize (pIcon->pAppli);
1482 		}
1483 	}
1484 }
1485 
_cairo_dock_close_class(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1486 static void _cairo_dock_close_class (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1487 {
1488 	Icon *icon = data[0];
1489 	// CairoDock *pDock = data[1];
1490 	g_return_if_fail (icon->pSubDock != NULL);
1491 
1492 	Icon *pIcon;
1493 	GList *ic;
1494 	for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1495 	{
1496 		pIcon = ic->data;
1497 		if (CAIRO_DOCK_IS_APPLI (pIcon))
1498 		{
1499 			gldi_window_close (pIcon->pAppli);
1500 		}
1501 	}
1502 }
1503 
_cairo_dock_move_class_to_current_desktop(G_GNUC_UNUSED GtkMenuItem * pMenuItem,gpointer * data)1504 static void _cairo_dock_move_class_to_current_desktop (G_GNUC_UNUSED GtkMenuItem *pMenuItem, gpointer *data)
1505 {
1506 	Icon *icon = data[0];
1507 	// CairoDock *pDock = data[1];
1508 	g_return_if_fail (icon->pSubDock != NULL);
1509 
1510 	Icon *pIcon;
1511 	GList *ic;
1512 	for (ic = icon->pSubDock->icons; ic != NULL; ic = ic->next)
1513 	{
1514 		pIcon = ic->data;
1515 		if (CAIRO_DOCK_IS_APPLI (pIcon))
1516 		{
1517 			gldi_window_move_to_current_desktop (pIcon->pAppli);
1518 		}
1519 	}
1520 }
1521 
1522   ///////////////////////////////////////////////////////////////////
1523  ///////////////// LES OPERATIONS SUR LES DESKLETS /////////////////
1524 ///////////////////////////////////////////////////////////////////
1525 
_cairo_dock_set_desklet_accessibility(CairoDesklet * pDesklet,CairoDeskletVisibility iVisibility)1526 static inline void _cairo_dock_set_desklet_accessibility (CairoDesklet *pDesklet, CairoDeskletVisibility iVisibility)
1527 {
1528 	gldi_desklet_set_accessibility (pDesklet, iVisibility, TRUE);  // TRUE <=> save state in conf.
1529 	cairo_dock_gui_update_desklet_visibility (pDesklet);
1530 }
_cairo_dock_keep_below(GtkCheckMenuItem * pMenuItem,gpointer * data)1531 static void _cairo_dock_keep_below (GtkCheckMenuItem *pMenuItem, gpointer *data)
1532 {
1533 	CairoDesklet *pDesklet = data[1];
1534 	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1535 		_cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_KEEP_BELOW);
1536 }
1537 
_cairo_dock_keep_normal(GtkCheckMenuItem * pMenuItem,gpointer * data)1538 static void _cairo_dock_keep_normal (GtkCheckMenuItem *pMenuItem, gpointer *data)
1539 {
1540 	CairoDesklet *pDesklet = data[1];
1541 	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1542 		_cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_NORMAL);
1543 }
1544 
_cairo_dock_keep_above(GtkCheckMenuItem * pMenuItem,gpointer * data)1545 static void _cairo_dock_keep_above (GtkCheckMenuItem *pMenuItem, gpointer *data)
1546 {
1547 	CairoDesklet *pDesklet = data[1];
1548 	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1549 		_cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_KEEP_ABOVE);
1550 }
1551 
_cairo_dock_keep_on_widget_layer(GtkMenuItem * pMenuItem,gpointer * data)1552 static void _cairo_dock_keep_on_widget_layer (GtkMenuItem *pMenuItem, gpointer *data)
1553 {
1554 	CairoDesklet *pDesklet = data[1];
1555 	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1556 		_cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_ON_WIDGET_LAYER);
1557 }
1558 
_cairo_dock_keep_space(GtkCheckMenuItem * pMenuItem,gpointer * data)1559 static void _cairo_dock_keep_space (GtkCheckMenuItem *pMenuItem, gpointer *data)
1560 {
1561 	CairoDesklet *pDesklet = data[1];
1562 	if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem)))
1563 		_cairo_dock_set_desklet_accessibility (pDesklet, CAIRO_DESKLET_RESERVE_SPACE);
1564 }
1565 
_cairo_dock_set_on_all_desktop(GtkCheckMenuItem * pMenuItem,gpointer * data)1566 static void _cairo_dock_set_on_all_desktop (GtkCheckMenuItem *pMenuItem, gpointer *data)
1567 {
1568 	CairoDesklet *pDesklet = data[1];
1569 	gboolean bSticky = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem));
1570 	gldi_desklet_set_sticky (pDesklet, bSticky);
1571 	cairo_dock_gui_update_desklet_visibility (pDesklet);
1572 }
1573 
_cairo_dock_lock_position(GtkMenuItem * pMenuItem,gpointer * data)1574 static void _cairo_dock_lock_position (GtkMenuItem *pMenuItem, gpointer *data)
1575 {
1576 	CairoDesklet *pDesklet = data[1];
1577 	gboolean bLocked = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (pMenuItem));
1578 	gldi_desklet_lock_position (pDesklet, bLocked);
1579 	cairo_dock_gui_update_desklet_visibility (pDesklet);
1580 }
1581 
1582 
1583   ////////////////////////////////////
1584  /// BUILD ICON MENU NOTIFICATION ///
1585 ////////////////////////////////////
1586 
1587 // stuff for the buttons inside a menu-item
_on_press_menu_item(GtkWidget * pWidget,GdkEventButton * pEvent,G_GNUC_UNUSED gpointer data)1588 static gboolean _on_press_menu_item (GtkWidget* pWidget, GdkEventButton *pEvent, G_GNUC_UNUSED gpointer data)
1589 {
1590 	GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1591 	GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1592 	int x = pEvent->x, y = pEvent->y;  // position of the mouse relatively to the menu-item
1593 	int xb, yb;  // position of the top-left corner of the button relatively to the menu-item
1594 	GtkWidget* pButton;
1595 	GList* c;
1596 	for (c = children->next; c != NULL; c = c->next)
1597 	{
1598 		pButton = GTK_WIDGET(c->data);
1599 		GtkAllocation alloc;
1600 		gtk_widget_get_allocation (pButton, &alloc);
1601 		gtk_widget_translate_coordinates (pButton, pWidget,
1602 			0, 0, &xb, &yb);
1603 		if (x >= xb && x < (xb + alloc.width)
1604 		&& y >= yb && y < (yb + alloc.height))
1605 		{
1606 			gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_ACTIVE, TRUE);
1607 			gtk_widget_set_state_flags (
1608 				gtk_bin_get_child(GTK_BIN(pButton)),
1609 				GTK_STATE_FLAG_ACTIVE, TRUE);
1610 			gtk_button_clicked (GTK_BUTTON (pButton));
1611 		}
1612 		else
1613 		{
1614 			gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1615 			gtk_widget_set_state_flags (
1616 				gtk_bin_get_child(GTK_BIN(pButton)),
1617 				GTK_STATE_FLAG_NORMAL, TRUE);
1618 		}
1619 	}
1620 	g_list_free (children);
1621 	gtk_widget_queue_draw (pWidget);
1622 	return TRUE;
1623 }
_draw_menu_item(GtkWidget * pWidget,cairo_t * cr)1624 static gboolean _draw_menu_item (GtkWidget* pWidget, cairo_t *cr)
1625 {
1626     gtk_container_propagate_draw (GTK_CONTAINER (pWidget),
1627 		gtk_bin_get_child (GTK_BIN (pWidget)),
1628 		cr);  // skip the drawing of the menu-item, just propagate to its child; there is no need to make anything else, the child hbox will draw its child as usual.
1629 	return TRUE;  // intercept
1630 }
_on_motion_notify_menu_item(GtkWidget * pWidget,GdkEventMotion * pEvent,G_GNUC_UNUSED gpointer data)1631 gboolean _on_motion_notify_menu_item (GtkWidget* pWidget,
1632 	GdkEventMotion* pEvent,
1633 	G_GNUC_UNUSED gpointer data)
1634 {
1635 	GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1636 	GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1637 	int x = pEvent->x, y = pEvent->y;  // position of the mouse relatively to the menu-item
1638 	int xb, yb;  // position of the top-left corner of the button relatively to the menu-item
1639 	GtkWidget* pButton;
1640 	GList* c;
1641 	for (c = children->next; c != NULL; c = c->next)  // skip the label
1642 	{
1643 		pButton = GTK_WIDGET (c->data);
1644 		GtkAllocation alloc;
1645 		gtk_widget_get_allocation (pButton, &alloc);
1646 		gtk_widget_translate_coordinates (pButton, pWidget,
1647 			0, 0, &xb, &yb);
1648 		if (x >= xb && x < (xb + alloc.width)
1649 		&& y >= yb && y < (yb + alloc.height))  // the mouse is inside the button -> select it
1650 		{
1651 			gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_PRELIGHT, TRUE);
1652 			gtk_widget_set_state_flags (
1653 				gtk_bin_get_child(GTK_BIN(pButton)),
1654 				GTK_STATE_FLAG_PRELIGHT, TRUE);
1655 		}
1656 		else  // else deselect it, in case it was selected
1657 		{
1658 			gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1659 			gtk_widget_set_state_flags (
1660 				gtk_bin_get_child(GTK_BIN(pButton)),
1661 				GTK_STATE_FLAG_NORMAL, TRUE);
1662 		}
1663 	}
1664 	GtkWidget *pLabel = children->data;  // force the label to be in a normal state
1665 	gtk_widget_set_state_flags (pLabel, GTK_STATE_FLAG_NORMAL, TRUE);
1666 	g_list_free (children);
1667 	gtk_widget_queue_draw (pWidget);  // and redraw everything
1668 	return FALSE;
1669 }
_on_leave_menu_item(GtkWidget * pWidget,G_GNUC_UNUSED GdkEventCrossing * pEvent,G_GNUC_UNUSED gpointer data)1670 static gboolean _on_leave_menu_item (GtkWidget* pWidget,
1671 	G_GNUC_UNUSED GdkEventCrossing* pEvent,
1672 	G_GNUC_UNUSED gpointer data)
1673 {
1674 	GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1675 	GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1676 	GtkWidget* pButton;
1677 	GList* c;
1678 	for (c = children->next; c != NULL; c = c->next)
1679 	{
1680 		pButton = GTK_WIDGET(c->data);
1681 		gtk_widget_set_state_flags (pButton, GTK_STATE_FLAG_NORMAL, TRUE);
1682 		gtk_widget_set_state_flags(
1683 			gtk_bin_get_child (GTK_BIN(pButton)),
1684 			GTK_STATE_FLAG_NORMAL, TRUE);
1685 	}
1686 	g_list_free (children);
1687 	gtk_widget_queue_draw (pWidget);
1688 	return FALSE;
1689 }
_on_enter_menu_item(GtkWidget * pWidget,G_GNUC_UNUSED GdkEventCrossing * pEvent,G_GNUC_UNUSED gpointer data)1690 static gboolean _on_enter_menu_item (GtkWidget* pWidget,
1691 	G_GNUC_UNUSED GdkEventCrossing* pEvent,
1692 	G_GNUC_UNUSED gpointer data)
1693 {
1694 	GtkWidget *hbox = gtk_bin_get_child (GTK_BIN (pWidget));
1695 	GList *children = gtk_container_get_children (GTK_CONTAINER (hbox));
1696 	GtkWidget* pLabel = children->data;  // force the label to be in a normal state
1697 	gtk_widget_set_state_flags (pLabel, GTK_STATE_FLAG_NORMAL, TRUE);
1698 	g_list_free (children);
1699 	gtk_widget_queue_draw (pWidget);
1700 	return FALSE;
1701 }
_add_new_button_to_hbox(const gchar * gtkStock,const gchar * cTooltip,GCallback pFunction,GtkWidget * hbox,gpointer data)1702 static GtkWidget *_add_new_button_to_hbox (const gchar *gtkStock, const gchar *cTooltip, GCallback pFunction, GtkWidget *hbox, gpointer data)
1703 {
1704 	GtkWidget *pButton = gtk_button_new ();
1705 	/*
1706 		GtkStyleContext *ctx = gtk_widget_get_style_context (pButton);
1707 	// or we can just remove the style of a button but it's still a button :)
1708 		gtk_style_context_remove_class (ctx, GTK_STYLE_CLASS_BUTTON);
1709 	 // a style like a menuitem but it's a button...
1710 		gtk_style_context_add_class (ctx, GTK_STYLE_CLASS_MENUITEM);
1711 	*/
1712 
1713 	if (gtkStock)
1714 	{
1715 		GtkWidget *pImage = NULL;
1716 		if (*gtkStock == '/')
1717 		{
1718 			int size = cairo_dock_search_icon_size (GTK_ICON_SIZE_MENU);
1719 			GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (gtkStock, size, size, NULL);
1720 			pImage = gtk_image_new_from_pixbuf (pixbuf);
1721 			g_object_unref (pixbuf);
1722 		}
1723 		else
1724 		{
1725 			pImage = gtk_image_new_from_icon_name (gtkStock, GTK_ICON_SIZE_MENU);
1726 		}
1727 		gtk_button_set_image (GTK_BUTTON (pButton), pImage);  // don't unref the image
1728 	}
1729 	gtk_widget_set_tooltip_text (pButton, cTooltip);
1730 	g_signal_connect (G_OBJECT (pButton), "clicked", G_CALLBACK(pFunction), data);
1731 	gtk_box_pack_end (GTK_BOX (hbox), pButton, FALSE, FALSE, 0);
1732 	return pButton;
1733 }
_add_menu_item_with_buttons(GtkWidget * menu)1734 static GtkWidget *_add_menu_item_with_buttons (GtkWidget *menu)
1735 {
1736 	GtkWidget *pMenuItem = gtk_menu_item_new ();
1737 	gtk_menu_shell_append  (GTK_MENU_SHELL (menu), pMenuItem);
1738 
1739 	g_signal_connect (G_OBJECT (pMenuItem), "button-press-event",
1740 		G_CALLBACK(_on_press_menu_item),
1741 		NULL);  // the press event on the menu will close it, which is fine for us.
1742 	g_signal_connect (G_OBJECT (pMenuItem), "motion-notify-event",
1743 		G_CALLBACK(_on_motion_notify_menu_item),
1744 		NULL);  // we need to manually higlight the currently pointed button
1745 	g_signal_connect (G_OBJECT (pMenuItem),
1746 		"leave-notify-event",
1747 		G_CALLBACK (_on_leave_menu_item),
1748 		NULL);  // to turn off the highlighted button when we leave the menu-item (if we leave it quickly, a motion event won't be generated)
1749 	g_signal_connect (G_OBJECT (pMenuItem),
1750 		"enter-notify-event",
1751 		G_CALLBACK (_on_enter_menu_item),
1752 		NULL);  // to force the label to not highlight (it gets highlighted, even if we overwrite the motion_notify_event callback)
1753 	g_signal_connect (G_OBJECT (pMenuItem),
1754 		"draw",
1755 		G_CALLBACK (_draw_menu_item),
1756 		NULL);  // we don't want the whole menu-item to be higlighted, but only the currently pointed button; so we draw the menu-item ourselves.
1757 
1758 	GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
1759 	gtk_container_add (GTK_CONTAINER (pMenuItem), hbox);
1760 	return hbox;
1761 }
1762 
cairo_dock_notification_build_icon_menu(G_GNUC_UNUSED gpointer * pUserData,Icon * icon,GldiContainer * pContainer,GtkWidget * menu)1763 gboolean cairo_dock_notification_build_icon_menu (G_GNUC_UNUSED gpointer *pUserData, Icon *icon, GldiContainer *pContainer, GtkWidget *menu)
1764 {
1765 	static gpointer data[3];
1766 	data[0] = icon;
1767 	data[1] = pContainer;
1768 	data[2] = menu;
1769 	GtkWidget *pMenuItem;
1770 
1771 	gchar *cLabel;
1772 
1773 	//\_________________________ Clic en-dehors d'une icone utile => on s'arrete la.
1774 	if (CAIRO_DOCK_IS_DOCK (pContainer) && (icon == NULL || CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (icon)))
1775 	{
1776 		return GLDI_NOTIFICATION_LET_PASS;
1777 	}
1778 
1779 	gboolean bAddSeparator = TRUE;
1780 	if (CAIRO_DOCK_IS_DESKLET (pContainer) && icon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // not on the icons of a desklet, except the applet icon (on a desklet, it's easy to click out of any icon).
1781 		bAddSeparator = FALSE;
1782 
1783 	if (CAIRO_DOCK_IS_DOCK (pContainer) && CAIRO_DOCK (pContainer)->iRefCount > 0)  // not on the sub-docks, except user sub-docks.
1784 	{
1785 		Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (CAIRO_DOCK (pContainer), NULL);
1786 		if (pPointingIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (pPointingIcon))
1787 			bAddSeparator = FALSE;
1788 	}
1789 
1790 	//\_________________________ class actions.
1791 	if (icon && icon->cClass != NULL && ! icon->bIgnoreQuicklist)
1792 	{
1793 		const GList *pClassMenuItems = cairo_dock_get_class_menu_items (icon->cClass);
1794 		if (pClassMenuItems != NULL)
1795 		{
1796 			if (bAddSeparator)
1797 			{
1798 				pMenuItem = gtk_separator_menu_item_new ();
1799 				gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1800 			}
1801 			bAddSeparator = TRUE;
1802 			gchar **pClassItem;
1803 			const GList *m;
1804 			for (m = pClassMenuItems; m != NULL; m = m->next)
1805 			{
1806 				pClassItem = m->data;
1807 				pMenuItem = cairo_dock_add_in_menu_with_stock_and_data (pClassItem[0], pClassItem[2], G_CALLBACK (_cairo_dock_launch_class_action), menu, pClassItem[1]);
1808 			}
1809 		}
1810 	}
1811 
1812 	//\_________________________ On rajoute les actions sur les applis.
1813 	if (CAIRO_DOCK_IS_APPLI (icon))
1814 	{
1815 		if (bAddSeparator)
1816 		{
1817 			pMenuItem = gtk_separator_menu_item_new ();
1818 			gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1819 		}
1820 		bAddSeparator = TRUE;
1821 
1822 		GldiWindowActor *pAppli = icon->pAppli;
1823 
1824 		gboolean bCanMinimize, bCanMaximize, bCanClose;
1825 		gldi_window_can_minimize_maximize_close (pAppli, &bCanMinimize, &bCanMaximize, &bCanClose);
1826 
1827 		//\_________________________ Window Management
1828 		GtkWidget *hbox = _add_menu_item_with_buttons (menu);
1829 
1830 		GtkWidget *pLabel = gtk_label_new (_("Window"));
1831 		gtk_box_pack_start (GTK_BOX (hbox), pLabel, FALSE, FALSE, 0);
1832 
1833 		if (bCanClose)
1834 		{
1835 			if (myTaskbarParam.iActionOnMiddleClick == 1 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // close
1836 				cLabel = g_strdup_printf ("%s (%s)", _("Close"), _("middle-click"));
1837 			else
1838 				cLabel = g_strdup (_("Close"));
1839 			_add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-close.svg",
1840 				cLabel,
1841 				G_CALLBACK(_cairo_dock_close_appli),
1842 				hbox, data);
1843 			g_free (cLabel);
1844 		}
1845 
1846 		if (! pAppli->bIsHidden)
1847 		{
1848 			if (bCanMaximize)
1849 			{
1850 				_add_new_button_to_hbox (pAppli->bIsMaximized ? CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-restore.svg" : CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-maximize.svg",
1851 					pAppli->bIsMaximized ? _("Unmaximise") : _("Maximise"),
1852 					G_CALLBACK(_cairo_dock_maximize_appli),
1853 					hbox, data);
1854 			}
1855 
1856 			if (bCanMinimize)
1857 			{
1858 				if (myTaskbarParam.iActionOnMiddleClick == 2 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // minimize
1859 					cLabel = g_strdup_printf ("%s (%s)", _("Minimise"), _("middle-click"));
1860 				else
1861 					cLabel = g_strdup (_("Minimise"));
1862 				_add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-minimize.svg",
1863 					cLabel,
1864 					G_CALLBACK(_cairo_dock_minimize_appli),
1865 					hbox, data);
1866 				g_free (cLabel);
1867 			}
1868 		}
1869 
1870 		if (pAppli->bIsHidden
1871 		    || pAppli != gldi_windows_get_active ()
1872 		    || !gldi_window_is_on_current_desktop (pAppli))
1873 		{
1874 			_add_new_button_to_hbox (GLDI_ICON_NAME_FIND,
1875 				_("Show"),
1876 				G_CALLBACK(_cairo_dock_show_appli),
1877 				hbox, data);
1878 		}
1879 
1880 		//\_________________________ Other actions
1881 		GtkWidget *pSubMenuOtherActions = cairo_dock_create_sub_menu (_("Other actions"), menu, NULL);
1882 
1883 		// Move
1884 		pMenuItem = _add_entry_in_menu (_("Move to this desktop"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_move_appli_to_current_desktop, pSubMenuOtherActions);
1885 		if (gldi_window_is_on_current_desktop (pAppli))
1886 			gtk_widget_set_sensitive (pMenuItem, FALSE);
1887 
1888 		// Fullscreen
1889 		_add_entry_in_menu (pAppli->bIsFullScreen ? _("Not Fullscreen") : _("Fullscreen"), pAppli->bIsFullScreen ? GLDI_ICON_NAME_LEAVE_FULLSCREEN : GLDI_ICON_NAME_FULLSCREEN, _cairo_dock_set_appli_fullscreen, pSubMenuOtherActions);
1890 
1891 		// Below
1892 		if (! pAppli->bIsHidden)  // this could be a button in the menu, if we find an icon that doesn't look too much like the "minimise" one
1893 		{
1894 			if (myTaskbarParam.iActionOnMiddleClick == 4 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // lower
1895 				cLabel = g_strdup_printf ("%s (%s)", _("Below other windows"), _("middle-click"));
1896 			else
1897 				cLabel = g_strdup (_("Below other windows"));
1898 			_add_entry_in_menu (cLabel, CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-lower.svg", _cairo_dock_lower_appli, pSubMenuOtherActions);
1899 			g_free (cLabel);
1900 		}
1901 
1902 		// Above
1903 		gboolean bIsAbove=FALSE, bIsBelow=FALSE;
1904 		gldi_window_is_above_or_below (pAppli, &bIsAbove, &bIsBelow);
1905 		_add_entry_in_menu (bIsAbove ? _("Don't keep above") : _("Keep above"), bIsAbove ? GLDI_ICON_NAME_GOTO_BOTTOM : GLDI_ICON_NAME_GOTO_TOP, _cairo_dock_change_window_above, pSubMenuOtherActions);
1906 
1907 		// Sticky
1908 		gboolean bIsSticky = gldi_window_is_sticky (pAppli);
1909 		_add_entry_in_menu (bIsSticky ? _("Visible only on this desktop") : _("Visible on all desktops"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_change_window_sticky, pSubMenuOtherActions);
1910 
1911 		_add_desktops_entry (pSubMenuOtherActions, FALSE, data);
1912 
1913 		// add separator
1914 		pMenuItem = gtk_separator_menu_item_new ();
1915 		gtk_menu_shell_append (GTK_MENU_SHELL (pSubMenuOtherActions), pMenuItem);
1916 
1917 		_add_entry_in_menu (_("Kill"), GLDI_ICON_NAME_CLOSE, _cairo_dock_kill_appli, pSubMenuOtherActions);
1918 	}
1919 	else if (CAIRO_DOCK_IS_MULTI_APPLI (icon))
1920 	{
1921 		if (bAddSeparator)
1922 		{
1923 			pMenuItem = gtk_separator_menu_item_new ();
1924 			gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1925 		}
1926 		bAddSeparator = TRUE;
1927 
1928 		//\_________________________ Window Management
1929 		GtkWidget *hbox = _add_menu_item_with_buttons (menu);
1930 
1931 		GtkWidget *pLabel = gtk_label_new (_("Windows"));
1932 		gtk_box_pack_start (GTK_BOX (hbox), pLabel, FALSE, FALSE, 0);
1933 
1934 		if (myTaskbarParam.iActionOnMiddleClick == 1 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // close
1935 			cLabel = g_strdup_printf ("%s (%s)", _("Close all"), _("middle-click"));
1936 		else
1937 			cLabel = g_strdup (_("Close all"));
1938 		_add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-close.svg",
1939 			cLabel,
1940 			G_CALLBACK(_cairo_dock_close_class),
1941 			hbox, data);
1942 		g_free (cLabel);
1943 
1944 		if (myTaskbarParam.iActionOnMiddleClick == 2 && ! CAIRO_DOCK_ICON_TYPE_IS_APPLET (icon))  // minimize
1945 			cLabel = g_strdup_printf ("%s (%s)", _("Minimise all"), _("middle-click"));
1946 		else
1947 			cLabel = g_strdup (_("Minimise all"));
1948 		_add_new_button_to_hbox (CAIRO_DOCK_SHARE_DATA_DIR"/icons/icon-minimize.svg",
1949 			cLabel,
1950 			G_CALLBACK(_cairo_dock_minimize_class),
1951 			hbox, data);
1952 		g_free (cLabel);
1953 
1954 		_add_new_button_to_hbox (GLDI_ICON_NAME_FIND,
1955 			_("Show all"),
1956 			G_CALLBACK(_cairo_dock_show_class),
1957 			hbox, data);
1958 
1959 		//\_________________________ Other actions
1960 		GtkWidget *pSubMenuOtherActions = cairo_dock_create_sub_menu (_("Other actions"), menu, NULL);
1961 
1962 		_add_entry_in_menu (_("Move all to this desktop"), GLDI_ICON_NAME_JUMP_TO, _cairo_dock_move_class_to_current_desktop, pSubMenuOtherActions);
1963 
1964 		_add_desktops_entry (pSubMenuOtherActions, TRUE, data);
1965 	}
1966 
1967 	//\_________________________ On rajoute les actions de positionnement d'un desklet.
1968 	if (! cairo_dock_is_locked () && CAIRO_DOCK_IS_DESKLET (pContainer))
1969 	{
1970 		if (bAddSeparator)
1971 		{
1972 			pMenuItem = gtk_separator_menu_item_new ();
1973 			gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
1974 		}
1975 		bAddSeparator = TRUE;
1976 
1977 		GtkWidget *pSubMenuAccessibility = cairo_dock_create_sub_menu (_("Visibility"), menu, GLDI_ICON_NAME_FIND);
1978 
1979 		GSList *group = NULL;
1980 
1981 		gboolean bIsSticky = gldi_desklet_is_sticky (CAIRO_DESKLET (pContainer));
1982 		CairoDesklet *pDesklet = CAIRO_DESKLET (pContainer);
1983 		CairoDeskletVisibility iVisibility = pDesklet->iVisibility;
1984 
1985 		pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Normal"));
1986 		group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
1987 		gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
1988 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), iVisibility == CAIRO_DESKLET_NORMAL/*bIsNormal*/);  // on coche celui-ci par defaut, il sera decoche par les suivants eventuellement.
1989 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_normal), data);
1990 
1991 		pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Always on top"));
1992 		group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
1993 		gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
1994 		if (iVisibility == CAIRO_DESKLET_KEEP_ABOVE)
1995 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
1996 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_above), data);
1997 
1998 		pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Always below"));
1999 		group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2000 		gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2001 		if (iVisibility == CAIRO_DESKLET_KEEP_BELOW)
2002 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2003 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_below), data);
2004 
2005 		if (gldi_desktop_can_set_on_widget_layer ())
2006 		{
2007 			pMenuItem = gtk_radio_menu_item_new_with_label(group, "Widget Layer");
2008 			group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2009 			gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2010 			if (iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER)
2011 				gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2012 			g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_on_widget_layer), data);
2013 		}
2014 
2015 		pMenuItem = gtk_radio_menu_item_new_with_label(group, _("Reserve space"));
2016 		group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(pMenuItem));
2017 		gtk_menu_shell_append(GTK_MENU_SHELL(pSubMenuAccessibility), pMenuItem);
2018 		if (iVisibility == CAIRO_DESKLET_RESERVE_SPACE)
2019 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2020 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_keep_space), data);
2021 
2022 		pMenuItem = gtk_check_menu_item_new_with_label(_("On all desktops"));
2023 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
2024 		if (bIsSticky)
2025 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2026 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_set_on_all_desktop), data);
2027 
2028 		pMenuItem = gtk_check_menu_item_new_with_label(_("Lock position"));
2029 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), pMenuItem);
2030 		if (pDesklet->bPositionLocked)
2031 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pMenuItem), TRUE);
2032 		g_signal_connect(G_OBJECT(pMenuItem), "toggled", G_CALLBACK(_cairo_dock_lock_position), data);
2033 	}
2034 
2035 	return GLDI_NOTIFICATION_LET_PASS;
2036 }
2037