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 <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 
24 #include "applet-struct.h"
25 #include "applet-notifications.h"
26 #include "applet-theme.h"
27 #include "applet-animation.h"
28 
29 
penguin_move_in_dock(GldiModuleInstance * myApplet)30 void penguin_move_in_dock (GldiModuleInstance *myApplet)
31 {
32 	static GdkRectangle area;
33 	if (! cairo_dock_animation_will_be_visible (myDock))
34 		return ;
35 
36 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
37 	g_return_if_fail (pAnimation != NULL);
38 	int iPreviousPositionX = myData.iCurrentPositionX, iPreviousPositionY = myData.iCurrentPositionY;
39 
40 	Icon *pFirstDrawnIcon = cairo_dock_get_first_icon (myDock->icons);
41 	int iXMin = (pFirstDrawnIcon != NULL ? pFirstDrawnIcon->fXAtRest : 0);
42 	iXMin = 0;
43 	int iXMax = iXMin + myDock->fFlatDockWidth;
44 	int iHeight = myDock->container.iHeight;
45 
46 	penguin_calculate_new_position (myApplet, pAnimation, iXMin, iXMax, iHeight);
47 
48 	penguin_advance_to_next_frame (myApplet, pAnimation);
49 
50 	if (myDock->container.bIsHorizontal)
51 	{
52 		area.x = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MIN (iPreviousPositionX, myData.iCurrentPositionX));
53 		area.y = myDock->container.iHeight - MAX (iPreviousPositionY, myData.iCurrentPositionY) - pAnimation->iFrameHeight;
54 		area.width = abs (iPreviousPositionX - myData.iCurrentPositionX) + pAnimation->iFrameWidth + 1;  // +1 car sinon on a des trainees parfois, pas compris pourquoi :-/
55 		area.height = abs (iPreviousPositionY - myData.iCurrentPositionY) + pAnimation->iFrameHeight;
56 	}
57 	else
58 	{
59 		if (myDock->container.bDirectionUp)
60 		{
61 			if (!g_bUseOpenGL)
62 			{
63 				area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MAX (iPreviousPositionX, myData.iCurrentPositionX));
64 				area.y = myDock->container.iWidth - area.y;
65 			}
66 			else
67 			{
68 				area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MAX (iPreviousPositionX, myData.iCurrentPositionX)) + pAnimation->iFrameWidth;
69 				area.y = myDock->container.iWidth - area.y;
70 			}
71 			area.x = myDock->container.iHeight - MAX (iPreviousPositionY, myData.iCurrentPositionY) - pAnimation->iFrameHeight;
72 		}
73 		else
74 		{
75 			area.y = (int) ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + MIN (iPreviousPositionX, myData.iCurrentPositionX));
76 			area.x = MAX (iPreviousPositionY, myData.iCurrentPositionY);
77 		}
78 		area.height = abs (iPreviousPositionX - myData.iCurrentPositionX) + pAnimation->iFrameWidth + 1;  // meme remarque sur le +1.
79 		area.width = abs (iPreviousPositionY - myData.iCurrentPositionY) + pAnimation->iFrameHeight;
80 	}
81 	cairo_dock_redraw_container_area (myContainer, &area);
82 }
83 
_penguin_draw_texture(GldiModuleInstance * myApplet,PenguinAnimation * pAnimation,double fOffsetX,double fOffsetY,double fScale)84 static void _penguin_draw_texture (GldiModuleInstance *myApplet, PenguinAnimation *pAnimation, double fOffsetX, double fOffsetY, double fScale)
85 {
86 	g_return_if_fail (pAnimation->iTexture != 0);
87 	int iIconWidth, iIconHeight;
88 	CD_APPLET_GET_MY_ICON_EXTENT (&iIconWidth, &iIconHeight);
89 
90 	_cairo_dock_enable_texture ();
91 	_cairo_dock_set_blend_alpha ();
92 	_cairo_dock_set_alpha (1.);
93 
94 	glBindTexture (GL_TEXTURE_2D, pAnimation->iTexture);
95 	_cairo_dock_apply_current_texture_portion_at_size_with_offset ((double) myData.iCurrentFrame/pAnimation->iNbFrames,
96 		.5*myData.iCurrentDirection,
97 		1./pAnimation->iNbFrames,
98 		1./pAnimation->iNbDirections,
99 		pAnimation->iFrameWidth*fScale,
100 		pAnimation->iFrameHeight*fScale,
101 		floor (fOffsetX + myData.iCurrentPositionX + .5*pAnimation->iFrameWidth) + .5,
102 		floor (fOffsetY + myData.iCurrentPositionY + .5*pAnimation->iFrameHeight*fScale) + .5);
103 	_cairo_dock_disable_texture ();
104 }
penguin_draw_on_dock_opengl(GldiModuleInstance * myApplet,GldiContainer * pContainer)105 void penguin_draw_on_dock_opengl (GldiModuleInstance *myApplet, GldiContainer *pContainer)
106 {
107 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
108 	if (pAnimation == NULL)
109 		return ;
110 
111 	glPushMatrix ();
112 	///glLoadIdentity ();
113 
114 	if (! myDock->container.bIsHorizontal)
115 	{
116 		glTranslatef (myDock->container.iHeight/2, myDock->container.iWidth/2, 0.);
117 		glRotatef (myDock->container.bDirectionUp ? 90. : -90., 0., 0., 1.);
118 		glTranslatef (- myDock->container.iWidth/2, - myDock->container.iHeight/2, 0.);
119 	}
120 	_penguin_draw_texture (myApplet, pAnimation, (myDock->container.iWidth - myDock->fFlatDockWidth) * .5, 0., 1.);
121 
122 	glPopMatrix ();
123 }
124 
penguin_draw_on_dock(GldiModuleInstance * myApplet,GldiContainer * pContainer,cairo_t * pCairoContext)125 void penguin_draw_on_dock (GldiModuleInstance *myApplet, GldiContainer *pContainer, cairo_t *pCairoContext)
126 {
127 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
128 	if (pAnimation == NULL)
129 		return ;
130 
131 	g_return_if_fail (pAnimation->pSurfaces != NULL);
132 	cairo_surface_t *pSurface = pAnimation->pSurfaces[myData.iCurrentDirection][myData.iCurrentFrame];
133 
134 	cairo_save (pCairoContext);
135 	cairo_set_operator (pCairoContext, CAIRO_OPERATOR_OVER);
136 
137 	if (myDock->container.bIsHorizontal)
138 	{
139 		cairo_translate (pCairoContext, floor ((myDock->container.iWidth - myDock->fFlatDockWidth) / 2 + myData.iCurrentPositionX), myDock->container.iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight);
140 		cairo_set_source_surface (pCairoContext, pSurface, 0.0, 0.0);
141 		cairo_paint (pCairoContext);
142 	}
143 	else
144 	{
145 		if (myDock->container.bDirectionUp)
146 			cairo_translate (pCairoContext,
147 				myDock->container.iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight,
148 				floor (myDock->container.iWidth - (.5*(myDock->container.iWidth - myDock->fFlatDockWidth) + myData.iCurrentPositionX)));
149 		else
150 			cairo_translate (pCairoContext,
151 				myData.iCurrentPositionY,
152 				floor (.5*(myDock->container.iWidth - myDock->fFlatDockWidth) + myData.iCurrentPositionX));
153 		cairo_dock_draw_surface (pCairoContext, pSurface, pAnimation->iFrameWidth, pAnimation->iFrameHeight, myDock->container.bDirectionUp, myDock->container.bIsHorizontal, 1.);
154 	}
155 
156 	cairo_restore (pCairoContext);
157 }
penguin_render_on_container(GldiModuleInstance * myApplet,GldiContainer * pContainer,cairo_t * pCairoContext)158 gboolean penguin_render_on_container (GldiModuleInstance *myApplet, GldiContainer *pContainer, cairo_t *pCairoContext)
159 {
160 	if (pContainer != myContainer)
161 		return GLDI_NOTIFICATION_LET_PASS;
162 	if (! cairo_dock_animation_will_be_visible (myDock))
163 		return GLDI_NOTIFICATION_LET_PASS;
164 
165 	if (pCairoContext != NULL)
166 		penguin_draw_on_dock (myApplet, pContainer, pCairoContext);
167 	else
168 		penguin_draw_on_dock_opengl (myApplet, pContainer);
169 	return GLDI_NOTIFICATION_LET_PASS;
170 }
171 
172 
173 
penguin_move_in_icon(GldiModuleInstance * myApplet)174 void penguin_move_in_icon (GldiModuleInstance *myApplet)
175 {
176 	if (! cairo_dock_animation_will_be_visible (myDock))
177 		return ;
178 
179 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
180 	g_return_if_fail (pAnimation != NULL);
181 
182 	double fScale = (pAnimation->iNbFrames > 1 || pAnimation->iSpeed != 0 || pAnimation->iAcceleration != 0 ? myIcon->fScale : 1.);  // s'il est a l'arret on le met a la taille de l'icone au repos.
183 	int iWidth = myIcon->fWidth / myDock->container.fRatio * fScale;
184 	int iHeight = myIcon->fHeight / myDock->container.fRatio * fScale;
185 	int iXMin = - iWidth / 2;
186 	int iXMax = - iXMin;
187 
188 	penguin_calculate_new_position (myApplet, pAnimation, iXMin, iXMax, iHeight);
189 
190 	penguin_advance_to_next_frame (myApplet, pAnimation);
191 
192 	if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
193 	{
194 		CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN ();
195 
196 		int iIconWidth, iIconHeight;
197 		CD_APPLET_GET_MY_ICON_EXTENT (&iIconWidth, &iIconHeight);
198 
199 		g_return_if_fail (pAnimation->iTexture != 0);
200 		double f = (1 + myIconsParam.fAmplitude) / fScale;
201 		double x, y;  // centre du pingouin, en coordonnées absolues.
202 		x = myData.iCurrentPositionX - iXMin - iIconWidth/2 + pAnimation->iFrameWidth/2*f;
203 		y = myData.iCurrentPositionY + pAnimation->iFrameHeight/2*f;
204 
205 		_cairo_dock_enable_texture ();
206 		_cairo_dock_set_blend_alpha ();
207 		_cairo_dock_set_alpha (1.);
208 
209 		glBindTexture (GL_TEXTURE_2D, pAnimation->iTexture);
210 		_cairo_dock_apply_current_texture_portion_at_size_with_offset (1.*myData.iCurrentFrame/pAnimation->iNbFrames,
211 			.5*myData.iCurrentDirection, 1./pAnimation->iNbFrames, 1./pAnimation->iNbDirections,
212 			pAnimation->iFrameWidth*f, pAnimation->iFrameHeight*f,
213 			x, - iIconHeight/2 + y);
214 		_cairo_dock_disable_texture ();
215 
216 		CD_APPLET_FINISH_DRAWING_MY_ICON;
217 	}
218 	else
219 	{
220 		g_return_if_fail (pAnimation->pSurfaces != NULL);
221 		cairo_surface_t *pSurface = pAnimation->pSurfaces[myData.iCurrentDirection][myData.iCurrentFrame];
222 		g_return_if_fail (pSurface != NULL);
223 
224 		CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN_CAIRO ();
225 		//\________________ On efface l'ancienne image.
226 		/**cairo_set_source_rgba (myDrawContext, 0.0, 0.0, 0.0, 0.0);
227 		cairo_set_operator (myDrawContext, CAIRO_OPERATOR_SOURCE);
228 		cairo_paint (myDrawContext);
229 		cairo_set_operator (myDrawContext, CAIRO_OPERATOR_OVER);*/
230 
231 		//\________________ On applique la nouvelle image.
232 		if (pSurface != NULL)
233 		{
234 			cairo_save (myDrawContext);
235 			cairo_scale (myDrawContext, (1 + myIconsParam.fAmplitude) / fScale, (1 + myIconsParam.fAmplitude) / fScale);
236 			cairo_set_source_surface (
237 				myDrawContext,
238 				pSurface,
239 				iXMax + myData.iCurrentPositionX,
240 				iHeight - myData.iCurrentPositionY - pAnimation->iFrameHeight);
241 			cairo_paint (myDrawContext);
242 			cairo_restore (myDrawContext);
243 		}
244 
245 		CD_APPLET_FINISH_DRAWING_MY_ICON_CAIRO;
246 	}
247 
248 	CD_APPLET_REDRAW_MY_ICON;
249 }
250 
251 
252 
penguin_calculate_new_position(GldiModuleInstance * myApplet,PenguinAnimation * pAnimation,int iXMin,int iXMax,int iHeight)253 void penguin_calculate_new_position (GldiModuleInstance *myApplet, PenguinAnimation *pAnimation, int iXMin, int iXMax, int iHeight)
254 {
255 	//\________________ On calule la nouvelle vitesse.
256 	if (pAnimation->iAcceleration != 0 && myData.iCurrentSpeed != pAnimation->iTerminalVelocity)
257 	{
258 		myData.iCurrentSpeed += pAnimation->iAcceleration;
259 		if ( (pAnimation->iAcceleration > 0 && myData.iCurrentSpeed > pAnimation->iTerminalVelocity) || (pAnimation->iAcceleration < 0 && myData.iCurrentSpeed < pAnimation->iTerminalVelocity))
260 			myData.iCurrentSpeed = pAnimation->iTerminalVelocity;
261 	}
262 
263 	//\________________ On calule la nouvelle position.
264 	int sens;
265 	if (pAnimation->iDirection == PENGUIN_HORIZONTAL)
266 	{
267 		sens = (myData.iCurrentDirection == 0 ? -1 : 1);
268 		myData.iCurrentPositionX += sens * myData.iCurrentSpeed;
269 	}
270 	else
271 	{
272 		sens = (pAnimation->iDirection == PENGUIN_UP ? 1 : -1);
273 		myData.iCurrentPositionY += sens * myData.iCurrentSpeed;
274 	}
275 
276 	//\________________ On tient compte des contraintes.
277 	if (myData.iCurrentPositionX < iXMin || myData.iCurrentPositionX + pAnimation->iFrameWidth > iXMax)
278 	{
279 		if (myData.iCurrentPositionX < iXMin)
280 			myData.iCurrentPositionX = iXMin;
281 		else
282 			myData.iCurrentPositionX = iXMax - pAnimation->iFrameWidth;
283 		if (pAnimation->iDirection == PENGUIN_HORIZONTAL && myConfig.bFree)  // dans l'icone on continue l'animation.
284 		{
285 			if (pAnimation->iNbDirections == 2) // on peut repartir dans l'autre sens ou remonter.
286 			{
287 				int iRandom = g_random_int_range (0, 3);
288 				if (iRandom != 0)  // 2 chance sur 3.
289 				{
290 					myData.iCurrentDirection = 1 - myData.iCurrentDirection;
291 					//cd_debug ("myData.iCurrentDirection <- %d", myData.iCurrentDirection);
292 				}
293 				else
294 				{
295 					int iNewAnimation = penguin_choose_go_up_animation (myApplet);
296 					penguin_set_new_animation (myApplet, iNewAnimation);
297 				}
298 			}
299 			else  // on remonte.
300 			{
301 				int iNewAnimation = penguin_choose_go_up_animation (myApplet);
302 				penguin_set_new_animation (myApplet, iNewAnimation);
303 			}
304 		}
305 	}
306 
307 	if (myData.iCurrentPositionY < (myConfig.bFree ? myDocksParam.iDockLineWidth + myConfig.iGroundOffset : 0))
308 	{
309 		myData.iCurrentPositionY = (myConfig.bFree ? myDocksParam.iDockLineWidth + myConfig.iGroundOffset : 0);
310 	}
311 	else if (myData.iCurrentPositionY + pAnimation->iFrameHeight > iHeight)
312 	{
313 		myData.iCurrentPositionY = iHeight - pAnimation->iFrameHeight;
314 	}
315 }
316 
317 
318 
penguin_advance_to_next_frame(GldiModuleInstance * myApplet,PenguinAnimation * pAnimation)319 void penguin_advance_to_next_frame (GldiModuleInstance *myApplet, PenguinAnimation *pAnimation)
320 {
321 	myData.iCurrentFrame ++;
322 	if (myData.iCurrentFrame >= pAnimation->iNbFrames)
323 	{
324 		myData.iCurrentFrame = 0;
325 		myData.iCount ++;
326 
327 		if (pAnimation->bEnding)  // c'est une animation de fin, elle ne se joue qu'une seule fois.
328 		{
329 			myData.iSleepingTime = 0;
330 			if (! myConfig.bFree)
331 			{
332 				CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN_CAIRO ();
333 				///cairo_dock_erase_cairo_context (myDrawContext);  // CD_APPLET_SET_SURFACE_ON_MY_ICON (NULL)
334 
335 				CD_APPLET_FINISH_DRAWING_MY_ICON_CAIRO;
336 				///if (CAIRO_DOCK_CONTAINER_IS_OPENGL (myContainer))
337 				///	cairo_dock_update_icon_texture (myIcon);
338 			}
339 			else  // on reste sur la derniere image de l'animation de fin.
340 			{
341 				myData.iCurrentFrame = pAnimation->iNbFrames - 1;
342 			}
343 
344 			penguin_start_animating_with_delay (myApplet);
345 		}
346 		else if (myData.iCount * myData.fFrameDelay * pAnimation->iNbFrames > myConfig.iDelayBetweenChanges)  // il est temps de changer d'animation.
347 		{
348 			int iNewAnimation = penguin_choose_next_animation (myApplet, pAnimation);
349 			penguin_set_new_animation (myApplet, iNewAnimation);
350 		}
351 	}
352 }
353 
354 
355 
penguin_choose_movement_animation(GldiModuleInstance * myApplet)356 int penguin_choose_movement_animation (GldiModuleInstance *myApplet)
357 {
358 	//cd_debug ("");
359 	if (myData.iNbMovmentAnimations == 0)
360 		return 0;
361 	else
362 	{
363 		int iRandom = g_random_int_range (0, myData.iNbMovmentAnimations);  // [a;b[
364 		//g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbMovmentAnimations, myData.pMovmentAnimations[iRandom]);
365 		return myData.pMovmentAnimations[iRandom];
366 	}
367 }
368 
penguin_choose_go_up_animation(GldiModuleInstance * myApplet)369 int penguin_choose_go_up_animation (GldiModuleInstance *myApplet)
370 {
371 	//cd_debug ("");
372 	if (myData.iNbGoUpAnimations == 0)
373 		return penguin_choose_movement_animation (myApplet);
374 	else
375 	{
376 		int iRandom = g_random_int_range (0, myData.iNbGoUpAnimations);  // [a;b[
377 		//g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbGoUpAnimations, myData.pGoUpAnimations[iRandom]);
378 		return myData.pGoUpAnimations[iRandom];
379 	}
380 }
381 
penguin_choose_beginning_animation(GldiModuleInstance * myApplet)382 int penguin_choose_beginning_animation (GldiModuleInstance *myApplet)
383 {
384 	//cd_debug ("");
385 	if (myData.iNbBeginningAnimations == 0)
386 		return penguin_choose_movement_animation (myApplet);
387 	else
388 	{
389 		int iRandom = g_random_int_range (0, myData.iNbBeginningAnimations);  // [a;b[
390 		//g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbBeginningAnimations, myData.pBeginningAnimations[iRandom]);
391 		return myData.pBeginningAnimations[iRandom];
392 	}
393 }
394 
penguin_choose_ending_animation(GldiModuleInstance * myApplet)395 int penguin_choose_ending_animation (GldiModuleInstance *myApplet)
396 {
397 	//cd_debug ("");
398 	if (myData.iNbEndingAnimations == 0)
399 		return penguin_choose_go_up_animation (myApplet);
400 	else
401 	{
402 		int iRandom = g_random_int_range (0, myData.iNbEndingAnimations);  // [a;b[
403 		//g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbEndingAnimations, myData.pEndingAnimations[iRandom]);
404 		return myData.pEndingAnimations[iRandom];
405 	}
406 }
407 
penguin_choose_resting_animation(GldiModuleInstance * myApplet)408 int penguin_choose_resting_animation (GldiModuleInstance *myApplet)
409 {
410 	//cd_debug ("");
411 	if (myData.iNbRestAnimations == 0)
412 		return penguin_choose_go_up_animation (myApplet);
413 	else
414 	{
415 		int iRandom = g_random_int_range (0, myData.iNbRestAnimations);  // [a;b[
416 		//g_print (  "0<%d<%d => %d\n", iRandom, myData.iNbRestAnimations, myData.pRestAnimations[iRandom]);
417 		return myData.pRestAnimations[iRandom];
418 	}
419 }
420 
penguin_choose_next_animation(GldiModuleInstance * myApplet,PenguinAnimation * pAnimation)421 int penguin_choose_next_animation (GldiModuleInstance *myApplet, PenguinAnimation *pAnimation)
422 {
423 	//cd_debug ("");
424 	int iNewAnimation;
425 	if (pAnimation == NULL || pAnimation->bEnding)  // le pingouin est en fin d'animation, on le relance.
426 	{
427 		iNewAnimation = penguin_choose_beginning_animation (myApplet);
428 	}
429 	else if (pAnimation->iDirection == PENGUIN_HORIZONTAL)  // le pingouin se deplace.
430 	{
431 		if (myConfig.bFree)
432 			iNewAnimation = penguin_choose_movement_animation (myApplet);
433 		else  // dans l'icone on ne repart pas en haut sur les bords.
434 		{
435 			int iRandom = g_random_int_range (0, 3);
436 			if (iRandom == 0)
437 				iNewAnimation = penguin_choose_go_up_animation (myApplet);
438 			else
439 				iNewAnimation = penguin_choose_movement_animation (myApplet);
440 		}
441 	}
442 	else  // le pingouin monte ou descend.
443 	{
444 		if (pAnimation->iDirection == PENGUIN_UP)  // il monte, on le refait descendre.
445 			iNewAnimation = penguin_choose_beginning_animation (myApplet);
446 		else  // il descend, on le fait se deplacer.
447 			iNewAnimation = penguin_choose_movement_animation (myApplet);
448 	}
449 	return iNewAnimation;
450 }
451 
452 
penguin_set_new_animation(GldiModuleInstance * myApplet,int iNewAnimation)453 void penguin_set_new_animation (GldiModuleInstance *myApplet, int iNewAnimation)
454 {
455 	//cd_message ("%s (%d)", __func__, iNewAnimation);
456 	PenguinAnimation *pPreviousAnimation = penguin_get_current_animation ();
457 	int iPreviousWidth = (pPreviousAnimation != NULL ? pPreviousAnimation->iFrameWidth : 0);
458 
459 	myData.iCurrentAnimation = iNewAnimation;
460 	myData.iCurrentFrame = 0;
461 	myData.iCount = 0;
462 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
463 	if (pAnimation == NULL)
464 		return ;
465 	myData.iCurrentSpeed = pAnimation->iSpeed;
466 
467 	if (pAnimation->pSurfaces == NULL && pAnimation->iTexture == 0)
468 	{
469 		penguin_load_animation_buffer (pAnimation, myDrawContext, myConfig.fAlpha, CAIRO_DOCK_CONTAINER_IS_OPENGL (myContainer));
470 	}
471 
472 	if (pAnimation->iDirection == PENGUIN_HORIZONTAL)
473 	{
474 		if (pAnimation->iNbDirections == 2)
475 			myData.iCurrentDirection = g_random_int_range (0, 2);  // [a;b[
476 		else
477 			myData.iCurrentDirection = 0;
478 		myData.iCurrentPositionY = (myConfig.bFree ? myDocksParam.iDockLineWidth + myConfig.iGroundOffset : 0);
479 	}
480 	else  // la direction reste la meme.
481 	{
482 		myData.iCurrentDirection = MIN (myData.iCurrentDirection, pAnimation->iNbDirections - 1);
483 		if (myData.iCurrentDirection == 1)  // on plaque a droite.
484 			myData.iCurrentPositionX += iPreviousWidth - pAnimation->iFrameWidth;
485 		if (pAnimation->iDirection == PENGUIN_DOWN)
486 		{
487 			if (myConfig.bFree)
488 				myData.iCurrentPositionY = myContainer->iHeight;
489 			else
490 				myData.iCurrentPositionY = myIcon->fHeight / myDock->container.fRatio * myIcon->fScale;
491 		}
492 	}
493 }
494 
495 
penguin_update_container(GldiModuleInstance * myApplet,GldiContainer * pContainer,gboolean * bContinueAnimation)496 gboolean penguin_update_container (GldiModuleInstance *myApplet, GldiContainer *pContainer, gboolean *bContinueAnimation)
497 {
498 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
499 	if (pAnimation == NULL || (pAnimation->bEnding && myData.iCount > 0))
500 		return GLDI_NOTIFICATION_LET_PASS;
501 
502 	penguin_move_in_dock (myApplet);
503 	*bContinueAnimation = TRUE;
504 	return GLDI_NOTIFICATION_LET_PASS;
505 }
506 
penguin_update_icon(GldiModuleInstance * myApplet,Icon * pIcon,GldiContainer * pContainer,gboolean * bContinueAnimation)507 gboolean penguin_update_icon (GldiModuleInstance *myApplet, Icon *pIcon, GldiContainer *pContainer, gboolean *bContinueAnimation)
508 {
509 	PenguinAnimation *pAnimation = penguin_get_current_animation ();
510 	if (pAnimation == NULL || (pAnimation->bEnding && myData.iCount > 0))
511 		return GLDI_NOTIFICATION_LET_PASS;
512 
513 	penguin_move_in_icon (myApplet);
514 	*bContinueAnimation = TRUE;
515 	return GLDI_NOTIFICATION_LET_PASS;
516 }
517 
518 
penguin_start_animating(GldiModuleInstance * myApplet)519 void penguin_start_animating (GldiModuleInstance *myApplet)
520 {
521 	int iNewAnimation = penguin_choose_beginning_animation (myApplet);
522 	penguin_set_new_animation (myApplet, iNewAnimation);
523 
524 	penguin_remove_notfications();
525 	if (myConfig.bFree)
526 	{
527 		gldi_object_register_notification (myContainer, NOTIFICATION_UPDATE_SLOW, (GldiNotificationFunc) penguin_update_container, GLDI_RUN_AFTER, myApplet);
528 		gldi_object_register_notification (myContainer, NOTIFICATION_RENDER, (GldiNotificationFunc) penguin_render_on_container, GLDI_RUN_AFTER, myApplet);
529 	}
530 	else
531 	{
532 		gldi_object_register_notification (myIcon, NOTIFICATION_UPDATE_ICON_SLOW, (GldiNotificationFunc) penguin_update_icon, GLDI_RUN_AFTER, myApplet);
533 	}
534 }
535 
_penguin_restart_delayed(GldiModuleInstance * myApplet)536 static gboolean _penguin_restart_delayed (GldiModuleInstance *myApplet)
537 {
538 	myData.iSidRestartDelayed = 0;
539 	penguin_start_animating (myApplet);
540 
541 	if (! myData.bHasBeenStarted)
542 	{
543 		myData.bHasBeenStarted = TRUE;
544 		cd_message ("le pingouin demarre pour la 1ere fois");
545 
546 		if (myConfig.bFree)  // attention : c'est un hack moyen; il faudrait pouvoir indiquer a cairo-dock de ne pas inserer notre icone...
547 		{
548 			gldi_icon_detach (myIcon);
549 		}
550 		else
551 		{
552 			gldi_icon_insert_in_container (myIcon, myContainer, ! CAIRO_DOCK_ANIMATE_ICON);
553 		}
554 		cairo_dock_launch_animation (myContainer);
555 	}
556 
557 	return FALSE;
558 }
penguin_start_animating_with_delay(GldiModuleInstance * myApplet)559 void penguin_start_animating_with_delay (GldiModuleInstance *myApplet)
560 {
561 	if (myData.iSidRestartDelayed != 0)
562 		return ;
563 	if (cairo_dock_is_loading ())
564 	{
565 		myData.iSidRestartDelayed = g_timeout_add_seconds (2, (GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // priorite au chargement du dock, on demarrera plus tard.
566 	}
567 	else
568 	{
569 		myData.iSidRestartDelayed = g_timeout_add_seconds (1, (GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // on est oblige de faire ca, pour detacher l'icone apres que le dock l'ait inseree.
570 		//myData.iSidRestartDelayed = g_idle_add ((GSourceFunc) _penguin_restart_delayed, (gpointer) myApplet);  // on est oblige de faire ca, pour detacher l'icone apres que le dock l'ait inseree.
571 	}
572 }
573