void cairo_dock_normalize_icons_order (GList *pIconList, CairoDockIconType iType)
{
	cd_message ("%s (%d)", __func__, iType);
	int iOrder = 1;
	CairoDockIconType iGroupOrder = cairo_dock_get_group_order (iType);
	GString *sDesktopFilePath = g_string_new ("");
	GList* ic;
	Icon *icon;
	for (ic = pIconList; ic != NULL; ic = ic->next)
	{
		icon = ic->data;
		if (cairo_dock_get_icon_order (icon) != iGroupOrder)
			continue;
		
		icon->fOrder = iOrder ++;
		if (icon->acDesktopFileName != NULL)
		{
			g_string_printf (sDesktopFilePath, "%s/%s", g_cCurrentLaunchersPath, icon->acDesktopFileName);
			cairo_dock_update_conf_file (sDesktopFilePath->str,
				G_TYPE_DOUBLE, "Desktop Entry", "Order", icon->fOrder,
				G_TYPE_INVALID);
		}
		else if (CAIRO_DOCK_IS_APPLET (icon))
		{
			cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
				G_TYPE_DOUBLE, "Icon", "order", icon->fOrder,
				G_TYPE_INVALID);
		}
	}
	g_string_free (sDesktopFilePath, TRUE);
}
static gboolean _cairo_dock_write_desklet_position (CairoDesklet *pDesklet)
{
	if (pDesklet->pIcon != NULL && pDesklet->pIcon->pModuleInstance != NULL)
	{
		int iRelativePositionX = (pDesklet->container.iWindowPositionX + pDesklet->container.iWidth/2 <= gldi_desktop_get_width()/2 ? pDesklet->container.iWindowPositionX : pDesklet->container.iWindowPositionX - gldi_desktop_get_width());
		int iRelativePositionY = (pDesklet->container.iWindowPositionY + pDesklet->container.iHeight/2 <= gldi_desktop_get_height()/2 ? pDesklet->container.iWindowPositionY : pDesklet->container.iWindowPositionY - gldi_desktop_get_height());
		
		int iNumDesktop = -1;
		if (! gldi_desklet_is_sticky (pDesklet))
		{
			iNumDesktop = gldi_container_get_current_desktop_index (CAIRO_CONTAINER (pDesklet));
			//g_print ("desormais on place le desklet sur le bureau (%d,%d,%d)\n", iDesktop, iViewportX, iViewportY);
		}
		cd_debug ("%d; %d; %d", iNumDesktop, iRelativePositionX, iRelativePositionY);
		cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
			G_TYPE_INT, "Desklet", "x position", iRelativePositionX,
			G_TYPE_INT, "Desklet", "y position", iRelativePositionY,
			G_TYPE_INT, "Desklet", "num desktop", iNumDesktop,
			G_TYPE_INVALID);
		gldi_object_notify (pDesklet, NOTIFICATION_CONFIGURE_DESKLET, pDesklet);
	}
	
	if (pDesklet->bSpaceReserved)  // l'espace est reserve, on reserve a la nouvelle position.
	{
		_reserve_space_for_desklet (pDesklet, TRUE);
	}
	if (pDesklet->pIcon && gldi_icon_has_dialog (pDesklet->pIcon))
	{
		gldi_dialogs_replace_all ();
	}
	pDesklet->iSidWritePosition = 0;
	return FALSE;
}
void gldi_desklet_set_sticky (CairoDesklet *pDesklet, gboolean bSticky)
{
	//g_print ("%s (%d)\n", __func__, bSticky);
	int iNumDesktop;
	if (bSticky)
	{
		gtk_window_stick (GTK_WINDOW (pDesklet->container.pWidget));
		iNumDesktop = -1;
	}
	else
	{
		gtk_window_unstick (GTK_WINDOW (pDesklet->container.pWidget));
		int iCurrentDesktop, iCurrentViewportX, iCurrentViewportY;
		gldi_desktop_get_current (&iCurrentDesktop, &iCurrentViewportX, &iCurrentViewportY);
		iNumDesktop = iCurrentDesktop * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY + iCurrentViewportX * g_desktopGeometry.iNbViewportY + iCurrentViewportY;
		cd_debug (">>> on colle ce desklet sur le bureau %d", iNumDesktop);
	}
	
	//\_________________ On enregistre le nouvel etat.
	Icon *icon = pDesklet->pIcon;
	if (CAIRO_DOCK_IS_APPLET (icon))
		cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
			G_TYPE_BOOLEAN, "Desklet", "sticky", bSticky,
			G_TYPE_INT, "Desklet", "num desktop", iNumDesktop,
			G_TYPE_INVALID);
}
static gboolean _cairo_dock_write_desklet_position (CairoDesklet *pDesklet)
{
	if (pDesklet->pIcon != NULL && pDesklet->pIcon->pModule != NULL)
		cairo_dock_update_conf_file (pDesklet->pIcon->pModule->cConfFilePath,
			G_TYPE_INT, "Desklet", "x position", pDesklet->iWindowPositionX,
			G_TYPE_INT, "Desklet", "y position", pDesklet->iWindowPositionY,
			G_TYPE_INVALID);
	pDesklet->iSidWritePosition = 0;
	return FALSE;
}
void cairo_dock_move_icon_after_icon (CairoDock *pDock, Icon *icon1, Icon *icon2)
{
	//g_print ("%s (%s, %.2f, %x)\n", __func__, icon1->acName, icon1->fOrder, icon2);
	///if ((icon2 != NULL) && (! ( (CAIRO_DOCK_IS_APPLI (icon1) && CAIRO_DOCK_IS_APPLI (icon2)) || (CAIRO_DOCK_IS_LAUNCHER (icon1) && CAIRO_DOCK_IS_LAUNCHER (icon2)) || (CAIRO_DOCK_IS_APPLET (icon1) && CAIRO_DOCK_IS_APPLET (icon2)) ) ))
	if ((icon2 != NULL) && fabs (cairo_dock_get_icon_order (icon1) - cairo_dock_get_icon_order (icon2)) > 1)
		return ;
	//\_________________ On change l'ordre de l'icone.
	gboolean bForceUpdate = FALSE;
	if (icon2 != NULL)
	{
		Icon *pNextIcon = cairo_dock_get_next_icon (pDock->icons, icon2);
		if (pNextIcon != NULL && fabs (pNextIcon->fOrder - icon2->fOrder) < 1e-3)
		{
			bForceUpdate = TRUE;
		}
		if (pNextIcon == NULL || cairo_dock_get_icon_order (pNextIcon) != cairo_dock_get_icon_order (icon2))
			icon1->fOrder = icon2->fOrder + 1;
		else
			icon1->fOrder = (pNextIcon->fOrder - icon2->fOrder > 1 ? icon2->fOrder + 1 : (pNextIcon->fOrder + icon2->fOrder) / 2);
	}
	else
	{
		Icon *pFirstIcon = cairo_dock_get_first_icon_of_order (pDock->icons, icon1->iType);
		if (pFirstIcon != NULL)
			icon1->fOrder = pFirstIcon->fOrder - 1;
		else
			icon1->fOrder = 1;
	}
	//g_print ("icon1->fOrder:%.2f\n", icon1->fOrder);
	
	//\_________________ On change l'ordre dans le fichier du lanceur 1.
	if ((CAIRO_DOCK_IS_LAUNCHER (icon1) || CAIRO_DOCK_IS_SEPARATOR (icon1)) && icon1->acDesktopFileName != NULL)
	{
		gchar *cDesktopFilePath = g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, icon1->acDesktopFileName);
		cairo_dock_update_conf_file (cDesktopFilePath,
			G_TYPE_DOUBLE, "Desktop Entry", "Order", icon1->fOrder,
			G_TYPE_INVALID);
		g_free (cDesktopFilePath);
	}
	else if (CAIRO_DOCK_IS_APPLET (icon1))
		cairo_dock_update_module_instance_order (icon1->pModuleInstance, icon1->fOrder);

	//\_________________ On change sa place dans la liste.
	pDock->pFirstDrawnElement = NULL;
	pDock->icons = g_list_remove (pDock->icons, icon1);
	pDock->icons = g_list_insert_sorted (pDock->icons,
		icon1,
		(GCompareFunc) cairo_dock_compare_icons_order);

	//\_________________ On recalcule la largeur max, qui peut avoir ete influencee par le changement d'ordre.
	cairo_dock_update_dock_size (pDock);
	
	if (bForceUpdate)
		cairo_dock_normalize_icons_order (pDock->icons, icon1->iType);
}
void gldi_desklet_lock_position (CairoDesklet *pDesklet, gboolean bPositionLocked)
{
	//g_print ("%s (%d)\n", __func__, bPositionLocked);
	pDesklet->bPositionLocked = bPositionLocked;
	
	//\_________________ On enregistre le nouvel etat.
	Icon *icon = pDesklet->pIcon;
	if (CAIRO_DOCK_IS_APPLET (icon))
		cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
			G_TYPE_BOOLEAN, "Desklet", "locked", pDesklet->bPositionLocked,
			G_TYPE_INVALID);
}
gboolean on_delete_desklet (GtkWidget *pWidget, GdkEvent *event, CairoDesklet *pDesklet)
{
	if (pDesklet->pIcon->pModule != NULL)
	{
		cairo_dock_update_conf_file (pDesklet->pIcon->pModule->cConfFilePath,
			G_TYPE_BOOLEAN, "Desklet", "initially detached", FALSE,
			G_TYPE_INVALID);

		cairo_dock_reload_module (pDesklet->pIcon->pModule, TRUE);
	}
	return TRUE;
}
void cairo_dock_update_icon_s_container_name (Icon *icon, const gchar *cNewParentDockName)
{
	g_free (icon->cParentDockName);
	icon->cParentDockName = g_strdup (cNewParentDockName);

	if (CAIRO_DOCK_IS_NORMAL_LAUNCHER (icon))  // icon->acDesktopFileName != NULL
	{
		gchar *cDesktopFilePath = g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, icon->acDesktopFileName);

		cairo_dock_update_conf_file (cDesktopFilePath,
			G_TYPE_STRING, "Desktop Entry", "Container", cNewParentDockName,
			G_TYPE_INVALID);
		g_free (cDesktopFilePath);
	}
	else if (CAIRO_DOCK_IS_APPLET (icon))
	{
		cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
			G_TYPE_STRING, "Icon", "dock name", cNewParentDockName,
			G_TYPE_INVALID);
	}
}
static gboolean _cairo_dock_write_desklet_size (CairoDesklet *pDesklet)
{
	if (pDesklet->pIcon != NULL && pDesklet->pIcon->pModule != NULL)
		cairo_dock_update_conf_file (pDesklet->pIcon->pModule->cConfFilePath,
			G_TYPE_INT, "Desklet", "width", pDesklet->iWidth,
			G_TYPE_INT, "Desklet", "height", pDesklet->iHeight,
			G_TYPE_INVALID);
	pDesklet->iSidWriteSize = 0;
	if (pDesklet->pIcon != NULL)
	{
		cairo_dock_reload_module (pDesklet->pIcon->pModule, FALSE);
		gtk_widget_queue_draw (pDesklet->pWidget);  // sinon on ne redessine que l'interieur.
	}
	return FALSE;
}
void gldi_desklet_set_accessibility (CairoDesklet *pDesklet, CairoDeskletVisibility iVisibility, gboolean bSaveState)
{
	cd_debug ("%s (%d)", __func__, iVisibility);
	
	//\_________________ On applique la nouvelle accessibilite.
	
	gtk_window_set_keep_below (GTK_WINDOW (pDesklet->container.pWidget), iVisibility == CAIRO_DESKLET_KEEP_BELOW);
	
	gtk_window_set_keep_above (GTK_WINDOW (pDesklet->container.pWidget), iVisibility == CAIRO_DESKLET_KEEP_ABOVE);
	
	if (iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER)
	{
		if (pDesklet->iVisibility != CAIRO_DESKLET_ON_WIDGET_LAYER)
			gldi_desktop_set_on_widget_layer (CAIRO_CONTAINER (pDesklet), TRUE);
	}
	else if (pDesklet->iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER)
	{
		gldi_desktop_set_on_widget_layer (CAIRO_CONTAINER (pDesklet), FALSE);
	}
	
	if (iVisibility == CAIRO_DESKLET_RESERVE_SPACE)
	{
		if (! pDesklet->bSpaceReserved)
			_reserve_space_for_desklet (pDesklet, TRUE);  // sinon inutile de le refaire, s'il y'a un changement de taille ce sera fait lors du configure-event.
	}
	else if (pDesklet->bSpaceReserved)
	{
		_reserve_space_for_desklet (pDesklet, FALSE);
	}
	
	//\_________________ On enregistre le nouvel etat.
	pDesklet->iVisibility = iVisibility;
	
	Icon *icon = pDesklet->pIcon;
	if (bSaveState && CAIRO_DOCK_IS_APPLET (icon))
		cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
			G_TYPE_INT, "Desklet", "accessibility", iVisibility,
			G_TYPE_INVALID);
}
static void _on_program_shutdown (int iClickedButton, GtkWidget *pInteractiveWidget, gpointer data, CairoDialog *pDialog)
{
	CD_APPLET_ENTER;
	if (iClickedButton == 0 || iClickedButton == -1)  // ok button or Enter.
	{
		int iDeltaT = 60 * gtk_range_get_value (GTK_RANGE (pInteractiveWidget));
		if (iDeltaT > 0)  // set the new time
		{
			//g_print ("iShutdownTime <- %ld + %d\n", t_cur, iDeltaT);
			time_t t_cur = (time_t) time (NULL);
			myConfig.iShutdownTime = (int) (t_cur + iDeltaT);
		}
		else if (iDeltaT == 0)  // cancel any previous shutdown 
		{
			myConfig.iShutdownTime = 0;
		}
		cairo_dock_update_conf_file (CD_APPLET_MY_CONF_FILE,
			G_TYPE_INT, "Configuration", "shutdown time", myConfig.iShutdownTime,
			G_TYPE_INVALID);
		cd_logout_set_timer ();
	}
	CD_APPLET_LEAVE ();
}
static gboolean on_button_press_desklet(G_GNUC_UNUSED GtkWidget *pWidget,
	GdkEventButton *pButton,
	CairoDesklet *pDesklet)
{
	if (pButton->button == 1)  // clic gauche.
	{
		pDesklet->container.iMouseX = pButton->x;
		pDesklet->container.iMouseY = pButton->y;
		if (pButton->type == GDK_BUTTON_PRESS)
		{
			pDesklet->bClicked = TRUE;
			if (cairo_dock_desklet_is_free (pDesklet))
			{
				///pDesklet->container.iMouseX = pButton->x;  // pour le deplacement manuel.
				///pDesklet->container.iMouseY = pButton->y;
				if (pButton->x < myDeskletsParam.iDeskletButtonSize && pButton->y < myDeskletsParam.iDeskletButtonSize)
					pDesklet->rotating = TRUE;
				else if (pButton->x > pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize && pButton->y < myDeskletsParam.iDeskletButtonSize)
					pDesklet->retaching = TRUE;
				else if (pButton->x > (pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize)/2 && pButton->x < (pDesklet->container.iWidth + myDeskletsParam.iDeskletButtonSize)/2 && pButton->y < myDeskletsParam.iDeskletButtonSize)
					pDesklet->rotatingY = TRUE;
				else if (pButton->y > (pDesklet->container.iHeight - myDeskletsParam.iDeskletButtonSize)/2 && pButton->y < (pDesklet->container.iHeight + myDeskletsParam.iDeskletButtonSize)/2 && pButton->x < myDeskletsParam.iDeskletButtonSize)
					pDesklet->rotatingX = TRUE;
				else
					pDesklet->time = pButton->time;
			}
			if (pDesklet->bAllowNoClickable && pButton->x > pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize && pButton->y > pDesklet->container.iHeight - myDeskletsParam.iDeskletButtonSize)
				pDesklet->making_transparent = TRUE;
		}
		else if (pButton->type == GDK_BUTTON_RELEASE)
		{
			if (!pDesklet->bClicked)  // on n'accepte le release que si on avait clique sur le desklet avant (on peut recevoir le release si on avait clique sur un dialogue qui chevauchait notre desklet et qui a disparu au clic).
			{
				return FALSE;
			}
			pDesklet->bClicked = FALSE;
			//g_print ("GDK_BUTTON_RELEASE\n");
			int x = pDesklet->container.iMouseX;
			int y = pDesklet->container.iMouseY;
			if (pDesklet->moving)
			{
				pDesklet->moving = FALSE;
			}
			else if (pDesklet->rotating)
			{
				pDesklet->rotating = FALSE;
				cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
					G_TYPE_INT, "Desklet", "rotation", (int) (pDesklet->fRotation / G_PI * 180.),
					G_TYPE_INVALID);
				gtk_widget_queue_draw (pDesklet->container.pWidget);
				gldi_object_notify (pDesklet, NOTIFICATION_CONFIGURE_DESKLET, pDesklet);
			}
			else if (pDesklet->retaching)
			{
				pDesklet->retaching = FALSE;
				if (x > pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize && y < myDeskletsParam.iDeskletButtonSize)  // on verifie qu'on est encore dedans.
				{
					Icon *icon = pDesklet->pIcon;
					g_return_val_if_fail (CAIRO_DOCK_IS_APPLET (icon), FALSE);
					gldi_module_instance_detach (icon->pModuleInstance);
					return GLDI_NOTIFICATION_INTERCEPT;  // interception du signal.
				}
			}
			else if (pDesklet->making_transparent)
			{
				cd_debug ("pDesklet->making_transparent\n");
				pDesklet->making_transparent = FALSE;
				if (x > pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize && y > pDesklet->container.iHeight - myDeskletsParam.iDeskletButtonSize)  // on verifie qu'on est encore dedans.
				{
					Icon *icon = pDesklet->pIcon;
					g_return_val_if_fail (CAIRO_DOCK_IS_APPLET (icon), FALSE);
					pDesklet->bNoInput = ! pDesklet->bNoInput;
					cd_debug ("no input : %d (%s)", pDesklet->bNoInput, icon->pModuleInstance->cConfFilePath);
					cairo_dock_update_conf_file (icon->pModuleInstance->cConfFilePath,
						G_TYPE_BOOLEAN, "Desklet", "no input", pDesklet->bNoInput,
						G_TYPE_INVALID);
					_cairo_dock_set_desklet_input_shape (pDesklet);
					gtk_widget_queue_draw (pDesklet->container.pWidget);
				}
			}
			else if (pDesklet->rotatingY)
			{
				pDesklet->rotatingY = FALSE;
				cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
					G_TYPE_INT, "Desklet", "depth rotation y", (int) (pDesklet->fDepthRotationY / G_PI * 180.),
					G_TYPE_INVALID);
				gtk_widget_queue_draw (pDesklet->container.pWidget);
			}
			else if (pDesklet->rotatingX)
			{
				pDesklet->rotatingX = FALSE;
				cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
					G_TYPE_INT, "Desklet", "depth rotation x", (int) (pDesklet->fDepthRotationX / G_PI * 180.),
					G_TYPE_INVALID);
				gtk_widget_queue_draw (pDesklet->container.pWidget);
			}
			else
			{
				Icon *pClickedIcon = gldi_desklet_find_clicked_icon (pDesklet);
				gldi_object_notify (pDesklet, NOTIFICATION_CLICK_ICON, pClickedIcon, pDesklet, pButton->state);
			}
			// prudence.
			pDesklet->rotating = FALSE;
			pDesklet->retaching = FALSE;
			pDesklet->making_transparent = FALSE;
			pDesklet->rotatingX = FALSE;
			pDesklet->rotatingY = FALSE;
		}
		else if (pButton->type == GDK_2BUTTON_PRESS)
		{
			if (! (pButton->x < myDeskletsParam.iDeskletButtonSize && pButton->y < myDeskletsParam.iDeskletButtonSize) && ! (pButton->x > (pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize)/2 && pButton->x < (pDesklet->container.iWidth + myDeskletsParam.iDeskletButtonSize)/2 && pButton->y < myDeskletsParam.iDeskletButtonSize))
			{
				Icon *pClickedIcon = gldi_desklet_find_clicked_icon (pDesklet);  // can be NULL
				gldi_object_notify (pDesklet, NOTIFICATION_DOUBLE_CLICK_ICON, pClickedIcon, pDesklet);
			}
		}
	}
	else if (pButton->button == 3 && pButton->type == GDK_BUTTON_PRESS)  // clique droit.
	{
		Icon *pClickedIcon = gldi_desklet_find_clicked_icon (pDesklet);
		GtkWidget *menu = gldi_container_build_menu (CAIRO_CONTAINER (pDesklet), pClickedIcon);  // genere un CAIRO_DOCK_BUILD_ICON_MENU.
		gldi_menu_popup (menu);
	}
	else if (pButton->button == 2 && pButton->type == GDK_BUTTON_PRESS)  // clique milieu.
	{
		if (pButton->x < myDeskletsParam.iDeskletButtonSize && pButton->y < myDeskletsParam.iDeskletButtonSize)
		{
			pDesklet->fRotation = 0.;
			gtk_widget_queue_draw (pDesklet->container.pWidget);
			cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
				G_TYPE_INT, "Desklet", "rotation", 0,
				G_TYPE_INVALID);
			gldi_object_notify (pDesklet, NOTIFICATION_CONFIGURE_DESKLET, pDesklet);
		}
		else if (pButton->x > (pDesklet->container.iWidth - myDeskletsParam.iDeskletButtonSize)/2 && pButton->x < (pDesklet->container.iWidth + myDeskletsParam.iDeskletButtonSize)/2 && pButton->y < myDeskletsParam.iDeskletButtonSize)
		{
			pDesklet->fDepthRotationY = 0.;
			gtk_widget_queue_draw (pDesklet->container.pWidget);
			cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
				G_TYPE_INT, "Desklet", "depth rotation y", 0,
				G_TYPE_INVALID);
		}
		else if (pButton->y > (pDesklet->container.iHeight - myDeskletsParam.iDeskletButtonSize)/2 && pButton->y < (pDesklet->container.iHeight + myDeskletsParam.iDeskletButtonSize)/2 && pButton->x < myDeskletsParam.iDeskletButtonSize)
		{
			pDesklet->fDepthRotationX = 0.;
			gtk_widget_queue_draw (pDesklet->container.pWidget);
			cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
				G_TYPE_INT, "Desklet", "depth rotation x", 0,
				G_TYPE_INVALID);
		}
		else
		{
			gldi_object_notify (pDesklet, NOTIFICATION_MIDDLE_CLICK_ICON, pDesklet->pIcon, pDesklet);
		}
	}
	return FALSE;
}
static gboolean _cairo_dock_write_desklet_size (CairoDesklet *pDesklet)
{
	if ((pDesklet->iDesiredWidth == 0 && pDesklet->iDesiredHeight == 0) && pDesklet->pIcon != NULL && pDesklet->pIcon->pModuleInstance != NULL && gldi_desklet_manager_is_ready ())
	{
		gchar *cSize = g_strdup_printf ("%d;%d", pDesklet->container.iWidth, pDesklet->container.iHeight);
		cairo_dock_update_conf_file (pDesklet->pIcon->pModuleInstance->cConfFilePath,
			G_TYPE_STRING, "Desklet", "size", cSize,
			G_TYPE_INVALID);
		g_free (cSize);
		gldi_object_notify (pDesklet, NOTIFICATION_CONFIGURE_DESKLET, pDesklet);
	}
	pDesklet->iSidWriteSize = 0;
	pDesklet->iKnownWidth = pDesklet->container.iWidth;
	pDesklet->iKnownHeight = pDesklet->container.iHeight;
	if (((pDesklet->iDesiredWidth != 0 || pDesklet->iDesiredHeight != 0) && pDesklet->iDesiredWidth == pDesklet->container.iWidth && pDesklet->iDesiredHeight == pDesklet->container.iHeight) || (pDesklet->iDesiredWidth == 0 && pDesklet->iDesiredHeight == 0))
	{
		pDesklet->iDesiredWidth = 0;
		pDesklet->iDesiredHeight = 0;
		
		gldi_desklet_load_desklet_decorations (pDesklet);  // reload the decorations at the new desklet size.
		
		if (pDesklet->pIcon != NULL && pDesklet->pIcon->pModuleInstance != NULL)
		{
			// on recalcule la vue du desklet a la nouvelle dimension.
			CairoDeskletRenderer *pRenderer = pDesklet->pRenderer;
			if (pRenderer)
			{
				// on calcule les icones et les parametres internes de la vue.
				if (pRenderer->calculate_icons != NULL)
					pRenderer->calculate_icons (pDesklet);
				
				// on recharge l'icone principale.
				Icon* pIcon = pDesklet->pIcon;
				if (pIcon)  // if the view doesn't display the main icon, it will set the allocated size to 0 so that the icon won't be loaded.
				{
					cairo_dock_load_icon_buffers (pIcon, CAIRO_CONTAINER (pDesklet));  // pas de trigger, car on veut pouvoir associer un contexte a l'icone principale tout de suite.
				}
				
				// on recharge chaque icone.
				GList* ic;
				for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
				{
					pIcon = ic->data;
					if (cairo_dock_icon_get_allocated_width (pIcon) != pIcon->image.iWidth || cairo_dock_icon_get_allocated_height (pIcon) != pIcon->image.iHeight)
					{
						cairo_dock_trigger_load_icon_buffers (pIcon);
					}
				}
				
				// on recharge les buffers de la vue.
				if (pRenderer->load_data != NULL)
					pRenderer->load_data (pDesklet);
			}
			
			// on recharge le module associe.
			gldi_object_reload (GLDI_OBJECT(pDesklet->pIcon->pModuleInstance), FALSE);
			
			gtk_widget_queue_draw (pDesklet->container.pWidget);  // sinon on ne redessine que l'interieur.
		}
		
		if (pDesklet->bSpaceReserved)  // l'espace est reserve, on reserve la nouvelle taille.
		{
			_reserve_space_for_desklet (pDesklet, TRUE);
		}
	}
	
	//g_print ("iWidth <- %d;iHeight <- %d ; (%dx%d) (%x)\n", pDesklet->container.iWidth, pDesklet->container.iHeight, pDesklet->iKnownWidth, pDesklet->iKnownHeight, pDesklet->pIcon);
	return FALSE;
}
static void init_object (GldiObject *obj, gpointer attr)
{
	Icon *icon = (Icon*)obj;
	GldiUserIconAttr *pAttributes = (GldiUserIconAttr*)attr;
	g_return_if_fail (pAttributes->pKeyFile != NULL);
	
	icon->iface.load_image = _load_image;
	
	// get additional parameters
	GKeyFile *pKeyFile = pAttributes->pKeyFile;
	gboolean bNeedUpdate = FALSE;
	
	icon->cFileName = g_key_file_get_string (pKeyFile, "Desktop Entry", "Icon", NULL);
	if (icon->cFileName != NULL && *icon->cFileName == '\0')
	{
		g_free (icon->cFileName);
		icon->cFileName = NULL;
	}
	
	icon->cName = cairo_dock_get_locale_string_from_conf_file (pKeyFile, "Desktop Entry", "Name", NULL);
	if (icon->cName != NULL && *icon->cName == '\0')
	{
		g_free (icon->cName);
		icon->cName = NULL;
	}
	if (g_strcmp0 (icon->cName, icon->cParentDockName) == 0)  // it shouldn't happen, but if ever it does, be sure to forbid an icon pointing on itself.
	{
		cd_warning ("It seems we have a sub-dock in itself! => its parent dock is now the main dock");
		g_key_file_set_string (pKeyFile, "Desktop Entry", "Container", CAIRO_DOCK_MAIN_DOCK_NAME);  // => to the main dock
		bNeedUpdate = TRUE;
		g_free (icon->cParentDockName);
		icon->cParentDockName = g_strdup (CAIRO_DOCK_MAIN_DOCK_NAME);
	}
	g_return_if_fail (icon->cName != NULL);
	
	icon->iSubdockViewType = g_key_file_get_integer (pKeyFile, "Desktop Entry", "render", NULL);  // on a besoin d'un entier dans le panneau de conf pour pouvoir degriser des options selon le rendu choisi. De plus c'est utile aussi pour Animated Icons...
	
	// create its sub-dock
	gchar *cSubDockRendererName = g_key_file_get_string (pKeyFile, "Desktop Entry", "Renderer", NULL);
	if (icon->cName != NULL)
	{
		CairoDock *pChildDock = gldi_dock_get (icon->cName);  // the dock might already exists (if an icon inside has been created beforehand), in this case it's still a root dock
		if (pChildDock && (pChildDock->iRefCount > 0 || pChildDock->bIsMainDock))  // if ever a sub-dock with this name already exists, change the icon's name to avoid the conflict
		{
			gchar *cUniqueDockName = cairo_dock_get_unique_dock_name (icon->cName);
			cd_warning ("A sub-dock with the same name (%s) already exists, we'll change it to %s", icon->cName, cUniqueDockName);
			gchar *cDesktopFilePath = g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, icon->cDesktopFileName);
			cairo_dock_update_conf_file (cDesktopFilePath,
				G_TYPE_STRING, "Desktop Entry", "Name", cUniqueDockName,
				G_TYPE_INVALID);
			g_free (cDesktopFilePath);
			g_free (icon->cName);
			icon->cName = cUniqueDockName;
			pChildDock = NULL;
		}
		CairoDock *pParentDock = gldi_dock_get (icon->cParentDockName);  // the icon is not yet inserted, but its dock has been created by the parent class.
		if (pChildDock == NULL)
		{
			cd_message ("The child dock (%s) doesn't exist, we create it with this view: %s", icon->cName, cSubDockRendererName);
			pChildDock = gldi_subdock_new (icon->cName, cSubDockRendererName, pParentDock, NULL);
		}
		else
		{
			cd_message ("The dock is now a 'child-dock' (%d, %d)", pChildDock->container.bIsHorizontal, pChildDock->container.bDirectionUp);
			gldi_dock_make_subdock (pChildDock, pParentDock, cSubDockRendererName);
		}
		icon->pSubDock = pChildDock;
	}
	g_free (cSubDockRendererName);
	
	if (! bNeedUpdate)
		bNeedUpdate = cairo_dock_conf_file_needs_update (pKeyFile, GLDI_VERSION);
	if (bNeedUpdate)
	{
		gchar *cDesktopFilePath = g_strdup_printf ("%s/%s", g_cCurrentLaunchersPath, pAttributes->cConfFileName);
		const gchar *cTemplateFile = GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_CONTAINER_CONF_FILE;
		cairo_dock_upgrade_conf_file (cDesktopFilePath, pKeyFile, cTemplateFile);  // update keys
		g_free (cDesktopFilePath);
	}
}
gboolean _new_xml_to_conf (GldiModuleInstance *myApplet, gchar *cReceivedData)
{
	gboolean bContinue = FALSE;
	
	if (cReceivedData && ((strncmp (cReceivedData, "file://", 7) == 0 && g_str_has_suffix (cReceivedData, ".xml")) \
			|| (strncmp (cReceivedData, "file://", 7) == 0 && g_str_has_suffix (cReceivedData, ".tar.gz")) \
			|| (strncmp (cReceivedData, "http://", 7) == 0 && g_str_has_suffix (cReceivedData, ".xml")) \
			|| (strncmp (cReceivedData, "http://", 7) == 0 && g_str_has_suffix (cReceivedData, ".tar.gz"))))
	{
		
		
		if (strncmp (cReceivedData, "file://", 7) == 0 && g_str_has_suffix (cReceivedData, ".xml")) // On laisse le fichier où il est et on ne crée pas de thème dans ~/.config/cairo-dock/doncky/
		{
			cd_debug ("DONCKY-debug : local xml file -> Use it without any copy.");
			// ltrim( cReceivedData, "file:///" );
			cReceivedData = g_filename_from_uri (cReceivedData, NULL, NULL);// FREE // g_strdup_printf("/%s", cReceivedData);
			bContinue = TRUE;
		}
		else // On crée un thème dans ~/.config/cairo-dock/doncky/
		{
			if (strncmp (cReceivedData, "file://", 7) == 0)
			{
				cReceivedData = g_filename_from_uri (cReceivedData, NULL, NULL); // FREE
			}

			// On récupère le 1er champ -> nom du fichier
			/*g_strreverse (cTmpFileName);			
			cTmpFileName = g_str_position (cTmpFileName, 1, '/');
			g_strreverse (cTmpFileName);*/
			gchar *cTmpFileName = g_path_get_basename (cReceivedData);
			
			
			
			// Récupération du nom du fichier sans l'extension
			gchar *cTmpThemeName = g_strdup (cTmpFileName);
			if (g_str_has_suffix(cReceivedData,".xml"))
				rtrim(cTmpThemeName,".xml");
			else if (g_str_has_suffix(cReceivedData,".tar.gz"))
			{
				rtrim (cTmpThemeName, ".tar.gz");
			}
			
			cd_debug ("DONCKY-debug : Theme name : %s", cTmpThemeName);
			
			// on cree le repertoire pour le theme.
			gchar *cDonckyThemesPath = g_strdup_printf ("%s/doncky", g_cCairoDockDataDir);
			gchar *cThemePath = g_strdup_printf ("%s/%s", cDonckyThemesPath, cTmpThemeName);
			
			if (! g_file_test (cThemePath, G_FILE_TEST_EXISTS))
			{
				cd_debug ("DONCKY-debug : the folder '%s' doesn't exist -> We create it", cThemePath);
				
				if (! g_file_test (cDonckyThemesPath, G_FILE_TEST_EXISTS))
				{
					cd_debug ("DONCKY-debug : the folder '%s' doesn't exist -> We create it", cDonckyThemesPath);
					if (g_mkdir (cDonckyThemesPath, 7*8*8+7*8+0) != 0)
					{
						cd_warning ("couldn't create directory '%s' !\nNo read history will be available.", cDonckyThemesPath);
						bContinue = FALSE;
					}
				}
				if (g_mkdir (cThemePath, 7*8*8+7*8+0) != 0)
				{
					cd_warning ("couldn't create directory '%s' !\nNo read history will be available.", cThemePath);
					bContinue = FALSE;
				}
				else
					bContinue = TRUE;
			}
			else
			{
				cd_debug ("DONCKY-debug : the folder '%s' exists -> give it a new name ...", cThemePath);
				gchar *cNewPath=NULL;
				int i=2;
				do
				{
					cNewPath = g_strdup_printf ("%s-%d", cThemePath, i);
					i ++;
				}
				while (g_file_test (cNewPath, G_FILE_TEST_EXISTS));
				g_free (cThemePath);
				cThemePath = cNewPath;
				bContinue = TRUE;
			}
			
			if (bContinue)
			{
				if (strncmp (cReceivedData, "http://", 7) == 0)
				{
					gchar *cCommand = g_strdup_printf ("wget \"%s\" -O \"%s/%s\" -t 3 -T 4 30 /dev/null 2>&1", cReceivedData, cThemePath, cTmpFileName);
					cd_debug ("DONCKY-debug : Downloading the file ...");
					cairo_dock_launch_command (cCommand);
					g_free (cCommand);												
				}
				else // C'est donc un fichier local
				{
					gchar *cCommand = g_strdup_printf ("cp \"/%s\" \"%s/%s\"", cReceivedData, cThemePath, cTmpFileName);
					cairo_dock_launch_command (cCommand);
					g_free (cCommand);
				}

				g_free (cReceivedData);
				cReceivedData = g_strdup_printf("%s/%s", cThemePath, cTmpFileName);
				
				cd_debug ("DONCKY-debug : Waiting to complete \"%s\"...", cReceivedData);
				do
				{
					// waiting for the download to be completed
					cd_debug ("DONCKY-debug : Waiting to complete...");
				}while (!_check_size_is_constant (myApplet, cReceivedData));
				
				cd_debug ("DONCKY-debug : \"%s\" is ready (Downloaded size : %i octets)", cReceivedData, myData.iCurrentFileSize);
				
				if (g_str_has_suffix(cReceivedData,".tar.gz"))
				{
					gchar *cCommand = g_strdup_printf ("cd \"%s\" && tar -xzvf \"%s\"",cThemePath, cTmpFileName);
					cairo_dock_launch_command (cCommand);
					g_free (cCommand);
					// On re-définit le chemin du xml
					rtrim (cTmpFileName, ".tar.gz");
					g_free (cReceivedData);
					cReceivedData = g_strdup_printf("%s/%s.xml", cThemePath, cTmpFileName);
				}
				
			}
			g_free (cDonckyThemesPath);
			g_free (cThemePath);
			g_free (cTmpFileName);
			g_free (cTmpThemeName);
		}
		
		if (bContinue)
		{
			cd_debug ("DONCKY-debug : \"%s\" was dropped", cReceivedData);
			
			cd_debug ("DONCKY-debug : This seems to be a valid XML File -> Let's continue...");
			// on definit la nouvelle URL en conf.
			g_free (myConfig.cXmlFilePath);
			myConfig.cXmlFilePath = g_strdup (cReceivedData);
			cairo_dock_update_conf_file (CD_APPLET_MY_CONF_FILE,
				G_TYPE_STRING,
				"Configuration",
				"xml_filepath",
				myConfig.cXmlFilePath,
				G_TYPE_INVALID);  // On l'ecrit dans le fichier de config
			
			cd_doncky_free_item_list (myApplet);
			cd_doncky_readxml (myApplet);
			
			// 2 times to allow xml files to modify the conf :		
			cd_doncky_free_item_list (myApplet);
			cd_doncky_readxml (myApplet);
			return TRUE;
		}
		else
			return FALSE;
		
	}
	else
	{
		cd_debug ("DONCKY-debug : It doesn't seem to be a valid XML.");	
		gldi_dialogs_remove_on_icon (myIcon);
		gldi_dialog_show_temporary_with_icon (D_("It doesn't seem to be a valid XML file."),
			myIcon,
			myContainer,
			3000, // Suffisant 
			MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
		return FALSE;
	}
}