From 0ea33dc830fa0eb80432504ea24701d7db0b162c Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sat, 28 Mar 2026 06:36:22 +0100 Subject: [PATCH] =?UTF-8?q?wayland:=20Phase=2041=20=E2=80=94=20prop=5Fget?= =?UTF-8?q?=5Fwm=5Fclass/window=5Ffetch=5Fname=20from=20XDG=20metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add wl_find_view_by_id() helper that walks toplevel_list to recover a wl_toplevel_view from its synthetic WNativeWindow ID. Implement vtable slots: - prop_get_wm_class: returns XDG app_id as both WM_CLASS and WM_INSTANCE - window_fetch_name: returns XDG toplevel title Extend the wManageWindow success log to include class= and name= so the smoke test can verify these fields are populated from Wayland metadata. Smoke test: add Phase 41 check — grep for "class=org.freedesktop.weston.simple-shm" in manage log. Co-Authored-By: Claude Sonnet 4.6 --- src/backend/wayland/wl_backend.c | 45 +++++++++++++++++++++++++++----- tests/wl-smoke-test.sh | 7 +++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index ab4171d..6c8f6b7 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -17,6 +17,8 @@ * synthetic WNativeWindow IDs; context_save/find/delete implemented. * Phase 39: handle_toplevel_map wires XDG toplevel map to wManageWindow so * Wayland surfaces appear in scr->focused_window list. + * Phase 40: handle_toplevel_unmap wires XDG toplevel unmap to wUnmanageWindow. + * Phase 41: prop_get_wm_class and window_fetch_name return XDG app_id/title. */ #ifdef HAVE_CONFIG_H @@ -131,6 +133,18 @@ frame_timer_cb(void *data) #define VIEW_FROM_LISTENER(ptr, field) \ ((struct wl_toplevel_view *)((char *)(ptr) - offsetof(struct wl_toplevel_view, field))) +/* Phase 41: look up the view for a given synthetic WNativeWindow ID. */ +static struct wl_toplevel_view * +wl_find_view_by_id(WNativeWindow id) +{ + struct wl_toplevel_view *v; + wl_list_for_each(v, &wl_state.toplevel_list, link) { + if (v->id == id) + return v; + } + return NULL; +} + /* * Phase 38: toplevel map — surface is ready to be managed. */ @@ -145,13 +159,16 @@ handle_toplevel_map(struct wl_listener *listener, void *data) view->xdg_surface->toplevel->app_id ? view->xdg_surface->toplevel->app_id : "(none)", view->xdg_surface->toplevel->title ? view->xdg_surface->toplevel->title : "(none)"); - /* Phase 39: register the surface as a managed window. */ + /* Phase 39/41: register the surface as a managed window. */ { WScreen *scr = wScreenWithNumber(0); if (scr) { WWindow *wwin = wManageWindow(scr, view->id); if (wwin) - wwarning("wl_backend: wManageWindow succeeded id=0x%lx", view->id); + wwarning("wl_backend: wManageWindow succeeded id=0x%lx class=%s name=%s", + view->id, + wwin->wm_class ? wwin->wm_class : "(none)", + wwin->wm_instance ? wwin->wm_instance : "(none)"); } } } @@ -645,15 +662,31 @@ static int wl_prop_get_wm_class(WNativeWindow win, char **wm_class, char **wm_instance) { - (void)win; - *wm_class = strdup("default"); - *wm_instance = strdup("default"); + /* Phase 41: use XDG app_id as both WM_CLASS and WM_INSTANCE. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + const char *app_id = (v && v->xdg_surface && v->xdg_surface->toplevel && + v->xdg_surface->toplevel->app_id) + ? v->xdg_surface->toplevel->app_id : "wayland-client"; + *wm_class = strdup(app_id); + *wm_instance = strdup(app_id); return 0; } static Bool wl_window_fetch_name(WNativeWindow win, char **name_out) -{ (void)win; *name_out = NULL; return False; } +{ + /* Phase 41: use XDG toplevel title as the window name. */ + struct wl_toplevel_view *v = wl_find_view_by_id(win); + const char *title = (v && v->xdg_surface && v->xdg_surface->toplevel && + v->xdg_surface->toplevel->title) + ? v->xdg_surface->toplevel->title : NULL; + if (title) { + *name_out = strdup(title); + return True; + } + *name_out = NULL; + return False; +} static Bool wl_window_get_icon_name(WNativeWindow win, char **name_out) diff --git a/tests/wl-smoke-test.sh b/tests/wl-smoke-test.sh index 0d1fae2..03be0e8 100755 --- a/tests/wl-smoke-test.sh +++ b/tests/wl-smoke-test.sh @@ -22,6 +22,8 @@ # logs "wManageWindow succeeded" for the synthetic surface ID # 10. (Phase 40) wUnmanageWindow called when client disconnects: compositor # logs "toplevel unmapped" and exits cleanly after cleanup +# 11. (Phase 41) prop_get_wm_class returns XDG app_id: "wManageWindow +# succeeded" log includes class=org.freedesktop.weston.simple-shm # # This test grows as wl_backend vtable slots are implemented. # @@ -162,6 +164,11 @@ if command -v weston-simple-shm >/dev/null 2>&1; then grep -q 'toplevel unmapped' /tmp/wl-smoke-stderr \ || die "compositor did not log 'toplevel unmapped' (wUnmanageWindow not triggered)" echo " unmanage check: toplevel unmapped and wUnmanageWindow called" + + # -- 11. Phase 41: wm_class set from XDG app_id ---------------------- + grep -q 'class=org.freedesktop.weston.simple-shm' /tmp/wl-smoke-stderr \ + || die "wManageWindow did not log XDG app_id as wm_class" + echo " class check: wm_class populated from XDG app_id" else echo " client check: skipped (weston-simple-shm not installed)" fi