~muktupavels/compiz/gnome

2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
1
/*
2
 * Copyright © 2011 Canonical Ltd.
3
 *
4
 * Permission to use, copy, modify, distribute, and sell this software
5
 * and its documentation for any purpose is hereby granted without
6
 * fee, provided that the above copyright notice appear in all copies
7
 * and that both that copyright notice and this permission notice
8
 * appear in supporting documentation, and that the name of
9
 * Canonical Ltd. not be used in advertising or publicity pertaining to
10
 * distribution of the software without specific, written prior permission.
11
 * Canonical Ltd. makes no representations about the suitability of this
12
 * software for any purpose. It is provided "as is" without express or
13
 * implied warranty.
14
 *
15
 * CANONICAL, LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
 * NO EVENT SHALL CANONICAL, LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 *
23
 * Authored by: Sam Spilsbury <sam.spilsbury@canonical.com>
24
 */
25
26
#include "privatestackdebugger.h"
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
27
#include "privatescreen.h"
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
28
#include "privatewindow.h"
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
29
#include <poll.h>
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
30
31
namespace
32
{
33
    StackDebugger * gStackDebugger = NULL;
34
}
35
36
StackDebugger *
37
StackDebugger::Default ()
38
{
39
    return gStackDebugger;
40
}
41
42
void
43
StackDebugger::SetDefault (StackDebugger *dbg)
44
{
45
    if (gStackDebugger)
46
	delete gStackDebugger;
47
48
    gStackDebugger = dbg;
49
}
50
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
51
StackDebugger::StackDebugger (Display *dpy, Window root, FetchXEventInterface *fetchXEvent) :
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
52
    mServerNChildren (0),
53
    mServerChildren (NULL),
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
54
    mWindowsChanged (false),
55
    mServerWindowsChanged (false),
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
56
    mRoot (root),
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
57
    mDpy (dpy),
3446.2.7 by MC Return
Also initialize the member variable bool mTimeoutRequired in the Stackdebugger::Stackdebugger (...) constructor
58
    mFetchXEvent (fetchXEvent),
