~cairo-dock-team/ubuntu/oneiric/cairo-dock/2.3.0-3

« back to all changes in this revision

Viewing changes to src/gldit/cairo-dock-flying-container.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: james.westby@ubuntu.com-20100809232612-pocdxliaxjdetm37
Tags: upstream-2.2.0~0beta4
ImportĀ upstreamĀ versionĀ 2.2.0~0beta4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <sys/time.h>
 
22
#include <cairo.h>
 
23
#include <glib/gstdio.h>
 
24
#include <gtk/gtk.h>
 
25
 
 
26
#ifdef HAVE_GLITZ
 
27
#include <gdk/gdkx.h>
 
28
#include <glitz-glx.h>
 
29
#include <cairo-glitz.h>
 
30
#endif
 
31
 
 
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"
 
51
 
 
52
#define HAND_WIDTH 80
 
53
#define HAND_HEIGHT 50
 
54
#define EXPLOSION_NB_FRAMES 10
 
55
 
 
56
extern CairoContainer *g_pPrimaryContainer;
 
57
extern CairoDockDesktopGeometry g_desktopGeometry;
 
58
extern gchar *g_cCurrentThemePath;
 
59
extern gboolean g_bUseOpenGL;
 
60
 
 
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;
 
67
 
 
68
static void _cairo_dock_load_hand_image (int iWidth)
 
69
{
 
70
        if (s_pHandSurface != NULL || s_iHandTexture != 0)
 
71
                return ;
 
72
        
 
73
        s_pHandSurface = cairo_dock_create_surface_from_image (CAIRO_DOCK_SHARE_DATA_DIR"/hand.svg",
 
74
                1.,
 
75
                iWidth, 0.,
 
76
                CAIRO_DOCK_KEEP_RATIO,
 
77
                &s_fHandWidth, &s_fHandHeight,
 
78
                NULL, NULL);
 
79
        if (s_pHandSurface != NULL && g_bUseOpenGL)
 
80
        {
 
81
                s_iHandTexture = cairo_dock_create_texture_from_surface (s_pHandSurface);
 
82
                cairo_surface_destroy (s_pHandSurface);
 
83
                s_pHandSurface = NULL;
 
84
        }
 
85
}
 
86
static void _cairo_dock_load_explosion_image (int iWidth)
 
87
{
 
88
        if (s_pExplosionSurface != NULL || s_iExplosionTexture != 0)
 
89
                return ;
 
90
        
 
91
        gchar *cExplosionFile = g_strdup_printf ("%s/%s", g_cCurrentThemePath, "explosion.png");
 
92
        if (g_file_test (cExplosionFile, G_FILE_TEST_EXISTS))
 
93
        {
 
94
                s_pExplosionSurface = cairo_dock_create_surface_for_icon (cExplosionFile,
 
95
                        iWidth * EXPLOSION_NB_FRAMES,
 
96
                        iWidth);
 
97
        }
 
98
        else
 
99
        {
 
100
                s_pExplosionSurface = cairo_dock_create_surface_for_icon (CAIRO_DOCK_SHARE_DATA_DIR"/explosion/explosion.png",
 
101
                        iWidth * EXPLOSION_NB_FRAMES,
 
102
                        iWidth);
 
103
        }
 
104
        g_free (cExplosionFile);
 
105
        s_fExplosionWidth = iWidth;
 
106
        s_fExplosionHeight = iWidth;
 
107
        if (s_pExplosionSurface != NULL && g_bUseOpenGL)
 
108
        {
 
109
                s_iExplosionTexture = cairo_dock_create_texture_from_surface (s_pExplosionSurface);
 
110
                cairo_surface_destroy (s_pExplosionSurface);
 
111
                s_pExplosionSurface = NULL;
 
112
        }
 
113
}
 
114
 
 
115
 
 
116
void cairo_dock_unload_flying_container_textures (void)
 
117
{
 
118
        if (s_iHandTexture != 0)
 
119
        {
 
120
                _cairo_dock_delete_texture (s_iHandTexture);
 
121
                s_iHandTexture = 0;
 
122
        }
 
123
        if (s_iExplosionTexture != 0)
 
124
        {
 
125
                _cairo_dock_delete_texture (s_iExplosionTexture);
 
126
                s_iExplosionTexture = 0;
 
127
        }
 
128
}
 
129
 
 
130
gboolean cairo_dock_update_flying_container_notification (gpointer pUserData, CairoFlyingContainer *pFlyingContainer, gboolean *bContinueAnimation)
 
