~ubuntu-branches/ubuntu/maverick/cairo-dock/maverick

« back to all changes in this revision

Viewing changes to src/cairo-dock-class-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthieu Baerts (matttbe)
  • Date: 2010-08-09 23:26:12 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100809232612-yp4c6ig3jt1bzpdv
Tags: 2.2.0~0beta4-0ubuntu1
* New Upstream Version (LP: #614624)
* Fixed a few bugs on LP:
 - LP: #518453: Dock appears under all windows
                 (Compiz - fullscreen window)
 - LP: #521369: Separator are not removed when closing
                 grouped windows
 - LP: #521762: Some sentences are not correct
 - LP: #526466: Icons of apps with same class shouldn't
                 be stacked by default
 - LP: #535083: Dialogues looks ugly when a lot of them
                 appears at the same time
 - More details on the 'ChangeLog' file
* debian/rules:
 - Autotools has been replaced by CMake
 - Man pages are now included in the source code
* debian/copyright:
 - Updated with the new pathes and new files
* debian/control:
 - Autotools has been replaced by CMake
 - Added libcurl4-gnutls-dev as Build-deps
 - Bump Standard-Version to 3.9.1
* debian/cairo-dock-core.install:
 - Man pages are now included in the source code
 - All sonames are now installed into lib32 or lib64
* debian/cairo-dock-dev.install:
 - pkgconfig is now installed into lib32 or lib64

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 <math.h>
21
 
#include <string.h>
22
 
#include <stdio.h>
23
 
#include <stdlib.h>
24
 
 
25
 
#include <cairo.h>
26
 
 
27
 
#include "cairo-dock-icons.h"
28
 
#include "cairo-dock-surface-factory.h"
29
 
#include "cairo-dock-log.h"
30
 
#include "cairo-dock-dock-manager.h"
31
 
#include "cairo-dock-dock-factory.h"
32
 
#include "cairo-dock-dock-facility.h"
33
 
#include "cairo-dock-config.h"
34
 
#include "cairo-dock-applications-manager.h"
35
 
#include "cairo-dock-draw.h"
36
 
#include "cairo-dock-load.h"
37
 
#include "cairo-dock-launcher-factory.h"
38
 
#include "cairo-dock-internal-taskbar.h"
39
 
#include "cairo-dock-internal-icons.h"
40
 
#include "cairo-dock-container.h"
41
 
#include "cairo-dock-animations.h"
42
 
#include "cairo-dock-application-facility.h"
43
 
#include "cairo-dock-class-manager.h"
44
 
 
45
 
extern CairoDock *g_pMainDock;
46
 
 
47
 
static GHashTable *s_hClassTable = NULL;
48
 
 
49
 
 
50
 
void cairo_dock_initialize_class_manager (void)
51
 
{
52
 
        if (s_hClassTable == NULL)
53
 
                s_hClassTable = g_hash_table_new_full (g_str_hash,
54
 
                        g_str_equal,
55
 
                        g_free,
56
 
                        (GDestroyNotify) cairo_dock_free_class_appli);
57
 
}
58
 
 
59
 
 
60
 
static CairoDockClassAppli *cairo_dock_find_class_appli (const gchar *cClass)
61
 
{
62
 
        return (cClass != NULL ? g_hash_table_lookup (s_hClassTable, cClass) : NULL);
63
 
}
64
 
 
65
 
const GList *cairo_dock_list_existing_appli_with_class (const gchar *cClass)
66
 
{
67
 
        g_return_val_if_fail (cClass != NULL, NULL);
68
 
        
69
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
70
 
        return (pClassAppli != NULL ? pClassAppli->pAppliOfClass : NULL);
71
 
}
72
 
 
73
 
 
74
 
static void _cairo_dock_set_same_indicator_on_sub_dock (Icon *pInhibhatorIcon)
75
 
{
76
 
        CairoDock *pInhibhatorDock = cairo_dock_search_dock_from_name (pInhibhatorIcon->cParentDockName);
77
 
        if (pInhibhatorDock != NULL && pInhibhatorDock->iRefCount > 0)  // l'inhibiteur est dans un sous-dock.
78
 
        {
79
 
                gboolean bSubDockHasIndicator = FALSE;
80
 
                if (pInhibhatorIcon->bHasIndicator)
81
 
                {
82
 
                        bSubDockHasIndicator = TRUE;
83
 
                }
84
 
                else
85
 
                {
86
 
                        GList* ic;
87
 
                        Icon *icon;
88
 
                        for (ic =pInhibhatorDock->icons ; ic != NULL; ic = ic->next)
89
 
                        {
90
 
                                icon = ic->data;
91
 
                                if (icon->bHasIndicator)
92
 
                                {
93
 
                                        bSubDockHasIndicator = TRUE;
94
 
                                        break;
95
 
                                }
96
 
                        }
97
 
                }
98
 
                CairoDock *pParentDock = NULL;
99
 
                Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pInhibhatorDock, &pParentDock);
100
 
                if (pPointingIcon != NULL && pPointingIcon->bHasIndicator != bSubDockHasIndicator)
101
 
                {
102
 
                        cd_message ("  pour le sous-dock %s : indicateur <- %d", pPointingIcon->cName, bSubDockHasIndicator);
103
 
                        pPointingIcon->bHasIndicator = bSubDockHasIndicator;
104
 
                        if (pParentDock != NULL)
105
 
                                cairo_dock_redraw_icon (pPointingIcon, CAIRO_CONTAINER (pParentDock));
106
 
                }
107
 
        }
108
 
}
109
 
 
110
 
void cairo_dock_free_class_appli (CairoDockClassAppli *pClassAppli)
111
 
{
112
 
        GList *pElement;
113
 
        Icon *pInhibatorIcon;
114
 
        for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
115
 
        {
116
 
                pInhibatorIcon = pElement->data;
117
 
                cd_message ("%s perd sa mana", pInhibatorIcon->cName);
118
 
                pInhibatorIcon->Xid = 0;
119
 
                pInhibatorIcon->bHasIndicator = FALSE;
120
 
                _cairo_dock_set_same_indicator_on_sub_dock (pInhibatorIcon);
121
 
        }
122
 
        g_list_free (pClassAppli->pIconsOfClass);
123
 
        g_list_free (pClassAppli->pAppliOfClass);
124
 
        g_free (pClassAppli);
125
 
}
126
 
 
127
 
static CairoDockClassAppli *cairo_dock_get_class (const gchar *cClass)
128
 
{
129
 
        g_return_val_if_fail (cClass != NULL, NULL);
130
 
        
131
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
132
 
        if (pClassAppli == NULL)
133
 
        {
134
 
                pClassAppli = g_new0 (CairoDockClassAppli, 1);
135
 
                g_hash_table_insert (s_hClassTable, g_strdup (cClass), pClassAppli);
136
 
        }
137
 
        return pClassAppli;
138
 
}
139
 
 
140
 
gboolean cairo_dock_add_inhibator_to_class (const gchar *cClass, Icon *pIcon)
141
 
{
142
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
143
 
        g_return_val_if_fail (pClassAppli!= NULL, FALSE);
144
 
        
145
 
        g_return_val_if_fail (g_list_find (pClassAppli->pIconsOfClass, pIcon) == NULL, TRUE);
146
 
        pClassAppli->pIconsOfClass = g_list_prepend (pClassAppli->pIconsOfClass, pIcon);
147
 
        
148
 
        return TRUE;
149
 
}
150
 
 
151
 
gboolean cairo_dock_add_appli_to_class (Icon *pIcon)
152
 
{
153
 
        g_return_val_if_fail (pIcon!= NULL, FALSE);
154
 
        cd_message ("%s (%s)", __func__, pIcon->cClass);
155
 
        
156
 
        if (pIcon->cClass == NULL)
157
 
        {
158
 
                cd_message (" %s n'a pas de classe, c'est po bien", pIcon->cName);
159
 
                return FALSE;
160
 
        }
161
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
162
 
        g_return_val_if_fail (pClassAppli!= NULL, FALSE);
163
 
        
164
 
        g_return_val_if_fail (g_list_find (pClassAppli->pAppliOfClass, pIcon) == NULL, TRUE);
165
 
        pClassAppli->pAppliOfClass = g_list_prepend (pClassAppli->pAppliOfClass, pIcon);
166
 
        
167
 
        return TRUE;
168
 
}
169
 
 
170
 
