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 
24 #include <gtk/gtk.h>
25 
26 #include "gldi-config.h"
27 #include "cairo-dock-icon-factory.h"
28 #include "cairo-dock-module-instance-manager.h"  // gldi_module_instance_reload
29 #include "cairo-dock-desklet-manager.h"  // gldi_desklets_foreach_icons
30 #include "cairo-dock-log.h"
31 #include "cairo-dock-config.h"
32 #include "cairo-dock-class-manager.h"  // cairo_dock_deinhibite_class
33 #include "cairo-dock-draw.h"  // cairo_dock_render_icon_notification
34 #include "cairo-dock-draw-opengl.h"  // cairo_dock_destroy_icon_fbo
35 #include "cairo-dock-container.h"
36 #include "cairo-dock-dock-manager.h"  // gldi_icons_foreach_in_docks
37 #include "cairo-dock-dialog-manager.h"  // cairo_dock_remove_dialog_if_any
38 #include "cairo-dock-data-renderer.h"  // cairo_dock_remove_data_renderer_on_icon
39 #include "cairo-dock-animations.h"  // cairo_dock_animation_will_be_visible
40 #include "cairo-dock-dock-facility.h"  // cairo_dock_update_dock_size
41 #include "cairo-dock-icon-facility.h"  // gldi_icons_foreach_of_type
42 #include "cairo-dock-keyfile-utilities.h"  // cairo_dock_open_key_file
43 #include "cairo-dock-indicator-manager.h"  // cairo_dock_unload_indicator_textures
44 #include "cairo-dock-desktop-manager.h"  // gldi_desktop_get_current
45 #include "cairo-dock-user-icon-manager.h"  // GLDI_OBJECT_IS_USER_ICON
46 #include "cairo-dock-separator-manager.h"  // GLDI_OBJECT_IS_SEPARATOR_ICON
47 #include "cairo-dock-applications-manager.h"  // GLDI_OBJECT_IS_APPLI_ICON
48 #include "cairo-dock-launcher-manager.h"  // GLDI_OBJECT_IS_LAUNCHER_ICON
49 #include "cairo-dock-applet-manager.h"  // GLDI_OBJECT_IS_APPLET_ICON
50 #include "cairo-dock-backends-manager.h"  // cairo_dock_foreach_icon_container_renderer
51 #include "cairo-dock-style-manager.h"
52 #define _MANAGER_DEF_
53 #include "cairo-dock-icon-manager.h"
54 
55 // public (manager, config, data)
56 CairoIconsParam myIconsParam;
57 GldiManager myIconsMgr;
58 GldiObjectManager myIconObjectMgr;
59 CairoDockImageBuffer g_pIconBackgroundBuffer;
60 GLuint g_pGradationTexture[2]={0, 0};
61 
62 // dependencies
63 extern CairoDock *g_pMainDock;
64 extern gchar *g_cCurrentThemePath;
65 extern gboolean g_bUseOpenGL;
66 extern gchar *g_cCurrentIconsPath;
67 
68 // private
69 static GList *s_pFloatingIconsList = NULL;
70 static int s_iNbNonStickyLaunchers = 0;
71 static GtkIconTheme *s_pIconTheme = NULL;
72 static gboolean s_bUseLocalIcons = FALSE;
73 static gboolean s_bUseDefaultTheme = TRUE;
74 static guint s_iSidReloadTheme = 0;
75 
76 static void _cairo_dock_unload_icon_textures (void);
77 static void _cairo_dock_unload_icon_theme (void);
78 static void _on_icon_theme_changed (GtkIconTheme *pIconTheme, gpointer data);
79 
80 
gldi_icons_foreach(GldiIconFunc pFunction,gpointer pUserData)81 void gldi_icons_foreach (GldiIconFunc pFunction, gpointer pUserData)
82 {
83 	gldi_icons_foreach_in_docks (pFunction, pUserData);
84 	gldi_desklets_foreach_icons (pFunction, pUserData);
85 }
86 
87   /////////////////////////
88  /// ICONS PER DESKTOP ///
89 /////////////////////////
90 
91 #define _is_invisible_on_this_desktop(icon, index) (icon->iSpecificDesktop != 0  /*specific desktop is defined*/ \
92 	&& icon->iSpecificDesktop != index  /*specific desktop is not the current one*/ \
93 	&& icon->iSpecificDesktop <= g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY)  /*specific desktop is reachable*/
94 
_cairo_dock_detach_launcher(Icon * pIcon)95 static void _cairo_dock_detach_launcher (Icon *pIcon)
96 {
97 	gchar *cParentDockName = g_strdup (pIcon->cParentDockName);
98 	gldi_icon_detach (pIcon);  // this will set cParentDockName to NULL
99 
100 	pIcon->cParentDockName = cParentDockName;  // put it back !
101 }
_hide_launcher_on_other_desktops(Icon * icon,int index)102 static void _hide_launcher_on_other_desktops (Icon *icon, int index)
103 {
104 	cd_debug ("%s (%s, iNumViewport=%d)", __func__, icon->cName, icon->iSpecificDesktop);
105 	if (_is_invisible_on_this_desktop (icon, index))
106 	{
107 		if (! g_list_find (s_pFloatingIconsList, icon))  // paranoia
108 		{
109 			cd_debug ("launcher %s is not present on this desktop", icon->cName);
110 			_cairo_dock_detach_launcher (icon);
111 			s_pFloatingIconsList = g_list_prepend (s_pFloatingIconsList, icon);
112 		}
113 	}
114 }
_hide_icon_on_other_desktops(Icon * icon,gpointer data)115 static void _hide_icon_on_other_desktops (Icon *icon, gpointer data)
116 {
117 	if (GLDI_OBJECT_IS_USER_ICON (icon))
118 	{
119 		int index = GPOINTER_TO_INT (data);
120 		_hide_launcher_on_other_desktops (icon, index);
121 	}
122 }
_show_launcher_on_this_desktop(Icon * icon,int index)123 static void _show_launcher_on_this_desktop (Icon *icon, int index)
124 {
125 	if (! _is_invisible_on_this_desktop (icon, index))
126 	{
127 		cd_debug (" => est visible sur ce viewport (iSpecificDesktop = %d).",icon->iSpecificDesktop);
128 		s_pFloatingIconsList = g_list_remove (s_pFloatingIconsList, icon);
129 
130 		CairoDock *pParentDock = gldi_dock_get (icon->cParentDockName);
131 		if (pParentDock != NULL)
132 		{
133 			gldi_icon_insert_in_container (icon, CAIRO_CONTAINER(pParentDock), ! CAIRO_DOCK_ANIMATE_ICON);
134 		}
135 		else  // the dock doesn't exist any more -> free the icon
136 		{
137 			icon->iSpecificDesktop = 0;  // pour ne pas qu'elle soit enlevee de la liste en parallele.
138 			gldi_object_delete (GLDI_OBJECT (icon));
139 		}
140 	}
141 }
142 
cairo_dock_hide_show_launchers_on_other_desktops(void)143 void cairo_dock_hide_show_launchers_on_other_desktops (void )  /// TODO: add a mechanism to hide an icon in a dock (or even in a container ?) without detaching it...
144 {
145 	if (s_iNbNonStickyLaunchers <= 0)
146 		return ;
147 
148 	// calculate the index of the current desktop
149 	int iCurrentDesktop = 0, iCurrentViewportX = 0, iCurrentViewportY = 0;
150 	gldi_desktop_get_current (&iCurrentDesktop, &iCurrentViewportX, &iCurrentViewportY);
151 	int index = iCurrentDesktop * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY + iCurrentViewportX * g_desktopGeometry.iNbViewportY + iCurrentViewportY + 1;  // +1 car on commence a compter a partir de 1.
152 
153 	// first detach what shouldn't be shown on this desktop
154 	gldi_icons_foreach_in_docks ((GldiIconFunc)_hide_icon_on_other_desktops, GINT_TO_POINTER (index));
155 
156 	// then reattach what was eventually missing
157 	Icon *icon;
158 	GList *ic = s_pFloatingIconsList, *next_ic;
159 	while (ic != NULL)
160 	{
161 		next_ic = ic->next;  // get the next element now, because '_show_launcher_on_this_desktop' might remove 'ic' from the list.
162 		icon = ic->data;
163 		_show_launcher_on_this_desktop (icon, index);
164 		ic = next_ic;
165 	}
166 }
167 
_on_change_current_desktop_viewport_notification(G_GNUC_UNUSED gpointer data)168 static gboolean _on_change_current_desktop_viewport_notification (G_GNUC_UNUSED gpointer data)
169 {
170 	cairo_dock_hide_show_launchers_on_other_desktops ();
171 	return GLDI_NOTIFICATION_LET_PASS;
172 }
173 
_cairo_dock_delete_floating_icons(void)174 static void _cairo_dock_delete_floating_icons (void)
175 {
176 	Icon *icon;
177 	GList *ic;
178 	for (ic = s_pFloatingIconsList; ic != NULL; ic = ic->next)
179 	{
180 		icon = ic->data;
181 		icon->iSpecificDesktop = 0;  // pour ne pas qu'elle soit enlevee de la liste en parallele.
182 		gldi_object_unref (GLDI_OBJECT (icon));
183 	}
184 	g_list_free (s_pFloatingIconsList);
185 	s_pFloatingIconsList = NULL;
186 	s_iNbNonStickyLaunchers = 0;
187 }
188 
cairo_dock_set_specified_desktop_for_icon(Icon * pIcon,int iSpecificDesktop)189 void cairo_dock_set_specified_desktop_for_icon (Icon *pIcon, int iSpecificDesktop)
190 {
191 	if (iSpecificDesktop != 0 && pIcon->iSpecificDesktop == 0)
192 	{
193 		s_iNbNonStickyLaunchers ++;
194 	}
195 	else if (iSpecificDesktop == 0 && pIcon->iSpecificDesktop != 0)
196 	{
197 		s_iNbNonStickyLaunchers --;
198 	}
199 	pIcon->iSpecificDesktop = iSpecificDesktop;
200 }
201 
202 
203   //////////////////
204  /// ICON THEME ///
205 //////////////////
206 
207 /*
208  * GTK_ICON_SIZE_MENU:          16
209  * GTK_ICON_SIZE_SMALL_TOOLBAR: 18
210  * GTK_ICON_SIZE_BUTTON:        20
211  * GTK_ICON_SIZE_LARGE_TOOLBAR: 24
212  * GTK_ICON_SIZE_DND:           32
213  * GTK_ICON_SIZE_DIALOG:        48
214  */
cairo_dock_search_icon_size(GtkIconSize iIconSize)215 gint cairo_dock_search_icon_size (GtkIconSize iIconSize)
216 {
217 	gint iWidth, iHeight;
218 	if (! gtk_icon_size_lookup (iIconSize, &iWidth, &iHeight))
219 		return CAIRO_DOCK_DEFAULT_ICON_SIZE;
220 
221 	return MAX (iWidth, iHeight);
222 }
223 
cairo_dock_search_icon_s_path(const gchar * cFileName,gint iDesiredIconSize)224 gchar *cairo_dock_search_icon_s_path (const gchar *cFileName, gint iDesiredIconSize)
225 {
226 	g_return_val_if_fail (cFileName != NULL, NULL);
227 
228 	//\_______________________ easy cases: we receive a path.
229 	if (*cFileName == '~')
230 	{
231 		return g_strdup_printf ("%s%s", g_getenv ("HOME"), cFileName+1);
232 	}
233 
234 	if (*cFileName == '/')
235 	{
236 		return g_strdup (cFileName);
237 	}
238 
239 	//\_______________________ check for the presence of suffix and version number.
240 	g_return_val_if_fail (s_pIconTheme != NULL, NULL);
241 
242 	GString *sIconPath = g_string_new ("");
243 	const gchar *cSuffixTab[4] = {".svg", ".png", ".xpm", NULL};
244 	gboolean bHasSuffix=FALSE, bFileFound=FALSE, bHasVersion=FALSE;
245 	GtkIconInfo* pIconInfo = NULL;
246 	gchar *str = strrchr (cFileName, '.');
247 	bHasSuffix = (str != NULL && g_ascii_isalpha (*(str+1)));  // exemple : "firefox.svg", but not "firefox-3.0"
248 	bHasVersion = (str != NULL && g_ascii_isdigit (*(str+1)) && g_ascii_isdigit (*(str-1)) && str-1 != cFileName);  // doit finir par x.y, x et y ayant autant de chiffres que l'on veut.
249 
250 	//\_______________________ search in the local icons folder if enabled.
251 	if (s_bUseLocalIcons)
252 	{
253 		if (! bHasSuffix)  // test all the suffix one by one.
254 		{
255 			int j = 0;
256 			while (cSuffixTab[j] != NULL)
257 			{
258 				g_string_printf (sIconPath, "%s/%s%s", g_cCurrentIconsPath, cFileName, cSuffixTab[j]);
259 				if ( g_file_test (sIconPath->str, G_FILE_TEST_EXISTS) )
260 				{
261 					bFileFound = TRUE;
262 					break;
263 				}
264 				j ++;
265 			}
266 		}
267 		else  // just test the file.
268 		{
269 			g_string_printf (sIconPath, "%s/%s", g_cCurrentIconsPath, cFileName);
270 			bFileFound = g_file_test (sIconPath->str, G_FILE_TEST_EXISTS);
271 		}
272 	}
273 
274 	//\_______________________ search in the icon theme
275 	if (! bFileFound)  // didn't found/search in the local icons, so try the icon theme.
276 	{
277 		g_string_assign (sIconPath, cFileName);
278 		if (bHasSuffix)  // on vire le suffixe pour chercher tous les formats dans le theme d'icones.
279 		{
280 			gchar *str = strrchr (sIconPath->str, '.');
281 			if (str != NULL)
282 				*str = '\0';
283 		}
284 
285 		pIconInfo = gtk_icon_theme_lookup_icon (s_pIconTheme,
286 			sIconPath->str,
287 			iDesiredIconSize, // GTK_ICON_LOOKUP_FORCE_SIZE if size < 30 ?? -> icons can be different // a lot of themes now use only svg files.
288 			GTK_ICON_LOOKUP_FORCE_SVG);
289 		if (pIconInfo == NULL && ! s_bUseLocalIcons && ! bHasVersion)  // if we were not using the default theme and didn't find any icon, let's try with the default theme (for instance gvfs will give us names from the default theme, and they might not exist in our current theme); if it has a version, we'll retry without it.
290 		{
291 			pIconInfo = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (),  // the default theme is mapped in shared memory so it's available at any time.
292 				sIconPath->str,
293 				iDesiredIconSize,
294 				GTK_ICON_LOOKUP_FORCE_SVG);
295 		}
296 		if (pIconInfo != NULL)
297 		{
298 			g_string_assign (sIconPath, gtk_icon_info_get_filename (pIconInfo));
299 			bFileFound = TRUE;
300 			#if GTK_CHECK_VERSION (3, 8, 0)
301 			g_object_unref (G_OBJECT (pIconInfo));
302 			#else
303 			gtk_icon_info_free (pIconInfo);
304 			#endif
305 		}
306 	}
307 
308 
309 	//\_______________________ si rien trouve, on cherche sans le numero de version.
310 	if (! bFileFound && bHasVersion)
311 	{
312 		cd_debug ("on cherche sans le numero de version...");
313 		g_string_assign (sIconPath, cFileName);
314 		gchar *str = strrchr (sIconPath->str, '.');
315 		str --;  // on sait que c'est un digit.
316 		str --;
317 		while ((g_ascii_isdigit (*str) || *str == '.' || *str == '-') && (str != sIconPath->str))
318 			str --;
319 		if (str != sIconPath->str)
320 		{
321 			*(str+1) = '\0';
322 			cd_debug (" on cherche '%s'...", sIconPath->str);
323 			gchar *cPath = cairo_dock_search_icon_s_path (sIconPath->str, iDesiredIconSize);
324 			if (cPath != NULL)
325 			{
326 				bFileFound = TRUE;
327 				g_string_assign (sIconPath, cPath);
328 				g_free (cPath);
329 			}
330 		}
331 	}
332 
333 	if (! bFileFound)
334 	{
335 		g_string_free (sIconPath, TRUE);
336 		return NULL;
337 	}
338 
339 	gchar *cIconPath = sIconPath->str;
340 	g_string_free (sIconPath, FALSE);
341 	return cIconPath;
342 }
343 
cairo_dock_add_path_to_icon_theme(const gchar * cThemePath)344 void cairo_dock_add_path_to_icon_theme (const gchar *cThemePath)
345 {
346 	if (s_bUseDefaultTheme)
347 	{
348 		g_signal_handlers_block_matched (s_pIconTheme,
349 			(GSignalMatchType) G_SIGNAL_MATCH_FUNC,
350 			0, 0, NULL, _on_icon_theme_changed, NULL);
351 	}
352 	gtk_icon_theme_append_search_path (s_pIconTheme,
353 		cThemePath);  /// TODO: does it check for unicity ?...
354 	gtk_icon_theme_rescan_if_needed (s_pIconTheme);
355 	if (s_bUseDefaultTheme)
356 	{
357 		g_signal_handlers_unblock_matched (s_pIconTheme,
358 			(GSignalMatchType) G_SIGNAL_MATCH_FUNC,
359 			0, 0, NULL, _on_icon_theme_changed, NULL);  // will do nothing if the callback has not been connected
360 	}
361 }
362 
cairo_dock_remove_path_from_icon_theme(const gchar * cThemePath)363 void cairo_dock_remove_path_from_icon_theme (const gchar *cThemePath)
364 {
365 	if (! GTK_IS_ICON_THEME (s_pIconTheme))
366 		return;
367 	g_signal_handlers_block_matched (s_pIconTheme,
368 		(GSignalMatchType) G_SIGNAL_MATCH_FUNC,
369 		0, 0, NULL, _on_icon_theme_changed, NULL);
370 
371 	gchar **paths = NULL;
372 	gint iNbPaths = 0;
373 	gtk_icon_theme_get_search_path (s_pIconTheme, &paths, &iNbPaths);
374 	int i;
375 	for (i = 0; i < iNbPaths; i++)  // on cherche sa position dans le tableau.
376 	{
377 		if (strcmp (paths[i], cThemePath))
378 			break;
379 	}
380 	if (i < iNbPaths)  // trouve
381 	{
382 		g_free (paths[i]);
383 		for (i = i+1; i < iNbPaths; i++)  // on decale tous les suivants vers l'arriere.
384 		{
385 			paths[i-1] = paths[i];
386 		}
387 		paths[i-1] = NULL;
388 		gtk_icon_theme_set_search_path (s_pIconTheme, (const gchar **)paths, iNbPaths - 1);
389 	}
390 	g_strfreev (paths);
391 
392 	g_signal_handlers_unblock_matched (s_pIconTheme,
393 		(GSignalMatchType) G_SIGNAL_MATCH_FUNC,
394 		0, 0, NULL, _on_icon_theme_changed, NULL);  // will do nothing if the callback has not been connected
395 }
396 
397 
398   //////////////////
399  /// GET CONFIG ///
400 //////////////////
401 
get_config(GKeyFile * pKeyFile,CairoIconsParam * pIcons)402 static gboolean get_config (GKeyFile *pKeyFile, CairoIconsParam *pIcons)
403 {
404 	gboolean bFlushConfFileNeeded = FALSE;
405 
406 	//\___________________ Reflets.
407 	pIcons->fReflectHeightRatio = cairo_dock_get_double_key_value (pKeyFile, "Icons", "field depth", &bFlushConfFileNeeded, 0.7, NULL, NULL);
408 
409 	pIcons->fAlbedo = cairo_dock_get_double_key_value (pKeyFile, "Icons", "albedo", &bFlushConfFileNeeded, .6, NULL, NULL);
410 
411 #ifndef AVOID_PATENT_CRAP
412 	double fMaxScale = cairo_dock_get_double_key_value (pKeyFile, "Icons", "zoom max", &bFlushConfFileNeeded, 0., NULL, NULL);
413 	if (fMaxScale == 0)
414 	{
415 		pIcons->fAmplitude = g_key_file_get_double (pKeyFile, "Icons", "amplitude", NULL);
416 		fMaxScale = 1 + pIcons->fAmplitude;
417 		g_key_file_set_double (pKeyFile, "Icons", "zoom max", fMaxScale);
418 	}
419 	else
420 		pIcons->fAmplitude = fMaxScale - 1;
421 #else
422 	pIcons->fAmplitude = 0.;
423 #endif
424 
425 	pIcons->iSinusoidWidth = cairo_dock_get_integer_key_value (pKeyFile, "Icons", "sinusoid width", &bFlushConfFileNeeded, 250, NULL, NULL);
426 	pIcons->iSinusoidWidth = MAX (1, pIcons->iSinusoidWidth);
427 
428 	pIcons->iIconGap = cairo_dock_get_integer_key_value (pKeyFile, "Icons", "icon gap", &bFlushConfFileNeeded, 0, NULL, NULL);
429 
430 	//\___________________ Ficelle.
431 	pIcons->iStringLineWidth = cairo_dock_get_integer_key_value (pKeyFile, "Icons", "string width", &bFlushConfFileNeeded, 0, NULL, NULL);
432 
433 	gdouble couleur[4];
434 	cairo_dock_get_double_list_key_value (pKeyFile, "Icons", "string color", &bFlushConfFileNeeded, pIcons->fStringColor, 4, couleur, NULL, NULL);
435 
436 	pIcons->fAlphaAtRest = cairo_dock_get_double_key_value (pKeyFile, "Icons", "alpha at rest", &bFlushConfFileNeeded, 1., NULL, NULL);
437 
438 	//\___________________ Theme d'icone.
439 	pIcons->cIconTheme = cairo_dock_get_string_key_value (pKeyFile, "Icons", "default icon directory", &bFlushConfFileNeeded, NULL, "Launchers", NULL);
440 	if (g_key_file_has_key (pKeyFile, "Icons", "local icons", NULL))  // anciens parametres.
441 	{
442 		bFlushConfFileNeeded = TRUE;
443 		gboolean bUseLocalIcons = g_key_file_get_boolean (pKeyFile, "Icons", "local icons", NULL);
444 		if (bUseLocalIcons)
445 		{
446 			g_free (pIcons->cIconTheme);
447 			pIcons->cIconTheme = g_strdup ("_Custom Icons_");
448 			g_key_file_set_string (pKeyFile, "Icons", "default icon directory", pIcons->cIconTheme);
449 		}
450 	}
451 
452 	gchar *cLauncherBackgroundImageName = cairo_dock_get_string_key_value (pKeyFile, "Icons", "icons bg", &bFlushConfFileNeeded, NULL, NULL, NULL);
453 	if (cLauncherBackgroundImageName != NULL)
454 	{
455 		pIcons->cBackgroundImagePath = cairo_dock_search_image_s_path (cLauncherBackgroundImageName);
456 		g_free (cLauncherBackgroundImageName);
457 	}
458 
459 	//\___________________ icons size
460 	cairo_dock_get_size_key_value_helper (pKeyFile, "Icons", "launcher ", bFlushConfFileNeeded, pIcons->iIconWidth, pIcons->iIconHeight);
461 	if (pIcons->iIconWidth == 0)
462 		pIcons->iIconWidth = 48;
463 	if (pIcons->iIconHeight == 0)
464 		pIcons->iIconHeight = 48;
465 
466 	//\___________________ Parametres des separateurs.
467 	cairo_dock_get_size_key_value_helper (pKeyFile, "Icons", "separator ", bFlushConfFileNeeded, pIcons->iSeparatorWidth, pIcons->iSeparatorHeight);
468 	if (pIcons->iSeparatorWidth == 0)
469 		pIcons->iSeparatorWidth = pIcons->iIconWidth;
470 	if (pIcons->iSeparatorHeight == 0)
471 		pIcons->iSeparatorHeight = pIcons->iIconHeight;
472 	if (pIcons->iSeparatorHeight > pIcons->iIconHeight)
473 		pIcons->iSeparatorHeight = pIcons->iIconHeight;
474 
475 	pIcons->iSeparatorType = cairo_dock_get_integer_key_value (pKeyFile, "Icons", "separator type", &bFlushConfFileNeeded, -1, NULL, NULL);
476 	if (pIcons->iSeparatorType >= CAIRO_DOCK_NB_SEPARATOR_TYPES)  // nouveau parametre, avant il etait dans dock-rendering.
477 	{
478 		pIcons->iSeparatorType = CAIRO_DOCK_NORMAL_SEPARATOR;  // ce qui suit est tres moche, mais c'est pour eviter d'avoir a repasser derriere tous les themes.
479 		gchar *cMainDockDefaultRendererName = g_key_file_get_string (pKeyFile, "Views", "main dock view", NULL);
480 		if (cMainDockDefaultRendererName && (strcmp (cMainDockDefaultRendererName, "3D plane") == 0 || strcmp (cMainDockDefaultRendererName, "Curve") == 0))
481 		{
482 			gchar *cRenderingConfFile = g_strdup_printf ("%s/plug-ins/rendering/rendering.conf", g_cCurrentThemePath);
483 			GKeyFile *keyfile = cairo_dock_open_key_file (cRenderingConfFile);
484 			g_free (cRenderingConfFile);
485 			if (keyfile == NULL)
486 				pIcons->iSeparatorType = CAIRO_DOCK_NORMAL_SEPARATOR;
487 			else
488 			{
489 				if (strcmp (cMainDockDefaultRendererName, "3D plane") == 0)
490 				{
491 					pIcons->iSeparatorType = g_key_file_get_integer (keyfile, "Inclinated Plane", "draw separator", NULL);
492 				}
493 				else
494 				{
495 					pIcons->iSeparatorType = g_key_file_get_integer (keyfile, "Curve", "draw curve separator", NULL);
496 				}
497 				cairo_dock_get_color_key_value (keyfile, "Inclinated Plane", "separator color", &bFlushConfFileNeeded, &pIcons->fSeparatorColor, NULL, NULL, NULL);
498 				g_key_file_free (keyfile);
499 			}
500 		}
501 		g_key_file_set_integer (pKeyFile, "Icons", "separator type", pIcons->iSeparatorType);
502 		g_key_file_set_double_list (pKeyFile, "Icons", "separator color", (double*)&pIcons->fSeparatorColor.rgba, 4);
503 		g_free (cMainDockDefaultRendererName);
504 	}
505 	else
506 	{
507 		GldiColor couleur = {{0.9,0.9,1.0,1.0}};
508 		cairo_dock_get_color_key_value (pKeyFile, "Icons", "separator color", &bFlushConfFileNeeded, &pIcons->fSeparatorColor, &couleur, NULL, NULL);
509 	}
510 
511 	pIcons->bSeparatorUseDefaultColors = (cairo_dock_get_integer_key_value (pKeyFile, "Icons", "separator_style", &bFlushConfFileNeeded, 1, NULL, NULL) == 0);
512 
513 	if (pIcons->iSeparatorType == CAIRO_DOCK_NORMAL_SEPARATOR)
514 		pIcons->cSeparatorImage = cairo_dock_get_string_key_value (pKeyFile, "Icons", "separator image", &bFlushConfFileNeeded, NULL, "Separators", NULL);
515 
516 	pIcons->bRevolveSeparator = cairo_dock_get_boolean_key_value (pKeyFile, "Icons", "revolve separator image", &bFlushConfFileNeeded, TRUE, "Separators", NULL);
517 
518 	pIcons->bConstantSeparatorSize = cairo_dock_get_boolean_key_value (pKeyFile, "Icons", "force size", &bFlushConfFileNeeded, TRUE, "Separators", NULL);
519 
520 	//\___________________ labels font
521 	CairoIconsParam *pLabels = pIcons;
522 	gboolean bCustomFont = cairo_dock_get_boolean_key_value (pKeyFile, "Labels", "custom", &bFlushConfFileNeeded, TRUE, NULL, NULL);
523 
524 	gchar *cFont = (bCustomFont ? cairo_dock_get_string_key_value (pKeyFile, "Labels", "police", &bFlushConfFileNeeded, NULL, "Icons", NULL) : NULL);
525 	gldi_text_description_set_font (&pLabels->iconTextDescription, cFont);
526 
527 	cd_debug ("label font: %s, %d\n", pLabels->iconTextDescription.cFont, pLabels->iconTextDescription.iSize);
528 
529 	//\___________________ labels text color
530 	pLabels->iconTextDescription.bOutlined = cairo_dock_get_boolean_key_value (pKeyFile, "Labels", "text oulined", &bFlushConfFileNeeded, TRUE, NULL, NULL);
531 
532 	GldiColor couleur_backlabel = {{0., 0., 0., 0.85}};
533 	GldiColor couleur_label = {{1., 1., 1., 1.}};
534 	gboolean bDefaultColors = (cairo_dock_get_integer_key_value (pKeyFile, "Labels", "style", &bFlushConfFileNeeded, 0, NULL, NULL) == 0);
535 	pLabels->iconTextDescription.bUseDefaultColors = bDefaultColors;
536 	if (bDefaultColors)
537 	{
538 		pLabels->iconTextDescription.bOutlined = FALSE;
539 	}
540 	else
541 	{
542 		cairo_dock_get_color_key_value (pKeyFile, "Labels", "text color", &bFlushConfFileNeeded, &pLabels->iconTextDescription.fColorStart, &couleur_label, "Labels", "text color start");
543 
544 		GldiColor couleur_linelabel = {{0., 0., 0., 1}};
545 		cairo_dock_get_color_key_value (pKeyFile, "Labels", "text line color", &bFlushConfFileNeeded, &pLabels->iconTextDescription.fLineColor, &couleur_linelabel, NULL, NULL);
546 
547 		cairo_dock_get_color_key_value (pKeyFile, "Labels", "text bg color", &bFlushConfFileNeeded, &pLabels->iconTextDescription.fBackgroundColor, &couleur_backlabel, "Icons", "text background color");
548 		if (!g_key_file_has_key (pKeyFile, "Labels", "qi same", NULL))  // old params
549 		{
550 			gboolean bUseBackgroundForLabel = cairo_dock_get_boolean_key_value (pKeyFile, "Labels", "background for label", &bFlushConfFileNeeded, FALSE, "Icons", NULL);
551 			if (! bUseBackgroundForLabel)
552 			{
553 				pLabels->iconTextDescription.fBackgroundColor.rgba.alpha = 0;  // ne sera pas dessine.
554 				g_key_file_set_double_list (pKeyFile, "Icons", "text background color", (double*)&pLabels->iconTextDescription.fBackgroundColor.rgba, 4);
555 			}
556 		}
557 	}
558 
559 	pLabels->iconTextDescription.iMargin = cairo_dock_get_integer_key_value (pKeyFile, "Labels", "text margin", &bFlushConfFileNeeded, 4, NULL, NULL);
560 
561 	//\___________________ quick-info
562 	gldi_text_description_copy (&pLabels->quickInfoTextDescription, &pLabels->iconTextDescription);
563 	pLabels->quickInfoTextDescription.iMargin = 1;  // to minimize the surface of the quick-info (0 would be too much).
564 	pLabels->quickInfoTextDescription.iSize = 12;  // no need to update the fd, it will be done when loading the text buffer
565 
566 	gboolean bQuickInfoSameLook = cairo_dock_get_boolean_key_value (pKeyFile, "Labels", "qi same", &bFlushConfFileNeeded, TRUE, NULL, NULL);
567 	if ( !bQuickInfoSameLook)
568 	{
569 		cairo_dock_get_color_key_value (pKeyFile, "Labels", "qi bg color", &bFlushConfFileNeeded, &pLabels->quickInfoTextDescription.fBackgroundColor, &couleur_backlabel, NULL, NULL);
570 		cairo_dock_get_color_key_value (pKeyFile, "Labels", "qi text color", &bFlushConfFileNeeded, &pLabels->quickInfoTextDescription.fColorStart, &couleur_label, NULL, NULL);
571 		pLabels->quickInfoTextDescription.bUseDefaultColors = FALSE;
572 	}
573 
574 	pLabels->iLabelSize = (pLabels->iconTextDescription.iSize != 0 ?
575 		pLabels->iconTextDescription.iSize +
576 		(pLabels->iconTextDescription.bOutlined ? 2 : 0) +
577 		2 * pLabels->iconTextDescription.iMargin +
578 		6  // 2px linewidth + 3px to take into account the y offset of the characters + 1 px to take into account the gap between icon and label
579 		: 0);
580 	cd_debug ("iLabelSize: %d (%d)\n", pLabels->iLabelSize, pLabels->iconTextDescription.iSize);
581 
582 	//\___________________ labels visibility
583 	int iShowLabel = cairo_dock_get_integer_key_value (pKeyFile, "Labels", "show_labels", &bFlushConfFileNeeded, -1, NULL, NULL);
584 	gboolean bShow, bLabelForPointedIconOnly;
585 	if (iShowLabel == -1)  // nouveau parametre
586 	{
587 		if (g_key_file_has_key (pKeyFile, "Labels", "show labels", NULL))
588 			bShow = g_key_file_get_boolean (pKeyFile, "Labels", "show labels", NULL);
589 		else
590 			bShow = TRUE;
591 		bLabelForPointedIconOnly = g_key_file_get_boolean (pKeyFile, "System", "pointed icon only", NULL);
592 		iShowLabel = (! bShow ? 0 : (bLabelForPointedIconOnly ? 1 : 2));
593 		g_key_file_set_integer (pKeyFile, "Labels", "show_labels", iShowLabel);
594 	}
595 	else
596 	{
597 		bShow = (iShowLabel != 0);
598 		bLabelForPointedIconOnly = (iShowLabel == 1);
599 	}
600 	if (! bShow)
601 		pLabels->iconTextDescription.iSize = 0;
602 
603 	pLabels->bLabelForPointedIconOnly = bLabelForPointedIconOnly;
604 
605 	pLabels->fLabelAlphaThreshold = cairo_dock_get_double_key_value (pKeyFile, "Labels", "alpha threshold", &bFlushConfFileNeeded, 10., "System", NULL);
606 	pLabels->fLabelAlphaThreshold = (pLabels->fLabelAlphaThreshold + 10.) / 10.;  // [0;50] -> [1;6]
607 
608 	return bFlushConfFileNeeded;
609 }
610 
611 
612   ////////////////////
613  /// RESET CONFIG ///
614 ////////////////////
615 
reset_config(CairoIconsParam * pIcons)616 static void reset_config (CairoIconsParam *pIcons)
617 {
618 	g_free (pIcons->cSeparatorImage);
619 	g_free (pIcons->cBackgroundImagePath);
620 	g_free (pIcons->cIconTheme);
621 
622 	// labels
623 	CairoIconsParam *pLabels = pIcons;
624 	gldi_text_description_reset (&pLabels->iconTextDescription);
625 	gldi_text_description_reset (&pLabels->quickInfoTextDescription);
626 }
627 
628 
629   ////////////
630  /// LOAD ///
631 ////////////
632 
_cairo_dock_load_icons_background_surface(const gchar * cImagePath)633 static void _cairo_dock_load_icons_background_surface (const gchar *cImagePath)
634 {
635 	cairo_dock_unload_image_buffer (&g_pIconBackgroundBuffer);
636 
637 	int iSizeWidth = myIconsParam.iIconWidth * (1 + myIconsParam.fAmplitude);
638 	int iSizeHeight = myIconsParam.iIconHeight * (1 + myIconsParam.fAmplitude);
639 
640 	cairo_dock_load_image_buffer (&g_pIconBackgroundBuffer,
641 		cImagePath,
642 		iSizeWidth,
643 		iSizeHeight,
644 		CAIRO_DOCK_FILL_SPACE);
645 }
646 
_load_renderer(G_GNUC_UNUSED const gchar * cRenderername,CairoIconContainerRenderer * pRenderer,G_GNUC_UNUSED gpointer data)647 static void _load_renderer (G_GNUC_UNUSED const gchar *cRenderername, CairoIconContainerRenderer *pRenderer, G_GNUC_UNUSED gpointer data)
648 {
649 	if (pRenderer && pRenderer->load)
650 		pRenderer->load ();
651 }
_cairo_dock_load_icon_textures(void)652 static void _cairo_dock_load_icon_textures (void)
653 {
654 	_cairo_dock_load_icons_background_surface (myIconsParam.cBackgroundImagePath);
655 
656 	cairo_dock_foreach_icon_container_renderer ((GHFunc)_load_renderer, NULL);
657 }
_reload_in_desklet(CairoDesklet * pDesklet,G_GNUC_UNUSED gpointer data)658 static void _reload_in_desklet (CairoDesklet *pDesklet, G_GNUC_UNUSED gpointer data)
659 {
660 	if (CAIRO_DOCK_IS_APPLET (pDesklet->pIcon))
661 	{
662 		gldi_object_reload (GLDI_OBJECT(pDesklet->pIcon->pModuleInstance), FALSE);
663 	}
664 }
_on_icon_theme_changed_idle(G_GNUC_UNUSED gpointer data)665 static gboolean _on_icon_theme_changed_idle (G_GNUC_UNUSED gpointer data)
666 {
667 	cd_debug ("");
668 	gldi_desklets_foreach ((GldiDeskletForeachFunc) _reload_in_desklet, NULL);
669 	cairo_dock_reload_buffers_in_all_docks (FALSE);
670 	s_iSidReloadTheme = 0;
671 	return FALSE;
672 }
_on_icon_theme_changed(G_GNUC_UNUSED GtkIconTheme * pIconTheme,G_GNUC_UNUSED gpointer data)673 static void _on_icon_theme_changed (G_GNUC_UNUSED GtkIconTheme *pIconTheme, G_GNUC_UNUSED gpointer data)
674 {
675 	cd_message ("theme has changed");
676 	// Reload the icons in idle, because this signal is triggered directly by 'gtk_icon_theme_set_search_path()'; so we may end reloading an applet in the middle of its work (ex.: Status-Notifier when the watcher terminates)
677 	if (s_iSidReloadTheme == 0)
678 		s_iSidReloadTheme = g_idle_add (_on_icon_theme_changed_idle, NULL);
679 }
_cairo_dock_load_icon_theme(void)680 static void _cairo_dock_load_icon_theme (void)
681 {
682 	g_return_if_fail (s_pIconTheme == NULL);
683 	if (myIconsParam.cIconTheme == NULL  // no icon theme defined => use the default one.
684 	|| strcmp (myIconsParam.cIconTheme, "_Custom Icons_") == 0)  // use custom icons and default theme as fallback
685 	{
686 		s_pIconTheme = gtk_icon_theme_get_default ();
687 		g_signal_connect (G_OBJECT (s_pIconTheme), "changed", G_CALLBACK (_on_icon_theme_changed), NULL);
688 		s_bUseDefaultTheme = TRUE;
689 		s_bUseLocalIcons = (myIconsParam.cIconTheme != NULL);
690 	}
691 	else  // use the given icon theme
692 	{
693 		s_pIconTheme = gtk_icon_theme_new ();
694 		gtk_icon_theme_set_custom_theme (s_pIconTheme, myIconsParam.cIconTheme);
695 		s_bUseLocalIcons = FALSE;
696 		s_bUseDefaultTheme = FALSE;
697 	}
698 }
699 
load(void)700 static void load (void)
701 {
702 	cairo_dock_create_icon_fbo ();
703 
704 	_cairo_dock_load_icon_theme ();
705 
706 	_cairo_dock_load_icon_textures ();
707 }
708 
709 
710   //////////////
711  /// RELOAD ///
712 //////////////
713 
_reload_separators(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,gpointer data)714 static void _reload_separators (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, gpointer data)
715 {
716 	///cairo_dock_remove_automatic_separators (pDock);
717 	gboolean bSeparatorsNeedReload = GPOINTER_TO_INT(data);
718 	gboolean bHasSeparator = FALSE;
719 	Icon *icon;
720 	GList *ic;
721 	for (ic = pDock->icons; ic != NULL; ic = ic->next)
722 	{
723 		icon = ic->data;
724 		if (GLDI_OBJECT_IS_SEPARATOR_ICON (icon))
725 		{
726 			if (bSeparatorsNeedReload)
727 			{
728 				cairo_dock_icon_set_requested_size (icon, 0, 0);
729 				cairo_dock_set_icon_size_in_dock (pDock, icon);
730 			}
731 			cairo_dock_load_icon_image (icon, icon->pContainer);
732 			bHasSeparator = TRUE;
733 		}
734 	}
735 	if (bHasSeparator)
736 	{
737 		if (bSeparatorsNeedReload)
738 			cairo_dock_update_dock_size (pDock);  // either to trigger the loading of the separator rendering, or to take into account the change in the separators size
739 		gtk_widget_queue_draw (pDock->container.pWidget);  // in any case, refresh the drawing
740 	}
741 }
742 
_calculate_icons(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)743 static void _calculate_icons (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
744 {
745 	cairo_dock_calculate_dock_icons (pDock);
746 }
747 
_cairo_dock_resize_one_dock(G_GNUC_UNUSED const gchar * cDockName,CairoDock * pDock,G_GNUC_UNUSED gpointer data)748 static void _cairo_dock_resize_one_dock (G_GNUC_UNUSED const gchar *cDockName, CairoDock *pDock, G_GNUC_UNUSED gpointer data)
749 {
750 	cairo_dock_update_dock_size (pDock);
751 }
752 
_reload_one_label(Icon * pIcon,G_GNUC_UNUSED gpointer data)753 static void _reload_one_label (Icon *pIcon, G_GNUC_UNUSED gpointer data)
754 {
755 	cairo_dock_load_icon_text (pIcon);
756 	cairo_dock_load_icon_quickinfo (pIcon);
757 }
758 
reload(CairoIconsParam * pPrevIcons,CairoIconsParam * pIcons)759 static void reload (CairoIconsParam *pPrevIcons, CairoIconsParam *pIcons)
760 {
761 	// if the separator size has changed, we need to re-allocate it, reload the image, and update the dock size
762 	// if the separator rendering has changed (type or color), we need to load the new rendering, which is done by the View (during the compute_size)
763 	// otherwise, we just need to redraw
764 	gboolean bSeparatorsNeedReload = (pPrevIcons->iSeparatorWidth != pIcons->iSeparatorWidth
765 		|| pPrevIcons->iSeparatorHeight != pIcons->iSeparatorHeight
766 		|| pPrevIcons->iSeparatorType != pIcons->iSeparatorType
767 		|| gldi_color_compare (&pPrevIcons->fSeparatorColor, &pIcons->fSeparatorColor));  // same if color has changed (for the flat separator rendering)
768 	gboolean bSeparatorNeedRedraw = (g_strcmp0 (pPrevIcons->cSeparatorImage, pIcons->cSeparatorImage) != 0
769 		|| pPrevIcons->bRevolveSeparator != pIcons->bRevolveSeparator);
770 
771 	if (bSeparatorsNeedReload || bSeparatorNeedRedraw)
772 	{
773 		gldi_docks_foreach ((GHFunc)_reload_separators, GINT_TO_POINTER(bSeparatorsNeedReload));
774 	}
775 
776 	gboolean bThemeChanged = (g_strcmp0 (pIcons->cIconTheme, pPrevIcons->cIconTheme) != 0);
777 	if (bThemeChanged)
778 	{
779 		_cairo_dock_unload_icon_theme ();
780 
781 		_cairo_dock_load_icon_theme ();
782 	}
783 
784 	gboolean bIconBackgroundImagesChanged = FALSE;
785 	// if background images are different, reload them and trigger the reload of all icons
786 	if (g_strcmp0 (pPrevIcons->cBackgroundImagePath, pIcons->cBackgroundImagePath) != 0
787 	|| pPrevIcons->fAmplitude != pIcons->fAmplitude)
788 	{
789 		bIconBackgroundImagesChanged = TRUE;
790 		_cairo_dock_load_icons_background_surface (pIcons->cBackgroundImagePath);
791 	}
792 
793 	///cairo_dock_create_icon_pbuffer ();
794 	cairo_dock_destroy_icon_fbo ();
795 	cairo_dock_create_icon_fbo ();
796 
797 	if (pPrevIcons->iIconWidth != pIcons->iIconWidth ||
798 		pPrevIcons->iIconHeight != pIcons->iIconHeight ||
799 		pPrevIcons->iSeparatorWidth != pIcons->iSeparatorWidth ||
800 		pPrevIcons->iSeparatorHeight != pIcons->iSeparatorHeight ||
801 		pPrevIcons->fAmplitude != pIcons->fAmplitude ||
802 		(!g_bUseOpenGL && pPrevIcons->fReflectHeightRatio != pIcons->fReflectHeightRatio) ||
803 		(!g_bUseOpenGL && pPrevIcons->fAlbedo != pIcons->fAlbedo) ||
804 		bThemeChanged ||
805 		bIconBackgroundImagesChanged)  // oui on ne fait pas dans la finesse.
806 	{
807 		cairo_dock_reload_buffers_in_all_docks (TRUE);
808 	}
809 
810 	if (pPrevIcons->iIconWidth != pIcons->iIconWidth ||
811 		pPrevIcons->iIconHeight != pIcons->iIconHeight ||
812 		pPrevIcons->fAmplitude != pIcons->fAmplitude)
813 	{
814 		_cairo_dock_unload_icon_textures ();
815 		myIndicatorsMgr.unload ();
816 		_cairo_dock_load_icon_textures ();
817 		myIndicatorsMgr.load ();
818 	}
819 
820 	cairo_dock_set_all_views_to_default (0);  // met a jour la taille (decorations incluses) de tous les docks; le chargement des separateurs plats se fait dans le calcul de max dock size.
821 	gldi_docks_foreach ((GHFunc)_calculate_icons, NULL);
822 	gldi_docks_redraw_all_root ();
823 
824 	// labels
825 	CairoIconsParam *pLabels = pIcons;
826 	CairoIconsParam *pPrevLabels = pPrevIcons;
827 	gldi_icons_foreach ((GldiIconFunc) _reload_one_label, NULL);
828 
829 	if (pPrevLabels->iLabelSize != pLabels->iLabelSize)
830 	{
831 		gldi_docks_foreach ((GHFunc) _cairo_dock_resize_one_dock, NULL);
832 	}
833 }
834 
835 
836   //////////////
837  /// UNLOAD ///
838 //////////////
839 
_unload_renderer(G_GNUC_UNUSED const gchar * cRenderername,CairoIconContainerRenderer * pRenderer,G_GNUC_UNUSED gpointer data)840 static void _unload_renderer (G_GNUC_UNUSED const gchar *cRenderername, CairoIconContainerRenderer *pRenderer, G_GNUC_UNUSED gpointer data)
841 {
842 	if (pRenderer && pRenderer->unload)
843 		pRenderer->unload ();
844 }
_cairo_dock_unload_icon_textures(void)845 static void _cairo_dock_unload_icon_textures (void)
846 {
847 	cairo_dock_unload_image_buffer (&g_pIconBackgroundBuffer);
848 
849 	cairo_dock_foreach_icon_container_renderer ((GHFunc)_unload_renderer, NULL);
850 }
_cairo_dock_unload_icon_theme(void)851 static void _cairo_dock_unload_icon_theme (void)
852 {
853 	if (s_bUseDefaultTheme)
854 		g_signal_handlers_disconnect_by_func (G_OBJECT(s_pIconTheme), G_CALLBACK(_on_icon_theme_changed), NULL);
855 	else
856 		g_object_unref (s_pIconTheme);
857 	s_pIconTheme = NULL;
858 }
unload(void)859 static void unload (void)
860 {
861 	_cairo_dock_unload_icon_textures ();
862 
863 	cairo_dock_destroy_icon_fbo ();
864 
865 	_cairo_dock_delete_floating_icons ();
866 
867 	if (g_pGradationTexture[0] != 0)
868 	{
869 		_cairo_dock_delete_texture (g_pGradationTexture[0]);
870 		g_pGradationTexture[0] = 0;
871 	}
872 	if (g_pGradationTexture[1] != 0)
873 	{
874 		_cairo_dock_delete_texture (g_pGradationTexture[1]);
875 		g_pGradationTexture[1] = 0;
876 	}
877 
878 	_cairo_dock_unload_icon_theme ();
879 }
880 
881 
882   ////////////
883  /// INIT ///
884 ////////////
885 
on_style_changed(G_GNUC_UNUSED gpointer data)886 static gboolean on_style_changed (G_GNUC_UNUSED gpointer data)
887 {
888 	cd_debug ("Icons: style changed to %d", myIconsParam.iconTextDescription.bUseDefaultColors);
889 
890 	if (myIconsParam.iconTextDescription.cFont == NULL)  // default font -> reload our text description
891 	{
892 		gldi_text_description_set_font (&myIconsParam.iconTextDescription, NULL);
893 		myIconsParam.quickInfoTextDescription.fd = pango_font_description_copy (myIconsParam.iconTextDescription.fd);
894 	}
895 
896 	if (myIconsParam.iconTextDescription.bUseDefaultColors || myIconsParam.iconTextDescription.cFont == NULL)  // reload labels and quick-info
897 	{
898 		cd_debug ("reload labels...");
899 		gldi_icons_foreach ((GldiIconFunc) _reload_one_label, NULL);
900 	}
901 
902 	// if label size changed, reload docks views
903 	int iLabelSize = (myIconsParam.iconTextDescription.iSize != 0 ?
904 		myIconsParam.iconTextDescription.iSize +
905 		(myIconsParam.iconTextDescription.bOutlined ? 2 : 0) +
906 		2 * myIconsParam.iconTextDescription.iMargin +
907 		6  // 2px linewidth + 3px to take into account the y offset of the characters + 1 px to take into account the gap between icon and label
908 		: 0);
909 	if (iLabelSize != myIconsParam.iLabelSize)
910 	{
911 		cd_debug ("myIconsParam.iLabelSize: %d -> %d (%d)", myIconsParam.iLabelSize, iLabelSize, myIconsParam.iconTextDescription.iSize);
912 		myIconsParam.iLabelSize = iLabelSize;
913 		gldi_docks_foreach ((GHFunc) _cairo_dock_resize_one_dock, NULL);
914 	}
915 	return GLDI_NOTIFICATION_LET_PASS;
916 }
917 
init(void)918 static void init (void)
919 {
920 	gldi_object_register_notification (&myDesktopMgr,
921 		NOTIFICATION_DESKTOP_CHANGED,
922 		(GldiNotificationFunc) _on_change_current_desktop_viewport_notification,
923 		GLDI_RUN_AFTER, NULL);
924 	gldi_object_register_notification (&myIconObjectMgr,
925 		NOTIFICATION_RENDER_ICON,
926 		(GldiNotificationFunc) cairo_dock_render_icon_notification,
927 		GLDI_RUN_FIRST, NULL);
928 	gldi_object_register_notification (&myStyleMgr,
929 		NOTIFICATION_STYLE_CHANGED,
930 		(GldiNotificationFunc) on_style_changed,
931 		GLDI_RUN_AFTER, NULL);
932 }
933 
934   ///////////////
935  /// MANAGER ///
936 ///////////////
937 
_load_image(Icon * icon)938 static void _load_image (Icon *icon)
939 {
940 	int iWidth = cairo_dock_icon_get_allocated_width (icon);
941 	int iHeight = cairo_dock_icon_get_allocated_height (icon);
942 	cairo_surface_t *pSurface = NULL;
943 
944 	if (icon->cFileName)
945 	{
946 		gchar *cIconPath = cairo_dock_search_icon_s_path (icon->cFileName, MAX (iWidth, iHeight));
947 		if (cIconPath != NULL && *cIconPath != '\0')
948 			pSurface = cairo_dock_create_surface_from_image_simple (cIconPath,
949 				iWidth,
950 				iHeight);
951 		g_free (cIconPath);
952 	}
953 	cairo_dock_load_image_buffer_from_surface (&icon->image, pSurface, iWidth, iHeight);
954 }
init_object(GldiObject * obj,G_GNUC_UNUSED gpointer attr)955 static void init_object (GldiObject *obj, G_GNUC_UNUSED gpointer attr)
956 {
957 	Icon *icon = (Icon*)obj;
958 	icon->iface.load_image = _load_image;
959 }
960 
reset_object(GldiObject * obj)961 static void reset_object (GldiObject *obj)
962 {
963 	Icon *icon = (Icon*)obj;
964 	cd_debug ("%s (%s , %s, %s)", __func__, icon->cName, icon->cClass, gldi_object_get_type(icon));
965 
966 	GldiContainer *pContainer = cairo_dock_get_icon_container (icon);
967 	if (pContainer != NULL)
968 	{
969 		gldi_icon_detach (icon);
970 	}
971 
972 	if (icon->cClass != NULL && (GLDI_OBJECT_IS_LAUNCHER_ICON (icon) || GLDI_OBJECT_IS_APPLET_ICON (icon)))  // c'est un inhibiteur.
973 		cairo_dock_deinhibite_class (icon->cClass, icon);  // unset the appli if it had any
974 
975 	gldi_object_notify (icon, NOTIFICATION_STOP_ICON, icon);
976 	cairo_dock_remove_transition_on_icon (icon);
977 	cairo_dock_remove_data_renderer_on_icon (icon);
978 
979 	if (icon->pSubDock != NULL)
980 		gldi_object_unref (GLDI_OBJECT(icon->pSubDock));
981 
982 	if (icon->iSpecificDesktop != 0)
983 	{
984 		s_iNbNonStickyLaunchers --;
985 		s_pFloatingIconsList = g_list_remove(s_pFloatingIconsList, icon);
986 	}
987 
988 	if (icon->iSidRedrawSubdockContent != 0)
989 		g_source_remove (icon->iSidRedrawSubdockContent);
990 	if (icon->iSidLoadImage != 0)  // remove timers after any function that could trigger one (for instance, cairo_dock_deinhibite_class calls cairo_dock_trigger_load_icon_buffers)
991 		g_source_remove (icon->iSidLoadImage);
992 	if (icon->iSidDoubleClickDelay != 0)
993 		g_source_remove (icon->iSidDoubleClickDelay);
994 
995 	// free data
996 	g_free (icon->cDesktopFileName);
997 	g_free (icon->cFileName);
998 	g_free (icon->cName);
999 	g_free (icon->cInitialName);
1000 	g_free (icon->cCommand);
1001 	g_free (icon->cWorkingDirectory);
1002 	g_free (icon->cBaseURI);
1003 	g_free (icon->cParentDockName);  // on ne liberera pas le sous-dock ici sous peine de se mordre la queue, donc il faut l'avoir fait avant.
1004 	g_free (icon->cClass);
1005 	g_free (icon->cWmClass);
1006 	g_free (icon->cQuickInfo);
1007 	///g_free (icon->cLastAttentionDemand);
1008 	g_free (icon->pHiddenBgColor);
1009 	if (icon->pMimeTypes)
1010 		g_strfreev (icon->pMimeTypes);
1011 
1012 	cairo_dock_unload_image_buffer (&icon->image);
1013 
1014 	cairo_dock_unload_image_buffer (&icon->label);
1015 
1016 	cairo_dock_destroy_icon_overlays (icon);
1017 }
1018 
gldi_register_icons_manager(void)1019 void gldi_register_icons_manager (void)
1020 {
1021 	// Manager
1022 	memset (&myIconsMgr, 0, sizeof (GldiManager));
1023 	gldi_object_init (GLDI_OBJECT(&myIconsMgr), &myManagerObjectMgr, NULL);
1024 	myIconsMgr.cModuleName  = "Icons";
1025 	// interface
1026 	myIconsMgr.init         = init;
1027 	myIconsMgr.load         = load;
1028 	myIconsMgr.unload       = unload;
1029 	myIconsMgr.reload       = (GldiManagerReloadFunc)reload;
1030 	myIconsMgr.get_config   = (GldiManagerGetConfigFunc)get_config;
1031 	myIconsMgr.reset_config = (GldiManagerResetConfigFunc)reset_config;
1032 	// Config
1033 	memset (&myIconsParam, 0, sizeof (CairoIconsParam));
1034 	myIconsMgr.pConfig = (GldiManagerConfigPtr)&myIconsParam;
1035 	myIconsMgr.iSizeOfConfig = sizeof (CairoIconsParam);
1036 	// data
1037 	memset (&g_pIconBackgroundBuffer, 0, sizeof (CairoDockImageBuffer));
1038 	myIconsMgr.pData = (GldiManagerDataPtr)NULL;
1039 	myIconsMgr.iSizeOfData = 0;
1040 
1041 	// ObjectManager
1042 	memset (&myIconObjectMgr, 0, sizeof (GldiObjectManager));
1043 	myIconObjectMgr.cName        = "Icon";
1044 	myIconObjectMgr.iObjectSize  = sizeof (Icon);
1045 	// interface
1046 	myIconObjectMgr.init_object  = init_object;
1047 	myIconObjectMgr.reset_object = reset_object;
1048 	// signals
1049 	gldi_object_install_notifications (&myIconObjectMgr, NB_NOTIFICATIONS_ICON);
1050 }
1051