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>
27
#include <X11/Xatom.h>
28
#include <X11/Xproto.h>
29
#include <X11/extensions/shape.h>
30
#include <X11/extensions/Xcomposite.h>
40
#define MwmHintsDecorations (1L << 1)
42
#define PropMotifWmHintElements 3
46
unsigned long functions;
47
unsigned long decorations;
51
reallocWindowPrivates (int size,
54
CompScreen *s = (CompScreen *) closure;
58
for (w = s->windows; w; w = w->next)
60
privates = realloc (w->privates, size * sizeof (CompPrivate));
64
w->privates = (CompPrivate *) privates;
71
allocateWindowPrivateIndex (CompScreen *screen)
73
return allocatePrivateIndex (&screen->windowPrivateLen,
74
&screen->windowPrivateIndices,
75
reallocWindowPrivates,
80
freeWindowPrivateIndex (CompScreen *screen,
83
freePrivateIndex (screen->windowPrivateLen,
84
screen->windowPrivateIndices,
89
recalcNormalHints (CompWindow *window)
91
window->sizeHints.x = window->attrib.x;
92
window->sizeHints.y = window->attrib.y;
93
window->sizeHints.width = window->attrib.width;
94
window->sizeHints.height = window->attrib.height;
96
if (window->sizeHints.flags & PMinSize)
98
window->sizeHints.base_width = window->sizeHints.min_width;
99
window->sizeHints.base_height = window->sizeHints.min_height;
103
window->sizeHints.base_width = 0;
104
window->sizeHints.base_height = 0;
107
window->sizeHints.flags |= PBaseSize;
109
if (window->sizeHints.flags & PBaseSize)
111
window->sizeHints.min_width = window->sizeHints.base_width;
112
window->sizeHints.min_height = window->sizeHints.base_height;
116
window->sizeHints.min_width = 0;
117
window->sizeHints.min_height = 0;
119
window->sizeHints.flags |= PMinSize;
121
if (!(window->sizeHints.flags & PMaxSize))
123
window->sizeHints.max_width = 65535;
124
window->sizeHints.max_height = 65535;
125
window->sizeHints.flags |= PMaxSize;
128
if (window->sizeHints.max_width < window->sizeHints.min_width)
129
window->sizeHints.max_width = window->sizeHints.min_width;
131
if (window->sizeHints.max_height < window->sizeHints.min_height)
132
window->sizeHints.max_height = window->sizeHints.min_height;
134
if (window->sizeHints.min_width < 1)
135
window->sizeHints.min_width = 1;
137
if (window->sizeHints.max_width < 1)
138
window->sizeHints.max_width = 1;
140
if (window->sizeHints.min_height < 1)
141
window->sizeHints.min_height = 1;
143
if (window->sizeHints.max_height < 1)
144
window->sizeHints.max_height = 1;
146
if (window->sizeHints.flags & PResizeInc)
148
if (window->sizeHints.width_inc == 0)
149
window->sizeHints.width_inc = 1;
151
if (window->sizeHints.height_inc == 0)
152
window->sizeHints.height_inc = 1;
156
window->sizeHints.width_inc = 1;
157
window->sizeHints.height_inc = 1;
158
window->sizeHints.flags |= PResizeInc;
161
if (window->sizeHints.flags & PAspect)
163
/* don't divide by 0 */
164
if (window->sizeHints.min_aspect.y < 1)
165
window->sizeHints.min_aspect.y = 1;
167
if (window->sizeHints.max_aspect.y < 1)
168
window->sizeHints.max_aspect.y = 1;
172
window->sizeHints.min_aspect.x = 1;
173
window->sizeHints.min_aspect.y = 65535;
174
window->sizeHints.max_aspect.x = 65535;
175
window->sizeHints.max_aspect.y = 1;
176
window->sizeHints.flags |= PAspect;
179
if (!(window->sizeHints.flags & PWinGravity))
181
window->sizeHints.win_gravity = NorthWestGravity;
182
window->sizeHints.flags |= PWinGravity;
187
updateNormalHints (CompWindow *w)
192
status = XGetWMNormalHints (w->screen->display->display, w->id,
193
&w->sizeHints, &supplied);
196
w->sizeHints.flags = 0;
198
recalcNormalHints (w);
202
updateWmHints (CompWindow *w)
206
hints = XGetWMHints (w->screen->display->display, w->id);
209
if (hints->flags & InputHint)
210
w->inputHint = hints->input;
217
updateWindowClassHints (CompWindow *w)
219
XClassHint classHint;
222
status = XGetClassHint (w->screen->display->display, w->id, &classHint);
226
if (classHint.res_name)
231
w->resName = strdup (classHint.res_name);
232
XFree (classHint.res_name);
235
if (classHint.res_class)
240
w->resClass = strdup (classHint.res_class);
241
XFree (classHint.res_class);
247
getClientLeaderOfAncestor (CompWindow *w)
251
w = findWindowAtScreen (w->screen, w->transientFor);
255
return w->clientLeader;
257
return getClientLeaderOfAncestor (w);
265
getClientLeader (CompWindow *w)
269
unsigned long n, left;
272
result = XGetWindowProperty (w->screen->display->display, w->id,
273
w->screen->display->wmClientLeaderAtom,
274
0L, 1L, False, XA_WINDOW, &actual, &format,
277
if (result == Success && n && data)
281
memcpy (&win, data, sizeof (Window));
282
XFree ((void *) data);
288
return getClientLeaderOfAncestor (w);
292
getWmState (CompDisplay *display,
297
unsigned long n, left;
299
unsigned long state = NormalState;
301
result = XGetWindowProperty (display->display, id,
302
display->wmStateAtom, 0L, 2L, FALSE,
303
display->wmStateAtom, &actual, &format,
306
if (result == Success && n && data)
308
memcpy (&state, data, sizeof (unsigned long));
309
XFree ((void *) data);
316
setWmState (CompDisplay *display,
320
unsigned long data[2];
325
XChangeProperty (display->display, id,
326
display->wmStateAtom, display->wmStateAtom,
327
32, PropModeReplace, (unsigned char *) data, 2);
331
windowStateMask (CompDisplay *display,
334
if (state == display->winStateModalAtom)
335
return CompWindowStateModalMask;
336
else if (state == display->winStateStickyAtom)
337
return CompWindowStateStickyMask;
338
else if (state == display->winStateMaximizedVertAtom)
339
return CompWindowStateMaximizedVertMask;
340
else if (state == display->winStateMaximizedHorzAtom)
341
return CompWindowStateMaximizedHorzMask;
342
else if (state == display->winStateShadedAtom)
343
return CompWindowStateShadedMask;
344
else if (state == display->winStateSkipTaskbarAtom)
345
return CompWindowStateSkipTaskbarMask;
346
else if (state == display->winStateSkipPagerAtom)
347
return CompWindowStateSkipPagerMask;
348
else if (state == display->winStateHiddenAtom)
349
return CompWindowStateHiddenMask;
350
else if (state == display->winStateFullscreenAtom)
351
return CompWindowStateFullscreenMask;
352
else if (state == display->winStateAboveAtom)
353
return CompWindowStateAboveMask;
354
else if (state == display->winStateBelowAtom)
355
return CompWindowStateBelowMask;
356
else if (state == display->winStateDemandsAttentionAtom)
357
return CompWindowStateDemandsAttentationMask;
358
else if (state == display->winStateDisplayModalAtom)
359
return CompWindowStateDisplayModalMask;
365
getWindowState (CompDisplay *display,
370
unsigned long n, left;
372
unsigned int state = 0;
374
result = XGetWindowProperty (display->display, id, display->winStateAtom,
375
0L, 1024L, FALSE, XA_ATOM, &actual, &format,
378
if (result == Success && n && data)
380
Atom *a = (Atom *) data;
383
state |= windowStateMask (display, *a++);
385
XFree ((void *) data);
392
setWindowState (CompDisplay *display,
399
if (state & CompWindowStateModalMask)
400
data[i++] = display->winStateModalAtom;
401
if (state & CompWindowStateStickyMask)
402
data[i++] = display->winStateStickyAtom;
403
if (state & CompWindowStateMaximizedVertMask)
404
data[i++] = display->winStateMaximizedVertAtom;
405
if (state & CompWindowStateMaximizedHorzMask)
406
data[i++] = display->winStateMaximizedHorzAtom;
407
if (state & CompWindowStateShadedMask)
408
data[i++] = display->winStateShadedAtom;
409
if (state & CompWindowStateSkipTaskbarMask)
410
data[i++] = display->winStateSkipTaskbarAtom;
411
if (state & CompWindowStateSkipPagerMask)
412
data[i++] = display->winStateSkipPagerAtom;
413
if (state & CompWindowStateHiddenMask)
414
data[i++] = display->winStateHiddenAtom;
415
if (state & CompWindowStateFullscreenMask)
416
data[i++] = display->winStateFullscreenAtom;
417
if (state & CompWindowStateAboveMask)
418
data[i++] = display->winStateAboveAtom;
419
if (state & CompWindowStateBelowMask)
420
data[i++] = display->winStateBelowAtom;
421
if (state & CompWindowStateDemandsAttentationMask)
422
data[i++] = display->winStateDemandsAttentionAtom;
423
if (state & CompWindowStateDisplayModalMask)
424
data[i++] = display->winStateDisplayModalAtom;
426
XChangeProperty (display->display, id, display->winStateAtom,
427
XA_ATOM, 32, PropModeReplace,
428
(unsigned char *) data, i);
432
setWindowActions (CompDisplay *display,
433
unsigned int actions,
439
if (actions & CompWindowActionMoveMask)
440
data[i++] = display->winActionMoveAtom;
441
if (actions & CompWindowActionResizeMask)
442
data[i++] = display->winActionResizeAtom;
443
if (actions & CompWindowActionStickMask)
444
data[i++] = display->winActionStickAtom;
445
if (actions & CompWindowActionMinimizeMask)
446
data[i++] = display->winActionMinimizeAtom;
447
if (actions & CompWindowActionMaximizeHorzMask)
448
data[i++] = display->winActionMaximizeHorzAtom;
449
if (actions & CompWindowActionMaximizeVertMask)
450
data[i++] = display->winActionMaximizeVertAtom;
451
if (actions & CompWindowActionFullscreenMask)
452
data[i++] = display->winActionFullscreenAtom;
453
if (actions & CompWindowActionCloseMask)
454
data[i++] = display->winActionCloseAtom;
456
XChangeProperty (display->display, id, display->wmAllowedActionsAtom,
457
XA_ATOM, 32, PropModeReplace,
458
(unsigned char *) data, i);
462
recalcWindowActions (CompWindow *w)
464
unsigned int actions = 0;
467
case CompWindowTypeFullscreenMask:
468
case CompWindowTypeNormalMask:
470
CompWindowActionMinimizeMask |
471
CompWindowActionMaximizeHorzMask |
472
CompWindowActionMaximizeVertMask |
473
CompWindowActionFullscreenMask;
475
case CompWindowTypeDialogMask:
476
case CompWindowTypeModalDialogMask:
478
CompWindowActionMoveMask |
479
CompWindowActionResizeMask |
480
CompWindowActionStickMask |
481
CompWindowActionCloseMask;
483
case CompWindowTypeUtilMask:
484
case CompWindowTypeToolbarMask:
485
case CompWindowTypeMenuMask:
486
case CompWindowTypeSplashMask:
487
case CompWindowTypeDesktopMask:
488
case CompWindowTypeDockMask:
489
case CompWindowTypeUnknownMask:
494
if (actions != w->actions)
496
w->actions = actions;
497
setWindowActions (w->screen->display, actions, w->id);
502
getWindowType (CompDisplay *display,
507
unsigned long n, left;
510
result = XGetWindowProperty (display->display, id, display->winTypeAtom,
511
0L, 1L, FALSE, XA_ATOM, &actual, &format,
514
if (result == Success && n && data)
518
memcpy (&a, data, sizeof (Atom));
519
XFree ((void *) data);
521
if (a == display->winTypeNormalAtom)
522
return CompWindowTypeNormalMask;
523
else if (a == display->winTypeMenuAtom)
524
return CompWindowTypeMenuMask;
525
else if (a == display->winTypeDesktopAtom)
526
return CompWindowTypeDesktopMask;
527
else if (a == display->winTypeDockAtom)
528
return CompWindowTypeDockMask;
529
else if (a == display->winTypeToolbarAtom)
530
return CompWindowTypeToolbarMask;
531
else if (a == display->winTypeUtilAtom)
532
return CompWindowTypeUtilMask;
533
else if (a == display->winTypeSplashAtom)
534
return CompWindowTypeSplashMask;
535
else if (a == display->winTypeDialogAtom)
536
return CompWindowTypeDialogMask;
539
return CompWindowTypeUnknownMask;
543
recalcWindowType (CompWindow *w)
549
if (!w->attrib.override_redirect && w->wmType == CompWindowTypeUnknownMask)
550
type = CompWindowTypeNormalMask;
552
if (w->state & CompWindowStateFullscreenMask)
553
type = CompWindowTypeFullscreenMask;
555
if (type == CompWindowTypeNormalMask)
558
type = CompWindowTypeDialogMask;
561
if ((type & (CompWindowTypeNormalMask | CompWindowTypeDialogMask)) &&
562
(w->state & CompWindowStateModalMask))
563
type = CompWindowTypeModalDialogMask;
568
recalcWindowActions (w);
573
getMwmDecor (CompDisplay *display,
578
unsigned long n, left;
580
unsigned int decor = MwmDecorAll;
582
result = XGetWindowProperty (display->display, id, display->mwmHintsAtom,
583
0L, 20L, FALSE, display->mwmHintsAtom,
584
&actual, &format, &n, &left,
585
(unsigned char **) &mwmHints);
587
if (result == Success && n && mwmHints)
589
if (n >= PropMotifWmHintElements)
591
if (mwmHints->flags & MwmHintsDecorations)
592
decor = mwmHints->decorations;
602
getProtocols (CompDisplay *display,
607
unsigned long n, left;
609
unsigned int protocols = 0;
611
result = XGetWindowProperty (display->display, id, display->wmProtocolsAtom,
612
0L, 20L, FALSE, XA_ATOM,
613
&actual, &format, &n, &left,
614
(unsigned char **) &protocol);
616
if (result == Success && n && protocol)
620
for (i = 0; i < n; i++)
622
if (protocol[i] == display->wmDeleteWindowAtom)
623
protocols |= CompWindowProtocolDeleteMask;
624
else if (protocol[i] == display->wmTakeFocusAtom)
625
protocols |= CompWindowProtocolTakeFocusMask;
626
else if (protocol[i] == display->wmPingAtom)
627
protocols |= CompWindowProtocolPingMask;
628
else if (protocol[i] == display->wmSyncRequestAtom)
629
protocols |= CompWindowProtocolSyncRequestMask;
639
getWindowProp32 (CompDisplay *display,
642
unsigned short defaultValue)
646
unsigned long n, left;
649
result = XGetWindowProperty (display->display, id, property,
650
0L, 1L, FALSE, XA_CARDINAL, &actual, &format,
653
if (result == Success && n && data)
657
memcpy (&value, data, sizeof (CARD32));
668
setWindowProp32 (CompDisplay *display,
671
unsigned short value)
675
value32 = value << 16 | value;
677
XChangeProperty (display->display, id, property,
678
XA_CARDINAL, 32, PropModeReplace,
679
(unsigned char *) &value32, 1);
684
updateFrameWindow (CompWindow *w)
686
if (w->input.left || w->input.right || w->input.top || w->input.bottom)
689
int x, y, width, height;
691
x = w->serverX - w->input.left;
692
y = w->serverY - w->input.top;
693
width = w->width + w->input.left + w->input.right;
694
height = w->height + w->input.top + w->input.bottom;
698
XSetWindowAttributes attr;
702
attr.override_redirect = TRUE;
704
w->frame = XCreateWindow (w->screen->display->display,
706
x, y, width, height, 0,
710
CWOverrideRedirect | CWEventMask, &attr);
712
XGrabButton (w->screen->display->display, AnyButton,
713
AnyModifier, w->frame, TRUE, ButtonPressMask |
714
ButtonReleaseMask | ButtonMotionMask,
715
GrabModeSync, GrabModeSync, None, None);
717
xwc.stack_mode = Below;
720
XConfigureWindow (w->screen->display->display, w->frame,
721
CWSibling | CWStackMode, &xwc);
724
XMapWindow (w->screen->display->display, w->frame);
726
XChangeProperty (w->screen->display->display, w->id,
727
w->screen->display->frameWindowAtom,
728
XA_WINDOW, 32, PropModeReplace,
729
(unsigned char *) &w->frame, 1);
732
XResizeWindow (w->screen->display->display, w->frame, width, height);
736
rects[0].width = width;
737
rects[0].height = w->input.top;
740
rects[1].y = w->input.top;
741
rects[1].width = w->input.left;
742
rects[1].height = height - w->input.top - w->input.bottom;
744
rects[2].x = width - w->input.right;
745
rects[2].y = w->input.top;
746
rects[2].width = w->input.right;
747
rects[2].height = height - w->input.top - w->input.bottom;
750
rects[3].y = height - w->input.bottom;
751
rects[3].width = width;
752
rects[3].height = w->input.bottom;
754
XShapeCombineRectangles (w->screen->display->display,
768
XDestroyWindow (w->screen->display->display, w->frame);
775
setWindowFrameExtents (CompWindow *w,
776
CompWindowExtents *input,
777
CompWindowExtents *output)
779
if (input->left != w->input.left ||
780
input->right != w->input.right ||
781
input->top != w->input.top ||
782
input->bottom != w->input.bottom)
784
unsigned long data[4];
788
data[0] = input->left;
789
data[1] = input->right;
790
data[2] = input->top;
791
data[3] = input->bottom;
793
updateFrameWindow (w);
795
XChangeProperty (w->screen->display->display, w->id,
796
w->screen->display->frameExtentsAtom,
797
XA_CARDINAL, 32, PropModeReplace,
798
(unsigned char *) data, 4);
801
if (output->left != w->output.left ||
802
output->right != w->output.right ||
803
output->top != w->output.top ||
804
output->bottom != w->output.bottom)
808
(*w->screen->windowResizeNotify) (w);
813
setWindowMatrix (CompWindow *w)
815
w->matrix = w->texture.matrix;
816
w->matrix.x0 -= (w->attrib.x * w->matrix.xx);
817
w->matrix.y0 -= (w->attrib.y * w->matrix.yy);
821
bindWindow (CompWindow *w)
825
unsigned int width, height;
827
if (readImageToTexture (w->screen, &w->texture,
828
windowImage, &width, &height))
830
XResizeWindow (w->screen->display->display, w->id, width, height);
837
w->texture.pixmap = 1;
844
XCompositeNameWindowPixmap (w->screen->display->display,
848
fprintf (stderr, "%s: XCompositeNameWindowPixmap failed\n",
853
if (!bindPixmapToTexture (w->screen, &w->texture, w->pixmap,
857
fprintf (stderr, "%s: Couldn't bind redirected window 0x%x to "
858
"texture\n", programName, (int) w->id);
866
releaseWindow (CompWindow *w)
870
releasePixmapFromTexture (w->screen, &w->texture);
873
XFreePixmap (w->screen->display->display, w->pixmap);
880
freeWindow (CompWindow *w)
885
XSyncDestroyAlarm (w->screen->display->display, w->syncAlarm);
887
if (w->syncWaitHandle)
888
compRemoveTimeout (w->syncWaitHandle);
891
finiTexture (w->screen, &w->texture);
894
XDestroyRegion (w->clip);
897
XDestroyRegion (w->region);
903
free (w->damageRects);
911
if (lastFoundWindow == w)
914
if (lastDamagedWindow == w)
915
lastDamagedWindow = 0;
933
damageWindowRegion (CompWindow *w,
941
reg.rects = ®.extents;
944
x1 = region->extents.x1 - w->attrib.x;
945
y1 = region->extents.y1 - w->attrib.y;
946
x2 = region->extents.x2 - w->attrib.x;
947
y2 = region->extents.y2 - w->attrib.y;
949
reg.extents.x1 = (x1 * w->paint.xScale) + w->attrib.x;
950
reg.extents.y1 = (y1 * w->paint.yScale) + w->attrib.y;
951
reg.extents.x2 = (x2 * w->paint.xScale + 0.5f) + w->attrib.x;
952
reg.extents.y2 = (y2 * w->paint.yScale + 0.5f) + w->attrib.y;
954
if (reg.extents.x2 > reg.extents.x1 && reg.extents.y2 > reg.extents.y1)
955
damageScreenRegion (w->screen, ®);
959
damageScreenRegion (w->screen, region);
964
damageWindowOutputExtents (CompWindow *w)
966
if (w->screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
969
if (w->attrib.map_state == IsViewable && w->damaged)
973
reg.rects = ®.extents;
974
reg.numRects = reg.size = 1;
977
reg.extents.x1 = w->attrib.x - w->output.left;
978
reg.extents.y1 = w->attrib.y - w->output.top;
979
reg.extents.x2 = w->attrib.x + w->width + w->output.right;
980
reg.extents.y2 = w->attrib.y;
982
if (reg.extents.x1 < reg.extents.x2 && reg.extents.y1 < reg.extents.y2)
983
damageWindowRegion (w, ®);
986
reg.extents.y1 = w->attrib.y + w->height;
987
reg.extents.y2 = reg.extents.y1 + w->output.bottom;
989
if (reg.extents.x1 < reg.extents.x2 && reg.extents.y1 < reg.extents.y2)
990
damageWindowRegion (w, ®);
993
reg.extents.x1 = w->attrib.x - w->output.left;
994
reg.extents.y1 = w->attrib.y;
995
reg.extents.x2 = w->attrib.x;
996
reg.extents.y2 = w->attrib.y + w->height;
998
if (reg.extents.x1 < reg.extents.x2 && reg.extents.y1 < reg.extents.y2)
999
damageWindowRegion (w, ®);
1002
reg.extents.x1 = w->attrib.x + w->width;
1003
reg.extents.x2 = reg.extents.x1 + w->output.right;
1005
if (reg.extents.x1 < reg.extents.x2 && reg.extents.y1 < reg.extents.y2)
1006
damageWindowRegion (w, ®);
1011
damageWindowRect (CompWindow *w,
1019
addWindowDamage (CompWindow *w)
1021
if (w->screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
1024
if (w->attrib.map_state == IsViewable && w->damaged)
1028
region.extents.x1 = -w->output.left - w->attrib.border_width;
1029
region.extents.y1 = -w->output.top - w->attrib.border_width;
1030
region.extents.x2 = w->width + w->output.right;
1031
region.extents.y2 = w->height + w->output.bottom;
1033
if (!(*w->screen->damageWindowRect) (w, FALSE, ®ion.extents))
1035
region.extents.x1 += w->attrib.x + w->attrib.border_width;
1036
region.extents.y1 += w->attrib.y + w->attrib.border_width;
1037
region.extents.x2 += w->attrib.x + w->attrib.border_width;
1038
region.extents.y2 += w->attrib.y + w->attrib.border_width;
1040
region.rects = ®ion.extents;
1041
region.numRects = region.size = 1;
1043
damageWindowRegion (w, ®ion);
1049
updateWindowRegion (CompWindow *w)
1052
XRectangle r, *rects, *shapeRects = 0;
1055
EMPTY_REGION (w->region);
1057
if (w->screen->display->shapeExtension)
1061
shapeRects = XShapeGetRectangles (w->screen->display->display, w->id,
1062
ShapeBounding, &n, &order);
1067
r.x = -w->attrib.border_width;
1068
r.y = -w->attrib.border_width;
1070
r.height = w->height;
1080
rect.rects = &rect.extents;
1081
rect.numRects = rect.size = 1;
1083
for (i = 0; i < n; i++)
1085
rect.extents.x1 = rects[i].x + w->attrib.border_width;
1086
rect.extents.y1 = rects[i].y + w->attrib.border_width;
1087
rect.extents.x2 = rect.extents.x1 + rects[i].width;
1088
rect.extents.y2 = rect.extents.y1 + rects[i].height;
1090
if (rect.extents.x1 < 0)
1091
rect.extents.x1 = 0;
1092
if (rect.extents.y1 < 0)
1093
rect.extents.y1 = 0;
1094
if (rect.extents.x2 > w->width)
1095
rect.extents.x2 = w->width;
1096
if (rect.extents.y2 > w->height)
1097
rect.extents.y2 = w->height;
1099
if (rect.extents.y1 < rect.extents.y2 &&
1100
rect.extents.x1 < rect.extents.x2)
1102
rect.extents.x1 += w->attrib.x;
1103
rect.extents.y1 += w->attrib.y;
1104
rect.extents.x2 += w->attrib.x;
1105
rect.extents.y2 += w->attrib.y;
1107
XUnionRegion (&rect, w->region, w->region);
1116
updateWindowStruts (CompWindow *w)
1120
unsigned long n, left;
1121
unsigned long *struts = NULL;
1122
Bool hasOld, hasNew;
1123
CompStruts old, new;
1125
#define MIN_EMPTY 76
1131
old.left = w->struts->left;
1132
old.right = w->struts->right;
1133
old.top = w->struts->top;
1134
old.bottom = w->struts->bottom;
1146
new.left.height = w->screen->height;
1148
new.right.x = w->screen->width;
1150
new.right.width = 0;
1151
new.right.height = w->screen->height;
1155
new.top.width = w->screen->width;
1159
new.bottom.y = w->screen->height;
1160
new.bottom.width = w->screen->width;
1161
new.bottom.height = 0;
1163
result = XGetWindowProperty (w->screen->display->display, w->id,
1164
w->screen->display->wmStrutPartialAtom,
1165
0L, 12L, FALSE, XA_CARDINAL, &actual, &format,
1166
&n, &left, (unsigned char **) &struts);
1168
if (result == Success && n && struts)
1176
gap = w->screen->width - struts[0] - struts[1];
1179
new.left.width = (int) struts[0] + MIN (0, gap / 2);
1180
new.right.width = (int) struts[1] + MIN (0, gap / 2);
1182
gap = w->screen->height - struts[2] - struts[3];
1185
new.top.height = (int) struts[2] + MIN (0, gap / 2);
1186
new.bottom.height = (int) struts[3] + MIN (0, gap / 2);
1188
new.right.x = w->screen->width - new.right.width;
1189
new.bottom.y = w->screen->height - new.bottom.height;
1191
new.left.y = struts[4];
1192
new.left.height = struts[5] - new.left.y + 1;
1193
new.right.y = struts[6];
1194
new.right.height = struts[7] - new.right.y + 1;
1196
new.top.x = struts[8];
1197
new.top.width = struts[9] - new.top.x + 1;
1198
new.bottom.x = struts[10];
1199
new.bottom.width = struts[11] - new.bottom.x + 1;
1207
result = XGetWindowProperty (w->screen->display->display, w->id,
1208
w->screen->display->wmStrutAtom,
1209
0L, 4L, FALSE, XA_CARDINAL,
1210
&actual, &format, &n, &left,
1211
(unsigned char **) &struts);
1213
if (result == Success && n && struts)
1221
gap = w->screen->width - struts[0] - struts[1];
1224
new.left.width = (int) struts[0] + MIN (0, gap / 2);
1225
new.right.width = (int) struts[1] + MIN (0, gap / 2);
1227
gap = w->screen->height - struts[2] - struts[3];
1230
new.top.height = (int) struts[2] + MIN (0, gap / 2);
1231
new.bottom.height = (int) struts[3] + MIN (0, gap / 2);
1234
new.right.x = w->screen->width - new.right.width;
1237
new.bottom.y = w->screen->height - new.bottom.height;
1244
if (hasOld != hasNew || (hasNew && hasOld &&
1245
memcmp (&new, &old, sizeof (CompStruts))))
1250
w->struts = malloc (sizeof (CompStruts));
1267
addWindow (CompScreen *screen,
1273
w = (CompWindow *) malloc (sizeof (CompWindow));
1286
w->minimized = FALSE;
1288
w->startupId = NULL;
1292
initTexture (screen, &w->texture);
1296
w->destroyed = FALSE;
1299
w->destroyRefCnt = 1;
1319
w->input.bottom = 0;
1322
w->output.right = 0;
1324
w->output.bottom = 0;
1326
w->paint.opacity = OPAQUE;
1327
w->paint.brightness = 0xffff;
1328
w->paint.saturation = COLOR;
1329
w->paint.xScale = 1.0f;
1330
w->paint.yScale = 1.0f;
1333
w->saturation = COLOR;
1337
w->mwmDecor = MwmDecorAll;
1339
if (screen->windowPrivateLen)
1341
w->privates = malloc (screen->windowPrivateLen * sizeof (CompPrivate));
1351
w->region = XCreateRegion ();
1358
w->clip = XCreateRegion ();
1365
if (!XGetWindowAttributes (screen->display->display, id, &w->attrib))
1371
w->width = w->attrib.width + w->attrib.border_width * 2;
1372
w->height = w->attrib.height + w->attrib.border_width * 2;
1374
w->sizeHints.flags = 0;
1376
recalcNormalHints (w);
1378
w->transientFor = None;
1379
w->clientLeader = None;
1381
w->serverX = w->attrib.x;
1382
w->serverY = w->attrib.y;
1384
w->syncAlarm = None;
1386
w->syncWaitHandle = 0;
1388
w->syncWait = FALSE;
1389
w->syncX = w->attrib.x;
1390
w->syncY = w->attrib.y;
1391
w->syncWidth = w->attrib.width;
1392
w->syncHeight = w->attrib.height;
1393
w->syncBorderWidth = w->attrib.border_width;
1397
XSelectInput (screen->display->display, id,
1398
PropertyChangeMask |
1404
XGrabButton (screen->display->display, AnyButton,
1405
AnyModifier, w->id, TRUE, ButtonPressMask |
1406
ButtonReleaseMask | ButtonMotionMask,
1407
GrabModeSync, GrabModeSync, None, None);
1409
w->inputHint = TRUE;
1410
w->alpha = (w->attrib.depth == 32);
1415
w->type = CompWindowTypeUnknownMask;
1416
w->lastPong = screen->display->lastPing;
1418
if (screen->display->shapeExtension)
1419
XShapeSelectInput (screen->display->display, id, ShapeNotifyMask);
1421
insertWindowIntoScreen (screen, w, aboveId);
1423
EMPTY_REGION (w->region);
1425
if (w->attrib.class != InputOnly)
1429
rect.rects = &rect.extents;
1430
rect.numRects = rect.size = 1;
1432
rect.extents.x1 = w->attrib.x;
1433
rect.extents.y1 = w->attrib.y;
1434
rect.extents.x2 = w->attrib.x + w->width;
1435
rect.extents.y2 = w->attrib.y + w->height;
1437
XUnionRegion (&rect, w->region, w->region);
1439
initTexture (screen, &w->texture);
1441
w->damage = XDamageCreate (screen->display->display, id,
1442
XDamageReportRawRectangles);
1444
/* need to check for DisplayModal state on all windows */
1445
w->state = getWindowState (w->screen->display, w->id);
1447
updateWindowClassHints (w);
1452
w->attrib.map_state = IsUnmapped;
1457
static int useAlpha = 0;
1459
w->attrib.map_state = IsViewable;
1462
w->attrib.width = 0;
1463
w->attrib.height = 0;
1467
w->alpha = useAlpha;
1468
useAlpha = !useAlpha;
1471
w->invisible = TRUE;
1473
if (!w->attrib.override_redirect)
1475
updateNormalHints (w);
1476
updateWindowStruts (w);
1480
XGetTransientForHint (w->screen->display->display,
1481
w->id, &w->transientFor);
1483
w->clientLeader = getClientLeader (w);
1485
w->wmType = getWindowType (w->screen->display, w->id);
1487
recalcWindowType (w);
1489
w->mwmDecor = getMwmDecor (w->screen->display, w->id);
1490
w->protocols = getProtocols (w->screen->display, w->id);
1492
if (!(w->type & CompWindowTypeDesktopMask))
1494
getWindowProp32 (w->screen->display, w->id,
1495
w->screen->display->winOpacityAtom,
1498
w->paint.brightness =
1499
getWindowProp32 (w->screen->display, w->id,
1500
w->screen->display->winBrightnessAtom,
1503
if (w->screen->canDoSaturated)
1506
getWindowProp32 (w->screen->display, w->id,
1507
w->screen->display->winSaturationAtom,
1510
w->paint.saturation = w->saturation;
1514
if (w->attrib.map_state == IsViewable)
1516
w->attrib.map_state = IsUnmapped;
1520
if (!w->attrib.override_redirect)
1521
updateWindowAttributes (w);
1524
windowInitPlugins (w);
1528
removeWindow (CompWindow *w)
1530
unhookWindowFromScreen (w->screen, w);
1532
if (w->attrib.map_state == IsViewable && w->damaged)
1534
if (w->type == CompWindowTypeDesktopMask)
1535
w->screen->desktopWindowCount--;
1538
updateWorkareaForScreen (w->screen);
1540
updateClientListForScreen (w->screen);
1542
else if (w->state & CompWindowStateHiddenMask)
1544
updateClientListForScreen (w->screen);
1547
windowFiniPlugins (w);
1553
destroyWindow (CompWindow *w)
1559
if (w->destroyRefCnt)
1564
w->destroyed = TRUE;
1565
w->screen->pendingDestroys++;
1570
sendConfigureNotify (CompWindow *w)
1572
XConfigureEvent xev;
1574
xev.type = ConfigureNotify;
1579
xev.width = w->attrib.width;
1580
xev.height = w->attrib.height;
1581
xev.border_width = w->attrib.border_width;
1583
xev.above = (w->prev) ? w->prev->id : None;
1584
xev.override_redirect = w->attrib.override_redirect;
1586
XSendEvent (w->screen->display->display, w->id, FALSE,
1587
StructureNotifyMask, (XEvent *) &xev);
1591
mapWindow (CompWindow *w)
1593
if (w->attrib.class == InputOnly)
1596
if (w->attrib.map_state == IsViewable)
1601
w->attrib.map_state = IsViewable;
1603
setWmState (w->screen->display, NormalState, w->id);
1605
w->invisible = TRUE;
1609
w->lastPong = w->screen->display->lastPing;
1611
w->mapNum = w->screen->mapNum++;
1613
updateWindowRegion (w);
1616
XMapWindow (w->screen->display->display, w->frame);
1619
updateWorkareaForScreen (w->screen);
1621
updateClientListForScreen (w->screen);
1623
if (w->type & CompWindowTypeDesktopMask)
1624
w->screen->desktopWindowCount++;
1626
if (w->protocols & CompWindowProtocolSyncRequestMask)
1628
sendSyncRequest (w);
1629
sendConfigureNotify (w);
1634
unmapWindow (CompWindow *w)
1639
XUnmapWindow (w->screen->display->display, w->frame);
1642
if (w->unmapRefCnt > 0)
1645
if (w->attrib.map_state != IsViewable)
1648
if (w->type == CompWindowTypeDesktopMask)
1649
w->screen->desktopWindowCount--;
1651
addWindowDamage (w);
1653
w->attrib.map_state = IsUnmapped;
1655
setWmState (w->screen->display, IconicState, w->id);
1657
w->invisible = TRUE;
1662
updateWorkareaForScreen (w->screen);
1664
updateClientListForScreen (w->screen);
1668
restackWindow (CompWindow *w,
1673
if (aboveId && aboveId == w->prev->id)
1676
else if (aboveId == None)
1679
unhookWindowFromScreen (w->screen, w);
1680
insertWindowIntoScreen (w->screen, w, aboveId);
1682
updateClientListForScreen (w->screen);
1688
resizeWindow (CompWindow *w,
1695
Window frame = None;
1697
if (x != w->serverX)
1705
if (y != w->serverY)
1714
XMoveWindow (w->screen->display->display, frame,
1715
w->serverX - w->input.left,
1716
w->serverY - w->input.top);
1718
if (w->attrib.width != width ||
1719
w->attrib.height != height ||
1720
w->attrib.border_width != borderWidth)
1722
unsigned int pw, ph, actualWidth, actualHeight, ui;
1723
Pixmap pixmap = None;
1728
pw = width + borderWidth * 2;
1729
ph = height + borderWidth * 2;
1733
pixmap = XCompositeNameWindowPixmap (w->screen->display->display,
1737
fprintf (stderr, "%s: XCompositeNameWindowPixmap failed\n",
1743
result = XGetGeometry (w->screen->display->display, pixmap, &root,
1744
&i, &i, &actualWidth, &actualHeight,
1747
if (actualWidth != pw || actualHeight != ph)
1749
XFreePixmap (w->screen->display->display, pixmap);
1755
addWindowDamage (w);
1759
w->attrib.width = width;
1760
w->attrib.height = height;
1761
w->attrib.border_width = borderWidth;
1771
updateWindowRegion (w);
1773
(*w->screen->windowResizeNotify) (w);
1775
addWindowDamage (w);
1777
w->invisible = WINDOW_INVISIBLE (w);
1779
updateFrameWindow (w);
1781
else if (w->attrib.x != x || w->attrib.y != y)
1785
dx = x - w->attrib.x;
1786
dy = y - w->attrib.y;
1788
moveWindow (w, dx, dy, TRUE);
1795
syncValueIncrement (XSyncValue *value)
1800
XSyncIntToValue (&one, 1);
1801
XSyncValueAdd (value, *value, one, &overflow);
1805
initializeSyncCounter (CompWindow *w)
1807
XSyncAlarmAttributes values;
1810
unsigned long n, left;
1811
unsigned long *counter;
1814
return w->syncAlarm != None;
1816
if (!(w->protocols & CompWindowProtocolSyncRequestMask))
1819
result = XGetWindowProperty (w->screen->display->display, w->id,
1820
w->screen->display->wmSyncRequestCounterAtom,
1821
0L, 1L, FALSE, XA_CARDINAL, &actual, &format,
1822
&n, &left, (unsigned char **) &counter);
1824
if (result == Success && n && counter)
1826
w->syncCounter = *counter;
1830
XSyncIntsToValue (&w->syncValue, (unsigned int) rand (), 0);
1831
XSyncSetCounter (w->screen->display->display,
1835
syncValueIncrement (&w->syncValue);
1837
values.events = TRUE;
1839
values.trigger.counter = w->syncCounter;
1840
values.trigger.wait_value = w->syncValue;
1842
values.trigger.value_type = XSyncAbsolute;
1843
values.trigger.test_type = XSyncPositiveComparison;
1845
XSyncIntToValue (&values.delta, 1);
1847
values.events = TRUE;
1849
compCheckForError (w->screen->display->display);
1851
/* Note that by default, the alarm increments the trigger value
1852
* when it fires until the condition (counter.value < trigger.value)
1855
w->syncAlarm = XSyncCreateAlarm (w->screen->display->display,
1864
if (!compCheckForError (w->screen->display->display))
1867
XSyncDestroyAlarm (w->screen->display->display, w->syncAlarm);
1868
w->syncAlarm = None;
1875
syncWaitTimeout (void *closure)
1877
CompWindow *w = closure;
1879
w->syncWaitHandle = 0;
1880
handleSyncAlarm (w);
1886
sendSyncRequest (CompWindow *w)
1888
XClientMessageEvent xev;
1893
if (!initializeSyncCounter (w))
1896
xev.type = ClientMessage;
1898
xev.message_type = w->screen->display->wmProtocolsAtom;
1900
xev.data.l[0] = w->screen->display->wmSyncRequestAtom;
1901
xev.data.l[1] = CurrentTime;
1902
xev.data.l[2] = XSyncValueLow32 (w->syncValue);
1903
xev.data.l[3] = XSyncValueHigh32 (w->syncValue);
1906
syncValueIncrement (&w->syncValue);
1908
XSendEvent (w->screen->display->display, w->id, FALSE, 0, (XEvent *) &xev);
1911
w->syncX = w->serverX;
1912
w->syncY = w->serverY;
1913
w->syncWidth = w->attrib.width;
1914
w->syncHeight = w->attrib.height;
1915
w->syncBorderWidth = w->attrib.border_width;
1917
if (!w->syncWaitHandle)
1918
w->syncWaitHandle = compAddTimeout (1000, syncWaitTimeout, w);
1922
configureWindow (CompWindow *w,
1923
XConfigureEvent *ce)
1929
w->syncWidth = ce->width;
1930
w->syncHeight = ce->height;
1931
w->syncBorderWidth = ce->border_width;
1935
resizeWindow (w, ce->x, ce->y, ce->width, ce->height,
1939
w->attrib.override_redirect = ce->override_redirect;
1941
if (restackWindow (w, ce->above))
1942
addWindowDamage (w);
1946
circulateWindow (CompWindow *w,
1947
XCirculateEvent *ce)
1951
if (ce->place == PlaceOnTop && w->screen->reverseWindows)
1952
newAboveId = w->screen->reverseWindows->id;
1956
if (restackWindow (w, newAboveId))
1957
addWindowDamage (w);
1961
moveWindow (CompWindow *w,
1969
addWindowDamage (w);
1974
XOffsetRegion (w->region, dx, dy);
1976
setWindowMatrix (w);
1978
w->invisible = WINDOW_INVISIBLE (w);
1980
(*w->screen->windowMoveNotify) (w, dx, dy);
1983
addWindowDamage (w);
1988
syncWindowPosition (CompWindow *w)
1990
if (w->attrib.x != w->serverX || w->attrib.y != w->serverY)
1992
XMoveWindow (w->screen->display->display, w->id,
1996
if (0 && !w->attrib.override_redirect)
2000
ce.type = ConfigureNotify;
2001
ce.display = w->screen->display->display;
2006
ce.width = w->attrib.width;
2007
ce.height = w->attrib.height;
2008
ce.border_width = w->attrib.border_width;
2009
ce.above = (w->prev) ? w->prev->id : None;
2010
ce.override_redirect = FALSE;
2012
XSendEvent (w->screen->display->display,
2013
w->id, FALSE, StructureNotifyMask,
2020
setWindowScale (CompWindow *w,
2024
if (xScale > 0.999f && xScale < 1.001f &&
2025
yScale > 0.999f && yScale < 1.001f)
2027
w->paint.xScale = 1.0f;
2028
w->paint.yScale = 1.0f;
2034
w->paint.xScale = xScale;
2035
w->paint.yScale = yScale;
2042
focusWindow (CompWindow *w)
2044
if (w->attrib.override_redirect)
2047
if (!w->mapNum || w->attrib.map_state != IsViewable)
2050
if (w->attrib.x + w->width <= 0 ||
2051
w->attrib.y + w->height <= 0 ||
2052
w->attrib.x >= w->screen->width ||
2053
w->attrib.y >= w->screen->height)
2056
if (w->inputHint || (w->protocols & CompWindowProtocolTakeFocusMask))
2063
windowResizeNotify (CompWindow *w)
2068
windowMoveNotify (CompWindow *w,
2075
windowGrabNotify (CompWindow *w,
2084
windowUngrabNotify (CompWindow *w)
2089
isGroupTransient (CompWindow *w,
2090
Window clientLeader)
2095
if (w->transientFor == None || w->transientFor == w->screen->root)
2097
if (w->type & (CompWindowTypeDialogMask |
2098
CompWindowTypeModalDialogMask))
2100
if (w->clientLeader == clientLeader)
2109
getModalTransient (CompWindow *window)
2111
CompWindow *w, *modalTransient;
2113
modalTransient = window;
2115
for (w = window->screen->reverseWindows; w; w = w->prev)
2117
if (w == modalTransient || w->mapNum == 0)
2120
if (w->transientFor == modalTransient->id)
2122
if (w->state & CompWindowStateModalMask)
2125
w = window->screen->reverseWindows;
2130
if (modalTransient == window)
2132
for (w = window->screen->reverseWindows; w; w = w->prev)
2134
if (w == modalTransient || w->mapNum == 0)
2137
if (isGroupTransient (w, modalTransient->clientLeader))
2139
if (w->state & CompWindowStateModalMask)
2148
if (modalTransient == window)
2149
modalTransient = NULL;
2151
return modalTransient;
2155
moveInputFocusToWindow (CompWindow *w)
2157
CompDisplay *d = w->screen->display;
2158
CompWindow *modalTransient;
2160
modalTransient = getModalTransient (w);
2164
if (w->id != d->activeWindow)
2166
if (w->inputHint || (w->protocols & CompWindowProtocolTakeFocusMask))
2167
XSetInputFocus (d->display, w->id, RevertToPointerRoot,
2173
isAncestorTo (CompWindow *transient,
2174
CompWindow *ancestor)
2176
if (transient->transientFor)
2178
if (transient->transientFor == ancestor->id)
2181
transient = findWindowAtScreen (transient->screen,
2182
transient->transientFor);
2184
return isAncestorTo (transient, ancestor);
2192
stackLayerCheck (CompWindow *w,
2193
Window clientLeader,
2196
if (w->transientFor == below->id)
2199
if (isAncestorTo (below, w))
2202
if (clientLeader && below->clientLeader == clientLeader)
2203
if (isGroupTransient (below, clientLeader))
2206
if (w->state & CompWindowStateAboveMask)
2210
else if (w->state & CompWindowStateBelowMask)
2212
if (below->state & CompWindowStateBelowMask)
2215
else if (!(below->state & CompWindowStateAboveMask))
2223
/* goes through the stack, top-down until we find a window we should
2224
stack above, normal windows can be stacked above fullscreen windows. */
2226
findSibilingBelow (CompWindow *w)
2229
Window clientLeader = w->clientLeader;
2230
unsigned int type = w->type;
2232
/* normal stacking fullscreen windows with below state */
2233
if ((type & CompWindowTypeFullscreenMask) &&
2234
(w->state & CompWindowStateBelowMask))
2235
type = CompWindowTypeNormalMask;
2237
if (w->transientFor || isGroupTransient (w, clientLeader))
2238
clientLeader = None;
2240
for (below = w->screen->reverseWindows; below; below = below->prev)
2245
if (below->attrib.override_redirect)
2248
if (below->attrib.map_state != IsViewable || below->mapNum == 0)
2251
/* always above desktop windows */
2252
if (below->type & CompWindowTypeDesktopMask)
2256
case CompWindowTypeDesktopMask:
2257
/* desktop window layer */
2259
case CompWindowTypeFullscreenMask:
2260
case CompWindowTypeDockMask:
2261
/* fullscreen and dock layer */
2262
if (below->type & (CompWindowTypeFullscreenMask |
2263
CompWindowTypeDockMask))
2265
if (stackLayerCheck (w, clientLeader, below))
2274
/* fullscreen and normal layer */
2275
if (!(below->type & CompWindowTypeDockMask))
2277
if (stackLayerCheck (w, clientLeader, below))
2288
saveWindowGeometry (CompWindow *w,
2291
int m = mask & ~w->saveMask;
2293
/* only save geometry if window has been placed */
2298
w->saveWc.x = w->attrib.x;
2301
w->saveWc.y = w->attrib.y;
2304
w->saveWc.width = w->attrib.width;
2307
w->saveWc.height = w->attrib.height;
2309
if (m & CWBorderWidth)
2310
w->saveWc.border_width = w->attrib.border_width;
2316
restoreWindowGeometry (CompWindow *w,
2317
XWindowChanges *xwc,
2320
int m = mask & w->saveMask;
2323
xwc->x = w->saveWc.x;
2326
xwc->y = w->saveWc.y;
2329
xwc->width = w->saveWc.width;
2332
xwc->height = w->saveWc.height;
2334
if (m & CWBorderWidth)
2335
xwc->border_width = w->saveWc.border_width;
2337
w->saveMask &= ~mask;
2342
configureXWindow (Display *dpy,
2344
unsigned int valueMask,
2345
XWindowChanges *xwc)
2347
XConfigureWindow (w->screen->display->display, w->id,
2350
if (w->frame && (valueMask & (CWSibling | CWStackMode)))
2351
XConfigureWindow (w->screen->display->display, w->frame,
2352
valueMask & (CWSibling | CWStackMode), xwc);
2356
stackTransients (CompWindow *w,
2358
XWindowChanges *xwc)
2361
Window clientLeader = w->clientLeader;
2363
if (w->transientFor || isGroupTransient (w, clientLeader))
2364
clientLeader = None;
2366
for (t = w->screen->reverseWindows; t; t = t->prev)
2368
if (t == w || t == avoid)
2371
if (t->transientFor == w->id || isGroupTransient (t, clientLeader))
2373
if (!stackTransients (t, avoid, xwc))
2376
if (xwc->sibling == t->id)
2380
configureXWindow (w->screen->display->display, t,
2381
CWSibling | CWStackMode, xwc);
2389
stackAncestors (CompWindow *w,
2390
XWindowChanges *xwc)
2392
if (w->transientFor && xwc->sibling != w->transientFor)
2394
CompWindow *ancestor;
2396
ancestor = findWindowAtScreen (w->screen, w->transientFor);
2399
if (!stackTransients (ancestor, w, xwc))
2402
if (ancestor->mapNum)
2403
configureXWindow (w->screen->display->display, ancestor,
2404
CWSibling | CWStackMode,
2407
stackAncestors (ancestor, xwc);
2410
else if (isGroupTransient (w, w->clientLeader))
2414
for (a = w->screen->reverseWindows; a; a = a->prev)
2416
if (a->clientLeader == w->clientLeader &&
2417
a->transientFor == None &&
2418
!isGroupTransient (a, w->clientLeader))
2420
if (xwc->sibling == a->id)
2423
if (!stackTransients (a, w, xwc))
2427
configureXWindow (w->screen->display->display, a,
2428
CWSibling | CWStackMode,
2436
updateWindowAttributes (CompWindow *w)
2438
CompWindow *sibiling;
2442
if (w->state & CompWindowStateHiddenMask)
2445
xwc.stack_mode = Above;
2448
sibiling = findSibilingBelow (w);
2450
xwc.sibling = sibiling->id;
2452
if (xwc.sibling != w->id)
2456
if (xwc.sibling == None)
2458
XLowerWindow (w->screen->display->display, w->id);
2460
XLowerWindow (w->screen->display->display, w->frame);
2462
else if (xwc.sibling != w->prev->id)
2463
mask |= CWSibling | CWStackMode;
2465
else if (xwc.sibling != None)
2466
mask |= CWSibling | CWStackMode;
2469
/* only update fullscreen and maximized size if window is visible on
2470
current viewport. Size is updated once we switch to the windows
2472
if (w->attrib.x < w->screen->width && w->attrib.x + w->width > 0)
2474
if (w->type & CompWindowTypeFullscreenMask)
2476
saveWindowGeometry (w,
2477
CWX | CWY | CWWidth | CWHeight |
2480
xwc.width = w->screen->width;
2481
xwc.height = w->screen->height;
2482
xwc.border_width = 0;
2484
mask |= CWWidth | CWHeight | CWBorderWidth;
2488
mask |= restoreWindowGeometry (w, &xwc, CWBorderWidth);
2490
if (w->state & CompWindowStateMaximizedVertMask)
2492
saveWindowGeometry (w, CWY | CWHeight);
2494
xwc.height = w->screen->workArea.height - w->input.top -
2495
w->input.bottom - w->attrib.border_width * 2;
2501
mask |= restoreWindowGeometry (w, &xwc, CWY | CWHeight);
2504
if (w->state & CompWindowStateMaximizedHorzMask)
2506
saveWindowGeometry (w, CWX | CWWidth);
2508
xwc.width = w->screen->workArea.width - w->input.left -
2509
w->input.right - w->attrib.border_width * 2;
2515
mask |= restoreWindowGeometry (w, &xwc, CWX | CWWidth);
2520
if (mask & (CWWidth | CWHeight))
2522
if (w->type & CompWindowTypeFullscreenMask)
2531
int width, height, max;
2533
width = (mask & CWWidth) ? xwc.width : w->attrib.width;
2534
height = (mask & CWHeight) ? xwc.height : w->attrib.height;
2536
xwc.width = w->attrib.width;
2537
xwc.height = w->attrib.height;
2539
if (constrainNewWindowSize (w, width, height, &width, &height))
2542
xwc.height = height;
2545
mask &= ~(CWWidth | CWHeight);
2547
if (w->state & CompWindowStateMaximizedVertMask)
2549
if (w->attrib.y < w->screen->workArea.y + w->input.top)
2551
xwc.y = w->screen->workArea.y + w->input.top;
2556
height = xwc.height + w->attrib.border_width * 2;
2558
max = w->screen->workArea.y + w->screen->workArea.height;
2559
if (w->attrib.y + height + w->input.bottom > max)
2561
xwc.y = max - height - w->input.bottom;
2567
if (w->state & CompWindowStateMaximizedHorzMask)
2569
if (w->attrib.x < w->screen->workArea.x + w->input.left)
2571
xwc.x = w->screen->workArea.x + w->input.left;
2576
width = xwc.width + w->attrib.border_width * 2;
2578
max = w->screen->workArea.x + w->screen->workArea.width;
2579
if (w->attrib.x + width + w->input.right > max)
2581
xwc.x = max - width - w->input.right;
2592
if (mask & (CWSibling | CWStackMode))
2594
/* a normal window can be stacked above fullscreen windows but we
2595
don't wont normal windows to be stacked above dock window so if
2596
the sibiling we're stacking above is a fullscreen window we also
2597
update all dock windows. */
2598
if ((sibiling->type & CompWindowTypeFullscreenMask) &&
2599
(!(w->type & (CompWindowTypeFullscreenMask |
2600
CompWindowTypeDockMask))))
2604
for (dw = w->screen->reverseWindows; dw; dw = dw->prev)
2608
for (; dw; dw = dw->prev)
2609
if (dw->type & CompWindowTypeDockMask)
2610
configureXWindow (w->screen->display->display, dw,
2611
CWSibling | CWStackMode,
2615
/* transient children above */
2616
if (stackTransients (w, NULL, &xwc))
2618
configureXWindow (w->screen->display->display, w, mask, &xwc);
2620
/* ancestors, sibilings and sibiling transients below */
2621
stackAncestors (w, &xwc);
2626
configureXWindow (w->screen->display->display, w, mask, &xwc);
2631
activateWindow (CompWindow *w)
2633
if (w->state & CompWindowStateHiddenMask)
2636
unminimizeWindow (w);
2638
if (w->screen->showingDesktopMask)
2639
leaveShowDesktopMode (w->screen);
2644
if (w->state & CompWindowStateHiddenMask)
2647
updateWindowAttributes (w);
2649
if (!(w->type & CompWindowTypeDockMask))
2650
moveInputFocusToWindow (w);
2654
closeWindow (CompWindow *w)
2656
CompDisplay *display = w->screen->display;
2658
if (w->actions & CompWindowActionCloseMask)
2662
ev.type = ClientMessage;
2663
ev.xclient.window = w->id;
2664
ev.xclient.message_type = display->wmProtocolsAtom;
2665
ev.xclient.format = 32;
2666
ev.xclient.data.l[0] = display->wmDeleteWindowAtom;
2667
ev.xclient.data.l[1] = CurrentTime;
2668
ev.xclient.data.l[2] = 0;
2669
ev.xclient.data.l[3] = 0;
2670
ev.xclient.data.l[4] = 0;
2672
XSendEvent (display->display, w->id, FALSE, NoEventMask, &ev);
2676
XKillClient (display->display, w->id);
2681
getOuterRectOfWindow (CompWindow *w,
2684
r->x = w->attrib.x - w->input.left;
2685
r->y = w->attrib.y - w->input.top;
2686
r->width = w->width + w->input.left + w->input.right;
2687
r->height = w->height + w->input.top + w->input.bottom;
2691
constrainNewWindowSize (CompWindow *w,
2697
const XSizeHints *hints = &w->sizeHints;
2701
int base_height = 0;
2704
int max_width = MAXSHORT;
2705
int max_height = MAXSHORT;
2707
/* Ater gdk_window_constrain_size(), which is partially borrowed from fvwm.
2709
* Copyright 1993, Robert Nation
2710
* You may use this code for any purpose, as long as the original
2711
* copyright remains in the source code and all documentation
2713
* which in turn borrows parts of the algorithm from uwm
2716
#define FLOOR(value, base) (((int) ((value) / (base))) * (base))
2717
#define FLOOR64(value, base) (((uint64_t) ((value) / (base))) * (base))
2718
#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
2720
if ((hints->flags & PBaseSize) && (hints->flags & PMinSize))
2722
base_width = hints->base_width;
2723
base_height = hints->base_height;
2724
min_width = hints->min_width;
2725
min_height = hints->min_height;
2727
else if (hints->flags & PBaseSize)
2729
base_width = hints->base_width;
2730
base_height = hints->base_height;
2731
min_width = hints->base_width;
2732
min_height = hints->base_height;
2734
else if (hints->flags & PMinSize)
2736
base_width = hints->min_width;
2737
base_height = hints->min_height;
2738
min_width = hints->min_width;
2739
min_height = hints->min_height;
2742
if (hints->flags & PMaxSize)
2744
max_width = hints->max_width ;
2745
max_height = hints->max_height;
2748
if (hints->flags & PResizeInc)
2750
xinc = MAX (xinc, hints->width_inc);
2751
yinc = MAX (yinc, hints->height_inc);
2754
/* clamp width and height to min and max values */
2755
width = CLAMP (width, min_width, max_width);
2756
height = CLAMP (height, min_height, max_height);
2758
/* shrink to base + N * inc */
2759
width = base_width + FLOOR (width - base_width, xinc);
2760
height = base_height + FLOOR (height - base_height, yinc);
2762
/* constrain aspect ratio, according to:
2764
* min_aspect.x width max_aspect.x
2765
* ------------ <= -------- <= -----------
2766
* min_aspect.y height max_aspect.y
2768
if (hints->flags & PAspect &&
2769
hints->min_aspect.y > 0 && hints->max_aspect.x > 0)
2771
/* Use 64 bit arithmetic to prevent overflow */
2773
uint64_t min_aspect_x = hints->min_aspect.x;
2774
uint64_t min_aspect_y = hints->min_aspect.y;
2775
uint64_t max_aspect_x = hints->max_aspect.x;
2776
uint64_t max_aspect_y = hints->max_aspect.y;
2779
if (min_aspect_x * height > width * min_aspect_y)
2781
delta = FLOOR64 (height - width * min_aspect_y / min_aspect_x, yinc);
2782
if (height - delta >= min_height)
2786
delta = FLOOR64 (height * min_aspect_x / min_aspect_y - width,
2788
if (width + delta <= max_width)
2793
if (width * max_aspect_y > max_aspect_x * height)
2795
delta = FLOOR64 (width - height * max_aspect_x / max_aspect_y, xinc);
2796
if (width - delta >= min_width)
2800
delta = FLOOR64 (width * min_aspect_y / max_aspect_y - height,
2802
if (height + delta <= max_height)
2811
if (width != w->attrib.width || height != w->attrib.height)
2814
*newHeight = height;
2823
hideWindow (CompWindow *w)
2825
if (w->attrib.map_state != IsViewable)
2828
if (w->state & CompWindowStateHiddenMask)
2831
if (!w->minimized && !(w->type & w->screen->showingDesktopMask))
2834
w->state |= CompWindowStateHiddenMask;
2836
XUnmapWindow (w->screen->display->display, w->id);
2838
setWindowState (w->screen->display, w->state, w->id);
2842
showWindow (CompWindow *w)
2844
if (!(w->state & CompWindowStateHiddenMask))
2847
if (w->minimized || (w->type & w->screen->showingDesktopMask))
2850
w->state &= ~CompWindowStateHiddenMask;
2852
XMapWindow (w->screen->display->display, w->id);
2854
setWindowState (w->screen->display, w->state, w->id);
2858
minimizeTransients (CompWindow *w,
2861
CompWindow *ancestor = closure;
2863
if (w->transientFor == ancestor->id ||
2864
isGroupTransient (w, ancestor->clientLeader))
2869
minimizeWindow (CompWindow *w)
2873
w->minimized = TRUE;
2875
forEachWindowOnScreen (w->screen, minimizeTransients, (void *) w);
2882
unminimizeTransients (CompWindow *w,
2885
CompWindow *ancestor = closure;
2887
if (w->transientFor == ancestor->id ||
2888
isGroupTransient (w, ancestor->clientLeader))
2889
unminimizeWindow (w);
2893
unminimizeWindow (CompWindow *w)
2897
w->minimized = FALSE;
2901
forEachWindowOnScreen (w->screen, unminimizeTransients, (void *) w);