gboolean cairo_dock_remove_appli_from_class (Icon *pIcon)
171
 
{
172
 
        g_return_val_if_fail (pIcon!= NULL, FALSE);
173
 
        cd_message ("%s (%s, %s)", __func__, pIcon->cClass, pIcon->cName);
174
 
        
175
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
176
 
        g_return_val_if_fail (pClassAppli!= NULL, FALSE);
177
 
        
178
 
        pClassAppli->pAppliOfClass = g_list_remove (pClassAppli->pAppliOfClass, pIcon);
179
 
        
180
 
        return TRUE;
181
 
}
182
 
 
183
 
gboolean cairo_dock_set_class_use_xicon (const gchar *cClass, gboolean bUseXIcon)
184
 
{
185
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
186
 
        g_return_val_if_fail (pClassAppli!= NULL, FALSE);
187
 
        
188
 
        if (pClassAppli->bUseXIcon == bUseXIcon)  // rien a faire.
189
 
                return FALSE;
190
 
        
191
 
        CairoDock *pDock;
192
 
        GList *pElement;
193
 
        Icon *pAppliIcon;
194
 
        cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (g_pMainDock));
195
 
        for (pElement = pClassAppli->pAppliOfClass; pElement != NULL; pElement = pElement->next)
196
 
        {
197
 
                pAppliIcon = pElement->data;
198
 
                if (bUseXIcon)
199
 
                {
200
 
                        cd_message ("%s prend l'icone de X", pAppliIcon->cName);
201
 
                }
202
 
                else
203
 
                {
204
 
                        cd_message ("%s n'utilise plus l'icone de X", pAppliIcon->cName);
205
 
                }
206
 
                
207
 
                pDock = cairo_dock_search_dock_from_name (pAppliIcon->cParentDockName);
208
 
                if (pDock != NULL)
209
 
                {
210
 
                        cairo_dock_reload_one_icon_buffer_in_dock_full (pAppliIcon, pDock, pCairoContext);
211
 
                }
212
 
                else
213
 
                {
214
 
                        cairo_dock_fill_one_icon_buffer (pAppliIcon, pCairoContext, (1 + myIcons.fAmplitude), g_pMainDock->container.bIsHorizontal, g_pMainDock->container.bDirectionUp);
215
 
                }
216
 
        }
217
 
        cairo_destroy (pCairoContext);
218
 
        
219
 
        return TRUE;
220
 
}
221
 
 
222
 
 
223
 
static Window _cairo_dock_detach_appli_of_class (const gchar *cClass, gboolean bDetachAll)
224
 
{
225
 
        g_return_val_if_fail (cClass != NULL, 0);
226
 
        
227
 
        const GList *pList = cairo_dock_list_existing_appli_with_class (cClass);
228
 
        Icon *pIcon;
229
 
        const GList *pElement;
230
 
        gboolean bNeedsRedraw = FALSE, bDetached;
231
 
        CairoDock *pParentDock;
232
 
        Window XFirstFoundId = 0;
233
 
        for (pElement = pList; pElement != NULL; pElement = pElement->next)
234
 
        {
235
 
                pIcon = pElement->data;
236
 
                pParentDock = cairo_dock_search_dock_from_name (pIcon->cParentDockName);
237
 
                if (pParentDock == NULL)  // pas dans un dock => rien a faire.
238
 
                        continue;
239
 
                
240
 
                cd_debug ("detachement de l'icone %s (%d;%d)", pIcon->cName, bDetachAll, XFirstFoundId);
241
 
                gchar *cParentDockName = pIcon->cParentDockName;
242
 
                pIcon->cParentDockName = NULL;  // astuce.
243
 
                bDetached = cairo_dock_detach_icon_from_dock (pIcon, pParentDock, myIcons.iSeparateIcons);
244
 
                if (bDetached)  // detachee => on met a jour son dock.
245
 
                {
246
 
                        if (! pParentDock->bIsMainDock)  // sous-dock de classe => on le met a jour / detruit.
247
 
                        {
248
 
                                if (pParentDock->icons == NULL)  // devient vide => on le detruit.
249
 
                                {
250
 
                                        if (pParentDock->iRefCount != 0)  // on vire l'icone de paille qui pointe sur ce sous-dock.
251
 
                                        {
252
 
                                                CairoDock *pMainDock=NULL;
253
 
                                                Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pParentDock, &pMainDock);
254
 
                                                if (pMainDock && pPointingIcon && pPointingIcon->cDesktopFileName == NULL)
255
 
                                                {
256
 
                                                        cairo_dock_remove_icon_from_dock (pMainDock, pPointingIcon);
257
 
                                                        bNeedsRedraw |= pMainDock->bIsMainDock;
258
 
                                                        cairo_dock_free_icon (pPointingIcon);
259
 
                                                }
260
 
                                        }
261
 
                                        cairo_dock_destroy_dock (pParentDock, cParentDockName, NULL, NULL);
262
 
                                }
263
 
                                else  // non vide => on le met a jour.
264
 
                                        cairo_dock_update_dock_size (pParentDock);
265
 
                        }
266
 
                        else  // main dock => on le met a jour a la fin.
267
 
                                bNeedsRedraw = TRUE;
268
 
                }
269
 
                g_free (cParentDockName);
270
 
                
271
 
                if (XFirstFoundId == 0)  // on recupere la 1ere appli de la classe.
272
 
                {
273
 
                        XFirstFoundId = pIcon->Xid;
274
 
                        if (! bDetachAll)
275
 
                                break;
276
 
                }
277
 
        }
278
 
        if (! cairo_dock_is_loading () && bNeedsRedraw)  // mise a jour du main dock en 1 coup.
279
 
        {
280
 
                cairo_dock_update_dock_size (g_pMainDock);
281
 
                cairo_dock_calculate_dock_icons (g_pMainDock);
282
 
                gtk_widget_queue_draw (g_pMainDock->container.pWidget);
283
 
        }
284
 
        return XFirstFoundId;
285
 
}
286
 
gboolean cairo_dock_inhibate_class (const gchar *cClass, Icon *pInhibatorIcon)
287
 
{
288
 
        g_return_val_if_fail (cClass != NULL, FALSE);
289
 
        cd_message ("%s (%s)", __func__, cClass);
290
 
        
291
 
        if (! cairo_dock_add_inhibator_to_class (cClass, pInhibatorIcon))  // on l'insere avant pour que les icones des applis puissent le trouver et prendre sa surface si necessaire.
292
 
                return FALSE;
293
 
        
294
 
        Window XFirstFoundId = _cairo_dock_detach_appli_of_class (cClass, (TRUE));
295
 
        if (pInhibatorIcon != NULL)
296
 
        {
297
 
                pInhibatorIcon->Xid = XFirstFoundId;
298
 
                pInhibatorIcon->bHasIndicator = (XFirstFoundId > 0);
299
 
                _cairo_dock_set_same_indicator_on_sub_dock (pInhibatorIcon);
300
 
                if (pInhibatorIcon->cClass != cClass)
301
 
                {
302
 
                        g_free (pInhibatorIcon->cClass);
303
 
                        pInhibatorIcon->cClass = g_strdup (cClass);
304
 
                }
305
 
                
306
 
                const GList *pList = cairo_dock_list_existing_appli_with_class (cClass);
307
 
                Icon *pIcon;
308
 
                const GList *pElement;
309
 
                for (pElement = pList; pElement != NULL; pElement = pElement->next)
310
 
                {
311
 
                        pIcon = pElement->data;
312
 
                        cd_debug ("une appli detachee (%s)", pIcon->cParentDockName);
313
 
                        if (pIcon->Xid != XFirstFoundId && pIcon->cParentDockName == NULL)  // s'est faite detacher et doit etre rattacher.
314
 
                                cairo_dock_insert_appli_in_dock (pIcon, g_pMainDock, CAIRO_DOCK_UPDATE_DOCK_SIZE, ! CAIRO_DOCK_ANIMATE_ICON);
315
 
                }
316
 
        }
317
 
        
318
 
        return TRUE;
319
 
}
320
 
 
321
 
