~alan-griffiths/compiz-core/Bug-931283

« back to all changes in this revision

Viewing changes to src/screen.c

  • Committer: David Reveman
  • Date: 2006-02-09 06:03:09 UTC
  • Revision ID: git-v1:9959c2b13ded64a5e66359a8097250dc9d87fc1c
Initial revision

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2005 Novell, Inc.
 
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
 * Novell, Inc. not be used in advertising or publicity pertaining to
 
10
 * distribution of the software without specific, written prior permission.
 
11
 * Novell, Inc. 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
 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 
17
 * NO EVENT SHALL NOVELL, INC. 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
 * Author: David Reveman <davidr@novell.com>
 
24
 */
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#  include "../config.h"
 
28
#endif
 
29
 
 
30
#include <stdio.h>
 
31
#include <stdlib.h>
 
32
#include <math.h>
 
33
#include <dlfcn.h>
 
34
#include <string.h>
 
35
#include <sys/types.h>
 
36
#include <unistd.h>
 
37
 
 
38
#include <X11/Xlib.h>
 
39
#include <X11/Xatom.h>
 
40
#include <X11/extensions/Xrandr.h>
 
41
#include <X11/cursorfont.h>
 
42
 
 
43
#include <compiz.h>
 
44
 
 
45
#define DETECT_REFRESH_RATE_DEFAULT TRUE
 
46
 
 
47
#define SCREEN_SIZE_DEFAULT 4
 
48
#define SCREEN_SIZE_MIN     4
 
49
#define SCREEN_SIZE_MAX     32
 
50
 
 
51
#define CLOSE_WINDOW_KEY_DEFAULT       "F4"
 
52
#define CLOSE_WINDOW_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
 
53
 
 
54
#define MAIN_MENU_KEY_DEFAULT       "F1"
 
55
#define MAIN_MENU_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
 
56
 
 
57
#define RUN_DIALOG_KEY_DEFAULT       "F2"
 
58
#define RUN_DIALOG_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
 
59
 
 
60
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
 
61
 
 
62
static int
 
63
reallocScreenPrivate (int  size,
 
64
                      void *closure)
 
65
{
 
66
    CompDisplay *d = (CompDisplay *) closure;
 
67
    CompScreen  *s;
 
68
    void        *privates;
 
69
 
 
70
    for (s = d->screens; s; s = s->next)
 
71
    {
 
72
        privates = realloc (s->privates, size * sizeof (CompPrivate));
 
73
        if (!privates)
 
74
            return FALSE;
 
75
 
 
76
        s->privates = (CompPrivate *) privates;
 
77
    }
 
78
 
 
79
    return TRUE;
 
80
}
 
81
 
 
82
int
 
83
allocateScreenPrivateIndex (CompDisplay *display)
 
84
{
 
85
    return allocatePrivateIndex (&display->screenPrivateLen,
 
86
                                 &display->screenPrivateIndices,
 
87
                                 reallocScreenPrivate,
 
88
                                 (void *) display);
 
89
}
 
90
 
 
91
void
 
92
freeScreenPrivateIndex (CompDisplay *display,
 
93
                        int         index)
 
94
{
 
95
    freePrivateIndex (display->screenPrivateLen,
 
96
                      display->screenPrivateIndices,
 
97
                      index);
 
98
}
 
99
 
 
100
static void
 
101
setVirtualScreenSize (CompScreen *screen,
 
102
                      int        size)
 
103
{
 
104
    unsigned long data[2];
 
105
 
 
106
    data[0] = screen->width * size;
 
107
    data[1] = screen->height;
 
108
 
 
109
    XChangeProperty (screen->display->display, screen->root,
 
110
                     screen->display->desktopGeometryAtom,
 
111
                     XA_CARDINAL, 32, PropModeReplace,
 
112
                     (unsigned char *) data, 2);
 
113
 
 
114
    screen->size = size;
 
115
}
 
116
 
 
117
CompOption *
 
118
compGetScreenOptions (CompScreen *screen,
 
119
                      int        *count)
 
120
{
 
121
    *count = NUM_OPTIONS (screen);
 
122
    return screen->opt;
 
123
}
 
124
 
 
125
static Bool
 
126
setScreenOption (CompScreen      *screen,
 
127
                 char            *name,
 
128
                 CompOptionValue *value)
 
129
{
 
130
    CompOption *o;
 
131
    int        index;
 
132
 
 
133
    o = compFindOption (screen->opt, NUM_OPTIONS (screen), name, &index);
 
134
    if (!o)
 
135
        return FALSE;
 
136
 
 
137
    switch (index) {
 
138
    case COMP_SCREEN_OPTION_DETECT_REFRESH_RATE:
 
139
        if (compSetBoolOption (o, value))
 
140
            return TRUE;
 
141
        break;
 
142
    case COMP_SCREEN_OPTION_REFRESH_RATE:
 
143
        if (screen->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b)
 
144
            return FALSE;
 
145
 
 
146
        if (compSetIntOption (o, value))
 
147
        {
 
148
            screen->redrawTime = 1000 / o->value.i;
 
149
            screen->optimalRedrawTime = screen->redrawTime;
 
150
            return TRUE;
 
151
        }
 
152
        break;
 
153
    case COMP_SCREEN_OPTION_SIZE:
 
154
        if (compSetIntOption (o, value))
 
155
        {
 
156
            if (o->value.i * screen->width > MAXSHORT)
 
157
                return FALSE;
 
158
 
 
159
            setVirtualScreenSize (screen, o->value.i);
 
160
            return TRUE;
 
161
        }
 
162
        break;
 
163
    case COMP_SCREEN_OPTION_COMMAND0:
 
164
    case COMP_SCREEN_OPTION_COMMAND1:
 
165
        if (compSetStringOption (o, value))
 
166
            return TRUE;
 
167
        break;
 
168
    case COMP_SCREEN_OPTION_CLOSE_WINDOW:
 
169
    case COMP_SCREEN_OPTION_MAIN_MENU:
 
170
    case COMP_SCREEN_OPTION_RUN_DIALOG:
 
171
    case COMP_SCREEN_OPTION_RUN_COMMAND0:
 
172
    case COMP_SCREEN_OPTION_RUN_COMMAND1:
 
173
        if (addScreenBinding (screen, &value->bind))
 
174
        {
 
175
            removeScreenBinding (screen, &o->value.bind);
 
176
 
 
177
            if (compSetBindingOption (o, value))
 
178
                return TRUE;
 
179
        }
 
180
    default:
 
181
        break;
 
182
    }
 
183
 
 
184
    return FALSE;
 
185
}
 
186
 
 
187
static Bool
 
188
setScreenOptionForPlugin (CompScreen      *screen,
 
189
                          char            *plugin,
 
190
                          char            *name,
 
191
                          CompOptionValue *value)
 
192
{
 
193
    CompPlugin *p;
 
194
 
 
195
    p = findActivePlugin (plugin);
 
196
    if (p && p->vTable->setScreenOption)
 
197
        return (*p->vTable->setScreenOption) (screen, name, value);
 
198
 
 
199
    return FALSE;
 
200
}
 
201
 
 
202
static void
 
203
compScreenInitOptions (CompScreen *screen)
 
204
{
 
205
    CompOption *o;
 
206
 
 
207
    o = &screen->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE];
 
208
    o->name       = "detect_refresh_rate";
 
209
    o->shortDesc  = "Detect Refresh Rate";
 
210
    o->longDesc   = "Automatic detection of refresh rate";
 
211
    o->type       = CompOptionTypeBool;
 
212
    o->value.b    = DETECT_REFRESH_RATE_DEFAULT;
 
213
 
 
214
    o = &screen->opt[COMP_SCREEN_OPTION_REFRESH_RATE];
 
215
    o->name       = "refresh_rate";
 
216
    o->shortDesc  = "Refresh Rate";
 
217
    o->longDesc   = "The rate at which the screen is redrawn (times/second)";
 
218
    o->type       = CompOptionTypeInt;
 
219
    o->value.i    = defaultRefreshRate;
 
220
    o->rest.i.min = 1;
 
221
    o->rest.i.max = 200;
 
222
 
 
223
    o = &screen->opt[COMP_SCREEN_OPTION_SIZE];
 
224
    o->name       = "size";
 
225
    o->shortDesc  = "Virtual Size";
 
226
    o->longDesc   = "Screen size multiplier for virtual size";
 
227
    o->type       = CompOptionTypeInt;
 
228
    o->value.i    = SCREEN_SIZE_DEFAULT;
 
229
    o->rest.i.min = SCREEN_SIZE_MIN;
 
230
    o->rest.i.max = SCREEN_SIZE_MAX;
 
231
 
 
232
    o = &screen->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW];
 
233
    o->name                       = "close_window";
 
234
    o->shortDesc                  = "Close Window";
 
235
    o->longDesc                   = "Close active window";
 
236
    o->type                       = CompOptionTypeBinding;
 
237
    o->value.bind.type            = CompBindingTypeKey;
 
238
    o->value.bind.u.key.modifiers = CLOSE_WINDOW_MODIFIERS_DEFAULT;
 
239
    o->value.bind.u.key.keycode   =
 
240
        XKeysymToKeycode (screen->display->display,
 
241
                          XStringToKeysym (CLOSE_WINDOW_KEY_DEFAULT));
 
242
 
 
243
    o = &screen->opt[COMP_SCREEN_OPTION_MAIN_MENU];
 
244
    o->name                       = "main_menu";
 
245
    o->shortDesc                  = "Main Menu";
 
246
    o->longDesc                   = "Open main menu";
 
247
    o->type                       = CompOptionTypeBinding;
 
248
    o->value.bind.type            = CompBindingTypeKey;
 
249
    o->value.bind.u.key.modifiers = MAIN_MENU_MODIFIERS_DEFAULT;
 
250
    o->value.bind.u.key.keycode   =
 
251
        XKeysymToKeycode (screen->display->display,
 
252
                          XStringToKeysym (MAIN_MENU_KEY_DEFAULT));
 
253
 
 
254
    o = &screen->opt[COMP_SCREEN_OPTION_RUN_DIALOG];
 
255
    o->name                       = "run";
 
256
    o->shortDesc                  = "Run";
 
257
    o->longDesc                   = "Run application";
 
258
    o->type                       = CompOptionTypeBinding;
 
259
    o->value.bind.type            = CompBindingTypeKey;
 
260
    o->value.bind.u.key.modifiers = RUN_DIALOG_MODIFIERS_DEFAULT;
 
261
    o->value.bind.u.key.keycode   =
 
262
        XKeysymToKeycode (screen->display->display,
 
263
                          XStringToKeysym (RUN_DIALOG_KEY_DEFAULT));
 
264
 
 
265
    o = &screen->opt[COMP_SCREEN_OPTION_COMMAND0];
 
266
    o->name                       = "command0";
 
267
    o->shortDesc                  = "Command line";
 
268
    o->longDesc                   = "Command line to be executed in shell";
 
269
    o->type                       = CompOptionTypeString;
 
270
    o->value.s                    = strdup ("");
 
271
    o->rest.s.string              = NULL;
 
272
    o->rest.s.nString             = 0;
 
273
 
 
274
    o = &screen->opt[COMP_SCREEN_OPTION_RUN_COMMAND0];
 
275
    o->name                       = "run_command0";
 
276
    o->shortDesc                  = "Run command";
 
277
    o->longDesc                   = "Run shell command";
 
278
    o->type                       = CompOptionTypeBinding;
 
279
    o->value.bind.type            = CompBindingTypeKey;
 
280
    o->value.bind.u.key.modifiers = 0;
 
281
    o->value.bind.u.key.keycode   = 0;
 
282
 
 
283
    o = &screen->opt[COMP_SCREEN_OPTION_COMMAND1];
 
284
    o->name                       = "command1";
 
285
    o->shortDesc                  = "Command line";
 
286
    o->longDesc                   = "Command line to be executed in shell";
 
287
    o->type                       = CompOptionTypeString;
 
288
    o->value.s                    = strdup ("");
 
289
    o->rest.s.string              = NULL;
 
290
    o->rest.s.nString             = 0;
 
291
 
 
292
    o = &screen->opt[COMP_SCREEN_OPTION_RUN_COMMAND1];
 
293
    o->name                       = "run_command1";
 
294
    o->shortDesc                  = "Run command";
 
295
    o->longDesc                   = "Run shell command";
 
