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 eafe28a..af207c8 100644
--- a/tabbed.c
+++ b/tabbed.c
@@ -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;
@@ -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);
@@ -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 (XmbTextPropertyToTextList(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;
@@ -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;
@@ -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));
 
@@ -1107,6 +1145,7 @@ spawn(const Arg *arg)
                perror(" failed");
                exit(0);
        }
+       free(pwd);
 }
 
 int
@@ -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


Reply via email to