wayland: Phase 41 — prop_get_wm_class/window_fetch_name from XDG metadata

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 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-28 06:36:22 +01:00
parent 490ecb34ff
commit 0ea33dc830
2 changed files with 46 additions and 6 deletions

View File

@ -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)

View File

@ -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