2
* This file is a part of the Cairo-Dock project
4
* Copyright : (C) see the 'copyright' file.
5
* E-mail : see the 'copyright' file.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 3
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
26
#include <X11/Xatom.h>
27
#include <X11/Xutil.h>
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"
39
extern CairoDock *g_pMainDock;
40
extern CairoDockDesktopGeometry g_desktopGeometry;
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;
58
void cairo_dock_initialize_application_factory (Display *pXDisplay)
60
s_XDisplay = pXDisplay;
61
g_return_if_fail (s_XDisplay != NULL);
63
s_aNetWmIcon = XInternAtom (s_XDisplay, "_NET_WM_ICON", False);
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);
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);
74
s_aWmHints = XInternAtom (s_XDisplay, "WM_HINTS", False);
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);
82
static Window _cairo_dock_get_parent_window (Window Xid)
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);
90
Window xParentWindow = (iBufferNbElements > 0 && pXBuffer != NULL ? pXBuffer[0] : 0);
95
Icon * cairo_dock_new_appli_icon (Window Xid, Window *XParentWindow)
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;
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)
112
guint i, iNbMaximizedDimensions = 0;
113
for (i = 0; i < iBufferNbElements && ! bSkip; i ++)
115
if (pXStateBuffer[i] == s_aNetWmSkipTaskbar)
117
else if (pXStateBuffer[i] == s_aNetWmHidden)
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 ...
130
bIsMaximized = (iNbMaximizedDimensions == 2);
131
//g_print (" -------- bSkip : %d\n", bSkip);
132
XFree (pXStateBuffer);
136
cd_debug (" cette fenetre est timide");
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)
146
gboolean bKeep = FALSE;
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.
150
if (pTypeBuffer[i] == s_aNetWmWindowTypeNormal) // une fenetre normale, on prend.
155
if (pTypeBuffer[i] == s_aNetWmWindowTypeDialog) // on saute si c'est un dialogue modal, sinon on garde.
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)
163
cd_debug (" dialogue 'transient for %d' => on ignore", XMainAppliWindow);
164
if (bDemandsAttention)
165
*XParentWindow = XMainAppliWindow;
170
} // autre type : on saute.
175
cd_debug ("type indesirable (%d)\n", *pTypeBuffer);
179
else // pas de type defini.
181
Window XMainAppliWindow = 0;
182
XGetTransientForHint (s_XDisplay, Xid, &XMainAppliWindow);
183
if (XMainAppliWindow != 0)
185
cd_debug (" fenetre modale => on saute.");
186
if (bDemandsAttention)
187
*XParentWindow = XMainAppliWindow;
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);
196
//\__________________ On recupere la classe.
197
XClassHint *pClassHint = XAllocClassHint ();
198
gchar *cClass = NULL;
199
if (XGetClassHint (s_XDisplay, Xid, pClassHint) != 0 && pClassHint->res_class)
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"))
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);
207
else if (*pClassHint->res_class == '/' && g_str_has_suffix (pClassHint->res_class, ".exe")) // cas des applications Mono telles que tomboy ...
209
gchar *str = strrchr (pClassHint->res_class, '/');
213
str = pClassHint->res_class;
214
cClass = g_ascii_strdown (str, -1);
215
cClass[strlen (cClass) - 4] = '\0';
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.
222
cairo_dock_remove_version_from_string (cClass); // on enleve les numeros de version (Openoffice.org-3.1)
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).
227
cd_debug ("got an application with class '%s'", cClass);
229
XFree (pClassHint->res_name);
230
XFree (pClassHint->res_class);
234
cd_warning ("this window doesn't belong to any class, skip it.");
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;
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;
254
icon->iNumDesktop = cairo_dock_get_xwindow_desktop (Xid);
256
int iLocalPositionX, iLocalPositionY, iWidthExtent, iHeightExtent;
257
cairo_dock_get_xwindow_geometry (Xid, &iLocalPositionX, &iLocalPositionY, &iWidthExtent, &iHeightExtent);
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;
262
icon->windowGeometry.x = iLocalPositionX;
263
icon->windowGeometry.y = iLocalPositionY;
264
icon->windowGeometry.width = iWidthExtent;
265
icon->windowGeometry.height = iHeightExtent;
267
cairo_dock_set_xwindow_mask (Xid, PropertyChangeMask | StructureNotifyMask);