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

« back to all changes in this revision

Viewing changes to src/event.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
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
#include <X11/Xlib.h>
 
30
#include <X11/Xatom.h>
 
31
#include <X11/extensions/shape.h>
 
32
#include <X11/extensions/Xrandr.h>
 
33
#include <X11/extensions/Xevie.h>
 
34
 
 
35
#include <compiz.h>
 
36
 
 
37
static void
 
38
handleWindowDamageRect (CompWindow *w,
 
39
                        int        x,
 
40
                        int        y,
 
41
                        int        width,
 
42
                        int        height)
 
43
{
 
44
    REGION region;
 
45
    Bool   initial = FALSE;
 
46
 
 
47
    if (!w->damaged)
 
48
    {
 
49
        w->damaged = initial = TRUE;
 
50
        w->invisible = WINDOW_INVISIBLE (w);
 
51
    }
 
52
 
 
53
    region.extents.x1 = x;
 
54
    region.extents.y1 = y;
 
55
    region.extents.x2 = region.extents.x1 + width;
 
56
    region.extents.y2 = region.extents.y1 + height;
 
57
 
 
58
    if (!(*w->screen->damageWindowRect) (w, initial, &region.extents))
 
59
    {
 
60
        region.extents.x1 += w->attrib.x + w->attrib.border_width;
 
61
        region.extents.y1 += w->attrib.y + w->attrib.border_width;
 
62
        region.extents.x2 += w->attrib.x + w->attrib.border_width;
 
63
        region.extents.y2 += w->attrib.y + w->attrib.border_width;
 
64
 
 
65
        region.rects = &region.extents;
 
66
        region.numRects = region.size = 1;
 
67
 
 
68
        damageWindowRegion (w, &region);
 
69
 
 
70
        if (initial)
 
71
            damageWindowOutputExtents (w);
 
72
    }
 
73
}
 
74
 
 
75
void
 
76
handleSyncAlarm (CompWindow *w)
 
77
{
 
78
    if (w->syncWait)
 
79
    {
 
80
        if (w->syncWaitHandle)
 
81
        {
 
82
            compRemoveTimeout (w->syncWaitHandle);
 
83
            w->syncWaitHandle = 0;
 
84
        }
 
85
 
 
86
        if (resizeWindow (w,
 
87
                          w->syncX, w->syncY,
 
88
                          w->syncWidth, w->syncHeight,
 
89
                          w->syncBorderWidth))
 
90
        {
 
91
            XRectangle *rects;
 
92
            int        nDamage;
 
93
 
 
94
            nDamage = w->nDamage;
 
95
            rects   = w->damageRects;
 
96
            while (nDamage--)
 
97
            {
 
98
                handleWindowDamageRect (w,
 
99
                                        rects[nDamage].x,
 
100
                                        rects[nDamage].y,
 
101
                                        rects[nDamage].width,
 
102
                                        rects[nDamage].height);
 
103
            }
 
104
 
 
105
            w->nDamage = 0;
 
106
            w->syncWait = FALSE;
 
107
        }
 
108
    }
 
109
}
 
110
 
 
111
static void
 
112
moveInputFocusToOtherWindow (CompWindow *w)
 
113
{
 
114
    CompDisplay *display = w->screen->display;
 
115
 
 
116
    if (w->id == display->activeWindow)
 
117
    {
 
118
        CompWindow *ancestor;
 
119
 
 
120
        if (w->transientFor && w->transientFor != w->screen->root)
 
121
        {
 
122
            ancestor = findWindowAtDisplay (display, w->transientFor);
 
123
            if (ancestor && !(ancestor->type & (CompWindowTypeDesktopMask |
 
124
                                                CompWindowTypeDockMask)))
 
125
            {
 
126
                moveInputFocusToWindow (ancestor);
 
127
            }
 
128
            else
 
129
                focusDefaultWindow (display);
 
130
        }
 
131
        else if (w->type & (CompWindowTypeDialogMask |
 
132
                            CompWindowTypeModalDialogMask))
 
133
        {
 
134
            CompWindow *a, *focus = NULL;
 
135
 
 
136
            for (a = w->screen->reverseWindows; a; a = a->prev)
 
137
            {
 
138
                if (a->clientLeader == w->clientLeader)
 
139
                {
 
140
                    if ((*w->screen->focusWindow) (a))
 
141
                    {
 
142
                        if (focus)
 
143
                        {
 
144
                            if (a->type & (CompWindowTypeNormalMask |
 
145
                                           CompWindowTypeDialogMask |
 
146
                                           CompWindowTypeModalDialogMask))
 
147
                            {
 
148
                                if (a->activeNum > focus->activeNum)
 
149
                                    focus = a;
 
150
                            }
 
151
                        }
 
152
                        else
 
153
                            focus = a;
 
154
                    }
 
155
                }
 
156
            }
 
157
 
 
158
            if (focus && !(focus->type & (CompWindowTypeDesktopMask |
 
159
                                          CompWindowTypeDockMask)))
 
160
            {
 
161
                moveInputFocusToWindow (focus);
 
162
            }
 
163
            else
 
164
                focusDefaultWindow (display);
 
165
        }
 
166
        else
 
167
            focusDefaultWindow (display);
 
168
    }
 
169
}
 