59
    mTimeoutRequired (false)
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
60
{
61
}
62
63
StackDebugger::~StackDebugger ()
64
{
65
    if (mServerChildren)
66
    {
67
	XFree (mServerChildren);
68
	mServerChildren = NULL;
69
	mServerNChildren = 0;
70
    }
71
}
72
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
73
bool
74
StackDebugger::timedOut ()
75
{
76
    return mTimeoutRequired;
77
}
78
79
void
80
StackDebugger::removeServerWindow (Window id)
81
{
82
    /* Find the toplevel window in the list and remove it */
83
    for (CompWindowList::iterator it = mLastServerWindows.begin ();
84
	 it != mLastServerWindows.end ();
3294.4.142 by MC Return
Hopefully fixed indentation
85
	 ++it)
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
86
    {
87
	if ((*it)->id () == id)
88
	{
89
	    mLastServerWindows.erase (it);
90
	    break;
91
	}
92
    }
93
}
94
95
void
96
StackDebugger::overrideRedirectRestack (Window toplevel, Window sibling)
97
{
98
    CompWindow *tl = screen->findWindow (toplevel);
99
100
    removeServerWindow (toplevel);
101
102
    /* Find the sibling of this window and insert above it or at
103
     * the bottom if the sibling is 0 */
104
105
    if (sibling)
106
    {
107
	for (CompWindowList::iterator it = mLastServerWindows.begin ();
108
	     it != mLastServerWindows.end ();
3294.4.142 by MC Return
Hopefully fixed indentation
109
	     ++it)
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
110
	{
111
	    if (sibling == (*it)->id () ||
112
		sibling == (*it)->frame ())
113
	    {
114
		mLastServerWindows.insert (++it, tl);
115
		break;
116
	    }
117
	}
118
    }
119
    else
120
	mLastServerWindows.push_front (tl);
121
}
122
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
123
bool
124
StackDebugger::getNextEvent (XEvent &ev)
125
{
126
    if (mEvents.empty ())
127
	return false;
128
129
    ev = mEvents.front ();
130
131
    mEvents.pop_front ();
132
133
    return true;
134
}
135
136
void
2800.2.17 by Sam Spilsbury
Merge in further stacking fixes
137
StackDebugger::loadStack (CompWindowList &serverWindows, bool wait)
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
138
{
139
    Window rootRet, parentRet;
140
141
    if (mServerChildren)
142
	XFree (mServerChildren);
143
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
144
    XSync (mDpy, FALSE);
145
    XGrabServer (mDpy);
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
146
    XQueryTree (mDpy, mRoot, &rootRet, &parentRet,
147
		&mServerChildren, &mServerNChildren);
148
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
149
    unsigned int n = XEventsQueued (mDpy, QueuedAfterFlush);
150
    mEvents.clear ();
151
    mEvents.resize (n);
3233.1.4 by Sam Spilsbury
Use list
152
    std::list <XEvent>::iterator it = mEvents.begin ();
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
153
154
    while (it != mEvents.end ())
155
    {
156
	mFetchXEvent->getNextXEvent ((*it));
3294.4.142 by MC Return
Hopefully fixed indentation
157
	++it;
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
158
    }
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
159
160
    XSync (mDpy, FALSE);
161
162
    /* It is possible that X might not be keeping up with us, so
163
     * we should give it about 300 ms in case the stacks are out of sync
164
     * in order to deliver any more events that might be pending */
165
166
    mTimeoutRequired = false;
167
    mLastServerWindows = serverWindows;
168
2800.2.17 by Sam Spilsbury
Merge in further stacking fixes
169
    if (mServerNChildren != serverWindows.size () && wait)
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
170
    {
171
	struct pollfd pfd;
172
173
	pfd.events = POLLIN;
174
	pfd.revents = 0;
175
	pfd.fd = ConnectionNumber (mDpy);
176
177
	poll (&pfd, 1, 300);
178
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
179
	XEvent e;
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
180
3233.1.2 by smspillaz
Fetch the events directly from the Xlib queue if we don't need to
181
	while (mFetchXEvent->getNextXEvent (e))
182
	    mEvents.push_back (e);
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
183
184
	mTimeoutRequired = true;
185
    }
186
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
187
    mDestroyedFrames.clear ();
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
188
189
    XUngrabServer (mDpy);
190
    XSync (mDpy, FALSE);
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
191
}
192
193
void
194
StackDebugger::addDestroyedFrame (Window f)
195
{
196
    mDestroyedFrames.push_back (f);
197
}
198
2800.2.9 by Sam Spilsbury
Immediately remove destroyed windows from the stacks last sent to the server
199
void
200
StackDebugger::removeDestroyedFrame (Window f)
201
{
202
    mDestroyedFrames.remove (f);
203
}
204
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
205
bool
206
StackDebugger::cmpStack (CompWindowList &windows,
207
			 CompWindowList &serverWindows,
208
			 bool           verbose)
