2 * Copyright (C) 2004-2009 Kim Woelders
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies of the Software, its documentation and marketing & publicity
13 * materials, and acknowledgment shall be given in the documentation, materials
14 * and software packages that this Software was used.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * This code was originally derived from xcompmgr.c, see original copyright
26 * It has been mostly rewritten since, only the shadow code is more or less
39 #include "windowmatch.h"
48 #include <X11/Xutil.h>
49 #include <X11/extensions/shape.h>
50 #include <X11/extensions/Xcomposite.h>
51 #include <X11/extensions/Xdamage.h>
52 #include <X11/extensions/Xfixes.h>
53 #include <X11/extensions/Xrender.h>
55 #define ENABLE_SHADOWS 1
57 #define USE_DESK_EXPOSE 0
58 #define USE_DESK_VISIBILITY 1
60 #define USE_CLIP_RELATIVE_TO_DESK 1
62 /* Composite Overlay Window (client) availability */
63 #if (1000 * COMPOSITE_MAJOR + COMPOSITE_MINOR) >= 3
64 #define USE_COMPOSITE_OVERLAY_WINDOW 1
66 #define USE_COMPOSITE_OVERLAY_WINDOW 0
69 #define ENABLE_DEBUG 1
71 #define D1printf(fmt...) if(EDebug(EDBUG_TYPE_COMPMGR))Eprintf(fmt)
72 #define D2printf(fmt...) if(EDebug(EDBUG_TYPE_COMPMGR2))Eprintf(fmt)
73 #define D3printf(fmt...) if(EDebug(EDBUG_TYPE_COMPMGR3))Eprintf(fmt)
75 #define D1printf(fmt...)
76 #define D2printf(fmt...)
77 #define D3printf(fmt...)
78 #endif /* ENABLE_DEBUG */
80 #define DEBUG_OPACITY 0
84 #define INV_SHAPE 0x04
86 #define INV_OPACITY 0x10
87 #define INV_SHADOW 0x20
88 #define INV_PIXMAP 0x40
89 #define INV_PICTURE 0x80
90 #define INV_GEOM (INV_POS | INV_SIZE | INV_SHAPE)
91 #define INV_ALL (INV_POS | INV_SIZE | INV_CLIP | INV_OPACITY | INV_SHADOW | INV_PIXMAP)
93 typedef struct _cmhook ECmWinInfo;
96 EObj *next; /* Paint order */
97 EObj *prev; /* Paint order */
99 int rcx, rcy, rcw, rch;
103 unsigned has_shadow:1;
104 unsigned have_shape:1; /* Region validity - shape */
105 unsigned have_extents:1; /* Region validity - extents */
106 unsigned have_clip:1; /* Region validity - clip */
109 Picture pict_alpha; /* Solid, current opacity */
111 XserverRegion extents;
113 int shape_x, shape_y;
115 Picture shadow_alpha; /* Solid, sharp * current opacity */
116 Picture shadow_pict; /* Blurred shaped shadow */
122 unsigned int opacity;
124 unsigned long damage_sequence; /* sequence when damage was created */
127 unsigned int opacity_to;
134 #define ECM_SHADOWS_OFF 0
135 #define ECM_SHADOWS_SHARP 1 /* use window alpha for shadow; sharp, but precise */
136 #define ECM_SHADOWS_ECHO 3 /* use window for shadow; sharp, but precise */
137 #define ECM_SHADOWS_BLURRED 2 /* use window extents for shadow, blurred */
140 #define ECM_OR_UNREDIRECTED 0
141 #define ECM_OR_ON_MAP 1
142 #define ECM_OR_ON_MAPUNMAP 2
143 #define ECM_OR_ON_CREATE 3
147 char resize_fix_enable;
148 char use_name_pixmap;
149 #if USE_COMPOSITE_OVERLAY_WINDOW
155 int offset_x, offset_y;
167 unsigned int time; /* Fading time, ms */
178 #define ECM_MODE_OFF 0
179 #define ECM_MODE_ROOT 1
180 #define ECM_MODE_WINDOW 2
181 #define ECM_MODE_AUTO 3
186 #if USE_COMPOSITE_OVERLAY_WINDOW
189 Pixmap pmap; /* Compositing buffer */
196 XserverRegion damage;
198 XserverRegion rgn_screen;
199 XserverRegion rgn_clip;
201 float opac_blur; /* 0. -> 1. */
202 float opac_sharp; /* 0. -> 1. */
205 /* FIXME - Optimize according to what actually changed */
206 #define _ECM_SET_CLIP_CHANGED() Mode_compmgr.reorder = 1
207 #define _ECM_SET_STACK_CHANGED() Mode_compmgr.reorder = 1
208 #define _ECM_SET_SHADOW_CHANGED() Mode_compmgr.reorder = 1
210 static Picture rootPicture;
211 static Picture rootBuffer;
213 static XserverRegion rgn_tmp; /* Region for temporary use */
214 static XserverRegion rgn_tmp2; /* Region for temporary use */
216 static ESelection *wm_cm_sel = NULL;
218 #define OPAQUE 0xffffffff
219 #define OP32To8(op) (((unsigned int)(op)) >> 24)
221 #define WINDOW_UNREDIR 0
222 #define WINDOW_SOLID 1
223 #define WINDOW_TRANS 2
224 #define WINDOW_ARGB 3
226 static void ECompMgrDamageAll(void);
227 static void ECompMgrHandleRootEvent(Win win, XEvent * ev, void *prm);
228 static void ECompMgrHandleWindowEvent(Win win, XEvent * ev, void *prm);
229 static int doECompMgrWinFade(void *data);
230 static void ECompMgrWinInvalidate(EObj * eo, int what);
231 static void ECompMgrWinSetPicts(EObj * eo);
232 static void ECompMgrWinFadeEnd(EObj * eo, int done);
233 static int ECompMgrDetermineOrder(EObj * const *lst, int num,
234 EObj ** first, EObj ** last,
235 Desk * dsk, XserverRegion clip);
237 #define PIXMAP_DESTROY(pmap) \
238 if (pmap != None) { XFreePixmap(disp, pmap); pmap = None; }
239 #define PICTURE_DESTROY(pict) \
240 if (pict != None) { XRenderFreePicture(disp, pict); pict = None; }
241 #define REGION_DESTROY(rgn) \
242 if (rgn != None) { ERegionDestroy(rgn); rgn = None; }
247 #define DEBUG_REGIONS 0
250 static int n_rgn_c = 0;
251 static int n_rgn_d = 0;
259 rgn = XFixesCreateRegion(disp, NULL, 0);
263 Eprintf("%s: %#lx %d %d %d\n", __func__, rgn,
264 n_rgn_c - n_rgn_d, n_rgn_c, n_rgn_d);
270 ERegionCreateRect(int x, int y, int w, int h)
279 rgn = XFixesCreateRegion(disp, &rct, 1);
283 Eprintf("%s: %#lx %d %d %d\n", __func__, rgn,
284 n_rgn_c - n_rgn_d, n_rgn_c, n_rgn_d);
291 ERegionCreateFromRects(XRectangle * rectangles, int nrectangles)
295 rgn = XFixesCreateRegion(disp, rectangles, nrectangles);
299 Eprintf("%s: %#lx %d %d %d\n", __func__, rgn,
300 n_rgn_c - n_rgn_d, n_rgn_c, n_rgn_d);
307 ERegionCreateFromWindow(Win win)
312 XFixesCreateRegionFromWindow(disp, WinGetXwin(win), WindowRegionBounding);
316 Eprintf("%s: %#lx %d %d %d\n", __func__, rgn,
317 n_rgn_c - n_rgn_d, n_rgn_c, n_rgn_d);
323 ERegionCopy(XserverRegion rgn, XserverRegion src)
325 XFixesCopyRegion(disp, rgn, src);
330 ERegionClone(XserverRegion src)
334 rgn = ERegionCreate();
335 ERegionCopy(rgn, src);
341 ERegionDestroy(XserverRegion rgn)
345 Eprintf("%s: %#lx %d %d %d\n", __func__, rgn,
346 n_rgn_c - n_rgn_d, n_rgn_c, n_rgn_d);
348 XFixesDestroyRegion(disp, rgn);
352 ERegionEmpty(XserverRegion rgn)
354 XFixesSetRegion(disp, rgn, NULL, 0);
358 ERegionSetRect(XserverRegion rgn, int x, int y, int w, int h)
366 XFixesSetRegion(disp, rgn, &rct, 1);
370 ERegionTranslate(XserverRegion rgn, int dx, int dy)
372 if (dx == 0 && dy == 0)
374 XFixesTranslateRegion(disp, rgn, dx, dy);
378 ERegionIntersect(XserverRegion dst, XserverRegion src)
380 XFixesIntersectRegion(disp, dst, dst, src);
384 ERegionUnion(XserverRegion dst, XserverRegion src)
386 XFixesUnionRegion(disp, dst, dst, src);
390 ERegionSubtract(XserverRegion dst, XserverRegion src)
392 XFixesSubtractRegion(disp, dst, dst, src);
396 ERegionSubtractOffset(XserverRegion dst, int dx, int dy, XserverRegion src)
402 if (dx != 0 || dy != 0)
404 rgn = ERegionCopy(rgn_tmp, src);
405 XFixesTranslateRegion(dpy, rgn, dx, dy);
407 XFixesSubtractRegion(dpy, dst, dst, rgn);
411 ERegionUnionOffset(XserverRegion dst, int dx, int dy, XserverRegion src)
417 if (dx != 0 || dy != 0)
419 rgn = ERegionCopy(rgn_tmp, src);
420 XFixesTranslateRegion(dpy, rgn, dx, dy);
422 XFixesUnionRegion(dpy, dst, dst, rgn);
425 #if 0 /* Unused (for debug) */
427 ERegionIsEmpty(XserverRegion rgn)
432 pr = XFixesFetchRegion(disp, rgn, &nr);
440 ERegionShow(const char *txt, XserverRegion rgn)
447 Eprintf(" - region: %s %#lx is None\n", txt, rgn);
451 pr = XFixesFetchRegion(disp, rgn, &nr);
454 Eprintf(" - region: %s %#lx is empty\n", txt, rgn);
458 Eprintf(" - region: %s %#lx:\n", txt, rgn);
459 for (i = 0; i < nr; i++)
460 Eprintf("%4d: %4d+%4d %4dx%4d\n", i, pr[i].x, pr[i].y, pr[i].width,
469 ECompMgrWinClipToGC(EObj * eo, GC gc)
471 XserverRegion rgn = rgn_tmp2;
473 if (!eo || !eo->cmhook)
476 ERegionCopy(rgn, Mode_compmgr.rgn_screen);
477 ERegionSubtract(rgn, eo->cmhook->clip);
478 XFixesSetGCClipRegion(disp, gc, 0, 0, rgn);
485 #define _R(x) (((x) >> 16) & 0xff)
486 #define _G(x) (((x) >> 8) & 0xff)
487 #define _B(x) (((x) ) & 0xff)
490 EPictureCreateSolid(Bool argb, unsigned int a, unsigned int rgb)
495 XRenderPictFormat *pictfmt;
496 XRenderPictureAttributes pa;
499 pmap = XCreatePixmap(dpy, Mode_compmgr.root, 1, 1, argb ? 32 : 8);
500 pictfmt = XRenderFindStandardFormat(dpy,
501 argb ? PictStandardARGB32 :
504 pict = XRenderCreatePicture(dpy, pmap, pictfmt, CPRepeat, &pa);
506 c.alpha = (unsigned short)(a * 0x101);
507 c.red = (unsigned short)(_R(rgb) * 0x101);
508 c.green = (unsigned short)(_G(rgb) * 0x101);
509 c.blue = (unsigned short)(_B(rgb) * 0x101);
510 XRenderFillRectangle(dpy, PictOpSrc, pict, &c, 0, 0, 1, 1);
512 XFreePixmap(dpy, pmap);
518 EPictureCreateBuffer(Win win, int w, int h, Pixmap * ppmap)
522 XRenderPictFormat *pictfmt;
524 pmap = XCreatePixmap(disp, WinGetXwin(win), w, h, WinGetDepth(win));
525 pictfmt = XRenderFindVisualFormat(disp, WinGetVisual(win));
526 pict = XRenderCreatePicture(disp, pmap, pictfmt, 0, 0);
530 XFreePixmap(disp, pmap);
537 EPictureCreate(Window win, int depth, Visual * vis)
540 XRenderPictFormat *pictfmt;
542 pictfmt = XRenderFindVisualFormat(disp, vis);
543 pict = XRenderCreatePicture(disp, win, pictfmt, 0, 0);
549 /* Hack to fix redirected window resize bug(?) */
551 ECompMgrMoveResizeFix(EObj * eo, int x, int y, int w, int h)
555 ECmWinInfo *cw = eo->cmhook;
557 if (!cw || !Conf_compmgr.resize_fix_enable)
559 EMoveResizeWindow(EobjGetWin(eo), x, y, w, h);
564 EGetGeometry(EobjGetWin(eo), NULL, NULL, NULL, &wo, &ho, NULL, NULL);
565 if (wo <= 0 || ho <= 0 || (wo == w && ho == h))
567 EMoveResizeWindow(EobjGetWin(eo), x, y, w, h);
571 /* Resizing - grab old contents */
572 pict = EPictureCreateBuffer(EobjGetWin(eo), wo, ho, NULL);
573 XRenderComposite(disp, PictOpSrc, cw->picture, None, pict, 0, 0, 0, 0, 0, 0,
577 EMoveResizeWindow(EobjGetWin(eo), x, y, w, h);
579 /* Paste old contents back in */
584 XRenderComposite(disp, PictOpSrc, pict, None, cw->picture,
585 0, 0, 0, 0, 0, 0, w, h);
586 XRenderFreePicture(disp, pict);
589 #if !USE_BG_WIN_ON_ALL_DESKS
595 ECompMgrDeskConfigure(Desk * dsk)
600 XRenderPictFormat *pictfmt;
601 XRenderPictureAttributes pa;
604 if (!Mode_compmgr.active)
611 ECompMgrWinInvalidate(eo, INV_PICTURE);
613 if (!dsk->viewable && dsk->bg.bg)
616 if (dsk->bg.pmap == None)
620 pmap = XCreatePixmap(disp, Mode_compmgr.root, 1, 1, WinGetDepth(VROOT));
621 gc = EXCreateGC(pmap, 0, NULL);
622 XSetClipMask(disp, gc, 0);
623 XSetFillStyle(disp, gc, FillSolid);
624 XSetForeground(disp, gc, dsk->bg.pixel);
625 XFillRectangle(disp, pmap, gc, 0, 0, 1, 1);
634 pictfmt = XRenderFindVisualFormat(disp, WinGetVisual(VROOT));
635 pict = XRenderCreatePicture(disp, pmap, pictfmt, CPRepeat, &pa);
637 if (pmap != dsk->bg.pmap)
638 XFreePixmap(disp, pmap);
640 /* New background, all must be repainted */
647 ("ECompMgrDeskConfigure: Desk %d: using pixmap %#lx picture=%#lx\n",
648 dsk->num, pmap, cw->picture);
654 #if USE_DESK_VISIBILITY
656 ECompMgrDeskVisibility(EObj * eo, XEvent * ev)
668 case EOBJ_TYPE_ROOT_BG:
673 visible = dsk->viewable && ev->xvisibility.state != VisibilityFullyObscured;
674 if (dsk->visible == visible)
676 dsk->visible = visible;
681 * A viewable desk is no longer fully obscured. Assume this happened due
682 * to a VT switch to our display and repaint all. This may happen in other
683 * situations as well, but most likely when we must repaint everything
695 ECompMgrDamageMerge(XserverRegion damage)
697 if (Mode_compmgr.got_damage)
699 if (EDebug(EDBUG_TYPE_COMPMGR3))
700 ERegionShow("ECompMgrDamageMerge add:", damage);
702 ERegionUnion(Mode_compmgr.damage, damage);
704 else if (Mode_compmgr.damage != None)
706 ERegionCopy(Mode_compmgr.damage, damage);
710 Mode_compmgr.damage = ERegionClone(damage);
712 Mode_compmgr.got_damage = 1;
714 if (EDebug(EDBUG_TYPE_COMPMGR3))
715 ERegionShow("ECompMgrDamageMerge all:", Mode_compmgr.damage);
719 ECompMgrDamageMergeObject(EObj * eo, XserverRegion damage)
721 ECmWinInfo *cw = eo->cmhook;
722 Desk *dsk = eo->desk;
724 if (!Mode_compmgr.active || damage == None)
727 if (dsk->num > 0 && !dsk->viewable && eo->ilayer < 512)
730 if (Mode_compmgr.reorder)
731 ECompMgrDetermineOrder(NULL, 0, &Mode_compmgr.eo_first,
732 &Mode_compmgr.eo_last, DeskGet(0), None);
734 damage = ERegionCopy(rgn_tmp, damage);
736 #if USE_CLIP_RELATIVE_TO_DESK
737 if (cw->have_clip && eo->type != EOBJ_TYPE_DESK)
738 ERegionSubtract(damage, cw->clip);
741 if (EoGetX(dsk) != 0 || EoGetY(dsk) != 0)
742 ERegionTranslate(damage, EoGetX(dsk), EoGetY(dsk));
744 #if !USE_CLIP_RELATIVE_TO_DESK
745 if (cw->have_clip && eo->type != EOBJ_TYPE_DESK)
746 ERegionSubtract(damage, cw->clip);
749 Mode.events.damage_count++;
751 ECompMgrDamageMerge(damage);
755 ECompMgrDamageAll(void)
757 ECompMgrDamageMerge(Mode_compmgr.rgn_screen);
762 static Picture transBlackPicture;
769 static conv *gaussianMap = NULL;
772 gaussian(double r, double x, double y)
774 return ((1 / (sqrt(2 * M_PI * r))) * exp((-(x * x + y * y)) / (2 * r * r)));
778 make_gaussian_map(double r)
781 int size = ((int)ceil((r * 3)) + 1) & ~1;
782 int center = size / 2;
787 c = (conv *) EMALLOC(char, sizeof(conv) + size * size * sizeof(double));
790 c->data = (double *)(c + 1);
792 for (y = 0; y < size; y++)
793 for (x = 0; x < size; x++)
795 g = gaussian(r, (double)(x - center), (double)(y - center));
797 c->data[y * size + x] = g;
799 /* printf ("gaussian total %f\n", t); */
800 for (y = 0; y < size; y++)
801 for (x = 0; x < size; x++)
803 c->data[y * size + x] /= t;
809 * A picture will help
811 * -center 0 width width+center
812 * -center +-----+-------------------+-----+
815 * 0 +-----+-------------------+-----+
819 * height +-----+-------------------+-----+
822 * center +-----+-------------------+-----+
826 sum_gaussian(conv * map, double opacity, int x, int y, int width, int height)
830 double *g_line = map->data;
831 int g_size = map->size;
832 int center = g_size / 2;
833 int fx_start, fx_end;
834 int fy_start, fy_end;
838 * Compute set of filter values which are "in range",
839 * that's the set with:
840 * 0 <= x + (fx-center) && x + (fx-center) < width &&
841 * 0 <= y + (fy-center) && y + (fy-center) < height
843 * 0 <= x + (fx - center) x + fx - center < width
844 * center - x <= fx fx < width + center - x
847 fx_start = center - x;
850 fx_end = width + center - x;
854 fy_start = center - y;
857 fy_end = height + center - y;
861 g_line = g_line + fy_start * g_size + fx_start;
864 for (fy = fy_start; fy < fy_end; fy++)
869 for (fx = fx_start; fx < fx_end; fx++)
875 return ((unsigned char)(v * opacity * 255.0));
879 make_shadow(double opacity, int width, int height)
884 int gsize = gaussianMap->size;
886 int swidth = width + gsize;
887 int sheight = height + gsize;
888 int center = gsize / 2;
893 data = ECALLOC(unsigned char, swidth * sheight);
898 ximage = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)),
901 swidth, sheight, 8, swidth * sizeof(unsigned char));
909 * Build the gaussian in sections
913 /* FIXME - Handle properly - shaped/non-shaped/offset */
915 * center (fill the complete data array)
917 d = sum_gaussian(gaussianMap, opacity, center, center, width, height);
918 memset(data, d, sheight * swidth);
925 if (ylimit > sheight / 2)
926 ylimit = (sheight + 1) / 2;
928 if (xlimit > swidth / 2)
929 xlimit = (swidth + 1) / 2;
931 for (y = 0; y < ylimit; y++)
932 for (x = 0; x < xlimit; x++)
934 d = sum_gaussian(gaussianMap, opacity, x - center, y - center, width,
936 data[y * swidth + x] = d;
937 data[(sheight - y - 1) * swidth + x] = d;
938 data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
939 data[y * swidth + (swidth - x - 1)] = d;
945 x_diff = swidth - (gsize * 2);
946 if (x_diff > 0 && ylimit > 0)
948 for (y = 0; y < ylimit; y++)
950 d = sum_gaussian(gaussianMap, opacity, center, y - center, width,
952 memset(&data[y * swidth + gsize], d, x_diff);
953 memset(&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
960 for (x = 0; x < xlimit; x++)
962 d = sum_gaussian(gaussianMap, opacity, x - center, center, width,
964 for (y = gsize; y < sheight - gsize; y++)
966 data[y * swidth + x] = d;
967 data[y * swidth + (swidth - x - 1)] = d;
975 shadow_picture(double opacity, int width, int height, int *wp, int *hp)
980 Picture shadowPicture;
983 shadowImage = make_shadow(opacity, width, height);
987 shadowPixmap = XCreatePixmap(dpy, Mode_compmgr.root,
988 shadowImage->width, shadowImage->height, 8);
989 shadowPicture = XRenderCreatePicture(dpy, shadowPixmap,
990 XRenderFindStandardFormat(dpy,
993 gc = XCreateGC(dpy, shadowPixmap, 0, 0);
995 XPutImage(dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0,
996 shadowImage->width, shadowImage->height);
997 *wp = shadowImage->width;
998 *hp = shadowImage->height;
1000 XDestroyImage(shadowImage);
1001 XFreePixmap(dpy, shadowPixmap);
1003 return shadowPicture;
1006 #endif /* ENABLE_SHADOWS */
1008 static void ECompMgrWinSetShape(EObj * eo);
1010 /* Region of window in screen coordinates, including shadows */
1012 ECompMgrWinSetExtents(EObj * eo)
1014 ECmWinInfo *cw = eo->cmhook;
1018 /* FIXME - Get this right */
1020 if (Mode_compmgr.use_pixmap)
1022 cw->rcx = EobjGetX(eo);
1023 cw->rcy = EobjGetY(eo);
1024 cw->rcw = EobjGetW(eo) + 2 * bw;
1025 cw->rch = EobjGetH(eo) + 2 * bw;
1029 cw->rcx = EobjGetX(eo) + bw;
1030 cw->rcy = EobjGetY(eo) + bw;
1031 cw->rcw = EobjGetW(eo);
1032 cw->rch = EobjGetH(eo);
1035 if (eo->noredir && bw)
1039 r.width = EobjGetW(eo) + 2 * bw;
1040 r.height = EobjGetH(eo) + 2 * bw;
1050 if (cw->extents == None)
1051 cw->extents = ERegionCreate();
1054 cw->has_shadow = (Mode_compmgr.shadow_mode != ECM_SHADOWS_OFF) &&
1055 eo->shadow && (EShapeCheck(EobjGetWin(eo)) >= 0);
1056 if (!cw->has_shadow)
1059 switch (Mode_compmgr.shadow_mode)
1064 case ECM_SHADOWS_SHARP:
1065 case ECM_SHADOWS_ECHO:
1066 cw->shadow_dx = Conf_compmgr.shadows.offset_x;
1067 cw->shadow_dy = Conf_compmgr.shadows.offset_y;
1068 cw->shadow_width = cw->rcw;
1069 cw->shadow_height = cw->rch;
1072 case ECM_SHADOWS_BLURRED:
1073 if (EobjIsShaped(eo) /* || cw->mode == WINDOW_ARGB */ )
1079 make_gaussian_map((double)Conf_compmgr.shadows.blur.radius);
1084 cw->shadow_dx = Conf_compmgr.shadows.offset_x - gaussianMap->size / 2;
1085 cw->shadow_dy = Conf_compmgr.shadows.offset_y - gaussianMap->size / 2;
1086 if (!cw->shadow_pict)
1087 cw->shadow_pict = shadow_picture(Mode_compmgr.opac_blur,
1090 &cw->shadow_height);
1093 sr.x = cw->rcx + cw->shadow_dx;
1094 sr.y = cw->rcy + cw->shadow_dy;
1095 sr.width = cw->shadow_width;
1096 sr.height = cw->shadow_height;
1099 r.width = (r.x + r.width) - sr.x;
1104 r.height = (r.y + r.height) - sr.y;
1107 if (sr.x + sr.width > r.x + r.width)
1108 r.width = sr.x + sr.width - r.x;
1109 if (sr.y + sr.height > r.y + r.height)
1110 r.height = sr.y + sr.height - r.y;
1112 ERegionSetRect(cw->extents, r.x, r.y, r.width, r.height);
1118 /* No shadow - extents = shape */
1119 if (!cw->have_shape)
1120 ECompMgrWinSetShape(eo);
1121 ERegionCopy(cw->extents, cw->shape);
1124 cw->have_extents = 1;
1126 D1printf("extents %#lx %d %d %d %d\n", EobjGetXwin(eo), r.x, r.y, r.width,
1129 if (EDebug(EDBUG_TYPE_COMPMGR))
1130 ERegionShow("extents", cw->extents);
1133 /* Region of shaped window in screen coordinates */
1135 ECompMgrWinSetShape(EObj * eo)
1137 ECmWinInfo *cw = eo->cmhook;
1140 if (cw->shape == None)
1142 cw->shape = ERegionCreateFromWindow(EobjGetWin(eo));
1144 if (WinIsShaped(EobjGetWin(eo)))
1146 /* Intersect with window size to get effective bounding region */
1147 ERegionSetRect(rgn_tmp, 0, 0, EobjGetW(eo), EobjGetH(eo));
1148 ERegionIntersect(cw->shape, rgn_tmp);
1150 x = EobjGetX(eo) + EobjGetBW(eo);
1151 y = EobjGetY(eo) + EobjGetBW(eo);
1155 x = EobjGetX(eo) + EobjGetBW(eo) - cw->shape_x;
1156 y = EobjGetY(eo) + EobjGetBW(eo) - cw->shape_y;
1159 ERegionTranslate(cw->shape, x, y);
1161 cw->shape_x = EobjGetX(eo) + EobjGetBW(eo);
1162 cw->shape_y = EobjGetY(eo) + EobjGetBW(eo);
1165 D1printf("shape %#lx: %d %d\n", EobjGetXwin(eo), cw->shape_x, cw->shape_y);
1166 if (EDebug(EDBUG_TYPE_COMPMGR))
1167 ERegionShow("shape", cw->shape);
1171 EWindowGetNamePixmap(const struct _xwin *win)
1173 XWindowAttributes xwa;
1175 if (XGetWindowAttributes(disp, win->xwin, &xwa) == 0 ||
1176 xwa.map_state == IsUnmapped)
1179 return XCompositeNameWindowPixmap(disp, WinGetXwin(win));
1183 ECompMgrWinGetPixmap(const EObj * eo)
1185 ECmWinInfo *cw = eo->cmhook;
1190 if (cw->pixmap != None)
1196 cw->pixmap = EWindowGetNamePixmap(EobjGetWin(eo));
1202 ECompMgrWinInvalidate(EObj * eo, int what)
1204 ECmWinInfo *cw = eo->cmhook;
1205 Display *dpy = disp;
1210 D2printf("ECompMgrWinInvalidate %#lx: %#x\n", EobjGetXwin(eo), what);
1212 if ((what & (INV_SIZE | INV_PIXMAP)) && cw->pixmap != None)
1214 XFreePixmap(dpy, cw->pixmap);
1216 if (Mode_compmgr.use_pixmap)
1217 what |= INV_PICTURE;
1219 EobjTextureInvalidate(eo);
1223 if (what & (INV_SIZE | INV_SHAPE))
1224 REGION_DESTROY(cw->shape);
1225 if (what & INV_GEOM)
1228 if (what & INV_PICTURE)
1229 PICTURE_DESTROY(cw->picture);
1231 if (what & INV_OPACITY)
1232 PICTURE_DESTROY(cw->pict_alpha);
1234 if (what & (INV_CLIP | INV_GEOM))
1238 if (what & (INV_SIZE | INV_SHADOW))
1239 PICTURE_DESTROY(cw->shadow_pict);
1240 if (what & (INV_OPACITY | INV_SHADOW))
1241 PICTURE_DESTROY(cw->shadow_alpha);
1244 if (what & (INV_GEOM | INV_SHADOW))
1245 cw->have_extents = 0;
1249 ECompMgrWinSetOpacity(EObj * eo, unsigned int opacity)
1251 ECmWinInfo *cw = eo->cmhook;
1254 if (!cw || cw->opacity == opacity)
1257 cw->opacity = opacity;
1259 D1printf("ECompMgrWinSetOpacity: %#lx opacity=%#x\n", EobjGetXwin(eo),
1262 if (eo->shown || cw->fadeout)
1263 ECompMgrDamageMergeObject(eo, cw->extents);
1265 /* Invalidate stuff changed by opacity */
1266 ECompMgrWinInvalidate(eo, INV_OPACITY);
1269 mode = WINDOW_UNREDIR;
1270 else if (EobjGetWin(eo)->argb)
1272 else if (cw->opacity != OPAQUE)
1273 mode = WINDOW_TRANS;
1275 mode = WINDOW_SOLID;
1277 if (mode != cw->mode)
1278 _ECM_SET_CLIP_CHANGED();
1284 doECompMgrWinFade(void *data)
1288 unsigned int op, step;
1293 if (EobjListStackCheck(eo) < 0)
1297 op = cw->opacity_to;
1300 Eprintf("doECompMgrWinFade %#lx, %d/%d, %#x->%#x\n", EobjGetXwin(eo),
1301 eo->fading, cw->fadeout, cw->opacity, op);
1306 eo->fading = cw->fadeout;
1308 step = Conf_compmgr.fading.time / Conf.animation.step;
1311 step = 0xffffffff / step;
1312 if (op == cw->opacity)
1315 ECompMgrWinFadeEnd(eo, 0);
1317 else if (op > cw->opacity)
1319 if (op - cw->opacity > step)
1321 op = cw->opacity + step;
1327 if (cw->opacity - op > step)
1329 op = cw->opacity - step;
1335 Eprintf("doECompMgrWinFade %#lx, %#x\n", EobjGetXwin(eo), op);
1337 ECompMgrWinSetOpacity(eo, op);
1342 if (eo->type == EOBJ_TYPE_EWIN)
1343 ModulesSignal(eo->shown ? ESIGNAL_EWIN_CHANGE : ESIGNAL_EWIN_UNMAP, eo);
1346 cw->anim_fade = NULL;
1351 ECompMgrWinFade(EObj * eo, unsigned int op_from, unsigned int op_to)
1353 ECmWinInfo *cw = eo->cmhook;
1355 if (op_from == op_to && op_to == eo->opacity)
1358 ECompMgrWinFadeEnd(eo, 0);
1363 cw->anim_fade = AnimatorAdd(doECompMgrWinFade, eo);
1364 cw->opacity_to = op_to;
1367 ECompMgrWinSetOpacity(eo, op_from);
1371 ECompMgrWinFadeIn(EObj * eo)
1374 Eprintf("ECompMgrWinFadeIn %#lx %#x -> %#x\n", EobjGetXwin(eo), 0x10000000,
1378 ECompMgrWinFadeEnd(eo, 0);
1380 ECompMgrWinFade(eo, 0x10000000, eo->opacity);
1384 ECompMgrWinFadeOut(EObj * eo)
1386 ECmWinInfo *cw = eo->cmhook;
1389 Eprintf("ECompMgrWinFadeOut %#lx %#x -> %#x\n", EobjGetXwin(eo), cw->opacity,
1393 ECompMgrWinInvalidate(eo, INV_PICTURE);
1394 ECompMgrWinFade(eo, cw->opacity, 0x10000000);
1398 ECompMgrWinFadeEnd(EObj * eo, int done)
1400 ECmWinInfo *cw = eo->cmhook;
1403 Eprintf("ECompMgrWinFadeEnd %#lx\n", EobjGetXwin(eo));
1408 ECompMgrWinInvalidate(eo, INV_PIXMAP | INV_PICTURE);
1409 ECompMgrDamageMergeObject(eo, cw->extents);
1410 _ECM_SET_CLIP_CHANGED();
1415 AnimatorDel(cw->anim_fade);
1416 cw->anim_fade = NULL;
1421 ECompMgrWinChangeOpacity(EObj * eo, unsigned int opacity)
1423 ECmWinInfo *cw = eo->cmhook;
1428 if (eo->shown && Conf_compmgr.fading.enable && eo->fade)
1429 ECompMgrWinFade(eo, cw->opacity, opacity);
1431 ECompMgrWinSetOpacity(eo, opacity);
1435 ECompMgrWinMap(EObj * eo)
1437 ECmWinInfo *cw = eo->cmhook;
1447 D1printf("ECompMgrWinMap %#lx\n", EobjGetXwin(eo));
1449 if (!cw->have_extents)
1450 ECompMgrWinSetExtents(eo);
1452 _ECM_SET_STACK_CHANGED();
1453 ECompMgrDamageMergeObject(eo, cw->extents);
1455 if (Conf_compmgr.fading.enable && eo->fade)
1456 ECompMgrWinFadeIn(eo);
1460 ECompMgrWinUnmap(EObj * eo)
1462 ECmWinInfo *cw = eo->cmhook;
1464 D1printf("ECompMgrWinUnmap %#lx shown=%d\n", EobjGetXwin(eo), eo->shown);
1465 if (!eo->shown) /* Sometimes we get a synthetic one too */
1468 ECompMgrDamageMergeObject(eo, cw->extents);
1469 _ECM_SET_STACK_CHANGED();
1470 if (Conf_compmgr.fading.enable && eo->fade && !eo->gone)
1471 ECompMgrWinFadeOut(eo);
1473 ECompMgrWinInvalidate(eo, INV_PIXMAP);
1477 ECompMgrWinSetPicts(EObj * eo)
1479 ECmWinInfo *cw = eo->cmhook;
1481 if (cw->pixmap == None && eo->shown && !eo->noredir &&
1482 (Mode_compmgr.use_pixmap || (eo->fade && Conf_compmgr.fading.enable)))
1484 cw->pixmap = EWindowGetNamePixmap(EobjGetWin(eo));
1485 D2printf("ECompMgrWinSetPicts %#lx: Pmap=%#lx\n", EobjGetXwin(eo),
1489 if (cw->picture == None)
1491 XRenderPictFormat *pictfmt;
1492 XRenderPictureAttributes pa;
1493 Drawable draw = EobjGetXwin(eo);
1495 if ((cw->pixmap && Mode_compmgr.use_pixmap) || (cw->fadeout))
1500 pictfmt = XRenderFindVisualFormat(disp, WinGetVisual(EobjGetWin(eo)));
1501 pa.subwindow_mode = IncludeInferiors;
1502 cw->picture = XRenderCreatePicture(disp, draw,
1503 pictfmt, CPSubwindowMode, &pa);
1504 D2printf("ECompMgrWinSetPicts %#lx: Pict=%#lx (drawable=%#lx)\n",
1505 EobjGetXwin(eo), cw->picture, draw);
1507 if (draw == cw->pixmap)
1511 clip = ERegionCreateFromWindow(EobjGetWin(eo));
1512 XFixesSetPictureClipRegion(disp, cw->picture, 0, 0, clip);
1513 ERegionDestroy(clip);
1519 ECompMgrWinNew(EObj * eo)
1523 if (!Mode_compmgr.active) /* FIXME - Here? */
1526 if (eo->inputonly || EobjGetWin(eo) == VROOT)
1532 cw = ECALLOC(ECmWinInfo, 1);
1536 D1printf("ECompMgrWinNew %#lx\n", EobjGetXwin(eo));
1540 if (eo->type == EOBJ_TYPE_EXT &&
1541 Conf_compmgr.override_redirect.mode == ECM_OR_UNREDIRECTED)
1550 /* If already auto-redirected undo that */
1551 if (Mode_compmgr.mode == ECM_MODE_ROOT)
1553 XCompositeUnredirectWindow(disp, EobjGetXwin(eo),
1554 CompositeRedirectManual);
1555 if (eo->type == EOBJ_TYPE_DESK)
1556 XCompositeRedirectSubwindows(disp, EobjGetXwin(eo),
1557 CompositeRedirectManual);
1562 if (Mode_compmgr.mode == ECM_MODE_WINDOW)
1563 XCompositeRedirectWindow(disp, EobjGetXwin(eo),
1564 CompositeRedirectManual);
1565 cw->damage_sequence = NextRequest(disp);
1567 XDamageCreate(disp, EobjGetXwin(eo), XDamageReportNonEmpty);
1570 if (eo->type == EOBJ_TYPE_EXT)
1571 eo->opacity = OpacityFromPercent(Conf_compmgr.override_redirect.opacity);
1572 if (eo->opacity == 0)
1573 eo->opacity = 0xFFFFFFFF;
1575 if (eo->type == EOBJ_TYPE_DESK || eo->type == EOBJ_TYPE_ROOT_BG)
1577 ESelectInputChange(EobjGetWin(eo), VisibilityChangeMask, 0);
1580 if (eo->type != EOBJ_TYPE_EWIN)
1581 WindowMatchEobjOps(eo);
1583 cw->opacity = 0xdeadbeef;
1584 ECompMgrWinSetOpacity(eo, eo->opacity);
1586 EventCallbackRegister(EobjGetWin(eo), 0, ECompMgrHandleWindowEvent, eo);
1590 ECompMgrWinMoveResize(EObj * eo, int change_xy, int change_wh, int change_bw)
1592 ECmWinInfo *cw = eo->cmhook;
1595 D1printf("ECompMgrWinMoveResize %#lx xy=%d wh=%d bw=%d\n",
1596 EobjGetXwin(eo), change_xy, change_wh, change_bw);
1599 if (change_xy || change_bw)
1600 invalidate |= INV_POS;
1601 if (change_wh || change_bw)
1602 invalidate |= INV_SIZE;
1608 ECompMgrWinFadeEnd(eo, 1);
1612 ECompMgrWinInvalidate(eo, invalidate);
1616 if (EDebug(EDBUG_TYPE_COMPMGR3))
1617 ERegionShow("old-extents:", cw->extents);
1619 #if 0 /* FIXME - We shouldn't have to update clip if transparent */
1620 if (cw->mode == WINDOW_UNREDIR || cw->mode == WINDOW_SOLID)
1622 _ECM_SET_CLIP_CHANGED();
1624 if (cw->have_extents)
1626 /* Invalidate old window region */
1627 ERegionCopy(rgn_tmp2, cw->extents);
1628 ECompMgrWinInvalidate(eo, invalidate);
1629 /* Invalidate new window region */
1630 ECompMgrWinSetExtents(eo);
1631 ERegionUnion(rgn_tmp2, cw->extents);
1632 ECompMgrDamageMergeObject(eo, rgn_tmp2);
1636 ECompMgrWinInvalidate(eo, invalidate);
1637 /* Invalidate new window region */
1638 ECompMgrWinSetExtents(eo);
1639 ECompMgrDamageMergeObject(eo, cw->extents);
1644 ECompMgrWinDamageArea(EObj * eo, int x __UNUSED__, int y __UNUSED__,
1645 int w __UNUSED__, int h __UNUSED__)
1647 ECmWinInfo *cw = eo->cmhook;
1649 ECompMgrDamageMergeObject(eo, cw->shape);
1653 ECompMgrWinChangeShadow(EObj * eo, int shadow)
1655 ECmWinInfo *cw = eo->cmhook;
1657 if (!cw || !eo->shown)
1660 if (!shadow && eo->shadow)
1662 /* Disable shadow */
1663 ECompMgrDamageMergeObject(eo, cw->extents);
1664 ECompMgrWinInvalidate(eo, INV_SHADOW);
1666 else if (shadow && !eo->shadow)
1669 ECompMgrWinInvalidate(eo, INV_SHADOW);
1670 eo->shadow = shadow;
1671 ECompMgrWinSetExtents(eo);
1672 ECompMgrDamageMergeObject(eo, cw->extents);
1675 eo->shadow = shadow;
1679 ECompMgrWinConfigure(EObj * eo, XEvent * ev)
1682 int change_xy, change_wh, change_bw;
1684 x = ev->xconfigure.x;
1685 y = ev->xconfigure.y;
1686 w = ev->xconfigure.width;
1687 h = ev->xconfigure.height;
1688 bw = ev->xconfigure.border_width;
1690 change_xy = EobjGetX(eo) != x || EobjGetY(eo) != y;
1691 change_wh = EobjGetW(eo) != w || EobjGetH(eo) != h;
1692 change_bw = EobjGetBW(eo) != bw;
1694 EWindowSetGeometry(EobjGetWin(eo), x, y, w, h, bw);
1696 ECompMgrWinMoveResize(eo, change_xy, change_wh, change_bw);
1700 ECompMgrWinReparent(EObj * eo, Desk * dsk, int change_xy)
1702 ECmWinInfo *cw = eo->cmhook;
1704 D1printf("ECompMgrWinReparent %#lx %#lx d=%d->%d x,y=%d,%d %d\n",
1705 EobjGetXwin(eo), cw->extents,
1706 (eo->desk) ? (int)eo->desk->num : -1, dsk->num,
1707 EobjGetX(eo), EobjGetY(eo), change_xy);
1712 ECompMgrWinInvalidate(eo, INV_POS);
1716 /* Invalidate old window region */
1717 if (EDebug(EDBUG_TYPE_COMPMGR3))
1718 ERegionShow("old-extents:", cw->extents);
1719 ECompMgrDamageMergeObject(eo, cw->extents);
1722 ECompMgrWinInvalidate(eo, INV_POS);
1724 /* Find new window region */
1725 ECompMgrWinSetExtents(eo);
1728 _ECM_SET_STACK_CHANGED();
1729 ECompMgrDamageMergeObject(eo, cw->extents);
1730 ECompMgrWinInvalidate(eo, INV_PIXMAP);
1734 ECompMgrWinCirculate(EObj * eo, XEvent * ev)
1736 D1printf("ECompMgrWinCirculate %#lx %#lx\n", ev->xany.window,
1739 _ECM_SET_STACK_CHANGED();
1743 ECompMgrWinChangeShape(EObj * eo)
1745 ECmWinInfo *cw = eo->cmhook;
1747 D1printf("ECompMgrWinChangeShape %#lx\n", EobjGetXwin(eo));
1748 if (cw->extents == None)
1751 ECompMgrDamageMergeObject(eo, cw->extents);
1752 ECompMgrWinInvalidate(eo, INV_SHAPE); /* Invalidate extents and shape */
1753 ECompMgrWinSetExtents(eo);
1754 ECompMgrDamageMergeObject(eo, cw->extents);
1755 _ECM_SET_CLIP_CHANGED();
1759 ECompMgrWinRaiseLower(EObj * eo, int delta)
1761 ECmWinInfo *cw = eo->cmhook;
1763 D1printf("ECompMgrWinRaiseLower %#lx delta=%d\n", EobjGetXwin(eo), delta);
1765 if (delta < 0) /* Raise */
1766 _ECM_SET_STACK_CHANGED();
1767 ECompMgrDamageMergeObject(eo, cw->extents);
1768 if (delta > 0) /* Lower */
1769 _ECM_SET_STACK_CHANGED();
1773 ECompMgrWinDel(EObj * eo)
1775 ECmWinInfo *cw = eo->cmhook;
1780 D1printf("ECompMgrWinDel %#lx\n", EobjGetXwin(eo));
1783 ECompMgrWinFadeEnd(eo, 1);
1785 EventCallbackUnregister(EobjGetWin(eo), 0, ECompMgrHandleWindowEvent, eo);
1789 ECompMgrWinInvalidate(eo, INV_PICTURE);
1793 if (Mode_compmgr.mode == ECM_MODE_ROOT &&
1794 eo->type == EOBJ_TYPE_DESK)
1795 XCompositeUnredirectSubwindows(disp, EobjGetXwin(eo),
1796 CompositeRedirectManual);
1800 if (cw->damage != None)
1801 XDamageDestroy(disp, cw->damage);
1803 if (Mode_compmgr.mode == ECM_MODE_WINDOW)
1804 XCompositeUnredirectWindow(disp, EobjGetXwin(eo),
1805 CompositeRedirectManual);
1809 ECompMgrWinInvalidate(eo, INV_ALL);
1810 REGION_DESTROY(cw->extents);
1811 REGION_DESTROY(cw->clip);
1816 _ECM_SET_STACK_CHANGED();
1820 ECompMgrWinDamage(EObj * eo, XEvent * ev __UNUSED__)
1822 ECmWinInfo *cw = eo->cmhook;
1823 Display *dpy = disp;
1824 XDamageNotifyEvent *de = (XDamageNotifyEvent *) ev;
1825 XserverRegion parts;
1827 D2printf("ECompMgrWinDamage %#lx %#lx damaged=%d %d,%d %dx%d\n",
1828 ev->xany.window, EobjGetXwin(eo), cw->damaged,
1829 de->area.x, de->area.y, de->area.width, de->area.height);
1833 parts = cw->extents;
1834 XDamageSubtract(dpy, cw->damage, None, None);
1840 XDamageSubtract(dpy, cw->damage, None, parts);
1841 ERegionTranslate(parts, EobjGetX(eo) + EobjGetBW(eo),
1842 EobjGetY(eo) + EobjGetBW(eo));
1844 eo->serial = ev->xany.serial;
1845 ECompMgrDamageMergeObject(eo, parts);
1847 if (eo->type == EOBJ_TYPE_EWIN)
1848 ModulesSignal(ESIGNAL_EWIN_DAMAGE, eo);
1852 ECompMgrWinDumpInfo(const char *txt, EObj * eo, XserverRegion rgn, int force)
1854 ECmWinInfo *cw = eo->cmhook;
1856 Eprintf("%s %#lx: %d,%d %dx%d: %s\n", txt, EobjGetXwin(eo),
1857 EobjGetX(eo), EobjGetY(eo), EobjGetW(eo), EobjGetH(eo),
1861 Eprintf("Not managed\n");
1865 if (force || EDebug(EDBUG_TYPE_COMPMGR3))
1867 Eprintf(" - pict=%#lx pmap=%#lx\n", cw->picture, cw->pixmap);
1869 ERegionShow("win extents", cw->extents);
1870 ERegionShow("win shape ", cw->shape);
1871 ERegionShow("win clip ", cw->clip);
1873 ERegionShow("region", rgn);
1878 ECompMgrDestroyClip(void)
1880 EObj *eo, *const *lst;
1884 lst = EobjListStackGet(&num);
1885 for (i = 0; i < num; i++)
1896 ECompMgrDetermineOrder(EObj * const *lst, int num, EObj ** first,
1897 EObj ** last, Desk * dsk, XserverRegion clip)
1899 EObj *eo, *eo_prev, *eo_first;
1903 D1printf("ECompMgrDetermineOrder %d\n", dsk->num);
1905 lst = EobjListStackGet(&num);
1908 ECompMgrDestroyClip();
1909 clip = Mode_compmgr.rgn_clip;
1913 /* Determine overall paint order, top to bottom */
1915 eo_first = eo_prev = NULL;
1916 Mode_compmgr.ghosts = 0;
1918 for (i = 0; i < num; i++)
1927 if ((!eo->shown && !eo->fading) || eo->desk != dsk)
1930 /* Region of shaped window in screen coordinates */
1931 if (!cw->have_shape)
1932 ECompMgrWinSetShape(eo);
1934 /* Region of window in screen coordinates, including shadows */
1935 if (!cw->have_extents)
1936 ECompMgrWinSetExtents(eo);
1938 D3printf(" - %#lx desk=%d shown=%d fading=%d fadeout=%d\n",
1939 EobjGetXwin(eo), eo->desk->num, eo->shown, eo->fading,
1942 if (eo->type == EOBJ_TYPE_DESK)
1945 Desk *d = (Desk *) eo;
1950 #if USE_CLIP_RELATIVE_TO_DESK
1951 ERegionTranslate(clip, -EoGetX(d), -EoGetY(d));
1953 stop = ECompMgrDetermineOrder(lst, num, &eo1, &eo2, d, clip);
1954 #if USE_CLIP_RELATIVE_TO_DESK
1955 ERegionTranslate(clip, EoGetX(d), EoGetY(d));
1962 eo_prev->cmhook->next = eo1;
1963 eo1->cmhook->prev = eo_prev;
1967 #if USE_BG_WIN_ON_ALL_DESKS /* Only if using per desk bg overlay */
1968 /* FIXME - We should break when the clip region becomes empty */
1969 if (EobjGetX(eo) == 0 && EobjGetY(eo) == 0)
1976 if (cw->clip == None)
1977 cw->clip = ERegionCreate();
1978 ERegionCopy(cw->clip, clip);
1981 ECompMgrWinSetPicts(eo);
1983 D3printf(" - %#lx desk=%d shown=%d dam=%d pict=%#lx\n",
1984 EobjGetXwin(eo), eo->desk->num, eo->shown, cw->damaged,
1987 #if 0 /* FIXME - Need this? */
1991 if (cw->picture == None && !eo->noredir)
1996 Mode_compmgr.ghosts = 1;
2001 ("ECompMgrDetermineOrder hook in %d - %#lx desk=%d shown=%d\n",
2002 dsk->num, EobjGetXwin(eo), eo->desk->num, eo->shown);
2008 eo_prev->cmhook->next = eo;
2013 case WINDOW_UNREDIR:
2015 D3printf("- clip %#lx %#lx %d,%d %dx%d: %s\n", EobjGetXwin(eo),
2016 cw->clip, EobjGetX(eo), EobjGetY(eo), EobjGetW(eo),
2017 EobjGetH(eo), EobjGetName(eo));
2018 #if USE_CLIP_RELATIVE_TO_DESK
2019 ERegionUnionOffset(clip, 0, 0, cw->shape);
2021 ERegionUnionOffset(clip, EoGetX(dsk), EoGetY(dsk), cw->shape);
2026 D3printf("- noclip %#lx %#lx %d,%d %dx%d: %s\n", EobjGetXwin(eo),
2027 cw->clip, EobjGetX(eo), EobjGetY(eo), EobjGetW(eo),
2028 EobjGetH(eo), EobjGetName(eo));
2032 #if !USE_BG_WIN_ON_ALL_DESKS /* Not if using per desk bg overlay */
2033 /* FIXME - We should break when the clip region becomes empty */
2034 if (eo->type == EOBJ_TYPE_DESK &&
2035 EobjGetX(eo) == 0 && EobjGetY(eo) == 0)
2042 eo_prev->cmhook->next = NULL;
2047 Mode_compmgr.reorder = 0;
2051 static XserverRegion
2052 ECompMgrRepaintObjSetClip(XserverRegion rgn, XserverRegion damage,
2053 XserverRegion clip, int x, int y)
2055 ERegionCopy(rgn, damage);
2056 #if USE_CLIP_RELATIVE_TO_DESK
2057 ERegionSubtractOffset(rgn, x, y, clip);
2059 ERegionSubtractOffset(rgn, 0, 0, clip);
2066 ECompMgrRepaintObj(Picture pbuf, XserverRegion region, EObj * eo, int mode)
2068 static XserverRegion rgn_clip = None;
2069 Display *dpy = disp;
2071 Desk *dsk = eo->desk;
2078 if (rgn_clip == None)
2079 rgn_clip = ERegionCreate();
2086 /* Painting opaque windows top down. */
2088 if (ERegionIsEmpty(clip))
2090 D2printf(" - Quit - repaint region is empty\n");
2097 case WINDOW_UNREDIR:
2099 clip = ECompMgrRepaintObjSetClip(rgn_clip, region, cw->clip, x, y);
2100 if (EDebug(EDBUG_TYPE_COMPMGR2))
2101 ECompMgrWinDumpInfo("ECompMgrRepaintObj solid", eo, clip, 0);
2102 XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, clip);
2103 XRenderComposite(dpy, PictOpSrc, cw->picture, None, pbuf,
2104 0, 0, 0, 0, x + cw->rcx, y + cw->rcy, cw->rcw,
2111 /* Painting trans stuff bottom up. */
2121 clip = ECompMgrRepaintObjSetClip(rgn_clip, region, cw->clip, x, y);
2122 if (EDebug(EDBUG_TYPE_COMPMGR2))
2123 ECompMgrWinDumpInfo("ECompMgrRepaintObj trans", eo, clip, 0);
2124 XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, clip);
2125 if (cw->opacity != OPAQUE && !cw->pict_alpha)
2127 EPictureCreateSolid(True, OP32To8(cw->opacity),
2128 Conf_compmgr.shadows.color);
2129 XRenderComposite(dpy, PictOpOver, cw->picture, cw->pict_alpha,
2130 pbuf, 0, 0, 0, 0, x + cw->rcx, y + cw->rcy,
2136 if (!cw->has_shadow)
2140 clip = ECompMgrRepaintObjSetClip(rgn_clip, region, cw->clip, x, y);
2141 ERegionSubtractOffset(clip, x, y, cw->shape);
2142 XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, clip);
2144 switch (Mode_compmgr.shadow_mode)
2146 case ECM_SHADOWS_SHARP:
2147 case ECM_SHADOWS_ECHO:
2148 if (cw->opacity != OPAQUE && !cw->shadow_alpha)
2150 EPictureCreateSolid(True,
2151 OP32To8(cw->opacity *
2152 Mode_compmgr.opac_sharp),
2153 Conf_compmgr.shadows.color);
2154 alpha = cw->shadow_alpha ? cw->shadow_alpha : transBlackPicture;
2155 if (Mode_compmgr.shadow_mode == ECM_SHADOWS_SHARP)
2156 XRenderComposite(dpy, PictOpOver, alpha, cw->picture, pbuf,
2158 x + cw->rcx + cw->shadow_dx,
2159 y + cw->rcy + cw->shadow_dy,
2160 cw->shadow_width, cw->shadow_height);
2162 XRenderComposite(dpy, PictOpOver, cw->picture, alpha, pbuf,
2164 x + cw->rcx + cw->shadow_dx,
2165 y + cw->rcy + cw->shadow_dy,
2166 cw->shadow_width, cw->shadow_height);
2169 case ECM_SHADOWS_BLURRED:
2170 if (cw->shadow_pict == None)
2173 if (cw->opacity != OPAQUE && !cw->pict_alpha)
2175 EPictureCreateSolid(True, OP32To8(cw->opacity),
2176 Conf_compmgr.shadows.color);
2177 alpha = (cw->pict_alpha) ? cw->pict_alpha : transBlackPicture;
2178 XRenderComposite(dpy, PictOpOver, alpha, cw->shadow_pict, pbuf,
2180 x + cw->rcx + cw->shadow_dx,
2181 y + cw->rcy + cw->shadow_dy,
2182 cw->shadow_width, cw->shadow_height);
2190 ECompMgrPaintGhosts(Picture pict, XserverRegion damage)
2192 EObj *eo, *const *lst;
2195 lst = EobjListStackGet(&num);
2196 for (i = 0; i < num; i++)
2199 if (!eo->shown || !eo->ghost)
2202 switch (eo->cmhook->mode)
2204 case WINDOW_UNREDIR:
2206 ECompMgrRepaintObj(pict, Mode_compmgr.rgn_screen, eo, 0);
2210 ECompMgrRepaintObj(pict, Mode_compmgr.rgn_screen, eo, 1);
2214 /* Subtract window region from damage region */
2215 ERegionSubtractOffset(damage, 0, 0, eo->cmhook->shape);
2220 ECompMgrRepaint(void)
2222 Display *dpy = disp;
2225 Desk *dsk = DeskGet(0);
2227 if (!Mode_compmgr.active || !Mode_compmgr.got_damage)
2230 ERegionIntersect(Mode_compmgr.damage, Mode_compmgr.rgn_screen);
2232 D2printf("ECompMgrRepaint rootBuffer=%#lx rootPicture=%#lx\n",
2233 rootBuffer, rootPicture);
2234 if (EDebug(EDBUG_TYPE_COMPMGR2))
2235 ERegionShow("damage", Mode_compmgr.damage);
2242 /* Do paint order list linking */
2243 if (Mode_compmgr.reorder)
2244 ECompMgrDetermineOrder(NULL, 0, &Mode_compmgr.eo_first,
2245 &Mode_compmgr.eo_last, dsk, None);
2247 /* Paint opaque windows top down */
2248 for (eo = Mode_compmgr.eo_first; eo; eo = eo->cmhook->next)
2249 ECompMgrRepaintObj(pbuf, Mode_compmgr.damage, eo, 0);
2251 #if 0 /* FIXME - NoBg? */
2254 if (EDebug(EDBUG_TYPE_COMPMGR2))
2255 ERegionShow("after opaque", region);
2257 /* Repaint background, clipped by damage region and opaque windows */
2258 pict = dsk->o.cmhook->picture;
2259 D1printf("ECompMgrRepaint desk picture=%#lx\n", pict);
2260 XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, region);
2261 XRenderComposite(dpy, PictOpSrc, pict, None, pbuf,
2262 0, 0, 0, 0, 0, 0, WinGetW(VROOT), WinGetH(VROOT));
2265 /* Paint trans windows and shadows bottom up */
2266 for (eo = Mode_compmgr.eo_last; eo; eo = eo->cmhook->prev)
2267 ECompMgrRepaintObj(pbuf, Mode_compmgr.damage, eo, 1);
2269 /* Paint any ghost windows (adjusting damage region) */
2270 if (Mode_compmgr.ghosts)
2271 ECompMgrPaintGhosts(rootPicture, Mode_compmgr.damage);
2273 if (pbuf != rootPicture)
2275 XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, Mode_compmgr.damage);
2276 XRenderComposite(dpy, PictOpSrc, pbuf, None, rootPicture,
2277 0, 0, 0, 0, 0, 0, WinGetW(VROOT), WinGetH(VROOT));
2280 Mode_compmgr.got_damage = 0;
2284 _ECompMgrIdler(void *data __UNUSED__)
2286 /* Do we get here on auto? */
2287 if (!Mode_compmgr.got_damage /* || Mode_compmgr.mode == ECM_MODE_AUTO */ )
2293 ECompMgrRootBufferCreate(unsigned int w, unsigned int h)
2295 /* Root buffer picture and pixmap */
2296 rootBuffer = EPictureCreateBuffer(VROOT, w, h, &Mode_compmgr.pmap);
2299 Mode_compmgr.rgn_screen = ERegionCreateRect(0, 0, w, h);
2301 /* Overall clip region used while recalculating window clip regions */
2302 Mode_compmgr.rgn_clip = ERegionCreate();
2306 ECompMgrRootBufferDestroy(void)
2308 PICTURE_DESTROY(rootBuffer);
2309 PIXMAP_DESTROY(Mode_compmgr.pmap);
2311 REGION_DESTROY(Mode_compmgr.rgn_screen);
2312 REGION_DESTROY(Mode_compmgr.rgn_clip);
2316 ECompMgrGetRootBuffer(void)
2318 return Mode_compmgr.pmap;
2322 ECompMgrRootConfigure(void *prm __UNUSED__, XEvent * ev)
2324 D1printf("ECompMgrRootConfigure root\n");
2326 ECompMgrRootBufferDestroy();
2327 ECompMgrRootBufferCreate(ev->xconfigure.width, ev->xconfigure.height);
2330 #if USE_DESK_EXPOSE /* FIXME - Remove? */
2332 ECompMgrRootExpose(void *prm __UNUSED__, XEvent * ev)
2334 static XRectangle *expose_rects = 0;
2335 static int size_expose = 0;
2336 static int n_expose = 0;
2337 int more = ev->xexpose.count + 1;
2339 if (ev->xexpose.window != WinGetXwin(VROOT))
2342 D1printf("ECompMgrRootExpose %d %d %d\n", n_expose, size_expose,
2345 if (n_expose == size_expose)
2347 expose_rects = EREALLOC(XRectangle, expose_rects, size_expose + more);
2348 size_expose += more;
2350 expose_rects[n_expose].x = ev->xexpose.x;
2351 expose_rects[n_expose].y = ev->xexpose.y;
2352 expose_rects[n_expose].width = ev->xexpose.width;
2353 expose_rects[n_expose].height = ev->xexpose.height;
2355 if (ev->xexpose.count == 0)
2357 XserverRegion region;
2359 region = ERegionCreateFromRects(expose_rects, n_expose);
2361 ECompMgrDamageMerge(region);
2362 ERegionDestroy(region);
2370 ECompMgrShadowsInit(int mode, int cleanup)
2372 Mode_compmgr.shadow_mode = mode;
2374 Conf_compmgr.shadows.blur.opacity =
2375 OpacityFix(Conf_compmgr.shadows.blur.opacity, 100);
2376 Mode_compmgr.opac_blur = .01 * Conf_compmgr.shadows.blur.opacity;
2377 Conf_compmgr.shadows.sharp.opacity =
2378 OpacityFix(Conf_compmgr.shadows.sharp.opacity, 100);
2379 Mode_compmgr.opac_sharp = .01 * Conf_compmgr.shadows.sharp.opacity;
2384 if (mode != ECM_SHADOWS_OFF)
2386 if (mode == ECM_SHADOWS_BLURRED)
2388 EPictureCreateSolid(True, 255, Conf_compmgr.shadows.color);
2391 EPictureCreateSolid(True,
2392 OP32To8(Mode_compmgr.opac_sharp * OPAQUE),
2393 Conf_compmgr.shadows.color);
2397 PICTURE_DESTROY(transBlackPicture);
2405 lst = EobjListStackGet(&num);
2406 for (i = 0; i < num; i++)
2407 ECompMgrWinInvalidate(lst[i], INV_SHADOW);
2408 _ECM_SET_SHADOW_CHANGED(); /* Force extents/shadow update */
2412 #define ECompMgrShadowsInit(mode, cleanup)
2416 ECompMgrIsActive(void)
2418 return Mode_compmgr.active;
2426 XRenderPictFormat *pictfmt;
2427 XRenderPictureAttributes pa;
2429 if (Mode_compmgr.active || Conf_compmgr.mode == ECM_MODE_OFF)
2431 Conf_compmgr.enable = Mode_compmgr.active = 1;
2432 Mode_compmgr.mode = Conf_compmgr.mode;
2434 Conf_compmgr.override_redirect.opacity =
2435 OpacityFix(Conf_compmgr.override_redirect.opacity, 100);
2437 ECompMgrRootBufferCreate(WinGetW(VROOT), WinGetH(VROOT));
2439 Mode_compmgr.root = WinGetXwin(VROOT);
2440 #if USE_COMPOSITE_OVERLAY_WINDOW
2441 if (Conf_compmgr.use_cow && !Mode.wm.window)
2443 Mode_compmgr.cow = XCompositeGetOverlayWindow(disp, WinGetXwin(VROOT));
2444 if (Mode_compmgr.cow != None)
2446 /* Ok, got the cow! */
2447 Mode_compmgr.root = Mode_compmgr.cow;
2448 /* It is possible to get it stacked below others?!? */
2449 XRaiseWindow(disp, Mode_compmgr.cow);
2450 /* Pass all input events through */
2451 XShapeCombineRectangles(disp, Mode_compmgr.cow, ShapeInput, 0, 0,
2452 NULL, 0, ShapeSet, Unsorted);
2453 D1printf("COW/CMroot=%#lx/%#lx\n",
2454 Mode_compmgr.cow, Mode_compmgr.root);
2459 Mode_compmgr.cow = None;
2463 pa.subwindow_mode = IncludeInferiors;
2464 pictfmt = XRenderFindVisualFormat(disp, WinGetVisual(VROOT));
2466 XRenderCreatePicture(disp, Mode_compmgr.root, pictfmt, CPSubwindowMode,
2469 ECompMgrShadowsInit(Conf_compmgr.shadows.mode, 0);
2473 switch (Mode_compmgr.mode)
2476 XCompositeRedirectSubwindows(disp, WinGetXwin(VROOT),
2477 CompositeRedirectManual);
2478 #if USE_DESK_EXPOSE /* FIXME - Remove? */
2479 ESelectInputChange(WinGetXwin(VROOT), ExposureMask, 0);
2482 case ECM_MODE_WINDOW:
2483 #if USE_DESK_EXPOSE /* FIXME - Remove? */
2484 ESelectInputChange(WinGetXwin(VROOT), ExposureMask, 0);
2488 XCompositeRedirectSubwindows(disp, WinGetXwin(VROOT),
2489 CompositeRedirectAutomatic);
2493 Mode_compmgr.got_damage = 0;
2495 rgn_tmp = ERegionCreate();
2496 rgn_tmp2 = ERegionCreate();
2498 EventCallbackRegister(VROOT, 0, ECompMgrHandleRootEvent, NULL);
2500 wm_cm_sel = SelectionAcquire("_NET_WM_CM_S", NULL, NULL);
2502 lst = EobjListStackGet(&num);
2503 for (i = 0; i < num; i++)
2505 ECompMgrWinNew(lst[i]);
2507 ECompMgrWinMap(lst[i]);
2510 #if !USE_BG_WIN_ON_ALL_DESKS
2511 DesksBackgroundRefresh(NULL, DESK_BG_RECONFIGURE_ALL);
2513 _ECM_SET_CLIP_CHANGED();
2521 EObj *const *lst1, **lst;
2524 if (!Mode_compmgr.active)
2526 Conf_compmgr.enable = Mode_compmgr.active = 0;
2530 SelectionRelease(wm_cm_sel);
2533 PICTURE_DESTROY(rootPicture);
2535 ECompMgrRootBufferDestroy();
2537 ECompMgrShadowsInit(ECM_SHADOWS_OFF, 0);
2539 lst1 = EobjListStackGet(&num);
2542 lst = EMALLOC(EObj *, num);
2545 memcpy(lst, lst1, num * sizeof(EObj *));
2546 for (i = 0; i < num; i++)
2548 if (lst[i]->type == EOBJ_TYPE_EXT)
2549 EobjUnregister(lst[i]); /* Modifies the object stack! */
2551 ECompMgrWinDel(lst[i]);
2557 Mode_compmgr.got_damage = 0;
2558 REGION_DESTROY(Mode_compmgr.damage);
2559 REGION_DESTROY(rgn_tmp);
2560 REGION_DESTROY(rgn_tmp2);
2562 if (Mode_compmgr.mode == ECM_MODE_ROOT)
2563 XCompositeUnredirectSubwindows(disp, WinGetXwin(VROOT),
2564 CompositeRedirectManual);
2566 EventCallbackUnregister(VROOT, 0, ECompMgrHandleRootEvent, NULL);
2568 #if USE_COMPOSITE_OVERLAY_WINDOW
2569 if (Mode_compmgr.cow != None)
2571 XCompositeReleaseOverlayWindow(disp, WinGetXwin(VROOT));
2572 Mode_compmgr.cow = None;
2576 #if !USE_BG_WIN_ON_ALL_DESKS
2577 DesksBackgroundRefresh(NULL, DESK_BG_RECONFIGURE_ALL);
2584 ECompMgrConfigGet(cfg_composite * cfg)
2586 cfg->enable = Conf_compmgr.enable;
2587 cfg->shadow = Conf_compmgr.shadows.mode;
2588 cfg->fading = Conf_compmgr.fading.enable;
2589 cfg->opacity_focused = Conf.opacity.focused;
2590 cfg->opacity_unfocused = Conf.opacity.unfocused;
2591 cfg->opacity_override = Conf_compmgr.override_redirect.opacity;
2592 cfg->fade_speed = 100 - (Conf_compmgr.fading.time / 10);
2596 ECompMgrConfigSet(const cfg_composite * cfg)
2598 if (Conf_compmgr.mode == ECM_MODE_OFF)
2601 DialogOK("Enable Composite Error",
2602 _("Cannot enable Composite Manager.\n"
2603 "Use xdpyinfo to check that\n"
2604 "Composite, Damage, Fixes, and Render\n"
2605 "extensions are loaded."));
2609 if (cfg->enable != Conf_compmgr.enable)
2611 Conf_compmgr.enable = cfg->enable;
2612 Conf_compmgr.shadows.mode = cfg->shadow;
2620 if (cfg->shadow != Conf_compmgr.shadows.mode)
2622 Conf_compmgr.shadows.mode = cfg->shadow;
2623 if (Conf_compmgr.enable)
2625 ECompMgrShadowsInit(Conf_compmgr.shadows.mode, 1);
2626 ECompMgrDamageAll();
2631 Conf_compmgr.fading.enable = cfg->fading;
2632 Conf_compmgr.fading.time = (100 - cfg->fade_speed) * 10;
2634 Conf.opacity.focused = cfg->opacity_focused;
2635 Conf.opacity.unfocused = cfg->opacity_unfocused;
2636 Conf_compmgr.override_redirect.opacity = cfg->opacity_override;
2638 EobjsOpacityUpdate(Conf_compmgr.override_redirect.opacity);
2646 #define USE_WINDOW_EVENTS 0
2649 ECompMgrHandleWindowEvent(Win win __UNUSED__, XEvent * ev, void *prm)
2651 EObj *eo = (EObj *) prm;
2653 D2printf("ECompMgrHandleWindowEvent: type=%d\n", ev->type);
2657 #if USE_WINDOW_EVENTS
2658 case ConfigureNotify:
2659 ECompMgrWinConfigure(eo, ev);
2666 if (eo->type == EOBJ_TYPE_EXT && eo->cmhook)
2668 ECompMgrWinUnmap(eo);
2673 case CirculateNotify:
2674 ECompMgrWinCirculate(eo, ev);
2678 #if USE_DESK_VISIBILITY
2679 case VisibilityNotify:
2680 ECompMgrDeskVisibility(eo, ev);
2684 case EX_EVENT_DAMAGE_NOTIFY:
2685 ECompMgrWinDamage(eo, ev);
2691 ECompMgrHandleRootEvent(Win win __UNUSED__, XEvent * ev, void *prm)
2696 D2printf("ECompMgrHandleRootEvent: type=%d\n", ev->type);
2701 xwin = ev->xcreatewindow.window;
2703 if (Conf_compmgr.override_redirect.mode != ECM_OR_ON_CREATE)
2705 eo = EobjListStackFind(xwin);
2707 EobjRegister(xwin, EOBJ_TYPE_EXT);
2711 xwin = ev->xdestroywindow.window;
2713 eo = EobjListStackFind(xwin);
2714 if (eo && eo->type == EOBJ_TYPE_EXT)
2716 if (ev->type == DestroyNotify)
2722 case ReparentNotify:
2723 case EX_EVENT_REPARENT_GONE:
2724 xwin = ev->xreparent.window;
2725 if (ev->xreparent.parent == WinGetXwin(VROOT))
2726 goto case_CreateNotify;
2728 goto case_DestroyNotify;
2730 case ConfigureNotify:
2731 if (ev->xconfigure.window == WinGetXwin(VROOT))
2733 ECompMgrRootConfigure(prm, ev);
2737 eo = EobjListStackFind(ev->xconfigure.window);
2738 if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
2740 ECompMgrWinConfigure(eo, ev);
2746 #if USE_COMPOSITE_OVERLAY_WINDOW
2747 if (ev->xmap.window == Mode_compmgr.cow)
2750 eo = EobjListStackFind(ev->xmap.window);
2752 eo = EobjRegister(ev->xmap.window, EOBJ_TYPE_EXT);
2753 if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
2756 EobjListStackRaise(eo, 0);
2762 case EX_EVENT_UNMAP_GONE:
2763 eo = EobjListStackFind(ev->xunmap.window);
2764 if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
2766 if (ev->type == EX_EVENT_UNMAP_GONE)
2769 /* No. Unredirection seems to cause map/unmap => loop */
2770 if (Conf_compmgr.override_redirect.mode == ECM_OR_ON_MAPUNMAP)
2777 ECompMgrWinUnmap(eo);
2783 case CirculateNotify:
2784 eo = EobjListStackFind(ev->xcirculate.window);
2785 if (eo && eo->cmhook)
2786 ECompMgrWinCirculate(eo, ev);
2789 #if USE_DESK_EXPOSE /* FIXME - Remove? */
2791 if (Mode_compmgr.shadow_mode != ECM_SHADOWS_OFF)
2792 ECompMgrRootExpose(prm, ev);
2805 if (!XEXT_AVAILABLE(XEXT_CM_ALL))
2807 Conf_compmgr.mode = ECM_MODE_OFF;
2811 Mode_compmgr.use_pixmap = Conf_compmgr.use_name_pixmap;
2813 #if 0 /* TBD - Force ECM_MODE_ROOT at startup */
2814 if (Conf_compmgr.mode == ECM_MODE_OFF)
2816 Conf_compmgr.mode = ECM_MODE_ROOT;
2819 if (Conf_compmgr.mode == ECM_MODE_OFF)
2820 Conf_compmgr.enable = 0;
2821 D1printf("ECompMgrInit: enable=%d mode=%d\n", Conf_compmgr.enable,
2826 ECompMgrSighan(int sig, void *prm __UNUSED__)
2828 if (sig != ESIGNAL_INIT && Mode_compmgr.mode == ECM_MODE_OFF)
2835 if (Conf_compmgr.enable)
2837 IdlerAdd(_ECompMgrIdler, NULL);
2843 CompMgrIpc(const char *params)
2846 char cmd[128], prm[4096];
2849 cmd[0] = prm[0] = '\0';
2854 sscanf(p, "%100s %4000s %n", cmd, prm, &len);
2858 if (!p || cmd[0] == '?')
2860 IpcPrintf("CompMgr - on=%d\n", Mode_compmgr.active);
2862 else if (!strcmp(cmd, "start"))
2867 else if (!strcmp(cmd, "stop"))
2872 else if (!strncmp(cmd, "list", 2))
2876 else if (!strncmp(cmd, "oi", 2))
2882 sscanf(prm, "%lx", &win);
2883 eo = EobjListStackFind(win);
2885 ECompMgrWinDumpInfo("EObj", eo, None, 1);
2889 static const IpcItem CompMgrIpcArray[] = {
2893 "Composite manager functions",
2895 " cm start Start composite manager\n"
2896 " cm stop Stop composite manager\n"}
2899 #define N_IPC_FUNCS (sizeof(CompMgrIpcArray)/sizeof(IpcItem))
2901 static const CfgItem CompMgrCfgItems[] = {
2902 CFG_ITEM_BOOL(Conf_compmgr, enable, 0),
2903 CFG_ITEM_INT(Conf_compmgr, mode, ECM_MODE_ROOT),
2904 CFG_ITEM_INT(Conf_compmgr, shadows.mode, 0),
2905 CFG_ITEM_INT(Conf_compmgr, shadows.offset_x, 3),
2906 CFG_ITEM_INT(Conf_compmgr, shadows.offset_y, 5),
2907 CFG_ITEM_INT(Conf_compmgr, shadows.blur.radius, 5),
2908 CFG_ITEM_INT(Conf_compmgr, shadows.blur.opacity, 75),
2909 CFG_ITEM_INT(Conf_compmgr, shadows.sharp.opacity, 30),
2910 CFG_ITEM_HEX(Conf_compmgr, shadows.color, 0),
2911 CFG_ITEM_BOOL(Conf_compmgr, resize_fix_enable, 0),
2912 CFG_ITEM_BOOL(Conf_compmgr, use_name_pixmap, 0),
2913 #if USE_COMPOSITE_OVERLAY_WINDOW
2914 CFG_ITEM_BOOL(Conf_compmgr, use_cow, 1),
2916 CFG_ITEM_BOOL(Conf_compmgr, fading.enable, 1),
2917 CFG_ITEM_INT(Conf_compmgr, fading.time, 200),
2918 CFG_ITEM_INT(Conf_compmgr, override_redirect.mode, 1),
2919 CFG_ITEM_INT(Conf_compmgr, override_redirect.opacity, 90),
2921 #define N_CFG_ITEMS (sizeof(CompMgrCfgItems)/sizeof(CfgItem))
2926 extern const EModule ModCompMgr;
2927 const EModule ModCompMgr = {
2930 {N_IPC_FUNCS, CompMgrIpcArray},
2931 {N_CFG_ITEMS, CompMgrCfgItems}
2934 #endif /* USE_COMPOSITE */
2937 * $Id: xcompmgr.c,v 1.26 2004/08/14 21:39:51 keithp Exp $
2939 * Copyright © 2003 Keith Packard
2941 * Permission to use, copy, modify, distribute, and sell this software and its
2942 * documentation for any purpose is hereby granted without fee, provided that
2943 * the above copyright notice appear in all copies and that both that
2944 * copyright notice and this permission notice appear in supporting
2945 * documentation, and that the name of Keith Packard not be used in
2946 * advertising or publicity pertaining to distribution of the software without
2947 * specific, written prior permission. Keith Packard makes no
2948 * representations about the suitability of this software for any purpose. It
2949 * is provided "as is" without express or implied warranty.
2951 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2952 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2953 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2954 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2955 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2956 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2957 * PERFORMANCE OF THIS SOFTWARE.
2960 * Modified by Matthew Hawn. I don't know what to say here so follow what it
2961 * says above. Not that I can really do anything about it