170
 
 
171
static Bool
 
172
autoRaiseTimeout (void *closure)
 
173
{
 
174
    CompDisplay *display = closure;
 
175
 
 
176
    if (display->autoRaiseWindow == display->activeWindow)
 
177
    {
 
178
        CompWindow *w;
 
179
 
 
180
        w = findWindowAtDisplay (display, display->autoRaiseWindow);
 
181
        if (w)
 
182
            updateWindowAttributes (w);
 
183
    }
 
184
 
 
185
    return FALSE;
 
186
}
 
187
 
 
188
void
 
189
handleEvent (CompDisplay *display,
 
190
             XEvent      *event)
 
191
{
 
192
    CompScreen *s;
 
193
    CompWindow *w;
 
194
 
 
195
    switch (event->type) {
 
196
    case Expose:
 
197
        s = findScreenAtDisplay (display, event->xexpose.window);
 
198
        if (s)
 
199
        {
 
200
            int more = event->xexpose.count + 1;
 
201
 
 
202
            if (s->nExpose == s->sizeExpose)
 
203
            {
 
204
                if (s->exposeRects)
 
205
                {
 
206
                    s->exposeRects = realloc (s->exposeRects,
 
207
                                              (s->sizeExpose + more) *
 
208
                                              sizeof (XRectangle));
 
209
                    s->sizeExpose += more;
 
210
                }
 
211
                else
 
212
                {
 
213
                    s->exposeRects = malloc (more * sizeof (XRectangle));
 
214
                    s->sizeExpose = more;
 
215
                }
 
216
            }
 
217
 
 
218
            s->exposeRects[s->nExpose].x      = event->xexpose.x;
 
219
            s->exposeRects[s->nExpose].y      = event->xexpose.y;
 
220
            s->exposeRects[s->nExpose].width  = event->xexpose.width;
 
221
            s->exposeRects[s->nExpose].height = event->xexpose.height;
 
222
            s->nExpose++;
 
223
 
 
224
            if (event->xexpose.count == 0)
 
225
            {
 
226
                REGION rect;
 
227
 
 
228
                rect.rects = &rect.extents;
 
229
                rect.numRects = rect.size = 1;
 
230
 
 
231
                while (s->nExpose--)
 
232
                {
 
233
                    rect.extents.x1 = s->exposeRects[s->nExpose].x;
 
234
                    rect.extents.y1 = s->exposeRects[s->nExpose].y;
 
235
                    rect.extents.x2 = rect.extents.x1 +
 
236
                        s->exposeRects[s->nExpose].width;
 
237
                    rect.extents.y2 = rect.extents.y1 +
 
238
                        s->exposeRects[s->nExpose].height;
 
239
 
 
240
                    damageScreenRegion (s, &rect);
 
241
                }
 
242
                s->nExpose = 0;
 
243
            }
 
244
        }
 
245
        break;
 
246
    case SelectionRequest:
 
247
        handleSelectionRequest (display, event);
 
248
        break;
 
249
    case SelectionClear:
 
250
        handleSelectionClear (display, event);
 
251
        break;
 
252
    case ConfigureNotify:
 
253
        w = findWindowAtDisplay (display, event->xconfigure.window);
 
254
        if (w)
 
255
        {
 
256
            configureWindow (w, &event->xconfigure);
 
257
        }
 
258
        else
 
259
        {
 
260
            s = findScreenAtDisplay (display, event->xconfigure.window);
 
261
            if (s)
 
262
                configureScreen (s, &event->xconfigure);
 
263
        }
 
264
        break;
 
265
    case CreateNotify:
 
266
        s = findScreenAtDisplay (display, event->xcreatewindow.parent);
 
267
        if (s)
 
268
        {
 
269
            addWindow (s, event->xcreatewindow.window,
 
270
                       s->reverseWindows ? s->reverseWindows->id : 0);
 
271
        }
 
272
        break;
 
273
    case DestroyNotify:
 
274
        w = findWindowAtDisplay (display, event->xdestroywindow.window);
 
275
        if (w)
 
276
        {
 
277
            destroyWindow (w);
 
278
            moveInputFocusToOtherWindow (w);
 
279
        }
 
280
        break;
 
281
    case MapNotify:
 
282
        w = findWindowAtDisplay (display, event->xmap.window);
 
283
        if (w)
 
284
            mapWindow (w);
 
285
        break;
 
286
    case UnmapNotify:
 
287
        w = findWindowAtDisplay (display, event->xunmap.window);
 
288
        if (w)
 
289
        {
 
290
            unmapWindow (w);
 
291
            moveInputFocusToOtherWindow (w);
 
292
        }
 
293
        break;
 
294
    case ReparentNotify:
 
295
        s = findScreenAtDisplay (display, event->xreparent.parent);
 
296
        if (s)
 
297
        {
 
298
            addWindow (s, event->xreparent.window, 0);
 
299
        }
 
300
        else
 
301
        {
 
302
            w = findWindowAtDisplay (display, event->xreparent.window);
 
303
            if (w)
 
304
            {
 
305
                destroyWindow (w);
 
306
                moveInputFocusToOtherWindow (w);
 
307
            }
 
308
        }
 
309
        break;
 
310
    case CirculateNotify:
 
311
        w = findWindowAtDisplay (display, event->xcirculate.window);
 
312
        if (w)
 
313
            circulateWindow (w, &event->xcirculate);
 
314
        break;
 
315
    case ButtonPress:
 
316
        if (!display->screens->maxGrab)
 
317
            XAllowEvents (display->display, ReplayPointer, event->xbutton.time);
 
318
 
 
319
        s = findScreenAtDisplay (display, event->xbutton.root);
 
320
        if (s)
 
321
        {
 
322
            if (event->xbutton.button == Button1 ||
 
323
                event->xbutton.button == Button3)
 
324
            {
 
325
                w = findTopLevelWindowAtScreen (s, event->xbutton.window);
 
326
                if (w)
 
327
                    activateWindow (w);
 
328
            }
 
329
 
 
330
            if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW], event))
 