131
{
 
132
        if (pFlyingContainer->container.iAnimationStep > 0)
 
133
        {
 
134
                pFlyingContainer->container.iAnimationStep --;
 
135
                if (pFlyingContainer->container.iAnimationStep == 0)
 
136
                {
 
137
                        *bContinueAnimation = FALSE;
 
138
                        return CAIRO_DOCK_INTERCEPT_NOTIFICATION;
 
139
                }
 
140
        }
 
141
        gtk_widget_queue_draw (pFlyingContainer->container.pWidget);
 
142
        
 
143
        *bContinueAnimation = TRUE;
 
144
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
145
}
 
146
 
 
147
gboolean cairo_dock_render_flying_container_notification (gpointer pUserData, CairoFlyingContainer *pFlyingContainer, cairo_t *pCairoContext)
 
148
{
 
149
        Icon *pIcon = pFlyingContainer->pIcon;
 
150
        if (pCairoContext != NULL)
 
151
        {
 
152
                if (pIcon != NULL)
 
153
                {
 
154
                        cairo_save (pCairoContext);
 
155
                        cairo_dock_render_one_icon (pIcon, CAIRO_CONTAINER (pFlyingContainer), pCairoContext, 1., TRUE);
 
156
                        cairo_restore (pCairoContext);
 
157
                        
 
158
                        cairo_set_source_surface (pCairoContext, s_pHandSurface, 0., 0.);
 
159
                        cairo_paint (pCairoContext);
 
160
                }
 
161
                else if (pFlyingContainer->container.iAnimationStep > 0)
 
162
                {
 
163
                        int x = 0;
 
164
                        int y = (pFlyingContainer->container.iHeight - pFlyingContainer->container.iWidth) / 2;
 
165
                        int iCurrentFrame = EXPLOSION_NB_FRAMES - pFlyingContainer->container.iAnimationStep;
 
166
                        
 
167
                        cairo_rectangle (pCairoContext,
 
168
                                x,
 
169
                                y,
 
170
                                s_fExplosionWidth,
 
171
                                s_fExplosionHeight);
 
172
                        cairo_clip (pCairoContext);
 
173
                        
 
174
                        cairo_set_source_surface (pCairoContext,
 
175
                                s_pExplosionSurface,
 
176
                                x - (iCurrentFrame * s_fExplosionWidth),
 
177
                                y);
 
178
                        cairo_paint (pCairoContext);
 
179
                }
 
180
        }
 
181
        else
 
182
        {
 
183
                if (pIcon != NULL)
 
184
                {
 
185
                        glPushMatrix ();
 
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);
 
190
                        glPopMatrix ();
 
191
                        
 
192
                        glTranslatef (pFlyingContainer->container.iWidth / 2,
 
193
                                pFlyingContainer->container.iHeight - s_fHandHeight/2,
 
194
                                - 3.);
 
195
                        cairo_dock_draw_texture (s_iHandTexture, s_fHandWidth, s_fHandHeight);
 
196
                }
 
197
                else if (pFlyingContainer->container.iAnimationStep > 0)
 
198
                {
 
199
                        int iCurrentFrame = EXPLOSION_NB_FRAMES - pFlyingContainer->container.iAnimationStep;
 
200
                        
 
201
                        glTranslatef (pFlyingContainer->container.iWidth/2,
 
202
                                pFlyingContainer->container.iHeight/2,
 
203
                                -3.);
 
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,
 
211
                                0., 0.);
 
212
                        
 
213
                        _cairo_dock_disable_texture ();
 
214
                }
 
215
        }
 
216
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
217
}
 
218
 
 
219
 
 
220
static gboolean on_expose_flying_icon (GtkWidget *pWidget,
 
221
        GdkEventExpose *pExpose,
 
222
        CairoFlyingContainer *pFlyingContainer)
 
223
{
 
224
        if (g_bUseOpenGL)
 
225
        {
 
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))
 
229
                        return FALSE;
 
230
                
 
231
                glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
232
                glLoadIdentity ();
 
233
                
 
234
                cairo_dock_apply_desktop_background_opengl (CAIRO_CONTAINER (pFlyingContainer));
 
235
                
 
236
                cairo_dock_notify (CAIRO_DOCK_RENDER_FLYING_CONTAINER, pFlyingContainer, NULL);
 
237
                
 
238
                if (gdk_gl_drawable_is_double_buffered (pGlDrawable))
 
239
                        gdk_gl_drawable_swap_buffers (pGlDrawable);
 
240
                else
 
241
                        glFlush ();
 
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).
 
244
                {
 
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);
 
249
                }
 
250
        }
 
251
        else
 