gboolean cairo_dock_class_is_inhibated (const gchar *cClass)
322
 
{
323
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
324
 
        return (pClassAppli != NULL && pClassAppli->pIconsOfClass != NULL);
325
 
}
326
 
 
327
 
gboolean cairo_dock_class_is_using_xicon (const gchar *cClass)
328
 
{
329
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
330
 
        return (pClassAppli != NULL && pClassAppli->bUseXIcon);  // si pClassAppli == NULL, il n'y a pas de lanceur pouvant lui filer son icone, mais on peut en trouver une dans le theme d'icones systeme.
331
 
}
332
 
 
333
 
gboolean cairo_dock_class_is_expanded (const gchar *cClass)
334
 
{
335
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
336
 
        return (pClassAppli != NULL && pClassAppli->bExpand);
337
 
}
338
 
 
339
 
gboolean cairo_dock_prevent_inhibated_class (Icon *pIcon)
340
 
{
341
 
        g_return_val_if_fail (pIcon != NULL, FALSE);
342
 
        //g_print ("%s (%s)\n", __func__, pIcon->cClass);
343
 
        
344
 
        gboolean bToBeInhibited = FALSE;
345
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (pIcon->cClass);
346
 
        if (pClassAppli != NULL)
347
 
        {
348
 
                Icon *pInhibatorIcon;
349
 
                GList *pElement;
350
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
351
 
                {
352
 
                        pInhibatorIcon = pElement->data;
353
 
                        if (pInhibatorIcon != NULL)  // un inhibiteur est present.
354
 
                        {
355
 
                                if (pInhibatorIcon->Xid == 0 && pInhibatorIcon->pSubDock == NULL)  // cette icone inhibe cette classe mais ne controle encore aucune appli, on s'y asservit.
356
 
                                {
357
 
                                        pInhibatorIcon->Xid = pIcon->Xid;
358
 
                                        pInhibatorIcon->bIsHidden = pIcon->bIsHidden;
359
 
                                        cd_message (">>> %s prendra un indicateur au prochain redraw ! (Xid : %d)", pInhibatorIcon->cName, pInhibatorIcon->Xid);
360
 
                                        pInhibatorIcon->bHasIndicator = TRUE;
361
 
                                        _cairo_dock_set_same_indicator_on_sub_dock (pInhibatorIcon);
362
 
                                }
363
 
                                
364
 
                                if (pInhibatorIcon->Xid == pIcon->Xid)  // cette icone nous controle.
365
 
                                {
366
 
                                        CairoDock *pInhibhatorDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
367
 
                                        //\______________ On place l'icone pour X.
368
 
                                        if (! bToBeInhibited)  // on ne met le thumbnail que sur la 1ere.
369
 
                                        {
370
 
                                                if (pInhibhatorDock != NULL)
371
 
                                                {
372
 
                                                        //g_print ("on positionne la miniature sur l'inhibiteur %s\n", pInhibatorIcon->cName);
373
 
                                                        cairo_dock_set_one_icon_geometry_for_window_manager (pInhibatorIcon, pInhibhatorDock);
374
 
                                                }
375
 
                                                bToBeInhibited = TRUE;
376
 
                                        }
377
 
                                        //\______________ On met a jour l'etiquette de l'inhibiteur.
378
 
                                        if (pInhibhatorDock != NULL && pIcon->cName != NULL)
379
 
                                        {
380
 
                                                if (pInhibatorIcon->cInitialName == NULL)
381
 
                                                        pInhibatorIcon->cInitialName = pInhibatorIcon->cName;
382
 
                                                else
383
 
                                                        g_free (pInhibatorIcon->cName);
384
 
                                                pInhibatorIcon->cName = NULL;
385
 
                                                cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (pInhibhatorDock));
386
 
                                                cairo_dock_set_icon_name (pCairoContext, pIcon->cName, pInhibatorIcon, CAIRO_CONTAINER (pInhibhatorDock));
387
 
                                                cairo_destroy (pCairoContext);
388
 
                                        }
389
 
                                }
390
 
                        }
391
 
                }
392
 
        }
393
 
        return bToBeInhibited;
394
 
}
395
 
 
396
 
 
397
 
gboolean cairo_dock_remove_icon_from_class (Icon *pInhibatorIcon)
398
 
{
399
 
        g_return_val_if_fail (pInhibatorIcon != NULL, FALSE);
400
 
        cd_message ("%s (%s)", __func__, pInhibatorIcon->cClass);
401
 
        
402
 
        gboolean bStillInhibated = FALSE;
403
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (pInhibatorIcon->cClass);
404
 
        if (pClassAppli != NULL)
405
 
        {
406
 
                pClassAppli->pIconsOfClass = g_list_remove (pClassAppli->pIconsOfClass, pInhibatorIcon);
407
 
                if (pClassAppli->pIconsOfClass == NULL && pClassAppli->pAppliOfClass == NULL && ! pClassAppli->bUseXIcon)  // cette classe ne sert plus a rien.
408
 
                {
409
 
                        cd_message ("  cette classe n'a plus d'interet");
410
 
                        g_hash_table_remove (s_hClassTable, pInhibatorIcon->cClass);  // detruit pClassAppli.
411
 
                        bStillInhibated = FALSE;
412
 
                }
413
 
                else
414
 
                        bStillInhibated = (pClassAppli->pIconsOfClass != NULL);
415
 
        }
416
 
        return bStillInhibated;
417
 
}
418
 
 
419
 
void cairo_dock_deinhibate_class (const gchar *cClass, Icon *pInhibatorIcon)
420
 
{
421
 
        cd_message ("%s (%s)", __func__, cClass);
422
 
        gboolean bStillInhibated = cairo_dock_remove_icon_from_class (pInhibatorIcon);
423
 
        cd_debug (" bStillInhibated : %d", bStillInhibated);
424
 
        ///if (! bStillInhibated)  // il n'y a plus personne dans cette classe.
425
 
        ///     return ;
426
 
        
427
 
        if (pInhibatorIcon == NULL || pInhibatorIcon->Xid != 0)
428
 
        {
429
 
                cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (g_pMainDock));
430
 
                const GList *pList = cairo_dock_list_existing_appli_with_class (cClass);
431
 
                Icon *pIcon;
432
 
                gboolean bNeedsRedraw = FALSE;
433
 
                CairoDock *pParentDock;
434
 
                const GList *pElement;
435
 
                for (pElement = pList; pElement != NULL; pElement = pElement->next)
436
 
                {
437
 
                        pIcon = pElement->data;
438
 
                        if (pInhibatorIcon == NULL || pIcon->Xid == pInhibatorIcon->Xid)
439
 
                        {
440
 
                                cd_message ("rajout de l'icone precedemment inhibee (Xid:%d)", pIcon->Xid);
441
 
                                pIcon->fInsertRemoveFactor = 0;
442
 
                                pIcon->fScale = 1.;
443
 
                                pParentDock = cairo_dock_insert_appli_in_dock (pIcon, g_pMainDock, CAIRO_DOCK_UPDATE_DOCK_SIZE, ! CAIRO_DOCK_ANIMATE_ICON);
444
 
                                bNeedsRedraw = (pParentDock != NULL && pParentDock->bIsMainDock);
445
 
                                //if (pInhibatorIcon != NULL)
446
 
                                //      break ;
447
 
                        }
448
 
                        pParentDock = cairo_dock_search_dock_from_name (pIcon->cParentDockName);
449
 
                        if (pParentDock != NULL)
450
 
                        {
451
 
                                cd_message ("on recharge l'icone de l'appli %s", pIcon->cName);
452
 
                                cairo_dock_reload_one_icon_buffer_in_dock_full (pIcon, pParentDock, pCairoContext);
453
 
                        }
454
 
                        else
455
 
                        {
456
 
                                cairo_dock_reload_one_icon_buffer_in_dock_full (pIcon, g_pMainDock, pCairoContext);
457
 
                        }
458
 
                }
459
 
                cairo_destroy (pCairoContext);
460
 
                if (bNeedsRedraw)
461
 
                        gtk_widget_queue_draw (g_pMainDock->container.pWidget);  /// pDock->pRenderer->calculate_icons (pDock); ?...
462
 
        }
