2
* Copyright © 2005 Novell, Inc.
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
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.
23
* Author: David Reveman <davidr@novell.com>
30
#include <X11/Xatom.h>
31
#include <X11/extensions/shape.h>
32
#include <X11/extensions/Xrandr.h>
33
#include <X11/extensions/Xevie.h>
38
handleWindowDamageRect (CompWindow *w,
49
w->damaged = initial = TRUE;
50
w->invisible = WINDOW_INVISIBLE (w);
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;
58
if (!(*w->screen->damageWindowRect) (w, initial, ®ion.extents))
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;
65
region.rects = ®ion.extents;
66
region.numRects = region.size = 1;
68
damageWindowRegion (w, ®ion);
71
damageWindowOutputExtents (w);
76
handleSyncAlarm (CompWindow *w)
80
if (w->syncWaitHandle)
82
compRemoveTimeout (w->syncWaitHandle);
83
w->syncWaitHandle = 0;
88
w->syncWidth, w->syncHeight,
95
rects = w->damageRects;
98
handleWindowDamageRect (w,
101
rects[nDamage].width,
102
rects[nDamage].height);
112
moveInputFocusToOtherWindow (CompWindow *w)
114
CompDisplay *display = w->screen->display;
116
if (w->id == display->activeWindow)
118
CompWindow *ancestor;
120
if (w->transientFor && w->transientFor != w->screen->root)
122
ancestor = findWindowAtDisplay (display, w->transientFor);
123
if (ancestor && !(ancestor->type & (CompWindowTypeDesktopMask |
124
CompWindowTypeDockMask)))
126
moveInputFocusToWindow (ancestor);
129
focusDefaultWindow (display);
131
else if (w->type & (CompWindowTypeDialogMask |
132
CompWindowTypeModalDialogMask))
134
CompWindow *a, *focus = NULL;
136
for (a = w->screen->reverseWindows; a; a = a->prev)
138
if (a->clientLeader == w->clientLeader)
140
if ((*w->screen->focusWindow) (a))
144
if (a->type & (CompWindowTypeNormalMask |
145
CompWindowTypeDialogMask |
146
CompWindowTypeModalDialogMask))
148
if (a->activeNum > focus->activeNum)
158
if (focus && !(focus->type & (CompWindowTypeDesktopMask |
159
CompWindowTypeDockMask)))
161
moveInputFocusToWindow (focus);
164
focusDefaultWindow (display);
167
focusDefaultWindow (display);
172
autoRaiseTimeout (void *closure)
174
CompDisplay *display = closure;
176
if (display->autoRaiseWindow == display->activeWindow)
180
w = findWindowAtDisplay (display, display->autoRaiseWindow);
182
updateWindowAttributes (w);
189
handleEvent (CompDisplay *display,
195
switch (event->type) {
197
s = findScreenAtDisplay (display, event->xexpose.window);
200
int more = event->xexpose.count + 1;
202
if (s->nExpose == s->sizeExpose)
206
s->exposeRects = realloc (s->exposeRects,
207
(s->sizeExpose + more) *
208
sizeof (XRectangle));
209
s->sizeExpose += more;
213
s->exposeRects = malloc (more * sizeof (XRectangle));
214
s->sizeExpose = more;
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;
224
if (event->xexpose.count == 0)
228
rect.rects = &rect.extents;
229
rect.numRects = rect.size = 1;
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;
240
damageScreenRegion (s, &rect);
246
case SelectionRequest:
247
handleSelectionRequest (display, event);
250
handleSelectionClear (display, event);
252
case ConfigureNotify:
253
w = findWindowAtDisplay (display, event->xconfigure.window);
256
configureWindow (w, &event->xconfigure);
260
s = findScreenAtDisplay (display, event->xconfigure.window);
262
configureScreen (s, &event->xconfigure);
266
s = findScreenAtDisplay (display, event->xcreatewindow.parent);
269
addWindow (s, event->xcreatewindow.window,
270
s->reverseWindows ? s->reverseWindows->id : 0);
274
w = findWindowAtDisplay (display, event->xdestroywindow.window);
278
moveInputFocusToOtherWindow (w);
282
w = findWindowAtDisplay (display, event->xmap.window);
287
w = findWindowAtDisplay (display, event->xunmap.window);
291
moveInputFocusToOtherWindow (w);
295
s = findScreenAtDisplay (display, event->xreparent.parent);
298
addWindow (s, event->xreparent.window, 0);
302
w = findWindowAtDisplay (display, event->xreparent.window);
306
moveInputFocusToOtherWindow (w);
310
case CirculateNotify:
311
w = findWindowAtDisplay (display, event->xcirculate.window);
313
circulateWindow (w, &event->xcirculate);
316
if (!display->screens->maxGrab)
317
XAllowEvents (display->display, ReplayPointer, event->xbutton.time);
319
s = findScreenAtDisplay (display, event->xbutton.root);
322
if (event->xbutton.button == Button1 ||
323
event->xbutton.button == Button3)
325
w = findTopLevelWindowAtScreen (s, event->xbutton.window);
330
if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW], event))
331
closeActiveWindow (s);
333
if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_MAIN_MENU], event))
334
panelAction (s, s->display->panelActionMainMenuAtom);
336
if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_DIALOG], event))
337
panelAction (s, s->display->panelActionRunDialogAtom);
339
if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND0], event))
340
runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND0].value.s);
342
if (EV_BUTTON (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND1], event))
343
runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND1].value.s);
349
s = findScreenAtDisplay (display, event->xkey.root);
352
if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW], event))
353
closeActiveWindow (s);
355
if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_MAIN_MENU], event))
356
panelAction (s, s->display->panelActionMainMenuAtom);
358
if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_DIALOG], event))
359
panelAction (s, s->display->panelActionRunDialogAtom);
361
if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND0], event))
362
runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND0].value.s);
364
if (EV_KEY (&s->opt[COMP_SCREEN_OPTION_RUN_COMMAND1], event))
365
runCommand (s, s->opt[COMP_SCREEN_OPTION_COMMAND1].value.s);
371
if (event->xproperty.atom == display->winActiveAtom)
373
Window newActiveWindow;
375
newActiveWindow = getActiveWindow (display, event->xproperty.window);
376
if (newActiveWindow != display->activeWindow)
378
display->activeWindow = newActiveWindow;
380
s = findScreenAtDisplay (display, event->xproperty.window);
383
w = findWindowAtDisplay (display, newActiveWindow);
385
w->activeNum = s->activeNum++;
389
else if (event->xproperty.atom == display->winTypeAtom)
391
w = findWindowAtDisplay (display, event->xproperty.window);
396
type = getWindowType (display, w->id);
398
if (type != w->wmType)
400
if (w->attrib.map_state == IsViewable)
402
if (w->type == CompWindowTypeDesktopMask)
403
w->screen->desktopWindowCount--;
404
else if (type == CompWindowTypeDesktopMask)
405
w->screen->desktopWindowCount++;
410
recalcWindowType (w);
412
if (w->type & CompWindowTypeDesktopMask)
413
w->paint.opacity = OPAQUE;
417
else if (event->xproperty.atom == display->winStateAtom)
419
w = findWindowAtDisplay (display, event->xproperty.window);
424
state = getWindowState (display, w->id);
426
if (state != w->state)
430
recalcWindowType (w);
432
if (w->type & CompWindowTypeDesktopMask)
433
w->paint.opacity = OPAQUE;
437
else if (event->xproperty.atom == XA_WM_NORMAL_HINTS)
439
w = findWindowAtDisplay (display, event->xproperty.window);
441
updateNormalHints (w);
443
else if (event->xproperty.atom == XA_WM_HINTS)
445
w = findWindowAtDisplay (display, event->xproperty.window);
449
else if (event->xproperty.atom == XA_WM_TRANSIENT_FOR)
451
w = findWindowAtDisplay (display, event->xproperty.window);
453
XGetTransientForHint (display->display,
454
w->id, &w->transientFor);
456
else if (event->xproperty.atom == display->wmClientLeaderAtom)
458
w = findWindowAtDisplay (display, event->xproperty.window);
460
w->clientLeader = getClientLeader (w);
462
else if (event->xproperty.atom == display->winOpacityAtom)
464
w = findWindowAtDisplay (display, event->xproperty.window);
465
if (w && (w->type & CompWindowTypeDesktopMask) == 0)
469
opacity = getWindowProp32 (display, w->id,
470
display->winOpacityAtom,
472
if (opacity != w->paint.opacity)
474
w->paint.opacity = opacity;
479
else if (event->xproperty.atom == display->winBrightnessAtom)
481
w = findWindowAtDisplay (display, event->xproperty.window);
486
brightness = getWindowProp32 (display, w->id,
487
display->winBrightnessAtom,
489
if (brightness != w->paint.brightness)
491
w->paint.brightness = brightness;
496
else if (event->xproperty.atom == display->winSaturationAtom)
498
w = findWindowAtDisplay (display, event->xproperty.window);
499
if (w && w->screen->canDoSaturated)
503
saturation = getWindowProp32 (display, w->id,
504
display->winSaturationAtom,
506
if (saturation != w->saturation)
508
w->saturation = saturation;
511
w->paint.saturation = w->saturation;
517
else if (event->xproperty.atom == display->xBackgroundAtom[0] ||
518
event->xproperty.atom == display->xBackgroundAtom[1])
520
s = findScreenAtDisplay (display, event->xproperty.window);
523
finiTexture (s, &s->backgroundTexture);
524
initTexture (s, &s->backgroundTexture);
529
else if (event->xproperty.atom == display->wmStrutAtom ||
530
event->xproperty.atom == display->wmStrutPartialAtom)
532
w = findWindowAtDisplay (display, event->xproperty.window);
535
if (updateWindowStruts (w))
536
updateWorkareaForScreen (w->screen);
539
else if (event->xproperty.atom == display->mwmHintsAtom)
541
w = findWindowAtDisplay (display, event->xproperty.window);
544
w->mwmDecor = getMwmDecor (w->screen->display, w->id);
546
updateWindowAttributes (w);
549
else if (event->xproperty.atom == display->wmProtocolsAtom)
551
w = findWindowAtDisplay (display, event->xproperty.window);
553
w->protocols = getProtocols (w->screen->display, w->id);
559
if (event->xclient.message_type == display->winActiveAtom)
561
w = findWindowAtDisplay (display, event->xclient.window);
565
else if (event->xclient.message_type == display->winOpacityAtom)
567
w = findWindowAtDisplay (display, event->xclient.window);
568
if (w && (w->type & CompWindowTypeDesktopMask) == 0)
572
opacity = event->xclient.data.l[0] >> 16;
573
if (opacity != w->paint.opacity)
575
w->paint.opacity = opacity;
577
setWindowProp32 (display, w->id, display->winOpacityAtom,
583
else if (event->xclient.message_type == display->winBrightnessAtom)
585
w = findWindowAtDisplay (display, event->xclient.window);
590
brightness = event->xclient.data.l[0] >> 16;
591
if (brightness != w->paint.brightness)
593
w->paint.brightness = brightness;
595
setWindowProp32 (display, w->id, display->winBrightnessAtom,
596
w->paint.brightness);
601
else if (event->xclient.message_type == display->winSaturationAtom)
603
w = findWindowAtDisplay (display, event->xclient.window);
604
if (w && w->screen->canDoSaturated)
608
saturation = event->xclient.data.l[0] >> 16;
609
if (saturation != w->saturation)
611
w->saturation = saturation;
613
setWindowProp32 (display, w->id, display->winSaturationAtom,
618
w->paint.saturation = w->saturation;
624
else if (event->xclient.message_type == display->winStateAtom)
626
w = findWindowAtDisplay (display, event->xclient.window);
629
unsigned long wState, state;
634
for (i = 1; i < 3; i++)
636
state = windowStateMask (display, event->xclient.data.l[i]);
637
if (state & ~CompWindowStateHiddenMask)
640
#define _NET_WM_STATE_REMOVE 0
641
#define _NET_WM_STATE_ADD 1
642
#define _NET_WM_STATE_TOGGLE 2
644
switch (event->xclient.data.l[0]) {
645
case _NET_WM_STATE_REMOVE:
648
case _NET_WM_STATE_ADD:
651
case _NET_WM_STATE_TOGGLE:
658
if (wState != w->state)
662
recalcWindowType (w);
664
if (!w->attrib.override_redirect)
665
updateWindowAttributes (w);
667
setWindowState (display, wState, w->id);
671
else if (event->xclient.message_type == display->wmProtocolsAtom)
673
if (event->xclient.data.l[0] == display->wmPingAtom)
675
w = findWindowAtDisplay (display, event->xclient.data.l[2]);
681
w->paint.saturation = w->saturation;
685
w->lastPong = display->lastPing;
689
else if (event->xclient.message_type == display->closeWindowAtom)
691
w = findWindowAtDisplay (display, event->xclient.window);
695
else if (event->xclient.message_type == display->desktopGeometryAtom)
697
s = findScreenAtDisplay (display, event->xclient.window);
700
CompOptionValue value;
702
value.i = event->xclient.data.l[0] / s->width;
704
(*s->setScreenOption) (s, "size", &value);
707
else if (event->xclient.message_type == display->moveResizeWindowAtom)
709
unsigned int xwcm = 0;
712
if (event->xclient.data.l[0] & (1 << 7))
715
xwc.x = event->xclient.data.l[1];
718
if (event->xclient.data.l[0] & (1 << 8))
721
xwc.y = event->xclient.data.l[2];
724
if (event->xclient.data.l[0] & (1 << 9))
727
xwc.width = event->xclient.data.l[3];
730
if (event->xclient.data.l[0] & (1 << 10))
733
xwc.height = event->xclient.data.l[4];
738
if (xwcm & (CWX | CWY))
740
w = findWindowAtDisplay (display, event->xclient.window);
744
xwc.x += w->input.left;
747
xwc.y += w->input.top;
751
XConfigureWindow (display->display,
752
event->xclient.window,
755
else if (event->xclient.message_type == display->wmChangeStateAtom)
757
w = findWindowAtDisplay (display, event->xclient.window);
758
if (w && w->type & CompWindowTypeNormalMask)
760
if (event->xclient.data.l[0] == IconicState)
762
else if (event->xclient.data.l[0] == NormalState)
763
unminimizeWindow (w);
766
else if (event->xclient.message_type == display->showingDesktopAtom)
768
s = findScreenAtDisplay (display, event->xclient.window);
771
if (event->xclient.data.l[0])
772
enterShowDesktopMode (s);
774
leaveShowDesktopMode (s);
779
updateModifierMappings (display);
782
w = findWindowAtDisplay (display, event->xmaprequest.window);
786
unminimizeWindow (w);
788
if (w->screen->showingDesktopMask)
789
leaveShowDesktopMode (w->screen);
791
if (!(w->state & CompWindowStateHiddenMask))
793
XMapWindow (display->display, event->xmaprequest.window);
795
updateWindowAttributes (w);
797
if (!(w->type & (CompWindowTypeDesktopMask |
798
CompWindowTypeDockMask)))
799
moveInputFocusToWindow (w);
804
XMapWindow (display->display, event->xmaprequest.window);
807
case ConfigureRequest: {
811
xwcm = event->xconfigurerequest.value_mask &
812
(CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
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;
822
if (xwcm & (CWX | CWY))
824
w = findWindowAtDisplay (display, event->xconfigurerequest.window);
827
xwc.x += w->input.left;
828
xwc.y += w->input.top;
832
XConfigureWindow (display->display,
833
event->xconfigurerequest.window,
836
case CirculateRequest:
839
if (event->xfocus.window != display->activeWindow &&
840
event->xfocus.mode != NotifyGrab)
842
w = findWindowAtDisplay (display, event->xfocus.window);
845
XChangeProperty (display->display, w->screen->root,
846
display->winActiveAtom,
847
XA_WINDOW, 32, PropModeReplace,
848
(unsigned char *) &w->id, 1);
853
if (!display->screens->maxGrab &&
854
event->xcrossing.mode != NotifyGrab &&
855
event->xcrossing.detail != NotifyInferior)
860
raise = display->opt[COMP_DISPLAY_OPTION_AUTORAISE].value.b;
861
delay = display->opt[COMP_DISPLAY_OPTION_AUTORAISE_DELAY].value.i;
863
s = findScreenAtDisplay (display, event->xcrossing.root);
865
w = findTopLevelWindowAtScreen (s, event->xcrossing.window);
869
if (w && w->id != display->below)
871
display->below = w->id;
873
if (!display->opt[COMP_DISPLAY_OPTION_CLICK_TO_FOCUS].value.b)
875
if (display->autoRaiseHandle &&
876
display->autoRaiseWindow != w->id)
878
compRemoveTimeout (display->autoRaiseHandle);
879
display->autoRaiseHandle = 0;
882
if (w->type & ~(CompWindowTypeDockMask |
883
CompWindowTypeDesktopMask))
885
moveInputFocusToWindow (w);
891
display->autoRaiseWindow = w->id;
892
display->autoRaiseHandle =
893
compAddTimeout (delay, autoRaiseTimeout,
897
updateWindowAttributes (w);
905
if (event->xcrossing.detail != NotifyInferior)
907
if (event->xcrossing.window == display->below)
908
display->below = None;
912
if (event->type == display->damageEvent + XDamageNotify)
914
XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
916
if (lastDamagedWindow && de->drawable == lastDamagedWindow->id)
918
w = lastDamagedWindow;
922
w = findWindowAtDisplay (display, de->drawable);
924
lastDamagedWindow = w;
931
if (w->nDamage == w->sizeDamage)
935
w->damageRects = realloc (w->damageRects,
936
(w->sizeDamage + 1) *
937
sizeof (XRectangle));
942
w->damageRects = malloc (sizeof (XRectangle));
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;
955
handleWindowDamageRect (w,
963
else if (display->shapeExtension &&
964
event->type == display->shapeEvent + ShapeNotify)
966
w = findWindowAtDisplay (display, ((XShapeEvent *) event)->window);
972
updateWindowRegion (w);
977
else if (event->type == display->randrEvent + RRScreenChangeNotify)
979
XRRScreenChangeNotifyEvent *rre;
981
rre = (XRRScreenChangeNotifyEvent *) event;
983
s = findScreenAtDisplay (display, rre->root);
985
detectRefreshRateOfScreen (s);
987
else if (event->type == display->syncEvent + XSyncAlarmNotify)
989
XSyncAlarmNotifyEvent *sa;
991
sa = (XSyncAlarmNotifyEvent *) event;
995
for (s = display->screens; s; s = s->next)
996
for (w = s->windows; w; w = w->next)
997
if (w->syncAlarm == sa->alarm)
1001
handleSyncAlarm (w);