Merge branch 'frame_opacity'
This commit is contained in:
commit
69f003348b
12
README.md
12
README.md
|
@ -12,12 +12,17 @@ partially doing this out of a desire to learn Xlib.
|
||||||
## Changes from xcompmgr:
|
## Changes from xcompmgr:
|
||||||
|
|
||||||
* __inactive window transparency__ (specified with `-i`)
|
* __inactive window transparency__ (specified with `-i`)
|
||||||
|
* __titlebar/frame transparency__ (specified with `-e`)
|
||||||
* shadows are now enabled for argb windows, e.g. terminals with transparency
|
* shadows are now enabled for argb windows, e.g. terminals with transparency
|
||||||
* removed serverside shadows (and simple compositing) to clean the code,
|
* removed serverside shadows (and simple compositing) to clean the code,
|
||||||
the only option that remains is clientside shadows
|
the only option that remains is clientside shadows
|
||||||
* titlebar transparency (and possibly border transparency) is on the way
|
|
||||||
* menu transparency (thanks to Dana)
|
* menu transparency (thanks to Dana)
|
||||||
|
|
||||||
|
The above features give compton a feature set similar to the xfce compositor.
|
||||||
|
|
||||||
|
Compton has only been tested with openbox so far, but frame transparency
|
||||||
|
should work with any window manager that properly sets `_NET_FRAME_EXTENTS`.
|
||||||
|
|
||||||
## Fixes from the original xcompmgr:
|
## Fixes from the original xcompmgr:
|
||||||
|
|
||||||
* fixed a segfault when opening certain window types
|
* fixed a segfault when opening certain window types
|
||||||
|
@ -64,7 +69,8 @@ The above will produce a single binary.
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ xcompmgr -cC -t -5 -l -5 -r 5 -o 0.5 -fF -I 0.065 -O 0.065 -D 6 -m 0.8 -i &
|
$ xcompmgr -cC -t -5 -l -5 -r 5 -o 0.4 \
|
||||||
|
-fF -I 0.065 -O 0.065 -D 6 -m 0.8 -i 0.6 -e 0.6 &
|
||||||
|
|
||||||
$ xcompmgr -cC -t -5 -l -5 -r 5 -o 0.5 -i &
|
$ xcompmgr -cC -t -5 -l -5 -r 5 -o 0.4 -i 0.6 -e 0.6 &
|
||||||
```
|
```
|
||||||
|
|
178
xcompmgr.c
178
xcompmgr.c
|
@ -88,6 +88,7 @@ typedef struct _win {
|
||||||
Damage damage;
|
Damage damage;
|
||||||
Picture picture;
|
Picture picture;
|
||||||
Picture alpha_pict;
|
Picture alpha_pict;
|
||||||
|
Picture alpha_border_pict;
|
||||||
Picture shadow_pict;
|
Picture shadow_pict;
|
||||||
XserverRegion border_size;
|
XserverRegion border_size;
|
||||||
XserverRegion extents;
|
XserverRegion extents;
|
||||||
|
@ -100,6 +101,10 @@ typedef struct _win {
|
||||||
wintype window_type;
|
wintype window_type;
|
||||||
unsigned long damage_sequence; /* sequence when damage was created */
|
unsigned long damage_sequence; /* sequence when damage was created */
|
||||||
Bool destroyed;
|
Bool destroyed;
|
||||||
|
unsigned int left_width;
|
||||||
|
unsigned int right_width;
|
||||||
|
unsigned int top_width;
|
||||||
|
unsigned int bottom_width;
|
||||||
|
|
||||||
Bool need_configure;
|
Bool need_configure;
|
||||||
XConfigureEvent queue_configure;
|
XConfigureEvent queue_configure;
|
||||||
|
@ -190,6 +195,7 @@ int fade_time = 0;
|
||||||
Bool fade_trans = False;
|
Bool fade_trans = False;
|
||||||
|
|
||||||
double inactive_opacity = 0;
|
double inactive_opacity = 0;
|
||||||
|
double frame_opacity = 0;
|
||||||
|
|
||||||
#define INACTIVE_OPACITY \
|
#define INACTIVE_OPACITY \
|
||||||
(unsigned long)((double)inactive_opacity * OPAQUE)
|
(unsigned long)((double)inactive_opacity * OPAQUE)
|
||||||
|
@ -937,6 +943,78 @@ border_size(Display *dpy, win *w) {
|
||||||
return border;
|
return border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Window
|
||||||
|
find_client_win(Display *dpy, Window win) {
|
||||||
|
Atom WM_STATE = XInternAtom(dpy, "WM_STATE", False);
|
||||||
|
|
||||||
|
Window root, parent;
|
||||||
|
Window *children;
|
||||||
|
unsigned int nchildren;
|
||||||
|
unsigned int i;
|
||||||
|
Atom type = None;
|
||||||
|
int format;
|
||||||
|
unsigned long nitems, after;
|
||||||
|
unsigned char *data;
|
||||||
|
Window client = 0;
|
||||||
|
|
||||||
|
XGetWindowProperty(
|
||||||
|
dpy, win, WM_STATE, 0, 0, False,
|
||||||
|
AnyPropertyType, &type, &format, &nitems,
|
||||||
|
&after, &data);
|
||||||
|
|
||||||
|
if (type) return win;
|
||||||
|
|
||||||
|
if (!XQueryTree(dpy, win, &root,
|
||||||
|
&parent, &children, &nchildren)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nchildren; i++) {
|
||||||
|
client = find_client_win(dpy, children[i]);
|
||||||
|
if (client) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children) XFree((char *)children);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_frame_extents(Display *dpy, Window w,
|
||||||
|
int *left, int *right, int *top, int *bottom) {
|
||||||
|
long *extents;
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long nitems, after;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
*left = 0;
|
||||||
|
*right = 0;
|
||||||
|
*top = 0;
|
||||||
|
*bottom = 0;
|
||||||
|
|
||||||
|
w = find_client_win(dpy, w);
|
||||||
|
if (!w) return;
|
||||||
|
|
||||||
|
result = XGetWindowProperty(
|
||||||
|
dpy, w, XInternAtom(dpy, "_NET_FRAME_EXTENTS", False),
|
||||||
|
0L, 4L, False, AnyPropertyType,
|
||||||
|
&type, &format, &nitems, &after,
|
||||||
|
(unsigned char **)&data);
|
||||||
|
|
||||||
|
if (result == Success) {
|
||||||
|
if (nitems == 4 && after == 0) {
|
||||||
|
extents = (long *)data;
|
||||||
|
*left = (int) *extents;
|
||||||
|
*right = (int) *(extents + 1);
|
||||||
|
*top = (int) *(extents + 2);
|
||||||
|
*bottom = (int) *(extents + 3);
|
||||||
|
}
|
||||||
|
XFree(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
paint_all(Display *dpy, XserverRegion region) {
|
paint_all(Display *dpy, XserverRegion region) {
|
||||||
win *w;
|
win *w;
|
||||||
|
@ -1042,7 +1120,8 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
w->extents = win_extents(dpy, w);
|
w->extents = win_extents(dpy, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->mode == WINDOW_SOLID) {
|
if (!(frame_opacity && w->top_width)
|
||||||
|
&& w->mode == WINDOW_SOLID) {
|
||||||
int x, y, wid, hei;
|
int x, y, wid, hei;
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
#if HAS_NAME_WINDOW_PIXMAP
|
||||||
|
@ -1099,12 +1178,19 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
w->shadow_width, w->shadow_height);
|
w->shadow_width, w->shadow_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->opacity != OPAQUE && !w->alpha_pict) {
|
if (((frame_opacity && w->top_width) || w->opacity != OPAQUE)
|
||||||
|
&& !w->alpha_pict) {
|
||||||
w->alpha_pict = solid_picture(
|
w->alpha_pict = solid_picture(
|
||||||
dpy, False, (double)w->opacity / OPAQUE, 0, 0, 0);
|
dpy, False, (double)w->opacity / OPAQUE, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->mode == WINDOW_TRANS) {
|
if (((frame_opacity && w->top_width) || w->opacity != OPAQUE)
|
||||||
|
&& !w->alpha_border_pict) {
|
||||||
|
w->alpha_border_pict = solid_picture(
|
||||||
|
dpy, False, frame_opacity, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((frame_opacity && w->top_width) || w->mode != WINDOW_SOLID) {
|
||||||
int x, y, wid, hei;
|
int x, y, wid, hei;
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
#if HAS_NAME_WINDOW_PIXMAP
|
||||||
|
@ -1121,30 +1207,42 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
|
|
||||||
set_ignore(dpy, NextRequest(dpy));
|
set_ignore(dpy, NextRequest(dpy));
|
||||||
|
|
||||||
XRenderComposite(
|
if (!frame_opacity || !w->top_width) {
|
||||||
dpy, PictOpOver, w->picture, w->alpha_pict,
|
XRenderComposite(
|
||||||
root_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
dpy, PictOpOver, w->picture, w->alpha_pict,
|
||||||
} else if (w->mode == WINDOW_ARGB) {
|
root_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
||||||
int x, y, wid, hei;
|
} else {
|
||||||
|
/* TODO - clean me */
|
||||||
|
unsigned int t = w->top_width;
|
||||||
|
unsigned int l = w->left_width;
|
||||||
|
unsigned int b = w->bottom_width;
|
||||||
|
unsigned int r = w->right_width;
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
/* top */
|
||||||
x = w->a.x;
|
XRenderComposite(
|
||||||
y = w->a.y;
|
dpy, PictOpOver, w->picture, w->alpha_border_pict, root_buffer,
|
||||||
wid = w->a.width + w->a.border_width * 2;
|
0, 0, 0, 0, x, y, wid, t);
|
||||||
hei = w->a.height + w->a.border_width * 2;
|
|
||||||
#else
|
|
||||||
x = w->a.x + w->a.border_width;
|
|
||||||
y = w->a.y + w->a.border_width;
|
|
||||||
wid = w->a.width;
|
|
||||||
hei = w->a.height;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
set_ignore(dpy, NextRequest(dpy));
|
/* left */
|
||||||
|
XRenderComposite(
|
||||||
|
dpy, PictOpOver, w->picture, w->alpha_border_pict, root_buffer,
|
||||||
|
0, t, 0, t, x, y + t, l, hei - t);
|
||||||
|
|
||||||
XRenderComposite(
|
/* bottom */
|
||||||
dpy, PictOpOver, w->picture, w->alpha_pict,
|
XRenderComposite(
|
||||||
root_buffer, 0, 0, 0, 0,
|
dpy, PictOpOver, w->picture, w->alpha_border_pict, root_buffer,
|
||||||
x, y, wid, hei);
|
l, hei - b, l, hei - b, x + l, y + hei - b, wid - l - r, b);
|
||||||
|
|
||||||
|
/* right */
|
||||||
|
XRenderComposite(
|
||||||
|
dpy, PictOpOver, w->picture, w->alpha_border_pict, root_buffer,
|
||||||
|
wid - r, t, wid - r, t, x + wid - r, y + t, r, hei - t);
|
||||||
|
|
||||||
|
/* body */
|
||||||
|
XRenderComposite(
|
||||||
|
dpy, PictOpOver, w->picture, w->alpha_pict, root_buffer,
|
||||||
|
l, t, l, t, x + l, y + t, wid - l - r, hei - t - b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XFixesDestroyRegion(dpy, w->border_clip);
|
XFixesDestroyRegion(dpy, w->border_clip);
|
||||||
|
@ -1500,6 +1598,11 @@ determine_mode(Display *dpy, win *w) {
|
||||||
w->alpha_pict = None;
|
w->alpha_pict = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (w->alpha_border_pict) {
|
||||||
|
XRenderFreePicture(dpy, w->alpha_border_pict);
|
||||||
|
w->alpha_border_pict = None;
|
||||||
|
}
|
||||||
|
|
||||||
if (w->shadow_pict) {
|
if (w->shadow_pict) {
|
||||||
XRenderFreePicture(dpy, w->shadow_pict);
|
XRenderFreePicture(dpy, w->shadow_pict);
|
||||||
w->shadow_pict = None;
|
w->shadow_pict = None;
|
||||||
|
@ -1573,6 +1676,7 @@ add_win(Display *dpy, Window id, Window prev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
new->alpha_pict = None;
|
new->alpha_pict = None;
|
||||||
|
new->alpha_border_pict = None;
|
||||||
new->shadow_pict = None;
|
new->shadow_pict = None;
|
||||||
new->border_size = None;
|
new->border_size = None;
|
||||||
new->extents = None;
|
new->extents = None;
|
||||||
|
@ -1591,6 +1695,13 @@ add_win(Display *dpy, Window id, Window prev) {
|
||||||
new->next = *p;
|
new->next = *p;
|
||||||
*p = new;
|
*p = new;
|
||||||
|
|
||||||
|
new->left_width = 0;
|
||||||
|
new->right_width = 0;
|
||||||
|
new->top_width = 0;
|
||||||
|
new->bottom_width = 0;
|
||||||
|
get_frame_extents(dpy, id,
|
||||||
|
&new->left_width, &new->right_width, &new->top_width, &new->bottom_width);
|
||||||
|
|
||||||
if (new->a.map_state == IsViewable) {
|
if (new->a.map_state == IsViewable) {
|
||||||
new->window_type = determine_wintype(dpy, id, id);
|
new->window_type = determine_wintype(dpy, id, id);
|
||||||
if (inactive_opacity && new->window_type == WINTYPE_NORMAL) {
|
if (inactive_opacity && new->window_type == WINTYPE_NORMAL) {
|
||||||
|
@ -1734,6 +1845,11 @@ finish_destroy_win(Display *dpy, Window id) {
|
||||||
w->alpha_pict = None;
|
w->alpha_pict = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (w->alpha_border_pict) {
|
||||||
|
XRenderFreePicture(dpy, w->alpha_border_pict);
|
||||||
|
w->alpha_border_pict = None;
|
||||||
|
}
|
||||||
|
|
||||||
if (w->shadow_pict) {
|
if (w->shadow_pict) {
|
||||||
XRenderFreePicture(dpy, w->shadow_pict);
|
XRenderFreePicture(dpy, w->shadow_pict);
|
||||||
w->shadow_pict = None;
|
w->shadow_pict = None;
|
||||||
|
@ -2032,6 +2148,9 @@ usage(char *program) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" -i opacity\n "
|
" -i opacity\n "
|
||||||
"Opacity of inactive windows. (0.1 - 1.0)\n");
|
"Opacity of inactive windows. (0.1 - 1.0)\n");
|
||||||
|
fprintf(stderr,
|
||||||
|
" -e opacity\n "
|
||||||
|
"Opacity of window titlebars and borders. (0.1 - 1.0)\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
" -S\n "
|
" -S\n "
|
||||||
"Enable synchronous operation (for debugging).\n");
|
"Enable synchronous operation (for debugging).\n");
|
||||||
|
@ -2100,7 +2219,7 @@ main(int argc, char **argv) {
|
||||||
/* don't bother to draw a shadow for the desktop */
|
/* don't bother to draw a shadow for the desktop */
|
||||||
win_type_shadow[WINTYPE_DESKTOP] = False;
|
win_type_shadow[WINTYPE_DESKTOP] = False;
|
||||||
|
|
||||||
while ((o = getopt(argc, argv, "D:I:O:d:r:o:m:l:t:i:scnfFCaS")) != -1) {
|
while ((o = getopt(argc, argv, "D:I:O:d:r:o:m:l:t:i:e:scnfFCaS")) != -1) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case 'd':
|
case 'd':
|
||||||
display = optarg;
|
display = optarg;
|
||||||
|
@ -2155,11 +2274,9 @@ main(int argc, char **argv) {
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
inactive_opacity = (double)atof(optarg);
|
inactive_opacity = (double)atof(optarg);
|
||||||
if (inactive_opacity < 0.1
|
break;
|
||||||
|| inactive_opacity > 1.0) {
|
case 'e':
|
||||||
fprintf(stderr, "Opacity must be 0.1 - 1.0.\n");
|
frame_opacity = (double)atof(optarg);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'n':
|
case 'n':
|
||||||
|
@ -2339,6 +2456,7 @@ main(int argc, char **argv) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CreateNotify:
|
case CreateNotify:
|
||||||
|
//if (ev.xcreatewindow.override_redirect) break;
|
||||||
add_win(dpy, ev.xcreatewindow.window, 0);
|
add_win(dpy, ev.xcreatewindow.window, 0);
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
|
|
Loading…
Reference in New Issue