463
 
        if (pInhibatorIcon != NULL)
464
 
        {
465
 
                cd_message (" l'inhibiteur a perdu toute sa mana");
466
 
                pInhibatorIcon->Xid = 0;
467
 
                pInhibatorIcon->bHasIndicator = FALSE;
468
 
                g_free (pInhibatorIcon->cClass);
469
 
                pInhibatorIcon->cClass = NULL;
470
 
                cd_debug ("  plus de classe");
471
 
        }
472
 
}
473
 
 
474
 
 
475
 
void cairo_dock_update_Xid_on_inhibators (Window Xid, const gchar *cClass)
476
 
{
477
 
        cd_message ("%s (%s)", __func__, cClass);
478
 
        CairoDockClassAppli *pClassAppli = cairo_dock_find_class_appli (cClass);
479
 
        if (pClassAppli != NULL)
480
 
        {
481
 
                int iNextXid = -1;
482
 
                Icon *pSameClassIcon = NULL;
483
 
                Icon *pIcon;
484
 
                GList *pElement;
485
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
486
 
                {
487
 
                        pIcon = pElement->data;
488
 
                        if (pIcon->Xid == Xid)
489
 
                        {
490
 
                                if (iNextXid == -1)  // on prend la 1ere appli de meme classe.
491
 
                                {
492
 
                                        GList *pList = pClassAppli->pAppliOfClass;
493
 
                                        Icon *pOneIcon;
494
 
                                        GList *ic;
495
 
                                        for (ic = pList; ic != NULL; ic = ic->next)
496
 
                                        {
497
 
                                                pOneIcon = ic->data;
498
 
                                                if (pOneIcon != NULL && ! cairo_dock_icon_is_being_removed (pOneIcon) && pOneIcon->Xid != Xid)  // la 2eme condition est a priori toujours vraie.
499
 
                                                {
500
 
                                                        pSameClassIcon = pOneIcon;
501
 
                                                        break ;
502
 
                                                }
503
 
                                        }
504
 
                                        iNextXid = (pSameClassIcon != NULL ? pSameClassIcon->Xid : 0);
505
 
                                        if (pSameClassIcon != NULL)
506
 
                                        {
507
 
                                                cd_message ("  c'est %s qui va la remplacer", pSameClassIcon->cName);
508
 
                                                CairoDock *pClassSubDock = cairo_dock_search_dock_from_name (pSameClassIcon->cParentDockName);
509
 
                                                if (pClassSubDock != NULL)
510
 
                                                {
511
 
                                                        cairo_dock_detach_icon_from_dock (pSameClassIcon, pClassSubDock, myIcons.iSeparateIcons);
512
 
                                                        if (pClassSubDock->icons == NULL && pClassSubDock == cairo_dock_search_dock_from_name (cClass))  // le sous-dock de la classe devient vide.
513
 
                                                                cairo_dock_destroy_dock (pClassSubDock, cClass, NULL, NULL);
514
 
                                                        else
515
 
                                                                cairo_dock_update_dock_size (pClassSubDock);
516
 
                                                }
517
 
                                        }
518
 
                                }
519
 
                                pIcon->Xid = iNextXid;
520
 
                                pIcon->bHasIndicator = (iNextXid != 0);
521
 
                                _cairo_dock_set_same_indicator_on_sub_dock (pIcon);
522
 
                                cd_message (" %s : bHasIndicator <- %d, Xid <- %d", pIcon->cName, pIcon->bHasIndicator, pIcon->Xid);
523
 
                        }
524
 
                }
525
 
        }
526
 
}
527
 
 
528
 
static void _cairo_dock_remove_all_applis_from_class (gchar *cClass, CairoDockClassAppli *pClassAppli, gpointer data)
529
 
{
530
 
        g_list_free (pClassAppli->pAppliOfClass);
531
 
        pClassAppli->pAppliOfClass = NULL;
532
 
        
533
 
        Icon *pInhibatorIcon;
534
 
        GList *pElement;
535
 
        for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
536
 
        {
537
 
                pInhibatorIcon = pElement->data;
538
 
                pInhibatorIcon->bHasIndicator = FALSE;
539
 
                pInhibatorIcon->Xid = 0;
540
 
                _cairo_dock_set_same_indicator_on_sub_dock (pInhibatorIcon);
541
 
        }
542
 
}
543
 
void cairo_dock_remove_all_applis_from_class_table (void)
544
 
{
545
 
        g_hash_table_foreach (s_hClassTable, (GHFunc) _cairo_dock_remove_all_applis_from_class, NULL);
546
 
}
547
 
 
548
 
void cairo_dock_reset_class_table (void)
549
 
{
550
 
        g_hash_table_remove_all (s_hClassTable);
551
 
}
552
 
 
553
 
 
554
 
 
555
 
cairo_surface_t *cairo_dock_duplicate_inhibator_surface_for_appli (cairo_t *pSourceContext, Icon *pInhibatorIcon, double fMaxScale, double *fWidth, double *fHeight)
556
 
{
557
 
        *fWidth = myIcons.tIconAuthorizedWidth[CAIRO_DOCK_APPLI];
558
 
        *fHeight = myIcons.tIconAuthorizedHeight[CAIRO_DOCK_APPLI];
559
 
        
560
 
        CairoContainer *pInhibhatorContainer = cairo_dock_search_container_from_icon (pInhibatorIcon);
561
 
        double fInhibatorMaxScale = (CAIRO_DOCK_IS_DOCK (pInhibhatorContainer) ? fMaxScale : 1);
562
 
        
563
 
        cairo_surface_t *pSurface = cairo_dock_duplicate_surface (pInhibatorIcon->pIconBuffer,
564
 
                pSourceContext,
565
 
                pInhibatorIcon->fWidth * fInhibatorMaxScale / (pInhibhatorContainer ? pInhibhatorContainer->fRatio : 1.),
566
 
                pInhibatorIcon->fHeight * fInhibatorMaxScale / (pInhibhatorContainer ? pInhibhatorContainer->fRatio : 1.),
567
 
                *fWidth * fMaxScale,
568
 
                *fHeight * fMaxScale);
569
 
        return pSurface;
570
 
}
571
 
cairo_surface_t *cairo_dock_create_surface_from_class (const gchar *cClass, cairo_t *pSourceContext, double fMaxScale, double *fWidth, double *fHeight)
572
 
{
573
 
        cd_debug ("%s (%s)", __func__, cClass);
574
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
575
 
        if (pClassAppli != NULL)
576
 
        {
577
 
                cd_debug ("bUseXIcon:%d", pClassAppli->bUseXIcon);
578
 
                if (pClassAppli->bUseXIcon)
579
 
                        return NULL;
580
 
                
581
 
                GList *pElement;
582
 
                Icon *pInhibatorIcon;
583
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
584
 
                {
585
 
                        pInhibatorIcon = pElement->data;
586
 
                        cd_debug ("  %s", pInhibatorIcon->cName);
587
 
                        if (! CAIRO_DOCK_IS_APPLET (pInhibatorIcon))
588
 
                        {
589
 
                                cd_message ("%s va fournir genereusement sa surface", pInhibatorIcon->cName);
590
 
                                return cairo_dock_duplicate_inhibator_surface_for_appli (pSourceContext, pInhibatorIcon, fMaxScale, fWidth, fHeight);
591
 
                        }
592
 
                }
593
 
        }
594
 
        
595
 
        gchar *cIconFilePath = cairo_dock_search_icon_s_path (cClass);
596
 
        if (cIconFilePath != NULL)
597
 
        {
598
 
                cd_debug ("on remplace l'icone X par %s", cIconFilePath);
599
 
                cairo_surface_t *pSurface = cairo_dock_create_surface_from_image (cIconFilePath,
600
 
                        pSourceContext,
601
 
                        1 + myIcons.fAmplitude,
602
 
                        myIcons.tIconAuthorizedWidth[CAIRO_DOCK_APPLI],
603
 
                        myIcons.tIconAuthorizedHeight[CAIRO_DOCK_APPLI],
604
 
                        CAIRO_DOCK_FILL_SPACE,
605
 
                        fWidth, fHeight,
606
 
                        NULL, NULL);
607
 
                g_free (cIconFilePath);
608
 
                return pSurface;
609
 
        }
610
 
        
611
 
        cd_debug ("classe %s prend l'icone X", cClass);
612
 
        
613
 
        return NULL;
614
 
}
615
 
 
616
 
 
617
 
