Change fade callback function parameter

Change `win *` to `win **`, because a window could be freed by the
callback, so we can set `*w` to NULL to communicate that.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2018-09-29 23:30:19 +01:00
parent 417744df14
commit ab12467c3f
3 changed files with 52 additions and 65 deletions

View File

@ -1162,7 +1162,7 @@ struct win {
/// Override value of window fade state. Set by D-Bus method calls. /// Override value of window fade state. Set by D-Bus method calls.
switch_t fade_force; switch_t fade_force;
/// Callback to be called after fading completed. /// Callback to be called after fading completed.
void (*fade_callback) (session_t *ps, win *w); void (*fade_callback) (session_t *ps, win **w);
// Frame-opacity-related members // Frame-opacity-related members
/// Current window frame opacity. Affected by window opacity. /// Current window frame opacity. Affected by window opacity.

View File

@ -16,17 +16,18 @@
#include <xcb/xcb_image.h> #include <xcb/xcb_image.h>
#include "compton.h" #include "compton.h"
#ifdef CONFIG_OPENGL
#include "opengl.h"
#endif
#include "win.h" #include "win.h"
#include "x.h" #include "x.h"
#include "config.h" #include "config.h"
static void static void
configure_win(session_t *ps, xcb_configure_notify_event_t *ce); finish_destroy_win(session_t *ps, win **_w);
static bool static void
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, configure_win(session_t *ps, xcb_configure_notify_event_t *ce);
int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns,
XserverRegion reg_clip);
static void static void
get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass); get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass);
@ -103,18 +104,12 @@ recheck_focus(session_t *ps);
static bool static bool
get_root_tile(session_t *ps); get_root_tile(session_t *ps);
static void
finish_map_win(session_t *ps, win *w);
static double static double
get_opacity_percent(win *w); get_opacity_percent(win *w);
static void static void
restack_win(session_t *ps, win *w, Window new_above); restack_win(session_t *ps, win *w, Window new_above);
static void
destroy_callback(session_t *ps, win *w);
static void static void
update_ewmh_active_win(session_t *ps); update_ewmh_active_win(session_t *ps);
@ -333,20 +328,34 @@ run_fade(session_t *ps, win *w, unsigned steps) {
* *
* @param exec_callback whether the previous callback is to be executed * @param exec_callback whether the previous callback is to be executed
*/ */
void set_fade_callback(session_t *ps, win *w, void set_fade_callback(session_t *ps, win **_w,
void (*callback) (session_t *ps, win *w), bool exec_callback) { void (*callback) (session_t *ps, win **w), bool exec_callback) {
void (*old_callback) (session_t *ps, win *w) = w->fade_callback; win *w = *_w;
void (*old_callback) (session_t *ps, win **w) = w->fade_callback;
w->fade_callback = callback; w->fade_callback = callback;
// Must be the last line as the callback could destroy w! // Must be the last line as the callback could destroy w!
if (exec_callback && old_callback) { if (exec_callback && old_callback) {
old_callback(ps, w); old_callback(ps, _w);
// Although currently no callback function affects window state on // Although currently no callback function affects window state on
// next paint, it could, in the future // next paint, it could, in the future
ps->idling = false; ps->idling = false;
} }
} }
/**
* Execute fade callback of a window if fading finished.
* XXX should be in win.c
*/
static inline void
check_fade_fin(session_t *ps, win **_w) {
win *w = *_w;
if (w->fade_callback && w->opacity == w->opacity_tgt) {
// Must be the last line as the callback could destroy w!
set_fade_callback(ps, _w, NULL, true);
}
}
// === Shadows === // === Shadows ===
static double __attribute__((const)) static double __attribute__((const))
@ -1160,19 +1169,17 @@ paint_preprocess(session_t *ps, win *list) {
w->flags = 0; w->flags = 0;
} }
// Avoid setting w->to_paint if w is to be freed
bool destroyed = (w->opacity_tgt == w->opacity && w->destroyed);
if (to_paint) { if (to_paint) {
w->prev_trans = t; w->prev_trans = t;
t = w; t = w;
} }
else { else {
assert(w->destroyed == (w->fade_callback == destroy_callback)); assert(w->destroyed == (w->fade_callback == finish_destroy_win));
check_fade_fin(ps, w); check_fade_fin(ps, &w);
} }
if (!destroyed) { // Avoid setting w->to_paint if w is to be freed
if (w) {
w->to_paint = to_paint; w->to_paint = to_paint;
if (w->to_paint) { if (w->to_paint) {
@ -1980,7 +1987,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
win *pprev = NULL; win *pprev = NULL;
for (win *w = t; w; w = pprev) { for (win *w = t; w; w = pprev) {
pprev = w->prev_trans; pprev = w->prev_trans;
check_fade_fin(ps, w); check_fade_fin(ps, &w);
} }
} }
} }
@ -2023,6 +2030,15 @@ repair_win(session_t *ps, win *w) {
add_damage(ps, parts); add_damage(ps, parts);
} }
static void
finish_map_win(session_t *ps, win **_w) {
win *w = *_w;
w->in_openclose = false;
if (ps->o.no_fading_openclose) {
win_determine_fade(ps, w);
}
}
void void
map_win(session_t *ps, Window id) { map_win(session_t *ps, Window id) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_connection_t *c = XGetXCBConnection(ps->dpy);
@ -2107,7 +2123,7 @@ map_win(session_t *ps, Window id) {
// Set fading state // Set fading state
w->in_openclose = true; w->in_openclose = true;
set_fade_callback(ps, w, finish_map_win, true); set_fade_callback(ps, &w, finish_map_win, true);
win_determine_fade(ps, w); win_determine_fade(ps, w);
win_determine_blur_background(ps, w); win_determine_blur_background(ps, w);
@ -2130,17 +2146,9 @@ map_win(session_t *ps, Window id) {
} }
static void static void
finish_map_win(session_t *ps, win *w) { finish_unmap_win(session_t *ps, win **_w) {
w->in_openclose = false; win *w = *_w;
if (ps->o.no_fading_openclose) {
win_determine_fade(ps, w);
}
}
static void
finish_unmap_win(session_t *ps, win *w) {
w->ever_damaged = false; w->ever_damaged = false;
w->in_openclose = false; w->in_openclose = false;
update_reg_ignore_expire(ps, w); update_reg_ignore_expire(ps, w);
@ -2157,12 +2165,8 @@ finish_unmap_win(session_t *ps, win *w) {
} }
static void static void
unmap_callback(session_t *ps, win *w) { unmap_win(session_t *ps, win **_w) {
finish_unmap_win(ps, w); win *w = *_w;
}
static void
unmap_win(session_t *ps, win *w) {
if (!w || IsUnmapped == w->a.map_state) return; if (!w || IsUnmapped == w->a.map_state) return;
if (w->destroyed) return; if (w->destroyed) return;
@ -2179,7 +2183,7 @@ unmap_win(session_t *ps, win *w) {
// Fading out // Fading out
w->flags |= WFLAG_OPCT_CHANGE; w->flags |= WFLAG_OPCT_CHANGE;
set_fade_callback(ps, w, unmap_callback, false); set_fade_callback(ps, _w, finish_unmap_win, false);
w->in_openclose = true; w->in_openclose = true;
win_determine_fade(ps, w); win_determine_fade(ps, w);
@ -2408,7 +2412,8 @@ circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) {
} }
static void static void
finish_destroy_win(session_t *ps, win *w) { finish_destroy_win(session_t *ps, win **_w) {
win *w = *_w;
assert(w->destroyed); assert(w->destroyed);
win **prev = NULL, *i = NULL; win **prev = NULL, *i = NULL;
@ -2422,7 +2427,7 @@ finish_destroy_win(session_t *ps, win *w) {
printf_dbgf("(%#010lx \"%s\"): %p\n", w->id, w->name, w); printf_dbgf("(%#010lx \"%s\"): %p\n", w->id, w->name, w);
#endif #endif
finish_unmap_win(ps, w); finish_unmap_win(ps, _w);
*prev = w->next; *prev = w->next;
// Clear active_win if it's pointing to the destroyed window // Clear active_win if it's pointing to the destroyed window
@ -2438,16 +2443,12 @@ finish_destroy_win(session_t *ps, win *w) {
w2->prev_trans = NULL; w2->prev_trans = NULL;
free(w); free(w);
*_w = NULL;
break; break;
} }
} }
} }
static void
destroy_callback(session_t *ps, win *w) {
finish_destroy_win(ps, w);
}
static void static void
destroy_win(session_t *ps, Window id) { destroy_win(session_t *ps, Window id) {
win *w = find_win(ps, id); win *w = find_win(ps, id);
@ -2457,7 +2458,7 @@ destroy_win(session_t *ps, Window id) {
#endif #endif
if (w) { if (w) {
unmap_win(ps, w); unmap_win(ps, &w);
w->destroyed = true; w->destroyed = true;
@ -2465,7 +2466,7 @@ destroy_win(session_t *ps, Window id) {
win_determine_fade(ps, w); win_determine_fade(ps, w);
// Set fading callback // Set fading callback
set_fade_callback(ps, w, destroy_callback, false); set_fade_callback(ps, &w, finish_destroy_win, false);
#ifdef CONFIG_DBUS #ifdef CONFIG_DBUS
// Send D-Bus signal // Send D-Bus signal
@ -2905,7 +2906,7 @@ ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
win *w = find_win(ps, ev->window); win *w = find_win(ps, ev->window);
if (w) if (w)
unmap_win(ps, w); unmap_win(ps, &w);
} }
inline static void inline static void

View File

@ -47,9 +47,6 @@ find_client_win(session_t *ps, Window w);
win *find_toplevel2(session_t *ps, Window wid); win *find_toplevel2(session_t *ps, Window wid);
void set_fade_callback(session_t *ps, win *w,
void (*callback) (session_t *ps, win *w), bool exec_callback);
void map_win(session_t *ps, Window id); void map_win(session_t *ps, Window id);
void void
@ -348,17 +345,6 @@ wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) {
return true; return true;
} }
/**
* Execute fade callback of a window if fading finished.
*/
static inline void
check_fade_fin(session_t *ps, win *w) {
if (w->fade_callback && w->opacity == w->opacity_tgt) {
// Must be the last line as the callback could destroy w!
set_fade_callback(ps, w, NULL, true);
}
}
/** /**
* Stop listening for events on a particular window. * Stop listening for events on a particular window.
*/ */