restore NULL-buffer unmap + dispatch pending events in wl_map after redisplay

Revert the 1x1-buffer approach which caused pointer focus issues. Return
to NULL-buffer unmap which correctly hides the popup. The configure event
from the NULL unmap is dispatched in wl_map via W_WLClientDispatchPending
after wl_redisplay and before returning, ensuring the surface is
configured before the user can interact with the popup.
This commit is contained in:
lkn 2026-06-07 16:52:58 +02:00
parent 96dc7fa6a8
commit a6a692baf1
2 changed files with 12 additions and 9 deletions

View File

@ -568,16 +568,15 @@ wl_client_view_unmap(WNativeWindow id)
{
WLClientToplevel *top = wlc_top_find(id);
if (!top || !top->surface) return;
/* Replace the popup buffer with a 1x1 transparent pixel instead of
* attaching NULL (which triggers a wlroots xdg unmap + configure
* cycle). A 1x1 invisible buffer keeps the surface alive and
* configured, so the next popup open can commit immediately. */
if (top->buf) wlclient_destroy_shm_buffer(top->buf);
top->buf = wlclient_create_shm_buffer(top->ctx, 1, 1);
if (!top->buf) return;
wl_surface_attach(top->surface, top->buf->wl_buf, 0, 0);
wl_surface_damage_buffer(top->surface, 0, 0, 1, 1);
/* Attach NULL + commit: the standard Wayland way to hide a surface.
* This triggers a wlroots xdg unmap and the compositor sends a new
* configure event. We set configured=0 so the next commit waits
* for the configure. The popup reopen path (wl_map) calls
* wl_display_dispatch_pending after redisplay to ensure the
* configure is processed before the user can interact. */
wl_surface_attach(top->surface, NULL, 0, 0);
wl_surface_commit(top->surface);
top->configured = 0;
if (top->ctx && top->ctx->display)
wl_display_flush(top->ctx->display);
}

View File

@ -341,6 +341,10 @@ static void wl_map(void *vctx, W_View *view)
view->pos.x, view->pos.y);
}
wl_redisplay(vctx, view);
/* Dispatch any pending Wayland events (e.g. the configure
* from a NULL-buffer unmap) so the next commit succeeds. */
extern void W_WLClientDispatchPending(void);
W_WLClientDispatchPending();
return;
}
/* Non-toplevel: find the toplevel and redisplay from there,