void cairo_dock_update_visibility_on_inhibators (const gchar *cClass, Window Xid, gboolean bIsHidden)
618
 
{
619
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
620
 
        if (pClassAppli != NULL)
621
 
        {
622
 
                GList *pElement;
623
 
                Icon *pInhibatorIcon;
624
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
625
 
                {
626
 
                        pInhibatorIcon = pElement->data;
627
 
                        
628
 
                        if (pInhibatorIcon->Xid == Xid)
629
 
                        {
630
 
                                cd_message (" %s aussi se %s", pInhibatorIcon->cName, (bIsHidden ? "cache" : "montre"));
631
 
                                pInhibatorIcon->bIsHidden = bIsHidden;
632
 
                                if (! CAIRO_DOCK_IS_APPLET (pInhibatorIcon) && myTaskBar.fVisibleAppliAlpha != 0)
633
 
                                {
634
 
                                        CairoDock *pInhibhatorDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
635
 
                                        pInhibatorIcon->fAlpha = 1;  // on triche un peu.
636
 
                                        cairo_dock_redraw_icon (pInhibatorIcon, CAIRO_CONTAINER (pInhibhatorDock));
637
 
                                }
638
 
                        }
639
 
                }
640
 
        }
641
 
}
642
 
 
643
 
void cairo_dock_update_activity_on_inhibators (const gchar *cClass, Window Xid)
644
 
{
645
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
646
 
        if (pClassAppli != NULL)
647
 
        {
648
 
                GList *pElement;
649
 
                Icon *pInhibatorIcon;
650
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
651
 
                {
652
 
                        pInhibatorIcon = pElement->data;
653
 
                        
654
 
                        if (pInhibatorIcon->Xid == Xid)
655
 
                        {
656
 
                                cd_message (" %s aussi devient active", pInhibatorIcon->cName);
657
 
                                ///pInhibatorIcon->bIsActive = TRUE;
658
 
                                CairoDock *pParentDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
659
 
                                if (pParentDock != NULL)
660
 
                                        cairo_dock_animate_icon_on_active (pInhibatorIcon, pParentDock);
661
 
                        }
662
 
                }
663
 
        }
664
 
}
665
 
 
666
 
void cairo_dock_update_inactivity_on_inhibators (const gchar *cClass, Window Xid)
667
 
{
668
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
669
 
        if (pClassAppli != NULL)
670
 
        {
671
 
                GList *pElement;
672
 
                Icon *pInhibatorIcon;
673
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
674
 
                {
675
 
                        pInhibatorIcon = pElement->data;
676
 
                        
677
 
                        if (pInhibatorIcon->Xid == Xid)
678
 
                        {
679
 
                                cd_message (" %s aussi devient inactive", pInhibatorIcon->cName);
680
 
                                ///pInhibatorIcon->bIsActive = FALSE;
681
 
                                CairoDock *pParentDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
682
 
                                if (pParentDock != NULL && ! pParentDock->bIsShrinkingDown)
683
 
                                        cairo_dock_redraw_icon (pInhibatorIcon, CAIRO_CONTAINER (pParentDock));
684
 
                        }
685
 
                }
686
 
        }
687
 
}
688
 
 
689
 
void cairo_dock_update_name_on_inhibators (const gchar *cClass, Window Xid, gchar *cNewName)
690
 
{
691
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClass);
692
 
        if (pClassAppli != NULL)
693
 
        {
694
 
                GList *pElement;
695
 
                Icon *pInhibatorIcon;
696
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
697
 
                {
698
 
                        pInhibatorIcon = pElement->data;
699
 
                        
700
 
                        if (pInhibatorIcon->Xid == Xid)
701
 
                        {
702
 
                                CairoDock *pParentDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
703
 
                                if (pParentDock != NULL)
704
 
                                {
705
 
                                        if (! CAIRO_DOCK_IS_APPLET (pInhibatorIcon))
706
 
                                        {
707
 
                                                cd_message (" %s change son nom en %s", pInhibatorIcon->cName, cNewName);
708
 
                                                if (pInhibatorIcon->cInitialName == NULL)
709
 
                                                {
710
 
                                                        pInhibatorIcon->cInitialName = pInhibatorIcon->cName;
711
 
                                                        cd_debug ("pInhibatorIcon->cInitialName <- %s", pInhibatorIcon->cInitialName);
712
 
                                                }
713
 
                                                else
714
 
                                                        g_free (pInhibatorIcon->cName);
715
 
                                                pInhibatorIcon->cName = NULL;
716
 
                                                
717
 
                                                cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (pParentDock));
718
 
                                                cairo_dock_set_icon_name (pCairoContext, (cNewName != NULL ? cNewName : pInhibatorIcon->cInitialName), pInhibatorIcon, CAIRO_CONTAINER (pParentDock));
719
 
                                                cairo_destroy (pCairoContext);
720
 
                                        }
721
 
                                        if (! pParentDock->bIsShrinkingDown)
722
 
                                                cairo_dock_redraw_icon (pInhibatorIcon, CAIRO_CONTAINER (pParentDock));
723
 
                                }
724
 
                        }
725
 
                }
726
 
        }
727
 
}
728
 
 
729
 
Icon *cairo_dock_get_classmate (Icon *pIcon)
730
 
{
731
 
        cd_debug ("%s (%s)", __func__, pIcon->cClass);
732
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
733
 
        if (pClassAppli == NULL)
734
 
                return NULL;
735
 
        
736
 
        Icon *pFriendIcon = NULL;
737
 
        GList *pElement;
738
 
        for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
739
 
        {
740
 
                pFriendIcon = pElement->data;
741
 
                if (pFriendIcon == NULL || pFriendIcon->cParentDockName == NULL)  // on ne prend pas les inhibiteurs situes dans un desklet.
742
 
                        continue ;
743
 
                cd_debug (" friend : %s (%d)", pFriendIcon->cName, pFriendIcon->Xid);
744
 
                if (pFriendIcon->Xid != 0 || pFriendIcon->pSubDock != NULL)
745
 
                        return pFriendIcon;
746
 
        }
747
 
        
748
 
        for (pElement = pClassAppli->pAppliOfClass; pElement != NULL; pElement = pElement->next)
749
 
        {
750
 
                pFriendIcon = pElement->data;
751
 
                if (pFriendIcon != pIcon && pFriendIcon->cParentDockName != NULL && strcmp (pFriendIcon->cParentDockName, CAIRO_DOCK_MAIN_DOCK_NAME) == 0)
752
 
                        return pFriendIcon;
753
 
        }
754
 
        
755
 
        return NULL;
756
 
}
757
 
 
758
 
 
759
 
 
760
 
 
761
 
gboolean cairo_dock_check_class_subdock_is_empty (CairoDock *pDock, const gchar *cClass)
762
 
{
763
 
        cd_debug ("%s (%s, %d)", __func__, cClass, g_list_length (pDock->icons));
764
 
        if (pDock->iRefCount == 0)
765
 
                return FALSE;
766
 
        if (pDock->icons == NULL)  // ne devrait plus arriver.
767
 
        {
768
 
                cd_warning ("the %s class sub-dock has no element, which is probably an error !\nit will be destroyed.", cClass);
769
 
                CairoDock *pFakeParentDock = NULL;
770
 
                Icon *pFakeClassIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pFakeParentDock);
771
 
                cairo_dock_destroy_dock (pDock, cClass, NULL, NULL);
772
 
                pFakeClassIcon->pSubDock = NULL;
773
 
                cairo_dock_remove_icon_from_dock (pFakeParentDock, pFakeClassIcon);
774
 
                cairo_dock_free_icon (pFakeClassIcon);
775
 
                cairo_dock_update_dock_size (pFakeParentDock);
776
 
                cairo_dock_calculate_dock_icons (pFakeParentDock);
777
 
                return TRUE;
778
 
        }
