[hackers] [tabbed][PATCH] Use PWD xprop to set workdir for spawned clients

From: Nikita Zlobin <nick87720z_AT_gmail.com>
Date: Thu, 11 Jun 2020 13:56:21 +0500

workdir could be got from active client via xprop, then set for spawned
client. Terminals can pass it with xprop -id ${WINDOWID} command from
hook, created for PWD change. Setting up hook depends on what shell is
used. For bash it's doable either via cd() function or PROMPT_COMMAND.

Example bash command:
> xprop -id "${WINDOWID}" -f PWD 8s -set "PWD" "${PWD}"

Rename gettextprop to gettextpropn, add proper gettextprop, for
unpredictable data length. Reading workdir may need unpredictable string
length. Just like with strcpy/strcpyn, variant expecting limited buffer
could end with 'n'. Well, it could be agettextprop, like asprintf, but
then what should match to sprintf...
---
 tabbed.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/tabbed.c b/tabbed.c
index d426c0d..90498d0 100644
--- a/tabbed.c
+++ b/tabbed.c
_AT_@ -49,7 +49,7 @@
 
 enum { ColFG, ColBG, ColLast };       /* color */
 enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen,
-       XEmbed, WMSelectTab, WMLast }; /* default atoms */
+       XEmbed, WMSelectTab, PWD, WMLast }; /* default atoms */
 
 typedef union {
 	int i;
_AT_@ -109,7 +109,8 @@ static char *getatom(int a);
 static int getclient(Window w);
 static XftColor getcolor(const char *colstr);
 static int getfirsttab(void);
-static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
+static char * gettextprop(Window w, Atom atom);
+static Bool gettextpropn(Window w, Atom atom, char *text, unsigned int size);
 static void initfont(const char *fontstr);
 static Bool isprotodel(int c);
 static void keypress(const XEvent *e);
_AT_@ -599,8 +600,34 @@ getfirsttab(void)
 	       ret;
 }
 
+char *
+gettextprop(Window w, Atom atom)
+{
+	char *text;
+	char **list = NULL;
+	int n;
+	XTextProperty name;
+
+	XGetTextProperty(dpy, w, &name, atom);
+	if (!name.nitems)
+		return NULL;
+
+	if (name.encoding == XA_STRING) {
+		text = ecalloc(1, strlen((char *)name.value) + 1);
+		strcpy(text, (char *)name.value);
+	} else if (Xutf8TextPropertyToTextList(dpy, &name, &list, &n) >= Success
+	           && n > 0 && *list) {
+		text = ecalloc(1, strlen(*list) + 1);
+		strcpy(text, *list);
+		XFreeStringList(list);
+	}
+	XFree(name.value);
+
+	return text;
+}
+
 Bool
-gettextprop(Window w, Atom atom, char *text, unsigned int size)
+gettextpropn(Window w, Atom atom, char *text, unsigned int size)
 {
 	char **list = NULL;
 	int n;
_AT_@ -995,6 +1022,7 @@ setup(void)
 	wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", False);
 	wmatom[WMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
 	wmatom[XEmbed] = XInternAtom(dpy, "_XEMBED", False);
+	wmatom[PWD] =  XInternAtom(dpy, "PWD", False);
 
 	/* init appearance */
 	wx = 0;
_AT_@ -1090,7 +1118,17 @@ sigchld(int unused)
 void
 spawn(const Arg *arg)
 {
+	char * pwd = NULL;
+
+	if (sel != -1)
+		pwd = gettextprop(clients[sel]->win, wmatom[PWD]);
+
 	if (fork() == 0) {
+		if (pwd) {
+			chdir(pwd);
+			free(pwd);
+		}
+
 		if(dpy)
 			close(ConnectionNumber(dpy));
 
_AT_@ -1107,6 +1145,7 @@ spawn(const Arg *arg)
 		perror(" failed");
 		exit(0);
 	}
+	free(pwd);
 }
 
 int
_AT_@ -1213,9 +1252,9 @@ updatenumlockmask(void)
 void
 updatetitle(int c)
 {
-	if (!gettextprop(clients[c]->win, wmatom[WMName], clients[c]->name,
+	if (!gettextpropn(clients[c]->win, wmatom[WMName], clients[c]->name,
 	    sizeof(clients[c]->name)))
-		gettextprop(clients[c]->win, XA_WM_NAME, clients[c]->name,
+		gettextpropn(clients[c]->win, XA_WM_NAME, clients[c]->name,
 		            sizeof(clients[c]->name));
 	if (sel == c)
 		xsettitle(win, clients[c]->name);
-- 
2.26.2
Received on Thu Jun 11 2020 - 10:56:21 CEST

This archive was generated by hypermail 2.3.0 : Thu Jun 11 2020 - 21:48:32 CEST