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:
parent
7d8a3e09be
commit
c0053d1c8a
|
@ -230,6 +230,8 @@ typedef struct session {
|
||||||
/// If compton should quit
|
/// If compton should quit
|
||||||
bool quit:1;
|
bool quit:1;
|
||||||
/// Whether there are pending updates, like window creation, etc.
|
/// 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;
|
bool pending_updates:1;
|
||||||
|
|
||||||
// === Expose event related ===
|
// === Expose event related ===
|
||||||
|
|
|
@ -313,6 +313,23 @@ uint32_t determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) {
|
||||||
return evmask;
|
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>
|
* Recheck currently focused window and set its <code>w->focused</code>
|
||||||
* to true.
|
* 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
|
* @param ps current session
|
||||||
* @return struct _win of currently focused window, NULL if not found
|
* @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
|
// Use EWMH _NET_ACTIVE_WINDOW if enabled
|
||||||
if (ps->o.use_ewmh_active_win) {
|
if (ps->o.use_ewmh_active_win) {
|
||||||
update_ewmh_active_win(ps);
|
update_ewmh_active_win(ps);
|
||||||
|
@ -820,27 +837,6 @@ void opts_set_no_fading_openclose(session_t *ps, bool newval) {
|
||||||
//!@}
|
//!@}
|
||||||
#endif
|
#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.
|
* 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
|
// Call fill_win on new windows
|
||||||
handle_new_windows(ps);
|
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 pixmaps
|
||||||
refresh_stale_images(ps);
|
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));
|
e = xcb_request_check(ps->c, xcb_ungrab_server(ps->c));
|
||||||
if (e) {
|
if (e) {
|
||||||
|
|
|
@ -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);
|
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
|
/// Handle configure event of a root window
|
||||||
void configure_root(session_t *ps, int width, int height);
|
void configure_root(session_t *ps, int width, int height);
|
||||||
|
|
||||||
void circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce);
|
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 update_refresh_rate(session_t *ps);
|
||||||
|
|
||||||
void root_damaged(session_t *ps);
|
void root_damaged(session_t *ps);
|
||||||
|
|
|
@ -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) {
|
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),
|
log_debug("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev),
|
||||||
ev_focus_detail_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) {
|
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),
|
log_debug("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev),
|
||||||
ev_focus_detail_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) {
|
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);
|
map_win_by_id(ps, ev->window);
|
||||||
// FocusIn/Out may be ignored when the window is unmapped, so we must
|
// FocusIn/Out may be ignored when the window is unmapped, so we must
|
||||||
// recheck focus here
|
// 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) {
|
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->root == ev->window) {
|
||||||
if (ps->o.use_ewmh_active_win &&
|
if (ps->o.use_ewmh_active_win &&
|
||||||
ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
|
ps->atoms->a_NET_ACTIVE_WINDOW == ev->atom) {
|
||||||
update_ewmh_active_win(ps);
|
// to update focus
|
||||||
|
ps->pending_updates = true;
|
||||||
} else {
|
} else {
|
||||||
// Destroy the root "image" if the wallpaper probably changed
|
// Destroy the root "image" if the wallpaper probably changed
|
||||||
if (x_is_root_back_pixmap_atom(ps, ev->atom)) {
|
if (x_is_root_back_pixmap_atom(ps, ev->atom)) {
|
||||||
|
|
Loading…
Reference in New Issue