331
                closeActiveWindow (s);
 
332
 
 
333
            if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_MAIN_MENU], event))
 
334
                panelAction (s, s->display->panelActionMainMenuAtom);
 
335
 
 
336
            if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_DIALOG], event))
 
337
                panelAction (s, s->display->panelActionRunDialogAtom);
 
338
 
 
339
            if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND0], event))
 
340
                runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND0].value.s);
 
341
 
 
342
            if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND1], event))
 
343
                runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND1].value.s);
 
344
        }
 
345
        break;
 
346
    case ButtonRelease:
 
347
        break;
 
348
    case KeyPress:
 
349
        s = findScreenAtDisplay (display, event->xkey.root);
 
350
        if (s)
 
351
        {
 
352
            if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW], event))
 
353
                closeActiveWindow (s);
 
354
 
 
355
            if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_MAIN_MENU], event))
 
356
                panelAction (s, s->display->panelActionMainMenuAtom);
 
357
 
 
358
            if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_DIALOG], event))
 
359
                panelAction (s, s->display->panelActionRunDialogAtom);
 
360
 
 
361
            if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND0], event))
 
362
                runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND0].value.s);
 
363
 
 
364
            if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND1], event))
 
365
                runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND1].value.s);
 
366
        }
 
367
        break;
 
368
    case KeyRelease:
 
369
        break;
 
370
    case PropertyNotify:
 
371
        if (event->xproperty.atom == display->winActiveAtom)
 
372
        {
 
373
            Window newActiveWindow;
 
374
 
 
375
            newActiveWindow = getActiveWindow (display, event->xproperty.window);
 
376
            if (newActiveWindow != display->activeWindow)
 
377
            {
 
378
                display->activeWindow = newActiveWindow;
 
379
 
 
380
                s = findScreenAtDisplay (display, event->xproperty.window);
 
381
                if (s)
 
382
                {
 
383
                    w = findWindowAtDisplay (display, newActiveWindow);
 
384
                    if (w)
 
385
                        w->activeNum = s->activeNum++;
 
386
                }
 
387
            }
 
388
        }
 
389
        else if (event->xproperty.atom == display->winTypeAtom)
 
