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)) {