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/>.
29
#include <X11/Xatom.h>
30
#include <X11/Xutil.h>
32
#include "cairo-dock-icons.h"
33
#include "cairo-dock-animations.h"
34
#include "cairo-dock-load.h"
35
#include "cairo-dock-dock-factory.h"
36
#include "cairo-dock-dock-facility.h"
37
#include "cairo-dock-container.h"
38
#include "cairo-dock-notifications.h"
39
#include "cairo-dock-callbacks.h"
40
#include "cairo-dock-log.h"
41
#include "cairo-dock-X-utilities.h"
42
#include "cairo-dock-config.h"
43
#include "cairo-dock-dock-manager.h"
44
#include "cairo-dock-class-manager.h"
45
#include "cairo-dock-dialog-manager.h"
46
#include "cairo-dock-animations.h"
47
#include "cairo-dock-internal-taskbar.h"
48
#include "cairo-dock-internal-icons.h"
49
#include "cairo-dock-internal-accessibility.h"
50
#include "cairo-dock-internal-labels.h"
51
#include "cairo-dock-application-facility.h"
52
#include "cairo-dock-applications-manager.h"
53
#include "cairo-dock-X-manager.h"
55
#define CAIRO_DOCK_TASKBAR_CHECK_INTERVAL 200
57
CairoDockDesktopGeometry g_desktopGeometry;
58
extern CairoContainer *g_pPrimaryContainer;
59
//extern int g_iDamageEvent;
61
static Display *s_XDisplay = NULL;
62
static int s_iSidPollXEvents = 0;
63
static Atom s_aNetClientList;
64
static Atom s_aNetActiveWindow;
65
static Atom s_aNetCurrentDesktop;
66
static Atom s_aNetDesktopViewport;
67
static Atom s_aNetDesktopGeometry;
68
static Atom s_aNetShowingDesktop;
69
static Atom s_aRootMapID;
70
static Atom s_aNetNbDesktops;
71
static Atom s_aXKlavierState;
73
static gboolean _cairo_dock_window_is_on_our_way (Window *Xid, Icon *icon, gpointer *data);
75
///////////////////////
76
// X listener : core //
77
///////////////////////
79
static inline void _cairo_dock_retrieve_current_desktop_and_viewport (void)
81
g_desktopGeometry.iCurrentDesktop = cairo_dock_get_current_desktop ();
82
cairo_dock_get_current_viewport (&g_desktopGeometry.iCurrentViewportX, &g_desktopGeometry.iCurrentViewportY);
83
g_desktopGeometry.iCurrentViewportX /= g_desktopGeometry.iXScreenWidth[CAIRO_DOCK_HORIZONTAL];
84
g_desktopGeometry.iCurrentViewportY /= g_desktopGeometry.iXScreenHeight[CAIRO_DOCK_HORIZONTAL];
87
static gboolean _on_change_current_desktop_viewport (void)
89
_cairo_dock_retrieve_current_desktop_and_viewport ();
91
// on propage la notification.
92
cairo_dock_notify (CAIRO_DOCK_DESKTOP_CHANGED);
94
// on gere le cas delicat de X qui nous fait sortir du dock plus tard.
98
static void _on_change_nb_desktops (void)
100
g_desktopGeometry.iNbDesktops = cairo_dock_get_nb_desktops ();
101
_cairo_dock_retrieve_current_desktop_and_viewport (); // au cas ou on enleve le bureau courant.
103
cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
106
static void _on_change_desktop_geometry (void)
108
if (cairo_dock_update_screen_geometry ()) // modification de la resolution.
110
cd_message ("resolution alteree");
112
cairo_dock_reposition_root_docks (FALSE); // main dock compris. Se charge de Xinerama.
115
cairo_dock_get_nb_viewports (&g_desktopGeometry.iNbViewportX, &g_desktopGeometry.iNbViewportY);
116
_cairo_dock_retrieve_current_desktop_and_viewport (); // au cas ou on enleve le viewport courant.
118
cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
121
static void _check_mouse_outside (CairoDock *pDock, gpointer data)
123
if (pDock->container.bIsHorizontal)
124
gdk_window_get_pointer (pDock->container.pWidget->window, &pDock->container.iMouseX, &pDock->container.iMouseY, NULL);
126
gdk_window_get_pointer (pDock->container.pWidget->window, &pDock->container.iMouseY, &pDock->container.iMouseX, NULL);
127
cairo_dock_calculate_dock_icons (pDock); // pour faire retrecir le dock si on n'est pas dedans, merci X de nous faire sortir du dock alors que la souris est toujours dedans :-/
129
static gboolean _cairo_dock_unstack_Xevents (gpointer data)
132
static gboolean bCheckMouseIsOutside = FALSE;
134
if (!g_pPrimaryContainer) // peut arriver en cours de chargement d'un theme.
137
long event_mask = 0xFFFFFFFF; // on les recupere tous, ca vide la pile au fur et a mesure plutot que tout a la fin.
139
Window root = DefaultRootWindow (s_XDisplay);
141
if (bCheckMouseIsOutside)
143
//g_print ("bCheckMouseIsOutside\n");
144
bCheckMouseIsOutside = FALSE;
145
cairo_dock_foreach_root_docks ((GFunc)_check_mouse_outside, NULL);
148
while (XCheckMaskEvent (s_XDisplay, event_mask, &event))
151
Xid = event.xany.window;
152
//g_print (" type : %d; atom : %s; window : %d\n", event.type, gdk_x11_get_xatom_name (event.xproperty.atom), Xid);
153
//if (event.type == ClientMessage)
154
//cd_message ("\n\n\n >>>>>>>>>>>< event.type : %d\n\n", event.type);
157
if (event.type == PropertyNotify) // PropertyNotify sur root
159
if (event.xproperty.atom == s_aNetClientList)
161
cairo_dock_notify (CAIRO_DOCK_WINDOW_CONFIGURED, Xid, NULL);
163
else if (event.xproperty.atom == s_aNetActiveWindow)
165
Window XActiveWindow = cairo_dock_get_active_xwindow ();
166
cairo_dock_notify (CAIRO_DOCK_WINDOW_ACTIVATED, &XActiveWindow);
168
else if (event.xproperty.atom == s_aNetCurrentDesktop || event.xproperty.atom == s_aNetDesktopViewport)
170
bCheckMouseIsOutside = _on_change_current_desktop_viewport (); // -> CAIRO_DOCK_DESKTOP_CHANGED
171
bCheckMouseIsOutside = TRUE; // au prochain passage, on testera que X ne nous a pas fait sortir du dock sans raison.
173
else if (event.xproperty.atom == s_aNetNbDesktops)
175
_on_change_nb_desktops (); // -> CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED
177
else if (event.xproperty.atom == s_aNetDesktopGeometry)
179
_on_change_desktop_geometry (); // -> CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED
181
else if (event.xproperty.atom == s_aRootMapID)
183
cd_debug ("change wallpaper");
184
cairo_dock_reload_desktop_background ();
185
cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
187
else if (event.xproperty.atom == s_aNetShowingDesktop)
189
cairo_dock_notify (CAIRO_DOCK_DESKTOP_VISIBILITY_CHANGED);
191
else if (event.xproperty.atom == s_aXKlavierState)
193
cairo_dock_notify (CAIRO_DOCK_KBD_STATE_CHANGED, NULL);
195
} // fin de PropertyNotify sur root.
197
else // evenement sur une fenetre.
199
if (event.type == PropertyNotify) // PropertyNotify sur une fenetre
201
if (event.xproperty.atom == s_aXKlavierState)
203
cairo_dock_notify (CAIRO_DOCK_KBD_STATE_CHANGED, &Xid);
207
cairo_dock_notify (CAIRO_DOCK_WINDOW_PROPERTY_CHANGED, Xid, event.xproperty.atom, event.xproperty.state);
210
else if (event.type == ConfigureNotify) // ConfigureNotify sur une fenetre.
212
cairo_dock_notify (CAIRO_DOCK_WINDOW_CONFIGURED, Xid, &event.xconfigure);
214
/*else if (event.type == g_iDamageEvent + XDamageNotify)
216
XDamageNotifyEvent *e = (XDamageNotifyEvent *) &event;
217
cd_debug ("window %s has been damaged (%d;%d %dx%d)\n", e->drawable, e->area.x, e->area.y, e->area.width, e->area.height);
218
// e->drawable is the window ID of the damaged window
219
// e->geometry is the geometry of the damaged window
220
// e->area is the bounding rect for the damaged area
221
// e->damage is the damage handle returned by XDamageCreate()
222
// Subtract all the damage, repairing the window.
223
XDamageSubtract (s_XDisplay, e->damage, None, None);
226
cd_debug (" type : %d (%d); window : %d\n", event.type, XDamageNotify, Xid);*/
227
} // fin d'evenement sur une fenetre.
229
if (XEventsQueued (s_XDisplay, QueuedAlready) != 0)
230
XSync (s_XDisplay, True); // True <=> discard.
231
//g_print ("XEventsQueued : %d\n", XEventsQueued (s_XDisplay, QueuedAfterFlush)); // QueuedAlready, QueuedAfterReading, QueuedAfterFlush
236
static void cairo_dock_initialize_X_manager (Display *pDisplay)
238
s_XDisplay = pDisplay;
240
s_aNetClientList = XInternAtom (s_XDisplay, "_NET_CLIENT_LIST_STACKING", False);
241
s_aNetActiveWindow = XInternAtom (s_XDisplay, "_NET_ACTIVE_WINDOW", False);
242
s_aNetCurrentDesktop = XInternAtom (s_XDisplay, "_NET_CURRENT_DESKTOP", False);
243
s_aNetDesktopViewport = XInternAtom (s_XDisplay, "_NET_DESKTOP_VIEWPORT", False);
244
s_aNetDesktopGeometry = XInternAtom (s_XDisplay, "_NET_DESKTOP_GEOMETRY", False);
245
s_aNetShowingDesktop = XInternAtom (s_XDisplay, "_NET_SHOWING_DESKTOP", False);
246
s_aRootMapID = XInternAtom (s_XDisplay, "_XROOTPMAP_ID", False);
247
s_aNetNbDesktops = XInternAtom (s_XDisplay, "_NET_NUMBER_OF_DESKTOPS", False);
248
s_aXKlavierState = XInternAtom (s_XDisplay, "XKLAVIER_STATE", False);
251
void cairo_dock_start_X_manager (void)
253
g_return_if_fail (s_iSidPollXEvents == 0);
255
//\__________________ On initialise le support de X.
256
Display *pDisplay = cairo_dock_initialize_X_desktop_support (); // renseigne la taille de l'ecran.
257
cairo_dock_initialize_class_manager ();
258
cairo_dock_initialize_application_manager (pDisplay);
259
cairo_dock_initialize_X_manager (pDisplay);
261
//\__________________ On recupere le bureau courant.
262
g_desktopGeometry.iNbDesktops = cairo_dock_get_nb_desktops ();
263
cairo_dock_get_nb_viewports (&g_desktopGeometry.iNbViewportX, &g_desktopGeometry.iNbViewportY);
264
_cairo_dock_retrieve_current_desktop_and_viewport ();
266
//\__________________ On se met a l'ecoute des evenements X.
267
Window root = DefaultRootWindow (s_XDisplay);
268
cairo_dock_set_xwindow_mask (root, PropertyChangeMask /*| StructureNotifyMask | SubstructureNotifyMask | ResizeRedirectMask | SubstructureRedirectMask*/);
270
//\__________________ On lance l'ecoute.
271
s_iSidPollXEvents = g_timeout_add (CAIRO_DOCK_TASKBAR_CHECK_INTERVAL, (GSourceFunc) _cairo_dock_unstack_Xevents, (gpointer) NULL); // un g_idle_add () consomme 90% de CPU ! :-/
274
void cairo_dock_stop_X_manager (void) // le met seulement en pause.
276
g_return_if_fail (s_iSidPollXEvents != 0);
278
//\__________________ On arrete l'ecoute.
279
g_source_remove (s_iSidPollXEvents);
280
s_iSidPollXEvents = 0;
283
/////////////////////////
284
// X listener : access //
285
/////////////////////////
287
void cairo_dock_get_current_desktop_and_viewport (int *iCurrentDesktop, int *iCurrentViewportX, int *iCurrentViewportY)
289
*iCurrentDesktop = g_desktopGeometry.iCurrentDesktop;
290
*iCurrentViewportX = g_desktopGeometry.iCurrentViewportX;
291
*iCurrentViewportY = g_desktopGeometry.iCurrentViewportY;