390
        {
 
391
            w = findWindowAtDisplay (display, event->xproperty.window);
 
392
            if (w)
 
393
            {
 
394
                unsigned int type;
 
395
 
 
396
                type = getWindowType (display, w->id);
 
397
 
 
398
                if (type != w->wmType)
 
399
                {
 
400
                    if (w->attrib.map_state == IsViewable)
 
401
                    {
 
402
                        if (w->type == CompWindowTypeDesktopMask)
 
403
                            w->screen->desktopWindowCount--;
 
404
                        else if (type == CompWindowTypeDesktopMask)
 
405
                            w->screen->desktopWindowCount++;
 
406
                    }
 
407
 
 
408
                    w->wmType = type;
 
409
 
 
410
                    recalcWindowType (w);
 
411
 
 
412
                    if (w->type & CompWindowTypeDesktopMask)
 
413
                        w->paint.opacity = OPAQUE;
 
414
                }
 
415
            }
 
416
        }
 
417
        else if (event->xproperty.atom == display->winStateAtom)
 
418
        {
 
419
            w = findWindowAtDisplay (display, event->xproperty.window);
 
420
            if (w)
 
421
            {
 
422
                unsigned int state;
 
423
 
 
424
                state = getWindowState (display, w->id);
 
425
 
 
426
                if (state != w->state)
 
427
                {
 
428
                    w->state = state;
 
429
 
 
430
                    recalcWindowType (w);
 
431
 
 
432
                    if (w->type & CompWindowTypeDesktopMask)
 
433
                        w->paint.opacity = OPAQUE;
 
434
                }
 
435
            }
 
436
        }
 
437
        else if (event->xproperty.atom == XA_WM_NORMAL_HINTS)
 
438
        {
 
439
            w = findWindowAtDisplay (display, event->xproperty.window);
 
440
            if (w)
 
441
                updateNormalHints (w);
 
442
        }
 
443
        else if (event->xproperty.atom == XA_WM_HINTS)
 
444
        {
 
445
            w = findWindowAtDisplay (display, event->xproperty.window);
 
446
            if (w)
 
447
                updateWmHints (w);
 
448
        }
 
449
        else if (event->xproperty.atom == XA_WM_TRANSIENT_FOR)
 
450
        {
 
451
            w = findWindowAtDisplay (display, event->xproperty.window);
 
452
            if (w)
 
453
                XGetTransientForHint (display->display,
 
454
                                      w->id, &w->transientFor);
 
455
        }
 
456
        else if (event->xproperty.atom == display->wmClientLeaderAtom)
 
457
        {
 
458
            w = findWindowAtDisplay (display, event->xproperty.window);
 
459
            if (w)
 
460
                w->clientLeader = getClientLeader (w);
 
461
        }
 
462
        else if (event->xproperty.atom == display->winOpacityAtom)
 
463
        {
 
464
            w = findWindowAtDisplay (display, event->xproperty.window);
 
465
            if (w && (w->type & CompWindowTypeDesktopMask) == 0)
 
466
            {
 
467
                GLushort opacity;
 
468
 
 
469
                opacity = getWindowProp32 (display, w->id,
 
470
                                           display->winOpacityAtom,
 
471
                                           OPAQUE);
 
472
                if (opacity != w->paint.opacity)
 
473
                {
 
474
                    w->paint.opacity = opacity;
 
475
                    addWindowDamage (w);
 
476
                }
 
477
            }
 
478
        }
 
479
        else if (event->xproperty.atom == display->winBrightnessAtom)
 
480
        {
 
481
            w = findWindowAtDisplay (display, event->xproperty.window);
 
482
            if (w)
 
483
            {
 
484
                GLushort brightness;
 
485
 
 
486
                brightness = getWindowProp32 (display, w->id,
 
487
                                              display->winBrightnessAtom,
 
488
                                              BRIGHT);
 
489
                if (brightness != w->paint.brightness)
 
490
                {
 
491
                    w->paint.brightness = brightness;
 
492
                    addWindowDamage (w);
 
493
                }
 
494
            }
 
495
        }
 
496
        else if (event->xproperty.atom == display->winSaturationAtom)
 
497
        {
 
498
            w = findWindowAtDisplay (display, event->xproperty.window);
 
499
            if (w && w->screen->canDoSaturated)
 
500
            {
 
501
                GLushort saturation;
 
502
 
 
503
                saturation = getWindowProp32 (display, w->id,
 
504
                                              display->winSaturationAtom,
 
505
                                              COLOR);
 
506
                if (saturation != w->saturation)
 
507
                {
 
508
                    w->saturation = saturation;
 
509
                    if (w->alive)
 
510
                    {
 
511
                        w->paint.saturation = w->saturation;
 
512
                        addWindowDamage (w);
 
513
                    }
 
514
                }
 
515
            }
 
516
        }
 
517
        else if (event->xproperty.atom == display->xBackgroundAtom[0] ||
 
518
                 event->xproperty.atom == display->xBackgroundAtom[1])
 
