2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
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.
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/>.
24
#include "applet-rotation.h"
25
#include "applet-spot.h"
26
#include "applet-struct.h"
27
#include "applet-rays.h"
28
#include "applet-wobbly.h"
29
#include "applet-mesh-factory.h"
30
#include "applet-wave.h"
31
#include "applet-pulse.h"
32
#include "applet-bounce.h"
33
#include "applet-blink.h"
34
#include "applet-unfold.h"
35
#include "applet-notifications.h"
37
#define _REFLECT_FADE_NB_STEP 12
39
#define _set_new_data(icon) \
40
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);\
42
pData = g_new0 (CDAnimationData, 1);\
43
CD_APPLET_SET_MY_ICON_DATA (pIcon, pData); }\
45
pData->fRadiusFactor = 0;\
46
pData->bIsWobblying = FALSE;\
47
pData->bIsWaving = FALSE;\
48
pData->fPulseAlpha = 0;\
49
pData->bIsBouncing = FALSE;\
50
pData->bIsBlinking = FALSE;\
51
pData->iNumRound = 0;\
52
pData->bIsUnfolding = FALSE; }
54
static void _cd_animations_start (gpointer pUserData, Icon *pIcon, CairoDock *pDock, CDAnimationsEffects *pAnimations, gboolean *bStartAnimation)
56
_set_new_data (pIcon);
58
gboolean bUseOpenGL = CAIRO_DOCK_CONTAINER_IS_OPENGL (CAIRO_CONTAINER (pDock));
59
double dt = (bUseOpenGL ? mySystem.iGLAnimationDeltaT : mySystem.iCairoAnimationDeltaT);
62
for (i = 0; i < CD_ANIMATIONS_NB_EFFECTS; i ++)
64
switch (pAnimations[i])
66
case CD_ANIMATIONS_BOUNCE :
67
cd_animations_init_bounce (pDock, pData, dt);
68
*bStartAnimation = TRUE;
71
case CD_ANIMATIONS_ROTATE :
72
cd_animations_init_rotation (pData, dt, bUseOpenGL);
73
*bStartAnimation = TRUE;
76
case CD_ANIMATIONS_BLINK :
77
cd_animations_init_blink (pData, dt);
78
*bStartAnimation = TRUE;
81
case CD_ANIMATIONS_PULSE :
82
cd_animations_init_pulse (pData, dt);
83
*bStartAnimation = TRUE;
86
case CD_ANIMATIONS_WOBBLY :
87
cd_animations_init_wobbly (pData, bUseOpenGL);
88
*bStartAnimation = TRUE;
91
case CD_ANIMATIONS_WAVE :
94
cd_animations_init_wave (pData);
95
*bStartAnimation = TRUE;
98
case CD_ANIMATIONS_SPOT :
101
cd_animations_init_spot (pIcon, pDock, pData, dt);
102
*bStartAnimation = TRUE;
106
i = CD_ANIMATIONS_NB_EFFECTS - 1;
110
if (pData->fRadiusFactor == 0)
111
pData->fIconOffsetY = 0;
114
gboolean cd_animations_on_enter (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bStartAnimation)
116
if (pIcon->bStatic || ! CAIRO_DOCK_CONTAINER_IS_OPENGL (CAIRO_CONTAINER (pDock)) || pIcon->iAnimationState > CAIRO_DOCK_STATE_MOUSE_HOVERED)
117
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
119
if (pIcon->pSubDock && pIcon->iSubdockViewType == 3 && !myAccessibility.bShowSubDockOnClick)
121
//cd_animations_free_data (pUserData, pIcon);
122
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
125
_cd_animations_start (pUserData, pIcon, pDock, myConfig.iEffectsOnMouseOver, bStartAnimation);
129
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
130
pData->iNumRound = 0;
131
cairo_dock_mark_icon_as_hovered_by_mouse (pIcon);
133
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
136
gboolean cd_animations_on_click (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gint iButtonState)
138
if (! CAIRO_DOCK_IS_DOCK (pDock) || pIcon->iAnimationState > CAIRO_DOCK_STATE_CLICKED)
139
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
141
if (pIcon->pSubDock && pIcon->iSubdockViewType == 3)
143
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
144
if (pData && ! pData->bIsUnfolding)
145
cd_animations_free_data (pUserData, pIcon); // on arrete l'animation en cours.
146
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
149
CairoDockIconType iType = cairo_dock_get_icon_type (pIcon);
150
if (iType == CAIRO_DOCK_LAUNCHER && CAIRO_DOCK_IS_APPLI (pIcon) && ! (iButtonState & GDK_SHIFT_MASK))
151
iType = CAIRO_DOCK_APPLI;
152
/**if (iType == CAIRO_DOCK_APPLI && CAIRO_DOCK_IS_LAUNCHER (pIcon) && iButtonState & GDK_SHIFT_MASK)
153
iType = CAIRO_DOCK_LAUNCHER;*/
155
gboolean bStartAnimation = FALSE;
156
_cd_animations_start (pUserData, pIcon, pDock, myConfig.iEffectsOnClick[iType], &bStartAnimation);
159
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
160
pData->iNumRound = myConfig.iNbRoundsOnClick[iType] - 1;
161
cairo_dock_mark_icon_as_clicked (pIcon);
163
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
166
gboolean cd_animations_on_request (gpointer pUserData, Icon *pIcon, CairoDock *pDock, const gchar *cAnimation, gint iNbRounds)
168
if (cAnimation == NULL || pIcon == NULL || pIcon->iAnimationState > CAIRO_DOCK_STATE_CLICKED)
169
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
171
CDAnimationsEffects anim[2] = {0, -1};
172
if (strcmp (cAnimation, "default") == 0)
174
CairoDockIconType iType = cairo_dock_get_icon_type (pIcon);
175
anim[0] = myConfig.iEffectsOnClick[iType][0];
179
int iAnimationID = cairo_dock_get_animation_id (cAnimation);
180
if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_BOUNCE])
181
anim[0] = CD_ANIMATIONS_BOUNCE;
182
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_ROTATE])
183
anim[0] = CD_ANIMATIONS_ROTATE;
184
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_BLINK])
185
anim[0] = CD_ANIMATIONS_BLINK;
186
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_PULSE])
187
anim[0] = CD_ANIMATIONS_PULSE;
188
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_WOBBLY])
189
anim[0] = CD_ANIMATIONS_WOBBLY;
190
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_WAVE])
191
anim[0] = CD_ANIMATIONS_WAVE;
192
else if (iAnimationID == myData.iAnimationID[CD_ANIMATIONS_SPOT])
193
anim[0] = CD_ANIMATIONS_SPOT;
195
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
198
gboolean bStartAnimation = FALSE;
199
_cd_animations_start (pUserData, pIcon, pDock, anim, &bStartAnimation);
203
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
204
pData->iNumRound = iNbRounds - 1;
205
cairo_dock_mark_icon_as_hovered_by_mouse (pIcon);
207
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
211
static void _cd_animations_render_rays (Icon *pIcon, CairoDock *pDock, CDAnimationData *pData, int iDepth)
214
if (pDock->container.bIsHorizontal)
215
glTranslatef (0., - pIcon->fHeight * pIcon->fScale/2, 0.);
217
glTranslatef (- pIcon->fHeight * pIcon->fScale/2, 0., 0.);
219
if (! pDock->container.bIsHorizontal)
220
glRotatef (-90, 0., 0., 1.);
222
if (pData->pRaysSystem != NULL)
224
cairo_dock_render_particles_full (pData->pRaysSystem, iDepth);
229
gboolean cd_animations_post_render_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bHasBeenRendered, cairo_t *pCairoContext)
231
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
232
if (pData == NULL || pData->bIsUnfolding)
233
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
235
if (pData->bIsBouncing)
237
if (pCairoContext != NULL)
238
cd_animations_draw_bounce_cairo (pIcon, pDock, pData, pCairoContext, -1);
240
cd_animations_draw_bounce_icon (pIcon, pDock, pData, -1);
243
if (pData->bIsBlinking)
245
cd_animations_draw_blink_icon (pIcon, pDock, pData, -1);
248
if (pData->fRadiusFactor != 0)
250
if (pDock->container.bIsHorizontal)
251
glTranslatef (0., - pData->fIconOffsetY * (pDock->container.bDirectionUp ? 1 : -1), 0.);
253
glTranslatef (- pData->fIconOffsetY * (pDock->container.bDirectionUp ? -1 : 1), 0., 0.);
254
if (pData->pRaysSystem != NULL)
255
_cd_animations_render_rays (pIcon, pDock, pData, 1);
257
cd_animation_render_spot_front (pIcon, pDock, pData->fRadiusFactor);
258
if (pData->fHaloRotationAngle > 90 && pData->fHaloRotationAngle < 270)
259
cd_animation_render_halo (pIcon, pDock, pData->fRadiusFactor, pData->fHaloRotationAngle);
261
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
264
gboolean cd_animations_render_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bHasBeenRendered, cairo_t *pCairoContext)
266
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
268
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
270
if (pData->bIsUnfolding && pIcon->pSubDock)
272
if (pCairoContext != NULL)
273
cd_animations_draw_unfolding_icon_cairo (pIcon, pDock, pData, pCairoContext);
275
cd_animations_draw_unfolding_icon (pIcon, pDock, pData);
276
*bHasBeenRendered = TRUE;
277
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
280
gboolean bHasBeenPulsed = FALSE;
281
if (*bHasBeenRendered)
283
if (pData->fPulseAlpha != 0)
285
if (pCairoContext != NULL)
286
cd_animations_draw_pulse_cairo (pIcon, pDock, pData, pCairoContext);
288
cd_animations_draw_pulse_icon (pIcon, pDock, pData);
290
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
293
if (pData->bIsBlinking)
295
cd_animations_draw_blink_icon (pIcon, pDock, pData, 1);
298
if (pData->fRadiusFactor != 0)
300
cd_animation_render_spot (pIcon, pDock, pData->fRadiusFactor);
301
if (pData->fHaloRotationAngle <= 90 || pData->fHaloRotationAngle >= 270)
302
cd_animation_render_halo (pIcon, pDock, pData->fRadiusFactor, pData->fHaloRotationAngle);
304
if (pData->pRaysSystem != NULL)
305
_cd_animations_render_rays (pIcon, pDock, pData, 1);
307
if (pDock->container.bIsHorizontal)
308
glTranslatef (0., pData->fIconOffsetY * (pDock->container.bDirectionUp ? 1 : -1), 0.);
310
glTranslatef (pData->fIconOffsetY * (pDock->container.bDirectionUp ? -1 : 1), 0., 0.);
313
if (pData->bIsBouncing)
315
if (pCairoContext != NULL)
316
cd_animations_draw_bounce_cairo (pIcon, pDock, pData, pCairoContext, 1);
318
cd_animations_draw_bounce_icon (pIcon, pDock, pData, 1);
321
if (pData->bIsWobblying)
323
if (pCairoContext != NULL)
324
cd_animations_draw_wobbly_cairo (pIcon, pDock, pData, pCairoContext);
326
cd_animations_draw_wobbly_icon (pIcon, pDock, pData);
327
*bHasBeenRendered = TRUE;
329
else if (pData->bIsWaving)
331
cd_animations_draw_wave_icon (pIcon, pDock, pData);
332
*bHasBeenRendered = TRUE;
334
else if (pData->fRotationSpeed != 0)
336
if (pCairoContext != NULL)
337
cd_animations_draw_rotating_cairo (pIcon, pDock, pData, pCairoContext);
340
cd_animations_draw_rotating_icon (pIcon, pDock, pData);
341
bHasBeenPulsed = myConfig.bPulseSameShape;
343
*bHasBeenRendered = TRUE;
346
if (pData->fPulseAlpha != 0 && ! bHasBeenPulsed)
348
if (pCairoContext != NULL)
349
cd_animations_draw_pulse_cairo (pIcon, pDock, pData, pCairoContext);
351
cd_animations_draw_pulse_icon (pIcon, pDock, pData);
354
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
358
#define _will_continue(bRepeat) ((pData->iNumRound > 0) || (pIcon->iAnimationState == CAIRO_DOCK_STATE_MOUSE_HOVERED && bRepeat && pIcon->bPointed && pDock->container.bInside))
359
gboolean cd_animations_update_icon (gpointer pUserData, Icon *pIcon, CairoDock *pDock, gboolean *bContinueAnimation)
361
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
363
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
364
gboolean bUseOpenGL = CAIRO_DOCK_CONTAINER_IS_OPENGL (CAIRO_CONTAINER (pDock));
365
double dt = (bUseOpenGL ? mySystem.iGLAnimationDeltaT : mySystem.iCairoAnimationDeltaT);
367
if (pData->bIsUnfolding)
369
if (pIcon->pSubDock->fFoldingFactor == 1 || pIcon->pSubDock == NULL || pIcon->pSubDock->icons == NULL) // fin du pliage.
370
pData->bIsUnfolding = FALSE;
372
*bContinueAnimation = TRUE;
373
cairo_dock_redraw_container (CAIRO_CONTAINER (pDock)); // un peu bourrin ...
374
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
377
if (pData->bIsWobblying)
380
pData->bIsWobblying = cd_animations_update_wobbly (pDock, pData, dt, _will_continue (myConfig.bContinueWobbly));
382
pData->bIsWobblying = cd_animations_update_wobbly_cairo (pIcon, pDock, pData, _will_continue (myConfig.bContinueWobbly));
384
if (! pData->bIsWobblying && _will_continue (myConfig.bContinueWobbly))
387
cd_animations_init_wobbly (pData, bUseOpenGL);
389
if (pData->bIsWobblying)
391
pData->iReflectShadeCount = 0;
392
*bContinueAnimation = TRUE;
395
pData->iReflectShadeCount = _REFLECT_FADE_NB_STEP;
397
if (! pData->bIsWobblying && pData->bIsWaving)
399
pData->bIsWaving = cd_animations_update_wave (pDock, pData, dt);
400
if (! pData->bIsWaving && _will_continue (myConfig.bContinueWave))
403
pData->bIsWaving = TRUE;
404
pData->fWavePosition = - myConfig.fWaveWidth / 2;
406
if (pData->bIsWaving)
408
pData->iReflectShadeCount = 0;
409
*bContinueAnimation = TRUE;
412
pData->iReflectShadeCount = _REFLECT_FADE_NB_STEP;
414
if (! pData->bIsWobblying && ! pData->bIsWaving && pData->fRotationSpeed != 0)
416
cd_animations_update_rotating (pIcon, pDock, pData, bUseOpenGL, _will_continue (myConfig.bContinueRotation));
417
if (pData->fRotationAngle < 360)
419
pData->iReflectShadeCount = 0;
420
*bContinueAnimation = TRUE;
424
if (_will_continue (myConfig.bContinueRotation))
426
pData->fRotationAngle -= 360;
428
pData->iReflectShadeCount = 0;
429
*bContinueAnimation = TRUE;
433
pData->fRotationAngle = 0;
434
pData->fRotationSpeed = 0;
436
pData->iReflectShadeCount = _REFLECT_FADE_NB_STEP;
441
if (pData->iReflectShadeCount != 0)
443
pData->iReflectShadeCount --;
444
pIcon->fReflectShading = (double) pData->iReflectShadeCount / _REFLECT_FADE_NB_STEP;
445
if (pData->iReflectShadeCount != 0)
446
*bContinueAnimation = TRUE;
449
if (pData->fRadiusFactor != 0)
451
gboolean bContinueSpot = cd_animations_update_spot (pIcon, pDock, pData, dt, _will_continue (myConfig.bContinueSpot));
452
if (bContinueSpot) // l'animation doit continuer, qu'on ait passe un tour ou pas.
453
*bContinueAnimation = TRUE;
454
if (pData->fHaloRotationAngle > 360) // un tour est passe.
456
pData->fHaloRotationAngle -= 360;
457
if (pData->iNumRound > 0)
464
if (pData->fPulseAlpha != 0)
466
gboolean bContinuePulse = cd_animations_update_pulse (pIcon, pDock, pData, bUseOpenGL);
468
*bContinueAnimation = TRUE;
469
else if (_will_continue (myConfig.bContinuePulse))
472
cd_animations_init_pulse (pData, dt);
473
*bContinueAnimation = TRUE;
477
if (pData->bIsBouncing)
479
pData->bIsBouncing = cd_animations_update_bounce (pIcon, pDock, pData, dt, bUseOpenGL, _will_continue (myConfig.bContinueBounce));
480
if (! pData->bIsBouncing && _will_continue (myConfig.bContinueBounce))
483
cd_animations_init_bounce (pDock, pData, dt);
485
if (pData->bIsBouncing)
486
*bContinueAnimation = TRUE;
489
if (pData->bIsBlinking)
491
pData->bIsBlinking = cd_animations_update_blink (pIcon, pDock, pData, dt, bUseOpenGL);
492
if (! pData->bIsBlinking && _will_continue (myConfig.bContinueBlink))
495
cd_animations_init_blink (pData, dt);
497
if (pData->bIsBlinking)
498
*bContinueAnimation = TRUE;
501
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
505
gboolean cd_animations_unfold_subdock (gpointer pUserData, Icon *pIcon) // called on start (un)folding.
507
if (pIcon == NULL || pIcon->iSubdockViewType != 3)
508
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
510
CairoDock *pDock = cairo_dock_search_dock_from_name (pIcon->cParentDockName);
513
_set_new_data (pIcon);
514
pData->bIsUnfolding = TRUE;
515
cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
518
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
522
gboolean cd_animations_free_data (gpointer pUserData, Icon *pIcon)
524
CDAnimationData *pData = CD_APPLET_GET_MY_ICON_DATA (pIcon);
526
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
528
cairo_dock_free_particle_system (pData->pRaysSystem);
530
pIcon->fReflectShading = 0.;
531
pIcon->fDeltaYReflection = 0.;
534
CD_APPLET_SET_MY_ICON_DATA (pIcon, NULL);
535
return CAIRO_DOCK_LET_PASS_NOTIFICATION;