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 "cairo-dock-icon-facility.h"  // gldi_icon_set_name
21 #include "cairo-dock-dialog-factory.h"
22 #include "cairo-dock-animations.h"
23 #include "cairo-dock-surface-factory.h"
24 #include "cairo-dock-applications-manager.h"
25 #include "cairo-dock-launcher-manager.h"
26 #include "cairo-dock-separator-manager.h"
27 #include "cairo-dock-applet-manager.h"
28 #include "cairo-dock-stack-icon-manager.h"
29 #include "cairo-dock-windows-manager.h"
30 #include "cairo-dock-log.h"
31 #include "cairo-dock-dock-manager.h"
32 #include "cairo-dock-class-manager.h"
33 #include "cairo-dock-dock-facility.h"  // cairo_dock_update_dock_size
34 #include "cairo-dock-desktop-manager.h"
35 #include "cairo-dock-indicator-manager.h"  // myIndicatorsParam.bUseClassIndic
36 #include "cairo-dock-class-icon-manager.h"  // gldi_class_icon_new
37 #include "cairo-dock-utils.h"  // cairo_dock_launch_command_full
38 #include "cairo-dock-application-facility.h"
39 
40 extern CairoDock *g_pMainDock;
41 extern CairoDockHidingEffect *g_pHidingBackend;  // cairo_dock_is_hidden
42 extern GldiContainer *g_pPrimaryContainer;
43 
_gldi_appli_icon_demands_attention(Icon * icon,CairoDock * pDock,gboolean bForceDemand,Icon * pHiddenIcon)44 static void _gldi_appli_icon_demands_attention (Icon *icon, CairoDock *pDock, gboolean bForceDemand, Icon *pHiddenIcon)
45 {
46 	cd_debug ("%s (%s, force:%d)", __func__, icon->cName, bForceDemand);
47 	if (CAIRO_DOCK_IS_APPLET (icon))  // on considere qu'une applet prenant le controle d'une icone d'appli dispose de bien meilleurs moyens pour interagir avec l'appli que la barre des taches.
48 		return ;
49 	//\____________________ On montre le dialogue.
50 	if (myTaskbarParam.bDemandsAttentionWithDialog)
51 	{
52 		CairoDialog *pDialog;
53 		if (pHiddenIcon == NULL)
54 		{
55 			pDialog = gldi_dialog_show_temporary_with_icon (icon->cName, icon, CAIRO_CONTAINER (pDock), 1000*myTaskbarParam.iDialogDuration, "same icon");
56 		}
57 		else
58 		{
59 			pDialog = gldi_dialog_show_temporary (pHiddenIcon->cName, icon, CAIRO_CONTAINER (pDock), 1000*myTaskbarParam.iDialogDuration); // mieux vaut montrer pas d'icone dans le dialogue que de montrer une icone qui n'a pas de rapport avec l'appli demandant l'attention.
60 			g_return_if_fail (pDialog != NULL);
61 			gldi_dialog_set_icon_surface (pDialog, pHiddenIcon->image.pSurface, pDialog->iIconSize);
62 		}
63 		if (pDialog && bForceDemand)
64 		{
65 			cd_debug ("force dock and dialog on top");
66 			if (pDock->iRefCount == 0 && pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && pDock->bIsBelow)
67 				cairo_dock_pop_up (pDock);
68 			gtk_window_set_keep_above (GTK_WINDOW (pDialog->container.pWidget), TRUE);
69 			gtk_window_set_type_hint (GTK_WINDOW (pDialog->container.pWidget), GDK_WINDOW_TYPE_HINT_DOCK);  // pour passer devant les fenetres plein ecran; depend du WM.
70 		}
71 	}
72 	//\____________________ On montre l'icone avec une animation.
73 	if (myTaskbarParam.cAnimationOnDemandsAttention && ! pHiddenIcon)  // on ne l'anime pas si elle n'est pas dans un dock.
74 	{
75 		if (pDock->iRefCount == 0)
76 		{
77 			if (bForceDemand)
78 			{
79 				if (pDock->iRefCount == 0 && pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && pDock->bIsBelow)
80 					cairo_dock_pop_up (pDock);
81 			}
82 		}
83 		/**else if (bForceDemand)
84 		{
85 			cd_debug ("force sub-dock to raise\n");
86 			CairoDock *pParentDock = NULL;
87 			Icon *pPointedIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pParentDock);
88 			if (pParentDock)
89 				cairo_dock_show_subdock (pPointedIcon, pParentDock);
90 		}*/
91 		gldi_icon_request_attention (icon, myTaskbarParam.cAnimationOnDemandsAttention, 10000);  // animation de 2-3 heures.
92 	}
93 }
gldi_appli_icon_demands_attention(Icon * icon)94 void gldi_appli_icon_demands_attention (Icon *icon)
95 {
96 	cd_debug ("%s (%s, %p)", __func__, icon->cName, cairo_dock_get_icon_container(icon));
97 	if (icon->pAppli == gldi_windows_get_active())  // apparemment ce cas existe, et conduit a ne pas pouvoir stopper l'animation de demande d'attention facilement.
98 	{
99 		cd_message ("cette fenetre a deja le focus, elle ne peut demander l'attention en plus.");
100 		return ;
101 	}
102 
103 	gboolean bForceDemand = (myTaskbarParam.cForceDemandsAttention && icon->cClass && g_strstr_len (myTaskbarParam.cForceDemandsAttention, -1, icon->cClass));
104 	CairoDock *pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (icon));
105 	if (pParentDock == NULL)  // appli inhibee ou non affichee.
106 	{
107 		Icon *pInhibitorIcon = cairo_dock_get_inhibitor (icon, TRUE);  // on cherche son inhibiteur dans un dock.
108 		if (pInhibitorIcon != NULL)  // appli inhibee.
109 		{
110 			pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (pInhibitorIcon));
111 			if (pParentDock != NULL)  // if the inhibitor is hidden (detached), there is no way to remember what should be its animation, so just forget it (we could fix it when inserting the icon back into a container, by checking if its appli is demanding the attention)
112 				_gldi_appli_icon_demands_attention (pInhibitorIcon, pParentDock, bForceDemand, NULL);
113 		}
114 		else if (bForceDemand)  // appli pas affichee, mais on veut tout de meme etre notifie.
115 		{
116 			Icon *pOneIcon = gldi_icons_get_any_without_dialog ();  // on prend une icone dans le main dock.
117 			if (pOneIcon != NULL)
118 				_gldi_appli_icon_demands_attention (pOneIcon, g_pMainDock, bForceDemand, icon);
119 		}
120 	}
121 	else  // appli dans un dock.
122 		_gldi_appli_icon_demands_attention (icon, pParentDock, bForceDemand, NULL);
123 }
124 
_gldi_appli_icon_stop_demanding_attention(Icon * icon,CairoDock * pDock)125 static void _gldi_appli_icon_stop_demanding_attention (Icon *icon, CairoDock *pDock)
126 {
127 	if (CAIRO_DOCK_IS_APPLET (icon))  // cf remarque plus haut.
128 		return ;
129 	if (myTaskbarParam.bDemandsAttentionWithDialog)
130 		gldi_dialogs_remove_on_icon (icon);
131 	if (myTaskbarParam.cAnimationOnDemandsAttention)
132 	{
133 		gldi_icon_stop_attention (icon);  // arrete l'animation precedemment lancee par la demande.
134 		gtk_widget_queue_draw (pDock->container.pWidget);  // optimisation possible : ne redessiner que l'icone en tenant compte de la zone de sa derniere animation (pulse ou rebond).
135 	}
136 	if (pDock->iRefCount == 0 && pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && ! pDock->bIsBelow && ! pDock->container.bInside)
137 		cairo_dock_pop_down (pDock);
138 }
gldi_appli_icon_stop_demanding_attention(Icon * icon)139 void gldi_appli_icon_stop_demanding_attention (Icon *icon)
140 {
141 	CairoDock *pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (icon));
142 	if (pParentDock == NULL)  // inhibited
143 	{
144 		Icon *pInhibitorIcon = cairo_dock_get_inhibitor (icon, TRUE);
145 		if (pInhibitorIcon != NULL)
146 		{
147 			pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (pInhibitorIcon));
148 			if (pParentDock != NULL)
149 				_gldi_appli_icon_stop_demanding_attention (pInhibitorIcon, pParentDock);
150 		}
151 	}
152 	else
153 		_gldi_appli_icon_stop_demanding_attention (icon, pParentDock);
154 }
155 
156 
gldi_appli_icon_animate_on_active(Icon * icon,CairoDock * pParentDock)157 void gldi_appli_icon_animate_on_active (Icon *icon, CairoDock *pParentDock)
158 {
159 	g_return_if_fail (pParentDock != NULL);
160 	if (! cairo_dock_icon_is_being_inserted_or_removed (icon))  // sinon on laisse l'animation actuelle.
161 	{
162 		if (myTaskbarParam.cAnimationOnActiveWindow)
163 		{
164 			if (cairo_dock_animation_will_be_visible (pParentDock) && icon->iAnimationState == CAIRO_DOCK_STATE_REST)
165 				gldi_icon_request_animation (icon, myTaskbarParam.cAnimationOnActiveWindow, 1);
166 		}
167 		else
168 		{
169 			cairo_dock_redraw_icon (icon);  // Si pas d'animation, on le fait pour redessiner l'indicateur.
170 		}
171 		if (pParentDock->iRefCount != 0)  // l'icone est dans un sous-dock, on veut que l'indicateur soit aussi dessine sur l'icone pointant sur ce sous-dock.
172 		{
173 			CairoDock *pMainDock = NULL;
174 			Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pParentDock, &pMainDock);
175 			if (pPointingIcon && pMainDock)
176 			{
177 				cairo_dock_redraw_icon (pPointingIcon);  // on se contente de redessiner cette icone sans l'animer. Une facon comme une autre de differencier ces 2 cas.
178 			}
179 		}
180 	}
181 }
182 
183 
184 // this function is used when we have an appli that is not inhibited. we can place it either in its subdock or in a dock next to an inhibitor or in the main dock amongst the other applis
_get_parent_dock_for_appli(Icon * icon,CairoDock * pMainDock)185 static CairoDock *_get_parent_dock_for_appli (Icon *icon, CairoDock *pMainDock)
186 {
187 	cd_message ("%s (%s)", __func__, icon->cName);
188 	CairoDock *pParentDock = pMainDock;
189 	if (CAIRO_DOCK_IS_APPLI (icon) && myTaskbarParam.bGroupAppliByClass && icon->cClass != NULL && ! cairo_dock_class_is_expanded (icon->cClass))  // if this is a valid appli and we want to group the classes.
190 	{
191 		Icon *pSameClassIcon = cairo_dock_get_classmate (icon);  // un inhibiteur dans un dock avec appli ou subdock OU une appli de meme classe dans un dock != class-sub-dock.
192 		if (pSameClassIcon == NULL)  // aucun classmate => elle va dans son class sub-dock ou dans le main dock.
193 		{
194 			cd_message ("  no classmate for %s", icon->cClass);
195 			pParentDock = cairo_dock_get_class_subdock (icon->cClass);
196 			if (pParentDock == NULL)  // no class sub-dock => go to main dock
197 				pParentDock = pMainDock;
198 		}
199 		else  // on la met dans le sous-dock de sa classe.
200 		{
201 			//\____________ create the class sub-dock if necessary
202 			pParentDock = cairo_dock_get_class_subdock (icon->cClass);
203 			if (pParentDock == NULL)  // no class sub-dock yet -> create it, and we'll link it to either pSameClassIcon or a class-icon.
204 			{
205 				cd_message ("  creation du dock pour la classe %s", icon->cClass);
206 				pMainDock = CAIRO_DOCK(cairo_dock_get_icon_container (pSameClassIcon));
207 				pParentDock = cairo_dock_create_class_subdock (icon->cClass, pMainDock);
208 			}
209 			else
210 				cd_message ("  sous-dock de la classe %s existant", icon->cClass);
211 
212 			//\____________ link this sub-dock to the inhibitor, or to a fake appli icon.
213 			if (GLDI_OBJECT_IS_LAUNCHER_ICON (pSameClassIcon) || GLDI_OBJECT_IS_APPLET_ICON (pSameClassIcon))  // it's an inhibitor
214 			{
215 				if (pSameClassIcon->pAppli != NULL)  // actuellement l'inhibiteur inhibe 1 seule appli.
216 				{
217 					cd_debug ("actuellement l'inhibiteur inhibe 1 seule appli");
218 					Icon *pInhibitedIcon = cairo_dock_get_appli_icon (pSameClassIcon->pAppli);  // get the currently inhibited appli-icon; it will go into the class sub-dock with 'icon'
219 					gldi_icon_unset_appli (pSameClassIcon);  // on lui laisse par contre l'indicateur.
220 					if (pSameClassIcon->pSubDock == NULL)  // paranoia
221 					{
222 						if (pSameClassIcon->cInitialName != NULL)
223 							gldi_icon_set_name (pSameClassIcon, pSameClassIcon->cInitialName);  // on lui remet son nom de lanceur.
224 
225 						pSameClassIcon->pSubDock = pParentDock;
226 
227 						cairo_dock_redraw_icon (pSameClassIcon);  // on la redessine car elle prend l'indicateur de classe.
228 					}
229 					else
230 						cd_warning ("this launcher (%s) already has a subdock !", pSameClassIcon->cName);
231 
232 					if (pInhibitedIcon != NULL)  // paranoia
233 					{
234 						cd_debug (" on insere %s dans le dock de la classe", pInhibitedIcon->cName);
235 						gldi_icon_insert_in_container (pInhibitedIcon, CAIRO_CONTAINER(pParentDock), ! CAIRO_DOCK_ANIMATE_ICON);
236 					}
237 					else
238 						cd_warning ("couldn't get the appli-icon for '%s' !", pSameClassIcon->cName);
239 				}
240 				else if (pSameClassIcon->pSubDock != pParentDock)
241 					cd_warning ("this inhibitor doesn't hold the class sub-dock !");
242 			}
243 			else  // it's an appli in a dock (not the class sub-dock)
244 			{
245 				//\______________ make a class-icon that will hold the class sub-dock
246 				cd_debug (" on cree un fake...");
247 				CairoDock *pClassMateParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (pSameClassIcon));  // c'est en fait le main dock.
248 				if (!pClassMateParentDock)  // if not yet in its dock (or hidden)
249 					pClassMateParentDock = gldi_dock_get (pSameClassIcon->cParentDockName);
250 				Icon *pFakeClassIcon = gldi_class_icon_new (pSameClassIcon, pParentDock);
251 
252 				//\______________ detach the classmate, and put it into the class sub-dock with 'icon'
253 				cd_debug (" on detache %s pour la passer dans le sous-dock de sa classe", pSameClassIcon->cName);
254 				gldi_icon_detach (pSameClassIcon);
255 				gldi_icon_insert_in_container (pSameClassIcon, CAIRO_CONTAINER(pParentDock), ! CAIRO_DOCK_ANIMATE_ICON);
256 
257 				//\______________ put the class-icon in place of the clasmate
258 				cd_debug (" on lui substitue le fake");
259 				gldi_icon_insert_in_container (pFakeClassIcon, CAIRO_CONTAINER(pClassMateParentDock), ! CAIRO_DOCK_ANIMATE_ICON);
260 
261 				if (!myIndicatorsParam.bUseClassIndic)
262 					cairo_dock_trigger_redraw_subdock_content_on_icon (pFakeClassIcon);
263 			}
264 		}
265 	}
266 	else  /// TODO: look for an inhibitor or a classmate to go in its dock (it's not necessarily the main dock) ...
267 	{
268 		pParentDock = pMainDock;
269 	}
270 	return pParentDock;
271 }
272 
gldi_appli_icon_insert_in_dock(Icon * icon,CairoDock * pMainDock,gboolean bAnimate)273 CairoDock *gldi_appli_icon_insert_in_dock (Icon *icon, CairoDock *pMainDock, gboolean bAnimate)
274 {
275 	if (! myTaskbarParam.bShowAppli)
276 		return NULL;
277 	cd_message ("%s (%s, %p)", __func__, icon->cName, icon->pAppli);
278 
279 	if (myTaskbarParam.bAppliOnCurrentDesktopOnly && ! gldi_window_is_on_current_desktop (icon->pAppli))
280 		return NULL;
281 
282 	//\_________________ On gere ses eventuels inhibiteurs.
283 	if (myTaskbarParam.bMixLauncherAppli && cairo_dock_prevent_inhibited_class (icon))
284 	{
285 		cd_message (" -> se fait inhiber");
286 		return NULL;
287 	}
288 
289 	//\_________________ On gere le filtre 'applis minimisees seulement'.
290 	if (!icon->pAppli->bIsHidden && myTaskbarParam.bHideVisibleApplis)
291 	{
292 		gldi_appli_reserve_geometry_for_window_manager (icon->pAppli, icon, pMainDock);  // on reserve la position de l'icone dans le dock pour que l'effet de minimisation puisse viser la bonne position avant que l'icone ne soit effectivement dans le dock.
293 		return NULL;
294 	}
295 
296 	//\_________________ On determine dans quel dock l'inserer (cree au besoin).
297 	CairoDock *pParentDock = _get_parent_dock_for_appli (icon, pMainDock);
298 	g_return_val_if_fail (pParentDock != NULL, NULL);
299 
300 	//\_________________ On l'insere dans son dock parent en animant ce dernier eventuellement.
301 	if (myTaskbarParam.bMixLauncherAppli && pParentDock != cairo_dock_get_class_subdock (icon->cClass))  // this appli is amongst the launchers in the main dock
302 	{
303 		cairo_dock_set_class_order_in_dock (icon, pParentDock);
304 	}
305 	else  // this appli is either in a different group or in the class sub-dock
306 	{
307 		cairo_dock_set_class_order_amongst_applis (icon, pParentDock);
308 	}
309 	gldi_icon_insert_in_container (icon, CAIRO_CONTAINER(pParentDock), bAnimate);
310 	cd_message (" insertion de %s complete (%.2f %.2fx%.2f) dans %s", icon->cName, icon->fInsertRemoveFactor, icon->fWidth, icon->fHeight, gldi_dock_get_name(pParentDock));
311 
312 	if (bAnimate && cairo_dock_animation_will_be_visible (pParentDock))
313 	{
314 		cairo_dock_launch_animation (CAIRO_CONTAINER (pParentDock));
315 	}
316 	else
317 	{
318 		icon->fInsertRemoveFactor = 0;
319 		icon->fScale = 1.;
320 	}
321 
322 	return pParentDock;
323 }
324 
gldi_appli_icon_detach(Icon * pIcon)325 CairoDock * gldi_appli_icon_detach (Icon *pIcon)
326 {
327 	cd_debug ("%s (%s)", __func__, pIcon->cName);
328 	CairoDock *pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (pIcon));
329 	if (! GLDI_OBJECT_IS_DOCK (pParentDock))
330 		return NULL;
331 
332 	gldi_icon_detach (pIcon);
333 
334 	if (pIcon->cClass != NULL && pParentDock == cairo_dock_get_class_subdock (pIcon->cClass))  // is in the sub-dock class -> check if we must destroy it.
335 	{
336 		gboolean bEmptyClassSubDock = cairo_dock_check_class_subdock_is_empty (pParentDock, pIcon->cClass);
337 		if (bEmptyClassSubDock)  // has been destroyed.
338 			return NULL;
339 	}
340 	return pParentDock;
341 }
342 
343 #define x_icon_geometry(icon, pDock) (pDock->container.iWindowPositionX + icon->fXAtRest + (pDock->container.iWidth - pDock->iActiveWidth) * pDock->fAlign + (pDock->iActiveWidth - pDock->fFlatDockWidth) / 2)
344 ///#define y_icon_geometry(icon, pDock) (pDock->container.iWindowPositionY + icon->fDrawY - icon->fHeight * myIconsParam.fAmplitude * pDock->fMagnitudeMax)
345 #define y_icon_geometry(icon, pDock) (pDock->container.iWindowPositionY + icon->fDrawY)
gldi_appli_icon_set_geometry_for_window_manager(Icon * icon,CairoDock * pDock)346 void gldi_appli_icon_set_geometry_for_window_manager (Icon *icon, CairoDock *pDock)
347 {
348 	//g_print ("%s (%s)\n", __func__, icon->cName);
349 	int iX, iY, iWidth, iHeight;
350 	iX = x_icon_geometry (icon, pDock);
351 	iY = y_icon_geometry (icon, pDock);  // il faudrait un fYAtRest ...
352 	//g_print (" -> %d;%d (%.2f)\n", iX - pDock->container.iWindowPositionX, iY - pDock->container.iWindowPositionY, icon->fXAtRest);
353 	iWidth = icon->fWidth;
354 	int dh = (icon->image.iWidth - icon->fHeight);
355 	iHeight = icon->fHeight + 2 * dh;  // on elargit en haut et en bas, pour gerer les cas ou l'icone grossirait vers le haut ou vers le bas.
356 
357 	if (pDock->container.bIsHorizontal)
358 		gldi_window_set_thumbnail_area (icon->pAppli, iX, iY - dh, iWidth, iHeight);
359 	else
360 		gldi_window_set_thumbnail_area (icon->pAppli, iY - dh, iX, iHeight, iWidth);
361 }
362 
gldi_appli_reserve_geometry_for_window_manager(GldiWindowActor * pAppli,Icon * icon,CairoDock * pMainDock)363 void gldi_appli_reserve_geometry_for_window_manager (GldiWindowActor *pAppli, Icon *icon, CairoDock *pMainDock)
364 {
365 	if (CAIRO_DOCK_IS_APPLI (icon) && cairo_dock_get_icon_container(icon) == NULL)  // a detached appli
366 	{
367 		/// TODO: use the same algorithm as the class-manager to find the future position of the icon ...
368 
369 		Icon *pInhibitor = cairo_dock_get_inhibitor (icon, FALSE);  // FALSE <=> meme en-dehors d'un dock
370 		if (pInhibitor == NULL)  // cette icone n'est pas inhibee, donc se minimisera dans le dock en une nouvelle icone.
371 		{
372 			int x, y;
373 			Icon *pClassmate = cairo_dock_get_classmate (icon);
374 			CairoDock *pClassmateDock = (pClassmate ? CAIRO_DOCK(cairo_dock_get_icon_container (pClassmate)) : NULL);
375 			if (myTaskbarParam.bGroupAppliByClass && pClassmate != NULL && pClassmateDock != NULL)  // on va se grouper avec cette icone.
376 			{
377 				x = x_icon_geometry (pClassmate, pClassmateDock);
378 				if (cairo_dock_is_hidden (pMainDock))
379 				{
380 					y = (pClassmateDock->container.bDirectionUp ? 0 : gldi_desktop_get_height());
381 				}
382 				else
383 				{
384 					y = y_icon_geometry (pClassmate, pClassmateDock);
385 				}
386 			}
387 			else if (myTaskbarParam.bMixLauncherAppli && pClassmate != NULL && pClassmateDock != NULL)  // on va se placer a cote.
388 			{
389 				x = x_icon_geometry (pClassmate, pClassmateDock) + pClassmate->fWidth/2;
390 				if (cairo_dock_is_hidden (pClassmateDock))
391 				{
392 					y = (pClassmateDock->container.bDirectionUp ? 0 : gldi_desktop_get_height());
393 				}
394 				else
395 				{
396 					y = y_icon_geometry (pClassmate, pClassmateDock);
397 				}
398 			}
399 			else  // on va se placer a la fin de la barre des taches.
400 			{
401 				Icon *pIcon, *pLastLauncher = NULL;
402 				GList *ic;
403 				for (ic = pMainDock->icons; ic != NULL; ic = ic->next)
404 				{
405 					pIcon = ic->data;
406 					if (GLDI_OBJECT_IS_LAUNCHER_ICON (pIcon)  // launcher, even without class
407 					|| GLDI_OBJECT_IS_STACK_ICON (pIcon)  // container icon (likely to contain some launchers)
408 					|| (GLDI_OBJECT_IS_APPLET_ICON (pIcon) && pIcon->cClass != NULL)  // applet acting like a launcher
409 					|| (GLDI_OBJECT_IS_SEPARATOR_ICON (pIcon)))  // separator (user or auto).
410 					{
411 						pLastLauncher = pIcon;
412 					}
413 				}
414 
415 				if (pLastLauncher != NULL)  // on se placera juste apres.
416 				{
417 					x = x_icon_geometry (pLastLauncher, pMainDock) + pLastLauncher->fWidth/2;
418 					if (cairo_dock_is_hidden (pMainDock))
419 					{
420 						y = (pMainDock->container.bDirectionUp ? 0 : gldi_desktop_get_height());
421 					}
422 					else
423 					{
424 						y = y_icon_geometry (pLastLauncher, pMainDock);
425 					}
426 				}
427 				else  // aucune icone avant notre groupe, on sera insere en 1er.
428 				{
429 					x = pMainDock->container.iWindowPositionX + 0 + (pMainDock->container.iWidth - pMainDock->fFlatDockWidth) / 2;
430 					if (cairo_dock_is_hidden (pMainDock))
431 					{
432 						y = (pMainDock->container.bDirectionUp ? 0 : gldi_desktop_get_height());
433 					}
434 					else
435 					{
436 						y = pMainDock->container.iWindowPositionY;
437 					}
438 				}
439 			}
440 			//g_print (" - %s en (%d;%d)\n", icon->cName, x, y);
441 			if (pMainDock->container.bIsHorizontal)
442 				gldi_window_set_minimize_position (pAppli, x, y);
443 			else
444 				gldi_window_set_minimize_position (pAppli, y, x);
445 		}
446 		else
447 		{
448 			/// gerer les desklets...
449 
450 		}
451 	}
452 }
453 
454 
gldi_appli_icon_get_image_buffer(Icon * pIcon)455 const CairoDockImageBuffer *gldi_appli_icon_get_image_buffer (Icon *pIcon)
456 {
457 	static CairoDockImageBuffer image;
458 
459 	// if the given icon is not loaded
460 	if (pIcon->image.pSurface == NULL)
461 	{
462 		// try to get the image from the class
463 		const CairoDockImageBuffer *pImageBuffer = cairo_dock_get_class_image_buffer (pIcon->cClass);
464 		if (pImageBuffer && pImageBuffer->pSurface)
465 		{
466 			return pImageBuffer;
467 		}
468 
469 		// try to load the icon.
470 		if (g_pMainDock)
471 		{
472 			// set a size (we could set any size, but let's set something useful: if the icon is inserted in a dock and is already loaded at the correct size, it won't be loaded again).
473 			gboolean bNoContainer = FALSE;
474 			if (pIcon->pContainer == NULL)  // not in a container (=> no size) -> set a size before loading it.
475 			{
476 				bNoContainer = TRUE;
477 				cairo_dock_set_icon_container (pIcon, g_pPrimaryContainer);
478 				pIcon->fWidth = pIcon->fHeight = 0;  /// useful ?...
479 				pIcon->iRequestedWidth = pIcon->iRequestedHeight = 0;  // no request
480 				cairo_dock_set_icon_size_in_dock (g_pMainDock, pIcon);
481 			}
482 
483 			// load the icon
484 			cairo_dock_load_icon_image (pIcon, g_pPrimaryContainer);
485 			if (bNoContainer)
486 			{
487 				cairo_dock_set_icon_container (pIcon, NULL);
488 			}
489 		}
490 	}
491 
492 	// if the given icon is loaded, use its image.
493 	if (pIcon->image.pSurface != NULL || pIcon->image.iTexture != 0)
494 	{
495 		memcpy (&image, &pIcon->image, sizeof (CairoDockImageBuffer));
496 		return &image;
497 	}
498 	else
499 	{
500 		return NULL;
501 	}
502 }
503 
504 
_set_inhibitor_name(Icon * pInhibitorIcon,const gchar * cNewName)505 static gboolean _set_inhibitor_name (Icon *pInhibitorIcon, const gchar *cNewName)
506 {
507 	if (! CAIRO_DOCK_ICON_TYPE_IS_APPLET (pInhibitorIcon))
508 	{
509 		cd_debug (" %s change son nom en %s", pInhibitorIcon->cName, cNewName);
510 		if (pInhibitorIcon->cInitialName == NULL)
511 		{
512 			pInhibitorIcon->cInitialName = pInhibitorIcon->cName;
513 			cd_debug ("pInhibitorIcon->cInitialName <- %s", pInhibitorIcon->cInitialName);
514 		}
515 		else
516 			g_free (pInhibitorIcon->cName);
517 		pInhibitorIcon->cName = NULL;
518 
519 		gldi_icon_set_name (pInhibitorIcon, (cNewName != NULL ? cNewName : pInhibitorIcon->cInitialName));
520 	}
521 	cairo_dock_redraw_icon (pInhibitorIcon);
522 	return TRUE;  // continue
523 }
gldi_window_inhibitors_set_name(GldiWindowActor * actor,const gchar * cNewName)524 void gldi_window_inhibitors_set_name (GldiWindowActor *actor, const gchar *cNewName)
525 {
526 	gldi_window_foreach_inhibitor (actor, (GldiIconRFunc)_set_inhibitor_name, (gpointer)cNewName);
527 }
528 
529 
_set_active_state(Icon * pInhibitorIcon,gpointer data)530 static gboolean _set_active_state (Icon *pInhibitorIcon, gpointer data)
531 {
532 	gboolean bActive = GPOINTER_TO_INT(data);
533 	if (bActive)
534 	{
535 		CairoDock *pParentDock = CAIRO_DOCK(cairo_dock_get_icon_container (pInhibitorIcon));
536 		if (pParentDock != NULL)
537 			gldi_appli_icon_animate_on_active (pInhibitorIcon, pParentDock);
538 	}
539 	else
540 	{
541 		cairo_dock_redraw_icon (pInhibitorIcon);
542 	}
543 	return TRUE;  // continue
544 }
gldi_window_inhibitors_set_active_state(GldiWindowActor * actor,gboolean bActive)545 void gldi_window_inhibitors_set_active_state (GldiWindowActor *actor, gboolean bActive)
546 {
547 	gldi_window_foreach_inhibitor (actor, (GldiIconRFunc)_set_active_state, GINT_TO_POINTER(bActive));
548 }
549 
550 
_set_hidden_state(Icon * pInhibitorIcon,G_GNUC_UNUSED gpointer data)551 static gboolean _set_hidden_state (Icon *pInhibitorIcon, G_GNUC_UNUSED gpointer data)
552 {
553 	if (! CAIRO_DOCK_ICON_TYPE_IS_APPLET (pInhibitorIcon) && myTaskbarParam.fVisibleAppliAlpha != 0)
554 	{
555 		pInhibitorIcon->fAlpha = 1;  // on triche un peu.
556 		cairo_dock_redraw_icon (pInhibitorIcon);
557 	}
558 	return TRUE;  // continue
559 }
gldi_window_inhibitors_set_hidden_state(GldiWindowActor * actor,gboolean bIsHidden)560 void gldi_window_inhibitors_set_hidden_state (GldiWindowActor *actor, gboolean bIsHidden)
561 {
562 	gldi_window_foreach_inhibitor (actor, (GldiIconRFunc)_set_hidden_state, GINT_TO_POINTER(bIsHidden));
563 }
564