event: reparent: always detach window from its previous parent

Otherwise we might see a window becoming child of two different parent
windows.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2020-04-05 21:07:59 +01:00
parent 53bb488530
commit 71e1a8a06f
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
1 changed files with 11 additions and 7 deletions

View File

@ -304,6 +304,10 @@ static inline void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev)
static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) {
log_debug("Window %#010x has new parent: %#010x, override_redirect: %d", log_debug("Window %#010x has new parent: %#010x, override_redirect: %d",
ev->window, ev->parent, ev->override_redirect); ev->window, ev->parent, ev->override_redirect);
auto w_top = find_toplevel(ps, ev->window);
if (w_top) {
win_unmark_client(ps, w_top);
}
if (ev->parent == ps->root) { if (ev->parent == ps->root) {
// X will generate reparent notifiy even if the parent didn't actually // X will generate reparent notifiy even if the parent didn't actually
@ -334,18 +338,18 @@ static inline void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t
// Check if the window is an undetected client window // Check if the window is an undetected client window
// Firstly, check if it's a known client window // Firstly, check if it's a known client window
if (!find_toplevel(ps, ev->window)) { if (!w_top) {
// If not, look for its frame window // If not, look for its frame window
auto w_top = find_toplevel_nocache(ps, ev->parent); auto w_real_top = find_toplevel_nocache(ps, ev->parent);
// If found, and the client window has not been determined, or its // If found, and the client window has not been determined, or its
// frame may not have a correct client, continue // frame may not have a correct client, continue
if (w_top && if (w_real_top && (!w_real_top->client_win ||
(!w_top->client_win || w_top->client_win == w_top->base.id)) { w_real_top->client_win == w_real_top->base.id)) {
// If it has WM_STATE, mark it the client window // If it has WM_STATE, mark it the client window
if (wid_has_prop(ps, ev->window, ps->atoms->aWM_STATE)) { if (wid_has_prop(ps, ev->window, ps->atoms->aWM_STATE)) {
w_top->wmwin = false; w_real_top->wmwin = false;
win_unmark_client(ps, w_top); win_unmark_client(ps, w_real_top);
win_mark_client(ps, w_top, ev->window); win_mark_client(ps, w_real_top, ev->window);
} }
// Otherwise, watch for WM_STATE on it // Otherwise, watch for WM_STATE on it
else { else {