From 2bcc6762026926facf6256360f4fa0e46a6a5a22 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Tue, 31 Mar 2026 16:54:21 +0200 Subject: [PATCH] wayland: fix XWayland window visibility Two bugs prevented XWayland client windows from appearing: 1. flags.mapped never set for XWayland windows (window.c) The condition `else if (!dpy)` is false when dpy is the XWayland Display* (it is only true for pure native-Wayland mode with no X11). Changed to `else if (!dpy || wm_backend->is_wayland)` so XWayland windows also get flags.mapped=1 after wManageWindow, matching the semantics of XDG toplevel windows. 2. scene node positioned at xw->x,xw->y before configure round-trip handle_xwayland_map used xw->x,xw->y for the initial scene node position. These values may not yet reflect the configure sent in handle_new_xwayland_surface (the X11 round-trip is async). Changed to use view->x,view->y which are set to output/4 in handle_new_xwayland_surface and kept in sync by set_geometry listener. Also added a log line when xw->surface is NULL at map time so the cause is diagnosable from wmaker stderr. Note: if xterm connects to the wrong DISPLAY (e.g. Sway's :1 instead of wmaker's :2), no handle_xwayland_map fires at all. Check wmaker's "XWayland ready on :X" log line for the correct display number. Co-Authored-By: Claude Sonnet 4.6 --- src/backend/wayland/wl_backend.c | 10 ++++++++-- src/window.c | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index c3ea4e3..25f5872 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -1046,12 +1046,18 @@ handle_xwayland_map(struct wl_listener *listener, void *data) xw->class ? xw->class : "(none)", xw->title ? xw->title : "(none)"); - /* Add to scene graph for compositing regardless of mode. */ + /* Add to scene graph for compositing regardless of mode. + * Use view->x,y (set in handle_new_xwayland_surface to output/4) + * rather than xw->x,y which may not yet reflect the configure we + * sent; the set_geometry listener keeps them in sync thereafter. */ if (wl_state.scene && !view->scene_node && xw->surface) { view->scene_node = wlr_scene_subsurface_tree_create( &wl_state.scene->node, xw->surface); if (view->scene_node) - wlr_scene_node_set_position(view->scene_node, xw->x, xw->y); + wlr_scene_node_set_position(view->scene_node, view->x, view->y); + } else if (!xw->surface) { + wwarning("wl_backend: xwayland map id=0x%lx: surface is NULL, window will not render", + view->id); } diff --git a/src/window.c b/src/window.c index e6f4775..68a2659 100644 --- a/src/window.c +++ b/src/window.c @@ -1251,8 +1251,8 @@ WWindow *wManageWindow(WScreen *scr, WNativeWindow window) if (wwin->frame) wWindowMap(wwin); - else if (!dpy) - wwin->flags.mapped = 1; /* Wayland: toplevel is visible by definition */ + else if (!dpy || wm_backend->is_wayland) + wwin->flags.mapped = 1; /* Wayland/XWayland: scene node visible by definition */ } /* setup stacking descriptor */