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

« back to all changes in this revision

Viewing changes to src/gldit/cairo-dock-X-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
#define __USE_POSIX
 
25
#include <signal.h>
 
26
 
 
27
#include <cairo.h>
 
28
#include <X11/Xlib.h>
 
29
#include <X11/Xatom.h>
 
30
#include <X11/Xutil.h>
 
31
 
 
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"
 
54
 
 
55
#define CAIRO_DOCK_TASKBAR_CHECK_INTERVAL 200
 
56
 
 
57
CairoDockDesktopGeometry g_desktopGeometry;
 
58
extern CairoContainer *g_pPrimaryContainer;
 
59
//extern int g_iDamageEvent;
 
60
 
 
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;
 
72
 
 
73
static gboolean _cairo_dock_window_is_on_our_way (Window *Xid, Icon *icon, gpointer *data);
 
74
 
 
75
  ///////////////////////
 
76
 // X listener : core //
 
77
///////////////////////
 
78
 
 
79
static inline void _cairo_dock_retrieve_current_desktop_and_viewport (void)
 
80
{
 
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];
 
85
}
 
86
 
 
87
static gboolean _on_change_current_desktop_viewport (void)
 
88
{
 
89
        _cairo_dock_retrieve_current_desktop_and_viewport ();
 
90
        
 
91
        // on propage la notification.
 
92
        cairo_dock_notify (CAIRO_DOCK_DESKTOP_CHANGED);
 
93
        
 
94
        // on gere le cas delicat de X qui nous fait sortir du dock plus tard.
 
95
        return FALSE;
 
96
}
 
97
 
 
98
static void _on_change_nb_desktops (void)
 
99
{
 
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.
 
102
        
 
103
        cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
 
104
}
 
105
 
 
106
static void _on_change_desktop_geometry (void)
 
107
{
 
108
        if (cairo_dock_update_screen_geometry ())  // modification de la resolution.
 
109
        {
 
110
                cd_message ("resolution alteree");
 
111
                
 
112
                cairo_dock_reposition_root_docks (FALSE);  // main dock compris. Se charge de Xinerama.
 
113
        }
 
114
        
 
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.
 
117
        
 
118
        cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
 
119
}
 
120
 
 
121
static void _check_mouse_outside (CairoDock *pDock, gpointer data)
 
122
{
 
123
        if (pDock->container.bIsHorizontal)
 
124
                gdk_window_get_pointer (pDock->container.pWidget->window, &pDock->container.iMouseX, &pDock->container.iMouseY, NULL);
 
125
        else
 
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 :-/
 
128
}
 
129
static gboolean _cairo_dock_unstack_Xevents (gpointer data)
 
