event: destroy: recheck client instead of unmark client

We detach the client window from its frame when it's destroyed, so later
a new window can be attached to that frame. But turns out that's not
enough.

When i3 restarts, it attaches a placeholder window to the frame, then
the real window, and only after that, it will destroy the placeholder.
The real window will fail to attach as the frame already has a client.
When the placeholder is destroyed, we have to call recheck client to
pick up the real window that failed to attach previously.

Related: #299

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2020-04-05 22:41:45 +01:00
parent 481ac54f67
commit e9ab970989
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
3 changed files with 7 additions and 4 deletions

View File

@ -274,7 +274,7 @@ static inline void ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *
if (w != NULL) { if (w != NULL) {
auto _ attr_unused = destroy_win_start(ps, w); auto _ attr_unused = destroy_win_start(ps, w);
} else if (mw != NULL) { } else if (mw != NULL) {
win_unmark_client(ps, mw); win_recheck_client(ps, mw);
} else { } else {
log_debug("Received a destroy notify from an unknown window, %#010x", log_debug("Received a destroy notify from an unknown window, %#010x",
ev->window); ev->window);

View File

@ -1037,6 +1037,8 @@ void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client)
*/ */
void win_unmark_client(session_t *ps, struct managed_win *w) { void win_unmark_client(session_t *ps, struct managed_win *w) {
xcb_window_t client = w->client_win; xcb_window_t client = w->client_win;
log_debug("Detaching client window %#010x from frame %#010x (%s)", client,
w->base.id, w->name);
w->client_win = XCB_NONE; w->client_win = XCB_NONE;
@ -1052,7 +1054,7 @@ void win_unmark_client(session_t *ps, struct managed_win *w) {
* @param ps current session * @param ps current session
* @param w struct _win of the parent window * @param w struct _win of the parent window
*/ */
static void win_recheck_client(session_t *ps, struct managed_win *w) { void win_recheck_client(session_t *ps, struct managed_win *w) {
// Initialize wmwin to false // Initialize wmwin to false
w->wmwin = false; w->wmwin = false;
@ -1062,14 +1064,14 @@ static void win_recheck_client(session_t *ps, struct managed_win *w) {
// sets override-redirect flags on all frame windows. // sets override-redirect flags on all frame windows.
xcb_window_t cw = find_client_win(ps, w->base.id); xcb_window_t cw = find_client_win(ps, w->base.id);
if (cw) { if (cw) {
log_trace("(%#010x): client %#010x", w->base.id, cw); log_debug("(%#010x): client %#010x", w->base.id, cw);
} }
// Set a window's client window to itself if we couldn't find a // Set a window's client window to itself if we couldn't find a
// client window // client window
if (!cw) { if (!cw) {
cw = w->base.id; cw = w->base.id;
w->wmwin = !w->a.override_redirect; w->wmwin = !w->a.override_redirect;
log_trace("(%#010x): client self (%s)", w->base.id, log_debug("(%#010x): client self (%s)", w->base.id,
(w->wmwin ? "wmwin" : "override-redirected")); (w->wmwin ? "wmwin" : "override-redirected"));
} }

View File

@ -299,6 +299,7 @@ void win_on_win_size_change(session_t *ps, struct managed_win *w);
void win_update_wintype(session_t *ps, struct managed_win *w); void win_update_wintype(session_t *ps, struct managed_win *w);
void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client); void win_mark_client(session_t *ps, struct managed_win *w, xcb_window_t client);
void win_unmark_client(session_t *ps, struct managed_win *w); void win_unmark_client(session_t *ps, struct managed_win *w);
void win_recheck_client(session_t *ps, struct managed_win *w);
bool win_get_class(session_t *ps, struct managed_win *w); bool win_get_class(session_t *ps, struct managed_win *w);
/** /**