win: split struct win

Currently compton handles window creation event by immediately query all
the information it needs and create a window struct with that
information. However, this is prone to race conditions.

In the future, we want to react to window creation event by creating a
placeholder in the window stack, and only query window information in a
critical section where the X server is grabbed by us.

This commit split struct win into two struct, one as placeholder, the
other for holding actual window information.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-04-17 23:14:45 +01:00
parent 27603343a1
commit bd4c242015
17 changed files with 699 additions and 514 deletions

View File

@ -50,7 +50,7 @@ static inline const char *ev_window_name(session_t *ps, xcb_window_t wid) {
} else if (ps->overlay == wid) {
name = "(Overlay)";
} else {
win *w = find_win(ps, wid);
auto w = find_managed_win(ps, wid);
if (!w) {
w = find_toplevel(ps, wid);
}
@ -169,7 +169,8 @@ static inline void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) {
static inline void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) {
assert(ev->parent == ps->root);
add_win(ps, ev->window, 0);
// TODO delay fill_win
fill_win(ps, add_win_top(ps, ev->window));
}
static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) {
@ -183,7 +184,7 @@ static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event
}
static inline void ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) {
win *w = find_win(ps, ev->window);
auto w = find_managed_win(ps, ev->window);
if (w) {
unmap_win(ps, &w, true);
}
@ -199,7 +200,7 @@ static inline void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) {
}
static inline void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) {
win *w = find_win(ps, ev->window);
auto w = find_managed_win(ps, ev->window);
if (w) {
unmap_win(ps, &w, false);
}
@ -211,12 +212,13 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
if (ev->parent == ps->root) {
// new window
add_win(ps, ev->window, 0);
// TODO delay fill_win
fill_win(ps, add_win_top(ps, ev->window));
} else {
// otherwise, find and destroy the window first
win *w = find_win(ps, ev->window);
if (w) {
unmap_win(ps, &w, true);
auto w = find_win(ps, ev->window);
if (w && w->managed) {
unmap_win(ps, (struct managed_win **)&w, true);
}
// Reset event mask in case something wrong happens
@ -228,10 +230,10 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
// Firstly, check if it's a known client window
if (!find_toplevel(ps, ev->window)) {
// If not, look for its frame window
win *w_top = find_toplevel2(ps, ev->parent);
auto w_top = find_toplevel2(ps, ev->parent);
// If found, and the client window has not been determined, or its
// frame may not have a correct client, continue
if (w_top && (!w_top->client_win || w_top->client_win == w_top->id)) {
if (w_top && (!w_top->client_win || w_top->client_win == w_top->base.id)) {
// If it has WM_STATE, mark it the client window
if (wid_has_prop(ps, ev->window, ps->atom_client)) {
w_top->wmwin = false;
@ -328,9 +330,9 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
(const uint32_t[]){determine_evmask(
ps, ev->window, WIN_EVMODE_UNKNOWN)});
win *w_top = find_toplevel2(ps, ev->window);
auto w_top = find_toplevel2(ps, ev->window);
// Initialize client_win as early as possible
if (w_top && (!w_top->client_win || w_top->client_win == w_top->id) &&
if (w_top && (!w_top->client_win || w_top->client_win == w_top->base.id) &&
wid_has_prop(ps, ev->window, ps->atom_client)) {
w_top->wmwin = false;
win_unmark_client(ps, w_top);
@ -342,14 +344,14 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, but
// there are always some stupid applications. (#144)
if (ev->atom == ps->atom_win_type) {
win *w = NULL;
struct managed_win *w = NULL;
if ((w = find_toplevel(ps, ev->window)))
win_update_wintype(ps, w);
}
// If _NET_WM_OPACITY changes
if (ev->atom == ps->atom_opacity) {
win *w = find_win(ps, ev->window) ?: find_toplevel(ps, ev->window);
auto w = find_managed_win(ps, ev->window) ?: find_toplevel(ps, ev->window);
if (w) {
win_update_opacity_prop(ps, w);
// we cannot receive OPACITY change when window is destroyed
@ -364,7 +366,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If frame extents property changes
if (ps->o.frame_opacity > 0 && ev->atom == ps->atom_frame_extents) {
win *w = find_toplevel(ps, ev->window);
auto w = find_toplevel(ps, ev->window);
if (w) {
win_update_frame_extents(ps, w, ev->window);
// If frame extents change, the window needs repaint
@ -374,7 +376,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If name changes
if (ps->o.track_wdata && (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) {
win *w = find_toplevel(ps, ev->window);
auto w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_name(ps, w)) {
win_on_factor_change(ps, w);
}
@ -382,7 +384,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If class changes
if (ps->o.track_wdata && ps->atom_class == ev->atom) {
win *w = find_toplevel(ps, ev->window);
auto w = find_toplevel(ps, ev->window);
if (w) {
win_get_class(ps, w);
win_on_factor_change(ps, w);
@ -391,7 +393,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If role changes
if (ps->o.track_wdata && ps->atom_role == ev->atom) {
win *w = find_toplevel(ps, ev->window);
auto w = find_toplevel(ps, ev->window);
if (w && 1 == win_get_role(ps, w)) {
win_on_factor_change(ps, w);
}
@ -399,15 +401,16 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// If _COMPTON_SHADOW changes
if (ps->o.respect_prop_shadow && ps->atom_compton_shadow == ev->atom) {
win *w = find_win(ps, ev->window);
if (w)
auto w = find_managed_win(ps, ev->window);
if (w) {
win_update_prop_shadow(ps, w);
}
}
// If a leader property changes
if ((ps->o.detect_transient && ps->atom_transient == ev->atom) ||
(ps->o.detect_client_leader && ps->atom_client_leader == ev->atom)) {
win *w = find_toplevel(ps, ev->window);
auto w = find_toplevel(ps, ev->window);
if (w) {
win_update_leader(ps, w);
}
@ -416,7 +419,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
// Check for other atoms we are tracking
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) {
if (platom->atom == ev->atom) {
win *w = find_win(ps, ev->window);
auto w = find_managed_win(ps, ev->window);
if (!w)
w = find_toplevel(ps, ev->window);
if (w)
@ -426,7 +429,7 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
}
}
static inline void repair_win(session_t *ps, win *w) {
static inline void repair_win(session_t *ps, struct managed_win *w) {
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
return;
@ -472,18 +475,20 @@ static inline void ev_damage_notify(session_t *ps, xcb_damage_notify_event_t *de
return;
} */
win *w = find_win(ps, de->drawable);
auto w = find_managed_win(ps, de->drawable);
if (!w)
if (!w) {
return;
}
repair_win(ps, w);
}
static inline void ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) {
win *w = find_win(ps, ev->affected_window);
if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED)
auto w = find_managed_win(ps, ev->affected_window);
if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED) {
return;
}
/*
* Empty bounding_shape may indicated an