519
        {
 
520
            s = findScreenAtDisplay (display, event->xproperty.window);
 
521
            if (s)
 
522
            {
 
523
                finiTexture (s, &s->backgroundTexture);
 
524
                initTexture (s, &s->backgroundTexture);
 
525
 
 
526
                damageScreen (s);
 
527
            }
 
528
        }
 
529
        else if (event->xproperty.atom == display->wmStrutAtom ||
 
530
                 event->xproperty.atom == display->wmStrutPartialAtom)
 
531
        {
 
532
            w = findWindowAtDisplay (display, event->xproperty.window);
 
533
            if (w)
 
534
            {
 
535
                if (updateWindowStruts (w))
 
536
                    updateWorkareaForScreen (w->screen);
 
537
            }
 
538
        }
 
539
        else if (event->xproperty.atom == display->mwmHintsAtom)
 
540
        {
 
541
            w = findWindowAtDisplay (display, event->xproperty.window);
 
542
            if (w)
 
543
            {
 
544
                w->mwmDecor = getMwmDecor (w->screen->display, w->id);
 
545
 
 
546
                updateWindowAttributes (w);
 
547
            }
 
548
        }
 
549
        else if (event->xproperty.atom == display->wmProtocolsAtom)
 
550
        {
 
551
            w = findWindowAtDisplay (display, event->xproperty.window);
 
552
            if (w)
 
553
                w->protocols = getProtocols (w->screen->display, w->id);
 
554
        }
 
555
        break;
 
556
    case MotionNotify:
 
557
        break;
 
558
    case ClientMessage:
 
559
        if (event->xclient.message_type == display->winActiveAtom)
 
560
        {
 
561
            w = findWindowAtDisplay (display, event->xclient.window);
 
562
            if (w)
 
563
                activateWindow (w);
 
564
        }
 
565
        else if (event->xclient.message_type == display->winOpacityAtom)
 
566
        {
 
567
            w = findWindowAtDisplay (display, event->xclient.window);
 
568
            if (w && (w->type & CompWindowTypeDesktopMask) == 0)
 
569
            {
 
570
                GLushort opacity;
 
571
 
 
572
                opacity = event->xclient.data.l[0] >> 16;
 
573
                if (opacity != w->paint.opacity)
 
574
                {
 
575
                    w->paint.opacity = opacity;
 
576
 
 
577
                    setWindowProp32 (display, w->id, display->winOpacityAtom,
 
578
                                     w->paint.opacity);
 
579
                    addWindowDamage (w);
 
580
                }
 
581
            }
 
582
        }
 
583
        else if (event->xclient.message_type == display->winBrightnessAtom)
 
584
        {
 
585
            w = findWindowAtDisplay (display, event->xclient.window);
 
586
            if (w)
 
587
            {
 
588
                GLushort brightness;
 
589
 
 
590
                brightness = event->xclient.data.l[0] >> 16;
 
591
                if (brightness != w->paint.brightness)
 
592
                {
 
593
                    w->paint.brightness = brightness;
 
594
 
 
595
                    setWindowProp32 (display, w->id, display->winBrightnessAtom,
 
596
                                     w->paint.brightness);
 
597
                    addWindowDamage (w);
 
598
                }
 
599
            }
 
600
        }
 
601
        else if (event->xclient.message_type == display->winSaturationAtom)
 
602
        {
 
603
            w = findWindowAtDisplay (display, event->xclient.window);
 
604
            if (w && w->screen->canDoSaturated)
 
605
            {
 
606
                GLushort saturation;
 
607
 
 
608
                saturation = event->xclient.data.l[0] >> 16;
 
609
                if (saturation != w->saturation)
 
610
                {
 
611
                    w->saturation = saturation;
 
612
 
 
613
                    setWindowProp32 (display, w->id, display->winSaturationAtom,
 
614
                                     w->saturation);
 
615
 
 
616
                    if (w->alive)
 
617
                    {
 
618
                        w->paint.saturation = w->saturation;
 
619
                        addWindowDamage (w);
 
620
                    }
 
621
                }
 
622
            }
 
623
        }
 
624
        else if (event->xclient.message_type == display->winStateAtom)
 