209
{
210
    std::vector <Window>             serverSideWindows;
211
    CompWindowList::reverse_iterator lrrit = windows.rbegin ();
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
212
    CompWindowList::reverse_iterator lsrit = mLastServerWindows.rbegin ();
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
213
    unsigned int                     i = 0;
214
    bool                             err = false;
215
216
    for (unsigned int n = 0; n < mServerNChildren; n++)
217
    {
218
	if (std::find (mDestroyedFrames.begin (),
219
		       mDestroyedFrames.end (), mServerChildren[n])
220
		== mDestroyedFrames.end ())
221
	    serverSideWindows.push_back (mServerChildren[n]);
222
    }
223
224
    if (verbose)
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
225
	compLogMessage ("core", CompLogLevelDebug, "sent       | recv       | server     |");
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
226
227
    for (;(lrrit != windows.rend () ||
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
228
	   lsrit != mLastServerWindows.rend () ||
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
229
	   i != serverSideWindows.size ());)
230
    {
231
	Window lrXid = 0;
232
	Window lsXid = 0;
233
	Window sXid = 0;
234
235
	if (lrrit != windows.rend ())
2800.2.11 by Sam Spilsbury
Fix a typo that was causing decoration frames to be added as normal windows (causing
236
	    lrXid = (*lrrit)->priv->frame ? (*lrrit)->priv->frame : (*lrrit)->id ();
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
237
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
238
	if (lsrit != mLastServerWindows.rend ())
2800.2.11 by Sam Spilsbury
Fix a typo that was causing decoration frames to be added as normal windows (causing
239
	    lsXid = (*lsrit)->priv->frame ? (*lsrit)->priv->frame : (*lsrit)->id ();
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
240
241
	if (i != serverSideWindows.size ())
242
	    sXid = serverSideWindows[serverSideWindows.size () - (i + 1)];
243
244
	if (verbose)
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
245
	    compLogMessage ("core", CompLogLevelDebug, "id 0x%x id 0x%x id 0x%x %s",
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
246
		     (unsigned int) lsXid, (unsigned int) lrXid,
2800.2.17 by Sam Spilsbury
Merge in further stacking fixes
247
		     (unsigned int) sXid, (lrXid != sXid) ? "  /!\\ " : "");
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
248
2800.2.17 by Sam Spilsbury
Merge in further stacking fixes
249
	if (lrXid != sXid)
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
250
	    err = true;
251
252
	if (lrrit != windows.rend ())
3294.4.142 by MC Return
Hopefully fixed indentation
253
	    ++lrrit;
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
254
2800.2.16 by Sam Spilsbury
Merge in more stacking fixes
255
	if (lsrit != mLastServerWindows.rend())
3294.4.142 by MC Return
Hopefully fixed indentation
256
	    ++lsrit;
2800.2.2 by Sam Spilsbury
Merge in the fixes for the various out of sync bugs and an object to debug stacking sync problems
257
258
	if (i != serverSideWindows.size ())
259
	    i++;
260
    }
261
262
    return err;
263
}
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
264
265
/* Checks the sanity of the list of windows last sent to the server.
266
 *
267
 * There are a few stacking "layers" here. From top to bottom:
268
 * - 1) Docks stacked above toplevel windows which are stacked
269
 *      above fullscreen windows
270
 * - 2) "Keep above" toplevel windows above fullscreen windows
271
 *      where a toplevel is in focus
272
 * - 3) Toplevel windows in focus above fullscreen windows
273
 * - 4) Fullscreen windows
274
 * - 5) Dock windows
275
 * - 6) Keep above windows
276
 * - 7) Toplevel windows
277
 * - 8) Docks which are marked "Keep Below"
278
 * - 9) "Keep Below" windows
279
 * - 10) Desktop windows
280
 *
281
 * There are also a few rules which apply here:
282
 * - 1) Dock windows should always be above normal windows
283
 *      except if marked keep below on any layer.
284
 * - 2) Dock windows should ONLY be on one layer at a time,
285
 *      eg if they are on layer 1 then there cannot
286
 *      also be dock windows on layer 5 (except in the
287
 *      case of below dock windows on layer 8)
288
 * - 3) Fullscreen windows must always be above docks when in
289
 *      focus, no matter if there is another window with "Keep Above"
290
 * - 4) Focused windows take priority over fullscreen windows and
291
 *      docks must always be above them (see rule 1)
292
 *
293
 * As we pass through each layer, this function flags each one from
294
 * lowest being the most bits set to highest being the least bits
295
 * set. If a window violates this it raises a warning */
296
297
#define DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN 0xffffffff >> 1
298
#define KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN 0xffffffff >> 2
299
#define TOPLEVELS_ABOVE_FULLSCREEN 0xffffffff >> 3
300
#define FULLSCREEN 0xffffffff >> 4
301
#define DOCKS 0xffffffff >> 5
302
#define KEEP_ABOVE 0xffffffff >> 6
303
#define TOPLEVELS 0xffffffff >> 7
304
#define DOCKS_BELOW 0xffffffff >> 8
305
#define KEEP_BELOW 0xffffffff >> 9
306
#define DESKTOP 0xffffffff >> 10
307
308
namespace
309
{
310
    bool setCurrentLayer (Window requestingWindow, int layer, int &current)
311
    {
312
	bool ret = false;
313
	/* Only allow steps down */
314
	if ((current & layer) != layer)
315
	{
316
	    ret = true;
317
	    compLogMessage ("stackdebugger", CompLogLevelWarn, "0x%x requested invalid layer 0x%x",
318
			    requestingWindow, layer, current);
319
	}
320
321
	current = layer;
322
323
	return ret;
324
    }
325
}
326
327
bool
328
StackDebugger::checkSanity (CompWindowList &serverWindows, bool verbose)
329
{
330
    int current = 0xffffffff;
331
    int oldCurrent = current;
332
    bool err = false;
333
334
    if (verbose)
335
	compLogMessage ("stackdebugger", CompLogLevelDebug, "processing new stack --------");
336
337
    /* go backwards down the stack */
338
    for (CompWindowList::reverse_iterator rit = serverWindows.rbegin ();
3294.4.165 by MC Return
Fixed intendation
339
	 rit != serverWindows.rend (); ++rit)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
340
    {
341
	CompWindow *w = (*rit);
342
343
	/* Override redirect windows set all kinds
344
	 * of crazy stuff and are required to stack
345
	 * themselves so skip those */
346
	if (w->overrideRedirect ())
347
	    continue;
348
349
	/* ignore non-override redirect unmanaged windows */
350
	if (!w->managed ())
351
	    continue;
352
2838.4.1 by Sam Spilsbury
Since we are the only one to make ConfigureWindow requests on toplevels which the
353
	/* ignore any windows that just got created */
354
	if (!w->mapNum ())
355
	    continue;
356
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
357
	/* determine the current layer */
358
	if (w->type () == CompWindowTypeDockMask)
359
	{
360
	    if ((current & DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN) ==
361
			   DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN)
362
	    {
363
		bool fullscreenWindow = false;
364
365
		/* search down the stack to check if there is a fullscreen
366
		 * window, otherwise we are not on the fullscreen layer */
2856.3.1 by Sam Spilsbury
When a window loses focus and is no longer capable of gaining focus we should
367
		for (CompWindow *rw = w->prev; rw; rw = rw->prev)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
368
		{
369
		    if (rw->type () & CompWindowTypeFullscreenMask)
370
		    {
371
			fullscreenWindow = true;
372
			break;
373
		    }
374
		}
375
376
		/* if there is no fullscreen window, change the layer */
377
		if (!fullscreenWindow)
378
		    err |= setCurrentLayer (w->id (), DOCKS, current);
379
		else
380
		    err |= setCurrentLayer (w->id (), DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN, current);
381
	    }
382
	    else if (w->state () & CompWindowStateBelowMask)
383
		err |= setCurrentLayer (w->id (), DOCKS_BELOW, current);
384
	    else
385
		err |= setCurrentLayer (w->id (), DOCKS, current);
386
	}
387
	else if (w->type () == CompWindowTypeFullscreenMask)
388
	{
389
	    err |= setCurrentLayer (w->id (), FULLSCREEN, current);
390
	}
391
	else if (w->type () == CompWindowTypeDesktopMask)
392
	{
393
	    err |= setCurrentLayer (w->id (), DESKTOP, current);
394
	}
395
	/* everything else that is not a fullscreen window or a desktop */
396
	else
397
	{
398
	    if (w->state () & CompWindowStateAboveMask)
399
	    {
400
		if ((current & KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN) ==
401
			       KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN)
402
		{
403
		    bool fullscreenWindow = false;
404
405
		    /* search down the stack to check if there is a fullscreen
406
		     * window, otherwise we are not on the fullscreen layer */
2856.3.1 by Sam Spilsbury
When a window loses focus and is no longer capable of gaining focus we should
407
		    for (CompWindow *rw = w->prev; rw; rw = rw->prev)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
408
		    {
2856.3.1 by Sam Spilsbury
When a window loses focus and is no longer capable of gaining focus we should
409
			if (rw->type () & CompWindowTypeFullscreenMask)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
410
			{
411
			    fullscreenWindow = true;
412
			    break;
413
			}
414
		    }
415
416
		    if (!fullscreenWindow)
417
			err |= setCurrentLayer (w->id (), KEEP_ABOVE, current);
418
		    else
419
			err |= setCurrentLayer (w->id (), KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN, current);
420
		}
421
		else
422
		    err |= setCurrentLayer (w->id (), KEEP_ABOVE, current);
423
	    }
424
	    else if (w->state () & CompWindowStateBelowMask)
425
		err |= setCurrentLayer (w->id (), KEEP_BELOW, current);
426
	    else
427
	    {
428
		if ((current & TOPLEVELS_ABOVE_FULLSCREEN) ==
429
			       TOPLEVELS_ABOVE_FULLSCREEN)
430
		{
431
		    bool fullscreenWindow = false;
432
433
		    /* search down the stack to check if there is a fullscreen
434
		     * window, otherwise we are not on the fullscreen layer */
2856.3.1 by Sam Spilsbury
When a window loses focus and is no longer capable of gaining focus we should
435
		    for (CompWindow *rw = w->prev; rw; rw = rw->prev)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
436
		    {
2856.3.1 by Sam Spilsbury
When a window loses focus and is no longer capable of gaining focus we should
437
			if (rw->type () & CompWindowTypeFullscreenMask)
2800.2.13 by Sam Spilsbury
Merge in StackDebugger stack sanity checker
438
			{
439
			    fullscreenWindow = true;
440
			    break;
441
			}
442
		    }
443
444
		    if (!fullscreenWindow)
445
			err |= setCurrentLayer (w->id (), TOPLEVELS, current);
446
		    else
447
			err |= setCurrentLayer (w->id (), TOPLEVELS_ABOVE_FULLSCREEN, current);
448
		}
449
		else
450
		    err |= setCurrentLayer (w->id (), TOPLEVELS, current);
451
	    }
452
	}
453
454
	if ((current & DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN) ==
455
		       DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN)
456
	{
457
	    if (verbose && current != oldCurrent)
458
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer DOCKS_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN");
459
	}
460
	else if ((current & KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN) ==
461
			    KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN)
462
	{
463
	    if (verbose && current != oldCurrent)
464
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer KEEP_ABOVE_TOPLEVELS_ABOVE_FULLSCREEN");
465
	}
466
	else if ((current & TOPLEVELS_ABOVE_FULLSCREEN) == TOPLEVELS_ABOVE_FULLSCREEN)
467
	{
468
	    if (verbose && current != oldCurrent)
469
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer TOPLEVELS_ABOVE_FULLSCREEN");
470
	}
471
	else if ((current & FULLSCREEN) == FULLSCREEN)
472
	{
473
	    if (verbose && current != oldCurrent)
474
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer FULLSCREEN");
475
	}
476
	else if ((current & DOCKS) == DOCKS)
477
	{
478
	    if (verbose && current != oldCurrent)
479
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer DOCKS");
480
	}
481
	else if ((current & KEEP_ABOVE) == KEEP_ABOVE)
482
	{
483
	    if (verbose && current != oldCurrent)
484
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer KEEP_ABOVE");
485
	}
486
	else if ((current & TOPLEVELS) == TOPLEVELS)
487
	{
488
	    if (verbose && current != oldCurrent)
489
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer TOPLEVELS");
490
	}
491
	else if ((current & DOCKS_BELOW) == DOCKS_BELOW)
492
	{
493
	    if (verbose && current != oldCurrent)
494
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer DOCKS_BELOW");
495
	}
496
	else if ((current & KEEP_BELOW) == KEEP_BELOW)
497
	{
498
	    if (verbose && current != oldCurrent)
499
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer KEEP_BELOW");
500
	}
501
	else if ((current & DESKTOP) == DESKTOP)
502
	{
503
	    if (verbose && current != oldCurrent)
504
		compLogMessage ("stackdebugger", CompLogLevelDebug, "on layer DESKTOP");
505
	}
506
507
	oldCurrent = current;
508
    }
509
510
    return err;
511
}