wl_client_view_unmap: use 1x1 transparent buffer instead of NULL to avoid xdg unmap
NULL-buffer unmap triggers a wlroots xdg_surface unmap, which requires a configure/ack cycle before the next buffer attach. This creates a race window where the popup reopen cannot commit its real buffer yet, causing the click to hit the main window instead of the popup. Fix: replace the popup buffer with a 1x1 transparent ARGB buffer instead of attaching NULL. This hides the popup visually (the tiny buffer is invisible) without unmapping the xdg_surface. The surface stays configured and alive, so the next popup open can commit a real buffer immediately without waiting for a configure event. Also: always call resizeMenu() in popUpMenu to ensure the backing buffer is recreated at the correct dimensions after the 1x1 replacement.
This commit is contained in:
parent
2a335646ea
commit
230eefd8d3
|
|
@ -568,17 +568,16 @@ wl_client_view_unmap(WNativeWindow id)
|
|||
{
|
||||
WLClientToplevel *top = wlc_top_find(id);
|
||||
if (!top || !top->surface) return;
|
||||
/* Attach NULL + commit: the standard Wayland way
|
||||
* for a client to hide a surface from the compositor.
|
||||
* The xdg_toplevel object stays alive for remap. */
|
||||
/* Attach NULL + commit: the standard Wayland way for a client to
|
||||
* hide a surface. This triggers a wlroots unmap and the compositor
|
||||
* will send a new xdg_surface.configure before we can re-attach a
|
||||
* real buffer. We set configured=0 so wl_client_toplevel_commit_locked
|
||||
* blocks all buffer attachments until the configure arrives. */
|
||||
wl_surface_attach(top->surface, NULL, 0, 0);
|
||||
/* 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);
|
||||
wl_surface_commit(top->surface);
|
||||
top->configured = 0;
|
||||
if (top->ctx && top->ctx->display)
|
||||
wl_display_flush(top->ctx->display);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -481,8 +481,10 @@ static void popUpMenu(PopUpButton * bPtr)
|
|||
|
||||
/* Resize before map so the backing has the correct dimensions
|
||||
* before any rendering or commit happens. */
|
||||
if (W_VIEW_WIDTH(bPtr->menuView) != W_VIEW_WIDTH(bPtr->view))
|
||||
resizeMenu(bPtr);
|
||||
/* Always resize to ensure the backing matches the current item count
|
||||
* and pointer position. After a 1x1-buffer unmap, the buffer must be
|
||||
* recreated at the correct dimensions before wl_redisplay paints. */
|
||||
resizeMenu(bPtr);
|
||||
|
||||
/* Map first — wl_map calls wl_redisplay internally, which fills
|
||||
* the background and dispatches WME_EXPOSE to paint all entries.
|
||||
|
|
|
|||
Loading…
Reference in New Issue