296
    o->type                       = CompOptionTypeBinding;
 
297
    o->value.bind.type            = CompBindingTypeKey;
 
298
    o->value.bind.u.key.modifiers = 0;
 
299
    o->value.bind.u.key.keycode   = 0;
 
300
}
 
301
 
 
302
static Bool
 
303
initPluginForScreen (CompPlugin *p,
 
304
                     CompScreen *s)
 
305
{
 
306
    if (p->vTable->initScreen)
 
307
        return (*p->vTable->initScreen) (p, s);
 
308
 
 
309
    return FALSE;
 
310
}
 
311
 
 
312
static void
 
313
finiPluginForScreen (CompPlugin *p,
 
314
                     CompScreen *s)
 
315
{
 
316
    if (p->vTable->finiScreen)
 
317
        (*p->vTable->finiScreen) (p, s);
 
318
}
 
319
 
 
320
static void
 
321
updateStartupFeedback (CompScreen *s)
 
322
{
 
323
    if (s->startupSequences)
 
324
        XDefineCursor (s->display->display, s->root, s->busyCursor);
 
325
    else
 
326
        XDefineCursor (s->display->display, s->root, s->normalCursor);
 
327
}
 
328
 
 
329
#define STARTUP_TIMEOUT_DELAY 15000
 
330
 
 
331
static Bool
 
332
startupSequenceTimeout (void *data)
 
333
{
 
334
    CompScreen          *screen = data;
 
335
    CompStartupSequence *s;
 
336
    struct timeval      now, active;
 
337
    double              elapsed;
 
338
 
 
339
    gettimeofday (&now, NULL);
 
340
 
 
341
    for (s = screen->startupSequences; s; s = s->next)
 
342
    {
 
343
        sn_startup_sequence_get_last_active_time (s->sequence,
 
344
                                                  &active.tv_sec,
 
345
                                                  &active.tv_usec);
 
346
 
 
347
        elapsed = ((((double) now.tv_sec - active.tv_sec) * 1000000.0 +
 
348
                    (now.tv_usec - active.tv_usec))) / 1000.0;
 
349
 
 
350
        if (elapsed > STARTUP_TIMEOUT_DELAY)
 
351
            sn_startup_sequence_complete (s->sequence);
 
352
    }
 
353
 
 
354
    return TRUE;
 
355
}
 
356
 
 
357
static void
 
358
addSequence (CompScreen        *screen,
 
359
             SnStartupSequence *sequence)
 
360
{
 
361
    CompStartupSequence *s;
 
362
 
 
363
    s = malloc (sizeof (CompStartupSequence));
 
364
    if (!s)
 
365
        return;
 
366
 
 
367
    sn_startup_sequence_ref (sequence);
 
368
 
 
369
    s->next     = screen->startupSequences;
 
370
    s->sequence = sequence;
 
371
 
 
372
    screen->startupSequences = s;
 
373
 
 
374
    if (!screen->startupSequenceTimeoutHandle)
 
375
        compAddTimeout (1000,
 
376
                        startupSequenceTimeout,
 
377
                        screen);
 
378
 
 
379
    updateStartupFeedback (screen);
 
380
}
 
381
 
 
382
static void
 
383
removeSequence (CompScreen        *screen,
 
384
                SnStartupSequence *sequence)
 
385
{
 
386
    CompStartupSequence *s, *p = NULL;
 
387
 
 
388
    for (s = screen->startupSequences; s; s = s->next)
 
389
    {
 
390
        if (s->sequence == sequence)
 
391
            break;
 
392
 
 
393
        p = s;
 
394
    }
 
395
 
 
396
    if (!s)
 
397
        return;
 
398
 
 
399
    sn_startup_sequence_unref (sequence);
 
400
 
 
401
    if (p)
 
402
        p->next = s->next;
 
403
    else
 
404
        screen->startupSequences = NULL;
 
405
 
 
406
    free (s);
 
407
 
 
408
    if (!screen->startupSequences && screen->startupSequenceTimeoutHandle)
 
409
    {
 
410
        compRemoveTimeout (screen->startupSequenceTimeoutHandle);
 
411
        screen->startupSequenceTimeoutHandle = 0;
 
412
    }
 
413
 
 
414
    updateStartupFeedback (screen);
 
415
}
 
416
 
 
417
static void
 
418
compScreenSnEvent (SnMonitorEvent *event,
 
419
                   void           *userData)
 
420
{
 
421
    CompScreen        *screen = userData;
 
422
    SnStartupSequence *sequence;
 
423
 
 
424
    sequence = sn_monitor_event_get_startup_sequence (event);
 
425
 
 
426
    switch (sn_monitor_event_get_type (event)) {
 
427
    case SN_MONITOR_EVENT_INITIATED:
 
428
        addSequence (screen, sequence);
 
429
        break;
 
430
    case SN_MONITOR_EVENT_COMPLETED:
 
431
        removeSequence (screen, sn_monitor_event_get_startup_sequence (event));
 
432
        break;
 
433
    case SN_MONITOR_EVENT_CHANGED:
 
434
    case SN_MONITOR_EVENT_CANCELED:
 
435
        break;
 
436
    }
 
437
}
 
438
 
 
439
static void
 
440
frustum (GLfloat left,
 
441
         GLfloat right,
 
442
         GLfloat bottom,
 
443
         GLfloat top,
 
444
         GLfloat nearval,
 
445
         GLfloat farval)
 
446
{
 
447
   GLfloat x, y, a, b, c, d;
 
448
   GLfloat m[16];
 
449
 
 
450
   x = (2.0 * nearval) / (right - left);
 
451
   y = (2.0 * nearval) / (top - bottom);
 
452
   a = (right + left) / (right - left);
 
453
   b = (top + bottom) / (top - bottom);
 
454
   c = -(farval + nearval) / ( farval - nearval);
 
455
   d = -(2.0 * farval * nearval) / (farval - nearval);
 
456
 
 
457
#define M(row,col)  m[col*4+row]
 
458
   M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
 
459
   M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
 
460
   M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
 
461
   M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
 
462
#undef M
 
463
 
 
464
   glMultMatrixf (m);
 
465
}
 
466
 
 
467
static void
 
468
perspective (GLfloat fovy,
 
469
             GLfloat aspect,
 
470
             GLfloat zNear,
 
471
             GLfloat zFar)
 
472
{
 
473
   GLfloat xmin, xmax, ymin, ymax;
 
474
 
 
475
   ymax = zNear * tan (fovy * M_PI / 360.0);
 
476
   ymin = -ymax;
 
477
   xmin = ymin * aspect;
 
478
   xmax = ymax * aspect;
 
479
 
 
480
   frustum (xmin, xmax, ymin, ymax, zNear, zFar);
 
481
}
 
482
 
 
483
static void
 
484
reshape (CompScreen *s,
 
485
         int        w,
 
486
         int        h)
 
487
{
 
488
    s->width  = w;
 
489
    s->height = h;
 
490
 
 
491
    glMatrixMode (GL_PROJECTION);
 
492
    glLoadIdentity ();
 
493
    glMatrixMode (GL_MODELVIEW);
 
494
    glLoadIdentity ();
 
495
    glDepthRange (0, 1);
 
496
    glViewport (-1, -1, 2, 2);
 
497
    glRasterPos2f (0, 0);
 
498
 
 
499
    s->rasterX = s->rasterY = 0;
 
500
 
 
501
    glViewport (0, 0, w, h);
 
502
    glMatrixMode (GL_PROJECTION);
 
503
    glLoadIdentity ();
 
504
    perspective (60.0f, 1.0f, 0.1f, 100.0f);
 
505
    glMatrixMode (GL_MODELVIEW);
 
506
 
 
507
    s->region.rects = &s->region.extents;
 
508
    s->region.numRects = 1;
 
509
    s->region.extents.x1 = 0;
 
510
    s->region.extents.y1 = 0;
 
511
    s->region.extents.x2 = w;
 
512
    s->region.extents.y2 = h;
 
513
    s->region.size = 1;
 
514
 
 
515
    updateWorkareaForScreen (s);
 
516
}
 
517
 
 
518
void
 
519
configureScreen (CompScreen      *s,
 
520
                 XConfigureEvent *ce)
 
521
{
 
522
    if (s->attrib.width  != ce->width ||
 
523
        s->attrib.height != ce->height)
 
524
    {
 
525
        s->attrib.width  = ce->width;
 
526
        s->attrib.height = ce->height;
 
527
 
 
528
        reshape (s, ce->width, ce->height);
 
529
 
 
530
        damageScreen (s);
 
531
    }
 
532
}
 
533
 
 
534
static FuncPtr
 
535
getProcAddress (CompScreen *s,
 
536
                const char *name)
 
537
{
 
538
    static void *dlhand = NULL;
 
539
    FuncPtr     funcPtr = NULL;
 
540
 
 
541
    if (s->getProcAddress)
 
542
        funcPtr = s->getProcAddress ((GLubyte *) name);
 
543
 
 
544
    if (!funcPtr)
 
545
    {
 
546
        if (!dlhand)
 
547
            dlhand = dlopen (NULL, RTLD_LAZY);
 
548
 
 
549
        if (dlhand)
 
550
        {
 
551
            dlerror ();
 
552
            funcPtr = (FuncPtr) dlsym (dlhand, name);
 
553
            if (dlerror () != NULL)
 
554
                funcPtr = NULL;
 
555
        }
 
556
    }
 
557
 
 
558
    return funcPtr;
 
559
}
 
560
 
 
561
void
 
562
updateScreenBackground (CompScreen  *screen,
 
563
                        CompTexture *texture)
 
564
{
 
565
    Display       *dpy = screen->display->display;
 
566
    Atom          pixmapAtom, actualType;
 
567
    int           actualFormat, i, status;
 
568
    unsigned int  width = 1, height = 1, depth = 0;
 
569
    unsigned long nItems;
 
570
    unsigned long bytesAfter;
 
571
    unsigned char *prop;
 
572
    Pixmap        pixmap = 0;
 
573
 
 
574
    pixmapAtom = XInternAtom (dpy, "PIXMAP", FALSE);
 
575
 
 
576
    for (i = 0; pixmap == 0 && i < 2; i++)
 
577
    {
 
578
        status = XGetWindowProperty (dpy, screen->root,
 
579
                                     screen->display->xBackgroundAtom[i],
 
580
                                     0, 4, FALSE, AnyPropertyType,
 
581
                                     &actualType, &actualFormat, &nItems,
 
582
                                     &bytesAfter, &prop);
 
583
 
 
584
        if (status == Success && nItems && prop)
 
585
        {
 
586
            if (actualType   == pixmapAtom &&
 
587
                actualFormat == 32         &&
 
588
                nItems       == 1)
 
589
            {
 
590
                Pixmap p;
 
591
 
 
592
                memcpy (&p, prop, 4);
 
593
 
 
594
                if (p)
 
595
                {
 
596
                    unsigned int ui;
 
597
                    int          i;
 
598
                    Window       w;
 
599
 
 
600
                    if (XGetGeometry (dpy, p, &w, &i, &i,
 
601
                                      &width, &height, &ui, &depth))
 
602
                    {
 
603
                        if (depth == screen->attrib.depth)
 
604
                            pixmap = p;
 
605
                    }
 
606
                }
 
607
            }
 
608
 
 
609
            XFree (prop);
 
610
        }
 
611
    }
 
612
 
 
613
    if (!testMode && pixmap)
 
614
    {
 
615
        if (pixmap == texture->pixmap)
 
616
            return;
 
617
 
 
618
        finiTexture (screen, texture);
 
619
        initTexture (screen, texture);
 
620
 
 
621
        if (!bindPixmapToTexture (screen, texture, pixmap,
 
622
                                  width, height, depth))
 
623
        {
 
624
            fprintf (stderr, "%s: Couldn't bind background pixmap 0x%x to "
 
625
                     "texture\n", programName, (int) pixmap);
 
626
        }
 
627
    }
 
628
    else
 
629
    {
 
630
        finiTexture (screen, texture);
 
631
        initTexture (screen, texture);
 
632
    }
 
633
 
 
634
    if (!texture->name)
 
635
        readImageToTexture (screen, texture, backgroundImage, &width, &height);
 
636
 
 
637
    if (texture->target == GL_TEXTURE_2D)
 
638
    {
 
639
        glBindTexture (texture->target, texture->name);
 
640
        glTexParameteri (texture->target, GL_TEXTURE_WRAP_S, GL_REPEAT);
 
641
        glTexParameteri (texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
642
        glBindTexture (texture->target, 0);
 
643
    }
 
644
}
 
645
 
 
646
void
 
647
detectRefreshRateOfScreen (CompScreen *s)
 
648
{
 
649
    if (s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b)
 
650
    {
 
651
        XRRScreenConfiguration *config;
 
652
        char                   *name;
 
653
        CompOptionValue        value;
 
654
 
 
655
        config  = XRRGetScreenInfo (s->display->display, s->root);
 
656
        value.i = (int) XRRConfigCurrentRate (config);
 
657
 
 
658
        XRRFreeScreenConfigInfo (config);
 
659
 
 
660
        name = s->opt[COMP_SCREEN_OPTION_REFRESH_RATE].name;
 
661
 
 
662
        s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b = FALSE;
 
663
        (*s->setScreenOption) (s, name, &value);
 
664
        s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b = TRUE;
 
665
    }
 
666
}
 
667
 
 
668
static void
 
669
setSupportingWmCheck (CompScreen *s)
 
670
{
 
671
    CompDisplay *d = s->display;
 
672
 
 
673
    XChangeProperty (d->display, s->grabWindow, d->supportingWmCheckAtom,
 
674
                     XA_WINDOW, 32, PropModeReplace,
 
675
                     (unsigned char *) &s->grabWindow, 1);
 
676
 
 
677
    XChangeProperty (d->display, s->grabWindow, d->wmNameAtom,
 
678
                     d->utf8StringAtom, 8, PropModeReplace,
 
679
                     (unsigned char *) PACKAGE, strlen (PACKAGE));
 
680
    XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
 
681
                     XA_ATOM, 32, PropModeReplace,
 
682
                     (unsigned char *) &d->winStateSkipTaskbarAtom, 1);
 
683
    XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
 
684
                     XA_ATOM, 32, PropModeAppend,
 
685
                     (unsigned char *) &d->winStateSkipPagerAtom, 1);
 
