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 <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-05-25 00:06:41 +01:00
parent 7d8a3e09be
commit c0053d1c8a
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
4 changed files with 31 additions and 31 deletions

View File

@ -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 ===

View File

@ -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 <code>w->focused</code>
* 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) {

View File

@ -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);

View File

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