From ab12467c3fdb64df8fad0092e2ab6975477e4861 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 29 Sep 2018 23:30:19 +0100 Subject: [PATCH] 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 --- src/common.h | 2 +- src/compton.c | 101 +++++++++++++++++++++++++------------------------- src/compton.h | 14 ------- 3 files changed, 52 insertions(+), 65 deletions(-) diff --git a/src/common.h b/src/common.h index 682dd45..84cf52c 100644 --- a/src/common.h +++ b/src/common.h @@ -1162,7 +1162,7 @@ struct win { /// Override value of window fade state. Set by D-Bus method calls. switch_t fade_force; /// 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 /// Current window frame opacity. Affected by window opacity. diff --git a/src/compton.c b/src/compton.c index c43cf78..8e645c9 100644 --- a/src/compton.c +++ b/src/compton.c @@ -16,17 +16,18 @@ #include #include "compton.h" +#ifdef CONFIG_OPENGL +#include "opengl.h" +#endif #include "win.h" #include "x.h" #include "config.h" static void -configure_win(session_t *ps, xcb_configure_notify_event_t *ce); +finish_destroy_win(session_t *ps, win **_w); -static bool -xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, - int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns, - XserverRegion reg_clip); +static void +configure_win(session_t *ps, xcb_configure_notify_event_t *ce); static void get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass); @@ -103,18 +104,12 @@ recheck_focus(session_t *ps); static bool get_root_tile(session_t *ps); -static void -finish_map_win(session_t *ps, win *w); - static double get_opacity_percent(win *w); static void restack_win(session_t *ps, win *w, Window new_above); -static void -destroy_callback(session_t *ps, win *w); - static void 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 */ -void set_fade_callback(session_t *ps, win *w, - void (*callback) (session_t *ps, win *w), bool exec_callback) { - void (*old_callback) (session_t *ps, win *w) = w->fade_callback; +void set_fade_callback(session_t *ps, win **_w, + void (*callback) (session_t *ps, win **w), bool exec_callback) { + win *w = *_w; + void (*old_callback) (session_t *ps, win **w) = w->fade_callback; w->fade_callback = callback; // Must be the last line as the callback could destroy w! if (exec_callback && old_callback) { - old_callback(ps, w); + old_callback(ps, _w); // Although currently no callback function affects window state on // next paint, it could, in the future 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 === static double __attribute__((const)) @@ -1160,19 +1169,17 @@ paint_preprocess(session_t *ps, win *list) { 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) { w->prev_trans = t; t = w; } else { - assert(w->destroyed == (w->fade_callback == destroy_callback)); - check_fade_fin(ps, w); + assert(w->destroyed == (w->fade_callback == finish_destroy_win)); + 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; if (w->to_paint) { @@ -1980,7 +1987,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t win *pprev = NULL; for (win *w = t; w; w = pprev) { 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); } +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 map_win(session_t *ps, Window id) { xcb_connection_t *c = XGetXCBConnection(ps->dpy); @@ -2107,7 +2123,7 @@ map_win(session_t *ps, Window id) { // Set fading state 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_blur_background(ps, w); @@ -2130,17 +2146,9 @@ map_win(session_t *ps, Window id) { } static void -finish_map_win(session_t *ps, win *w) { - w->in_openclose = false; - if (ps->o.no_fading_openclose) { - win_determine_fade(ps, w); - } -} - -static void -finish_unmap_win(session_t *ps, win *w) { +finish_unmap_win(session_t *ps, win **_w) { + win *w = *_w; w->ever_damaged = false; - w->in_openclose = false; update_reg_ignore_expire(ps, w); @@ -2157,12 +2165,8 @@ finish_unmap_win(session_t *ps, win *w) { } static void -unmap_callback(session_t *ps, win *w) { - finish_unmap_win(ps, w); -} - -static void -unmap_win(session_t *ps, win *w) { +unmap_win(session_t *ps, win **_w) { + win *w = *_w; if (!w || IsUnmapped == w->a.map_state) return; if (w->destroyed) return; @@ -2179,7 +2183,7 @@ unmap_win(session_t *ps, win *w) { // Fading out 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; win_determine_fade(ps, w); @@ -2408,7 +2412,8 @@ circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) { } static void -finish_destroy_win(session_t *ps, win *w) { +finish_destroy_win(session_t *ps, win **_w) { + win *w = *_w; assert(w->destroyed); 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); #endif - finish_unmap_win(ps, w); + finish_unmap_win(ps, _w); *prev = w->next; // 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; free(w); + *_w = NULL; break; } } } -static void -destroy_callback(session_t *ps, win *w) { - finish_destroy_win(ps, w); -} - static void destroy_win(session_t *ps, Window id) { win *w = find_win(ps, id); @@ -2457,7 +2458,7 @@ destroy_win(session_t *ps, Window id) { #endif if (w) { - unmap_win(ps, w); + unmap_win(ps, &w); w->destroyed = true; @@ -2465,7 +2466,7 @@ destroy_win(session_t *ps, Window id) { win_determine_fade(ps, w); // Set fading callback - set_fade_callback(ps, w, destroy_callback, false); + set_fade_callback(ps, &w, finish_destroy_win, false); #ifdef CONFIG_DBUS // 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); if (w) - unmap_win(ps, w); + unmap_win(ps, &w); } inline static void diff --git a/src/compton.h b/src/compton.h index 434c20c..5ec4fd4 100644 --- a/src/compton.h +++ b/src/compton.h @@ -47,9 +47,6 @@ find_client_win(session_t *ps, Window w); 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 @@ -348,17 +345,6 @@ wid_set_text_prop(session_t *ps, Window wid, Atom prop_atom, char *str) { 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. */