625
        {
 
626
            w = findWindowAtDisplay (display, event->xclient.window);
 
627
            if (w)
 
628
            {
 
629
                unsigned long wState, state;
 
630
                int           i;
 
631
 
 
632
                wState = w->state;
 
633
 
 
634
                for (i = 1; i < 3; i++)
 
635
                {
 
636
                    state = windowStateMask (display, event->xclient.data.l[i]);
 
637
                    if (state & ~CompWindowStateHiddenMask)
 
638
                    {
 
639
 
 
640
#define _NET_WM_STATE_REMOVE 0
 
641
#define _NET_WM_STATE_ADD    1
 
642
#define _NET_WM_STATE_TOGGLE 2
 
643
 
 
644
                        switch (event->xclient.data.l[0]) {
 
645
                        case _NET_WM_STATE_REMOVE:
 
646
                            wState &= ~state;
 
647
                            break;
 
648
                        case _NET_WM_STATE_ADD:
 
649
                            wState |= state;
 
650
                            break;
 
651
                        case _NET_WM_STATE_TOGGLE:
 
652
                            wState ^= state;
 
653
                            break;
 
654
                        }
 
655
                    }
 
656
                }
 
657
 
 
658
                if (wState != w->state)
 
659
                {
 
660
                    w->state = wState;
 
661
 
 
662
                    recalcWindowType (w);
 
663
 
 
664
                    if (!w->attrib.override_redirect)
 
665
                        updateWindowAttributes (w);
 
666
 
 
667
                    setWindowState (display, wState, w->id);
 
668
                }
 
669
            }
 
670
        }
 
671
        else if (event->xclient.message_type == display->wmProtocolsAtom)
 
672
        {
 
673
            if (event->xclient.data.l[0] == display->wmPingAtom)
 
674
            {
 
675
                w = findWindowAtDisplay (display, event->xclient.data.l[2]);
 
676
                if (w)
 
677
                {
 
678
                    if (!w->alive)
 
679
                    {
 
680
                        w->alive            = TRUE;
 
681
                        w->paint.saturation = w->saturation;
 
682
 
 
683
                        addWindowDamage (w);
 
684
                    }
 
685
                    w->lastPong = display->lastPing;
 
686
                }
 
687
            }
 
688
        }
 
689
        else if (event->xclient.message_type == display->closeWindowAtom)
 
690
        {
 
691
            w = findWindowAtDisplay (display, event->xclient.window);
 
692
            if (w)
 
693
                closeWindow (w);
 
694
        }
 
695
        else if (event->xclient.message_type == display->desktopGeometryAtom)
 
696
        {
 
697
            s = findScreenAtDisplay (display, event->xclient.window);
 
698
            if (s)
 
699
            {
 
700
                CompOptionValue value;
 
701
 
 
702
                value.i = event->xclient.data.l[0] / s->width;
 
703
 
 
704
                (*s->setScreenOption) (s, "size", &value);
 
705
            }
 
706
        }
 
707
        else if (event->xclient.message_type == display->moveResizeWindowAtom)
 
708
        {
 
709
            unsigned int   xwcm = 0;
 
710
            XWindowChanges xwc;
 
711
 
 
712
            if (event->xclient.data.l[0] & (1 << 7))
 
713
            {
 
714
                xwcm |= CWX;
 
715
                xwc.x = event->xclient.data.l[1];
 
716
            }
 
717
 
 
718
            if (event->xclient.data.l[0] & (1 << 8))
 
719
            {
 
720
                xwcm |= CWY;
 
721
                xwc.y = event->xclient.data.l[2];
 
722
            }
 
723
 
 
724
            if (event->xclient.data.l[0] & (1 << 9))
 
725
            {
 
726
                xwcm |= CWWidth;
 
727
                xwc.width = event->xclient.data.l[3];
 
728
            }
 
729
 
 
730
            if (event->xclient.data.l[0] & (1 << 10))
 
731
            {
 
732
                xwcm |= CWHeight;
 
733
                xwc.height = event->xclient.data.l[4];
 
734
            }
 
735
 
 
736
            /* TODO: gravity */
 
737
 
 
738
            if (xwcm & (CWX | CWY))
 
739
            {
 
740
                w = findWindowAtDisplay (display, event->xclient.window);
 
741
                if (w)
 
742
                {
 
743
                    if (xwcm & CWX)
 
744
                        xwc.x += w->input.left;
 
745
 
 
746
                    if (xwcm & CWY)
 
747
                        xwc.y += w->input.top;
 
748
                }
 
749
            }
 
750
 
 
751
            XConfigureWindow (display->display,
 
752
                              event->xclient.window,
 
753
                              xwcm, &xwc);
 
754
        }
 
755
        else if (event->xclient.message_type == display->wmChangeStateAtom)
 
756
        {
 
757
            w = findWindowAtDisplay (display, event->xclient.window);
 
758
            if (w && w->type & CompWindowTypeNormalMask)
 
759
            {
 
760
                if (event->xclient.data.l[0] == IconicState)
 
761
                    minimizeWindow (w);
 
762
                else if (event->xclient.data.l[0] == NormalState)
 
763
                    unminimizeWindow (w);
 
764
            }
 
765
        }
 