686
    XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
 
687
                     XA_ATOM, 32, PropModeAppend,
 
688
                     (unsigned char *) &d->winStateHiddenAtom, 1);
 
689
 
 
690
    XChangeProperty (d->display, s->root, d->supportingWmCheckAtom,
 
691
                     XA_WINDOW, 32, PropModeReplace,
 
692
                     (unsigned char *) &s->grabWindow, 1);
 
693
}
 
694
 
 
695
static void
 
696
setSupported (CompScreen *s)
 
697
{
 
698
    CompDisplay *d = s->display;
 
699
    Atom        data[256];
 
700
    int         i = 0;
 
701
 
 
702
    data[i++] = d->supportedAtom;
 
703
    data[i++] = d->supportingWmCheckAtom;
 
704
 
 
705
    data[i++] = d->utf8StringAtom;
 
706
 
 
707
    data[i++] = d->clientListAtom;
 
708
    data[i++] = d->clientListStackingAtom;
 
709
 
 
710
    data[i++] = d->winActiveAtom;
 
711
 
 
712
    data[i++] = d->desktopViewportAtom;
 
713
    data[i++] = d->desktopGeometryAtom;
 
714
    data[i++] = d->currentDesktopAtom;
 
715
    data[i++] = d->numberOfDesktopsAtom;
 
716
    data[i++] = d->showingDesktopAtom;
 
717
 
 
718
    data[i++] = d->workareaAtom;
 
719
 
 
720
    data[i++] = d->wmNameAtom;
 
721
/*
 
722
    data[i++] = d->wmVisibleNameAtom;
 
723
*/
 
724
 
 
725
    data[i++] = d->wmStrutAtom;
 
726
    data[i++] = d->wmStrutPartialAtom;
 
727
 
 
728
/*
 
729
    data[i++] = d->wmPidAtom;
 
730
    data[i++] = d->wmUserTimeAtom;
 
731
*/
 
732
 
 
733
    data[i++] = d->frameExtentsAtom;
 
734
    data[i++] = d->frameWindowAtom;
 
735
 
 
736
    data[i++] = d->winStateModalAtom;
 
737
    data[i++] = d->winStateStickyAtom;
 
738
    data[i++] = d->winStateMaximizedVertAtom;
 
739
    data[i++] = d->winStateMaximizedHorzAtom;
 
740
    data[i++] = d->winStateShadedAtom;
 
741
    data[i++] = d->winStateSkipTaskbarAtom;
 
742
    data[i++] = d->winStateSkipPagerAtom;
 
743
    data[i++] = d->winStateHiddenAtom;
 
744
    data[i++] = d->winStateFullscreenAtom;
 
745
    data[i++] = d->winStateAboveAtom;
 
746
    data[i++] = d->winStateBelowAtom;
 
747
    data[i++] = d->winStateDemandsAttentionAtom;
 
748
 
 
749
    data[i++] = d->winOpacityAtom;
 
750
    data[i++] = d->winBrightnessAtom;
 
751
 
 
752
    if (s->canDoSaturated)
 
753
    {
 
754
        data[i++] = d->winSaturationAtom;
 
755
        data[i++] = d->winStateDisplayModalAtom;
 
756
    }
 
757
 
 
758
    data[i++] = d->wmAllowedActionsAtom;
 
759
 
 
760
    data[i++] = d->winActionMoveAtom;
 
761
    data[i++] = d->winActionResizeAtom;
 
762
    data[i++] = d->winActionStickAtom;
 
763
    data[i++] = d->winActionMinimizeAtom;
 
764
    data[i++] = d->winActionMaximizeHorzAtom;
 
765
    data[i++] = d->winActionMaximizeVertAtom;
 
766
    data[i++] = d->winActionFullscreenAtom;
 
767
    data[i++] = d->winActionCloseAtom;
 
768
 
 
769
    data[i++] = d->winTypeAtom;
 
770
    data[i++] = d->winTypeDesktopAtom;
 
771
    data[i++] = d->winTypeDockAtom;
 
772
    data[i++] = d->winTypeToolbarAtom;
 
773
    data[i++] = d->winTypeMenuAtom;
 
774
    data[i++] = d->winTypeSplashAtom;
 
775
    data[i++] = d->winTypeDialogAtom;
 
776
    data[i++] = d->winTypeUtilAtom;
 
777
    data[i++] = d->winTypeNormalAtom;
 
778
 
 
779
    data[i++] = d->wmDeleteWindowAtom;
 
780
    data[i++] = d->wmPingAtom;
 
781
 
 
782
    data[i++] = d->wmMoveResizeAtom;
 
783
    data[i++] = d->moveResizeWindowAtom;
 
784
 
 
785
    XChangeProperty (d->display, s->root, d->supportedAtom, XA_ATOM, 32,
 
786
                     PropModeReplace, (unsigned char *) data, i);
 
787
}
 
788
 
 
789
static void
 
790
setDesktopHints (CompScreen *s)
 
791
{
 
792
    CompDisplay   *d = s->display;
 
793
    unsigned long data[2];
 
794
    Atom          actual;
 
795
    int           result, format;
 
796
    unsigned long n, left;
 
797
    unsigned char *propData;
 
798
 
 
799
    result = XGetWindowProperty (s->display->display, s->root,
 
800
                                 d->desktopViewportAtom, 0L, 2L, FALSE,
 
801
                                 XA_CARDINAL, &actual, &format,
 
802
                                 &n, &left, &propData);
 
803
 
 
804
    if (result == Success && n && propData)
 
805
    {
 
806
        if (n == 2)
 
807
        {
 
808
            memcpy (data, propData, sizeof (unsigned long));
 
809
 
 
810
            if (data[0] / s->width < s->size - 1)
 
811
                s->x = data[0] / s->width;
 
812
        }
 
813
 
 
814
        XFree (propData);
 
815
    }
 
816
 
 
817
    data[0] = s->x * s->width;
 
818
    data[1] = 0;
 
819
 
 
820
    XChangeProperty (d->display, s->root, d->desktopViewportAtom,
 
821
                     XA_CARDINAL, 32, PropModeReplace,
 
822
                     (unsigned char *) data, 2);
 
823
 
 
824
    data[0] = s->width * s->size;
 
825
    data[1] = s->height;
 
826
 
 
827
    XChangeProperty (d->display, s->root, d->desktopGeometryAtom,
 
828
                     XA_CARDINAL, 32, PropModeReplace,
 
829
                     (unsigned char *) data, 2);
 
830
 
 
831
    data[0] = 1;
 
832
 
 
833
    XChangeProperty (d->display, s->root, d->numberOfDesktopsAtom,
 
834
                     XA_CARDINAL, 32, PropModeReplace,
 
835
                     (unsigned char *) data, 1);
 
836
 
 
837
    data[0] = 0;
 
838
 
 
839
    XChangeProperty (d->display, s->root, d->currentDesktopAtom,
 
840
                     XA_CARDINAL, 32, PropModeReplace,
 
841
                     (unsigned char *) data, 1);
 
842
 
 
843
    data[0] = 0;
 
844
 
 
845
    result = XGetWindowProperty (s->display->display, s->root,
 
846
                                 d->showingDesktopAtom, 0L, 1L, FALSE,
 
847
                                 XA_CARDINAL, &actual, &format,
 
848
                                 &n, &left, &propData);
 
849
 
 
850
    if (result == Success && n && propData)
 
851
    {
 
852
        memcpy (data, propData, sizeof (unsigned long));
 
853
        XFree (propData);
 
854
 
 
855
        if (data[0])
 
856
            enterShowDesktopMode (s);
 
857
    }
 
858
 
 
859
    XChangeProperty (d->display, s->root, d->showingDesktopAtom,
 
860
                     XA_CARDINAL, 32, PropModeReplace,
 
861
                     (unsigned char *) data, 1);
 
862
}
 
863
 
 
864
Bool
 
865
addScreen (CompDisplay *display,
 
866
           int         screenNum,
 
867
           Window      wmSnSelectionWindow,
 
868
           Atom        wmSnAtom,
 
869
           Time        wmSnTimestamp)
 