130
{
 
131
        static XEvent event;
 
132
        static gboolean bCheckMouseIsOutside = FALSE;
 
133
        
 
134
        if (!g_pPrimaryContainer)  // peut arriver en cours de chargement d'un theme.
 
135
                return TRUE;
 
136
        
 
137
        long event_mask = 0xFFFFFFFF;  // on les recupere tous, ca vide la pile au fur et a mesure plutot que tout a la fin.
 
138
        Window Xid;
 
139
        Window root = DefaultRootWindow (s_XDisplay);
 
140
        Icon *icon;
 
141
        if (bCheckMouseIsOutside)
 
142
        {
 
143
                //g_print ("bCheckMouseIsOutside\n");
 
144
                bCheckMouseIsOutside = FALSE;
 
145
                cairo_dock_foreach_root_docks ((GFunc)_check_mouse_outside, NULL);
 
146
        }
 
147
        
 
148
        while (XCheckMaskEvent (s_XDisplay, event_mask, &event))
 
149
        {
 
150
                icon = NULL;
 
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);
 
155
                if (Xid == root)
 
156
                {
 
157
                        if (event.type == PropertyNotify)  // PropertyNotify sur root
 
158
                        {
 
159
                                if (event.xproperty.atom == s_aNetClientList)
 
160
                                {
 
161
                                        cairo_dock_notify (CAIRO_DOCK_WINDOW_CONFIGURED, Xid, NULL);
 
162
                                }
 
163
                                else if (event.xproperty.atom == s_aNetActiveWindow)
 
164
                                {
 
165
                                        Window XActiveWindow = cairo_dock_get_active_xwindow ();
 
166
                                        cairo_dock_notify (CAIRO_DOCK_WINDOW_ACTIVATED, &XActiveWindow);
 
167
                                }
 
168
                                else if (event.xproperty.atom == s_aNetCurrentDesktop || event.xproperty.atom == s_aNetDesktopViewport)
 
169
                                {
 
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.
 
172
                                }
 
173
                                else if (event.xproperty.atom == s_aNetNbDesktops)
 
174
                                {
 
175
                                        _on_change_nb_desktops ();  // -> CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED
 
176
                                }
 
177
                                else if (event.xproperty.atom == s_aNetDesktopGeometry)
 
178
                                {
 
179
                                        _on_change_desktop_geometry ();  // -> CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED
 
180
                                }
 
181
                                else if (event.xproperty.atom == s_aRootMapID)
 
182
                                {
 
183
                                        cd_debug ("change wallpaper");
 
184
                                        cairo_dock_reload_desktop_background ();
 
185
                                        cairo_dock_notify (CAIRO_DOCK_SCREEN_GEOMETRY_ALTERED);
 
186
                                }
 
187
                                else if (event.xproperty.atom == s_aNetShowingDesktop)
 
188
                                {
 
189
                                        cairo_dock_notify (CAIRO_DOCK_DESKTOP_VISIBILITY_CHANGED);
 
190
                                }
 
191
                                else if (event.xproperty.atom == s_aXKlavierState)
 
192
                                {
 
193
                                        cairo_dock_notify (CAIRO_DOCK_KBD_STATE_CHANGED, NULL);
 
194
                                }
 
195
                        }  // fin de PropertyNotify sur root.
 
196
                }
 
197
                else  // evenement sur une fenetre.
 
198
                {
 
199
                        if (event.type == PropertyNotify)  // PropertyNotify sur une fenetre
 
200
                        {
 
201
                                if (event.xproperty.atom == s_aXKlavierState)
 
202
                                {
 
203
                                        cairo_dock_notify (CAIRO_DOCK_KBD_STATE_CHANGED, &Xid);
 
204
                                }
 
205
                                else
 
206
                                {
 
207
                                        cairo_dock_notify (CAIRO_DOCK_WINDOW_PROPERTY_CHANGED, Xid, event.xproperty.atom, event.xproperty.state);
 
208
                                }
 
209
                        }
 
210
                        else if (event.type == ConfigureNotify)  // ConfigureNotify sur une fenetre.
 
211
                        {
 
212
                                cairo_dock_notify (CAIRO_DOCK_WINDOW_CONFIGURED, Xid, &event.xconfigure);
 
213
                        }
 
214
                        /*else if (event.type == g_iDamageEvent + XDamageNotify)
 
215
                        {
 
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);
 
224
                        }
 
225
                        else
 
226
                                cd_debug ("  type : %d (%d); window : %d\n", event.type, XDamageNotify, Xid);*/
 
227
                }  // fin d'evenement sur une fenetre.
 
228
        }
 
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
 
232
        
 
233
        return TRUE;
 
234
}
 
235
 
 
236
static void cairo_dock_initialize_X_manager (Display *pDisplay)
 
237
{
 
238
        s_XDisplay = pDisplay;
 
239
 
 
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);
 
249
}
 
250
 
 
251
void cairo_dock_start_X_manager (void)
 
252
{
 
253
        g_return_if_fail (s_iSidPollXEvents == 0);
 
254
        
 
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);
 
260
        
 
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 ();
 
265
        
 
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*/);
 
269
        
 
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 ! :-/
 
272
}
 
273
 
 
274
void cairo_dock_stop_X_manager (void)  // le met seulement en pause.
 
275
{
 
276
        g_return_if_fail (s_iSidPollXEvents != 0);
 
277
        
 
278
        //\__________________ On arrete l'ecoute.
 
279
        g_source_remove (s_iSidPollXEvents);
 
280
        s_iSidPollXEvents = 0;
 
281
}
 
282
 
 
283
  /////////////////////////
 
284
 // X listener : access //
 
285
/////////////////////////
 
286
 
 
287
void cairo_dock_get_current_desktop_and_viewport (int *iCurrentDesktop, int *iCurrentViewportX, int *iCurrentViewportY)
 
288
{
 
289
        *iCurrentDesktop = g_desktopGeometry.iCurrentDesktop;
 
290
        *iCurrentViewportX = g_desktopGeometry.iCurrentViewportX;
 
291
        *iCurrentViewportY = g_desktopGeometry.iCurrentViewportY;
 
292
}