766
        else if (event->xclient.message_type == display->showingDesktopAtom)
 
767
        {
 
768
            s = findScreenAtDisplay (display, event->xclient.window);
 
769
            if (s)
 
770
            {
 
771
                if (event->xclient.data.l[0])
 
772
                    enterShowDesktopMode (s);
 
773
                else
 
774
                    leaveShowDesktopMode (s);
 
775
            }
 
776
        }
 
777
        break;
 
778
    case MappingNotify:
 
779
        updateModifierMappings (display);
 
780
        break;
 
781
    case MapRequest:
 
782
        w = findWindowAtDisplay (display, event->xmaprequest.window);
 
783
        if (w)
 
784
        {
 
785
            if (w->minimized)
 
786
                unminimizeWindow (w);
 
787
 
 
788
            if (w->screen->showingDesktopMask)
 
789
                leaveShowDesktopMode (w->screen);
 
790
 
 
791
            if (!(w->state & CompWindowStateHiddenMask))
 
792
            {
 
793
                XMapWindow (display->display, event->xmaprequest.window);
 
794
 
 
795
                updateWindowAttributes (w);
 
796
 
 
797
                if (!(w->type & (CompWindowTypeDesktopMask |
 
798
                                 CompWindowTypeDockMask)))
 
799
                    moveInputFocusToWindow (w);
 
800
            }
 
801
        }
 
802
        else
 
803
        {
 
804
            XMapWindow (display->display, event->xmaprequest.window);
 
805
        }
 
806
        break;
 
