diff --git a/WINGs/wclient_wl.c b/WINGs/wclient_wl.c index 37a0424..359bb7a 100644 --- a/WINGs/wclient_wl.c +++ b/WINGs/wclient_wl.c @@ -561,89 +561,24 @@ wl_client_toplevel_destroy(struct W_View *view) } void -wl_client_toplevel_recycle(WNativeWindow id) +wl_client_view_unmap(WNativeWindow id) { WLClientToplevel *top = wlc_top_find(id); - if (!top) return; - /* Destroy the Wayland protocol objects but keep the - * WLClientToplevel struct and its view->window mapping, - * so the surface can be recreated cleanly on remap. */ - if (top->wmaker_popup) { - wmaker_popup_v1_destroy(top->wmaker_popup); - top->wmaker_popup = NULL; - } - if (top->xdg_toplevel) { - xdg_toplevel_destroy(top->xdg_toplevel); - top->xdg_toplevel = NULL; - } - if (top->xdg_surface) { - xdg_surface_destroy(top->xdg_surface); - top->xdg_surface = NULL; - } - if (top->surface) { - wl_surface_destroy(top->surface); - top->surface = NULL; - } - if (top->buf) { - wlclient_destroy_shm_buffer(top->buf); - top->buf = NULL; - } - top->configured = 0; - top->mapped = 0; - top->want_close = 0; -} - -static void -wl_client_toplevel_remap_locked(WLClientToplevel *top) -{ - if (!top || top->surface) return; /* already mapped */ - WLClientCtx *ctx = top->ctx; - if (!ctx || !ctx->compositor || !ctx->wm_base) return; - - top->buf = wlclient_create_shm_buffer(ctx, - top->pending_w, top->pending_h); - if (!top->buf) return; - - top->surface = wl_compositor_create_surface(ctx->compositor); - if (!top->surface) return; - - top->xdg_surface = xdg_wm_base_get_xdg_surface( - ctx->wm_base, top->surface); - if (!top->xdg_surface) return; - xdg_surface_add_listener(top->xdg_surface, - &xdg_surface_listener, top); - - top->xdg_toplevel = xdg_surface_get_toplevel( - top->xdg_surface); - if (!top->xdg_toplevel) return; - xdg_toplevel_add_listener(top->xdg_toplevel, - &xdg_toplevel_listener, top); - - if (top->view->flags.popup) { - xdg_toplevel_set_app_id(top->xdg_toplevel, "wings-popup"); - xdg_toplevel_set_title(top->xdg_toplevel, ""); - if (ctx->wmaker_popup_mgr) { - top->wmaker_popup = - wmaker_popup_manager_v1_get_popup( - ctx->wmaker_popup_mgr, - top->xdg_toplevel); - if (top->wmaker_popup && ctx->main_toplevel) - wmaker_popup_v1_set_parent( - top->wmaker_popup, - ctx->main_toplevel); - } - } - + 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. */ + wl_surface_attach(top->surface, NULL, 0, 0); wl_surface_commit(top->surface); - W_SetViewBacking(top->view->window, top->buf->image); + if (top->ctx && top->ctx->display) + wl_display_flush(top->ctx->display); } -void -wl_client_toplevel_remap(WNativeWindow id) -{ - WLClientToplevel *top = wlc_top_find(id); - wl_client_toplevel_remap_locked(top); -} + + + + + void W_WLClientSetMinMaxSize(W_View *view) diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index 359cc52..f350668 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -18,8 +18,6 @@ static unsigned int wl_view_next_id = WL_VIEW_ID_BASE; void (*W_ViewCommitBackingFn)(unsigned long id) = NULL; /* Optional hook: destroy wl_surface + xdg_toplevel on popup unmap * so the compositor has no stale state. Set by the WM backend. */ -void (*W_WLClientToplevelRecycleFn)(unsigned long id) = NULL; -void (*W_WLClientToplevelRemapFn)(unsigned long id) = NULL; void (*W_ViewDestroyBackingFn)(unsigned long id) = NULL; void (*W_ViewSceneNodeSetEnabledFn)(unsigned long id, int enabled) = NULL; @@ -224,12 +222,16 @@ static void wl_unmap(void *vctx, W_View *view) } else wwarning("wl_unmap: W_ViewSceneNodeSetEnabledFn is NULL"); /* Scene node disabled in the diagnostic block above. */ - /* Destroy the WINGs client wl_surface + xdg_toplevel on unmap so - * the compositor has no stale state for this surface. The recycle - * function preserves the WLClientToplevel struct and ID mapping - * so the surface can be recreated on the next map. */ - if (view->flags.topLevel && view->flags.popup && W_WLClientToplevelRecycleFn) - W_WLClientToplevelRecycleFn((unsigned long)view->window); + /* In client mode (e.g. WPrefs), W_ViewSceneNodeSetEnabledFn may be + * NULL because the compositor-side function is not available in the + * client process. Attach NULL to the wl_surface, which is the + * standard Wayland way for a client to hide a surface. */ + if (view->flags.topLevel && view->flags.popup + && !W_ViewSceneNodeSetEnabledFn) { + extern void wl_client_view_unmap(WNativeWindow id); + wl_client_view_unmap((WNativeWindow)view->window); + } + if (view->parent && view->parent->flags.mapped) wl_redisplay(vctx, view->parent); } @@ -324,10 +326,7 @@ static void wl_map(void *vctx, W_View *view) child = child->nextSister; } } - /* Re-enable scene node after unmap so the surface becomes visible again. - * For recycled popups, recreate the wl_surface + xdg_toplevel first. */ - if (view->flags.topLevel && view->flags.popup && W_WLClientToplevelRemapFn) - W_WLClientToplevelRemapFn((unsigned long)view->window); + if (W_ViewSceneNodeSetEnabledFn) W_ViewSceneNodeSetEnabledFn((unsigned long)view->window, 1); diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index a425438..56ac5c8 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -470,12 +470,7 @@ wl_display_open(const char *name) unsigned int, int, int, unsigned long); extern void wl_pointer_ungrab(unsigned long); W_WLPointerGrabFn = wl_pointer_grab; - extern void (*W_WLClientToplevelRecycleFn)(unsigned long); - extern void wl_client_toplevel_recycle(WNativeWindow); - W_WLClientToplevelRecycleFn = wl_client_toplevel_recycle; - extern void (*W_WLClientToplevelRemapFn)(unsigned long); - extern void wl_client_toplevel_remap(WNativeWindow); - W_WLClientToplevelRemapFn = wl_client_toplevel_remap; + W_WLPointerUngrabFn = wl_pointer_ungrab; extern void (*W_ClipboardStoreFn)(const char *text, int len);