wayland: Phase 50 — client_get_pid via wl_client_get_credentials; misc guards

Implement wl_client_get_pid using wl_resource_get_client +
wl_client_get_credentials so the WM can retrieve the OS PID of
Wayland clients.  Guard getCommandForWindow in misc.c against NULL
dpy to prevent XGetCommand crash when the real PID path fires.
Guard wWindowChangeWorkspace against NULL frame for frameless
Wayland windows.  Log pid= in the wManageWindow-succeeded line;
add Phase 50 pid check to smoke test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-28 07:03:55 +01:00
parent 0ca749896a
commit 14da9a65ae
4 changed files with 30 additions and 4 deletions

View File

@ -151,6 +151,8 @@ frame_timer_cb(void *data)
/* Phase 43: forward declaration — defined in the focus section below. */
static void wl_focus_set(WNativeWindow win, int revert_to, unsigned long timestamp);
/* Phase 50: forward declaration — defined in client section below. */
static int wl_client_get_pid(WNativeWindow win);
/* Phase 41: look up the view for a given synthetic WNativeWindow ID. */
static struct wl_toplevel_view *
@ -212,12 +214,13 @@ handle_toplevel_map(struct wl_listener *listener, void *data)
if (scr) {
WWindow *wwin = wManageWindow(scr, view->id);
if (wwin) {
int pid = wl_client_get_pid(view->id);
wwarning("wl_backend: wManageWindow succeeded id=0x%lx "
"class=%s name=%s geo=%dx%d",
"class=%s name=%s geo=%dx%d pid=%d",
view->id,
wwin->wm_class ? wwin->wm_class : "(none)",
wwin->wm_instance ? wwin->wm_instance : "(none)",
wwin->client.width, wwin->client.height);
wwin->client.width, wwin->client.height, pid);
/* Phase 43: focus the newly mapped toplevel. */
wl_focus_set(view->id, 0, 0);
}
@ -940,7 +943,17 @@ static int
wl_client_get_gnustep_attrs(WNativeWindow win, GNUstepWMAttributes **attr_out)
{ (void)win; *attr_out = NULL; return 0; }
static int wl_client_get_pid(WNativeWindow win) { (void)win; return 0; }
static int wl_client_get_pid(WNativeWindow win)
{
struct wl_toplevel_view *v = wl_find_view_by_id(win);
if (!v || !v->xdg_surface || !v->xdg_surface->resource)
return 0;
struct wl_client *client = wl_resource_get_client(v->xdg_surface->resource);
if (!client) return 0;
pid_t pid = 0; uid_t uid = 0; gid_t gid = 0;
wl_client_get_credentials(client, &pid, &uid, &gid);
return (int)pid;
}
static RImage *
wl_client_snapshot(WScreen *scr, WNativeWindow client_win, WNativeWindow frame_win)

View File

@ -1072,6 +1072,8 @@ static char *getCommandForWindow(Window win, int elements)
char **argv, *command = NULL;
int argc;
if (!dpy) return NULL; /* Wayland: no X11 WM_COMMAND property */
if (XGetCommand(dpy, win, &argv, &argc)) {
if (argc > 0 && argv != NULL) {
if (elements == 0)

View File

@ -1827,7 +1827,10 @@ void wWindowChangeWorkspace(WWindow *wwin, int workspace)
WApplication *wapp;
int unmap = 0;
if (workspace >= scr->workspace_count || workspace < 0 || workspace == wwin->frame->workspace)
if (workspace >= scr->workspace_count || workspace < 0)
return;
if (!wwin->frame) return; /* Wayland: frameless windows have no workspace slot */
if (workspace == wwin->frame->workspace)
return;
if (workspace != scr->current_workspace) {

View File

@ -32,6 +32,8 @@
# events so clients receive WM-initiated size changes (no external check)
# 15. (Phase 45) pointer_query returns 1 so wSetFocusTo fires from
# wManageWindow; wWindowFocus/Unfocus guarded on frame!=NULL
# 16. (Phase 50) client_get_pid returns real PID via wl_client_get_credentials;
# logged as pid= in wManageWindow succeeded line
#
# This test grows as wl_backend vtable slots are implemented.
#
@ -188,6 +190,12 @@ if command -v weston-simple-shm >/dev/null 2>&1; then
grep -q 'focus_set id=' /tmp/wl-smoke-stderr \
|| die "compositor did not log focus_set (keyboard focus not delivered)"
echo " focus check: keyboard focus delivered to mapped toplevel"
# -- 14. Phase 50: client PID retrieved via wl_client_get_credentials --
PID=$(grep -o 'pid=[0-9]*' /tmp/wl-smoke-stderr | head -1 | sed 's/pid=//')
[ -n "$PID" ] && [ "$PID" -gt 0 ] 2>/dev/null \
|| die "compositor did not log a valid pid= for managed toplevel"
echo " pid check: client PID=$PID retrieved via wl_client_get_credentials"
else
echo " client check: skipped (weston-simple-shm not installed)"
fi