Improvement: Change fading mechanism
- Change fading mechanism for better modularity. Remove fade queue and use members in struct _win to record fading data. In contrast to previous commits, this one actually could make the program slower (but very slightly, hardly noticeable if your CPU is anywhere close to AMD K7). As this commit changes lots of things, bugs are to be expected. - Currently -F does not do its job. -f actually equals -fF. (While in the past -F equals nothing and -f is just -f.) A fix will be made soon. I suppose it isn't hard. - Add a preprocessor function paint_preprocess() and move all preprocessing code in paint_all() to it. - Add window flag support but currently unused. - Add DamageNotify handling to ev_window(). - I'm considering removing HAS_NAME_WINDOW_PIXMAP = 0 support as I couldn't see what it is good for. Nor do I know what CAN_DO_USABLE does. Basically all my changes ignore these cases.
This commit is contained in:
parent
e7da88890d
commit
778a8b177c
451
src/compton.c
451
src/compton.c
|
@ -17,7 +17,6 @@
|
||||||
struct timeval time_start = { 0, 0 };
|
struct timeval time_start = { 0, 0 };
|
||||||
|
|
||||||
win *list;
|
win *list;
|
||||||
fade *fades;
|
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
int scr;
|
int scr;
|
||||||
|
|
||||||
|
@ -97,10 +96,12 @@ int shadow_offset_x = -15;
|
||||||
int shadow_offset_y = -15;
|
int shadow_offset_y = -15;
|
||||||
double shadow_opacity = .75;
|
double shadow_opacity = .75;
|
||||||
|
|
||||||
double fade_in_step = 0.028;
|
/// How much to fade in in a single fading step.
|
||||||
double fade_out_step = 0.03;
|
opacity_t fade_in_step = 0.028 * OPAQUE;
|
||||||
int fade_delta = 10;
|
/// How much to fade out in a single fading step.
|
||||||
int fade_time = 0;
|
opacity_t fade_out_step = 0.03 * OPAQUE;
|
||||||
|
unsigned long fade_delta = 10;
|
||||||
|
unsigned long fade_time = 0;
|
||||||
Bool fade_trans = False;
|
Bool fade_trans = False;
|
||||||
|
|
||||||
Bool clear_shadow = False;
|
Bool clear_shadow = False;
|
||||||
|
@ -125,7 +126,13 @@ Bool synchronize = False;
|
||||||
* Fades
|
* Fades
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
/**
|
||||||
|
* Get current system clock in milliseconds.
|
||||||
|
*
|
||||||
|
* The return type must be unsigned long because so many milliseconds have
|
||||||
|
* passed since the epoch.
|
||||||
|
*/
|
||||||
|
static unsigned long
|
||||||
get_time_in_milliseconds() {
|
get_time_in_milliseconds() {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
|
@ -134,153 +141,70 @@ get_time_in_milliseconds() {
|
||||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fade *
|
/**
|
||||||
find_fade(win *w) {
|
* Get the time left before next fading point.
|
||||||
fade *f;
|
*
|
||||||
|
* In milliseconds.
|
||||||
for (f = fades; f; f = f->next) {
|
*/
|
||||||
if (f->w == w) return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dequeue_fade(Display *dpy, fade *f) {
|
|
||||||
fade **prev;
|
|
||||||
|
|
||||||
for (prev = &fades; *prev; prev = &(*prev)->next) {
|
|
||||||
if (*prev == f) {
|
|
||||||
*prev = f->next;
|
|
||||||
if (f->callback) {
|
|
||||||
(*f->callback)(dpy, f->w);
|
|
||||||
}
|
|
||||||
free(f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cleanup_fade(Display *dpy, win *w) {
|
|
||||||
fade *f = find_fade (w);
|
|
||||||
if (f) {
|
|
||||||
dequeue_fade(dpy, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
enqueue_fade(Display *dpy, fade *f) {
|
|
||||||
if (!fades) {
|
|
||||||
fade_time = get_time_in_milliseconds() + fade_delta;
|
|
||||||
}
|
|
||||||
f->next = fades;
|
|
||||||
fades = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_fade(Display *dpy, win *w, double start,
|
|
||||||
double finish, double step,
|
|
||||||
void(*callback) (Display *dpy, win *w),
|
|
||||||
Bool exec_callback, Bool override) {
|
|
||||||
fade *f;
|
|
||||||
|
|
||||||
f = find_fade(w);
|
|
||||||
if (!f) {
|
|
||||||
f = malloc(sizeof(fade));
|
|
||||||
f->next = 0;
|
|
||||||
f->w = w;
|
|
||||||
f->cur = start;
|
|
||||||
enqueue_fade(dpy, f);
|
|
||||||
} else if (!override) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (exec_callback && f->callback) {
|
|
||||||
(*f->callback)(dpy, f->w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finish < 0) finish = 0;
|
|
||||||
if (finish > 1) finish = 1;
|
|
||||||
f->finish = finish;
|
|
||||||
|
|
||||||
if (f->cur < finish) {
|
|
||||||
f->step = step;
|
|
||||||
} else if (f->cur > finish) {
|
|
||||||
f->step = -step;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->callback = callback;
|
|
||||||
set_opacity(dpy, w, f->cur * OPAQUE);
|
|
||||||
|
|
||||||
/* fading windows need to be drawn, mark
|
|
||||||
them as damaged. when a window maps,
|
|
||||||
if it tries to fade in but it already
|
|
||||||
at the right opacity (map/unmap/map fast)
|
|
||||||
then it will never get drawn without this
|
|
||||||
until it repaints */
|
|
||||||
w->damaged = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fade_timeout(void) {
|
fade_timeout(void) {
|
||||||
int now;
|
int diff = fade_delta - get_time_in_milliseconds() + fade_time;
|
||||||
int delta;
|
|
||||||
|
|
||||||
if (!fades) return -1;
|
if (diff < 0)
|
||||||
|
diff = 0;
|
||||||
|
|
||||||
now = get_time_in_milliseconds();
|
return diff;
|
||||||
delta = fade_time - now;
|
|
||||||
|
|
||||||
if (delta < 0) delta = 0;
|
|
||||||
|
|
||||||
return delta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run fading on a window.
|
||||||
|
*
|
||||||
|
* @param steps steps of fading
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
run_fades(Display *dpy) {
|
run_fade(Display *dpy, win *w, unsigned steps) {
|
||||||
int now = get_time_in_milliseconds();
|
// If we reach target opacity, set fade_fin so the callback gets
|
||||||
fade *next = fades;
|
// executed
|
||||||
int steps;
|
if (w->opacity == w->opacity_tgt) {
|
||||||
Bool need_dequeue;
|
w->fade_fin = True;
|
||||||
|
return;
|
||||||
if (fade_time - now > 0) return;
|
|
||||||
steps = 1 + (now - fade_time) / fade_delta;
|
|
||||||
|
|
||||||
while (next) {
|
|
||||||
fade *f = next;
|
|
||||||
win *w = f->w;
|
|
||||||
next = f->next;
|
|
||||||
|
|
||||||
f->cur += f->step * steps;
|
|
||||||
if (f->cur >= 1) {
|
|
||||||
f->cur = 1;
|
|
||||||
} else if (f->cur < 0) {
|
|
||||||
f->cur = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w->opacity = f->cur * OPAQUE;
|
if (!w->fade)
|
||||||
need_dequeue = False;
|
w->opacity = w->opacity_tgt;
|
||||||
if (f->step > 0) {
|
else if (steps) {
|
||||||
if (f->cur >= f->finish) {
|
// Use double below because opacity_t will probably overflow during
|
||||||
w->opacity = f->finish * OPAQUE;
|
// calculations
|
||||||
need_dequeue = True;
|
if (w->opacity < w->opacity_tgt)
|
||||||
}
|
w->opacity = normalize_d_range(
|
||||||
} else {
|
(double) w->opacity + (double) fade_in_step * steps,
|
||||||
if (f->cur <= f->finish) {
|
0.0, w->opacity_tgt);
|
||||||
w->opacity = f->finish * OPAQUE;
|
else
|
||||||
need_dequeue = True;
|
w->opacity = normalize_d_range(
|
||||||
}
|
(double) w->opacity - (double) fade_out_step * steps,
|
||||||
|
w->opacity_tgt, OPAQUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
determine_mode(dpy, w);
|
if (w->opacity == w->opacity_tgt) {
|
||||||
|
w->fade_fin = True;
|
||||||
/* Must do this last as it might
|
return;
|
||||||
destroy f->w in callbacks */
|
|
||||||
if (need_dequeue) dequeue_fade(dpy, f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fade_time = now + fade_delta;
|
w->fade_fin = False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set fade callback of a window, and possibly execute the previous
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* @param exec_callback whether the previous callback is to be executed
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_fade_callback(Display *dpy, win *w,
|
||||||
|
void (*callback) (Display *dpy, win *w), Bool exec_callback) {
|
||||||
|
if (exec_callback && w->fade_callback)
|
||||||
|
(w->fade_callback)(dpy, w);
|
||||||
|
w->fade_callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1003,62 +927,39 @@ get_frame_extents(Display *dpy, Window w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static win *
|
||||||
paint_all(Display *dpy, XserverRegion region) {
|
paint_preprocess(Display *dpy, win *list) {
|
||||||
win *w;
|
win *w;
|
||||||
win *t = 0;
|
win *t = NULL, *next = NULL;
|
||||||
|
// Sounds like the timeout in poll() frequently does not work
|
||||||
|
// accurately, asking it to wait to 20ms, and often it would wait for
|
||||||
|
// 19ms, so the step value has to be rounded.
|
||||||
|
unsigned steps = roundl((double) (get_time_in_milliseconds() - fade_time) / fade_delta);
|
||||||
|
|
||||||
if (!region) {
|
// Reset fade_time
|
||||||
region = get_screen_region(dpy);
|
fade_time = get_time_in_milliseconds();
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MONITOR_REPAINT
|
for (w = list; w; w = next) {
|
||||||
root_buffer = root_picture;
|
// In case calling the fade callback function destroys this window
|
||||||
#else
|
next = w->next;
|
||||||
if (!root_buffer) {
|
opacity_t opacity_old = w->opacity;
|
||||||
Pixmap root_pixmap = XCreatePixmap(
|
|
||||||
dpy, root, root_width, root_height,
|
|
||||||
DefaultDepth(dpy, scr));
|
|
||||||
|
|
||||||
root_buffer = XRenderCreatePicture(dpy, root_pixmap,
|
|
||||||
XRenderFindVisualFormat(dpy, DefaultVisual(dpy, scr)),
|
|
||||||
0, 0);
|
|
||||||
|
|
||||||
XFreePixmap(dpy, root_pixmap);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
XFixesSetPictureClipRegion(dpy, root_picture, 0, 0, region);
|
|
||||||
|
|
||||||
#ifdef MONITOR_REPAINT
|
|
||||||
XRenderComposite(
|
|
||||||
dpy, PictOpSrc, black_picture, None,
|
|
||||||
root_picture, 0, 0, 0, 0, 0, 0,
|
|
||||||
root_width, root_height);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_REPAINT
|
|
||||||
printf("paint:");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (w = list; w; w = w->next) {
|
|
||||||
#if CAN_DO_USABLE
|
#if CAN_DO_USABLE
|
||||||
if (!w->usable) continue;
|
if (!w->usable) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* never painted, ignore it */
|
// Run fading
|
||||||
if (!w->damaged) continue;
|
run_fade(dpy, w, steps);
|
||||||
|
|
||||||
/* if invisible, ignore it */
|
// Give up if it's not damaged or invisible
|
||||||
if (w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
|
if (!w->damaged
|
||||||
|
|| w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
|
||||||
|| w->a.x >= root_width || w->a.y >= root_height) {
|
|| w->a.x >= root_width || w->a.y >= root_height) {
|
||||||
|
check_fade_fin(dpy, w);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_REPAINT
|
// Fetch the picture and pixmap if needed
|
||||||
printf(" %#010lx", w->id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!w->picture) {
|
if (!w->picture) {
|
||||||
XRenderPictureAttributes pa;
|
XRenderPictureAttributes pa;
|
||||||
XRenderPictFormat *format;
|
XRenderPictFormat *format;
|
||||||
|
@ -1078,6 +979,7 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
dpy, draw, format, CPSubwindowMode, &pa);
|
dpy, draw, format, CPSubwindowMode, &pa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch bounding region and extents if needed
|
||||||
if (!w->border_size) {
|
if (!w->border_size) {
|
||||||
w->border_size = border_size(dpy, w);
|
w->border_size = border_size(dpy, w);
|
||||||
}
|
}
|
||||||
|
@ -1086,6 +988,17 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
w->extents = win_extents(dpy, w);
|
w->extents = win_extents(dpy, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If opacity changes
|
||||||
|
if (w->opacity != opacity_old) {
|
||||||
|
determine_mode(dpy, w);
|
||||||
|
add_damage_win(dpy, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!w->opacity) {
|
||||||
|
check_fade_fin(dpy, w);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Rebuild alpha_pict only if necessary
|
// Rebuild alpha_pict only if necessary
|
||||||
if (OPAQUE != w->opacity
|
if (OPAQUE != w->opacity
|
||||||
&& (!w->alpha_pict || w->opacity != w->opacity_cur)) {
|
&& (!w->alpha_pict || w->opacity != w->opacity_cur)) {
|
||||||
|
@ -1137,15 +1050,48 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
t = w;
|
t = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_REPAINT
|
return t;
|
||||||
printf("\n");
|
}
|
||||||
fflush(stdout);
|
|
||||||
|
static void
|
||||||
|
paint_all(Display *dpy, XserverRegion region, win *t) {
|
||||||
|
win *w;
|
||||||
|
|
||||||
|
if (!region) {
|
||||||
|
region = get_screen_region(dpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MONITOR_REPAINT
|
||||||
|
root_buffer = root_picture;
|
||||||
|
#else
|
||||||
|
if (!root_buffer) {
|
||||||
|
Pixmap root_pixmap = XCreatePixmap(
|
||||||
|
dpy, root, root_width, root_height,
|
||||||
|
DefaultDepth(dpy, scr));
|
||||||
|
|
||||||
|
root_buffer = XRenderCreatePicture(dpy, root_pixmap,
|
||||||
|
XRenderFindVisualFormat(dpy, DefaultVisual(dpy, scr)),
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
XFreePixmap(dpy, root_pixmap);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region);
|
XFixesSetPictureClipRegion(dpy, root_picture, 0, 0, region);
|
||||||
|
|
||||||
|
#ifdef MONITOR_REPAINT
|
||||||
|
XRenderComposite(
|
||||||
|
dpy, PictOpSrc, black_picture, None,
|
||||||
|
root_picture, 0, 0, 0, 0, 0, 0,
|
||||||
|
root_width, root_height);
|
||||||
|
#endif
|
||||||
|
|
||||||
paint_root(dpy);
|
paint_root(dpy);
|
||||||
|
|
||||||
|
#ifdef DEBUG_REPAINT
|
||||||
|
printf("paint:");
|
||||||
|
#endif
|
||||||
|
|
||||||
for (w = t; w; w = w->prev_trans) {
|
for (w = t; w; w = w->prev_trans) {
|
||||||
int x, y, wid, hei;
|
int x, y, wid, hei;
|
||||||
|
|
||||||
|
@ -1161,6 +1107,10 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
hei = w->a.height;
|
hei = w->a.height;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_REPAINT
|
||||||
|
printf(" %#010lx", w->id);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Allow shadow to be painted anywhere in the damaged region
|
// Allow shadow to be painted anywhere in the damaged region
|
||||||
XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region);
|
XFixesSetPictureClipRegion(dpy, root_buffer, 0, 0, region);
|
||||||
|
|
||||||
|
@ -1226,8 +1176,15 @@ paint_all(Display *dpy, XserverRegion region) {
|
||||||
}
|
}
|
||||||
|
|
||||||
XFixesDestroyRegion(dpy, paint_reg);
|
XFixesDestroyRegion(dpy, paint_reg);
|
||||||
|
|
||||||
|
check_fade_fin(dpy, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_REPAINT
|
||||||
|
printf("\n");
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
|
||||||
XFixesDestroyRegion(dpy, region);
|
XFixesDestroyRegion(dpy, region);
|
||||||
|
|
||||||
if (root_buffer != root_picture) {
|
if (root_buffer != root_picture) {
|
||||||
|
@ -1415,18 +1372,12 @@ map_win(Display *dpy, Window id,
|
||||||
w->a.map_state = IsViewable;
|
w->a.map_state = IsViewable;
|
||||||
w->window_type = determine_wintype(dpy, w->id, w->id);
|
w->window_type = determine_wintype(dpy, w->id, w->id);
|
||||||
|
|
||||||
// Window type change could affect shadow
|
// Window type change could affect shadow and fade
|
||||||
{
|
|
||||||
Bool shadow_old = w->shadow;
|
|
||||||
determine_shadow(dpy, w);
|
determine_shadow(dpy, w);
|
||||||
if (w->shadow != shadow_old) {
|
determine_fade(dpy, w);
|
||||||
calc_shadow_geometry(dpy, w);
|
|
||||||
if (w->extents) {
|
// Determine mode here just in case the colormap changes
|
||||||
free_region(dpy, &w->extents);
|
determine_mode(dpy, w);
|
||||||
w->extents = win_extents(dpy, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_WINTYPE
|
#ifdef DEBUG_WINTYPE
|
||||||
printf("map_win(): window %#010lx type %s\n",
|
printf("map_win(): window %#010lx type %s\n",
|
||||||
|
@ -1461,22 +1412,18 @@ map_win(Display *dpy, Window id,
|
||||||
recheck_focus(dpy);
|
recheck_focus(dpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fading in
|
||||||
calc_opacity(dpy, w, True);
|
calc_opacity(dpy, w, True);
|
||||||
calc_dim(dpy, w);
|
set_fade_callback(dpy, w, NULL, True);
|
||||||
|
|
||||||
determine_mode(dpy, w);
|
calc_dim(dpy, w);
|
||||||
|
|
||||||
#if CAN_DO_USABLE
|
#if CAN_DO_USABLE
|
||||||
w->damage_bounds.x = w->damage_bounds.y = 0;
|
w->damage_bounds.x = w->damage_bounds.y = 0;
|
||||||
w->damage_bounds.width = w->damage_bounds.height = 0;
|
w->damage_bounds.width = w->damage_bounds.height = 0;
|
||||||
#endif
|
#endif
|
||||||
w->damaged = 0;
|
w->damaged = 1;
|
||||||
|
|
||||||
if (fade && win_type_fade[w->window_type]) {
|
|
||||||
set_fade(
|
|
||||||
dpy, w, 0, get_opacity_percent(dpy, w),
|
|
||||||
fade_in_step, 0, True, True);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if any configure events happened while
|
/* if any configure events happened while
|
||||||
the window was unmapped, then configure
|
the window was unmapped, then configure
|
||||||
|
@ -1508,12 +1455,10 @@ finish_unmap_win(Display *dpy, win *w) {
|
||||||
free_picture(dpy, &w->shadow_pict);
|
free_picture(dpy, &w->shadow_pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
|
||||||
static void
|
static void
|
||||||
unmap_callback(Display *dpy, win *w) {
|
unmap_callback(Display *dpy, win *w) {
|
||||||
finish_unmap_win(dpy, w);
|
finish_unmap_win(dpy, w);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unmap_win(Display *dpy, Window id, Bool fade) {
|
unmap_win(Display *dpy, Window id, Bool fade) {
|
||||||
|
@ -1523,6 +1468,10 @@ unmap_win(Display *dpy, Window id, Bool fade) {
|
||||||
|
|
||||||
w->a.map_state = IsUnmapped;
|
w->a.map_state = IsUnmapped;
|
||||||
|
|
||||||
|
// Fading out
|
||||||
|
w->opacity_tgt = 0;
|
||||||
|
set_fade_callback(dpy, w, unmap_callback, False);
|
||||||
|
|
||||||
// don't care about properties anymore
|
// don't care about properties anymore
|
||||||
// Will get BadWindow if the window is destroyed
|
// Will get BadWindow if the window is destroyed
|
||||||
set_ignore(dpy, NextRequest(dpy));
|
set_ignore(dpy, NextRequest(dpy));
|
||||||
|
@ -1532,14 +1481,6 @@ unmap_win(Display *dpy, Window id, Bool fade) {
|
||||||
set_ignore(dpy, NextRequest(dpy));
|
set_ignore(dpy, NextRequest(dpy));
|
||||||
XSelectInput(dpy, w->client_win, 0);
|
XSelectInput(dpy, w->client_win, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
|
||||||
if (w->pixmap && fade && win_type_fade[w->window_type]) {
|
|
||||||
set_fade(dpy, w, get_opacity_percent(dpy, w), 0.0,
|
|
||||||
fade_out_step, unmap_callback, False, True);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
finish_unmap_win(dpy, w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static opacity_t
|
static opacity_t
|
||||||
|
@ -1594,15 +1535,6 @@ determine_mode(Display *dpy, win *w) {
|
||||||
add_damage_win(dpy, w);
|
add_damage_win(dpy, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_opacity(Display *dpy, win *w, opacity_t opacity) {
|
|
||||||
// Do nothing if the opacity does not change
|
|
||||||
if (w->opacity == opacity) return;
|
|
||||||
|
|
||||||
w->opacity = opacity;
|
|
||||||
determine_mode(dpy, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate and set the opacity of a window.
|
* Calculate and set the opacity of a window.
|
||||||
*
|
*
|
||||||
|
@ -1650,7 +1582,7 @@ calc_opacity(Display *dpy, win *w, Bool refetch_prop) {
|
||||||
opacity = inactive_opacity;
|
opacity = inactive_opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_opacity(dpy, w, opacity);
|
w->opacity_tgt = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1670,11 +1602,32 @@ calc_dim(Display *dpy, win *w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if a window should have shadow.
|
* Determine if a window should fade on opacity change.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
determine_fade(Display *dpy, win *w) {
|
||||||
|
w->fade = win_type_fade[w->window_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a window should have shadow, and update things depending
|
||||||
|
* on shadow state.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
determine_shadow(Display *dpy, win *w) {
|
determine_shadow(Display *dpy, win *w) {
|
||||||
|
Bool shadow_old = w->shadow;
|
||||||
|
|
||||||
w->shadow = win_type_shadow[w->window_type];
|
w->shadow = win_type_shadow[w->window_type];
|
||||||
|
|
||||||
|
// Window extents need update on shadow state change
|
||||||
|
if (w->shadow != shadow_old) {
|
||||||
|
// Shadow geometry currently doesn't change on shadow state change
|
||||||
|
// calc_shadow_geometry(dpy, w);
|
||||||
|
if (w->extents) {
|
||||||
|
free_region(dpy, &w->extents);
|
||||||
|
w->extents = win_extents(dpy, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1776,9 +1729,13 @@ add_win(Display *dpy, Window id, Window prev, Bool override_redirect) {
|
||||||
new->shadow_dy = 0;
|
new->shadow_dy = 0;
|
||||||
new->shadow_width = 0;
|
new->shadow_width = 0;
|
||||||
new->shadow_height = 0;
|
new->shadow_height = 0;
|
||||||
new->opacity = OPAQUE;
|
new->opacity = 0;
|
||||||
|
new->opacity_tgt = 0;
|
||||||
new->opacity_cur = OPAQUE;
|
new->opacity_cur = OPAQUE;
|
||||||
new->opacity_prop = OPAQUE;
|
new->opacity_prop = OPAQUE;
|
||||||
|
new->fade = False;
|
||||||
|
new->fade_callback = NULL;
|
||||||
|
new->fade_fin = False;
|
||||||
new->alpha_pict = None;
|
new->alpha_pict = None;
|
||||||
new->frame_opacity = 1.0;
|
new->frame_opacity = 1.0;
|
||||||
new->frame_opacity_cur = 1.0;
|
new->frame_opacity_cur = 1.0;
|
||||||
|
@ -1976,7 +1933,6 @@ finish_destroy_win(Display *dpy, Window id) {
|
||||||
free_picture(dpy, &w->shadow_pict);
|
free_picture(dpy, &w->shadow_pict);
|
||||||
free_damage(dpy, &w->damage);
|
free_damage(dpy, &w->damage);
|
||||||
|
|
||||||
cleanup_fade(dpy, w);
|
|
||||||
free(w);
|
free(w);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1994,17 +1950,12 @@ static void
|
||||||
destroy_win(Display *dpy, Window id, Bool fade) {
|
destroy_win(Display *dpy, Window id, Bool fade) {
|
||||||
win *w = find_win(dpy, id);
|
win *w = find_win(dpy, id);
|
||||||
|
|
||||||
if (w) w->destroyed = True;
|
if (w) {
|
||||||
|
w->destroyed = True;
|
||||||
|
|
||||||
#if HAS_NAME_WINDOW_PIXMAP
|
// Fading out the window
|
||||||
if (w && w->pixmap && fade && win_type_fade[w->window_type]) {
|
w->opacity_tgt = 0;
|
||||||
set_fade(dpy, w, get_opacity_percent(dpy, w),
|
set_fade_callback(dpy, w, destroy_callback, False);
|
||||||
0.0, fade_out_step, destroy_callback,
|
|
||||||
False, True);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
finish_destroy_win(dpy, id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2273,6 +2224,8 @@ ev_window(XEvent *ev) {
|
||||||
return ev->xcreatewindow.window;
|
return ev->xcreatewindow.window;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
return ev->xconfigure.window;
|
return ev->xconfigure.window;
|
||||||
|
case DestroyNotify:
|
||||||
|
return ev->xdestroywindow.window;
|
||||||
case MapNotify:
|
case MapNotify:
|
||||||
return ev->xmap.window;
|
return ev->xmap.window;
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
|
@ -2748,6 +2701,7 @@ main(int argc, char **argv) {
|
||||||
double shadow_red = 0.0;
|
double shadow_red = 0.0;
|
||||||
double shadow_green = 0.0;
|
double shadow_green = 0.0;
|
||||||
double shadow_blue = 0.0;
|
double shadow_blue = 0.0;
|
||||||
|
win *t;
|
||||||
|
|
||||||
gettimeofday(&time_start, NULL);
|
gettimeofday(&time_start, NULL);
|
||||||
|
|
||||||
|
@ -2792,16 +2746,10 @@ main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
fade_in_step = atof(optarg);
|
fade_in_step = normalize_d(atof(optarg)) * OPAQUE;
|
||||||
if (fade_in_step <= 0) {
|
|
||||||
fade_in_step = 0.01;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
fade_out_step = atof(optarg);
|
fade_out_step = normalize_d(atof(optarg)) * OPAQUE;
|
||||||
if (fade_out_step <= 0) {
|
|
||||||
fade_out_step = 0.01;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
for (i = 0; i < NUM_WINTYPES; ++i) {
|
for (i = 0; i < NUM_WINTYPES; ++i) {
|
||||||
|
@ -2882,6 +2830,8 @@ main(int argc, char **argv) {
|
||||||
track_focus = True;
|
track_focus = True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fade_time = get_time_in_milliseconds();
|
||||||
|
|
||||||
dpy = XOpenDisplay(display);
|
dpy = XOpenDisplay(display);
|
||||||
if (!dpy) {
|
if (!dpy) {
|
||||||
fprintf(stderr, "Can't open display\n");
|
fprintf(stderr, "Can't open display\n");
|
||||||
|
@ -2994,13 +2944,13 @@ main(int argc, char **argv) {
|
||||||
ufd.fd = ConnectionNumber(dpy);
|
ufd.fd = ConnectionNumber(dpy);
|
||||||
ufd.events = POLLIN;
|
ufd.events = POLLIN;
|
||||||
|
|
||||||
paint_all(dpy, None);
|
t = paint_preprocess(dpy, list);
|
||||||
|
paint_all(dpy, None, t);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
do {
|
do {
|
||||||
if (!QLength(dpy)) {
|
if (!QLength(dpy)) {
|
||||||
if (poll(&ufd, 1, fade_timeout()) == 0) {
|
if (poll(&ufd, 1, fade_timeout()) == 0) {
|
||||||
run_fades(dpy);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3009,9 +2959,10 @@ main(int argc, char **argv) {
|
||||||
ev_handle((XEvent *)&ev);
|
ev_handle((XEvent *)&ev);
|
||||||
} while (QLength(dpy));
|
} while (QLength(dpy));
|
||||||
|
|
||||||
|
t = paint_preprocess(dpy, list);
|
||||||
if (all_damage) {
|
if (all_damage) {
|
||||||
static int paint;
|
static int paint;
|
||||||
paint_all(dpy, all_damage);
|
paint_all(dpy, all_damage, t);
|
||||||
paint++;
|
paint++;
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
all_damage = None;
|
all_damage = None;
|
||||||
|
|
103
src/compton.h
103
src/compton.h
|
@ -107,13 +107,12 @@ typedef struct _win {
|
||||||
Bool destroyed;
|
Bool destroyed;
|
||||||
/// Cached width/height of the window including border.
|
/// Cached width/height of the window including border.
|
||||||
int widthb, heightb;
|
int widthb, heightb;
|
||||||
unsigned int left_width;
|
|
||||||
unsigned int right_width;
|
|
||||||
unsigned int top_width;
|
|
||||||
unsigned int bottom_width;
|
|
||||||
|
|
||||||
|
// Opacity-related members
|
||||||
/// Current window opacity.
|
/// Current window opacity.
|
||||||
opacity_t opacity;
|
opacity_t opacity;
|
||||||
|
/// Target window opacity.
|
||||||
|
opacity_t opacity_tgt;
|
||||||
/// Opacity of current alpha_pict.
|
/// Opacity of current alpha_pict.
|
||||||
opacity_t opacity_cur;
|
opacity_t opacity_cur;
|
||||||
/// Cached value of opacity window attribute.
|
/// Cached value of opacity window attribute.
|
||||||
|
@ -121,13 +120,26 @@ typedef struct _win {
|
||||||
/// Alpha mask Picture to render window with opacity.
|
/// Alpha mask Picture to render window with opacity.
|
||||||
Picture alpha_pict;
|
Picture alpha_pict;
|
||||||
|
|
||||||
|
// Fading-related members
|
||||||
|
/// Do not fade if it's false. Change on window type change.
|
||||||
|
/// Used by fading blacklist in the future.
|
||||||
|
Bool fade;
|
||||||
|
/// Callback to be called after fading completed.
|
||||||
|
void (*fade_callback) (Display *dpy, struct _win *w);
|
||||||
|
/// Whether fading is finished.
|
||||||
|
Bool fade_fin;
|
||||||
|
|
||||||
|
// Frame-opacity-related members
|
||||||
/// Current window frame opacity. Affected by window opacity.
|
/// Current window frame opacity. Affected by window opacity.
|
||||||
double frame_opacity;
|
double frame_opacity;
|
||||||
/// Opacity of current frame_alpha_pict.
|
/// Opacity of current frame_alpha_pict.
|
||||||
opacity_t frame_opacity_cur;
|
opacity_t frame_opacity_cur;
|
||||||
/// Alpha mask Picture to render window frame with opacity.
|
/// Alpha mask Picture to render window frame with opacity.
|
||||||
Picture frame_alpha_pict;
|
Picture frame_alpha_pict;
|
||||||
|
/// Frame widths. Determined by client window attributes.
|
||||||
|
unsigned int left_width, right_width, top_width, bottom_width;
|
||||||
|
|
||||||
|
// Shadow-related members
|
||||||
/// Whether a window has shadow. Affected by window type.
|
/// Whether a window has shadow. Affected by window type.
|
||||||
Bool shadow;
|
Bool shadow;
|
||||||
/// Opacity of the shadow. Affected by window opacity and frame opacity.
|
/// Opacity of the shadow. Affected by window opacity and frame opacity.
|
||||||
|
@ -146,6 +158,7 @@ typedef struct _win {
|
||||||
/// shadow opacity.
|
/// shadow opacity.
|
||||||
Picture shadow_pict;
|
Picture shadow_pict;
|
||||||
|
|
||||||
|
// Dim-related members
|
||||||
/// Whether the window is to be dimmed.
|
/// Whether the window is to be dimmed.
|
||||||
Bool dim;
|
Bool dim;
|
||||||
|
|
||||||
|
@ -165,16 +178,6 @@ typedef struct _conv {
|
||||||
double *data;
|
double *data;
|
||||||
} conv;
|
} conv;
|
||||||
|
|
||||||
typedef struct _fade {
|
|
||||||
struct _fade *next;
|
|
||||||
win *w;
|
|
||||||
double cur;
|
|
||||||
double finish;
|
|
||||||
double step;
|
|
||||||
void (*callback) (Display *dpy, win *w);
|
|
||||||
Display *dpy;
|
|
||||||
} fade;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WIN_EVMODE_UNKNOWN,
|
WIN_EVMODE_UNKNOWN,
|
||||||
WIN_EVMODE_FRAME,
|
WIN_EVMODE_FRAME,
|
||||||
|
@ -217,16 +220,30 @@ normalize_i_range(int i, int min, int max) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a double value to a specific range.
|
||||||
|
*
|
||||||
|
* @param d double value to normalize
|
||||||
|
* @param min minimal value
|
||||||
|
* @param max maximum value
|
||||||
|
* @return normalized value
|
||||||
|
*/
|
||||||
|
static inline double
|
||||||
|
normalize_d_range(double d, double min, double max) {
|
||||||
|
if (d > max) return max;
|
||||||
|
if (d < min) return min;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a double value to 0.\ 0 - 1.\ 0.
|
* Normalize a double value to 0.\ 0 - 1.\ 0.
|
||||||
*
|
*
|
||||||
* @param d double value to normalize
|
* @param d double value to normalize
|
||||||
|
* @return normalized value
|
||||||
*/
|
*/
|
||||||
static inline double
|
static inline double
|
||||||
normalize_d(double d) {
|
normalize_d(double d) {
|
||||||
if (d > 1.0) return 1.0;
|
return normalize_d_range(d, 0.0, 1.0);
|
||||||
if (d < 0.0) return 0.0;
|
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -388,32 +405,33 @@ win_get_children(Display *dpy, Window w,
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static unsigned long
|
||||||
get_time_in_milliseconds(void);
|
get_time_in_milliseconds(void);
|
||||||
|
|
||||||
static fade *
|
|
||||||
find_fade(win *w);
|
|
||||||
|
|
||||||
static void
|
|
||||||
dequeue_fade(Display *dpy, fade *f);
|
|
||||||
|
|
||||||
static void
|
|
||||||
cleanup_fade(Display *dpy, win *w);
|
|
||||||
|
|
||||||
static void
|
|
||||||
enqueue_fade(Display *dpy, fade *f);
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_fade(Display *dpy, win *w, double start,
|
|
||||||
double finish, double step,
|
|
||||||
void(*callback) (Display *dpy, win *w),
|
|
||||||
Bool exec_callback, Bool override);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fade_timeout(void);
|
fade_timeout(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_fades(Display *dpy);
|
run_fade(Display *dpy, win *w, unsigned steps);
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_fade_callback(Display *dpy, win *w,
|
||||||
|
void (*callback) (Display *dpy, win *w), Bool exec_callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute fade callback of a window if fading finished.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
check_fade_fin(Display *dpy, win *w) {
|
||||||
|
if (w->fade_fin) {
|
||||||
|
set_fade_callback(dpy, w, NULL, True);
|
||||||
|
w->fade_fin = False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_fade_callback(Display *dpy, win *w,
|
||||||
|
void (*callback) (Display *dpy, win *w), Bool exec_callback);
|
||||||
|
|
||||||
static double
|
static double
|
||||||
gaussian(double r, double x, double y);
|
gaussian(double r, double x, double y);
|
||||||
|
@ -476,8 +494,11 @@ get_frame_extents(Display *dpy, Window w,
|
||||||
unsigned int *top,
|
unsigned int *top,
|
||||||
unsigned int *bottom);
|
unsigned int *bottom);
|
||||||
|
|
||||||
|
static win *
|
||||||
|
paint_preprocess(Display *dpy, win *list);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
paint_all(Display *dpy, XserverRegion region);
|
paint_all(Display *dpy, XserverRegion region, win *t);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_damage(Display *dpy, XserverRegion damage);
|
add_damage(Display *dpy, XserverRegion damage);
|
||||||
|
@ -516,15 +537,15 @@ get_opacity_percent(Display *dpy, win *w);
|
||||||
static void
|
static void
|
||||||
determine_mode(Display *dpy, win *w);
|
determine_mode(Display *dpy, win *w);
|
||||||
|
|
||||||
static void
|
|
||||||
set_opacity(Display *dpy, win *w, opacity_t opacity);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
calc_opacity(Display *dpy, win *w, Bool refetch_prop);
|
calc_opacity(Display *dpy, win *w, Bool refetch_prop);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
calc_dim(Display *dpy, win *w);
|
calc_dim(Display *dpy, win *w);
|
||||||
|
|
||||||
|
static void
|
||||||
|
determine_fade(Display *dpy, win *w);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
determine_shadow(Display *dpy, win *w);
|
determine_shadow(Display *dpy, win *w);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue