1 /**
2 * This file is a part of the Cairo-Dock project
3 * Login : <ctaf42@gmail.com>
4 * Started on Sun Jan 27 18:35:38 2008 Cedric GESTES
5 * $Id$
6 *
7 * Author(s)
8 * - Cedric GESTES <ctaf42@gmail.com>
9 * - Fabrice REY
10 *
11 * Copyright (C) 2008 Cedric GESTES
12 * E-mail : see the 'copyright' file.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 3
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include <time.h>
31
32 #include <GL/gl.h>
33 #include <GL/glu.h>
34
35 #include "gldi-config.h"
36 #include "cairo-dock-module-manager.h"
37 #include "cairo-dock-animations.h" // cairo_dock_launch_animation
38 #include "cairo-dock-module-instance-manager.h" // gldi_module_instance_open_conf_file
39 #include "cairo-dock-config.h"
40 #include "cairo-dock-icon-facility.h" // cairo_dock_set_icon_container
41 #include "cairo-dock-desktop-manager.h"
42 #include "cairo-dock-log.h"
43 #include "cairo-dock-container.h"
44 #include "cairo-dock-backends-manager.h"
45 #include "cairo-dock-style-manager.h"
46 #include "cairo-dock-draw.h"
47 #include "cairo-dock-draw-opengl.h"
48 #include "cairo-dock-image-buffer.h"
49 #include "cairo-dock-desklet-factory.h"
50 #include "cairo-dock-opengl.h"
51 #include "cairo-dock-opengl-path.h"
52 #define _MANAGER_DEF_
53 #include "cairo-dock-desklet-manager.h"
54
55 // public (manager, config, data)
56 CairoDeskletsParam myDeskletsParam;
57 GldiManager myDeskletsMgr;
58 GldiObjectManager myDeskletObjectMgr;
59
60 // dependancies
61 extern gboolean g_bUseOpenGL;
62 extern CairoDock *g_pMainDock; // pour savoir s'il faut afficher les boutons rattach.
63
64 // private
65 static CairoDockImageBuffer s_pRotateButtonBuffer;
66 static CairoDockImageBuffer s_pRetachButtonBuffer;
67 static CairoDockImageBuffer s_pDepthRotateButtonBuffer;
68 static CairoDockImageBuffer s_pNoInputButtonBuffer;
69 static GList *s_pDeskletList = NULL;
70 static time_t s_iStartupTime = 0;
71
72 static gboolean _on_update_desklet_notification (gpointer data, CairoDesklet *pDesklet, gboolean *bContinueAnimation);
73 static gboolean _on_enter_leave_desklet_notification (gpointer data, CairoDesklet *pDesklet, gboolean *bStartAnimation);
74 static gboolean _on_render_desklet_notification (gpointer pUserData, CairoDesklet *pDesklet, cairo_t *pCairoContext);
75
76 #define _no_input_button_alpha(pDesklet) (pDesklet->bNoInput ? .4+.6*pDesklet->fButtonsAlpha : pDesklet->fButtonsAlpha)
77 #define ANGLE_MIN .1 // under this angle, the rotation is ignored.
78
_load_desklet_buttons(void)79 void _load_desklet_buttons (void)
80 {
81 if (myDeskletsParam.cRotateButtonImage != NULL)
82 {
83 cairo_dock_load_image_buffer (&s_pRotateButtonBuffer,
84 myDeskletsParam.cRotateButtonImage,
85 myDeskletsParam.iDeskletButtonSize,
86 myDeskletsParam.iDeskletButtonSize,
87 CAIRO_DOCK_FILL_SPACE);
88 }
89 if (s_pRotateButtonBuffer.pSurface == NULL)
90 {
91 cairo_dock_load_image_buffer (&s_pRotateButtonBuffer,
92 GLDI_SHARE_DATA_DIR"/icons/rotate-desklet.svg",
93 myDeskletsParam.iDeskletButtonSize,
94 myDeskletsParam.iDeskletButtonSize,
95 CAIRO_DOCK_FILL_SPACE);
96 }
97
98 if (myDeskletsParam.cRetachButtonImage != NULL)
99 {
100 cairo_dock_load_image_buffer (&s_pRetachButtonBuffer,
101 myDeskletsParam.cRetachButtonImage,
102 myDeskletsParam.iDeskletButtonSize,
103 myDeskletsParam.iDeskletButtonSize,
104 CAIRO_DOCK_FILL_SPACE);
105 }
106 if (s_pRetachButtonBuffer.pSurface == NULL)
107 {
108 cairo_dock_load_image_buffer (&s_pRetachButtonBuffer,
109 GLDI_SHARE_DATA_DIR"/icons/retach-desklet.svg",
110 myDeskletsParam.iDeskletButtonSize,
111 myDeskletsParam.iDeskletButtonSize,
112 CAIRO_DOCK_FILL_SPACE);
113 }
114
115 if (myDeskletsParam.cDepthRotateButtonImage != NULL)
116 {
117 cairo_dock_load_image_buffer (&s_pDepthRotateButtonBuffer,
118 myDeskletsParam.cDepthRotateButtonImage,
119 myDeskletsParam.iDeskletButtonSize,
120 myDeskletsParam.iDeskletButtonSize,
121 CAIRO_DOCK_FILL_SPACE);
122 }
123 if (s_pDepthRotateButtonBuffer.pSurface == NULL)
124 {
125 cairo_dock_load_image_buffer (&s_pDepthRotateButtonBuffer,
126 GLDI_SHARE_DATA_DIR"/icons/depth-rotate-desklet.svg",
127 myDeskletsParam.iDeskletButtonSize,
128 myDeskletsParam.iDeskletButtonSize,
129 CAIRO_DOCK_FILL_SPACE);
130 }
131
132 if (myDeskletsParam.cNoInputButtonImage != NULL)
133 {
134 cairo_dock_load_image_buffer (&s_pNoInputButtonBuffer,
135 myDeskletsParam.cNoInputButtonImage,
136 myDeskletsParam.iDeskletButtonSize,
137 myDeskletsParam.iDeskletButtonSize,
138 CAIRO_DOCK_FILL_SPACE);
139 }
140 if (s_pNoInputButtonBuffer.pSurface == NULL)
141 {
142 cairo_dock_load_image_buffer (&s_pNoInputButtonBuffer,
143 GLDI_SHARE_DATA_DIR"/icons/no-input-desklet.png",
144 myDeskletsParam.iDeskletButtonSize,
145 myDeskletsParam.iDeskletButtonSize,
146 CAIRO_DOCK_FILL_SPACE);
147 }
148 }
149
_unload_desklet_buttons(void)150 static void _unload_desklet_buttons (void)
151 {
152 cairo_dock_unload_image_buffer (&s_pRotateButtonBuffer);
153 cairo_dock_unload_image_buffer (&s_pRetachButtonBuffer);
154 cairo_dock_unload_image_buffer (&s_pDepthRotateButtonBuffer);
155 cairo_dock_unload_image_buffer (&s_pNoInputButtonBuffer);
156 }
157
158
159 ///////////////
160 /// DRAWING ///
161 ///////////////
162
_compute_zoom_for_rotation(CairoDesklet * pDesklet)163 static inline double _compute_zoom_for_rotation (CairoDesklet *pDesklet)
164 {
165 double w = pDesklet->container.iWidth/2, h = pDesklet->container.iHeight/2;
166 double alpha = atan2 (h, w);
167 double theta = fabs (pDesklet->fRotation);
168 if (theta > G_PI/2)
169 theta -= G_PI/2;
170
171 double d = sqrt (w * w + h * h);
172 double xmax = d * MAX (fabs (cos (alpha + theta)), fabs (cos (alpha - theta)));
173 double ymax = d * MAX (fabs (sin (alpha + theta)), fabs (sin (alpha - theta)));
174 double fZoom = MIN (w / xmax, h / ymax);
175 return fZoom;
176 }
177
_render_desklet_cairo(CairoDesklet * pDesklet,cairo_t * pCairoContext)178 static void _render_desklet_cairo (CairoDesklet *pDesklet, cairo_t *pCairoContext)
179 {
180 cairo_save (pCairoContext);
181 gboolean bUseDefaultColors = pDesklet->bUseDefaultColors;
182
183 if (pDesklet->container.fRatio != 1)
184 {
185 //g_print (" desklet zoom : %.2f (%dx%d)\n", pDesklet->container.fRatio, pDesklet->container.iWidth, pDesklet->container.iHeight);
186 cairo_translate (pCairoContext,
187 pDesklet->container.iWidth * (1 - pDesklet->container.fRatio)/2,
188 pDesklet->container.iHeight * (1 - pDesklet->container.fRatio)/2);
189 cairo_scale (pCairoContext, pDesklet->container.fRatio, pDesklet->container.fRatio);
190 }
191
192 if (fabs (pDesklet->fRotation) > ANGLE_MIN)
193 {
194 double fZoom = _compute_zoom_for_rotation (pDesklet);
195
196 cairo_translate (pCairoContext,
197 .5*pDesklet->container.iWidth,
198 .5*pDesklet->container.iHeight);
199
200 cairo_rotate (pCairoContext, pDesklet->fRotation);
201
202 cairo_scale (pCairoContext, fZoom, fZoom);
203
204 cairo_translate (pCairoContext,
205 -.5*pDesklet->container.iWidth,
206 -.5*pDesklet->container.iHeight);
207 }
208
209 if (bUseDefaultColors)
210 {
211 cairo_save (pCairoContext);
212 cairo_dock_draw_rounded_rectangle (pCairoContext, myStyleParam.iCornerRadius, myStyleParam.iLineWidth, pDesklet->container.iWidth - 2 * (myStyleParam.iCornerRadius + myStyleParam.iLineWidth), pDesklet->container.iHeight - myStyleParam.iLineWidth);
213 gldi_style_colors_set_bg_color (pCairoContext);
214 cairo_fill_preserve (pCairoContext);
215 gldi_style_colors_set_line_color (pCairoContext);
216 cairo_set_line_width (pCairoContext, myStyleParam.iLineWidth);
217 cairo_stroke (pCairoContext);
218 cairo_restore (pCairoContext);
219 }
220 else if (pDesklet->backGroundImageBuffer.pSurface != NULL)
221 {
222 cairo_dock_apply_image_buffer_surface (&pDesklet->backGroundImageBuffer, pCairoContext);
223 }
224
225 cairo_save (pCairoContext);
226 if (pDesklet->iLeftSurfaceOffset != 0 || pDesklet->iTopSurfaceOffset != 0 || pDesklet->iRightSurfaceOffset != 0 || pDesklet->iBottomSurfaceOffset != 0)
227 {
228 cairo_translate (pCairoContext, pDesklet->iLeftSurfaceOffset, pDesklet->iTopSurfaceOffset);
229 cairo_scale (pCairoContext,
230 1. - (double)(pDesklet->iLeftSurfaceOffset + pDesklet->iRightSurfaceOffset) / pDesklet->container.iWidth,
231 1. - (double)(pDesklet->iTopSurfaceOffset + pDesklet->iBottomSurfaceOffset) / pDesklet->container.iHeight);
232 }
233
234 if (pDesklet->pRenderer != NULL && pDesklet->pRenderer->render != NULL) // un moteur de rendu specifique a ete fourni.
235 {
236 pDesklet->pRenderer->render (pCairoContext, pDesklet);
237 }
238 cairo_restore (pCairoContext);
239
240 if (pDesklet->foreGroundImageBuffer.pSurface != NULL)
241 {
242 cairo_dock_apply_image_buffer_surface (&pDesklet->foreGroundImageBuffer, pCairoContext);
243 }
244
245 if (! pDesklet->rotating) // si on est en train de tourner, les boutons suivent le mouvement, sinon ils sont dans les coins.
246 {
247 cairo_restore (pCairoContext);
248 cairo_save (pCairoContext);
249 }
250 if ((pDesklet->container.bInside || pDesklet->rotating || pDesklet->fButtonsAlpha != 0) && cairo_dock_desklet_is_free (pDesklet))
251 {
252 if (s_pRotateButtonBuffer.pSurface != NULL)
253 {
254 cairo_dock_apply_image_buffer_surface_with_offset (&s_pRotateButtonBuffer, pCairoContext,
255 0., 0., pDesklet->fButtonsAlpha);
256 }
257 if (s_pRetachButtonBuffer.pSurface != NULL && g_pMainDock)
258 {
259 cairo_dock_apply_image_buffer_surface_with_offset (&s_pRetachButtonBuffer, pCairoContext,
260 pDesklet->container.iWidth - s_pRetachButtonBuffer.iWidth, 0., pDesklet->fButtonsAlpha);
261 }
262 }
263 if ((pDesklet->container.bInside || pDesklet->bNoInput || pDesklet->fButtonsAlpha) && s_pNoInputButtonBuffer.pSurface != NULL && pDesklet->bAllowNoClickable)
264 {
265 cairo_dock_apply_image_buffer_surface_with_offset (&s_pNoInputButtonBuffer, pCairoContext,
266 pDesklet->container.iWidth - s_pNoInputButtonBuffer.iWidth, pDesklet->container.iHeight - s_pNoInputButtonBuffer.iHeight, _no_input_button_alpha (pDesklet));
267 }
268 cairo_restore (pCairoContext);
269 }
270
_set_desklet_matrix(CairoDesklet * pDesklet)271 static inline void _set_desklet_matrix (CairoDesklet *pDesklet)
272 {
273 double fDepthRotationY = (fabs (pDesklet->fDepthRotationY) > ANGLE_MIN ? pDesklet->fDepthRotationY : 0.);
274 double fDepthRotationX = (fabs (pDesklet->fDepthRotationX) > ANGLE_MIN ? pDesklet->fDepthRotationX : 0.);
275 glTranslatef (0., 0., -pDesklet->container.iHeight * sqrt(3)/2 -
276 .45 * MAX (pDesklet->container.iWidth * fabs (sin (fDepthRotationY)),
277 pDesklet->container.iHeight * fabs (sin (fDepthRotationX)))
278 ); // avec 60 deg de perspective
279
280 if (pDesklet->container.fRatio != 1)
281 {
282 glScalef (pDesklet->container.fRatio, pDesklet->container.fRatio, 1.);
283 }
284
285 if (fabs (pDesklet->fRotation) > ANGLE_MIN)
286 {
287 double fZoom = _compute_zoom_for_rotation (pDesklet);
288 glScalef (fZoom, fZoom, 1.);
289 glRotatef (- pDesklet->fRotation / G_PI * 180., 0., 0., 1.);
290 }
291
292 if (fDepthRotationY != 0)
293 {
294 glRotatef (- pDesklet->fDepthRotationY / G_PI * 180., 0., 1., 0.);
295 }
296
297 if (fDepthRotationX != 0)
298 {
299 glRotatef (- pDesklet->fDepthRotationX / G_PI * 180., 1., 0., 0.);
300 }
301 }
302
_render_desklet_opengl(CairoDesklet * pDesklet)303 static void _render_desklet_opengl (CairoDesklet *pDesklet)
304 {
305 gboolean bUseDefaultColors = pDesklet->bUseDefaultColors;
306 glPushMatrix ();
307 ///glTranslatef (0*pDesklet->container.iWidth/2, 0*pDesklet->container.iHeight/2, 0.); // avec une perspective ortho.
308 ///glTranslatef (0*pDesklet->container.iWidth/2, 0*pDesklet->container.iHeight/2, -pDesklet->container.iWidth*(1.87 +.35*fabs (sin(pDesklet->fDepthRotationY)))); // avec 30 deg de perspective
309 _set_desklet_matrix (pDesklet);
310
311 if (bUseDefaultColors)
312 {
313 _cairo_dock_set_blend_alpha ();
314 gldi_style_colors_set_bg_color (NULL);
315 cairo_dock_draw_rounded_rectangle_opengl (pDesklet->container.iWidth - 2 * (myStyleParam.iCornerRadius + myStyleParam.iLineWidth), pDesklet->container.iHeight - 2*myStyleParam.iLineWidth, myStyleParam.iCornerRadius, 0, NULL);
316
317 gldi_style_colors_set_line_color (NULL);
318 cairo_dock_draw_rounded_rectangle_opengl (pDesklet->container.iWidth - 2 * (myStyleParam.iCornerRadius + myStyleParam.iLineWidth), pDesklet->container.iHeight - 2*myStyleParam.iLineWidth, myStyleParam.iCornerRadius, myStyleParam.iLineWidth, NULL);
319 }
320
321 _cairo_dock_enable_texture ();
322 _cairo_dock_set_blend_pbuffer ();
323 _cairo_dock_set_alpha (1.);
324 if (pDesklet->backGroundImageBuffer.iTexture != 0)
325 {
326 cairo_dock_apply_image_buffer_texture (&pDesklet->backGroundImageBuffer);
327 }
328
329 glPushMatrix ();
330 if (pDesklet->iLeftSurfaceOffset != 0 || pDesklet->iTopSurfaceOffset != 0 || pDesklet->iRightSurfaceOffset != 0 || pDesklet->iBottomSurfaceOffset != 0)
331 {
332 glTranslatef ((pDesklet->iLeftSurfaceOffset - pDesklet->iRightSurfaceOffset)/2, (pDesklet->iBottomSurfaceOffset - pDesklet->iTopSurfaceOffset)/2, 0.);
333 glScalef (1. - (double)(pDesklet->iLeftSurfaceOffset + pDesklet->iRightSurfaceOffset) / pDesklet->container.iWidth,
334 1. - (double)(pDesklet->iTopSurfaceOffset + pDesklet->iBottomSurfaceOffset) / pDesklet->container.iHeight,
335 1.);
336 }
337
338 if (pDesklet->pRenderer != NULL && pDesklet->pRenderer->render_opengl != NULL) // un moteur de rendu specifique a ete fourni.
339 {
340 pDesklet->pRenderer->render_opengl (pDesklet);
341 }
342 glPopMatrix ();
343
344 _cairo_dock_enable_texture ();
345 _cairo_dock_set_blend_pbuffer ();
346 if (pDesklet->foreGroundImageBuffer.iTexture != 0)
347 {
348 cairo_dock_apply_image_buffer_texture (&pDesklet->foreGroundImageBuffer);
349 }
350
351 //if (pDesklet->container.bInside && cairo_dock_desklet_is_free (pDesklet))
352 {
353 if (! pDesklet->rotating && ! pDesklet->rotatingY && ! pDesklet->rotatingX)
354 {
355 glPopMatrix ();
356 glPushMatrix ();
357 glTranslatef (0., 0., -pDesklet->container.iHeight*(sqrt(3)/2));
358 }
359 }
360
361 if ((pDesklet->container.bInside || pDesklet->fButtonsAlpha != 0 || pDesklet->rotating || pDesklet->rotatingY || pDesklet->rotatingX) && cairo_dock_desklet_is_free (pDesklet))
362 {
363 _cairo_dock_set_blend_alpha ();
364 _cairo_dock_set_alpha (sqrt(pDesklet->fButtonsAlpha));
365 if (s_pRotateButtonBuffer.iTexture != 0)
366 {
367 cairo_dock_apply_image_buffer_texture_with_offset (&s_pRotateButtonBuffer,
368 -pDesklet->container.iWidth/2 + s_pRotateButtonBuffer.iWidth/2,
369 pDesklet->container.iHeight/2 - s_pRotateButtonBuffer.iHeight/2);
370 }
371 if (s_pRetachButtonBuffer.iTexture != 0 && g_pMainDock)
372 {
373 cairo_dock_apply_image_buffer_texture_with_offset (&s_pRetachButtonBuffer,
374 pDesklet->container.iWidth/2 - s_pRetachButtonBuffer.iWidth/2,
375 pDesklet->container.iHeight/2 - s_pRetachButtonBuffer.iHeight/2);
376 }
377 if (s_pDepthRotateButtonBuffer.iTexture != 0)
378 {
379 cairo_dock_apply_image_buffer_texture_with_offset (&s_pDepthRotateButtonBuffer,
380 0.,
381 pDesklet->container.iHeight/2 - s_pDepthRotateButtonBuffer.iHeight/2);
382
383 glPushMatrix ();
384 glRotatef (90., 0., 0., 1.);
385 cairo_dock_apply_image_buffer_texture_with_offset (&s_pDepthRotateButtonBuffer,
386 0.,
387 pDesklet->container.iWidth/2 - s_pDepthRotateButtonBuffer.iHeight/2);
388 glPopMatrix ();
389 }
390 }
391 if ((pDesklet->container.bInside || pDesklet->fButtonsAlpha != 0 || pDesklet->bNoInput) && s_pNoInputButtonBuffer.iTexture != 0 && pDesklet->bAllowNoClickable)
392 {
393 _cairo_dock_set_blend_alpha ();
394 _cairo_dock_set_alpha (_no_input_button_alpha(pDesklet));
395 cairo_dock_apply_image_buffer_texture_with_offset (&s_pNoInputButtonBuffer,
396 pDesklet->container.iWidth/2 - s_pNoInputButtonBuffer.iWidth/2,
397 - pDesklet->container.iHeight/2 + s_pNoInputButtonBuffer.iHeight/2);
398 }
399
400 _cairo_dock_disable_texture ();
401 glPopMatrix ();
402 }
403
_on_render_desklet_notification(G_GNUC_UNUSED gpointer pUserData,CairoDesklet * pDesklet,cairo_t * pCairoContext)404 static gboolean _on_render_desklet_notification (G_GNUC_UNUSED gpointer pUserData, CairoDesklet *pDesklet, cairo_t *pCairoContext)
405 {
406 if (pCairoContext != NULL)
407 _render_desklet_cairo (pDesklet, pCairoContext);
408 else
409 _render_desklet_opengl (pDesklet);
410 return GLDI_NOTIFICATION_LET_PASS;
411 }
412
_on_enter_leave_desklet_notification(G_GNUC_UNUSED gpointer data,CairoDesklet * pDesklet,gboolean * bStartAnimation)413 static gboolean _on_enter_leave_desklet_notification (G_GNUC_UNUSED gpointer data, CairoDesklet *pDesklet, gboolean *bStartAnimation)
414 {
415 pDesklet->bButtonsApparition = TRUE;
416 *bStartAnimation = TRUE;
417 return GLDI_NOTIFICATION_LET_PASS;
418 }
419
_on_update_desklet_notification(G_GNUC_UNUSED gpointer data,CairoDesklet * pDesklet,gboolean * bContinueAnimation)420 static gboolean _on_update_desklet_notification (G_GNUC_UNUSED gpointer data, CairoDesklet *pDesklet, gboolean *bContinueAnimation)
421 {
422 if (!pDesklet->bButtonsApparition && !pDesklet->bGrowingUp)
423 return GLDI_NOTIFICATION_LET_PASS;
424
425 if (pDesklet->bButtonsApparition)
426 {
427 pDesklet->fButtonsAlpha += (pDesklet->container.bInside ? .1 : -.1);
428 //g_print ("fButtonsAlpha <- %.2f\n", pDesklet->fButtonsAlpha);
429
430 if (pDesklet->fButtonsAlpha <= 0 || pDesklet->fButtonsAlpha >= 1)
431 {
432 pDesklet->bButtonsApparition = FALSE;
433 if (pDesklet->fButtonsAlpha < 0)
434 pDesklet->fButtonsAlpha = 0.;
435 else if (pDesklet->fButtonsAlpha > 1)
436 pDesklet->fButtonsAlpha = 1.;
437 }
438 else
439 {
440 *bContinueAnimation = TRUE;
441 }
442 }
443
444 if (pDesklet->bGrowingUp)
445 {
446 pDesklet->container.fRatio += .04;
447 //g_print ("pDesklet->container.fRatio:%.2f\n", pDesklet->container.fRatio);
448
449 if (pDesklet->container.fRatio >= 1.1) // la derniere est a x1.1
450 {
451 pDesklet->container.fRatio = 1;
452 pDesklet->bGrowingUp = FALSE;
453 }
454 else
455 {
456 *bContinueAnimation = TRUE;
457 }
458 }
459
460 gtk_widget_queue_draw (pDesklet->container.pWidget);
461 return GLDI_NOTIFICATION_LET_PASS;
462 }
463
_cairo_dock_pick_icon_on_opengl_desklet(CairoDesklet * pDesklet)464 static Icon *_cairo_dock_pick_icon_on_opengl_desklet (CairoDesklet *pDesklet)
465 {
466 GLuint selectBuf[4];
467 GLint hits=0;
468 GLint viewport[4];
469
470 if (! gldi_gl_container_make_current (CAIRO_CONTAINER (pDesklet)))
471 return NULL;
472
473 glGetIntegerv (GL_VIEWPORT, viewport);
474 glSelectBuffer (4, selectBuf);
475
476 glRenderMode(GL_SELECT);
477 glInitNames();
478 glPushName(0);
479
480 glMatrixMode (GL_PROJECTION);
481 glPushMatrix ();
482 glLoadIdentity ();
483 gluPickMatrix ((GLdouble) pDesklet->container.iMouseX, (GLdouble) (viewport[3] - pDesklet->container.iMouseY), 2.0, 2.0, viewport);
484 gluPerspective (60.0, 1.0*(GLfloat)pDesklet->container.iWidth/(GLfloat)pDesklet->container.iHeight, 1., 4*pDesklet->container.iHeight);
485
486 glMatrixMode (GL_MODELVIEW);
487 glPushMatrix ();
488 glLoadIdentity ();
489
490 _set_desklet_matrix (pDesklet);
491
492 if (pDesklet->iLeftSurfaceOffset != 0 || pDesklet->iTopSurfaceOffset != 0 || pDesklet->iRightSurfaceOffset != 0 || pDesklet->iBottomSurfaceOffset != 0)
493 {
494 glTranslatef ((pDesklet->iLeftSurfaceOffset - pDesklet->iRightSurfaceOffset)/2, (pDesklet->iBottomSurfaceOffset - pDesklet->iTopSurfaceOffset)/2, 0.);
495 glScalef (1. - (double)(pDesklet->iLeftSurfaceOffset + pDesklet->iRightSurfaceOffset) / pDesklet->container.iWidth,
496 1. - (double)(pDesklet->iTopSurfaceOffset + pDesklet->iBottomSurfaceOffset) / pDesklet->container.iHeight,
497 1.);
498 }
499
500 glPolygonMode (GL_FRONT, GL_FILL);
501 glColor4f (1., 1., 1., 1.);
502
503 pDesklet->iPickedObject = 0;
504 if (pDesklet->render_bounding_box != NULL) // surclasse la fonction du moteur de rendu.
505 {
506 pDesklet->render_bounding_box (pDesklet);
507 }
508 else if (pDesklet->pRenderer && pDesklet->pRenderer->render_bounding_box != NULL)
509 {
510 pDesklet->pRenderer->render_bounding_box (pDesklet);
511 }
512 else // on le fait nous-memes a partir des coordonnees des icones.
513 {
514 glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
515
516 double x, y, w, h;
517 Icon *pIcon;
518
519 pIcon = pDesklet->pIcon;
520 if (pIcon != NULL && pIcon->image.iTexture != 0)
521 {
522 w = pIcon->fWidth/2;
523 h = pIcon->fHeight/2;
524 x = pIcon->fDrawX + w;
525 y = pDesklet->container.iHeight - pIcon->fDrawY - h;
526
527 glLoadName(pIcon->image.iTexture);
528
529 glBegin(GL_QUADS);
530 glVertex3f(x-w, y+h, 0.);
531 glVertex3f(x+w, y+h, 0.);
532 glVertex3f(x+w, y-h, 0.);
533 glVertex3f(x-w, y-h, 0.);
534 glEnd();
535 }
536
537 GList *ic;
538 for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
539 {
540 pIcon = ic->data;
541 if (pIcon->image.iTexture == 0)
542 continue;
543
544 w = pIcon->fWidth/2;
545 h = pIcon->fHeight/2;
546 x = pIcon->fDrawX + w;
547 y = pDesklet->container.iHeight - pIcon->fDrawY - h;
548
549 glLoadName(pIcon->image.iTexture);
550
551 glBegin(GL_QUADS);
552 glVertex3f(x-w, y+h, 0.);
553 glVertex3f(x+w, y+h, 0.);
554 glVertex3f(x+w, y-h, 0.);
555 glVertex3f(x-w, y-h, 0.);
556 glEnd();
557 }
558 }
559
560 glPopName();
561
562 hits = glRenderMode (GL_RENDER);
563
564 glMatrixMode (GL_PROJECTION);
565 glPopMatrix ();
566 glMatrixMode(GL_MODELVIEW);
567 glPopMatrix ();
568
569 Icon *pFoundIcon = NULL;
570 if (hits != 0)
571 {
572 GLuint id = selectBuf[3];
573 Icon *pIcon;
574
575 if (pDesklet->render_bounding_box != NULL)
576 {
577 pDesklet->iPickedObject = id;
578 //g_print ("iPickedObject <- %d\n", id);
579 pFoundIcon = pDesklet->pIcon; // il faut mettre qqch, sinon la notification est filtree par la macro CD_APPLET_ON_CLICK_BEGIN.
580 }
581 else
582 {
583 pIcon = pDesklet->pIcon;
584 if (pIcon != NULL && pIcon->image.iTexture != 0)
585 {
586 if (pIcon->image.iTexture == id)
587 {
588 pFoundIcon = pIcon;
589 }
590 }
591
592 if (pFoundIcon == NULL)
593 {
594 GList *ic;
595 for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
596 {
597 pIcon = ic->data;
598 if (pIcon->image.iTexture == id)
599 {
600 pFoundIcon = pIcon;
601 break ;
602 }
603 }
604 }
605 }
606 }
607
608 return pFoundIcon;
609 }
gldi_desklet_find_clicked_icon(CairoDesklet * pDesklet)610 Icon *gldi_desklet_find_clicked_icon (CairoDesklet *pDesklet)
611 {
612 if (g_bUseOpenGL && pDesklet->pRenderer && pDesklet->pRenderer->render_opengl)
613 {
614 return _cairo_dock_pick_icon_on_opengl_desklet (pDesklet);
615 }
616
617 int iMouseX = pDesklet->container.iMouseX, iMouseY = pDesklet->container.iMouseY;
618 if (fabs (pDesklet->fRotation) > ANGLE_MIN)
619 {
620 //g_print (" clic en (%d;%d) rotations : %.2frad\n", iMouseX, iMouseY, pDesklet->fRotation);
621 double x, y; // par rapport au centre du desklet.
622 x = iMouseX - pDesklet->container.iWidth/2;
623 y = pDesklet->container.iHeight/2 - iMouseY;
624
625 double r, t; // coordonnees polaires.
626 r = sqrt (x*x + y*y);
627 t = atan2 (y, x);
628
629 double z = _compute_zoom_for_rotation (pDesklet);
630 r /= z;
631
632 x = r * cos (t + pDesklet->fRotation); // la rotation de cairo est dans le sene horaire.
633 y = r * sin (t + pDesklet->fRotation);
634
635 iMouseX = x + pDesklet->container.iWidth/2;
636 iMouseY = pDesklet->container.iHeight/2 - y;
637 //g_print (" => (%d;%d)\n", iMouseX, iMouseY);
638 }
639 pDesklet->iMouseX2d = iMouseX;
640 pDesklet->iMouseY2d = iMouseY;
641
642 Icon *icon = pDesklet->pIcon;
643 g_return_val_if_fail (icon != NULL, NULL); // peut arriver au tout debut, car on associe l'icone au desklet _apres_ l'avoir cree, et on fait tourner la gtk_main entre-temps (pour le redessiner invisible).
644 if (icon->fDrawX < iMouseX && icon->fDrawX + icon->fWidth * icon->fScale > iMouseX && icon->fDrawY < iMouseY && icon->fDrawY + icon->fHeight * icon->fScale > iMouseY)
645 {
646 return icon;
647 }
648
649 if (pDesklet->icons != NULL)
650 {
651 GList* ic;
652 for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
653 {
654 icon = ic->data;
655 if (icon->fDrawX < iMouseX && icon->fDrawX + icon->fWidth * icon->fScale > iMouseX && icon->fDrawY < iMouseY && icon->fDrawY + icon->fHeight * icon->fScale > iMouseY)
656 {
657 return icon;
658 }
659 }
660 }
661 return NULL;
662 }
663
664
665 ///////////////
666 /// MANAGER ///
667 ///////////////
668
gldi_desklets_foreach(GldiDeskletForeachFunc pCallback,gpointer user_data)669 CairoDesklet *gldi_desklets_foreach (GldiDeskletForeachFunc pCallback, gpointer user_data)
670 {
671 CairoDesklet *pDesklet;
672 GList *dl;
673 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
674 {
675 pDesklet = dl->data;
676 if (pCallback (pDesklet, user_data))
677 return pDesklet;
678 }
679
680 return NULL;
681 }
682
_foreach_icons_in_desklet(CairoDesklet * pDesklet,gpointer * data)683 static gboolean _foreach_icons_in_desklet (CairoDesklet *pDesklet, gpointer *data)
684 {
685 GldiIconFunc pFunction = data[0];
686 gpointer pUserData = data[1];
687 if (pDesklet->pIcon != NULL)
688 pFunction (pDesklet->pIcon, pUserData);
689 GList *ic;
690 for (ic = pDesklet->icons; ic != NULL; ic = ic->next)
691 {
692 pFunction ((Icon*)ic->data, pUserData);
693 }
694 return FALSE;
695 }
gldi_desklets_foreach_icons(GldiIconFunc pFunction,gpointer pUserData)696 void gldi_desklets_foreach_icons (GldiIconFunc pFunction, gpointer pUserData)
697 {
698 gpointer data[2] = {pFunction, pUserData};
699 gldi_desklets_foreach ((GldiDeskletForeachFunc) _foreach_icons_in_desklet, data);
700 }
701
702
_set_one_desklet_visible(CairoDesklet * pDesklet,gpointer data)703 static void _set_one_desklet_visible (CairoDesklet *pDesklet, gpointer data)
704 {
705 gboolean bOnWidgetLayerToo = GPOINTER_TO_INT (data);
706 gboolean bIsOnWidgetLayer = (pDesklet->iVisibility == CAIRO_DESKLET_ON_WIDGET_LAYER);
707 if (bOnWidgetLayerToo || ! bIsOnWidgetLayer)
708 {
709 if (bIsOnWidgetLayer) // on le passe sur la couche visible.
710 gldi_desktop_set_on_widget_layer (CAIRO_CONTAINER (pDesklet), FALSE);
711
712 gtk_window_set_keep_below (GTK_WINDOW (pDesklet->container.pWidget), FALSE);
713
714 gldi_desklet_show (pDesklet);
715 }
716 }
gldi_desklets_set_visible(gboolean bOnWidgetLayerToo)717 void gldi_desklets_set_visible (gboolean bOnWidgetLayerToo)
718 {
719 cd_debug ("%s (%d)", __func__, bOnWidgetLayerToo);
720 CairoDesklet *pDesklet;
721 GList *dl;
722 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
723 {
724 pDesklet = dl->data;
725 _set_one_desklet_visible (pDesklet, GINT_TO_POINTER (bOnWidgetLayerToo));
726 }
727 }
728
_set_one_desklet_visibility_to_default(CairoDesklet * pDesklet,CairoDockMinimalAppletConfig * pMinimalConfig)729 static void _set_one_desklet_visibility_to_default (CairoDesklet *pDesklet, CairoDockMinimalAppletConfig *pMinimalConfig)
730 {
731 if (pDesklet->pIcon != NULL)
732 {
733 GldiModuleInstance *pInstance = pDesklet->pIcon->pModuleInstance;
734 GKeyFile *pKeyFile = gldi_module_instance_open_conf_file (pInstance, pMinimalConfig);
735 g_key_file_free (pKeyFile);
736
737 gldi_desklet_set_accessibility (pDesklet, pMinimalConfig->deskletAttribute.iVisibility, FALSE);
738 }
739 pDesklet->bAllowMinimize = FALSE; /// utile ?...
740 }
gldi_desklets_set_visibility_to_default(void)741 void gldi_desklets_set_visibility_to_default (void)
742 {
743 CairoDockMinimalAppletConfig minimalConfig;
744 CairoDesklet *pDesklet;
745 GList *dl;
746 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
747 {
748 pDesklet = dl->data;
749 _set_one_desklet_visibility_to_default (pDesklet, &minimalConfig);
750 }
751 }
752
753
gldi_desklet_manager_is_ready(void)754 gboolean gldi_desklet_manager_is_ready (void)
755 {
756 static gboolean bReady = FALSE;
757 if (!bReady) // once we are ready, no need to test it again.
758 {
759 bReady = (time (NULL) > s_iStartupTime + 5); // 5s delay on startup
760 }
761 return bReady;
762 }
763
_on_desktop_geometry_changed(G_GNUC_UNUSED gpointer data)764 static gboolean _on_desktop_geometry_changed (G_GNUC_UNUSED gpointer data)
765 {
766 // when the screen size changes, X will send a 'configure' event to each windows (because size and position might have changed), which will be interpreted by the desklet as a user displacement.
767 // we must therefore replace the desklets at their correct position in the new desktop space.
768 CairoDesklet *pDesklet;
769 CairoDockMinimalAppletConfig *pMinimalConfig;
770 GList *dl;
771 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
772 {
773 pDesklet = dl->data;
774 //g_print ("%s : %d;%d\n", pDesklet->pIcon->pModuleInstance->pModule->pVisitCard->cModuleName, pDesklet->container.iWindowPositionX, pDesklet->container.iWindowPositionY);
775
776 if (CAIRO_DOCK_IS_APPLET (pDesklet->pIcon))
777 {
778 // get the position (and other parameters) as defined by the user.
779 pMinimalConfig = g_new0 (CairoDockMinimalAppletConfig, 1);
780 GKeyFile *pKeyFile = gldi_module_instance_open_conf_file (pDesklet->pIcon->pModuleInstance, pMinimalConfig);
781 //g_print (" %d;%d\n", pMinimalConfig->deskletAttribute.iDeskletPositionX, pMinimalConfig->deskletAttribute.iDeskletPositionY);
782
783 // apply the settings to the desklet (actually we only need the position).
784 gldi_desklet_configure (pDesklet, &pMinimalConfig->deskletAttribute);
785 gldi_module_instance_free_generic_config (pMinimalConfig);
786 g_key_file_free (pKeyFile);
787 }
788 }
789 return GLDI_NOTIFICATION_LET_PASS;
790 }
791
792
793 //////////////////
794 /// GET CONFIG ///
795 //////////////////
796
get_config(GKeyFile * pKeyFile,CairoDeskletsParam * pDesklets)797 static gboolean get_config (GKeyFile *pKeyFile, CairoDeskletsParam *pDesklets)
798 {
799 gboolean bFlushConfFileNeeded = FALSE;
800
801 // register an "automatic" decoration, that takes its colors from the global style (do it now, after the global style has been defined)
802 CairoDeskletDecoration * pDecoration = cairo_dock_get_desklet_decoration ("automatic");
803 if (pDecoration == NULL)
804 {
805 pDecoration = g_new0 (CairoDeskletDecoration, 1);
806 pDecoration->cDisplayedName = _("Automatic");
807 pDecoration->iLeftMargin = pDecoration->iTopMargin = pDecoration->iRightMargin = pDecoration->iBottomMargin = myStyleParam.iLineWidth;
808 pDecoration->fBackGroundAlpha = 1.;
809 pDecoration->cBackGroundImagePath = g_strdup ("automatic"); // keyword to say we use global style colors rather an image
810 cairo_dock_register_desklet_decoration ("automatic", pDecoration); // we don't actually load an Imagebuffer,
811 }
812
813 // register a "custom" decoration, that takes its colors from the config if the use has defined it
814 pDesklets->cDeskletDecorationsName = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "decorations", &bFlushConfFileNeeded, NULL, NULL, NULL);
815 CairoDeskletDecoration *pUserDeskletDecorations = cairo_dock_get_desklet_decoration ("personnal");
816 if (pUserDeskletDecorations == NULL)
817 {
818 pUserDeskletDecorations = g_new0 (CairoDeskletDecoration, 1);
819 pUserDeskletDecorations->cDisplayedName = _("_custom decoration_");
820 cairo_dock_register_desklet_decoration ("personnal", pUserDeskletDecorations);
821 }
822 if (pDesklets->cDeskletDecorationsName != NULL && strcmp (pDesklets->cDeskletDecorationsName, "personnal") == 0)
823 {
824 g_free (pUserDeskletDecorations->cBackGroundImagePath);
825 pUserDeskletDecorations->cBackGroundImagePath = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "bg desklet", &bFlushConfFileNeeded, NULL, NULL, NULL);
826 g_free (pUserDeskletDecorations->cForeGroundImagePath);
827 pUserDeskletDecorations->cForeGroundImagePath = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "fg desklet", &bFlushConfFileNeeded, NULL, NULL, NULL);
828 pUserDeskletDecorations->iLoadingModifier = CAIRO_DOCK_FILL_SPACE;
829 pUserDeskletDecorations->fBackGroundAlpha = cairo_dock_get_double_key_value (pKeyFile, "Desklets", "bg alpha", &bFlushConfFileNeeded, 1.0, NULL, NULL);
830 pUserDeskletDecorations->fForeGroundAlpha = cairo_dock_get_double_key_value (pKeyFile, "Desklets", "fg alpha", &bFlushConfFileNeeded, 1.0, NULL, NULL);
831 pUserDeskletDecorations->iLeftMargin = cairo_dock_get_integer_key_value (pKeyFile, "Desklets", "left offset", &bFlushConfFileNeeded, 0, NULL, NULL);
832 pUserDeskletDecorations->iTopMargin = cairo_dock_get_integer_key_value (pKeyFile, "Desklets", "top offset", &bFlushConfFileNeeded, 0, NULL, NULL);
833 pUserDeskletDecorations->iRightMargin = cairo_dock_get_integer_key_value (pKeyFile, "Desklets", "right offset", &bFlushConfFileNeeded, 0, NULL, NULL);
834 pUserDeskletDecorations->iBottomMargin = cairo_dock_get_integer_key_value (pKeyFile, "Desklets", "bottom offset", &bFlushConfFileNeeded, 0, NULL, NULL);
835 }
836
837 pDesklets->iDeskletButtonSize = cairo_dock_get_integer_key_value (pKeyFile, "Desklets", "button size", &bFlushConfFileNeeded, 16, NULL, NULL);
838 pDesklets->cRotateButtonImage = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "rotate image", &bFlushConfFileNeeded, NULL, NULL, NULL);
839 pDesklets->cRetachButtonImage = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "retach image", &bFlushConfFileNeeded, NULL, NULL, NULL);
840 pDesklets->cDepthRotateButtonImage = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "depth rotate image", &bFlushConfFileNeeded, NULL, NULL, NULL);
841 pDesklets->cNoInputButtonImage = cairo_dock_get_string_key_value (pKeyFile, "Desklets", "no input image", &bFlushConfFileNeeded, NULL, NULL, NULL);
842 return bFlushConfFileNeeded;
843 }
844
845 ////////////////////
846 /// RESET CONFIG ///
847 ////////////////////
848
reset_config(CairoDeskletsParam * pDesklets)849 static void reset_config (CairoDeskletsParam *pDesklets)
850 {
851 g_free (pDesklets->cDeskletDecorationsName);
852 g_free (pDesklets->cRotateButtonImage);
853 g_free (pDesklets->cRetachButtonImage);
854 g_free (pDesklets->cDepthRotateButtonImage);
855 g_free (pDesklets->cNoInputButtonImage);
856 }
857
858 //////////////
859 /// RELOAD ///
860 //////////////
861
reload(CairoDeskletsParam * pPrevDesklets,CairoDeskletsParam * pDesklets)862 static void reload (CairoDeskletsParam *pPrevDesklets, CairoDeskletsParam *pDesklets)
863 {
864 if (g_strcmp0 (pPrevDesklets->cRotateButtonImage, pDesklets->cRotateButtonImage) != 0
865 || g_strcmp0 (pPrevDesklets->cRetachButtonImage, pDesklets->cRetachButtonImage) != 0
866 || g_strcmp0 (pPrevDesklets->cDepthRotateButtonImage, pDesklets->cDepthRotateButtonImage) != 0
867 || g_strcmp0 (pPrevDesklets->cNoInputButtonImage, pDesklets->cNoInputButtonImage) != 0)
868 {
869 _unload_desklet_buttons ();
870 _load_desklet_buttons ();
871 }
872 if (g_strcmp0 (pPrevDesklets->cDeskletDecorationsName, pDesklets->cDeskletDecorationsName) != 0) // the default theme has changed -> reload all desklets that use it
873 {
874 CairoDesklet *pDesklet;
875 GList *dl;
876 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
877 {
878 pDesklet = dl->data;
879 if (pDesklet->cDecorationTheme == NULL || strcmp (pDesklet->cDecorationTheme, "default") == 0)
880 {
881 gldi_desklet_load_desklet_decorations (pDesklet);
882 }
883 }
884 }
885 }
886
887 //////////////
888 /// UNLOAD ///
889 //////////////
890
unload(void)891 static void unload (void)
892 {
893 _unload_desklet_buttons ();
894 }
895
896 ////////////
897 /// INIT ///
898 ////////////
899
on_style_changed(G_GNUC_UNUSED gpointer data)900 static gboolean on_style_changed (G_GNUC_UNUSED gpointer data)
901 {
902 cd_debug ("Desklets: style change to %s", myDeskletsParam.cDeskletDecorationsName);
903 gboolean bUseDefaultColors = (!myDeskletsParam.cDeskletDecorationsName || strcmp (myDeskletsParam.cDeskletDecorationsName, "automatic") == 0);
904
905 CairoDeskletDecoration * pDecoration = cairo_dock_get_desklet_decoration ("automatic");
906 if (pDecoration)
907 pDecoration->iLeftMargin = pDecoration->iTopMargin = pDecoration->iRightMargin = pDecoration->iBottomMargin = myStyleParam.iLineWidth;
908
909 CairoDesklet *pDesklet;
910 GList *dl;
911 for (dl = s_pDeskletList; dl != NULL; dl = dl->next)
912 {
913 pDesklet = dl->data;
914 if ( ((pDesklet->cDecorationTheme == NULL || strcmp (pDesklet->cDecorationTheme, "default") == 0) && bUseDefaultColors)
915 || strcmp (pDesklet->cDecorationTheme, "automatic") == 0)
916 {
917 cd_debug ("Reload desklet's bg...");
918 gldi_desklet_load_desklet_decorations (pDesklet);
919 cairo_dock_redraw_container (CAIRO_CONTAINER (pDesklet));
920 }
921 }
922 return GLDI_NOTIFICATION_LET_PASS;
923 }
924
init(void)925 static void init (void)
926 {
927 gldi_object_register_notification (&myDeskletObjectMgr,
928 NOTIFICATION_UPDATE,
929 (GldiNotificationFunc) _on_update_desklet_notification,
930 GLDI_RUN_FIRST, NULL);
931 gldi_object_register_notification (&myDeskletObjectMgr,
932 NOTIFICATION_ENTER_DESKLET,
933 (GldiNotificationFunc) _on_enter_leave_desklet_notification,
934 GLDI_RUN_FIRST, NULL);
935 gldi_object_register_notification (&myDeskletObjectMgr,
936 NOTIFICATION_LEAVE_DESKLET,
937 (GldiNotificationFunc) _on_enter_leave_desklet_notification,
938 GLDI_RUN_FIRST, NULL);
939 gldi_object_register_notification (&myDeskletObjectMgr,
940 NOTIFICATION_RENDER,
941 (GldiNotificationFunc) _on_render_desklet_notification,
942 GLDI_RUN_FIRST, NULL);
943 gldi_object_register_notification (&myDesktopMgr,
944 NOTIFICATION_DESKTOP_GEOMETRY_CHANGED,
945 (GldiNotificationFunc) _on_desktop_geometry_changed,
946 GLDI_RUN_AFTER, NULL); // replace all desklets that are positionned relatively to the right or bottom edge
947 gldi_object_register_notification (&myStyleMgr,
948 NOTIFICATION_STYLE_CHANGED,
949 (GldiNotificationFunc) on_style_changed,
950 GLDI_RUN_AFTER, NULL);
951 s_iStartupTime = time (NULL); // on startup, the WM can take a long time before it has positionned all the desklets. To avoid irrelevant configure events, we set a delay.
952 }
953
954 ///////////////
955 /// MANAGER ///
956 ///////////////
957
init_object(GldiObject * obj,gpointer attr)958 static void init_object (GldiObject *obj, gpointer attr)
959 {
960 CairoDesklet *pDesklet = (CairoDesklet*)obj;
961 CairoDeskletAttr *pAttributes = (CairoDeskletAttr*)attr;
962 g_return_if_fail (pAttributes->pIcon != NULL);
963
964 gldi_desklet_init_internals (pDesklet);
965
966 // attach the main icon
967 Icon *pIcon = pAttributes->pIcon;
968 pDesklet->pIcon = pIcon;
969 cairo_dock_set_icon_container (pIcon, pDesklet);
970 if (CAIRO_DOCK_IS_APPLET (pIcon))
971 gtk_window_set_title (GTK_WINDOW (pDesklet->container.pWidget), pIcon->pModuleInstance->pModule->pVisitCard->cModuleName);
972
973 // configure the desklet
974 gldi_desklet_configure (pDesklet, pAttributes);
975
976 // load buttons images
977 if (s_pRotateButtonBuffer.pSurface == NULL)
978 {
979 _load_desklet_buttons ();
980 }
981
982 // register the new desklet
983 s_pDeskletList = g_list_prepend (s_pDeskletList, pDesklet);
984
985 // start the appearance animation
986 if (! cairo_dock_is_loading ())
987 {
988 pDesklet->container.fRatio = 0.1;
989 pDesklet->bGrowingUp = TRUE;
990 cairo_dock_launch_animation (CAIRO_CONTAINER (pDesklet));
991 }
992 }
993
reset_object(GldiObject * obj)994 static void reset_object (GldiObject *obj)
995 {
996 CairoDesklet *pDesklet = (CairoDesklet*)obj;
997
998 // stop timers
999 if (pDesklet->iSidWriteSize != 0)
1000 g_source_remove (pDesklet->iSidWriteSize);
1001 if (pDesklet->iSidWritePosition != 0)
1002 g_source_remove (pDesklet->iSidWritePosition);
1003
1004 // detach the main icon
1005 Icon *pIcon = pDesklet->pIcon;
1006 if (pIcon != NULL)
1007 {
1008 if (pIcon->pContainer != NULL && pIcon->pContainer != CAIRO_CONTAINER (pDesklet)) // shouldn't happen
1009 cd_warning ("This icon (%s) has not been detached from its desklet properly !", pIcon->cName);
1010 else
1011 cairo_dock_set_icon_container (pIcon, NULL);
1012 }
1013
1014 // detach the interactive widget
1015 gldi_desklet_steal_interactive_widget (pDesklet);
1016
1017 // free sub-icons
1018 if (pDesklet->icons != NULL)
1019 {
1020 GList *icons = pDesklet->icons;
1021 pDesklet->icons = NULL;
1022 g_list_foreach (icons, (GFunc) gldi_object_unref, NULL);
1023 g_list_free (icons);
1024 }
1025
1026 // free data
1027 if (pDesklet->pRenderer != NULL)
1028 {
1029 if (pDesklet->pRenderer->free_data != NULL)
1030 {
1031 pDesklet->pRenderer->free_data (pDesklet);
1032 pDesklet->pRendererData = NULL;
1033 }
1034 }
1035
1036 g_free (pDesklet->cDecorationTheme);
1037 gldi_desklet_decoration_free (pDesklet->pUserDecoration);
1038
1039 cairo_dock_unload_image_buffer (&pDesklet->backGroundImageBuffer);
1040 cairo_dock_unload_image_buffer (&pDesklet->foreGroundImageBuffer);
1041
1042 // unregister the desklet
1043 s_pDeskletList = g_list_remove (s_pDeskletList, pDesklet);
1044 }
1045
gldi_register_desklets_manager(void)1046 void gldi_register_desklets_manager (void)
1047 {
1048 // Manager
1049 memset (&myDeskletsMgr, 0, sizeof (GldiManager));
1050 gldi_object_init (GLDI_OBJECT(&myDeskletsMgr), &myManagerObjectMgr, NULL);
1051 myDeskletsMgr.cModuleName = "Desklets";
1052 // interface
1053 myDeskletsMgr.init = init;
1054 myDeskletsMgr.load = NULL; // data are loaded the first time a desklet is created, to avoid create them for nothing.
1055 myDeskletsMgr.unload = unload;
1056 myDeskletsMgr.reload = (GldiManagerReloadFunc)reload;
1057 myDeskletsMgr.get_config = (GldiManagerGetConfigFunc)get_config;
1058 myDeskletsMgr.reset_config = (GldiManagerResetConfigFunc)reset_config;
1059 // Config
1060 memset (&myDeskletsParam, 0, sizeof (CairoDeskletsParam));
1061 myDeskletsMgr.pConfig = (GldiManagerConfigPtr)&myDeskletsParam;
1062 myDeskletsMgr.iSizeOfConfig = sizeof (CairoDeskletsParam);
1063 // data
1064 memset (&s_pRotateButtonBuffer, 0, sizeof (CairoDockImageBuffer));
1065 memset (&s_pRetachButtonBuffer, 0, sizeof (CairoDockImageBuffer));
1066 memset (&s_pDepthRotateButtonBuffer, 0, sizeof (CairoDockImageBuffer));
1067 memset (&s_pNoInputButtonBuffer, 0, sizeof (CairoDockImageBuffer));
1068 myDeskletsMgr.iSizeOfData = 0;
1069 myDeskletsMgr.pData = (GldiManagerDataPtr)NULL;
1070
1071 // Object Manager
1072 memset (&myDeskletObjectMgr, 0, sizeof (GldiObjectManager));
1073 myDeskletObjectMgr.cName = "Desklet";
1074 myDeskletObjectMgr.iObjectSize = sizeof (CairoDesklet);
1075 // interface
1076 myDeskletObjectMgr.init_object = init_object;
1077 myDeskletObjectMgr.reset_object = reset_object;
1078 // signals
1079 gldi_object_install_notifications (&myDeskletObjectMgr, NB_NOTIFICATIONS_DESKLET);
1080 // parent object
1081 gldi_object_set_manager (GLDI_OBJECT (&myDeskletObjectMgr), &myContainerObjectMgr);
1082 }
1083