void cd_tomboy_draw_content_on_all_icons (void)
{
	g_print ("%s ()\n", __func__);
	Icon *icon;
	GList *ic, *pList = CD_APPLET_MY_ICONS_LIST;
	for (ic = pList; ic != NULL; ic = ic->next)
	{
		icon = ic->data;
		if (icon->cClass != NULL)
		{
			cairo_t *pIconContext = cairo_create (icon->pIconBuffer);
			cd_tomboy_draw_content_on_icon (pIconContext, icon);
			if (g_bUseOpenGL)
				cairo_dock_update_icon_texture (icon);
			else if (myDock)
				cairo_dock_add_reflection_to_icon (pIconContext, icon, CD_APPLET_MY_ICONS_LIST_CONTAINER);
			cairo_destroy (pIconContext);
		}
	}
}
void cd_tomboy_draw_content_on_icon (cairo_t *pIconContext, Icon *pIcon)
{
	if (pIcon->cClass == NULL || *pIcon->cClass == '\0')  // note vide => rien a afficher.
		return ;
	int w, h;
	cairo_dock_get_icon_extent (pIcon, CD_APPLET_MY_ICONS_LIST_CONTAINER, &w, &h);
	const int iNeedleOffset = 42./200*h;  // on laisse de la place pour l'aiguille de la punaise.
	gchar **cLines = g_strsplit (pIcon->cClass, "\n", -1);
	
	cairo_set_operator (pIconContext, CAIRO_OPERATOR_OVER);
	cairo_set_source_rgb (pIconContext, myConfig.fTextColor[0], myConfig.fTextColor[1], myConfig.fTextColor[2]);

	cairo_select_font_face (pIconContext,
		"sans",
		CAIRO_FONT_SLANT_NORMAL,
		CAIRO_FONT_WEIGHT_NORMAL);
	cairo_set_font_size (pIconContext, (myDock ? 14. : 12.));  // police 12 au zoom maximal.
	cairo_text_extents_t textExtents;
	cairo_text_extents (pIconContext, cLines[0], &textExtents);  // on recupere la hauteur d'une ligne.
	
	int i = 1, j = 1;
	while (cLines[i] != NULL && iNeedleOffset+j*textExtents.height < h)
	{
		if (*cLines[i] != '\0')  // on saute les lignes vides.
		{
			cairo_move_to (pIconContext,
				12./200*h,  // on laisse un peu de place pour ne pas deborder sur la gauche.
				iNeedleOffset+j*(textExtents.height+2));
			cairo_show_text (pIconContext, cLines[i]);
			j ++;
		}
		i ++;
	}
	g_strfreev (cLines);
	
	if (g_bUseOpenGL)
		cairo_dock_update_icon_texture (pIcon);
	else if (myDock)
		cairo_dock_add_reflection_to_icon (pIconContext, pIcon, CD_APPLET_MY_ICONS_LIST_CONTAINER);
}
void cd_switcher_draw_main_icon_compact_mode (void)
{
	//cd_debug ("%s (%d;%d)", __func__, myData.switcher.iCurrentLine, myData.switcher.iCurrentColumn);
	// On efface l'icone.
	cairo_dock_erase_cairo_context (myDrawContext);
	
	// definition des parametres de dessin.
	//double fRatio = (myDock ? myDock->fRatio : 1.);
	//double fMaxScale = cairo_dock_get_max_scale (myContainer); //coefficient Max icone Width
	int iWidth, iHeight;
	CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
	myData.switcher.fOneViewportHeight = (iHeight - 2 * myConfig.iLineSize - (myData.switcher.iNbLines - 1) * myConfig.iInLineSize) / myData.switcher.iNbLines; //hauteur d'un bureau/viewport sans compter les lignes exterieures et interieures.
	myData.switcher.fOneViewportWidth = (iWidth - 2 * myConfig.iLineSize - (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize) / myData.switcher.iNbColumns; //largeur d'un bureau/viewport sans compter les lignes exterieures et interieures.
	
	cairo_surface_t *pSurface = NULL;
	double fZoomX, fZoomY;
	if (myConfig.bMapWallpaper)
	{
		pSurface = cairo_dock_get_desktop_bg_surface ();
		fZoomX = (double) myData.switcher.fOneViewportWidth / g_iXScreenWidth[CAIRO_DOCK_HORIZONTAL];
		fZoomY= (double) myData.switcher.fOneViewportHeight / g_iXScreenHeight[CAIRO_DOCK_HORIZONTAL];
	}
	if (pSurface == NULL)
	{
		pSurface = myData.pDefaultMapSurface;
		fZoomX = (double) myData.switcher.fOneViewportWidth / iWidth;
		fZoomY = (double) myData.switcher.fOneViewportHeight / iHeight;
	}
	
	// cadre exterieur.
	cairo_set_line_width (myDrawContext,myConfig.iLineSize);
	cairo_set_source_rgba(myDrawContext,myConfig.RGBLineColors[0],myConfig.RGBLineColors[1],myConfig.RGBLineColors[2],myConfig.RGBLineColors[3]);
	cairo_rectangle(myDrawContext,
		.5*myConfig.iLineSize,
		.5*myConfig.iLineSize,
		iWidth - myConfig.iLineSize,
		iHeight - myConfig.iLineSize);

	cairo_stroke (myDrawContext);
	
	// lignes interieures.
	cairo_set_line_width (myDrawContext,myConfig.iInLineSize);
	cairo_set_source_rgba(myDrawContext,myConfig.RGBInLineColors[0],myConfig.RGBInLineColors[1],myConfig.RGBInLineColors[2],myConfig.RGBInLineColors[3]);
	double xi, yj;
	int i, j;
	for (i = 1; i < myData.switcher.iNbColumns; i ++)  // lignes verticales.
	{
		xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
		cairo_move_to (myDrawContext, xi, myConfig.iLineSize);
		cairo_rel_line_to (myDrawContext, 0, iHeight - 2*myConfig.iLineSize);
		cairo_stroke (myDrawContext);
	}
	for (j = 1; j < myData.switcher.iNbLines; j ++)  // lignes horizontales.
	{
		yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
		cairo_move_to (myDrawContext, myConfig.iLineSize, yj);
		cairo_rel_line_to (myDrawContext, iWidth - 2*myConfig.iLineSize, 0);
		cairo_stroke (myDrawContext);
	}
	
	GList *pWindowList = NULL;
	if (myConfig.bDrawWindows)
	{
		pWindowList = cairo_dock_get_current_applis_list ();
		pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
	}
	
	// chaque bureau/viewport.
	int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
	int k = 0, N = g_iNbDesktops * g_iNbViewportX * g_iNbViewportY;
	for (j = 0; j < myData.switcher.iNbLines; j ++)
	{
		for (i = 0; i < myData.switcher.iNbColumns; i ++)
		{
			cairo_save (myDrawContext);

			xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize);
			yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize);

			cairo_translate (myDrawContext,
				xi,
				yj);

			cairo_scale (myDrawContext,
				fZoomX,
				fZoomY);
			cairo_set_source_surface (myDrawContext,
				pSurface,
				0.,
				0.);
			cairo_paint(myDrawContext);
			
			cairo_restore (myDrawContext);
			
			if (myConfig.iDrawCurrentDesktopMode == SWICTHER_FILL_INVERTED && (i != myData.switcher.iCurrentColumn || j != myData.switcher.iCurrentLine))
			{
				cairo_save (myDrawContext);
				
				cairo_set_source_rgba (myDrawContext, myConfig.RGBIndColors[0], myConfig.RGBIndColors[1], myConfig.RGBIndColors[2], myConfig.RGBIndColors[3]);
				cairo_rectangle(myDrawContext,
					xi - .5*myConfig.iLineSize,
					yj - .5*myConfig.iLineSize,
					myData.switcher.fOneViewportWidth + myConfig.iLineSize,
					myData.switcher.fOneViewportHeight + myConfig.iLineSize);
				cairo_fill (myDrawContext);
				
				cairo_restore (myDrawContext);
			}
			
			if (myConfig.bDrawWindows)
			{
				cairo_save (myDrawContext);
				
				cairo_translate (myDrawContext,
					xi,
					yj);
				cairo_set_line_width (myDrawContext, 1.);
				cairo_rectangle (myDrawContext,
					0.,
					0.,
					myData.switcher.fOneViewportWidth,
					myData.switcher.fOneViewportHeight);
				cairo_clip (myDrawContext);
				
				//g_print (" dessin des fenetres du bureau (%d;%d;%d) ...\n", iNumDesktop, iNumViewportX, iNumViewportY);
				gint data[6] = {iNumDesktop, iNumViewportX, iNumViewportY, (int) myData.switcher.fOneViewportWidth, (int) myData.switcher.fOneViewportHeight, GPOINTER_TO_INT (myDrawContext)};
				g_list_foreach (pWindowList, (GFunc) _cd_switcher_draw_windows_on_viewport, data);
				
				cairo_restore (myDrawContext);
			}
			
			iNumViewportX ++;
			if (iNumViewportX == g_iNbViewportX)
			{
				iNumViewportY ++;
				if (iNumViewportY == g_iNbViewportY)
					iNumDesktop ++;
			}
			k ++;
			if (k == N)
				break ;
		}
	}
	
	// dessin de l'indicateur sur le bureau courant (on le fait maintenant car dans le cas ou la ligne interieure est plus petite que la ligne de l'indicateur, les surfaces suivantes recouvreraient en partie la ligne.
	if (myConfig.iDrawCurrentDesktopMode != SWICTHER_FILL_INVERTED)
	{
		i = myData.switcher.iCurrentColumn;
		j = myData.switcher.iCurrentLine;
		xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize);
		yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize);
		
		cairo_set_line_width (myDrawContext,myConfig.iLineSize);
		cairo_set_source_rgba (myDrawContext,myConfig.RGBIndColors[0],myConfig.RGBIndColors[1],myConfig.RGBIndColors[2],myConfig.RGBIndColors[3]);
		cairo_rectangle(myDrawContext,
			xi - .5*myConfig.iLineSize,
			yj - .5*myConfig.iLineSize,
			myData.switcher.fOneViewportWidth + myConfig.iLineSize,
			myData.switcher.fOneViewportHeight + myConfig.iLineSize);
		
		if (myConfig.iDrawCurrentDesktopMode == SWICTHER_FILL)
			cairo_fill (myDrawContext);
		else
			cairo_stroke(myDrawContext);
	}
	
	g_list_free (pWindowList);  // le contenu appartient a la hash table, mais pas la liste.
	
	if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
		cairo_dock_update_icon_texture (myIcon);
	else
		CD_APPLET_UPDATE_REFLECT_ON_MY_ICON;
}
void cd_switcher_draw_main_icon_expanded_mode (void)
{
	// definition des parametres de dessin.
	int iWidth, iHeight;
	CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
	//double fRatio = (myDock ? myDock->fRatio : 1.);
	//double fMaxScale = cairo_dock_get_max_scale (myContainer); //coefficient Max icone Width
	myData.switcher.fOneViewportHeight = (iHeight - 2 * myConfig.iLineSize - (myData.switcher.iNbLines - 1) * myConfig.iInLineSize) / myData.switcher.iNbLines; //hauteur d'un bureau/viewport sans compter les lignes exterieures et interieures.
	myData.switcher.fOneViewportWidth = (iWidth - 2 * myConfig.iLineSize - (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize) / myData.switcher.iNbColumns; //largeur d'un bureau/viewport sans compter les lignes exterieures et interieures.

	cairo_surface_t *pSurface = NULL;
	double fZoomX, fZoomY;
	if (myConfig.bMapWallpaper)
	{
		cairo_dock_erase_cairo_context (myDrawContext);
		
		pSurface = cairo_dock_get_desktop_bg_surface ();
		fZoomX = 1. * iWidth / g_iXScreenWidth[CAIRO_DOCK_HORIZONTAL];
		fZoomY= 1. * iHeight / g_iXScreenHeight[CAIRO_DOCK_HORIZONTAL];
		cairo_translate (myDrawContext,
			0.,
			0.);

		cairo_save (myDrawContext);
		cairo_scale (myDrawContext,
			fZoomX ,
			fZoomY );
		cairo_set_source_surface (myDrawContext,
			pSurface,
			0.,
			0.);
		cairo_paint(myDrawContext);
		cairo_restore (myDrawContext);
		
		if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
			cairo_dock_update_icon_texture (myIcon);
		else
			CD_APPLET_UPDATE_REFLECT_ON_MY_ICON;
	}
	else
	{
		CD_APPLET_SET_LOCAL_IMAGE_ON_MY_ICON (MY_APPLET_ICON_FILE);
	}

	if (myConfig.bDrawWindows)
	{
		GList *pWindowList = cairo_dock_get_current_applis_list ();
		pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
		
		//fMaxScale = (myIcon->pSubDock != NULL ? cairo_dock_get_max_scale (myIcon->pSubDock) : 1);
		//fRatio = (myIcon->pSubDock != NULL ? myIcon->pSubDock->fRatio : 1);
		gint data[6];
		int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
		cairo_t *pCairoContext;
		Icon *pIcon;
		CairoContainer *pContainer = CD_APPLET_MY_ICONS_LIST_CONTAINER;
		GList *pIconsList = CD_APPLET_MY_ICONS_LIST;
		GList *ic;
		for (ic = pIconsList; ic != NULL; ic = ic->next)
		{
			pIcon = ic->data;
			cairo_dock_get_icon_extent (pIcon, pContainer, &iWidth, &iHeight);
			
			data[0] = iNumDesktop;
			data[1] = iNumViewportX;
			data[2] = iNumViewportY;
			data[3] = iWidth;
			data[4] = iHeight;
			pCairoContext = cairo_create (pIcon->pIconBuffer);
			data[5] = GPOINTER_TO_INT (pCairoContext);
			cairo_set_line_width (pCairoContext, 1.);
			cairo_set_source_rgba (pCairoContext, myConfig.RGBWLineColors[0], myConfig.RGBWLineColors[1], myConfig.RGBWLineColors[2], myConfig.RGBWLineColors[3]);
		
			g_list_foreach (pWindowList, (GFunc) _cd_switcher_draw_windows_on_viewport, data);
			
			iNumViewportX ++;
			if (iNumViewportX == g_iNbViewportX)
			{
				iNumViewportY ++;
				if (iNumViewportY == g_iNbViewportY)
					iNumDesktop ++;
			}
			cairo_destroy (pCairoContext);
		}
		g_list_free (pWindowList);  // le contenu appartient a la hash table, mais pas la liste.
	}
}
void cd_switcher_draw_main_icon_expanded_mode (void)
{
	// apply the desktop bg or the user image on the main icon, in dock mode
	int iWidth, iHeight;
	
	if (myDock)
	{
		CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
		myData.switcher.fOneViewportHeight = (iHeight - 2 * myConfig.iLineSize - (myData.switcher.iNbLines - 1) * myConfig.iInLineSize) / myData.switcher.iNbLines; //hauteur d'un bureau/viewport sans compter les lignes exterieures et interieures.
		myData.switcher.fOneViewportWidth = (iWidth - 2 * myConfig.iLineSize - (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize) / myData.switcher.iNbColumns; //largeur d'un bureau/viewport sans compter les lignes exterieures et interieures.

		cairo_surface_t *pSurface = NULL;
		double fZoomX, fZoomY;
		if (myConfig.iIconDrawing == SWICTHER_MAP_WALLPAPER)
		{
			cairo_dock_erase_cairo_context (myDrawContext);

			pSurface = myData.pDesktopBgMapSurface;
			fZoomX = 1. * iWidth / myData.iSurfaceWidth;
			fZoomY= 1. * iHeight / myData.iSurfaceHeight;
			cairo_translate (myDrawContext,
				0.,
				0.);

			cairo_save (myDrawContext);
			cairo_scale (myDrawContext,
				fZoomX ,
				fZoomY );
			cairo_set_source_surface (myDrawContext,
				pSurface,
				0.,
				0.);
			cairo_paint(myDrawContext);
			cairo_restore (myDrawContext);

			if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
				cairo_dock_update_icon_texture (myIcon);
		}
		else
		{
			CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
		}
	}
	
	if (myConfig.bDrawWindows)
	{
		GList *pWindowList = cairo_dock_get_current_applis_list ();
		pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
		
		CDSwitcherDesktop data;
		int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
		cairo_t *pCairoContext;
		Icon *pIcon;
		GList *pIconsList = CD_APPLET_MY_ICONS_LIST;
		GList *ic;
		for (ic = pIconsList; ic != NULL; ic = ic->next)
		{
			pIcon = ic->data;
			cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
			
			pCairoContext = cairo_create (pIcon->image.pSurface);
			cairo_set_line_width (pCairoContext, 1.);
			if (myConfig.bUseDefaultColors)
				gldi_style_colors_set_line_color (myDrawContext);
			else
				cairo_set_source_rgba (pCairoContext, myConfig.RGBWLineColors[0], myConfig.RGBWLineColors[1], myConfig.RGBWLineColors[2], myConfig.RGBWLineColors[3]);
			
			data.iNumDesktop = iNumDesktop;
			data.iNumViewportX = iNumViewportX;
			data.iNumViewportY = iNumViewportY;
			data.iOneViewportWidth = iWidth;
			data.iOneViewportHeight = iHeight;
			data.pCairoContext = pCairoContext;
			g_list_foreach (pWindowList, (GFunc) _cd_switcher_draw_windows_on_viewport, &data);
			
			iNumViewportX ++;
			if (iNumViewportX == g_desktopGeometry.iNbViewportX)
			{
				iNumViewportY ++;
				if (iNumViewportY == g_desktopGeometry.iNbViewportY)
					iNumDesktop ++;
			}
			cairo_destroy (pCairoContext);
		}
		g_list_free (pWindowList);  // le contenu appartient a la hash table, mais pas la liste.
	}
}