252
        {
 
253
                cairo_t *pCairoContext = cairo_dock_create_drawing_context_on_container (CAIRO_CONTAINER (pFlyingContainer));
 
254
                
 
255
                cairo_dock_notify (CAIRO_DOCK_RENDER_FLYING_CONTAINER, pFlyingContainer, pCairoContext);
 
256
                
 
257
                cairo_destroy (pCairoContext);
 
258
        }
 
259
        
 
260
        return FALSE;
 
261
}
 
262
 
 
263
static gboolean on_configure_flying_icon (GtkWidget* pWidget,
 
264
        GdkEventConfigure* pEvent,
 
265
        CairoFlyingContainer *pFlyingContainer)
 
266
{
 
267
        if (pFlyingContainer->container.iWidth != pEvent->width || pFlyingContainer->container.iHeight != pEvent->height)
 
268
        {
 
269
                pFlyingContainer->container.iWidth = pEvent->width;
 
270
                pFlyingContainer->container.iHeight = pEvent->height;
 
271
                
 
272
                if (g_bUseOpenGL)
 
273
                {
 
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))
 
279
                                return FALSE;
 
280
                        
 
281
                        glViewport(0, 0, w, h);
 
282
                        
 
283
                        cairo_dock_set_ortho_view (CAIRO_CONTAINER (pFlyingContainer));
 
284
                        
 
285
                        gdk_gl_drawable_gl_end (pGlDrawable);
 
286
                }
 
287
        }
 
288
        return FALSE;
 
289
}
 
290
 
 
291
CairoFlyingContainer *cairo_dock_create_flying_container (Icon *pFlyingIcon, CairoDock *pOriginDock, gboolean bDrawHand)
 
292
{
 
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);
 
306
        
 
307
        g_signal_connect (G_OBJECT (pWindow),
 
308
                "expose-event",
 
309
                G_CALLBACK (on_expose_flying_icon),
 
310
                pFlyingContainer);
 
311
        g_signal_connect (G_OBJECT (pWindow),
 
312
                "configure-event",
 
313
                G_CALLBACK (on_configure_flying_icon),
 
314
                pFlyingContainer);
 
315
        
 
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;
 
323
        
 
324
        if (pOriginDock->container.bIsHorizontal)
 
325
        {
 
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;
 
328
        }
 
329
        else
 
330
        {
 
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;
 
333
        }
 
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));
 
350
        
 
351
        _cairo_dock_load_hand_image (pFlyingContainer->container.iWidth);
 
352
        _cairo_dock_load_explosion_image (pFlyingContainer->container.iWidth);
 
353
        
 
354
        pFlyingContainer->bDrawHand = bDrawHand;
 
355
        if (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.
 
358
        
 
359
        struct timeval tv;
 
360
        int r = gettimeofday (&tv, NULL);
 
361
        pFlyingContainer->fCreationTime = tv.tv_sec + tv.tv_usec * 1e-6;
 
362
        
 
363
        return pFlyingContainer;
 
364
}
 
365
 
 
366
void cairo_dock_drag_flying_container (CairoFlyingContainer *pFlyingContainer, CairoDock *pOriginDock)
 
367
{
 
368
        if (pOriginDock->container.bIsHorizontal)
 
369
        {
 
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;
 
372
        }
 
373
        else
 
374
        {
 
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;
 
377
        }
 
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);
 
382
}
 
383
 
 
384
void cairo_dock_free_flying_container (CairoFlyingContainer *pFlyingContainer)
 
385
{
 
386
        cd_debug ("%s ()", __func__);
 
387
        cairo_dock_finish_container (CAIRO_CONTAINER (pFlyingContainer));
 
388
        g_free (pFlyingContainer);
 
389
}
 
390
 
 
391
void cairo_dock_terminate_flying_container (CairoFlyingContainer *pFlyingContainer)
 
392
{
 
393
        Icon *pIcon = pFlyingContainer->pIcon;
 
394
        pFlyingContainer->pIcon = NULL;
 
395
        pFlyingContainer->container.iAnimationStep = EXPLOSION_NB_FRAMES+1;
 
396
        
 
397
        if (pIcon->cDesktopFileName != NULL)  // c'est un lanceur, ou un separateur manuel, ou un sous-dock.
 
398
        {
 
399
                cairo_dock_remove_one_icon_from_dock (NULL, pIcon);
 
400
                cairo_dock_free_icon (pIcon);
 
401
        }
 
402
        else if (CAIRO_DOCK_IS_APPLET(pIcon))  /// faire une fonction dans la factory ...
 
403
        {
 
404
                cd_debug ("le module %s devient un desklet", pIcon->pModuleInstance->cConfFilePath);
 
405
                
 
406
                cairo_dock_stop_icon_animation (pIcon);
 
407
                
 
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);
 
411
        }
 
412
}