e16/src/ecompmgr.c

2264 lines
53 KiB
C
Raw Normal View History

2004-12-28 15:46:49 -08:00
/*
* Copyright (C) 2004-2005 Kim Woelders
2004-12-28 15:46:49 -08:00
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
2005-04-22 00:10:18 -07:00
* This code was originally derived from xcompmgr.c, see original copyright
* notice at end.
* It has been mostly rewritten since, only the shadow code is more or less
* intact.
2004-12-28 15:46:49 -08:00
*/
#include "E.h"
#if USE_COMPOSITE
#include "ecompmgr.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
#define HAS_NAME_WINDOW_PIXMAP 1
#endif
#define CAN_DO_USABLE 0
#define ENABLE_SHADOWS 1
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define EDBUG_TYPE_COMPMGR 161
#define EDBUG_TYPE_COMPMGR2 162
#define EDBUG_TYPE_COMPMGR3 163
#define EDBUG_TYPE_COMPMGR4 164
2004-12-28 15:46:49 -08:00
#define D1printf(fmt...) if(EventDebug(EDBUG_TYPE_COMPMGR))Eprintf(fmt)
#define D2printf(fmt...) if(EventDebug(EDBUG_TYPE_COMPMGR2))Eprintf(fmt)
#define D3printf(fmt...) if(EventDebug(EDBUG_TYPE_COMPMGR3))Eprintf(fmt)
#define D4printf(fmt...) if(EventDebug(EDBUG_TYPE_COMPMGR4))Eprintf(fmt)
2004-12-28 15:46:49 -08:00
#else
#define D1printf(fmt...)
#define D2printf(fmt...)
#endif /* ENABLE_DEBUG */
#define INV_POS 0x01
#define INV_SIZE 0x02
#define INV_OPACITY 0x04
#define INV_SHADOW 0x08
#define INV_GEOM (INV_POS | INV_SIZE)
#define INV_ALL (INV_POS | INV_SIZE | INV_OPACITY | INV_SHADOW)
typedef struct
2004-12-28 15:46:49 -08:00
{
EObj *next; /* Paint order */
EObj *prev; /* Paint order */
2004-12-28 15:46:49 -08:00
#if HAS_NAME_WINDOW_PIXMAP
Pixmap pixmap;
#endif
struct
{
int class; /* FIXME - Remove? */
int map_state; /* FIXME - Remove? */
int depth; /* FIXME - Remove? */
Visual *visual; /* FIXME - Remove? */
int border_width;
} a;
2004-12-28 15:46:49 -08:00
int rcx, rcy, rcw, rch;
#if CAN_DO_USABLE
Bool usable; /* mapped and all damaged at one point */
XRectangle damage_bounds; /* bounds of damage */
#endif
int mode;
char visible;
char damaged;
Damage damage;
Picture picture;
Picture alphaPict;
XserverRegion borderSize;
XserverRegion extents;
XserverRegion clip;
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
Picture shadowPict;
Picture shadow;
int shadow_dx;
int shadow_dy;
int shadow_width;
int shadow_height;
#endif
unsigned int opacity;
unsigned long damage_sequence; /* sequence when damage was created */
} ECmWinInfo;
/*
* Configuration
*/
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
#define ECM_SHADOWS_OFF 0
#define ECM_SHADOWS_SHARP 1 /* use window alpha for shadow; sharp, but precise */
#define ECM_SHADOWS_BLURRED 2 /* use window extents for shadow, blurred */
#endif
static struct
{
char enable;
char resize_fix_enable;
char use_name_pixmap;
2004-12-28 15:46:49 -08:00
int mode;
int shadow;
int shadow_radius;
} Conf_compmgr;
/*
* State
*/
2004-12-28 15:46:49 -08:00
#define ECM_MODE_OFF 0
#define ECM_MODE_ROOT 1
#define ECM_MODE_WINDOW 2
#define ECM_MODE_AUTO 3
static struct
{
char *args;
char active;
#if HAS_NAME_WINDOW_PIXMAP
char use_pixmap;
2004-12-28 15:46:49 -08:00
#endif
EObj *eo_first;
EObj *eo_last;
2004-12-28 15:46:49 -08:00
} Mode_compmgr;
static Picture rootPicture;
static Picture rootBuffer;
static XserverRegion allDamage;
#define OPAQUE 0xffffffff
#define WINDOW_SOLID 0
#define WINDOW_TRANS 1
#define WINDOW_ARGB 2
static void ECompMgrWinSetPicts(EObj * eo);
2004-12-28 15:46:49 -08:00
static void ECompMgrDamageAll(void);
static void ECompMgrHandleRootEvent(XEvent * ev, void *prm);
static void ECompMgrHandleWindowEvent(XEvent * ev, void *prm);
/*
* Regions
*/
static XserverRegion
ERegionCreate(int x, int y, int w, int h)
{
XserverRegion rgn;
XRectangle rct;
rct.x = x;
rct.y = y;
rct.width = w;
rct.height = h;
rgn = XFixesCreateRegion(disp, &rct, 1);
return rgn;
}
static void
ERegionShow(const char *txt, XserverRegion rgn)
{
int i, nr;
XRectangle *pr;
pr = XFixesFetchRegion(disp, rgn, &nr);
2005-04-25 15:07:37 -07:00
if (!pr || nr <= 0)
{
Eprintf(" - region: %s %#lx is empty\n", txt, rgn);
goto done;
}
2004-12-28 15:46:49 -08:00
2005-04-25 15:07:37 -07:00
Eprintf(" - region: %s %#lx:\n", txt, rgn);
2004-12-28 15:46:49 -08:00
for (i = 0; i < nr; i++)
Eprintf("%4d: %4d+%4d %4dx%4d\n", i, pr[i].x, pr[i].y, pr[i].width,
pr[i].height);
2005-04-25 15:07:37 -07:00
done:
if (pr)
XFree(pr);
2004-12-28 15:46:49 -08:00
}
/*
* Pictures
*/
static Picture
EPictureCreateSolid(Bool argb, double a, double r, double g, double b)
{
Display *dpy = disp;
Pixmap pmap;
Picture pict;
XRenderPictFormat *pictfmt;
XRenderPictureAttributes pa;
XRenderColor c;
pmap = XCreatePixmap(dpy, VRoot.win, 1, 1, argb ? 32 : 8);
pictfmt = XRenderFindStandardFormat(dpy,
argb ? PictStandardARGB32 :
PictStandardA8);
pa.repeat = True;
pict = XRenderCreatePicture(dpy, pmap, pictfmt, CPRepeat, &pa);
c.alpha = a * 0xffff;
c.red = r * 0xffff;
c.green = g * 0xffff;
c.blue = b * 0xffff;
XRenderFillRectangle(dpy, PictOpSrc, pict, &c, 0, 0, 1, 1);
XFreePixmap(dpy, pmap);
return pict;
}
static Picture
EPictureCreateBuffer(Window win, int w, int h, int depth, Visual * vis)
{
Picture pict;
Pixmap pmap;
XRenderPictFormat *pictfmt;
pmap = XCreatePixmap(disp, win, w, h, depth);
pictfmt = XRenderFindVisualFormat(disp, vis);
pict = XRenderCreatePicture(disp, pmap, pictfmt, 0, 0);
XFreePixmap(disp, pmap);
return pict;
}
#if 0
static Picture
EPictureCreate(Window win, int depth, Visual * vis)
{
Picture pict;
XRenderPictFormat *pictfmt;
pictfmt = XRenderFindVisualFormat(disp, vis);
pict = XRenderCreatePicture(disp, win, pictfmt, 0, 0);
return pict;
}
#endif
2004-12-28 15:46:49 -08:00
/* Hack to fix redirected window resize bug(?) */
void
ECompMgrMoveResizeFix(EObj * eo, int x, int y, int w, int h)
{
Picture pict;
int wo, ho;
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
if (!cw || !Conf_compmgr.resize_fix_enable)
2004-12-28 15:46:49 -08:00
{
EMoveResizeWindow(eo->win, x, y, w, h);
2004-12-28 15:46:49 -08:00
return;
}
wo = ho = 0;
EGetGeometry(eo->win, NULL, NULL, NULL, &wo, &ho, NULL, NULL);
2004-12-28 15:46:49 -08:00
if (wo <= 0 || ho <= 0 || (wo == w && ho == h))
{
EMoveResizeWindow(eo->win, x, y, w, h);
2004-12-28 15:46:49 -08:00
return;
}
/* Resizing - grab old contents */
2005-04-22 00:10:18 -07:00
pict = EPictureCreateBuffer(eo->win, wo, ho, cw->a.depth, cw->a.visual);
XRenderComposite(disp, PictOpSrc, cw->picture, None, pict,
2004-12-28 15:46:49 -08:00
0, 0, 0, 0, 0, 0, wo, ho);
/* Resize (+move) */
EMoveResizeWindow(eo->win, x, y, w, h);
2004-12-28 15:46:49 -08:00
/* Paste old contents back in */
if (w < wo)
w = wo;
if (h < ho)
h = ho;
2005-04-22 00:10:18 -07:00
XRenderComposite(disp, PictOpSrc, pict, None, cw->picture,
2004-12-28 15:46:49 -08:00
0, 0, 0, 0, 0, 0, w, h);
XRenderFreePicture(disp, pict);
}
/*
* Desktops (move to desktops.c?)
*/
static Picture
DeskBackgroundPictureGet(Desk * d)
2004-12-28 15:46:49 -08:00
{
ECmWinInfo *cw = d->o.cmhook;
2004-12-28 15:46:49 -08:00
Picture pict;
Pixmap pmap;
Bool fill;
XRenderPictFormat *pictfmt;
XRenderPictureAttributes pa;
2005-04-25 15:07:37 -07:00
if (!cw)
{
ECompMgrWinNew(&d->o);
cw = d->o.cmhook;
if (!cw)
return None;
}
if (cw->picture != None)
2005-04-25 15:07:37 -07:00
{
if (d->pmap)
return cw->picture;
XRenderFreePicture(disp, cw->picture);
}
2004-12-28 15:46:49 -08:00
fill = False;
pmap = BackgroundGetPixmap(DeskGetBackground(d->num));
D1printf("DeskBackgroundPictureGet: Desk %d: using pixmap %#lx\n", d->num,
2004-12-28 15:46:49 -08:00
pmap);
if (!pmap)
{
pmap = XCreatePixmap(disp, VRoot.win, 1, 1, VRoot.depth);
fill = True;
}
pa.repeat = True;
pictfmt = XRenderFindVisualFormat(disp, VRoot.vis);
pict = XRenderCreatePicture(disp, pmap, pictfmt, CPRepeat, &pa);
if (fill)
{
/* FIXME - use desk bg color */
XRenderColor c;
c.red = c.green = c.blue = 0x8080;
c.alpha = 0xffff;
XRenderFillRectangle(disp, PictOpSrc, pict, &c, 0, 0, 1, 1);
}
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Not in window mode? */
2004-12-28 15:46:49 -08:00
/* New background, all must be repainted */
ECompMgrDamageAll();
2005-04-25 15:07:37 -07:00
#endif
2004-12-28 15:46:49 -08:00
2005-04-25 15:07:37 -07:00
d->pmap = pmap;
cw->picture = pict;
2004-12-28 15:46:49 -08:00
return pict;
}
static void
DeskBackgroundPictureFree(Desk * d)
2004-12-28 15:46:49 -08:00
{
ECmWinInfo *cw = d->o.cmhook;
2004-12-28 15:46:49 -08:00
Picture pict;
pict = cw->picture;
2004-12-28 15:46:49 -08:00
if (pict == None)
return;
D1printf("DeskBackgroundPictureFree: Desk %d: pict=%#lx\n", d->num, pict);
2005-04-25 15:07:37 -07:00
XClearArea(disp, EoGetWin(d), 0, 0, 0, 0, False);
2004-12-28 15:46:49 -08:00
XRenderFreePicture(disp, pict);
cw->picture = None;
2004-12-28 15:46:49 -08:00
}
/*
* Root (?)
*/
static void
ECompMgrDamageMerge(int desk, XserverRegion damage, int destroy)
2004-12-28 15:46:49 -08:00
{
if (desk)
{
Desk *d = DeskGet(desk);
if (EoGetX(d) != 0 || EoGetY(d) != 0)
{
if (!destroy)
{
XserverRegion region;
region = XFixesCreateRegion(disp, 0, 0);
XFixesCopyRegion(disp, region, damage);
damage = region;
}
XFixesTranslateRegion(disp, damage, EoGetX(d), EoGetY(d));
}
}
2004-12-28 15:46:49 -08:00
if (allDamage)
{
if (EventDebug(EDBUG_TYPE_COMPMGR3))
ERegionShow("ECompMgrDamageMerge add:", damage);
XFixesUnionRegion(disp, allDamage, allDamage, damage);
if (destroy)
XFixesDestroyRegion(disp, damage);
}
else if (!destroy)
{
allDamage = XFixesCreateRegion(disp, 0, 0);
XFixesCopyRegion(disp, allDamage, damage);
}
else
{
allDamage = damage;
}
if (EventDebug(EDBUG_TYPE_COMPMGR3))
ERegionShow("ECompMgrDamageMerge all:", allDamage);
}
static void
ECompMgrDamageAll(void)
{
ECompMgrDamageMerge(0, ERegionCreate(0, 0, VRoot.w, VRoot.h), 1);
2004-12-28 15:46:49 -08:00
}
#if ENABLE_SHADOWS
#define SHADOW_OPACITY 0.75
static Picture blackPicture;
static Picture transBlackPicture;
typedef struct _conv
{
int size;
double *data;
} conv;
static conv *gaussianMap;
static double
gaussian(double r, double x, double y)
{
return ((1 / (sqrt(2 * M_PI * r))) * exp((-(x * x + y * y)) / (2 * r * r)));
}
static conv *
make_gaussian_map(Display * dpy __UNUSED__, double r)
{
conv *c;
int size = ((int)ceil((r * 3)) + 1) & ~1;
int center = size / 2;
int x, y;
double t;
double g;
c = malloc(sizeof(conv) + size * size * sizeof(double));
c->size = size;
c->data = (double *)(c + 1);
t = 0.0;
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
{
g = gaussian(r, (double)(x - center), (double)(y - center));
t += g;
c->data[y * size + x] = g;
}
/* printf ("gaussian total %f\n", t); */
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
{
c->data[y * size + x] /= t;
}
return c;
}
/*
* A picture will help
*
* -center 0 width width+center
* -center +-----+-------------------+-----+
* | | | |
* | | | |
* 0 +-----+-------------------+-----+
* | | | |
* | | | |
* | | | |
* height +-----+-------------------+-----+
* | | | |
* height+ | | | |
* center +-----+-------------------+-----+
*/
static unsigned char
sum_gaussian(conv * map, double opacity, int x, int y, int width, int height)
{
int fx, fy;
double *g_data;
double *g_line = map->data;
int g_size = map->size;
int center = g_size / 2;
int fx_start, fx_end;
int fy_start, fy_end;
double v;
/*
* Compute set of filter values which are "in range",
* that's the set with:
* 0 <= x + (fx-center) && x + (fx-center) < width &&
* 0 <= y + (fy-center) && y + (fy-center) < height
*
* 0 <= x + (fx - center) x + fx - center < width
* center - x <= fx fx < width + center - x
*/
fx_start = center - x;
if (fx_start < 0)
fx_start = 0;
fx_end = width + center - x;
if (fx_end > g_size)
fx_end = g_size;
fy_start = center - y;
if (fy_start < 0)
fy_start = 0;
fy_end = height + center - y;
if (fy_end > g_size)
fy_end = g_size;
g_line = g_line + fy_start * g_size + fx_start;
v = 0;
for (fy = fy_start; fy < fy_end; fy++)
{
g_data = g_line;
g_line += g_size;
for (fx = fx_start; fx < fx_end; fx++)
v += *g_data++;
}
if (v > 1)
v = 1;
return ((unsigned char)(v * opacity * 255.0));
}
static XImage *
make_shadow(Display * dpy, double opacity, int width, int height)
{
XImage *ximage;
unsigned char *data;
int gsize = gaussianMap->size;
int ylimit, xlimit;
int swidth = width + gsize;
int sheight = height + gsize;
int center = gsize / 2;
int x, y;
unsigned char d;
int x_diff;
data = calloc(swidth * sheight, sizeof(unsigned char));
2004-12-28 15:46:49 -08:00
if (!data)
return NULL;
2004-12-28 15:46:49 -08:00
ximage = XCreateImage(dpy, DefaultVisual(dpy, DefaultScreen(dpy)),
8, ZPixmap, 0,
(char *)data,
swidth, sheight, 8, swidth * sizeof(unsigned char));
if (!ximage)
{
free(data);
return NULL;
2004-12-28 15:46:49 -08:00
}
2004-12-28 15:46:49 -08:00
/*
* Build the gaussian in sections
*/
#if 0 /* Never used */
2004-12-28 15:46:49 -08:00
/*
* center (fill the complete data array)
*/
d = sum_gaussian(gaussianMap, opacity, center, center, width, height);
memset(data, d, sheight * swidth);
#endif
2004-12-28 15:46:49 -08:00
/*
* corners
*/
ylimit = gsize;
if (ylimit > sheight / 2)
ylimit = (sheight + 1) / 2;
xlimit = gsize;
if (xlimit > swidth / 2)
xlimit = (swidth + 1) / 2;
for (y = 0; y < ylimit; y++)
for (x = 0; x < xlimit; x++)
{
d = sum_gaussian(gaussianMap, opacity, x - center, y - center, width,
height);
data[y * swidth + x] = d;
data[(sheight - y - 1) * swidth + x] = d;
data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
data[y * swidth + (swidth - x - 1)] = d;
}
/*
* top/bottom
*/
x_diff = swidth - (gsize * 2);
if (x_diff > 0 && ylimit > 0)
{
for (y = 0; y < ylimit; y++)
{
d = sum_gaussian(gaussianMap, opacity, center, y - center, width,
height);
memset(&data[y * swidth + gsize], d, x_diff);
memset(&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
}
}
/*
* sides
*/
for (x = 0; x < xlimit; x++)
{
d = sum_gaussian(gaussianMap, opacity, x - center, center, width,
height);
for (y = gsize; y < sheight - gsize; y++)
{
data[y * swidth + x] = d;
data[y * swidth + (swidth - x - 1)] = d;
}
}
return ximage;
}
static Picture
shadow_picture(Display * dpy, double opacity, int width, int height, int *wp,
int *hp)
{
XImage *shadowImage;
Pixmap shadowPixmap;
Picture shadowPicture;
GC gc;
shadowImage = make_shadow(dpy, opacity, width, height);
if (!shadowImage)
return None;
shadowPixmap = XCreatePixmap(dpy, VRoot.win,
shadowImage->width, shadowImage->height, 8);
shadowPicture = XRenderCreatePicture(dpy, shadowPixmap,
XRenderFindStandardFormat(dpy,
PictStandardA8),
0, 0);
gc = XCreateGC(dpy, shadowPixmap, 0, 0);
XPutImage(dpy, shadowPixmap, gc, shadowImage, 0, 0, 0, 0,
shadowImage->width, shadowImage->height);
*wp = shadowImage->width;
*hp = shadowImage->height;
XFreeGC(dpy, gc);
XDestroyImage(shadowImage);
XFreePixmap(dpy, shadowPixmap);
return shadowPicture;
}
#endif /* ENABLE_SHADOWS */
/*
* Window ops
*/
static XserverRegion
win_extents(Display * dpy, EObj * eo)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
XRectangle r;
#if HAS_NAME_WINDOW_PIXMAP
if (Mode_compmgr.use_pixmap)
{
cw->rcx = eo->x;
cw->rcy = eo->y;
cw->rcw = eo->w + cw->a.border_width * 2;
cw->rch = eo->h + cw->a.border_width * 2;
}
else
2004-12-28 15:46:49 -08:00
#endif
{
cw->rcx = eo->x + cw->a.border_width;
cw->rcy = eo->y + cw->a.border_width;
cw->rcw = eo->w;
cw->rch = eo->h;
}
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
r.x = cw->rcx;
r.y = cw->rcy;
r.width = cw->rcw;
r.height = cw->rch;
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
if (eo->shadow && Conf_compmgr.shadow != ECM_SHADOWS_OFF &&
2005-04-22 00:10:18 -07:00
(Conf_compmgr.shadow == ECM_SHADOWS_SHARP || cw->mode != WINDOW_ARGB) &&
(Conf_compmgr.shadow != ECM_SHADOWS_BLURRED || !EobjIsShaped(eo)))
2004-12-28 15:46:49 -08:00
{
XRectangle sr;
if (Conf_compmgr.shadow == ECM_SHADOWS_SHARP)
{
2005-04-22 00:10:18 -07:00
cw->shadow_dx = 2;
cw->shadow_dy = 7;
cw->shadow_width = cw->rcw;
cw->shadow_height = cw->rcw;
2004-12-28 15:46:49 -08:00
}
else
{
2005-04-22 00:10:18 -07:00
cw->shadow_dx = -Conf_compmgr.shadow_radius * 5 / 4;
cw->shadow_dy = -Conf_compmgr.shadow_radius * 5 / 4;
if (!cw->shadow)
2004-12-28 15:46:49 -08:00
{
double opacity = SHADOW_OPACITY;
2005-04-22 00:10:18 -07:00
if (cw->mode == WINDOW_TRANS)
opacity *= ((double)cw->opacity) / OPAQUE;
cw->shadow = shadow_picture(dpy, opacity, cw->rcw, cw->rch,
&cw->shadow_width,
&cw->shadow_height);
2004-12-28 15:46:49 -08:00
}
}
2005-04-22 00:10:18 -07:00
sr.x = cw->rcx + cw->shadow_dx;
sr.y = cw->rcy + cw->shadow_dy;
sr.width = cw->shadow_width;
sr.height = cw->shadow_height;
2004-12-28 15:46:49 -08:00
if (sr.x < r.x)
{
r.width = (r.x + r.width) - sr.x;
r.x = sr.x;
}
if (sr.y < r.y)
{
r.height = (r.y + r.height) - sr.y;
r.y = sr.y;
}
if (sr.x + sr.width > r.x + r.width)
r.width = sr.x + sr.width - r.x;
if (sr.y + sr.height > r.y + r.height)
r.height = sr.y + sr.height - r.y;
}
#endif
D2printf("win_extents %#lx %d %d %d %d\n", eo->win, r.x, r.y, r.width,
r.height);
return XFixesCreateRegion(dpy, &r, 1);
}
static XserverRegion
border_size(EObj * eo)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
XserverRegion border;
int x, y;
2004-12-28 15:46:49 -08:00
border = XFixesCreateRegionFromWindow(disp, eo->win, WindowRegionBounding);
/* translate this */
2005-04-22 00:10:18 -07:00
x = eo->x + cw->a.border_width;
y = eo->y + cw->a.border_width;
XFixesTranslateRegion(disp, border, x, y);
2004-12-28 15:46:49 -08:00
D2printf("border_size %#lx: %d %d\n", eo->win, x, y);
2005-04-25 15:07:37 -07:00
if (EventDebug(EDBUG_TYPE_COMPMGR3))
ERegionShow("borderSize", border);
2004-12-28 15:46:49 -08:00
return border;
}
Pixmap
ECompMgrWinGetPixmap(const EObj * eo)
{
#if HAS_NAME_WINDOW_PIXMAP
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
return (cw) ? cw->pixmap : None;
2004-12-28 15:46:49 -08:00
#else
eo = NULL;
return None;
#endif
}
static void
ECompMgrWinInvalidate(EObj * eo, int what)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
Display *dpy = disp;
2005-04-22 00:10:18 -07:00
if (!cw)
2004-12-28 15:46:49 -08:00
return;
#if HAS_NAME_WINDOW_PIXMAP
2005-04-22 00:10:18 -07:00
if ((what & INV_SIZE) && cw->pixmap != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XFreePixmap(dpy, cw->pixmap);
cw->pixmap = None;
if (cw->picture != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(dpy, cw->picture);
cw->picture = None;
2004-12-28 15:46:49 -08:00
}
}
#endif
2005-04-22 00:10:18 -07:00
if ((what & INV_GEOM) && cw->borderSize != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XFixesDestroyRegion(dpy, cw->borderSize);
cw->borderSize = None;
2004-12-28 15:46:49 -08:00
}
2005-04-22 00:10:18 -07:00
if ((what & INV_OPACITY) && cw->alphaPict != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(dpy, cw->alphaPict);
cw->alphaPict = None;
2004-12-28 15:46:49 -08:00
}
#if 0 /* Recalculating clip every repaint for now. */
2005-04-22 00:10:18 -07:00
if ((what & INV_SIZE) && cw->clip != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XFixesDestroyRegion(dpy, cw->clip);
cw->clip = None;
2004-12-28 15:46:49 -08:00
}
#endif
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
2005-04-22 00:10:18 -07:00
if ((what & (INV_SIZE | INV_OPACITY | INV_SHADOW)) && cw->shadow != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(dpy, cw->shadow);
cw->shadow = None;
what |= INV_GEOM;
2004-12-28 15:46:49 -08:00
}
2005-04-22 00:10:18 -07:00
if ((what & (INV_SIZE | INV_OPACITY | INV_SHADOW)) && cw->shadowPict != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(dpy, cw->shadowPict);
cw->shadowPict = None;
2004-12-28 15:46:49 -08:00
}
#endif
2005-04-22 00:10:18 -07:00
if ((what & (INV_GEOM | INV_SHADOW)) && cw->extents != None)
{
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Not necessary? */
2005-04-22 00:10:18 -07:00
ECompMgrDamageMerge(cw->extents, 1);
#else
2005-04-22 00:10:18 -07:00
XFixesDestroyRegion(dpy, cw->extents);
#endif
2005-04-22 00:10:18 -07:00
cw->extents = None;
}
2004-12-28 15:46:49 -08:00
}
void
ECompMgrWinChangeOpacity(EObj * eo, unsigned int opacity)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
Display *dpy = disp;
int mode;
XRenderPictFormat *pictfmt;
2005-04-22 00:10:18 -07:00
if (!cw || cw->opacity == opacity)
2004-12-28 15:46:49 -08:00
return;
2005-04-22 00:10:18 -07:00
cw->opacity = opacity;
2004-12-28 15:46:49 -08:00
D1printf("ECompMgrWinChangeOpacity: %#lx opacity=%#x\n", eo->win,
2005-04-22 00:10:18 -07:00
cw->opacity);
2004-12-28 15:46:49 -08:00
if (eo->shown) /* FIXME - ??? */
/* Extents may be unchanged, however, we must repaint */
2005-04-22 00:10:18 -07:00
if (cw->extents != None)
ECompMgrDamageMerge(eo->desk, cw->extents, 0);
/* Invalidate stuff changed by opacity */
ECompMgrWinInvalidate(eo, INV_OPACITY);
2004-12-28 15:46:49 -08:00
pictfmt = XRenderFindVisualFormat(dpy, cw->a.visual);
2004-12-28 15:46:49 -08:00
if (pictfmt && pictfmt->type == PictTypeDirect && pictfmt->direct.alphaMask)
mode = WINDOW_ARGB;
2005-04-22 00:10:18 -07:00
else if (cw->opacity != OPAQUE)
2004-12-28 15:46:49 -08:00
mode = WINDOW_TRANS;
else
mode = WINDOW_SOLID;
2005-04-22 00:10:18 -07:00
cw->mode = mode;
2004-12-28 15:46:49 -08:00
}
void
ECompMgrWinMap(EObj * eo)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
if (!cw)
2004-12-28 15:46:49 -08:00
{
ECompMgrWinNew(eo);
2005-04-22 00:10:18 -07:00
cw = eo->cmhook;
if (!cw)
2004-12-28 15:46:49 -08:00
return;
}
2005-04-25 15:07:37 -07:00
D1printf("ECompMgrWinMap %#lx\n", eo->win);
2005-04-22 00:10:18 -07:00
cw->a.map_state = IsViewable;
cw->visible = 1;
2004-12-28 15:46:49 -08:00
#if CAN_DO_USABLE
2005-04-22 00:10:18 -07:00
cw->damage_bounds.x = cw->damage_bounds.y = 0;
cw->damage_bounds.width = cw->damage_bounds.height = 0;
2004-12-28 15:46:49 -08:00
#endif
2005-04-25 15:07:37 -07:00
if (cw->extents == None)
cw->extents = win_extents(disp, eo);
2005-04-22 00:10:18 -07:00
ECompMgrDamageMerge(eo->desk, cw->extents, 0);
ECompMgrWinSetPicts(eo);
2004-12-28 15:46:49 -08:00
}
static void
finish_unmap_win(EObj * eo)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
cw->visible = 0;
2004-12-28 15:46:49 -08:00
#if 0
2005-04-22 00:10:18 -07:00
cw->damaged = 0;
2004-12-28 15:46:49 -08:00
#if CAN_DO_USABLE
2005-04-22 00:10:18 -07:00
cw->usable = False;
2004-12-28 15:46:49 -08:00
#endif
ECompMgrWinInvalidate(eo, INV_SIZE);
2005-04-22 00:10:18 -07:00
if (cw->extents != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
ECompMgrDamageMerge(eo->desk, cw->extents, 1);
cw->extents = None;
2004-12-28 15:46:49 -08:00
}
#else
2005-04-22 00:10:18 -07:00
if (cw->extents != None)
ECompMgrDamageMerge(eo->desk, cw->extents, 0);
2004-12-28 15:46:49 -08:00
#endif
}
void
ECompMgrWinUnmap(EObj * eo)
2004-12-28 15:46:49 -08:00
{
D1printf("ECompMgrWinUnmap %#lx\n", eo->win);
2005-04-22 00:10:18 -07:00
finish_unmap_win(eo);
2004-12-28 15:46:49 -08:00
}
static void
ECompMgrWinSetPicts(EObj * eo)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
if (eo->type == EOBJ_TYPE_DESK)
{
if (cw->picture == None)
{
cw->picture = DeskBackgroundPictureGet((Desk *) eo);
cw->damaged = 1; /* FIXME - ??? */
}
return;
}
2004-12-28 15:46:49 -08:00
#if HAS_NAME_WINDOW_PIXMAP
2005-04-22 00:10:18 -07:00
if (cw->pixmap != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XFreePixmap(disp, cw->pixmap);
cw->pixmap = None;
if (cw->picture != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(disp, cw->picture);
cw->picture = None;
2004-12-28 15:46:49 -08:00
}
Eprintf("*** ECompMgrWinSetPicts pixmap set!!!\n");
2004-12-28 15:46:49 -08:00
}
if (Mode_compmgr.use_pixmap)
2005-04-22 00:10:18 -07:00
cw->pixmap = XCompositeNameWindowPixmap(disp, eo->win);
2004-12-28 15:46:49 -08:00
#endif
2005-04-22 00:10:18 -07:00
if (cw->picture == None)
2004-12-28 15:46:49 -08:00
{
XRenderPictFormat *pictfmt;
XRenderPictureAttributes pa;
Drawable draw = eo->win;
2004-12-28 15:46:49 -08:00
#if HAS_NAME_WINDOW_PIXMAP
if (cw->pixmap)
draw = cw->pixmap;
2004-12-28 15:46:49 -08:00
#endif
pictfmt = XRenderFindVisualFormat(disp, cw->a.visual);
pa.subwindow_mode = IncludeInferiors;
cw->picture = XRenderCreatePicture(disp, draw,
pictfmt, CPSubwindowMode, &pa);
2005-04-22 00:10:18 -07:00
D2printf("New picture %#lx\n", cw->picture);
2004-12-28 15:46:49 -08:00
}
}
void
ECompMgrWinNew(EObj * eo)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw;
XWindowAttributes attr;
if (!Conf_compmgr.enable) /* FIXME - Here? */
return;
2004-12-28 15:46:49 -08:00
if (!XGetWindowAttributes(disp, eo->win, &attr))
return;
if (attr.class == InputOnly)
return;
2005-04-22 00:10:18 -07:00
cw = Ecalloc(1, sizeof(ECmWinInfo));
if (!cw)
2004-12-28 15:46:49 -08:00
return;
D1printf("ECompMgrWinNew %#lx\n", eo->win);
2005-04-22 00:10:18 -07:00
eo->cmhook = cw;
2005-04-22 00:10:18 -07:00
cw->damaged = 0;
2004-12-28 15:46:49 -08:00
#if CAN_DO_USABLE
2005-04-22 00:10:18 -07:00
cw->usable = False;
2004-12-28 15:46:49 -08:00
#endif
cw->a.class = attr.class; /* FIXME - remove */
cw->a.map_state = attr.map_state; /* FIXME - remove */
cw->a.depth = attr.depth;
cw->a.visual = attr.visual;
cw->a.border_width = attr.border_width;
if (eo->type != EOBJ_TYPE_DESK)
{
if (Conf_compmgr.mode == ECM_MODE_WINDOW)
XCompositeRedirectWindow(disp, eo->win, CompositeRedirectManual);
2005-04-22 00:10:18 -07:00
cw->damage_sequence = NextRequest(disp);
cw->damage = XDamageCreate(disp, eo->win, XDamageReportNonEmpty);
2004-12-28 15:46:49 -08:00
}
2005-04-22 00:10:18 -07:00
cw->picture = None;
2004-12-28 15:46:49 -08:00
#if HAS_NAME_WINDOW_PIXMAP
2005-04-22 00:10:18 -07:00
cw->pixmap = None;
2004-12-28 15:46:49 -08:00
#endif
#if 0 /* FIXME - Remove? */
2004-12-28 15:46:49 -08:00
ECompMgrWinSetPicts(eo);
#endif
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
cw->alphaPict = None;
cw->borderSize = None;
cw->extents = None;
cw->clip = None;
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
2005-04-22 00:10:18 -07:00
cw->shadowPict = None;
cw->shadow = None;
cw->shadow_dx = 0;
cw->shadow_dy = 0;
cw->shadow_width = 0;
cw->shadow_height = 0;
2004-12-28 15:46:49 -08:00
#endif
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Do we need this? */
if (Conf_compmgr.mode == ECM_MODE_WINDOW)
ESelectInputAdd(eo->win, StructureNotifyMask);
2004-12-28 15:46:49 -08:00
#endif
2005-04-22 00:10:18 -07:00
cw->opacity = 0xdeadbeef;
2004-12-28 15:46:49 -08:00
ECompMgrWinChangeOpacity(eo, eo->opacity);
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Do we need this? */
/* Find new window region */
2005-04-22 00:10:18 -07:00
cw->extents = win_extents(disp, eo);
#endif
2004-12-28 15:46:49 -08:00
EventCallbackRegister(eo->win, 0, ECompMgrHandleWindowEvent, eo);
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Not necessary? */
2005-04-22 00:10:18 -07:00
if (cw->a.map_state == IsViewable)
ECompMgrWinMap(eo, cw->damage_sequence - 1, False);
2004-12-28 15:46:49 -08:00
#endif
}
void
ECompMgrWinMoveResize(EObj * eo, int change_xy, int change_wh, int change_bw)
2004-12-28 15:46:49 -08:00
{
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
XserverRegion damage = None;
int invalidate;
2004-12-28 15:46:49 -08:00
D1printf("ECompMgrWinMoveResize %#lx xy=%d wh=%d bw=%d\n",
eo->win, change_xy, change_wh, change_bw);
2004-12-28 15:46:49 -08:00
invalidate = 0;
if (change_xy || change_bw)
invalidate |= INV_POS;
if (change_wh || change_bw)
invalidate |= INV_SIZE;
if (!invalidate)
return;
if (!eo->shown)
2004-12-28 15:46:49 -08:00
{
ECompMgrWinInvalidate(eo, invalidate);
return;
}
2004-12-28 15:46:49 -08:00
/* Invalidate old window region */
damage = XFixesCreateRegion(disp, 0, 0);
if (cw->extents != None)
XFixesCopyRegion(disp, damage, cw->extents);
if (EventDebug(EDBUG_TYPE_COMPMGR3))
ERegionShow("old-extents:", damage);
2004-12-28 15:46:49 -08:00
ECompMgrWinInvalidate(eo, invalidate);
2004-12-28 15:46:49 -08:00
if (invalidate & INV_SIZE) /* FIXME - ??? */
ECompMgrWinSetPicts(eo);
/* Find new window region */
cw->extents = win_extents(disp, eo);
#if 1
/* Hmmm. Why if not changed? - To get shadows painted. */
/* Invalidate new window region */
XFixesUnionRegion(disp, damage, damage, cw->extents);
2005-04-25 15:07:37 -07:00
#endif
if (damage != None)
ECompMgrDamageMerge(eo->desk, damage, 1);
}
static void
ECompMgrWinConfigure(EObj * eo, XEvent * ev)
{
ECmWinInfo *cw = eo->cmhook;
2005-04-25 15:07:37 -07:00
int x, y, w, h, bw;
int change_xy, change_wh, change_bw;
x = ev->xconfigure.x;
y = ev->xconfigure.y;
w = ev->xconfigure.width;
h = ev->xconfigure.height;
2005-04-25 15:07:37 -07:00
bw = ev->xconfigure.border_width;
change_xy = eo->x != x || eo->y != y;
change_wh = eo->w != w || eo->h != h;
change_bw = cw->a.border_width != bw;
eo->x = x;
eo->y = y;
eo->w = w;
eo->h = h;
cw->a.border_width = bw;
ECompMgrWinMoveResize(eo, change_xy, change_wh, change_bw);
2004-12-28 15:46:49 -08:00
}
void
ECompMgrWinReparent(EObj * eo, int desk, int change_xy)
{
ECmWinInfo *cw = eo->cmhook;
D1printf("ECompMgrWinReparent %#lx %#lx d=%d->%d x,y=%d,%d %d\n",
eo->win, cw->extents, eo->desk, desk, eo->x, eo->y, change_xy);
/* Invalidate old window region */
if (EventDebug(EDBUG_TYPE_COMPMGR3))
ERegionShow("old-extents:", cw->extents);
ECompMgrDamageMerge(eo->desk, cw->extents, change_xy);
if (change_xy)
{
cw->extents = None;
ECompMgrWinInvalidate(eo, INV_POS);
/* Find new window region */
cw->extents = win_extents(disp, eo);
ECompMgrDamageMerge(desk, cw->extents, 0);
}
}
2004-12-28 15:46:49 -08:00
static void
ECompMgrWinCirculate(EObj * eo, XEvent * ev)
{
D1printf("ECompMgrWinCirculate %#lx %#lx\n", ev->xany.window, eo->win);
/* FIXME - Check if stacking was changed */
}
static void
finish_destroy_win(EObj * eo, Bool gone)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
if (!gone)
finish_unmap_win(eo);
ECompMgrWinInvalidate(eo, INV_ALL);
2005-04-22 00:10:18 -07:00
if (cw->picture != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XRenderFreePicture(disp, cw->picture);
cw->picture = None;
2004-12-28 15:46:49 -08:00
}
2005-04-22 00:10:18 -07:00
if (cw->damage != None)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
XDamageDestroy(disp, cw->damage);
cw->damage = None;
2004-12-28 15:46:49 -08:00
}
_EFREE(eo->cmhook);
}
void
2005-04-25 15:07:37 -07:00
ECompMgrWinDel(EObj * eo, Bool gone, Bool do_fade __UNUSED__)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
2005-04-22 00:10:18 -07:00
if (!cw)
2004-12-28 15:46:49 -08:00
return;
D1printf("ECompMgrWinDel %#lx\n", eo->win);
2005-04-25 15:07:37 -07:00
if (eo->type == EOBJ_TYPE_DESK)
{
DeskBackgroundPictureFree((Desk *) eo);
}
else
{
if (Conf_compmgr.mode == ECM_MODE_WINDOW)
XCompositeUnredirectWindow(disp, eo->win, CompositeRedirectManual);
}
2005-04-25 15:07:37 -07:00
finish_destroy_win(eo, gone);
2004-12-28 15:46:49 -08:00
EventCallbackUnregister(eo->win, 0, ECompMgrHandleWindowEvent, eo);
}
static void
ECompMgrWinDamage(EObj * eo, XEvent * ev __UNUSED__)
{
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw = eo->cmhook;
2004-12-28 15:46:49 -08:00
Display *dpy = disp;
XDamageNotifyEvent *de = (XDamageNotifyEvent *) ev;
XserverRegion parts;
D1printf("ECompMgrWinDamage %#lx %#lx damaged=%d %d,%d %dx%d\n",
2005-04-22 00:10:18 -07:00
ev->xany.window, eo->win, cw->damaged,
2004-12-28 15:46:49 -08:00
de->area.x, de->area.y, de->area.width, de->area.height);
#if CAN_DO_USABLE
2005-04-22 00:10:18 -07:00
if (!cw->usable)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
if (cw->damage_bounds.width == 0 || cw->damage_bounds.height == 0)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
cw->damage_bounds = de->area;
2004-12-28 15:46:49 -08:00
}
else
{
2005-04-22 00:10:18 -07:00
if (de->area.x < cw->damage_bounds.x)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
cw->damage_bounds.width += (cw->damage_bounds.x - de->area.x);
cw->damage_bounds.x = de->area.x;
2004-12-28 15:46:49 -08:00
}
2005-04-22 00:10:18 -07:00
if (de->area.y < cw->damage_bounds.y)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
cw->damage_bounds.height +=
(cw->damage_bounds.y - de->area.y);
cw->damage_bounds.y = de->area.y;
2004-12-28 15:46:49 -08:00
}
if (de->area.x + de->area.width >
2005-04-22 00:10:18 -07:00
cw->damage_bounds.x + cw->damage_bounds.width)
cw->damage_bounds.width =
de->area.x + de->area.width - cw->damage_bounds.x;
2004-12-28 15:46:49 -08:00
if (de->area.y + de->area.height >
2005-04-22 00:10:18 -07:00
cw->damage_bounds.y + cw->damage_bounds.height)
cw->damage_bounds.height =
de->area.y + de->area.height - cw->damage_bounds.y;
2004-12-28 15:46:49 -08:00
}
#if 0
printf("unusable damage %d, %d: %d x %d bounds %d, %d: %d x %d\n",
2005-04-22 00:10:18 -07:00
de->area.x, de->area.y, de->area.width, de->area.height,
cw->damage_bounds.x, cw->damage_bounds.y,
cw->damage_bounds.width, cw->damage_bounds.height);
2004-12-28 15:46:49 -08:00
#endif
2005-04-22 00:10:18 -07:00
if (cw->damage_bounds.x <= 0 &&
cw->damage_bounds.y <= 0 &&
eo->width <= cw->damage_bounds.x + cw->damage_bounds.width &&
eo->height <= cw->damage_bounds.y + cw->damage_bounds.height)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
cw->usable = True;
2004-12-28 15:46:49 -08:00
}
}
2005-04-22 00:10:18 -07:00
if (!cw->usable)
2004-12-28 15:46:49 -08:00
return;
#else
de = NULL;
#endif
2005-04-22 00:10:18 -07:00
if (!cw->damaged)
2004-12-28 15:46:49 -08:00
{
parts = win_extents(dpy, eo);
2005-04-22 00:10:18 -07:00
XDamageSubtract(dpy, cw->damage, None, None);
cw->damaged = 1;
2004-12-28 15:46:49 -08:00
}
else
{
parts = XFixesCreateRegion(dpy, 0, 0);
2005-04-22 00:10:18 -07:00
XDamageSubtract(dpy, cw->damage, None, parts);
2004-12-28 15:46:49 -08:00
XFixesTranslateRegion(dpy, parts,
2005-04-22 00:10:18 -07:00
eo->x + cw->a.border_width,
eo->y + cw->a.border_width);
2004-12-28 15:46:49 -08:00
#if ENABLE_SHADOWS
if (Conf_compmgr.shadow == ECM_SHADOWS_SHARP)
{
XserverRegion o;
o = XFixesCreateRegion(dpy, 0, 0);
XFixesCopyRegion(dpy, o, parts);
2005-04-22 00:10:18 -07:00
XFixesTranslateRegion(dpy, o, cw->shadow_dx, cw->shadow_dy);
2004-12-28 15:46:49 -08:00
XFixesUnionRegion(dpy, parts, parts, o);
XFixesDestroyRegion(dpy, o);
}
#endif
}
ECompMgrDamageMerge(eo->desk, parts, 1);
2004-12-28 15:46:49 -08:00
}
/* Ensure that the blend mask is up to date */
static void
2005-04-22 00:10:18 -07:00
ECompMgrCheckAlphaMask(ECmWinInfo * cw)
2004-12-28 15:46:49 -08:00
{
2005-04-22 00:10:18 -07:00
if (cw->opacity != OPAQUE && !cw->alphaPict)
cw->alphaPict = EPictureCreateSolid(False, (double)cw->opacity / OPAQUE,
0, 0, 0);
2004-12-28 15:46:49 -08:00
}
static int
ECompMgrRepaintDetermineOrder(EObj * const *lst, int num, EObj ** first,
EObj ** last, int desk)
{
EObj *eo, *eo_prev, *eo_first;
int i, stop;
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw;
D4printf("ECompMgrRepaintDetermineOrder %d\n", desk);
if (!lst)
lst = EobjListStackGet(&num);
/* Determine overall paint order, top to bottom */
stop = 0;
eo_first = eo_prev = NULL;
for (i = 0; i < num; i++)
{
eo = lst[i];
2005-04-25 15:07:37 -07:00
if (!eo->shown || eo->desk != desk)
continue;
D4printf(" - %#lx desk=%d shown=%d\n", eo->win, eo->desk, eo->shown);
if (eo->type == EOBJ_TYPE_DESK)
{
EObj *eo1, *eo2;
ECmWinInfo *ec1;
Desk *d = (Desk *) eo;
if (!d->viewable)
continue;
stop = ECompMgrRepaintDetermineOrder(lst, num, &eo1, &eo2,
((Desk *) eo)->num);
if (eo1)
{
ec1 = eo1->cmhook;
if (!eo_first)
eo_first = eo1;
if (eo_prev)
((ECmWinInfo *) (eo_prev->cmhook))->next = eo1;
((ECmWinInfo *) (eo1->cmhook))->prev = eo_prev;
eo_prev = eo2;
}
ECompMgrWinSetPicts(&d->o);
}
2005-04-22 00:10:18 -07:00
cw = eo->cmhook;
2005-04-25 15:07:37 -07:00
if (!cw)
continue;
D4printf(" - %#lx desk=%d shown=%d vis=%d dam=%d pict=%#lx\n",
2005-04-22 00:10:18 -07:00
eo->win, eo->desk, eo->shown, cw->visible, cw->damaged,
cw->picture);
2005-04-22 00:10:18 -07:00
if (!cw->visible)
continue;
#if CAN_DO_USABLE
2005-04-22 00:10:18 -07:00
if (!cw->usable)
continue;
#endif
2005-04-22 00:10:18 -07:00
if (!cw->damaged)
continue;
2005-04-22 00:10:18 -07:00
if (!cw->picture)
continue;
D4printf
("ECompMgrRepaintDetermineOrder hook in %d - %#lx desk=%d shown=%d\n",
desk, eo->win, eo->desk, eo->shown);
if (!eo_first)
eo_first = eo;
2005-04-22 00:10:18 -07:00
cw->prev = eo_prev;
if (eo_prev)
((ECmWinInfo *) (eo_prev->cmhook))->next = eo;
eo_prev = eo;
2005-04-22 00:10:18 -07:00
/* FIXME - We should break when the repaint region (cw->clip) becomes empty */
if (eo->type == EOBJ_TYPE_DESK && eo->x == 0 && eo->y == 0)
stop = 1;
if (stop)
break;
}
if (eo_prev)
((ECmWinInfo *) (eo_prev->cmhook))->next = NULL;
*first = eo_first;
*last = eo_prev;
return stop;
}
2005-04-25 15:07:37 -07:00
static void
ERegionSubtractOffset(XserverRegion dst, int dx, int dy, XserverRegion src)
{
Display *dpy = disp;
XserverRegion reg;
if (dx == 0 && dy == 0)
{
reg = src;
}
else
{
reg = XFixesCreateRegion(dpy, 0, 0);
XFixesCopyRegion(dpy, reg, src);
XFixesTranslateRegion(dpy, reg, dx, dy);
}
XFixesSubtractRegion(dpy, dst, dst, reg);
if (reg != src)
XFixesDestroyRegion(dpy, reg);
}
static void
ECompMgrRepaintObj(Picture pbuf, XserverRegion region, EObj * eo, int mode)
{
Display *dpy = disp;
2005-04-22 00:10:18 -07:00
ECmWinInfo *cw;
Desk *d = DeskGet(eo->desk);
int x, y;
2005-04-22 00:10:18 -07:00
cw = eo->cmhook;
#if 0
ECompMgrWinSetPicts(eo);
#endif
2005-04-25 15:07:37 -07:00
D2printf("ECompMgrRepaintObj mode=%d %#lx %s\n", mode, eo->win, eo->name);
/* Region of shaped window in screen coordinates */
2005-04-22 00:10:18 -07:00
if (!cw->borderSize)
cw->borderSize = border_size(eo);
if (EventDebug(EDBUG_TYPE_COMPMGR3))
2005-04-25 15:07:37 -07:00
ERegionShow("borderSize", cw->borderSize);
/* Region of window in screen coordinates, including shadows */
2005-04-22 00:10:18 -07:00
if (!cw->extents)
cw->extents = win_extents(dpy, eo);
if (EventDebug(EDBUG_TYPE_COMPMGR3))
2005-04-25 15:07:37 -07:00
ERegionShow("extents", cw->extents);
x = EoGetX(d);
y = EoGetY(d);
if (mode == 0)
{
/* Painting opaque windows top down, updating clip regions. */
2005-04-22 00:10:18 -07:00
cw->clip = XFixesCreateRegion(dpy, 0, 0);
XFixesCopyRegion(dpy, cw->clip, region);
2005-04-22 00:10:18 -07:00
switch (cw->mode)
{
case WINDOW_SOLID:
2005-04-25 15:07:37 -07:00
D2printf(" * solid pict=%#lx d=%d l=%d\n",
cw->picture, eo->desk, eo->ilayer);
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, region);
2005-04-22 00:10:18 -07:00
XRenderComposite(dpy, PictOpSrc, cw->picture, None, pbuf,
0, 0, 0, 0, x + cw->rcx, y + cw->rcy, cw->rcw,
cw->rch);
2005-04-25 15:07:37 -07:00
ERegionSubtractOffset(region, x, y, cw->borderSize);
break;
}
}
else
{
/* Painting trans stuff bottom up. */
2005-04-22 00:10:18 -07:00
switch (cw->mode)
{
case WINDOW_TRANS:
case WINDOW_ARGB:
2005-04-25 15:07:37 -07:00
D2printf(" * trans pict=%#lx d=%d l=%d\n",
cw->picture, eo->desk, eo->ilayer);
2005-04-22 00:10:18 -07:00
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, cw->clip);
ECompMgrCheckAlphaMask(cw);
XRenderComposite(dpy, PictOpOver, cw->picture, cw->alphaPict, pbuf,
0, 0, 0, 0, x + cw->rcx, y + cw->rcy, cw->rcw,
cw->rch);
break;
}
#if ENABLE_SHADOWS
switch (Conf_compmgr.shadow)
{
case ECM_SHADOWS_OFF:
break;
case ECM_SHADOWS_SHARP:
2005-04-22 00:10:18 -07:00
if (cw->opacity != OPAQUE && !cw->shadowPict)
cw->shadowPict = EPictureCreateSolid(True,
(double)cw->opacity /
OPAQUE * 0.3, 0, 0, 0);
2005-04-25 15:07:37 -07:00
ERegionSubtractOffset(cw->clip, x, y, cw->borderSize);
2005-04-22 00:10:18 -07:00
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, cw->clip);
XRenderComposite(dpy, PictOpOver,
2005-04-22 00:10:18 -07:00
cw->shadowPict ? cw->
shadowPict : transBlackPicture, cw->picture, pbuf,
0, 0, 0, 0,
x + cw->rcx + cw->shadow_dx,
y + cw->rcy + cw->shadow_dy,
cw->shadow_width, cw->shadow_height);
break;
case ECM_SHADOWS_BLURRED:
2005-04-25 15:07:37 -07:00
if (cw->shadow == None)
break;
ERegionSubtractOffset(cw->clip, x, y, cw->borderSize);
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, cw->clip);
XRenderComposite(dpy, PictOpOver, blackPicture, cw->shadow, pbuf,
0, 0, 0, 0,
2005-04-25 15:07:37 -07:00
x + cw->rcx + cw->shadow_dx,
y + cw->rcy + cw->shadow_dy,
cw->shadow_width, cw->shadow_height);
break;
}
#endif
2005-04-22 00:10:18 -07:00
XFixesDestroyRegion(dpy, cw->clip);
cw->clip = None;
}
}
2004-12-28 15:46:49 -08:00
static void
ECompMgrRepaint(void)
{
Display *dpy = disp;
XserverRegion region;
EObj *eo;
2004-12-28 15:46:49 -08:00
Picture pict, pbuf;
Desk *d = DeskGet(0);
region = XFixesCreateRegion(disp, 0, 0);
XFixesCopyRegion(disp, region, allDamage);
2004-12-28 15:46:49 -08:00
D2printf("ECompMgrRepaint rootBuffer=%#lx rootPicture=%#lx\n",
rootBuffer, rootPicture);
if (EventDebug(EDBUG_TYPE_COMPMGR3))
2005-04-25 15:07:37 -07:00
ERegionShow("allDamage", region);
2004-12-28 15:46:49 -08:00
if (!rootBuffer)
rootBuffer = EPictureCreateBuffer(VRoot.win, VRoot.w, VRoot.h,
VRoot.depth, VRoot.vis);
pbuf = rootBuffer;
if (!d)
return;
2004-12-28 15:46:49 -08:00
/* Do paint order list linking */
ECompMgrRepaintDetermineOrder(NULL, 0, &Mode_compmgr.eo_first,
&Mode_compmgr.eo_last, 0);
2004-12-28 15:46:49 -08:00
/* Paint opaque windows top down, adjusting clip regions */
for (eo = Mode_compmgr.eo_first; eo;
eo = ((ECmWinInfo *) (eo->cmhook))->next)
ECompMgrRepaintObj(pbuf, region, eo, 0);
if (EventDebug(EDBUG_TYPE_COMPMGR2))
2005-04-25 15:07:37 -07:00
ERegionShow("after opaque", region);
/* Repaint background, clipped by damage region and opaque windows */
pict = DeskBackgroundPictureGet(d);
D1printf("ECompMgrRepaint desk picture=%#lx\n", pict);
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, region);
XRenderComposite(dpy, PictOpSrc, pict, None, pbuf,
0, 0, 0, 0, 0, 0, VRoot.w, VRoot.h);
/* Paint trans windows and shadows bottom up */
for (eo = Mode_compmgr.eo_last; eo; eo = ((ECmWinInfo *) (eo->cmhook))->prev)
ECompMgrRepaintObj(pbuf, None, eo, 1);
2004-12-28 15:46:49 -08:00
if (pbuf != rootPicture)
{
XFixesSetPictureClipRegion(dpy, pbuf, 0, 0, allDamage);
2004-12-28 15:46:49 -08:00
XRenderComposite(dpy, PictOpSrc, pbuf, None, rootPicture,
0, 0, 0, 0, 0, 0, VRoot.w, VRoot.h);
}
XFixesDestroyRegion(dpy, region);
XFixesDestroyRegion(dpy, allDamage);
2004-12-28 15:46:49 -08:00
allDamage = None;
}
static void
ECompMgrRootConfigure(void *prm __UNUSED__, XEvent * ev)
{
Display *dpy = disp;
D1printf("ECompMgrRootConfigure root\n");
if (ev->xconfigure.window == VRoot.win)
{
if (rootBuffer)
{
XRenderFreePicture(dpy, rootBuffer);
rootBuffer = None;
}
#if 0 /* Should be handled elsewhere */
VRoot.w = ev->xconfigure.width;
VRoot.h = ev->xconfigure.height;
#endif
}
return;
}
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Need this? */
2004-12-28 15:46:49 -08:00
static void
ECompMgrRootExpose(void *prm __UNUSED__, XEvent * ev)
{
Display *dpy = disp;
static XRectangle *expose_rects = 0;
static int size_expose = 0;
static int n_expose = 0;
int more = ev->xexpose.count + 1;
if (ev->xexpose.window != VRoot.win)
return;
D1printf("ECompMgrRootExpose %d %d %d\n", n_expose, size_expose,
ev->xexpose.count);
if (n_expose == size_expose)
{
if (expose_rects)
{
expose_rects = realloc(expose_rects,
(size_expose + more) * sizeof(XRectangle));
size_expose += more;
}
else
{
expose_rects = malloc(more * sizeof(XRectangle));
size_expose = more;
}
}
expose_rects[n_expose].x = ev->xexpose.x;
expose_rects[n_expose].y = ev->xexpose.y;
expose_rects[n_expose].width = ev->xexpose.width;
expose_rects[n_expose].height = ev->xexpose.height;
n_expose++;
if (ev->xexpose.count == 0)
{
XserverRegion region;
region = XFixesCreateRegion(dpy, expose_rects, n_expose);
ECompMgrDamageMerge(0, region, 1);
2004-12-28 15:46:49 -08:00
n_expose = 0;
}
}
2005-04-25 15:07:37 -07:00
#endif
2004-12-28 15:46:49 -08:00
static void
ECompMgrDeskChanged(int desk)
{
Desk *d = DeskGet(desk);
if (!d || !d->o.cmhook)
return;
2004-12-28 15:46:49 -08:00
D1printf("ECompMgrDeskChanged: desk=%d\n", desk);
DeskBackgroundPictureFree(d);
2004-12-28 15:46:49 -08:00
}
#if ENABLE_SHADOWS
static void
ECompMgrShadowsInit(int mode, int cleanup)
{
if (mode == ECM_SHADOWS_BLURRED)
gaussianMap = make_gaussian_map(disp, Conf_compmgr.shadow_radius);
else
{
if (gaussianMap)
free(gaussianMap);
gaussianMap = NULL;
}
if (mode != ECM_SHADOWS_OFF)
blackPicture = EPictureCreateSolid(True, 1, 0, 0, 0);
else
{
if (blackPicture)
XRenderFreePicture(disp, blackPicture);
blackPicture = None;
}
if (mode == ECM_SHADOWS_SHARP)
transBlackPicture = EPictureCreateSolid(True, 0.3, 0, 0, 0);
else
{
if (transBlackPicture)
XRenderFreePicture(disp, transBlackPicture);
transBlackPicture = None;
}
if (cleanup)
{
EObj *const *lst;
int i, num;
lst = EobjListStackGet(&num);
for (i = 0; i < num; i++)
ECompMgrWinInvalidate(lst[i], INV_SHADOW);
}
}
#else
#define ECompMgrShadowsInit(mode, cleanup)
#endif
static void
ECompMgrStart(void)
{
EObj *const *lst;
int i, num;
2004-12-28 15:46:49 -08:00
XRenderPictFormat *pictfmt;
XRenderPictureAttributes pa;
if (!Conf_compmgr.enable || Mode_compmgr.active)
return;
Mode_compmgr.active = 1;
pa.subwindow_mode = IncludeInferiors;
pictfmt = XRenderFindVisualFormat(disp, VRoot.vis);
rootPicture =
XRenderCreatePicture(disp, VRoot.win, pictfmt, CPSubwindowMode, &pa);
ECompMgrShadowsInit(Conf_compmgr.shadow, 0);
switch (Conf_compmgr.mode)
{
case ECM_MODE_ROOT:
XCompositeRedirectSubwindows(disp, VRoot.win, CompositeRedirectManual);
ESelectInputAdd(VRoot.win,
2004-12-28 15:46:49 -08:00
SubstructureNotifyMask |
ExposureMask | StructureNotifyMask);
2004-12-28 15:46:49 -08:00
break;
case ECM_MODE_WINDOW:
ESelectInputAdd(VRoot.win,
SubstructureNotifyMask |
ExposureMask | StructureNotifyMask);
break;
2004-12-28 15:46:49 -08:00
case ECM_MODE_AUTO:
XCompositeRedirectSubwindows(disp, VRoot.win,
CompositeRedirectAutomatic);
break;
}
allDamage = None;
if (Conf_compmgr.mode != ECM_MODE_AUTO)
{
ECompMgrDamageAll();
#if 0 /* FIXME - Remove? */
2004-12-28 15:46:49 -08:00
ECompMgrRepaint();
#endif
2004-12-28 15:46:49 -08:00
}
EventCallbackRegister(VRoot.win, 0, ECompMgrHandleRootEvent, NULL);
lst = EobjListStackGet(&num);
for (i = 0; i < num; i++)
{
ECompMgrWinNew(lst[i]);
if (lst[i]->shown)
ECompMgrWinMap(lst[i]);
}
2004-12-28 15:46:49 -08:00
}
static void
ECompMgrStop(void)
{
EObj *const *lst;
int i, num;
if (!Mode_compmgr.active)
return;
Mode_compmgr.active = 0;
if (rootPicture)
XRenderFreePicture(disp, rootPicture);
rootPicture = None;
if (rootBuffer)
XRenderFreePicture(disp, rootBuffer);
rootBuffer = None;
DeskBackgroundPictureFree(DeskGet(0));
2004-12-28 15:46:49 -08:00
ECompMgrShadowsInit(ECM_SHADOWS_OFF, 0);
lst = EobjListStackGet(&num);
for (i = 0; i < num; i++)
ECompMgrWinDel(lst[i], False, False);
if (allDamage)
XFixesDestroyRegion(disp, allDamage);
allDamage = None;
if (Conf_compmgr.mode == ECM_MODE_ROOT)
XCompositeUnredirectSubwindows(disp, VRoot.win, CompositeRedirectManual);
2004-12-28 15:46:49 -08:00
EventCallbackUnregister(VRoot.win, 0, ECompMgrHandleRootEvent, NULL);
}
void
ECompMgrConfigGet(cfg_composite * cfg)
{
cfg->enable = Conf_compmgr.enable;
cfg->shadow = Conf_compmgr.shadow;
}
void
ECompMgrConfigSet(const cfg_composite * cfg)
{
if (Conf_compmgr.mode == ECM_MODE_OFF)
{
if (cfg->enable)
DialogOK("Enable Composite Error",
_("Cannot enable Composite Manager.\n"
"Use xdpyinfo to check that\n"
"Composite, Damage, Fixes, and Render\n"
"extensions are loaded."));
return;
}
2004-12-28 15:46:49 -08:00
if (cfg->enable != Conf_compmgr.enable)
{
Conf_compmgr.enable = cfg->enable;
Conf_compmgr.shadow = cfg->shadow;
if (cfg->enable)
ECompMgrStart();
else
ECompMgrStop();
}
else
{
if (cfg->shadow != Conf_compmgr.shadow)
{
Conf_compmgr.shadow = cfg->shadow;
if (Conf_compmgr.enable)
{
ECompMgrShadowsInit(Conf_compmgr.shadow, 1);
ECompMgrDamageAll();
}
}
}
}
#if 0 /* FIXME - Remove */
2004-12-28 15:46:49 -08:00
int
ECompMgrActive(void)
2004-12-28 15:46:49 -08:00
{
return Mode_compmgr.active;
}
#endif
2004-12-28 15:46:49 -08:00
/*
* Event handlers
*/
#define USE_WINDOW_EVENTS 0
2004-12-28 15:46:49 -08:00
static void
ECompMgrHandleWindowEvent(XEvent * ev, void *prm)
{
EObj *eo = prm;
D2printf("ECompMgrHandleWindowEvent: type=%d\n", ev->type);
2004-12-28 15:46:49 -08:00
switch (ev->type)
{
#if USE_WINDOW_EVENTS
2004-12-28 15:46:49 -08:00
case ConfigureNotify:
ECompMgrWinConfigure(eo, ev);
break;
case MapNotify:
ECompMgrWinMap(eo);
2004-12-28 15:46:49 -08:00
break;
case UnmapNotify:
2005-04-25 15:07:37 -07:00
if (eo->type == EOBJ_TYPE_EXT && eo->cmhook)
{
ECompMgrWinUnmap(eo);
eo->shown = 0;
}
2004-12-28 15:46:49 -08:00
break;
case CirculateNotify:
ECompMgrWinCirculate(eo, ev);
break;
#endif
case EX_EVENT_DAMAGE_NOTIFY:
ECompMgrWinDamage(eo, ev);
break;
}
}
static void
ECompMgrHandleRootEvent(XEvent * ev, void *prm)
{
EObj *eo;
D2printf("ECompMgrHandleRootEvent: type=%d\n", ev->type);
2004-12-28 15:46:49 -08:00
switch (ev->type)
{
case CreateNotify:
#if 0
case_CreateNotify:
eo = EobjListStackFind(ev->xcreatewindow.window);
if (eo)
ECompMgrWinNew(eo);
#endif
break;
case DestroyNotify:
eo = EobjListStackFind(ev->xdestroywindow.window);
2005-04-25 15:07:37 -07:00
if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
{
ECompMgrWinDel(eo, True, True);
EobjUnregister(ev->xdestroywindow.window);
}
2004-12-28 15:46:49 -08:00
break;
#if 0
2004-12-28 15:46:49 -08:00
case ReparentNotify:
if (Conf_compmgr.mode != ECM_MODE_WINDOW)
{
eo = EobjListStackFind(ev->xreparent.window);
if (eo && eo->cmhook)
ECompMgrWinUnmap(eo);
}
2004-12-28 15:46:49 -08:00
#if 0
if (ev->xreparent.parent == VRoot.win)
goto case_CreateNotify;
eo = EobjListStackFind(ev->xreparent.window);
if (eo)
ECompMgrWinDel(eo, False, True);
#endif
break;
#endif
2004-12-28 15:46:49 -08:00
case ConfigureNotify:
if (ev->xconfigure.window == VRoot.win)
{
ECompMgrRootConfigure(prm, ev);
}
else
{
eo = EobjListStackFind(ev->xconfigure.window);
2005-04-25 15:07:37 -07:00
if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
{
ECompMgrWinConfigure(eo, ev);
}
2004-12-28 15:46:49 -08:00
}
break;
case MapNotify:
eo = EobjListStackFind(ev->xmap.window);
if (!eo)
eo = EobjRegister(ev->xmap.window, EOBJ_TYPE_EXT);
2005-04-25 15:07:37 -07:00
if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
{
eo->shown = 1;
ECompMgrWinMap(eo);
}
2004-12-28 15:46:49 -08:00
break;
case UnmapNotify:
eo = EobjListStackFind(ev->xunmap.window);
2005-04-25 15:07:37 -07:00
if (eo && eo->type == EOBJ_TYPE_EXT && eo->cmhook)
{
ECompMgrWinUnmap(eo);
eo->shown = 0;
}
2004-12-28 15:46:49 -08:00
break;
case CirculateNotify:
eo = EobjListStackFind(ev->xcirculate.window);
if (eo && eo->cmhook)
ECompMgrWinCirculate(eo, ev);
break;
case Expose:
2005-04-25 15:07:37 -07:00
#if 0 /* FIXME - Need this? */
2004-12-28 15:46:49 -08:00
ECompMgrRootExpose(prm, ev);
2005-04-25 15:07:37 -07:00
#endif
2004-12-28 15:46:49 -08:00
break;
}
}
void
ECompMgrParseArgs(const char *args)
{
Mode_compmgr.args = Estrdup(args);
}
/*
* Module functions
*/
static void
ECompMgrInit(void)
{
int events, errors, major, minor;
if (!XCompositeQueryExtension(disp, &events, &errors) ||
!XDamageQueryExtension(disp, &events, &errors) ||
!XFixesQueryExtension(disp, &events, &errors) ||
!XRenderQueryExtension(disp, &events, &errors))
{
Conf_compmgr.mode = ECM_MODE_OFF;
goto done;
}
if (!XDamageQueryVersion(disp, &major, &minor))
{
Conf_compmgr.mode = ECM_MODE_OFF;
goto done;
}
#if HAS_NAME_WINDOW_PIXMAP
Mode_compmgr.use_pixmap =
(major > 0 || minor >= 2) && Conf_compmgr.use_name_pixmap;
2004-12-28 15:46:49 -08:00
#endif
if (Conf_compmgr.mode == ECM_MODE_OFF)
Conf_compmgr.mode = ECM_MODE_ROOT;
/* FIXME - Hardcode for now. */
Conf_compmgr.mode = ECM_MODE_WINDOW;
2004-12-28 15:46:49 -08:00
if (Mode_compmgr.args)
{
switch (Mode_compmgr.args[0])
{
case '0':
Conf_compmgr.mode = ECM_MODE_OFF;
break;
case '1':
Conf_compmgr.mode = ECM_MODE_ROOT;
break;
case '2':
Conf_compmgr.mode = ECM_MODE_WINDOW;
break;
case '3':
Conf_compmgr.mode = ECM_MODE_AUTO;
break;
}
_EFREE(Mode_compmgr.args);
}
done:
if (Conf_compmgr.mode == ECM_MODE_OFF)
Conf_compmgr.enable = 0;
D1printf("ECompMgrInit: enable=%d mode=%d\n", Conf_compmgr.enable,
Conf_compmgr.mode);
}
static void
ECompMgrSighan(int sig, void *prm)
{
if (sig != ESIGNAL_INIT && Conf_compmgr.mode == ECM_MODE_OFF)
return;
switch (sig)
{
case ESIGNAL_INIT:
ECompMgrInit();
ECompMgrStart();
break;
case ESIGNAL_BACKGROUND_CHANGE:
ECompMgrDeskChanged((int)prm);
break;
case ESIGNAL_IDLE:
/* Do we get here on auto? */
if (!allDamage /* || Conf_compmgr.mode == ECM_MODE_AUTO */ )
return;
ECompMgrRepaint();
XSync(disp, False);
break;
}
}
static void
CompMgrIpc(const char *params, Client * c __UNUSED__)
{
const char *p;
char cmd[128], prm[4096];
int len;
cmd[0] = prm[0] = '\0';
p = params;
if (p)
{
len = 0;
sscanf(p, "%100s %4000s %n", cmd, prm, &len);
p += len;
}
if (!p || cmd[0] == '?')
{
IpcPrintf("CompMgr - on=%d\n", Mode_compmgr.active);
}
else if (!strcmp(cmd, "cfg"))
{
SettingsComposite();
}
else if (!strcmp(cmd, "start"))
{
ECompMgrStart();
}
else if (!strcmp(cmd, "stop"))
{
ECompMgrStop();
}
else if (!strncmp(cmd, "list", 2))
{
/* TBD */
}
}
IpcItem CompMgrIpcArray[] = {
{
CompMgrIpc,
"compmgr", "cm",
"Composite manager functions",
" cm ? Show info\n"
" cm cfg Configure\n"
" cm start Start composite manager\n"
" cm stop Stop composite manager\n"}
,
};
#define N_IPC_FUNCS (sizeof(CompMgrIpcArray)/sizeof(IpcItem))
static const CfgItem CompMgrCfgItems[] = {
CFG_ITEM_BOOL(Conf_compmgr, enable, 0),
CFG_ITEM_INT(Conf_compmgr, mode, 1),
CFG_ITEM_INT(Conf_compmgr, shadow, 0),
CFG_ITEM_INT(Conf_compmgr, shadow_radius, 12),
CFG_ITEM_BOOL(Conf_compmgr, resize_fix_enable, 0),
CFG_ITEM_BOOL(Conf_compmgr, use_name_pixmap, 0),
2004-12-28 15:46:49 -08:00
};
#define N_CFG_ITEMS (sizeof(CompMgrCfgItems)/sizeof(CfgItem))
/*
* Module descriptor
*/
EModule ModCompMgr = {
"compmgr", "cm",
ECompMgrSighan,
{N_IPC_FUNCS, CompMgrIpcArray},
{N_CFG_ITEMS, CompMgrCfgItems}
};
#endif /* USE_COMPOSITE */
2005-04-22 00:10:18 -07:00
/*
* $Id: xcompmgr.c,v 1.26 2004/08/14 21:39:51 keithp Exp $
*
* Copyright © 2003 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Modified by Matthew Hawn. I don't know what to say here so follow what it
* says above. Not that I can really do anything about it
*/