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

« back to all changes in this revision

Viewing changes to src/icon-factory/cairo-dock-application-factory.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 <cairo.h>
 
23
#include <stdlib.h>
 
24
 
 
25
#include <X11/Xlib.h>
 
26
#include <X11/Xatom.h>
 
27
#include <X11/Xutil.h>
 
28
#include <gdk/gdkx.h>
 
29
 
 
30
#include "cairo-dock-icons.h"
 
31
#include "cairo-dock-animations.h"
 
32
#include "cairo-dock-log.h"
 
33
#include "cairo-dock-X-utilities.h"
 
34
#include "cairo-dock-launcher-factory.h"
 
35
#include "cairo-dock-application-facility.h"
 
36
#include "cairo-dock-X-manager.h"
 
37
#include "cairo-dock-application-factory.h"
 
38
 
 
39
extern CairoDock *g_pMainDock;
 
40
extern CairoDockDesktopGeometry g_desktopGeometry;
 
41
 
 
42
static Display *s_XDisplay = NULL;
 
43
static Atom s_aNetWmIcon;
 
44
static Atom s_aNetWmState;
 
45
static Atom s_aNetWmSkipPager;
 
46
static Atom s_aNetWmSkipTaskbar;
 
47
static Atom s_aNetWmWindowType;
 
48
static Atom s_aNetWmWindowTypeNormal;
 
49
static Atom s_aNetWmWindowTypeDialog;
 
50
static Atom s_aWmHints;
 
51
static Atom s_aNetWmHidden;
 
52
static Atom s_aNetWmFullScreen;
 
53
static Atom s_aNetWmMaximizedHoriz;
 
54
static Atom s_aNetWmMaximizedVert;
 
55
static Atom s_aNetWmDemandsAttention;
 
56
 
 
57
 
 
58
void cairo_dock_initialize_application_factory (Display *pXDisplay)
 
