From 83b8dc03f5ea40f472e90d452671f8e55faf2c4c Mon Sep 17 00:00:00 2001
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
Date: Sun, 9 Feb 2025 23:27:48 +0100
Subject: [PATCH] spawninfo: spawn but pass client info via stdin

---
 client.h | 12 ++++++++++++
 dwl.c    | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/client.h b/client.h
index 42f225f..bc9cad2 100644
--- a/client.h
+++ b/client.h
@@ -131,6 +131,18 @@ client_get_appid(Client *c)
 	return c->surface.xdg->toplevel->app_id;
 }
 
+static inline int
+client_get_pid(Client *c)
+{
+	pid_t pid;
+#ifdef XWAYLAND
+	if (client_is_x11(c))
+		return c->surface.xwayland->pid;
+#endif
+	wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
+	return pid;
+}
+
 static inline void
 client_get_clip(Client *c, struct wlr_box *clip)
 {
diff --git a/dwl.c b/dwl.c
index def2562..859514c 100644
--- a/dwl.c
+++ b/dwl.c
@@ -141,6 +141,7 @@ typedef struct {
 	uint32_t tags;
 	int isfloating, isurgent, isfullscreen;
 	uint32_t resize; /* configure serial of a pending resize */
+	pid_t pid;
 } Client;
 
 typedef struct {
@@ -334,6 +335,7 @@ static void setpsel(struct wl_listener *listener, void *data);
 static void setsel(struct wl_listener *listener, void *data);
 static void setup(void);
 static void spawn(const Arg *arg);
+static void spawninfo(const Arg *arg);
 static void startdrag(struct wl_listener *listener, void *data);
 static void tag(const Arg *arg);
 static void tagmon(const Arg *arg);
@@ -466,6 +468,8 @@ applyrules(Client *c)
 	if (!(title = client_get_title(c)))
 		title = broken;
 
+	c->pid = client_get_pid(c);
+
 	for (r = rules; r < END(rules); r++) {
 		if ((!r->title || strstr(title, r->title))
 				&& (!r->id || strstr(appid, r->id))) {
@@ -2658,6 +2662,44 @@ spawn(const Arg *arg)
 	}
 }
 
+void
+spawninfo(const Arg *arg)
+{
+	int fd[2];
+	pid_t pid;
+	const char *title, *appid;
+	Client *c = focustop(selmon);
+
+	if (pipe(fd) == -1)
+		return;
+	if ((pid = fork()) == -1)
+		return;
+	if (pid == 0) {
+		dup2(fd[0], STDIN_FILENO);
+		close(fd[0]);
+		close(fd[1]);
+		dup2(STDERR_FILENO, STDOUT_FILENO);
+		setsid();
+		execvp(((char **)arg->v)[0], (char **)arg->v);
+		die("dwl: execvp %s failed:", ((char **)arg->v)[0]);
+	}
+
+	close(fd[0]);
+
+	if (c) {
+		if (!(title = client_get_title(c)))
+			title = "";
+		if (!(appid = client_get_appid(c)))
+			appid = "";
+		dprintf(fd[1], "%d\n%s\n%s\n%"PRIu32"\n%d,%d %dx%d\n", c->pid,
+				title, appid, c->tags,
+				c->geom.x + c->bw, c->geom.y + c->bw,
+				c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
+	}
+
+	close(fd[1]);
+}
+
 void
 startdrag(struct wl_listener *listener, void *data)
 {
-- 
2.48.1