779
 
        else if (pDock->icons->next == NULL)
780
 
        {
781
 
                cd_debug ("   le sous-dock de la classe %s n'a plus que 1 element et va etre vide puis detruit", cClass);
782
 
                Icon *pLastClassIcon = pDock->icons->data;
783
 
                
784
 
                CairoDock *pFakeParentDock = NULL;
785
 
                Icon *pFakeClassIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pFakeParentDock);
786
 
                g_return_val_if_fail (pFakeClassIcon != NULL, TRUE);
787
 
                if (CAIRO_DOCK_IS_FAKE_LAUNCHER (pFakeClassIcon))  // le sous-dock est pointe par une icone de paille.
788
 
                {
789
 
                        cd_debug ("trouve l'icone en papier (%x;%x)", pFakeClassIcon, pFakeParentDock);
790
 
                        cairo_dock_detach_icon_from_dock (pLastClassIcon, pDock, FALSE);
791
 
                        g_free (pLastClassIcon->cParentDockName);
792
 
                        pLastClassIcon->cParentDockName = g_strdup (pFakeClassIcon->cParentDockName);
793
 
                        pLastClassIcon->fOrder = pFakeClassIcon->fOrder;
794
 
                        
795
 
                        cd_debug ("on enleve l'icone de paille");
796
 
                        cairo_dock_remove_icon_from_dock (pFakeParentDock, pFakeClassIcon);  // a faire avant que l'icone n'ait plus de sous-dock, sinon elle est consideree comme un separateur auto, et du coup le separateur n'est pas enleve.
797
 
                        
798
 
                        cd_debug (" on detruit le sous-dock...");
799
 
                        cairo_dock_destroy_dock (pDock, cClass, NULL, NULL);
800
 
                        pFakeClassIcon->pSubDock = NULL;
801
 
                        
802
 
                        cd_debug ("on detruit l'icone de paille");
803
 
                        cairo_dock_free_icon (pFakeClassIcon);
804
 
                        
805
 
                        cd_debug (" puis on re-insere l'appli restante");
806
 
                        if (! cairo_dock_icon_is_being_removed (pLastClassIcon))
807
 
                        {
808
 
                                cairo_dock_insert_icon_in_dock (pLastClassIcon, pFakeParentDock, CAIRO_DOCK_UPDATE_DOCK_SIZE, ! CAIRO_DOCK_ANIMATE_ICON);
809
 
                                cairo_dock_calculate_dock_icons (pFakeParentDock);
810
 
                                cairo_dock_redraw_icon (pLastClassIcon, CAIRO_CONTAINER (pFakeParentDock));  // on suppose que les tailles des 2 icones sont identiques.
811
 
                        }
812
 
                        else  // la derniere icone est en cours de suppression, inutile de la re-inserer. (c'est souvent lorsqu'on ferme toutes une classe d'un coup. donc les animations sont pratiquement dans le meme etat, donc la derniere icone en est aussi a la fin, donc on ne verrait de toute facon aucune animation.
813
 
                        {
814
 
                                g_print ("inutile de re-inserer l'icone restante\n");
815
 
                                cairo_dock_free_icon (pLastClassIcon);
816
 
                                cairo_dock_update_dock_size (pFakeParentDock);
817
 
                                cairo_dock_calculate_dock_icons (pFakeParentDock);
818
 
                                cairo_dock_redraw_container (CAIRO_CONTAINER (pFakeParentDock));
819
 
                        }
820
 
                }
821
 
                else  // le sous-dock est pointe par un inhibiteur (normal launcher ou applet).
822
 
                {
823
 
                        cairo_dock_detach_icon_from_dock (pLastClassIcon, pDock, FALSE);
824
 
                        g_free (pLastClassIcon->cParentDockName);
825
 
                        pLastClassIcon->cParentDockName = NULL;
826
 
                        
827
 
                        cairo_dock_destroy_dock (pDock, cClass, NULL, NULL);
828
 
                        pFakeClassIcon->pSubDock = NULL;
829
 
                        cd_debug ("sanity check : pFakeClassIcon->Xid : %d", pFakeClassIcon->Xid);
830
 
                        if (! cairo_dock_icon_is_being_removed (pLastClassIcon))
831
 
                        {
832
 
                                cairo_dock_insert_appli_in_dock (pLastClassIcon, g_pMainDock, ! CAIRO_DOCK_UPDATE_DOCK_SIZE, ! CAIRO_DOCK_ANIMATE_ICON);  // a priori inutile.
833
 
                                cairo_dock_update_name_on_inhibators (cClass, pLastClassIcon->Xid, pLastClassIcon->cName);
834
 
                        }
835
 
                        else  // la derniere icone est en cours de suppression, inutile de la re-inserer
836
 
                        {
837
 
                                pFakeClassIcon->bHasIndicator = FALSE;
838
 
                                cairo_dock_free_icon (pLastClassIcon);
839
 
                        }
840
 
                        cairo_dock_redraw_icon (pFakeClassIcon, CAIRO_CONTAINER (g_pMainDock));
841
 
                }
842
 
                return TRUE;
843
 
        }
844
 
        return FALSE;
845
 
}
846
 
 
847
 
 
848
 
static void _cairo_dock_reset_overwrite_exceptions (gchar *cClass, CairoDockClassAppli *pClassAppli, gpointer data)
849
 
{
850
 
        pClassAppli->bUseXIcon = FALSE;
851
 
}
852
 
void cairo_dock_set_overwrite_exceptions (const gchar *cExceptions)
853
 
{
854
 
        g_hash_table_foreach (s_hClassTable, (GHFunc) _cairo_dock_reset_overwrite_exceptions, NULL);
855
 
        if (cExceptions == NULL)
856
 
                return ;
857
 
        
858
 
        gchar **cClassList = g_strsplit (cExceptions, ";", -1);
859
 
        if (cClassList == NULL || cClassList[0] == NULL || *cClassList[0] == '\0')
860
 
        {
861
 
                g_strfreev (cClassList);
862
 
                return ;
863
 
        }
864
 
        CairoDockClassAppli *pClassAppli;
865
 
        int i;
866
 
        for (i = 0; cClassList[i] != NULL; i ++)
867
 
        {
868
 
                CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClassList[i]);
869
 
                pClassAppli->bUseXIcon = TRUE;
870
 
        }
871
 
        
872
 
        g_strfreev (cClassList);
873
 
}
874
 
 
875
 
static void _cairo_dock_reset_group_exceptions (gchar *cClass, CairoDockClassAppli *pClassAppli, gpointer data)
876
 
{
877
 
        pClassAppli->bExpand = FALSE;
878
 
}
879
 
void cairo_dock_set_group_exceptions (const gchar *cExceptions)
880
 
{
881
 
        g_hash_table_foreach (s_hClassTable, (GHFunc) _cairo_dock_reset_group_exceptions, NULL);
882
 
        if (cExceptions == NULL)
883
 
                return ;
884
 
        
885
 
        gchar **cClassList = g_strsplit (cExceptions, ";", -1);
886
 
        if (cClassList == NULL || cClassList[0] == NULL || *cClassList[0] == '\0')
887
 
        {
888
 
                g_strfreev (cClassList);
889
 
                return ;
890
 
        }
891
 
        CairoDockClassAppli *pClassAppli;
892
 
        int i;
893
 
        for (i = 0; cClassList[i] != NULL; i ++)
894
 
        {
895
 
                CairoDockClassAppli *pClassAppli = cairo_dock_get_class (cClassList[i]);
896
 
                pClassAppli->bExpand = TRUE;
897
 
        }
898
 
        
899
 
        g_strfreev (cClassList);
900
 
}
901
 
 
902
 
 
903
 