59
{
 
60
        s_XDisplay = pXDisplay;
 
61
        g_return_if_fail (s_XDisplay != NULL);
 
62
 
 
63
        s_aNetWmIcon = XInternAtom (s_XDisplay, "_NET_WM_ICON", False);
 
64
 
 
65
        s_aNetWmState = XInternAtom (s_XDisplay, "_NET_WM_STATE", False);
 
66
        s_aNetWmSkipPager = XInternAtom (s_XDisplay, "_NET_WM_STATE_SKIP_PAGER", False);
 
67
        s_aNetWmSkipTaskbar = XInternAtom (s_XDisplay, "_NET_WM_STATE_SKIP_TASKBAR", False);
 
68
        s_aNetWmHidden = XInternAtom (s_XDisplay, "_NET_WM_STATE_HIDDEN", False);
 
69
 
 
70
        s_aNetWmWindowType = XInternAtom (s_XDisplay, "_NET_WM_WINDOW_TYPE", False);
 
71
        s_aNetWmWindowTypeNormal = XInternAtom (s_XDisplay, "_NET_WM_WINDOW_TYPE_NORMAL", False);
 
72
        s_aNetWmWindowTypeDialog = XInternAtom (s_XDisplay, "_NET_WM_WINDOW_TYPE_DIALOG", False);
 
73
        
 
74
        s_aWmHints = XInternAtom (s_XDisplay, "WM_HINTS", False);
 
75
        
 
76
        s_aNetWmFullScreen = XInternAtom (s_XDisplay, "_NET_WM_STATE_FULLSCREEN", False);
 
77
        s_aNetWmMaximizedHoriz = XInternAtom (s_XDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
 
78
        s_aNetWmMaximizedVert = XInternAtom (s_XDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", False);
 
79
        s_aNetWmDemandsAttention = XInternAtom (s_XDisplay, "_NET_WM_STATE_DEMANDS_ATTENTION", False);
 
80
}
 
81
 
 
82
static Window _cairo_dock_get_parent_window (Window Xid)
 
83
{
 
84
        Atom aReturnedType = 0;
 
85
        int aReturnedFormat = 0;
 
86
        unsigned long iLeftBytes, iBufferNbElements = 0;
 
87
        Window *pXBuffer = NULL;
 
88
        XGetWindowProperty (s_XDisplay, Xid, XInternAtom (s_XDisplay, "WM_TRANSIENT_FOR", False), 0, G_MAXULONG, False, XA_WINDOW, &aReturnedType, &aReturnedFormat, &iBufferNbElements, &iLeftBytes, (guchar **)&pXBuffer);
 
89
 
 
90
        Window xParentWindow = (iBufferNbElements > 0 && pXBuffer != NULL ? pXBuffer[0] : 0);
 
91
        if (pXBuffer != NULL)
 
92
                XFree (pXBuffer);
 
93
        return xParentWindow;
 
94
}
 
95
Icon * cairo_dock_new_appli_icon (Window Xid, Window *XParentWindow)
 
96
{
 
97
        //g_print ("%s (%d)\n", __func__, Xid);
 
98
        guchar *pNameBuffer = NULL;
 
99
        Atom aReturnedType = 0;
 
100
        int aReturnedFormat = 0;
 
101
        unsigned long iLeftBytes, iBufferNbElements;
 
102
        cairo_surface_t *pNewSurface = NULL;
 
103
        double fWidth, fHeight;
 
104
 
 
105
        //\__________________ On regarde si on doit l'afficher ou la sauter.
 
106
        gboolean bSkip = FALSE, bIsHidden = FALSE, bIsFullScreen = FALSE, bIsMaximized = FALSE, bDemandsAttention = FALSE;
 
107
        gulong *pXStateBuffer = NULL;
 
108
        iBufferNbElements = 0;
 
109
        XGetWindowProperty (s_XDisplay, Xid, s_aNetWmState, 0, G_MAXULONG, False, XA_ATOM, &aReturnedType, &aReturnedFormat, &iBufferNbElements, &iLeftBytes, (guchar **)&pXStateBuffer);
 
110
        if (iBufferNbElements > 0)
 
111
        {
 
112
                guint i, iNbMaximizedDimensions = 0;
 
113
                for (i = 0; i < iBufferNbElements && ! bSkip; i ++)
 
114
                {
 
115
                        if (pXStateBuffer[i] == s_aNetWmSkipTaskbar)
 
116
                                bSkip = TRUE;
 
117
                        else if (pXStateBuffer[i] == s_aNetWmHidden)
 
118
                                bIsHidden = TRUE;
 
119
                        else if (pXStateBuffer[i] == s_aNetWmMaximizedVert)
 
120
                                iNbMaximizedDimensions ++;
 
121
                        else if (pXStateBuffer[i] == s_aNetWmMaximizedHoriz)
 
122
                                iNbMaximizedDimensions ++;
 
123
                        else if (pXStateBuffer[i] == s_aNetWmFullScreen)
 
124
                                bIsFullScreen = TRUE;
 
125
                        else if (pXStateBuffer[i] == s_aNetWmDemandsAttention)
 
126
                                bDemandsAttention = TRUE;
 
127
                        //else if (pXStateBuffer[i] == s_aNetWmSkipPager)  // contestable ...
 
128
                        //      bSkip = TRUE;
 
129
                }
 
130
                bIsMaximized = (iNbMaximizedDimensions == 2);
 
131
                //g_print (" -------- bSkip : %d\n",  bSkip);
 
132
                XFree (pXStateBuffer);
 
133
        }
 
134
        if (bSkip)
 
135
        {
 
136
                cd_debug ("  cette fenetre est timide");
 
137
                return NULL;
 
138
        }
 
139
 
 
140
        //\__________________ On regarde son type.
 
141
        gulong *pTypeBuffer = NULL;
 
142
        cd_debug (" + nouvelle icone d'appli (%d)", Xid);
 
143
        XGetWindowProperty (s_XDisplay, Xid, s_aNetWmWindowType, 0, G_MAXULONG, False, XA_ATOM, &aReturnedType, &aReturnedFormat, &iBufferNbElements, &iLeftBytes, (guchar **)&pTypeBuffer);
 
144
        if (iBufferNbElements != 0)
 
145
        {
 
146
                gboolean bKeep = FALSE;
 
147
                guint i;
 
148
                for (i = 0; i < iBufferNbElements; i ++)  // The Client SHOULD specify window types in order of preference (the first being most preferable) but MUST include at least one of the basic window type atoms.
 
149
                {
 
150
                        if (pTypeBuffer[i] == s_aNetWmWindowTypeNormal)  // une fenetre normale, on prend.
 
151
                        {
 
152
                                bKeep = TRUE;
 
153
                                break;
 
154
                        }
 
155
                        if (pTypeBuffer[i] == s_aNetWmWindowTypeDialog)  // on saute si c'est un dialogue modal, sinon on garde.
 
156
                        {
 
157
                                /*Window iPropWindow;
 
158
                                XGetTransientForHint (s_XDisplay, Xid, &iPropWindow);
 
159
                                cd_debug ("%s\n", gdk_x11_get_xatom_name (iPropWindow));*/
 
160
                                Window XMainAppliWindow = _cairo_dock_get_parent_window (Xid);
 
161
                                if (XMainAppliWindow != 0)
 
162
                                {
 
163
                                        cd_debug ("  dialogue 'transient for %d' => on ignore", XMainAppliWindow);
 
164
                                        if (bDemandsAttention)
 
165
                                                *XParentWindow = XMainAppliWindow;
 
166
                                        break;
 
167
                                }
 
168
                                bKeep = TRUE;
 
169
                                break;
 
170
                        }  // autre type : on saute.
 
171
                }
 
172
                XFree (pTypeBuffer);
 
173
                if (! bKeep)
 
174
                {
 
175
                        cd_debug ("type indesirable (%d)\n", *pTypeBuffer);
 
176
                        return NULL;
 
177
                }
 
178
        }
 
179
        else  // pas de type defini.
 
180
        {
 
181
                Window XMainAppliWindow = 0;
 
182
                XGetTransientForHint (s_XDisplay, Xid, &XMainAppliWindow);
 
183
                if (XMainAppliWindow != 0)
 
184
                {
 
185
                        cd_debug ("  fenetre modale => on saute.");
 
186
                        if (bDemandsAttention)
 
187
                                *XParentWindow = XMainAppliWindow;
 
188
                        return NULL;
 
189
                }
 
190
        }
 
191
        
 
192
        //\__________________ On recupere son nom.
 
193
        gchar *cName = cairo_dock_get_xwindow_name (Xid, TRUE);
 
194
        cd_debug ("recuperation de '%s' (bIsHidden : %d)", cName, bIsHidden);
 
195
        
 
196
        //\__________________ On recupere la classe.
 
197
        XClassHint *pClassHint = XAllocClassHint ();
 
198
        gchar *cClass = NULL;
 
199
        if (XGetClassHint (s_XDisplay, Xid, pClassHint) != 0 && pClassHint->res_class)
 
200
        {
 
201
                cd_debug ("  res_name : %s(%x); res_class : %s(%x)", pClassHint->res_name, pClassHint->res_name, pClassHint->res_class, pClassHint->res_class);
 
202
                if (strcmp (pClassHint->res_class, "Wine") == 0 && pClassHint->res_name && g_str_has_suffix (pClassHint->res_name, ".exe"))
 
203
                {
 
204
                        cd_debug ("  wine application detected, changing the class '%s' to '%s'", pClassHint->res_class, pClassHint->res_name);
 
205
                        cClass = g_ascii_strdown (pClassHint->res_name, -1);
 
206
                }
 
207
                else if (*pClassHint->res_class == '/' && g_str_has_suffix (pClassHint->res_class, ".exe"))  // cas des applications Mono telles que tomboy ...
 
208
                {
 
209
                        gchar *str = strrchr (pClassHint->res_class, '/');
 
210
                        if (str)
 
211
                                str ++;
 
212
                        else
 
213
                                str = pClassHint->res_class;
 
214
                        cClass = g_ascii_strdown (str, -1);
 
215
                        cClass[strlen (cClass) - 4] = '\0';
 
216
                }
 
217
                else
 
218
                {
 
219
                        cClass = g_ascii_strdown (pClassHint->res_class, -1);  // on la passe en minuscule, car certaines applis ont la bonne idee de donner des classes avec une majuscule ou non suivant les fenetres.
 
220
                }
 
221
                
 
222
                cairo_dock_remove_version_from_string (cClass);  // on enleve les numeros de version (Openoffice.org-3.1)
 
223
                
 
224
                gchar *str = strchr (cClass, '.');  // on vire les .xxx, sinon on ne sait pas detecter l'absence d'extension quand on cherche l'icone (openoffice.org), ou tout simplement ca empeche de trouver l'icone (jbrout.py).
 
225
                if (str != NULL)
 
226
                        *str = '\0';
 
227
                cd_debug ("got an application with class '%s'", cClass);
 
228
                
 
229
                XFree (pClassHint->res_name);
 
230
                XFree (pClassHint->res_class);
 
231
        }
 
232
        else
 
233
        {
 
234
                cd_warning ("this window doesn't belong to any class, skip it.");
 
235
        }
 
236
        XFree (pClassHint);
 
237
        
 
238
        
 
239
        //\__________________ On cree l'icone.
 
240
        Icon *icon = g_new0 (Icon, 1);
 
241
        icon->iType = CAIRO_DOCK_APPLI;
 
242
        icon->iTrueType = CAIRO_DOCK_ICON_TYPE_APPLI;
 
243
        icon->Xid = Xid;
 
244
        
 
245
        //\__________________ On renseigne les infos en provenance de X.
 
246
        icon->cName = (cName ? cName : g_strdup (cClass));
 
247
        icon->cClass = cClass;
 
248
        icon->bIsHidden = bIsHidden;
 
249
        icon->bIsMaximized = bIsMaximized;
 
250
        icon->bIsFullScreen = bIsFullScreen;
 
251
        icon->bIsDemandingAttention = bDemandsAttention;
 
252
        icon->fOrder = CAIRO_DOCK_LAST_ORDER;
 
253
        
 
254
        icon->iNumDesktop = cairo_dock_get_xwindow_desktop (Xid);
 
255
        
 
256
        int iLocalPositionX, iLocalPositionY, iWidthExtent, iHeightExtent;
 
257
        cairo_dock_get_xwindow_geometry (Xid, &iLocalPositionX, &iLocalPositionY, &iWidthExtent, &iHeightExtent);
 
258
        
 
259
        icon->iViewPortX = iLocalPositionX / g_desktopGeometry.iXScreenWidth[CAIRO_DOCK_HORIZONTAL] + g_desktopGeometry.iCurrentViewportX;
 
260
        icon->iViewPortY = iLocalPositionY / g_desktopGeometry.iXScreenHeight[CAIRO_DOCK_HORIZONTAL] + g_desktopGeometry.iCurrentViewportY;
 
261
        
 
262
        icon->windowGeometry.x = iLocalPositionX;
 
263
        icon->windowGeometry.y = iLocalPositionY;
 
264
        icon->windowGeometry.width = iWidthExtent;
 
265
        icon->windowGeometry.height = iHeightExtent;
 
266
        
 
267
        cairo_dock_set_xwindow_mask (Xid, PropertyChangeMask | StructureNotifyMask);
 
268
 
 
269
        return icon;
 
270
}