870
{
 
871
    CompScreen           *s;
 
872
    Display              *dpy = display->display;
 
873
    static char          data = 0;
 
874
    XColor               black;
 
875
    Pixmap               bitmap;
 
876
    XVisualInfo          templ;
 
877
    XVisualInfo          *visinfo;
 
878
    VisualID             visualIDs[MAX_DEPTH + 1];
 
879
    Window               rootReturn, parentReturn;
 
880
    Window               *children;
 
881
    unsigned int         nchildren;
 
882
    int                  defaultDepth, nvisinfo, value, i;
 
883
    const char           *glxExtensions, *glExtensions;
 
884
    GLint                stencilBits;
 
885
    XSetWindowAttributes attrib;
 
886
    CompWindow           *w;
 
887
 
 
888
    s = malloc (sizeof (CompScreen));
 
889
    if (!s)
 
890
        return FALSE;
 
891
 
 
892
    s->windowPrivateIndices = 0;
 
893
    s->windowPrivateLen     = 0;
 
894
 
 
895
    if (display->screenPrivateLen)
 
896
    {
 
897
        s->privates = malloc (display->screenPrivateLen *
 
898
                              sizeof (CompPrivate));
 
899
        if (!s->privates)
 
900
        {
 
901
            free (s);
 
902
            return FALSE;
 
903
        }
 
904
    }
 
905
    else
 
906
        s->privates = 0;
 
907
 
 
908
    s->display = display;
 
909
 
 
910
    compScreenInitOptions (s);
 
911
 
 
912
    s->damage = XCreateRegion ();
 
913
    if (!s->damage)
 
914
        return FALSE;
 
915
 
 
916
    s->x    = 0;
 
917
    s->size = 4;
 
918
 
 
919
    s->buttonGrab  = 0;
 
920
    s->nButtonGrab = 0;
 
921
    s->keyGrab     = 0;
 
922
    s->nKeyGrab    = 0;
 
923
 
 
924
    s->grabs    = 0;
 
925
    s->grabSize = 0;
 
926
    s->maxGrab  = 0;
 
927
 
 
928
    s->pendingDestroys = 0;
 
929
 
 
930
    s->clientList  = 0;
 
931
    s->nClientList = 0;
 
932
 
 
933
    s->screenNum = screenNum;
 
934
    s->colormap  = DefaultColormap (dpy, screenNum);
 
935
    s->root      = XRootWindow (dpy, screenNum);
 
936
 
 
937
    s->mapNum    = 1;
 
938
    s->activeNum = 1;
 
939
 
 
940
    s->groups = NULL;
 
941
 
 
942
    s->snContext = sn_monitor_context_new (display->snDisplay,
 
943
                                           screenNum,
 
944
                                           compScreenSnEvent, s,
 
945
                                           NULL);
 
946
 
 
947
    s->startupSequences             = NULL;
 
948
    s->startupSequenceTimeoutHandle = 0;
 
949
 
 
950
    s->wmSnSelectionWindow = wmSnSelectionWindow;
 
951
    s->wmSnAtom            = wmSnAtom;
 
952
    s->wmSnTimestamp       = wmSnTimestamp;
 
953
 
 
954
    if (testMode)
 
955
    {
 
956
        XWMHints   *wmHints;
 
957
        XSizeHints *normalHints;
 
958
        XClassHint *classHint;
 
959
        int        glx_attrib[] = {
 
960
            GLX_RGBA,
 
961
            GLX_RED_SIZE, 1,
 
962
            GLX_STENCIL_SIZE, 2,
 
963
            GLX_DOUBLEBUFFER,
 
964
            None
 
965
        };
 
966
 
 
967
        visinfo = glXChooseVisual (dpy, screenNum, glx_attrib);
 
968
        if (!visinfo)
 
969
        {
 
970
            int glx_attrib2[] = {
 
971
                GLX_RGBA,
 
972
                GLX_RED_SIZE, 1,
 
973
                GLX_DOUBLEBUFFER,
 
974
                None
 
975
            };
 
976
 
 
977
            visinfo = glXChooseVisual (dpy, screenNum, glx_attrib2);
 
978
            if (!visinfo)
 
979
            {
 
980
                fprintf (stderr, "%s: Couldn't find a double buffered "
 
981
                         "RGB visual.\n", programName);
 
982
                return FALSE;
 
983
            }
 
984
        }
 
985
 
 
986
        attrib.colormap = XCreateColormap (dpy, s->root, visinfo->visual,
 
987
                                           AllocNone);
 
988
 
 
989
        normalHints = XAllocSizeHints ();
 
990
        normalHints->flags = 0;
 
991
        normalHints->x = 0;
 
992
        normalHints->y = 0;
 
993
        normalHints->width = 800;
 
994
        normalHints->height = 600;
 
995
 
 
996
        classHint = XAllocClassHint ();
 
997
        classHint->res_name = "compiz";
 
998
        classHint->res_class = "Compiz";
 
999
 
 
1000
        wmHints = XAllocWMHints ();
 
1001
        wmHints->flags = InputHint;
 
1002
        wmHints->input = TRUE;
 
1003
 
 
1004
        s->root = XCreateWindow (dpy, s->root, 0, 0,
 
1005
                                 normalHints->width, normalHints->height, 0,
 
1006
                                 visinfo->depth, InputOutput, visinfo->visual,
 
1007
                                 CWColormap, &attrib);
 
1008
 
 
1009
        XSelectInput (dpy, s->root,
 
1010
                      SubstructureNotifyMask |
 
1011
                      ExposureMask           |
 
1012
                      ButtonPressMask        |
 
1013
                      ButtonReleaseMask      |
 
1014
                      ButtonMotionMask);
 
1015
 
 
1016
        XRRSelectInput (dpy, s->root, RRScreenChangeNotifyMask);
 
1017
 
 
1018
        XSetWMProtocols (dpy, s->root, &display->wmDeleteWindowAtom, 1);
 
1019
 
 
1020
        XmbSetWMProperties (dpy, s->root,
 
1021
                            "glxcompmgr - Test mode", "glxcompmgr",
 
1022
                            programArgv, programArgc,
 
1023
                            normalHints, wmHints, classHint);
 
1024
 
 
1025
        XMapWindow (dpy, s->root);
 
1026
 
 
1027
        XFree (wmHints);
 
1028
        XFree (classHint);
 
1029
        XFree (normalHints);
 
1030
    }
 
1031
 
 
1032
    s->fake[0] = s->fake[1] = 0;
 
1033
 
 
1034
    s->escapeKeyCode = XKeysymToKeycode (display->display,
 
1035
                                         XStringToKeysym ("Escape"));
 
1036
 
 
1037
    s->damageMask  = COMP_SCREEN_DAMAGE_ALL_MASK;
 
1038
    s->next        = 0;
 
1039
    s->exposeRects = 0;
 
1040
    s->sizeExpose  = 0;
 
1041
    s->nExpose     = 0;
 
1042
 
 
1043
    s->rasterX = 0;
 
1044
    s->rasterY = 0;
 
1045
 
 
1046
    s->windows = 0;
 
1047
    s->reverseWindows = 0;
 
1048
 
 
1049
    s->stencilRef = 0x1;
 
1050
 
 
1051
    s->nextRedraw  = 0;
 
1052
    s->frameStatus = 0;
 
1053
 
 
1054
    s->showingDesktopMask = 0;
 
1055
 
 
1056
    gettimeofday (&s->lastRedraw, 0);
 
1057
 
 
1058
    s->setScreenOption          = setScreenOption;
 
1059
    s->setScreenOptionForPlugin = setScreenOptionForPlugin;
 
1060
 
 
1061
    s->initPluginForScreen = initPluginForScreen;
 
1062
    s->finiPluginForScreen = finiPluginForScreen;
 
1063
 
 
1064
    s->preparePaintScreen     = preparePaintScreen;
 
1065
    s->donePaintScreen        = donePaintScreen;
 
1066
    s->paintScreen            = paintScreen;
 
1067
    s->paintTransformedScreen = paintTransformedScreen;
 
1068
    s->paintBackground        = paintBackground;
 
1069
    s->paintWindow            = paintWindow;
 
1070
    s->addWindowGeometry      = addWindowGeometry;
 
1071
    s->drawWindowGeometry     = drawWindowGeometry;
 
1072
    s->damageWindowRect       = damageWindowRect;
 
1073
    s->focusWindow            = focusWindow;
 
1074
    s->setWindowScale         = setWindowScale;
 
1075
 
 
1076
    s->windowResizeNotify = windowResizeNotify;
 
1077
    s->windowMoveNotify   = windowMoveNotify;
 
1078
    s->windowGrabNotify   = windowGrabNotify;
 
1079
    s->windowUngrabNotify = windowUngrabNotify;
 
1080
 
 
1081
    s->getProcAddress = 0;
 
1082
 
 
1083
    if (!XGetWindowAttributes (dpy, s->root, &s->attrib))
 
1084
        return FALSE;
 
1085
 
 
1086
    s->workArea.x      = 0;
 
1087
    s->workArea.y      = 0;
 
1088
    s->workArea.width  = s->attrib.width;
 
1089
    s->workArea.height = s->attrib.height;
 
1090
 
 
1091
    s->grabWindow = None;
 
1092
 
 
1093
    templ.visualid = XVisualIDFromVisual (s->attrib.visual);
 
1094
 
 
1095
    visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &nvisinfo);
 
1096
    if (!nvisinfo)
 
1097
    {
 
1098
        fprintf (stderr, "%s: Couldn't get visual info for default visual\n",
 
1099
                 programName);
 
1100
        return FALSE;
 
1101
    }
 
1102
 
 
1103
    defaultDepth = visinfo->depth;
 
1104
 
 
1105
    black.red = black.green = black.blue = 0;
 
1106
 
 
1107
    if (!XAllocColor (dpy, s->colormap, &black))
 
1108
    {
 
1109
        fprintf (stderr, "%s: Couldn't allocate color\n", programName);
 
1110
        return FALSE;
 
1111
    }
 
1112
 
 
1113
    bitmap = XCreateBitmapFromData (dpy, s->root, &data, 1, 1);
 
1114
    if (!bitmap)
 
1115
    {
 
1116
        fprintf (stderr, "%s: Couldn't create bitmap\n", programName);
 
1117
        return FALSE;
 
1118
    }
 
1119
 
 
1120
    s->invisibleCursor = XCreatePixmapCursor (dpy, bitmap, bitmap,
 
1121
                                              &black, &black, 0, 0);
 
1122
    if (!s->invisibleCursor)
 
1123
    {
 
1124
        fprintf (stderr, "%s: Couldn't create invisible cursor\n",
 
1125
                 programName);
 
1126
        return FALSE;
 
1127
    }
 
1128
 
 
1129
    XFreePixmap (dpy, bitmap);
 
1130
    XFreeColors (dpy, s->colormap, &black.pixel, 1, 0);
 
1131
 
 
1132
    glXGetConfig (dpy, visinfo, GLX_USE_GL, &value);
 
1133
    if (!value)
 
1134
    {
 
1135
        fprintf (stderr, "%s: Root visual is not a GL visual\n",
 
1136
                 programName);
 
1137
        return FALSE;
 
1138
    }
 
1139
 
 
1140
    addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW].value.bind);
 
1141
    addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_MAIN_MENU].value.bind);
 
1142
    addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_RUN_DIALOG].value.bind);
 
1143
 
 
1144
    glXGetConfig (dpy, visinfo, GLX_DOUBLEBUFFER, &value);
 
1145
    if (!value)
 
1146
    {
 
1147
        fprintf (stderr,
 
1148
                 "%s: Root visual is not a double buffered GL visual\n",
 
1149
                 programName);
 
1150
        return FALSE;
 
1151
    }
 
1152
 
 
1153
    s->ctx = glXCreateContext (dpy, visinfo, NULL, TRUE);
 
1154
    if (!s->ctx)
 
1155
    {
 
1156
        fprintf (stderr, "%s: glXCreateContext failed\n", programName);
 
1157
        return FALSE;
 
1158
    }
 
1159
 
 
1160
    XFree (visinfo);
 
1161
 
 
1162
    /* we don't want to allocate back, stencil or depth buffers for pixmaps
 
1163
       so lets see if we can find an approriate visual without these buffers */
 
1164
    for (i = 0; i <= MAX_DEPTH; i++)
 
1165
    {
 
1166
        int j, db, stencil, depth;
 
1167
 
 
1168
        visualIDs[i] = 0;
 
1169
 
 
1170
        db      = MAXSHORT;
 
1171
        stencil = MAXSHORT;
 
1172
        depth   = MAXSHORT;
 
1173
 
 
1174
        templ.depth = i;
 
1175
 
 
1176
        visinfo = XGetVisualInfo (dpy, VisualDepthMask, &templ, &nvisinfo);
 
1177
        for (j = 0; j < nvisinfo; j++)
 
1178
        {
 
1179
            glXGetConfig (dpy, &visinfo[j], GLX_USE_GL, &value);
 
1180
            if (!value)
 
1181
                continue;
 
1182
 
 
1183
            glXGetConfig (dpy, &visinfo[j], GLX_DOUBLEBUFFER, &value);
 
1184
            if (value > db)
 
1185
                continue;
 
1186
 
 
1187
            db = value;
 
1188
            glXGetConfig (dpy, &visinfo[j], GLX_STENCIL_SIZE, &value);
 
1189
            if (value > stencil)
 
1190
                continue;
 
1191
 
 
1192
            stencil = value;
 
1193
            glXGetConfig (dpy, &visinfo[j], GLX_DEPTH_SIZE, &value);
 
1194
            if (value > depth)
 
1195
                continue;
 
1196
 
 
1197
            depth = value;
 
1198
            visualIDs[i] = visinfo[j].visualid;
 
1199
        }
 
1200
 
 
1201
        if (nvisinfo)
 
1202
            XFree (visinfo);
 
1203
    }
 
1204
 
 
1205
    /* create contexts for supported depths */
 
1206
    for (i = 0; i <= MAX_DEPTH; i++)
 
1207
    {
 
1208
        templ.visualid = visualIDs[i];
 
1209
        s->glxPixmapVisuals[i] = XGetVisualInfo (dpy,
 
1210
                                                 VisualIDMask,
 
1211
                                                 &templ,
 
1212
                                                 &nvisinfo);
 
1213
    }
 
1214
 
 
1215
    if (!s->glxPixmapVisuals[defaultDepth])
 
1216
    {
 
1217
        fprintf (stderr, "%s: No GL visual for default depth, "
 
1218
                 "this isn't going to work.\n", programName);
 
1219
        return FALSE;
 
1220
    }
 
1221
 
 
1222
    glXMakeCurrent (dpy, s->root, s->ctx);
 
