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/>.
23
#include <glib/gstdio.h>
28
#include <glitz-glx.h>
29
#include <cairo-glitz.h>
32
#include "../config.h"
33
#include "cairo-dock-draw.h"
34
#include "cairo-dock-draw-opengl.h"
35
#include "cairo-dock-icons.h"
36
#include "cairo-dock-modules.h"
37
#include "cairo-dock-config.h"
38
#include "cairo-dock-log.h"
39
#include "cairo-dock-desklet-factory.h"
40
#include "cairo-dock-container.h"
41
#include "cairo-dock-surface-factory.h"
42
#include "cairo-dock-callbacks.h"
43
#include "cairo-dock-animations.h"
44
#include "cairo-dock-notifications.h"
45
#include "cairo-dock-internal-system.h"
46
#include "cairo-dock-keyfile-utilities.h"
47
#include "cairo-dock-dock-factory.h"
48
#include "cairo-dock-gui-manager.h"
49
#include "cairo-dock-X-manager.h"
50
#include "cairo-dock-flying-container.h"
53
#define HAND_HEIGHT 50
54
#define EXPLOSION_NB_FRAMES 10
56
extern CairoContainer *g_pPrimaryContainer;
57
extern CairoDockDesktopGeometry g_desktopGeometry;
58
extern gchar *g_cCurrentThemePath;
59
extern gboolean g_bUseOpenGL;
61
static cairo_surface_t *s_pHandSurface = NULL;
62
static GLuint s_iHandTexture = 0;
63
static double s_fHandWidth, s_fHandHeight;
64
static cairo_surface_t *s_pExplosionSurface = NULL;
65
static GLuint s_iExplosionTexture = 0;
66
static double s_fExplosionWidth, s_fExplosionHeight;
68
static void _cairo_dock_load_hand_image (int iWidth)
70
if (s_pHandSurface != NULL || s_iHandTexture != 0)
73
s_pHandSurface = cairo_dock_create_surface_from_image (CAIRO_DOCK_SHARE_DATA_DIR"/hand.svg",
76
CAIRO_DOCK_KEEP_RATIO,
77
&s_fHandWidth, &s_fHandHeight,
79
if (s_pHandSurface != NULL && g_bUseOpenGL)
81
s_iHandTexture = cairo_dock_create_texture_from_surface (s_pHandSurface);
82
cairo_surface_destroy (s_pHandSurface);
83
s_pHandSurface = NULL;
86
static void _cairo_dock_load_explosion_image (int iWidth)
88
if (s_pExplosionSurface != NULL || s_iExplosionTexture != 0)
91
gchar *cExplosionFile = g_strdup_printf ("%s/%s", g_cCurrentThemePath, "explosion.png");
92
if (g_file_test (cExplosionFile, G_FILE_TEST_EXISTS))
94
s_pExplosionSurface = cairo_dock_create_surface_for_icon (cExplosionFile,
95
iWidth * EXPLOSION_NB_FRAMES,
100
s_pExplosionSurface = cairo_dock_create_surface_for_icon (CAIRO_DOCK_SHARE_DATA_DIR"/explosion/explosion.png",
101
iWidth * EXPLOSION_NB_FRAMES,
104
g_free (cExplosionFile);
105
s_fExplosionWidth = iWidth;
106
s_fExplosionHeight = iWidth;
107
if (s_pExplosionSurface != NULL && g_bUseOpenGL)
109
s_iExplosionTexture = cairo_dock_create_texture_from_surface (s_pExplosionSurface);
110
cairo_surface_destroy (s_pExplosionSurface);
111
s_pExplosionSurface = NULL;
116
void cairo_dock_unload_flying_container_textures (void)
118
if (s_iHandTexture != 0)
120
_cairo_dock_delete_texture (s_iHandTexture);
123
if (s_iExplosionTexture != 0)
125
_cairo_dock_delete_texture (s_iExplosionTexture);
126
s_iExplosionTexture = 0;
130
gboolean cairo_dock_update_flying_container_notification (gpointer pUserData, CairoFlyingContainer *pFlyingContainer, gboolean *bContinueAnimation)
132
if (pFlyingContainer->container.iAnimationStep > 0)
134
pFlyingContainer->container.iAnimationStep --;
135
if (pFlyingContainer->container.iAnimationStep == 0)
137
*bContinueAnimation = FALSE;
138
return CAIRO_DOCK_INTERCEPT_NOTIFICATION;
141
gtk_widget_queue_draw (pFlyingContainer->container.pWidget);
143
*bContinueAnimation = TRUE;
144
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
147
gboolean cairo_dock_render_flying_container_notification (gpointer pUserData, CairoFlyingContainer *pFlyingContainer, cairo_t *pCairoContext)
149
Icon *pIcon = pFlyingContainer->pIcon;
150
if (pCairoContext != NULL)
154
cairo_save (pCairoContext);
155
cairo_dock_render_one_icon (pIcon, CAIRO_CONTAINER (pFlyingContainer), pCairoContext, 1., TRUE);
156
cairo_restore (pCairoContext);
158
cairo_set_source_surface (pCairoContext, s_pHandSurface, 0., 0.);
159
cairo_paint (pCairoContext);
161
else if (pFlyingContainer->container.iAnimationStep > 0)
164
int y = (pFlyingContainer->container.iHeight - pFlyingContainer->container.iWidth) / 2;
165
int iCurrentFrame = EXPLOSION_NB_FRAMES - pFlyingContainer->container.iAnimationStep;
167
cairo_rectangle (pCairoContext,
172
cairo_clip (pCairoContext);
174
cairo_set_source_surface (pCairoContext,
176
x - (iCurrentFrame * s_fExplosionWidth),
178
cairo_paint (pCairoContext);
186
/*glTranslatef (pFlyingContainer->container.iWidth / 2,
187
pIcon->fHeight * pIcon->fScale/2,
188
- pFlyingContainer->container.iHeight);*/
189
cairo_dock_render_one_icon_opengl (pIcon, CAIRO_CONTAINER (pFlyingContainer), 1., TRUE);
192
glTranslatef (pFlyingContainer->container.iWidth / 2,
193
pFlyingContainer->container.iHeight - s_fHandHeight/2,
195
cairo_dock_draw_texture (s_iHandTexture, s_fHandWidth, s_fHandHeight);
197
else if (pFlyingContainer->container.iAnimationStep > 0)
199
int iCurrentFrame = EXPLOSION_NB_FRAMES - pFlyingContainer->container.iAnimationStep;
201
glTranslatef (pFlyingContainer->container.iWidth/2,
202
pFlyingContainer->container.iHeight/2,
204
glBindTexture (GL_TEXTURE_2D, s_iExplosionTexture);
205
_cairo_dock_enable_texture ();
206
_cairo_dock_set_blend_source ();
207
_cairo_dock_set_alpha (1.);
208
_cairo_dock_apply_current_texture_portion_at_size_with_offset ((double) iCurrentFrame / EXPLOSION_NB_FRAMES, 1.,
209
1. / EXPLOSION_NB_FRAMES, 1.,
210
s_fExplosionWidth, s_fExplosionHeight,
213
_cairo_dock_disable_texture ();
216
return CAIRO_DOCK_LET_PASS_NOTIFICATION;
220
static gboolean on_expose_flying_icon (GtkWidget *pWidget,
221
GdkEventExpose *pExpose,
222
CairoFlyingContainer *pFlyingContainer)
226
GdkGLContext *pGlContext = gtk_widget_get_gl_context (pWidget);
227
GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable (pWidget);
228
if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
231
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
234
cairo_dock_apply_desktop_background_opengl (CAIRO_CONTAINER (pFlyingContainer));
236
cairo_dock_notify (CAIRO_DOCK_RENDER_FLYING_CONTAINER, pFlyingContainer, NULL);
238
if (gdk_gl_drawable_is_double_buffered (pGlDrawable))
239
gdk_gl_drawable_swap_buffers (pGlDrawable);
242
gdk_gl_drawable_gl_end (pGlDrawable);
243
if (! pFlyingContainer->pIcon) // plus d'icone, le container va se faire detruire sous peu, on repasse donc sur un contexte qui a plus d'avenir, sinon cela peut invalider les fonctions qui font appel a OpenGL sans definir de contexte (genre cairo_dock_create_texture_from_surface).
245
GdkGLContext *pGlContext = gtk_widget_get_gl_context (g_pPrimaryContainer->pWidget);
246
GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable (g_pPrimaryContainer->pWidget);
247
if (gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
248
gdk_gl_drawable_gl_end (pGlDrawable);
253
cairo_t *pCairoContext = cairo_dock_create_drawing_context_on_container (CAIRO_CONTAINER (pFlyingContainer));
255
cairo_dock_notify (CAIRO_DOCK_RENDER_FLYING_CONTAINER, pFlyingContainer, pCairoContext);
257
cairo_destroy (pCairoContext);
263
static gboolean on_configure_flying_icon (GtkWidget* pWidget,
264
GdkEventConfigure* pEvent,
265
CairoFlyingContainer *pFlyingContainer)
267
if (pFlyingContainer->container.iWidth != pEvent->width || pFlyingContainer->container.iHeight != pEvent->height)
269
pFlyingContainer->container.iWidth = pEvent->width;
270
pFlyingContainer->container.iHeight = pEvent->height;
274
GdkGLContext* pGlContext = gtk_widget_get_gl_context (pWidget);
275
GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (pWidget);
276
GLsizei w = pEvent->width;
277
GLsizei h = pEvent->height;
278
if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext))
281
glViewport(0, 0, w, h);
283
cairo_dock_set_ortho_view (CAIRO_CONTAINER (pFlyingContainer));
285
gdk_gl_drawable_gl_end (pGlDrawable);
291
CairoFlyingContainer *cairo_dock_create_flying_container (Icon *pFlyingIcon, CairoDock *pOriginDock, gboolean bDrawHand)
293
g_return_val_if_fail (pFlyingIcon != NULL, NULL);
294
CairoFlyingContainer * pFlyingContainer = g_new0 (CairoFlyingContainer, 1);
295
pFlyingContainer->container.iType = CAIRO_DOCK_TYPE_FLYING_CONTAINER;
296
GtkWidget* pWindow = cairo_dock_init_container (CAIRO_CONTAINER (pFlyingContainer));
297
gtk_window_set_keep_above (GTK_WINDOW (pWindow), TRUE);
298
gtk_window_set_title (GTK_WINDOW(pWindow), "cairo-dock-flying-icon");
299
pFlyingContainer->container.pWidget = pWindow;
300
pFlyingContainer->pIcon = pFlyingIcon;
301
pFlyingContainer->container.bIsHorizontal = TRUE;
302
pFlyingContainer->container.bDirectionUp = TRUE;
303
pFlyingContainer->container.fRatio = 1.;
304
pFlyingContainer->container.bUseReflect = FALSE;
305
cairo_dock_set_default_animation_delta_t (pFlyingContainer);
307
g_signal_connect (G_OBJECT (pWindow),
309
G_CALLBACK (on_expose_flying_icon),
311
g_signal_connect (G_OBJECT (pWindow),
313
G_CALLBACK (on_configure_flying_icon),
316
pFlyingContainer->container.bInside = TRUE;
317
pFlyingIcon->bPointed = TRUE;
318
pFlyingIcon->fScale = 1.;
319
pFlyingContainer->container.iWidth = pFlyingIcon->fWidth * pFlyingIcon->fScale * 3.7;
320
pFlyingContainer->container.iHeight = pFlyingIcon->fHeight * pFlyingIcon->fScale + 1.*pFlyingContainer->container.iWidth / HAND_WIDTH * HAND_HEIGHT * .6;
321
pFlyingIcon->fDrawX = (pFlyingContainer->container.iWidth - pFlyingIcon->fWidth * pFlyingIcon->fScale) / 2 * 1.2;
322
pFlyingIcon->fDrawY = pFlyingContainer->container.iHeight - pFlyingIcon->fHeight * pFlyingIcon->fScale;
324
if (pOriginDock->container.bIsHorizontal)
326
pFlyingContainer->container.iWindowPositionX = pOriginDock->container.iWindowPositionX + pOriginDock->container.iMouseX - pFlyingContainer->container.iWidth/2;
327
pFlyingContainer->container.iWindowPositionY = pOriginDock->container.iWindowPositionY + pOriginDock->container.iMouseY - pFlyingContainer->container.iHeight/2;
331
pFlyingContainer->container.iWindowPositionY = pOriginDock->container.iWindowPositionX + pOriginDock->container.iMouseX - pFlyingContainer->container.iWidth/2;
332
pFlyingContainer->container.iWindowPositionX = pOriginDock->container.iWindowPositionY + pOriginDock->container.iMouseY - pFlyingContainer->container.iHeight/2;
334
/*cd_debug ("%s (%d;%d %dx%d)\n", __func__ pFlyingContainer->container.iWindowPositionX,
335
pFlyingContainer->container.iWindowPositionY,
336
pFlyingContainer->container.iWidth,
337
pFlyingContainer->container.iHeight);*/
338
gdk_window_move_resize (pWindow->window,
339
pFlyingContainer->container.iWindowPositionX,
340
pFlyingContainer->container.iWindowPositionY,
341
pFlyingContainer->container.iWidth,
342
pFlyingContainer->container.iHeight);
343
/*gtk_window_resize (GTK_WINDOW (pWindow),
344
pFlyingContainer->container.iWidth,
345
pFlyingContainer->container.iHeight);
346
gtk_window_move (GTK_WINDOW (pWindow),
347
pFlyingContainer->container.iWindowPositionX,
348
pFlyingContainer->container.iWindowPositionY);*/
349
gtk_window_present (GTK_WINDOW (pWindow));
351
_cairo_dock_load_hand_image (pFlyingContainer->container.iWidth);
352
_cairo_dock_load_explosion_image (pFlyingContainer->container.iWidth);
354
pFlyingContainer->bDrawHand = bDrawHand;
356
cairo_dock_request_icon_animation (pFlyingIcon, CAIRO_CONTAINER (pFlyingContainer), bDrawHand ? "pulse" : "bounce", 1e6);
357
cairo_dock_launch_animation (CAIRO_CONTAINER (pFlyingContainer)); // au cas ou pas d'animation.
360
int r = gettimeofday (&tv, NULL);
361
pFlyingContainer->fCreationTime = tv.tv_sec + tv.tv_usec * 1e-6;
363
return pFlyingContainer;
366
void cairo_dock_drag_flying_container (CairoFlyingContainer *pFlyingContainer, CairoDock *pOriginDock)
368
if (pOriginDock->container.bIsHorizontal)
370
pFlyingContainer->container.iWindowPositionX = pOriginDock->container.iWindowPositionX + pOriginDock->container.iMouseX - pFlyingContainer->container.iWidth/2;
371
pFlyingContainer->container.iWindowPositionY = pOriginDock->container.iWindowPositionY + pOriginDock->container.iMouseY - pFlyingContainer->container.iHeight/2;
375
pFlyingContainer->container.iWindowPositionY = pOriginDock->container.iWindowPositionX + pOriginDock->container.iMouseX - pFlyingContainer->container.iWidth/2;
376
pFlyingContainer->container.iWindowPositionX = pOriginDock->container.iWindowPositionY + pOriginDock->container.iMouseY - pFlyingContainer->container.iHeight/2;
378
//g_print (" on tire l'icone volante en (%d;%d)\n", pFlyingContainer->container.iWindowPositionX, pFlyingContainer->container.iWindowPositionY);
379
gtk_window_move (GTK_WINDOW (pFlyingContainer->container.pWidget),
380
pFlyingContainer->container.iWindowPositionX,
381
pFlyingContainer->container.iWindowPositionY);
384
void cairo_dock_free_flying_container (CairoFlyingContainer *pFlyingContainer)
386
cd_debug ("%s ()", __func__);
387
cairo_dock_finish_container (CAIRO_CONTAINER (pFlyingContainer));
388
g_free (pFlyingContainer);
391
void cairo_dock_terminate_flying_container (CairoFlyingContainer *pFlyingContainer)
393
Icon *pIcon = pFlyingContainer->pIcon;
394
pFlyingContainer->pIcon = NULL;
395
pFlyingContainer->container.iAnimationStep = EXPLOSION_NB_FRAMES+1;
397
if (pIcon->cDesktopFileName != NULL) // c'est un lanceur, ou un separateur manuel, ou un sous-dock.
399
cairo_dock_remove_one_icon_from_dock (NULL, pIcon);
400
cairo_dock_free_icon (pIcon);
402
else if (CAIRO_DOCK_IS_APPLET(pIcon)) /// faire une fonction dans la factory ...
404
cd_debug ("le module %s devient un desklet", pIcon->pModuleInstance->cConfFilePath);
406
cairo_dock_stop_icon_animation (pIcon);
408
cairo_dock_detach_module_instance_at_position (pIcon->pModuleInstance,
409
pFlyingContainer->container.iWindowPositionX + pFlyingContainer->container.iWidth/2,
410
pFlyingContainer->container.iWindowPositionY + pFlyingContainer->container.iHeight/2);