807
    case ConfigureRequest: {
 
808
          unsigned int   xwcm;
 
809
          XWindowChanges xwc;
 
810
 
 
811
          xwcm = event->xconfigurerequest.value_mask &
 
812
              (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
 
813
 
 
814
          xwc.x            = event->xconfigurerequest.x;
 
815
          xwc.y            = event->xconfigurerequest.y;
 
816
          xwc.width        = event->xconfigurerequest.width;
 
817
          xwc.height       = event->xconfigurerequest.height;
 
818
          xwc.border_width = event->xconfigurerequest.border_width;
 
819
 
 
820
            /* TODO: gravity */
 
821
 
 
822
          if (xwcm & (CWX | CWY))
 
823
          {
 
824
              w = findWindowAtDisplay (display, event->xconfigurerequest.window);
 
825
              if (w)
 
826
              {
 
827
                  xwc.x += w->input.left;
 
828
                  xwc.y += w->input.top;
 
829
              }
 
830
          }
 
831
 
 
832
          XConfigureWindow (display->display,
 
833
                            event->xconfigurerequest.window,
 
834
                            xwcm, &xwc);
 
835
    } break;
 
836
    case CirculateRequest:
 
837
        break;
 
838
    case FocusIn:
 
839
        if (event->xfocus.window != display->activeWindow &&
 
840
            event->xfocus.mode   != NotifyGrab)
 
841
        {
 
842
            w = findWindowAtDisplay (display, event->xfocus.window);
 
843
            if (w)
 
844
            {
 
845
                XChangeProperty (display->display, w->screen->root,
 
846
                                 display->winActiveAtom,
 
847
                                 XA_WINDOW, 32, PropModeReplace,
 
848
                                 (unsigned char *) &w->id, 1);
 
849
            }
 
850
        }
 
851
        break;
 
852
    case EnterNotify:
 
853
        if (!display->screens->maxGrab              &&
 
854
            event->xcrossing.mode   != NotifyGrab   &&
 
855
            event->xcrossing.detail != NotifyInferior)
 
856
        {
 
857
            Bool raise;
 
858
            int  delay;
 
859
 
 
860
            raise = display->opt[COMP_DISPLAY_OPTION_AUTORAISE].value.b;
 
861
            delay = display->opt[COMP_DISPLAY_OPTION_AUTORAISE_DELAY].value.i;
 
862
 
 
863
            s = findScreenAtDisplay (display, event->xcrossing.root);
 
864
            if (s)
 
865
                w = findTopLevelWindowAtScreen (s, event->xcrossing.window);
 
866
            else
 
867
                w = NULL;
 
868
 
 
869
            if (w && w->id != display->below)
 
870
            {
 
871
                display->below = w->id;
 
872
 
 
873
                if (!display->opt[COMP_DISPLAY_OPTION_CLICK_TO_FOCUS].value.b)
 
874
                {
 
875
                    if (display->autoRaiseHandle &&
 
876
                        display->autoRaiseWindow != w->id)
 
877
                    {
 
878
                        compRemoveTimeout (display->autoRaiseHandle);
 
879
                        display->autoRaiseHandle = 0;
 
880
                    }
 
881
 
 
882
                    if (w->type & ~(CompWindowTypeDockMask |
 
883
                                    CompWindowTypeDesktopMask))
 
884
                    {
 
885
                        moveInputFocusToWindow (w);
 
886
 
 
887
                        if (raise)
 
888
                        {
 
889
                            if (delay > 0)
 
890
                            {
 
891
                                display->autoRaiseWindow = w->id;
 
892
                                display->autoRaiseHandle =
 
893
                                    compAddTimeout (delay, autoRaiseTimeout,
 
894
                                                    display);
 
895
                            }
 
896
                            else
 
897
                                updateWindowAttributes (w);
 
898
                        }
 
899
                    }
 
900
                }
 
901
            }
 
902
        }
 
903
        break;
 
904
    case LeaveNotify:
 
905
        if (event->xcrossing.detail != NotifyInferior)
 
906
        {
 
907
            if (event->xcrossing.window == display->below)
 
908
                display->below = None;
 
909
        }
 
910
        break;
 
911
    default:
 
912
        if (event->type == display->damageEvent + XDamageNotify)
 
913
        {
 
914
            XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
 
915
 
 
916
            if (lastDamagedWindow && de->drawable == lastDamagedWindow->id)
 
917
            {
 
918
                w = lastDamagedWindow;
 
919
            }
 
920
            else
 
921
            {
 
922
                w = findWindowAtDisplay (display, de->drawable);
 
923
                if (w)
 
924
                    lastDamagedWindow = w;
 
925
            }
 
926
 
 
927
            if (w)
 
928
            {
 
929
                if (w->syncWait)
 
930
                {
 
931
                    if (w->nDamage == w->sizeDamage)
 
932
                    {
 
933
                        if (w->damageRects)
 
934
                        {
 
935
                            w->damageRects = realloc (w->damageRects,
 
936
                                                      (w->sizeDamage + 1) *
 
937
                                                      sizeof (XRectangle));
 
938
                            w->sizeDamage += 1;
 
939
                        }
 
940
                        else
 
941
                        {
 
942
                            w->damageRects = malloc (sizeof (XRectangle));
 
943
                            w->sizeDamage  = 1;
 
944
                        }
 
945
                    }
 
946
 
 
947
                    w->damageRects[w->nDamage].x      = de->area.x;
 
948
                    w->damageRects[w->nDamage].y      = de->area.y;
 
949
                    w->damageRects[w->nDamage].width  = de->area.width;
 
950
                    w->damageRects[w->nDamage].height = de->area.height;
 
951
                    w->nDamage++;
 
952
                }
 
953
                else
 
954
                {
 
955
                    handleWindowDamageRect (w,
 
956
                                            de->area.x,
 
957
                                            de->area.y,
 
958
                                            de->area.width,
 
959
                                            de->area.height);
 
960
                }
 
961
            }
 
962
        }
 
963
        else if (display->shapeExtension &&
 
964
                 event->type == display->shapeEvent + ShapeNotify)
 
965
        {
 
966
            w = findWindowAtDisplay (display, ((XShapeEvent *) event)->window);
 
967
            if (w)
 
968
            {
 
969
                if (w->mapNum)
 
970
                {
 
971
                    addWindowDamage (w);
 
972
                    updateWindowRegion (w);
 
973
                    addWindowDamage (w);
 
974
                }
 
975
            }
 
976
        }
 
977
        else if (event->type == display->randrEvent + RRScreenChangeNotify)
 
978
        {
 
979
            XRRScreenChangeNotifyEvent *rre;
 
980
 
 
981
            rre = (XRRScreenChangeNotifyEvent *) event;
 
982
 
 
983
            s = findScreenAtDisplay (display, rre->root);
 
984
            if (s)
 
985
                detectRefreshRateOfScreen (s);
 
986
        }
 
987
        else if (event->type == display->syncEvent + XSyncAlarmNotify)
 
988
        {
 
989
            XSyncAlarmNotifyEvent *sa;
 
990
 
 
991
            sa = (XSyncAlarmNotifyEvent *) event;
 
992
 
 
993
            w = NULL;
 
994
 
 
995
            for (s = display->screens; s; s = s->next)
 
996
                for (w = s->windows; w; w = w->next)
 
997
                    if (w->syncAlarm == sa->alarm)
 
998
                        break;
 
999
 
 
1000
            if (w)
 
1001
                handleSyncAlarm (w);
 
1002
        }
 
1003
        break;
 
1004
    }
 
1005
}