1223
    currentRoot = s->root;
 
1224
 
 
1225
    glxExtensions = glXQueryExtensionsString (s->display->display, screenNum);
 
1226
    if (!testMode && !strstr (glxExtensions, "GLX_EXT_texture_from_pixmap"))
 
1227
    {
 
1228
        fprintf (stderr, "%s: GLX_EXT_texture_from_pixmap is missing\n",
 
1229
                 programName);
 
1230
        return FALSE;
 
1231
    }
 
1232
 
 
1233
    s->getProcAddress = (GLXGetProcAddressProc)
 
1234
        getProcAddress (s, "glXGetProcAddressARB");
 
1235
    s->bindTexImage = (GLXBindTexImageProc)
 
1236
        getProcAddress (s, "glXBindTexImageEXT");
 
1237
    s->releaseTexImage = (GLXReleaseTexImageProc)
 
1238
        getProcAddress (s, "glXReleaseTexImageEXT");
 
1239
    s->queryDrawable = (GLXQueryDrawableProc)
 
1240
        getProcAddress (s, "glXQueryDrawable");
 
1241
 
 
1242
    if (!testMode && !s->bindTexImage)
 
1243
    {
 
1244
        fprintf (stderr, "%s: glXBindTexImageEXT is missing\n", programName);
 
1245
        return FALSE;
 
1246
    }
 
1247
 
 
1248
    if (!testMode && !s->releaseTexImage)
 
1249
    {
 
1250
        fprintf (stderr, "%s: glXReleaseTexImageEXT is missing\n",
 
1251
                 programName);
 
1252
        return FALSE;
 
1253
    }
 
1254
 
 
1255
    if (!testMode && !s->queryDrawable)
 
1256
    {
 
1257
        fprintf (stderr, "%s: glXQueryDrawable is missing\n", programName);
 
1258
        return FALSE;
 
1259
    }
 
1260
 
 
1261
    s->textureRectangle = 0;
 
1262
    glExtensions = (const char *) glGetString (GL_EXTENSIONS);
 
1263
    if (strstr (glExtensions, "GL_NV_texture_rectangle")  ||
 
1264
        strstr (glExtensions, "GL_EXT_texture_rectangle") ||
 
1265
        strstr (glExtensions, "GL_ARB_texture_rectangle"))
 
1266
        s->textureRectangle = 1;
 
1267
 
 
1268
    s->textureNonPowerOfTwo = 0;
 
1269
    if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
 
1270
        s->textureNonPowerOfTwo = 1;
 
1271
 
 
1272
    if (!(s->textureRectangle || s->textureNonPowerOfTwo))
 
1273
    {
 
1274
        fprintf (stderr, "%s: Support for non power of two textures missing\n",
 
1275
                 programName);
 
1276
        return FALSE;
 
1277
    }
 
1278
 
 
1279
    s->textureEnvCombine = s->textureEnvCrossbar = 0;
 
1280
    if (strstr (glExtensions, "GL_ARB_texture_env_combine"))
 
1281
    {
 
1282
        s->textureEnvCombine = 1;
 
1283
 
 
1284
        /* XXX: GL_NV_texture_env_combine4 need special code but it seams to
 
1285
           be working anyway for now... */
 
1286
        if (strstr (glExtensions, "GL_ARB_texture_env_crossbar") ||
 
1287
            strstr (glExtensions, "GL_NV_texture_env_combine4"))
 
1288
            s->textureEnvCrossbar = 1;
 
1289
    }
 
1290
 
 
1291
    s->textureBorderClamp = 0;
 
1292
    if (strstr (glExtensions, "GL_ARB_texture_border_clamp") ||
 
1293
        strstr (glExtensions, "GL_SGIS_texture_border_clamp"))
 
1294
        s->textureBorderClamp = 1;
 
1295
 
 
1296
    s->maxTextureUnits = 1;
 
1297
    if (strstr (glExtensions, "GL_ARB_multitexture"))
 
1298
    {
 
1299
        s->activeTexture = (GLActiveTextureProc)
 
1300
            getProcAddress (s, "glActiveTexture");
 
1301
        s->clientActiveTexture = (GLClientActiveTextureProc)
 
1302
            getProcAddress (s, "glClientActiveTexture");
 
1303
 
 
1304
        if (s->activeTexture && s->clientActiveTexture)
 
1305
            glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &s->maxTextureUnits);
 
1306
    }
 
1307
 
 
1308
    initTexture (s, &s->backgroundTexture);
 
1309
 
 
1310
    s->desktopWindowCount = 0;
 
1311
 
 
1312
    glGetIntegerv (GL_STENCIL_BITS, &stencilBits);
 
1313
    if (!stencilBits)
 
1314
    {
 
1315
        fprintf (stderr, "%s: No stencil buffer. Clipping of transformed "
 
1316
                 "windows is not going to be correct when screen is "
 
1317
                 "transformed.\n", programName);
 
1318
    }
 
1319
 
 
1320
    glClearColor (0.0, 0.0, 0.0, 1.0);
 
1321
    glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
1322
    glEnable (GL_CULL_FACE);
 
1323
    glDisable (GL_BLEND);
 
1324
    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
1325
    glColor4usv (defaultColor);
 
1326
    glEnableClientState (GL_VERTEX_ARRAY);
 
1327
    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
1328
 
 
1329
    s->canDoSaturated = s->canDoSlightlySaturated = FALSE;
 
1330
    if (s->textureEnvCombine && s->maxTextureUnits >= 2)
 
1331
    {
 
1332
        s->canDoSaturated = TRUE;
 
1333
        if (s->textureEnvCrossbar && s->maxTextureUnits >= 4)
 
1334
            s->canDoSlightlySaturated = TRUE;
 
1335
    }
 
1336
 
 
1337
    s->redrawTime = 1000 / defaultRefreshRate;
 
1338
    s->optimalRedrawTime = s->redrawTime;
 
1339
 
 
1340
    reshape (s, s->attrib.width, s->attrib.height);
 
1341
 
 
1342
    s->next = display->screens;
 
1343
    display->screens = s;
 
1344
 
 
1345
    screenInitPlugins (s);
 
1346
 
 
1347
    detectRefreshRateOfScreen (s);
 
1348
 
 
1349
    XGrabServer (dpy);
 
1350
 
 
1351
    XQueryTree (dpy, s->root,
 
1352
                &rootReturn, &parentReturn,
 
1353
                &children, &nchildren);
 
1354
 
 
1355
    for (i = 0; i < nchildren; i++)
 
1356
        addWindow (s, children[i], i ? children[i - 1] : 0);
 
1357
 
 
1358
    for (w = s->windows; w; w = w->next)
 
1359
    {
 
1360
        if (w->attrib.map_state == IsViewable)
 
1361
        {
 
1362
            w->activeNum = s->activeNum++;
 
1363
            w->damaged   = TRUE;
 
1364
            w->placed    = TRUE;
 
1365
            w->invisible = WINDOW_INVISIBLE (w);
 
1366
        }
 
1367
        else if (w->state & CompWindowStateHiddenMask)
 
1368
        {
 
1369
            w->placed = TRUE;
 
1370
        }
 
1371
    }
 
1372
 
 
1373
    XUngrabServer (dpy);
 
1374
 
 
1375
    XFree (children);
 
1376
 
 
1377
    attrib.override_redirect = 1;
 
1378
    s->grabWindow = XCreateWindow (dpy, s->root, -100, -100, 1, 1, 0,
 
1379
                                   CopyFromParent, InputOnly,
 
1380
                                   CopyFromParent, CWOverrideRedirect,
 
1381
                                   &attrib);
 
1382
 
 
1383
    XMapWindow (dpy, s->grabWindow);
 
1384
 
 
1385
    if (testMode)
 
1386
    {
 
1387
        s->fake[0] = XCreateWindow (dpy, s->root, 64, 32, 1, 1, 0,
 
1388
                                    CopyFromParent, InputOutput,
 
1389
                                    CopyFromParent, 0, NULL);
 
1390
 
 
1391
        s->fake[1] = XCreateWindow (dpy, s->root, 256, 256, 1, 1, 0,
 
1392
                                    CopyFromParent, InputOutput,
 
1393
                                    CopyFromParent, 0, NULL);
 
1394
    }
 
1395
 
 
1396
    setDesktopHints (s);
 
1397
    setSupportingWmCheck (s);
 
1398
    setSupported (s);
 
1399
 
 
1400
    s->normalCursor = XCreateFontCursor (dpy, XC_left_ptr);
 
1401
    s->busyCursor   = XCreateFontCursor (dpy, XC_watch);
 
1402
 
 
1403
    XDefineCursor (dpy, s->root, s->normalCursor);
 
1404
 
 
1405
    return TRUE;
 
1406
}
 
1407
 
 
1408
void
 
1409
damageScreenRegion (CompScreen *screen,
 
1410
                    Region     region)
 
1411
{
 
1412
    if (screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
 
1413
        return;
 
1414
 
 
1415
    XUnionRegion (screen->damage, region, screen->damage);
 
1416
 
 
1417
    screen->damageMask |= COMP_SCREEN_DAMAGE_REGION_MASK;
 
1418
}
 
1419
 
 
1420
void
 
1421
damageScreen (CompScreen *s)
 
1422
{
 
1423
    s->damageMask |= COMP_SCREEN_DAMAGE_ALL_MASK;
 
1424
    s->damageMask &= ~COMP_SCREEN_DAMAGE_REGION_MASK;
 
1425
}
 
1426
 
 
1427
void
 
1428
damagePendingOnScreen (CompScreen *s)
 
1429
{
 
1430
    s->damageMask |= COMP_SCREEN_DAMAGE_PENDING_MASK;
 
1431
}
 
1432
 
 
1433
void
 
1434
forEachWindowOnScreen (CompScreen        *screen,
 
1435
                       ForEachWindowProc proc,
 
1436
                       void              *closure)
 
1437
{
 
1438
    CompWindow *w;
 
1439
 
 
1440
    for (w = screen->windows; w; w = w->next)
 
1441
        (*proc) (w, closure);
 
1442
}
 
1443
 
 
1444
CompWindow *
 
1445
findWindowAtScreen (CompScreen *s,
 
1446
                    Window     id)
 
1447
{
 
1448
    if (lastFoundWindow && lastFoundWindow->id == id)
 
1449
    {
 
1450
        return lastFoundWindow;
 
1451
    }
 
1452
    else
 
1453
    {
 
1454
        CompWindow *w;
 
1455
 
 
1456
        for (w = s->windows; w; w = w->next)
 
1457
            if (w->id == id)
 
1458
                return (lastFoundWindow = w);
 
1459
    }
 
1460
 
 
1461
    return 0;
 
1462
}
 
1463
 
 
1464
CompWindow *
 
1465
findTopLevelWindowAtScreen (CompScreen *s,
 
1466
                            Window      id)
 
1467
{
 
1468
    CompWindow *found = NULL;
 
1469
 
 
1470
    if (lastFoundWindow && lastFoundWindow->id == id)
 
1471
    {
 
1472
        found = lastFoundWindow;
 
1473
    }
 
1474
    else
 
1475
    {
 
1476
        CompWindow *w;
 
1477
 
 
1478
        for (w = s->windows; w; w = w->next)
 
1479
        {
 
1480
            if (w->id == id)
 
1481
            {
 
1482
                found = (lastFoundWindow = w);
 
1483
                break;
 
1484
            }
 
1485
        }
 
1486
    }
 
1487
 
 
1488
    if (!found)
 
1489
        return NULL;
 
1490
 
 
1491
    if (found->attrib.override_redirect)
 
1492
    {
 
1493
        /* likely a frame window */
 
1494
        if (found->attrib.class == InputOnly)
 
1495
        {
 
1496
            CompWindow *w;
 
1497
 
 
1498
            for (w = s->windows; w; w = w->next)
 
1499
                if (w->frame == id)
 
1500
                    return w;
 
1501
        }
 
1502
 
 
1503
        return NULL;
 
1504
    }
 
1505
 
 
1506
    return found;
 
1507
}
 
1508
 
 
1509
void
 
1510
insertWindowIntoScreen (CompScreen *s,
 
1511
                        CompWindow *w,
 
1512
                        Window     aboveId)
 
1513
{
 
1514
    CompWindow *p;
 
1515
 
 
1516
    if (s->windows)
 
1517
    {
 
1518
        if (!aboveId)
 
1519
        {
 
1520
            w->next = s->windows;
 
1521
            w->prev = NULL;
 
1522
            s->windows->prev = w;
 
1523
            s->windows = w;
 
1524
        }
 
1525
        else
 
1526
        {
 
1527
            for (p = s->windows; p; p = p->next)
 
1528
            {
 
1529
                if (p->next)
 
1530
                {
 
1531
                    if (p->id == aboveId && p->mapNum)
 
1532
                    {
 
1533
                        w->next = p->next;
 
1534
                        w->prev = p;
 
1535
                        p->next->prev = w;
 
1536
                        p->next = w;
 
1537
 
 
1538
                        break;
 
1539
                    }
 
1540
                }
 
1541
                else
 
1542
                {
 
1543
                    p->next = w;
 
1544
                    w->next = NULL;
 
1545
                    w->prev = p;
 
1546
                    s->reverseWindows = w;
 
1547
 
 
1548
                    break;
 
1549
                }
 
1550
            }
 
1551
        }
 
1552
    }
 
1553
    else
 
1554
    {
 
1555
        s->reverseWindows = s->windows = w;
 
1556
        w->prev = w->next = NULL;
 
1557
    }
 
1558
}
 
1559
 
 
1560
void
 
1561
unhookWindowFromScreen (CompScreen *s,
 
1562
                        CompWindow *w)
 
1563
{
 
1564
    CompWindow *next, *prev;
 
1565
 
 
1566
    next = w->next;
 
1567
    prev = w->prev;
 
1568
 
 
1569
    if (next || prev)
 
1570
    {
 
1571
        if (next)
 
1572
        {
 
1573
            if (prev)
 
1574
            {
 
1575
                next->prev = prev;
 
1576
            }
 
1577
            else
 
1578
            {
 
1579
                s->windows = next;
 
1580
                next->prev = NULL;
 
1581
            }
 
1582
        }
 
1583
 
 
1584
        if (prev)
 
1585
        {
 
1586
            if (next)
 
1587
            {
 
1588
                prev->next = next;
 
1589
            }
 
1590
            else
 
1591
            {
 
1592
                s->reverseWindows = prev;
 
1593
                prev->next = NULL;
 
1594
            }
 
1595
        }
 
1596
    }
 
1597
    else
 
1598
    {
 
1599
        s->windows = s->reverseWindows = NULL;
 
1600
    }
 
1601
 
 
1602
    if (w == lastFoundWindow)
 
1603
        lastFoundWindow = NULL;
 
1604
    if (w == lastDamagedWindow)
 
1605
        lastDamagedWindow = NULL;
 
1606
}
 
1607
 
 
1608
#define POINTER_GRAB_MASK (ButtonReleaseMask | \
 
1609
                           ButtonPressMask   | \
 
1610
                           PointerMotionMask)
 
