From c0053d1c8a68b06abb1917a715d10cd99c8bcc64 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 25 May 2019 00:06:41 +0100 Subject: [PATCH] core: delay focus updates Delay focus updates until critical section. Rational is that focus events might arrive when the focused window hasn't been managed by compton, result in that that window not being focused. This commit makes compton mark focus update events, and only update focus in critical section, after we managed all the new windows. Fixes #177 Signed-off-by: Yuxuan Shui --- src/common.h | 2 ++ src/compton.c | 47 ++++++++++++++++++++++++----------------------- src/compton.h | 4 ---- src/event.c | 9 +++++---- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/common.h b/src/common.h index 63019fb..6df57c6 100644 --- a/src/common.h +++ b/src/common.h @@ -230,6 +230,8 @@ typedef struct session { /// If compton should quit bool quit:1; /// Whether there are pending updates, like window creation, etc. + /// TODO use separate flags for dfferent kinds of updates so we don't + /// waste our time. bool pending_updates:1; // === Expose event related === diff --git a/src/compton.c b/src/compton.c index 27b0aef..5e096d9 100644 --- a/src/compton.c +++ b/src/compton.c @@ -313,6 +313,23 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { return evmask; } +/** + * Update current active window based on EWMH _NET_ACTIVE_WIN. + * + * Does not change anything if we fail to get the attribute or the window + * returned could not be found. + */ +void update_ewmh_active_win(session_t *ps) { + // Search for the window + xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atoms->a_NET_ACTIVE_WINDOW); + auto w = find_win_all(ps, wid); + + // Mark the window focused. No need to unfocus the previous one. + if (w) { + win_set_focused(ps, w); + } +} + /** * Recheck currently focused window and set its w->focused * to true. @@ -320,7 +337,7 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { * @param ps current session * @return struct _win of currently focused window, NULL if not found */ -void recheck_focus(session_t *ps) { +static void recheck_focus(session_t *ps) { // Use EWMH _NET_ACTIVE_WINDOW if enabled if (ps->o.use_ewmh_active_win) { update_ewmh_active_win(ps); @@ -820,27 +837,6 @@ void opts_set_no_fading_openclose(session_t *ps, bool newval) { //!@} #endif -// === Events === - -/** - * Update current active window based on EWMH _NET_ACTIVE_WIN. - * - * Does not change anything if we fail to get the attribute or the window - * returned could not be found. - */ -void update_ewmh_active_win(session_t *ps) { - // Search for the window - xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atoms->a_NET_ACTIVE_WINDOW); - auto w = find_win_all(ps, wid); - - // Mark the window focused. No need to unfocus the previous one. - if (w) { - win_set_focused(ps, w); - } -} - -// === Main === - /** * Register a window as symbol, and initialize GLX context if wanted. */ @@ -1227,6 +1223,11 @@ static void _draw_callback(EV_P_ session_t *ps, int revents) { // Call fill_win on new windows handle_new_windows(ps); + auto r = xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL); + if (!ps->active_win || (r && r->focus != ps->active_win->base.id)) { + recheck_focus(ps); + } + // Refresh pixmaps refresh_stale_images(ps); @@ -1961,7 +1962,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy, } } - recheck_focus(ps); + ps->pending_updates = true; e = xcb_request_check(ps->c, xcb_ungrab_server(ps->c)); if (e) { diff --git a/src/compton.h b/src/compton.h index f0a74d7..c619cfc 100644 --- a/src/compton.h +++ b/src/compton.h @@ -42,15 +42,11 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode); xcb_window_t find_client_win(session_t *ps, xcb_window_t w); -void recheck_focus(session_t *ps); - /// Handle configure event of a root window void configure_root(session_t *ps, int width, int height); void circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce); -void update_ewmh_active_win(session_t *ps); - void update_refresh_rate(session_t *ps); void root_damaged(session_t *ps); diff --git a/src/event.c b/src/event.c index 16fc60a..a948a89 100644 --- a/src/event.c +++ b/src/event.c @@ -160,13 +160,13 @@ static inline const char *attr_pure ev_focus_detail_name(xcb_focus_in_event_t *e static inline void ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) { log_debug("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev), ev_focus_detail_name(ev)); - recheck_focus(ps); + ps->pending_updates = true; } static inline void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) { log_debug("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev), ev_focus_detail_name(ev)); - recheck_focus(ps); + ps->pending_updates = true; } static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) { @@ -266,7 +266,7 @@ static inline void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) { map_win_by_id(ps, ev->window); // FocusIn/Out may be ignored when the window is unmapped, so we must // recheck focus here - recheck_focus(ps); + ps->pending_updates = true; // to update focus } static inline void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) { @@ -402,7 +402,8 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t if (ps->root == ev->window) { if (ps->o.use_ewmh_active_win && ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) { - update_ewmh_active_win(ps); + // to update focus + ps->pending_updates = true; } else { // Destroy the root "image" if the wallpaper probably changed if (x_is_root_back_pixmap_atom(ps, ev->atom)) {