Icon *cairo_dock_get_prev_next_classmate_icon (Icon *pIcon, gboolean bNext)
904
 
{
905
 
        cd_debug ("%s (%s, %s)", __func__, pIcon->cClass, pIcon->cName);
906
 
        g_return_val_if_fail (pIcon->cClass != NULL, NULL);
907
 
        
908
 
        Icon *pActiveIcon = cairo_dock_get_current_active_icon ();
909
 
        if (pActiveIcon == NULL || pActiveIcon->cClass == NULL || strcmp (pActiveIcon->cClass, pIcon->cClass) != 0)  // la fenetre active n'est pas de notre classe, on active l'icone fournies en entree.
910
 
        {
911
 
                cd_debug ("on active la classe %s", pIcon->cClass);
912
 
                return pIcon;
913
 
        }
914
 
        
915
 
        //\________________ on va chercher dans la classe la fenetre active, et prendre la suivante ou la precedente.
916
 
        Icon *pNextIcon = NULL;
917
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
918
 
        if (pClassAppli == NULL)
919
 
                return NULL;
920
 
        
921
 
        //\________________ On cherche dans les icones d'applis.
922
 
        Icon *pClassmateIcon;
923
 
        GList *pElement, *ic;
924
 
        for (pElement = pClassAppli->pAppliOfClass; pElement != NULL && pNextIcon == NULL; pElement = pElement->next)
925
 
        {
926
 
                pClassmateIcon = pElement->data;
927
 
                cd_debug (" %s est-elle active ?", pClassmateIcon->cName);
928
 
                if (pClassmateIcon->Xid == pActiveIcon->Xid)  // on a trouve la fenetre active.
929
 
                {
930
 
                        cd_debug ("  fenetre active trouvee (%s; %d)", pClassmateIcon->cName, pClassmateIcon->Xid);
931
 
                        if (bNext)  // on prend la 1ere non nulle qui suit.
932
 
                        {
933
 
                                ic = pElement;
934
 
                                do
935
 
                                {
936
 
                                        ic = cairo_dock_get_next_element (ic, pClassAppli->pAppliOfClass);
937
 
                                        if (ic == pElement)
938
 
                                        {
939
 
                                                cd_debug ("  on a fait le tour sans rien trouve");
940
 
                                                break ;
941
 
                                        }
942
 
                                        pClassmateIcon = ic->data;
943
 
                                        if (pClassmateIcon != NULL && pClassmateIcon->Xid != 0)
944
 
                                        {
945
 
                                                cd_debug ("  ok on prend celle-la (%s; %d)", pClassmateIcon->cName, pClassmateIcon->Xid);
946
 
                                                pNextIcon = pClassmateIcon;
947
 
                                                break ;
948
 
                                        }
949
 
                                        cd_debug ("un coup pour rien");
950
 
                                }
951
 
                                while (1);
952
 
                        }
953
 
                        else  // on prend la 1ere non nulle qui precede.
954
 
                        {
955
 
                                ic = pElement;
956
 
                                do
957
 
                                {
958
 
                                        ic = cairo_dock_get_previous_element (ic, pClassAppli->pAppliOfClass);
959
 
                                        if (ic == pElement)
960
 
                                                break ;
961
 
                                        pClassmateIcon = ic->data;
962
 
                                        if (pClassmateIcon != NULL && pClassmateIcon->Xid != 0)
963
 
                                        {
964
 
                                                pNextIcon = pClassmateIcon;
965
 
                                                break ;
966
 
                                        }
967
 
                                }
968
 
                                while (1);
969
 
                        }
970
 
                        break ;
971
 
                }
972
 
        }
973
 
        return pNextIcon;
974
 
}
975
 
 
976
 
 
977
 
 
978
 
Icon *cairo_dock_get_inhibator (Icon *pIcon, gboolean bOnlyInDock)
979
 
{
980
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
981
 
        if (pClassAppli != NULL)
982
 
        {
983
 
                GList *pElement;
984
 
                Icon *pInhibatorIcon;
985
 
                for (pElement = pClassAppli->pIconsOfClass; pElement != NULL; pElement = pElement->next)
986
 
                {
987
 
                        pInhibatorIcon = pElement->data;
988
 
                        
989
 
                        if (pInhibatorIcon->Xid == pIcon->Xid)
990
 
                        {
991
 
                                if (! bOnlyInDock || pInhibatorIcon->cParentDockName != NULL)
992
 
                                        return pInhibatorIcon;
993
 
                        }
994
 
                }
995
 
        }
996
 
        return NULL;
997
 
}
998
 
 
999
 
void cairo_dock_set_class_order (Icon *pIcon)
1000
 
{
1001
 
        double fOrder = CAIRO_DOCK_LAST_ORDER;
1002
 
        CairoDockClassAppli *pClassAppli = cairo_dock_get_class (pIcon->cClass);
1003
 
        if (pClassAppli != NULL)  // on va chercher une icone de meme classe dans le dock principal
1004
 
        {
1005
 
                // on cherche un inhibiteur de cette classe, de preference un lanceur.
1006
 
                Icon *pSameClassIcon = NULL;
1007
 
                CairoDock *pDock;
1008
 
                Icon *pInhibatorIcon;
1009
 
                GList *ic;
1010
 
                for (ic = pClassAppli->pIconsOfClass; ic != NULL; ic = ic->next)
1011
 
                {
1012
 
                        pInhibatorIcon = ic->data;
1013
 
                        if (CAIRO_DOCK_IS_APPLET (pInhibatorIcon) && myIcons.iSeparateIcons)
1014
 
                                continue;
1015
 
                        pDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
1016
 
                        if (!pDock || !pDock->bIsMainDock)
1017
 
                                pInhibatorIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
1018
 
                        pSameClassIcon = pInhibatorIcon;
1019
 
                        if (CAIRO_DOCK_IS_LAUNCHER (pSameClassIcon))  // on prend les lanceurs de preference.
1020
 
                                break ;
1021
 
                }
1022
 
                
1023
 
                // si aucun trouve, on cherche une autre appli de cette classe.
1024
 
                if (pSameClassIcon == NULL)
1025
 
                {
1026
 
                        Icon *pAppliIcon = NULL;
1027
 
                        for (ic = pClassAppli->pAppliOfClass; ic != NULL; ic = ic->next)
1028
 
                        {
1029
 
                                pAppliIcon = ic->data;
1030
 
                                if (pAppliIcon == pIcon)
1031
 
                                        continue;
1032
 
                                pDock = cairo_dock_search_dock_from_name (pAppliIcon->cParentDockName);
1033
 
                                if (pDock && pDock->bIsMainDock)
1034
 
                                {
1035
 
                                        pSameClassIcon = pAppliIcon;
1036
 
                                        break ;
1037
 
                                }
1038
 
                        }
1039
 
                }
1040
 
                
1041
 
                // on se place entre l'icone trouvee et la suivante de classe differente.
1042
 
                if (pSameClassIcon != NULL)  // une icone de meme classe existe dans le main dock, on va se placer apres.
1043
 
                {
1044
 
                        Icon *pNextIcon = NULL;
1045
 
                        ic = g_list_find (g_pMainDock->icons, pSameClassIcon);
1046
 
                        if (ic && ic->next != NULL)  // on remonte vers la droite toutes les icones de meme classe, et on cherche l'icone suivante.
1047
 
                        {
1048
 
                                ic = ic->next;
1049
 
                                for (;ic != NULL; ic = ic->next)
1050
 
                                {
1051
 
                                        pNextIcon = ic->data;
1052
 
                                        if (!pNextIcon->cClass || strcmp (pNextIcon->cClass, pIcon->cClass) != 0)
1053
 
                                                break;
1054
 
                                        pSameClassIcon = pNextIcon;
1055
 
                                        pNextIcon = NULL;
1056
 
                                }
1057
 
                        }
1058
 
                        //g_print ("on se place apres la derniere icone de cette classe\n");
1059
 
                        if (pNextIcon != NULL && cairo_dock_get_icon_order (pNextIcon) == cairo_dock_get_icon_order (pSameClassIcon))  // l'icone suivante est dans le meme groupe que nous, on s'intercalle entre elle et pSameClassIcon.
1060
 
                                fOrder = (pNextIcon->fOrder + pSameClassIcon->fOrder) / 2;
1061
 
                        else  // aucune icone apres notre classe, ou alors dans un groupe different, on se place juste apres pSameClassIcon.
1062
 
                                fOrder = pSameClassIcon->fOrder + 1;
1063
 
                }
1064
 
        }
1065
 
        
1066
 
        if (fOrder == CAIRO_DOCK_LAST_ORDER)  // cette classe n'existe pas encore ou est vide ou n'a aucune icone dans le main dock => on va se positionner par rapport a la derniere appli.
1067
 
        {
1068
 
                GList* ic;
1069
 
                Icon *icon;
1070
 
                for (ic = g_list_last (g_pMainDock->icons); ic != NULL; ic = ic->prev)
1071
 
                {
1072
 
                        icon = ic->data;
1073
 
                        if (icon->iType == CAIRO_DOCK_APPLI && ! cairo_dock_class_is_inhibated (icon->cClass))  // on verifie qu'elle n'est pas placé a cote de son lanceur, sinon cela cree des incoherences suivants que l'appli est lancee 2 fois ou pas.
1074
 
                        {
1075
 
                                break ;
1076
 
                        }
1077
 
                }
1078
 
                if (ic != NULL)  // on a trouve une icone d'appli.
1079
 
                {
1080
 
                        //g_print ("on se place apres la derniere appli\n");
1081
 
                        ic = ic->next;
1082
 
                        Icon *next_icon = (ic ? ic->data : NULL);
1083
 
                        if (next_icon != NULL && cairo_dock_get_icon_order (next_icon) == cairo_dock_get_icon_order (icon))
1084
 
                                fOrder = (icon->fOrder + next_icon->fOrder) / 2;
1085
 
                        else
1086
 
                                fOrder = icon->fOrder + 1;
1087
 
                }
1088
 
                else if (myTaskBar.bMixLauncherAppli)  // on decide de la placer apres le dernier lanceur dans le cas ou les lanceurs peuvent faire appli.
1089
 
                {
1090
 
                        for (ic = g_list_last (g_pMainDock->icons); ic != NULL; ic = ic->prev)
1091
 
                        {
1092
 
                                icon = ic->data;
1093
 
                                if (icon->iType == CAIRO_DOCK_LAUNCHER)
1094
 
                                        break;
1095
 
                        }
1096
 
                        if (ic != NULL)  // on a trouve une icone de lanceur.
1097
 
                        {
1098
 
                                //g_print ("on se place apres le dernier lanceur\n");
1099
 
                                ic = ic->next;
1100
 
                                Icon *next_icon = (ic ? ic->data : NULL);
1101
 
                                if (next_icon != NULL && cairo_dock_get_icon_order (next_icon) == cairo_dock_get_icon_order (icon))
1102
 
                                        fOrder = (icon->fOrder + next_icon->fOrder) / 2;
1103
 
                                else
1104
 
                                        fOrder = icon->fOrder + 1;
1105
 
                        }
1106
 
                }
1107
 
        }
1108
 
        pIcon->fOrder = fOrder;
1109
 
}
1110
 
 
1111
 