1611
int
 
1612
pushScreenGrab (CompScreen *s,
 
1613
                Cursor     cursor)
 
1614
{
 
1615
    if (s->maxGrab == 0)
 
1616
    {
 
1617
        int status;
 
1618
 
 
1619
        status = XGrabPointer (s->display->display, s->grabWindow, TRUE,
 
1620
                               POINTER_GRAB_MASK,
 
1621
                               GrabModeAsync, GrabModeAsync,
 
1622
                               s->root, cursor,
 
1623
                               CurrentTime);
 
1624
 
 
1625
        if (status == GrabSuccess)
 
1626
        {
 
1627
            status = XGrabKeyboard (s->display->display,
 
1628
                                    s->grabWindow, TRUE,
 
1629
                                    GrabModeAsync, GrabModeAsync,
 
1630
                                    CurrentTime);
 
1631
            if (status != GrabSuccess)
 
1632
            {
 
1633
                XUngrabPointer (s->display->display, CurrentTime);
 
1634
                return 0;
 
1635
            }
 
1636
        }
 
1637
        else
 
1638
            return 0;
 
1639
    }
 
1640
    else
 
1641
    {
 
1642
        XChangeActivePointerGrab (s->display->display, POINTER_GRAB_MASK,
 
1643
                                  cursor, CurrentTime);
 
1644
    }
 
1645
 
 
1646
    if (s->grabSize <= s->maxGrab)
 
1647
    {
 
1648
        s->grabs = realloc (s->grabs, sizeof (CompGrab) * (s->maxGrab + 1));
 
1649
        if (!s->grabs)
 
1650
            return 0;
 
1651
 
 
1652
        s->grabSize = s->maxGrab + 1;
 
1653
    }
 
1654
 
 
1655
    s->grabs[s->maxGrab].cursor = cursor;
 
1656
    s->grabs[s->maxGrab].active = TRUE;
 
1657
 
 
1658
    s->maxGrab++;
 
1659
 
 
1660
    return s->maxGrab;
 
1661
}
 
1662
 
 
1663
void
 
1664
removeScreenGrab (CompScreen *s,
 
1665
                  int        index,
 
1666
                  XPoint     *restorePointer)
 
1667
{
 
1668
    int maxGrab;
 
1669
 
 
1670
    index--;
 
1671
    if (index < 0 || index >= s->maxGrab)
 
1672
        abort ();
 
1673
 
 
1674
    s->grabs[index].cursor = None;
 
1675
    s->grabs[index].active = FALSE;
 
1676
 
 
1677
    for (maxGrab = s->maxGrab; maxGrab; maxGrab--)
 
1678
        if (s->grabs[maxGrab - 1].active)
 
1679
            break;
 
1680
 
 
1681
    if (maxGrab != s->maxGrab)
 
1682
    {
 
1683
        if (maxGrab)
 
1684
        {
 
1685
            XChangeActivePointerGrab (s->display->display,
 
1686
                                      POINTER_GRAB_MASK,
 
1687
                                      s->grabs[s->maxGrab - 1].cursor,
 
1688
                                      CurrentTime);
 
1689
        }
 
1690
        else
 
1691
        {
 
1692
            if (restorePointer)
 
1693
                XWarpPointer (s->display->display, None, s->root, 0, 0, 0, 0,
 
1694
                              restorePointer->x, restorePointer->y);
 
1695
 
 
1696
            XUngrabPointer (s->display->display, CurrentTime);
 
1697
            XUngrabKeyboard (s->display->display, CurrentTime);
 
1698
        }
 
1699
        s->maxGrab = maxGrab;
 
1700
    }
 
1701
}
 
1702
 
 
1703
static Bool
 
1704
addPassiveKeyGrab (CompScreen     *s,
 
1705
                   CompKeyBinding *key)
 
1706
{
 
1707
    CompKeyGrab  *keyGrab;
 
1708
    unsigned int modifiers, mask, ignore;
 
1709
    int          i;
 
1710
 
 
1711
    modifiers = key->modifiers & ~(CompPressMask | CompReleaseMask);
 
1712
    if (modifiers == key->modifiers)
 
1713
        return TRUE;
 
1714
 
 
1715
    for (i = 0; i < s->nKeyGrab; i++)
 
1716
    {
 
1717
        if (key->keycode == s->keyGrab[i].keycode &&
 
1718
            modifiers    == s->keyGrab[i].modifiers)
 
1719
        {
 
1720
            s->keyGrab[i].count++;
 
1721
            return TRUE;
 
1722
        }
 
1723
    }
 
1724
 
 
1725
    keyGrab = realloc (s->keyGrab, sizeof (CompKeyGrab) * (s->nKeyGrab + 1));
 
1726
    if (!keyGrab)
 
1727
        return FALSE;
 
1728
 
 
1729
    s->keyGrab = keyGrab;
 
1730
 
 
1731
    mask = virtualToRealModMask (s->display, modifiers);
 
1732
    if (!(mask & CompNoMask))
 
1733
    {
 
1734
        compCheckForError (s->display->display);
 
1735
 
 
1736
        for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
 
1737
        {
 
1738
            if (ignore & ~s->display->ignoredModMask)
 
1739
                continue;
 
1740
 
 
1741
            XGrabKey (s->display->display,
 
1742
                      key->keycode,
 
1743
                      mask | ignore,
 
1744
                      s->root,
 
1745
                      TRUE,
 
1746
                      GrabModeAsync,
 
1747
                      GrabModeAsync);
 
1748
        }
 
1749
 
 
1750
        if (compCheckForError (s->display->display))
 
1751
        {
 
1752
 
 
1753
#ifdef DEBUG
 
1754
            KeySym keysym;
 
1755
            char   *keyname;
 
1756
 
 
1757
            keysym = XKeycodeToKeysym (s->display->display,
 
1758
                                       key->keycode,
 
1759
                                       0);
 
1760
            keyname = XKeysymToString (keysym);
 
1761
 
 
1762
            fprintf (stderr, "XGrabKey failed: %s 0x%x\n",
 
1763
                     keyname, modifiers);
 
1764
#endif
 
1765
 
 
1766
            return FALSE;
 
1767
        }
 
1768
    }
 
1769
 
 
1770
    s->keyGrab[s->nKeyGrab].keycode   = key->keycode;
 
1771
    s->keyGrab[s->nKeyGrab].modifiers = modifiers;
 
1772
    s->keyGrab[s->nKeyGrab].count     = 1;
 
1773
 
 
1774
    s->nKeyGrab++;
 
1775
 
 
1776
    return TRUE;
 
1777
}
 
1778
 
 
1779
static void
 
1780
removePassiveKeyGrab (CompScreen     *s,
 
1781
                      CompKeyBinding *key)
 
1782
{
 
1783
    unsigned int modifiers, mask, ignore;
 
1784
    int          i;
 
1785
 
 
1786
    modifiers = key->modifiers & ~(CompPressMask | CompReleaseMask);
 
1787
    if (modifiers == key->modifiers)
 
1788
        return;
 
1789
 
 
1790
    for (i = 0; i < s->nKeyGrab; i++)
 
1791
    {
 
1792
        if (key->keycode == s->keyGrab[i].keycode &&
 
1793
            modifiers    == s->keyGrab[i].modifiers)
 
1794
        {
 
1795
            s->keyGrab[i].count--;
 
1796
            if (s->keyGrab[i].count)
 
1797
                return;
 
1798
 
 
1799
            s->nKeyGrab--;
 
1800
            s->keyGrab = realloc (s->keyGrab,
 
1801
                                  sizeof (CompKeyGrab) * s->nKeyGrab);
 
1802
 
 
1803
            mask = virtualToRealModMask (s->display, modifiers);
 
1804
            if (!(mask & CompNoMask))
 
1805
            {
 
1806
                for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
 
1807
                {
 
1808
                    if (ignore & ~s->display->ignoredModMask)
 
1809
                        continue;
 
1810
 
 
1811
                    XUngrabKey (s->display->display,
 
1812
                                key->keycode,
 
1813
                                mask | ignore,
 
1814
                                s->root);
 
1815
                }
 
1816
            }
 
1817
        }
 
1818
    }
 
1819
}
 
1820
 
 
1821
static void
 
1822
updatePassiveKeyGrabs (CompScreen *s)
 
1823
{
 
1824
    unsigned int mask, ignore;
 
1825
    int          i;
 
1826
 
 
1827
    XUngrabKey (s->display->display, AnyKey, AnyModifier, s->root);
 
1828
 
 
1829
    for (i = 0; i < s->nKeyGrab; i++)
 
1830
    {
 
1831
        mask = virtualToRealModMask (s->display, s->keyGrab[i].modifiers);
 
1832
        if (!(mask & CompNoMask))
 
1833
        {
 
1834
            for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
 
1835
            {
 
1836
                if (ignore & ~s->display->ignoredModMask)
 
1837
                    continue;
 
1838
 
 
1839
                XGrabKey (s->display->display,
 
1840
                          s->keyGrab[i].keycode,
 
1841
                          mask | ignore,
 
1842
                          s->root,
 
1843
                          TRUE,
 
1844
                          GrabModeAsync,
 
1845
                          GrabModeAsync);
 
1846
            }
 
1847
        }
 
1848
    }
 
1849
}
 
1850
 
 
1851
static Bool
 
1852
addPassiveButtonGrab (CompScreen        *s,
 
1853
                      CompButtonBinding *button)
 