static void _cairo_dock_reorder_one_class (gchar *cClass, CairoDockClassAppli *pClassAppli, int *iMaxOrder)
1112
 
{
1113
 
        // on touve un inhibiteur par rapport auquel se placer.
1114
 
        Icon *pSameClassIcon = NULL;
1115
 
        Icon *pInhibatorIcon;
1116
 
        CairoDock *pParentDock;
1117
 
        GList *ic;
1118
 
        for (ic = pClassAppli->pIconsOfClass; ic != NULL; ic = ic->next)
1119
 
        {
1120
 
                pInhibatorIcon = ic->data;
1121
 
                if (CAIRO_DOCK_IS_APPLET (pInhibatorIcon) && myIcons.iSeparateIcons)
1122
 
                        continue;
1123
 
                
1124
 
                pParentDock = cairo_dock_search_dock_from_name (pInhibatorIcon->cParentDockName);
1125
 
                CairoDock *pDock;
1126
 
                while (pParentDock && pParentDock->iRefCount != 0)
1127
 
                {
1128
 
                        pDock = pParentDock;
1129
 
                        pInhibatorIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pParentDock);
1130
 
                }
1131
 
                if (!pParentDock || !pParentDock->bIsMainDock)  // on place les icones d'applis dans le main dock.
1132
 
                        continue;
1133
 
                pSameClassIcon = pInhibatorIcon;
1134
 
                if (CAIRO_DOCK_IS_LAUNCHER (pSameClassIcon))  // on prend les lanceurs de preference aux applets.
1135
 
                        break ;
1136
 
        }
1137
 
        
1138
 
        // on cherche une icone qui nous borne a droite.
1139
 
        Icon *pNextIcon = NULL;
1140
 
        if (pSameClassIcon != NULL)  // on se place apres l'icone trouve.
1141
 
        {
1142
 
                ic = g_list_find (g_pMainDock->icons, pSameClassIcon);
1143
 
                if (ic != NULL && ic->next != NULL)  // on remonte vers la droite jusqu'a trouver une icone de classe differente.
1144
 
                {
1145
 
                        for (ic = ic->next; ic != NULL; ic = ic->next)
1146
 
                        {
1147
 
                                pNextIcon = ic->data;
1148
 
                                if (!pNextIcon->cClass || strcmp (pNextIcon->cClass, cClass) != 0)  // icone d'une autre classe. (pSameClassIcon->cClass peut etre NULL dans le cas d'un inhibiteur place dans un sous-dock, car alors pSameClassIcon est l'icone pointant sur le sous-dock.)
1149
 
                                        break;
1150
 
                                pSameClassIcon = pNextIcon;
1151
 
                                pNextIcon = NULL;
1152
 
                        }
1153
 
                }
1154
 
        }
1155
 
        
1156
 
        // on se place entre les 2 icones, ou a la fin si aucune icone trouvee.
1157
 
        Icon *pAppliIcon;
1158
 
        CairoDock *pDock;
1159
 
        if (pNextIcon != NULL)  // on se place entre les 2.
1160
 
        {
1161
 
                int i=1, iNbIcons = g_list_length (pClassAppli->pAppliOfClass);  // majorant.
1162
 
                for (ic = pClassAppli->pAppliOfClass; ic != NULL; ic = ic->next)
1163
 
                {
1164
 
                        pAppliIcon = ic->data;
1165
 
                        pDock = cairo_dock_search_dock_from_name (pAppliIcon->cParentDockName);
1166
 
                        if (pDock && pDock->iRefCount == 0)
1167
 
                        {
1168
 
                                pAppliIcon->fOrder = pSameClassIcon->fOrder + (pNextIcon->fOrder - pSameClassIcon->fOrder) * i / (iNbIcons + 1);
1169
 
                                i ++;
1170
 
                        }
1171
 
                }
1172
 
        }
1173
 
        else  // on se place a la fin.
1174
 
        {
1175
 
                for (ic = pClassAppli->pAppliOfClass; ic != NULL; ic = ic->next)
1176
 
                {
1177
 
                        pAppliIcon = ic->data;
1178
 
                        pDock = cairo_dock_search_dock_from_name (pAppliIcon->cParentDockName);
1179
 
                        if (pDock && pDock->iRefCount == 0)
1180
 
                        {
1181
 
                                pAppliIcon->fOrder = *iMaxOrder;
1182
 
                                *iMaxOrder ++;
1183
 
                        }
1184
 
                }
1185
 
        }
1186
 
}
1187
 
void cairo_dock_reorder_classes (void)
1188
 
{
1189
 
        Icon *pLastIcon = cairo_dock_get_last_icon (g_pMainDock->icons);
1190
 
        int iMaxOrder = (pLastIcon ? pLastIcon->fOrder + 1 : 1);
1191
 
        g_hash_table_foreach (s_hClassTable, (GHFunc) _cairo_dock_reorder_one_class, &iMaxOrder);
1192
 
}
1193