1854
{
 
1855
    CompButtonGrab *buttonGrab;
 
1856
    unsigned int   modifiers;
 
1857
    int            i;
 
1858
 
 
1859
    modifiers = button->modifiers & ~(CompPressMask | CompReleaseMask);
 
1860
    if (modifiers == button->modifiers)
 
1861
        return TRUE;
 
1862
 
 
1863
    for (i = 0; i < s->nButtonGrab; i++)
 
1864
    {
 
1865
        if (button->button  == s->buttonGrab[i].button &&
 
1866
            modifiers       == s->buttonGrab[i].modifiers)
 
1867
        {
 
1868
            s->buttonGrab[i].count++;
 
1869
            return TRUE;
 
1870
        }
 
1871
    }
 
1872
 
 
1873
    buttonGrab = realloc (s->buttonGrab,
 
1874
                          sizeof (CompButtonGrab) * (s->nButtonGrab + 1));
 
1875
    if (!buttonGrab)
 
1876
        return FALSE;
 
1877
 
 
1878
    s->buttonGrab = buttonGrab;
 
1879
 
 
1880
    s->buttonGrab[s->nButtonGrab].button    = button->button;
 
1881
    s->buttonGrab[s->nButtonGrab].modifiers = modifiers;
 
1882
    s->buttonGrab[s->nButtonGrab].count     = 1;
 
1883
 
 
1884
    s->nButtonGrab++;
 
1885
 
 
1886
    return TRUE;
 
1887
}
 
1888
 
 
1889
static void
 
1890
removePassiveButtonGrab (CompScreen        *s,
 
1891
                         CompButtonBinding *button)
 
1892
{
 
1893
    unsigned int modifiers;
 
1894
    int          i;
 
1895
 
 
1896
    modifiers = button->modifiers & ~(CompPressMask | CompReleaseMask);
 
1897
    if (modifiers == button->modifiers)
 
1898
        return;
 
1899
 
 
1900
    for (i = 0; i < s->nButtonGrab; i++)
 
1901
    {
 
1902
        if (button->button == s->buttonGrab[i].button &&
 
1903
            modifiers      == s->buttonGrab[i].modifiers)
 
1904
        {
 
1905
            s->buttonGrab[i].count--;
 
1906
            if (s->buttonGrab[i].count)
 
1907
                return;
 
1908
 
 
1909
            s->nButtonGrab--;
 
1910
            s->buttonGrab = realloc (s->buttonGrab,
 
1911
                                     sizeof (CompButtonGrab) * s->nButtonGrab);
 
1912
        }
 
1913
    }
 
1914
}
 
1915
 
 
1916
Bool
 
1917
addScreenBinding (CompScreen  *s,
 
1918
                  CompBinding *binding)
 
1919
{
 
1920
    if (binding->type == CompBindingTypeKey)
 
1921
        return addPassiveKeyGrab (s, &binding->u.key);
 
1922
    else if (binding->type == CompBindingTypeButton)
 
1923
        return addPassiveButtonGrab (s, &binding->u.button);
 
1924
 
 
1925
    return FALSE;
 
1926
}
 
1927
 
 
1928
void
 
1929
removeScreenBinding (CompScreen  *s,
 
1930
                     CompBinding *binding)
 
1931
{
 
1932
    if (binding->type == CompBindingTypeKey)
 
1933
        removePassiveKeyGrab (s, &binding->u.key);
 
1934
    else if (binding->type == CompBindingTypeButton)
 
1935
        removePassiveButtonGrab (s, &binding->u.button);
 
1936
}
 
1937
 
 
1938
void
 
1939
updatePassiveGrabs (CompScreen *s)
 
1940
{
 
1941
    updatePassiveKeyGrabs (s);
 
1942
}
 
1943
 
 
1944
void
 
1945
updateWorkareaForScreen (CompScreen *s)
 
1946
{
 
1947
    CompWindow *w;
 
1948
    int        leftStrut, rightStrut, topStrut, bottomStrut;
 
1949
    XRectangle workArea;
 
1950
 
 
1951
    leftStrut   = 0;
 
1952
    rightStrut  = 0;
 
1953
    topStrut    = 0;
 
1954
    bottomStrut = 0;
 
1955
 
 
1956
    for (w = s->windows; w; w = w->next)
 
1957
    {
 
1958
        if (w->attrib.map_state == IsUnmapped)
 
1959
            continue;
 
1960
 
 
1961
        if (w->struts)
 
1962
        {
 
1963
            if (w->struts->left.width > leftStrut)
 
1964
                leftStrut = w->struts->left.width;
 
1965
 
 
1966
            if (w->struts->right.width > rightStrut)
 
1967
                rightStrut = w->struts->right.width;
 
1968
 
 
1969
            if (w->struts->top.height > topStrut)
 
1970
                topStrut = w->struts->top.height;
 
1971
 
 
1972
            if (w->struts->bottom.height > bottomStrut)
 
1973
                bottomStrut = w->struts->bottom.height;
 
1974
        }
 
1975
    }
 
1976
 
 
1977
#define MIN_SANE_AREA 100
 
1978
 
 
1979
    if ((leftStrut + rightStrut) > (s->width - MIN_SANE_AREA))
 
1980
    {
 
1981
        leftStrut  = (s->width - MIN_SANE_AREA) / 2;
 
1982
        rightStrut = leftStrut;
 
1983
    }
 
1984
 
 
1985
    if ((topStrut + bottomStrut) > (s->height - MIN_SANE_AREA))
 
1986
    {
 
1987
        topStrut    = (s->height - MIN_SANE_AREA) / 2;
 
1988
        bottomStrut = topStrut;
 
1989
    }
 
1990
 
 
1991
    workArea.x      = leftStrut;
 
1992
    workArea.y      = topStrut;
 
1993
    workArea.width  = s->width  - leftStrut - rightStrut;
 
1994
    workArea.height = s->height - topStrut  - bottomStrut;
 
1995
 
 
1996
    if (memcmp (&workArea, &s->workArea, sizeof (XRectangle)))
 
1997
    {
 
1998
        unsigned long data[4];
 
1999
 
 
2000
        data[0] = workArea.x;
 
2001
        data[1] = workArea.y;
 
2002
        data[2] = workArea.width;
 
2003
        data[3] = workArea.height;
 
2004
 
 
2005
        XChangeProperty (s->display->display, s->root,
 
2006
                         s->display->workareaAtom, XA_CARDINAL, 32,
 
2007
                         PropModeReplace, (unsigned char *) data, 4);
 
2008
 
 
2009
        s->workArea = workArea;
 
2010
    }
 
2011
}
 
2012
 
 
2013
static Bool
 
2014
isClientListWindow (CompWindow *w)
 
2015
{
 
2016
    if (w->attrib.override_redirect)
 
2017
        return FALSE;
 
2018
 
 
2019
    if (w->attrib.map_state != IsViewable)
 
2020
    {
 
2021
        if (!(w->state & CompWindowStateHiddenMask))
 
2022
            return FALSE;
 
2023
    }
 
2024
 
 
2025
    if (w->type & CompWindowTypeNormalMask)
 
2026
        return TRUE;
 
2027
 
 
2028
    return FALSE;
 
2029
}
 
2030
 
 
2031
static void
 
2032
countClientListWindow (CompWindow *w,
 
2033
                       void       *closure)
 
2034
{
 
2035
    if (isClientListWindow (w))
 
2036
    {
 
2037
        int *num = (int *) closure;
 
2038
 
 
2039
        *num = *num + 1;
 
2040
    }
 
2041
}
 
2042
 
 
2043
static void
 
2044
addClientListWindow (CompWindow *w,
 
2045
                     void       *closure)
 
2046
{
 
2047
    if (isClientListWindow (w))
 
2048
    {
 
2049
        int *num = (int *) closure;
 
2050
 
 
2051
        w->screen->clientList[*num] = w;
 
2052
        *num = *num + 1;
 
2053
    }
 
2054
}
 
2055
 
 
2056
static int
 
2057
compareMappingOrder (const void *w1,
 
2058
                     const void *w2)
 
2059
{
 
2060
    return (*((CompWindow **) w1))->mapNum - (*((CompWindow **) w2))->mapNum;
 
2061
}
 
2062
 
 
2063
void
 
2064
updateClientListForScreen (CompScreen *s)
 
2065
{
 
2066
    Window *clientList;
 
2067
    Window *clientListStacking;
 
2068
    Bool   updateClientList = FALSE;
 
2069
    Bool   updateClientListStacking = FALSE;
 
2070
    int    i, n = 0;
 
2071
 
 
2072
    forEachWindowOnScreen (s, countClientListWindow, (void *) &n);
 
2073
 
 
2074
    if (n == 0)
 
2075
    {
 
2076
        if (n != s->nClientList)
 
2077
        {
 
2078
            free (s->clientList);
 
2079
 
 
2080
            s->clientList  = NULL;
 
2081
            s->nClientList = 0;
 
2082
 
 
2083
            XChangeProperty (s->display->display, s->root,
 
2084
                             s->display->clientListAtom,
 
2085
                             XA_WINDOW, 32, PropModeReplace,
 
2086
                             (unsigned char *) &s->grabWindow, 1);
 
2087
            XChangeProperty (s->display->display, s->root,
 
2088
                             s->display->clientListStackingAtom,
 
2089
                             XA_WINDOW, 32, PropModeReplace,
 
2090
                             (unsigned char *) &s->grabWindow, 1);
 
2091
        }
 
2092
 
 
2093
        return;
 
2094
    }
 
2095
 
 
2096
    if (n != s->nClientList)
 
2097
    {
 
2098
        CompWindow **list;
 
2099
 
 
2100
        list = realloc (s->clientList,
 
2101
                        (sizeof (CompWindow *) + sizeof (Window) * 2) * n);
 
2102
        if (!list)
 
2103
            return;
 
2104
 
 
2105
        s->clientList  = list;
 
2106
        s->nClientList = n;
 
2107
 
 
2108
        updateClientList = updateClientListStacking = TRUE;
 
2109
    }
 
2110
 
 
2111
    clientList         = (Window *) (s->clientList + n);
 
2112
    clientListStacking = clientList + n;
 
2113
 
 
2114
    i = 0;
 
2115
    forEachWindowOnScreen (s, addClientListWindow, (void *) &i);
 
2116
 
 
2117
    for (i = 0; i < n; i++)
 
2118
    {
 
2119
        if (!updateClientListStacking)
 
2120
        {
 
2121
            if (clientListStacking[i] != s->clientList[i]->id)
 
2122
                updateClientListStacking = TRUE;
 
2123
        }
 
2124
 
 
2125
        clientListStacking[i] = s->clientList[i]->id;
 
2126
    }
 
2127
 
 
2128
    /* sort window list in mapping order */
 
2129
    qsort (s->clientList, n, sizeof (CompWindow *), compareMappingOrder);
 
2130
 
 
2131
    for (i = 0; i < n; i++)
 
2132
    {
 
2133
        if (!updateClientList)
 
2134
        {
 
2135
            if (clientList[i] != s->clientList[i]->id)
 
2136
                updateClientList = TRUE;
 
2137
        }
 
2138
 
 
2139
        clientList[i] = s->clientList[i]->id;
 
2140
    }
 
2141
 
 
2142
    if (updateClientList)
 
2143
        XChangeProperty (s->display->display, s->root,
 
2144
                         s->display->clientListAtom,
 
2145
                         XA_WINDOW, 32, PropModeReplace,
 
2146
                         (unsigned char *) clientList, s->nClientList);
 
2147
 
 
2148
    if (updateClientListStacking)
 
2149
        XChangeProperty (s->display->display, s->root,
 
2150
                         s->display->clientListStackingAtom,
 
2151
                         XA_WINDOW, 32, PropModeReplace,
 
2152
                         (unsigned char *) clientListStacking, s->nClientList);
 
2153
}
 
2154
 
 
2155
Window
 
2156
getActiveWindow (CompDisplay *display,
 
2157
                 Window      root)
 
2158
{
 
2159
    Atom          actual;
 
2160
    int           result, format;
 
2161
    unsigned long n, left;
 
2162
    unsigned char *data;
 
2163
    Window        w = None;
 
2164
 
 
2165
    result = XGetWindowProperty (display->display, root,
 
2166
                                 display->winActiveAtom, 0L, 1L, FALSE,
 
2167
                                 XA_WINDOW, &actual, &format,
 
2168
                                 &n, &left, &data);
 
2169
 
 
2170
    if (result == Success && n && data)
 
2171
    {
 
2172
        memcpy (&w, data, sizeof (Window));
 
2173
        XFree (data);
 
2174
    }
 
2175
 
 
2176
    return w;
 
2177
}
 
2178
 
 
2179
void
 
2180
closeActiveWindow (CompScreen *s)
 
2181
{
 
2182
    CompWindow *w;
 
2183
 
 
2184
    w = findWindowAtDisplay (s->display, s->display->activeWindow);
 
2185
    if (w)
 
2186
        closeWindow (w);
 
2187
}
 
2188
 
 
2189
void
 
2190
panelAction (CompScreen *s,
 
2191
             Atom       panelAction)
 
2192
{
 
2193
    XEvent ev;
 
2194
 
 
2195
    ev.type                 = ClientMessage;
 
2196
    ev.xclient.window       = s->root;
 
2197
    ev.xclient.message_type = s->display->panelActionAtom;
 
2198
    ev.xclient.format       = 32;
 
2199
    ev.xclient.data.l[0]    = panelAction;
 
2200
    ev.xclient.data.l[1]    = CurrentTime;
 
2201
    ev.xclient.data.l[2]    = 0;
 
2202
    ev.xclient.data.l[3]    = 0;
 
2203
    ev.xclient.data.l[4]    = 0;
 
2204
 
 
2205
    XUngrabPointer (s->display->display, CurrentTime);
 
2206
    XUngrabKeyboard (s->display->display, CurrentTime);
 
2207
 
 
2208
    XSendEvent (s->display->display, s->root, FALSE, StructureNotifyMask, &ev);
 
2209
}
 
2210
 
 
2211
void
 
2212
runCommand (CompScreen *s,
 
2213
            const char *command)
 
2214
{
 
2215
    if (*command == '\0')
 
2216
        return;
 
2217
 
 
2218
    if (fork () == 0)
 
2219
    {
 
2220
        setsid ();
 
2221
        putenv (s->display->displayString);
 
2222
        execl ("/bin/sh", "/bin/sh", "-c", command, NULL);
 
2223
        exit (0);
 
2224
    }
 
2225
}
 
2226
 
 
2227
void
 
2228
moveScreenViewport (CompScreen *s,
 
2229
                    int        tx,
 
2230
                    Bool       sync)
 
2231
{
 
2232
    tx = s->x - tx;
 
2233
    tx = MOD (tx, s->size);
 
2234
    tx -= s->x;
 
2235
 
 
2236
    if (tx)
 
2237
    {
 
2238
        CompWindow *w;
 
2239
        int        m, wx, vWidth = s->width * s->size;
 
2240
 
 
2241
        s->x += tx;
 
2242
 
 
2243
        tx *= -s->width;
 
2244
 
 
2245
        for (w = s->windows; w; w = w->next)
 
2246
        {
 
2247
            if (w->attrib.map_state != IsViewable)
 
2248
                continue;
 
2249
 
 
2250
            if (w->attrib.override_redirect)
 
2251
                continue;
 
2252
 
 
2253
            if (w->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
 
2254
                continue;
 
2255
 
 
2256
            if (w->state & CompWindowStateStickyMask)
 
2257
                continue;
 
2258
 
 
2259
            m = w->attrib.x + tx;
 
2260
            if (m - w->output.left < s->width - vWidth)
 
2261
                wx = tx + vWidth;
 
2262
            else if (m + w->width + w->output.right > vWidth)
 
2263
                wx = tx - vWidth;
 
2264
            else
 
2265
                wx = tx;
 
2266
 
 
2267
            if (w->saveMask & CWX)
 
2268
                w->saveWc.x += wx;
 
2269
 
 
2270
            moveWindow (w, wx, 0, sync);
 
2271
 
 
2272
            if (sync)
 
2273
                syncWindowPosition (w);
 
2274
        }
 
2275
 
 
2276
        if (sync)
 
2277
        {
 
2278
            unsigned long data[2];
 
2279
 
 
2280
            data[0] = s->x * s->width;
 
2281
            data[1] = 0;
 
2282
 
 
2283
            XChangeProperty (s->display->display, s->root,
 
2284
                             s->display->desktopViewportAtom,
 
2285
                             XA_CARDINAL, 32, PropModeReplace,
 
2286
                             (unsigned char *) data, 2);
 
2287
        }
 
2288
    }
 
2289
}
 
2290
 
 
2291
void
 
2292
moveWindowToViewportPosition (CompWindow *w,
 
2293
                              int        x,
 
2294
                              Bool       sync)
 
2295
{
 
2296
    int tx, vWidth = w->screen->width * w->screen->size;
 
2297
 
 
2298
    x += w->screen->x * w->screen->width;
 
2299
    x = MOD (x, vWidth);
 
2300
    x -= w->screen->x * w->screen->width;
 
2301
 
 
2302
    tx = x - w->attrib.x;
 
2303
    if (tx)
 
2304
    {
 
2305
        int m, wx;
 
2306
 
 
2307
        if (w->attrib.map_state != IsViewable)
 
2308
            return;
 
2309
 
 
2310
        if (w->attrib.override_redirect)
 
2311
            return;
 
2312
 
 
2313
        if (w->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
 
2314
            return;
 
2315
 
 
2316
        if (w->state & CompWindowStateStickyMask)
 
2317
            return;
 
2318
 
 
2319
        m = w->attrib.x + tx;
 
2320
        if (m - w->output.left < w->screen->width - vWidth)
 
2321
            wx = tx + vWidth;
 
2322
        else if (m + w->width + w->output.right > vWidth)
 
2323
            wx = tx - vWidth;
 
2324
        else
 
2325
            wx = tx;
 
2326
 
 
2327
        if (w->saveMask & CWX)
 
2328
            w->saveWc.x += wx;
 
2329
 
 
2330
        moveWindow (w, wx, 0, sync);
 
2331
 
 
2332
        if (sync)
 
2333
            syncWindowPosition (w);
 
2334
    }
 
2335
}
 
2336
 
 
2337
CompGroup *
 
2338
addGroupToScreen (CompScreen *s,
 
2339
                  Window     id)
 
2340
{
 
2341
    CompGroup *group;
 
2342
 
 
2343
    group = malloc (sizeof (CompGroup));
 
2344
    if (!group)
 
2345
        return NULL;
 
2346
 
 
2347
    group->next   = s->groups;
 
2348
    group->refCnt = 1;
 
2349
    group->id     = id;
 
2350
 
 
2351
    s->groups = group;
 
2352
 
 
2353
    return group;
 
2354
}
 
2355
 
 
2356
void
 
2357
removeGroupFromScreen (CompScreen *s,
 
2358
                       CompGroup  *group)
 
2359
{
 
2360
    group->refCnt--;
 
2361
    if (group->refCnt)
 
2362
        return;
 
2363
 
 
2364
    if (group == s->groups)
 
2365
    {
 
2366
        s->groups = group->next;
 
2367
    }
 
2368
    else
 
2369
    {
 
2370
        CompGroup *g;
 
2371
 
 
2372
        for (g = s->groups; g; g = g->next)
 
2373
        {
 
2374
            if (g->next == group)
 
2375
            {
 
2376
                g->next = group->next;
 
2377
                break;
 
2378
            }
 
2379
        }
 
2380
    }
 
2381
 
 
2382
    free (group);
 
2383
}
 
2384
 
 
2385
CompGroup *
 
2386
findGroupAtScreen (CompScreen *s,
 
2387
                   Window     id)
 
2388
{
 
2389
    CompGroup *g;
 
2390
 
 
2391
    for (g = s->groups; g; g = g->next)
 
2392
        if (g->id == id)
 
2393
            return g;
 
2394
 
 
2395
    return NULL;
 
2396
}
 
2397
 
 
2398
void
 
2399
applyStartupProperties (CompScreen *screen,
 
2400
                        CompWindow *window)
 
2401
{
 
2402
    CompStartupSequence *s = NULL;
 
2403
    const char          *startupId = window->startupId;
 
2404
 
 
2405
    printf ("Applying startup props to %d id \"%s\"\n",
 
2406
            (int) window->id, window->startupId ? window->startupId : "(none)");
 
2407
 
 
2408
    if (!startupId)
 
2409
    {
 
2410
        const char *wmClass;
 
2411
 
 
2412
        for (s = screen->startupSequences; s; s = s->next)
 
2413
        {
 
2414
            wmClass = sn_startup_sequence_get_wmclass (s->sequence);
 
2415
            if (!wmClass)
 
2416
                continue;
 
2417
 
 
2418
            if ((window->resClass && strcmp (wmClass, window->resClass) == 0) ||
 
2419
                (window->resName  && strcmp (wmClass, window->resName)  == 0))
 
2420
            {
 
2421
                startupId = sn_startup_sequence_get_id (s->sequence);
 
2422
 
 
2423
                window->startupId = strdup (startupId);
 
2424
 
 
2425
                printf ("Ending legacy sequence %s due to window %d\n",
 
2426
                        startupId, (int) window->id);
 
2427
 
 
2428
                sn_startup_sequence_complete (s->sequence);
 
2429
                break;
 
2430
            }
 
2431
        }
 
2432
 
 
2433
        if (!startupId)
 
2434
            return;
 
2435
    }
 
2436
 
 
2437
    if (!s)
 
2438
    {
 
2439
        const char *id;
 
2440
 
 
2441
        for (s = screen->startupSequences; s; s = s->next)
 
2442
        {
 
2443
            id = sn_startup_sequence_get_id (s->sequence);
 
2444
 
 
2445
            if (strcmp (id, startupId) == 0)
 
2446
                break;
 
2447
        }
 
2448
    }
 
2449
 
 
2450
    if (s)
 
2451
    {
 
2452
        printf ("Found startup sequence for window %d ID \"%s\"\n",
 
2453
                (int) window->id, startupId);
 
2454
    }
 
2455
    else
 
2456
    {
 
2457
        printf ("Did not find startup sequence for window %d ID \"%s\"\n",
 
2458
                (int) window->id, startupId);
 
2459
    }
 
2460
}
 
2461
 
 
2462
void
 
2463
enterShowDesktopMode (CompScreen *s)
 
2464
{
 
2465
    CompWindow    *w;
 
2466
    unsigned long data = 1;
 
2467
 
 
2468
    s->showingDesktopMask = ~(CompWindowTypeDesktopMask |
 
2469
                              CompWindowTypeDockMask);
 
2470
 
 
2471
    for (w = s->windows; w; w = w->next)
 
2472
        hideWindow (w);
 
2473
 
 
2474
    XChangeProperty (s->display->display, s->root,
 
2475
                     s->display->showingDesktopAtom,
 
2476
                     XA_CARDINAL, 32, PropModeReplace,
 
2477
                     (unsigned char *) &data, 1);
 
2478
}
 
2479
 
 
2480
void
 
2481
leaveShowDesktopMode (CompScreen *s)
 
2482
{
 
2483
    CompWindow    *w;
 
2484
    unsigned long data = 0;
 
2485
 
 
2486
    s->showingDesktopMask = 0;
 
2487
 
 
2488
    for (w = s->windows; w; w = w->next)
 
2489
        showWindow (w);
 
2490
 
 
2491
    XChangeProperty (s->display->display, s->root,
 
2492
                     s->display->showingDesktopAtom,
 
2493
                     XA_CARDINAL, 32, PropModeReplace,
 
2494
                     (unsigned char *) &data, 1);
 
2495
}
 
2496
 
 
2497
void
 
2498
sendWindowActivationRequest (CompScreen *s,
 
2499
                             Window     id)
 
2500
{
 
2501
    XEvent xev;
 
2502
 
 
2503
    xev.xclient.type    = ClientMessage;
 
2504
    xev.xclient.display = s->display->display;
 
2505
    xev.xclient.format  = 32;
 
2506
 
 
2507
    xev.xclient.message_type = s->display->winActiveAtom;
 
2508
    xev.xclient.window       = id;
 
2509
 
 
2510
    xev.xclient.data.l[0] = 2;
 
2511
    xev.xclient.data.l[1] = 0;
 
2512
    xev.xclient.data.l[2] = 0;
 
2513
    xev.xclient.data.l[3] = 0;
 
2514
    xev.xclient.data.l[4] = 0;
 
2515
 
 
2516
    XSendEvent (s->display->display,
 
2517
                s->root,
 
2518
                FALSE,
 
2519
                SubstructureRedirectMask | SubstructureNotifyMask,
 
2520
                &xev);
 
2521
}