master hovercats/oakiss / pkg / st / patch / 0003-Add-support-for-plumbing-via-right-click.patch
  1From 85a6bb6ba81de493c0ceb9a8d4c2f78eb5d1567f Mon Sep 17 00:00:00 2001
  2From: Michael Forney <mforney@mforney.org>
  3Date: Wed, 2 Dec 2020 17:54:35 -0800
  4Subject: [PATCH] Add support for plumbing via right click
  5
  6---
  7 config.def.h |  5 ++++
  8 st.c         | 79 ++++++++++++++++++++++++++++++++++++++++++++--------
  9 2 files changed, 72 insertions(+), 12 deletions(-)
 10
 11diff --git a/config.def.h b/config.def.h
 12index 49ca50b..a63d2be 100644
 13--- a/config.def.h
 14+++ b/config.def.h
 15@@ -460,3 +460,8 @@ static char ascii_printable[] =
 16 	"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 17 	"`abcdefghijklmnopqrstuvwxyz{|}~";
 18 
 19+/*
 20+ * plumb_cmd is run on mouse button 3 click, with first NULL set to
 21+ * current selection and with cwd set to the cwd of the active shell
 22+ */
 23+static char *plumb_cmd[] = {"plumb", NULL, NULL};
 24diff --git a/st.c b/st.c
 25index 20a3c3c..914fdd5 100644
 26--- a/st.c
 27+++ b/st.c
 28@@ -44,6 +44,9 @@ char *argv0;
 29 #elif defined(__FreeBSD__) || defined(__DragonFly__)
 30  #include <libutil.h>
 31 #endif
 32+#if defined(__OpenBSD__)
 33+ #include <sys/sysctl.h>
 34+#endif
 35 
 36 
 37 /* Arbitrary sizes */
 38@@ -558,6 +561,8 @@ static void *xmalloc(size_t);
 39 static void *xrealloc(void *, size_t);
 40 static char *xstrdup(char *);
 41 
 42+static int subprocwd(char *, size_t);
 43+
 44 static void usage(void);
 45 
 46 static struct wl_registry_listener reglistener = { regglobal, regglobalremove };
 47@@ -579,6 +584,7 @@ static struct wl_data_source_listener datasrclistener =
 48 	{ datasrctarget, datasrcsend, datasrccancelled };
 49 
 50 /* Globals */
 51+static int plumbsel;
 52 static DC dc;
 53 static Wayland wl;
 54 static WLD wld;
 55@@ -763,6 +769,21 @@ utf8validate(Rune *u, size_t i)
 56 	return i;
 57 }
 58 
 59+int
 60+subprocwd(char *path, size_t len)
 61+{
 62+#if defined(__linux__)
 63+	if (snprintf(path, len, "/proc/%d/cwd", pid) < 0)
 64+		return -1;
 65+	return 0;
 66+#elif defined(__OpenBSD__)
 67+	int name[3] = {CTL_KERN, KERN_PROC_CWD, pid};
 68+	if (sysctl(name, 3, path, &len, 0, 0) == -1)
 69+		return -1;
 70+	return 0;
 71+#endif
 72+}
 73+
 74 void
 75 selinit(void)
 76 {
 77@@ -1165,6 +1186,29 @@ wlsetsel(char *str, uint32_t serial)
 78 	wl_data_device_set_selection(wl.datadev, sel.source, serial);
 79 }
 80 
 81+void
 82+plumbinit(void)
 83+{
 84+	for (plumbsel = 0; plumb_cmd[plumbsel]; ++plumbsel)
 85+		;
 86+}
 87+
 88+void
 89+plumb(char *sel)
 90+{
 91+	char cwd[PATH_MAX];
 92+
 93+	if (!sel || subprocwd(cwd, sizeof(cwd)) != 0)
 94+		return;
 95+	plumb_cmd[plumbsel] = sel;
 96+
 97+	if (fork() == 0) {
 98+		if (chdir(cwd) == 0)
 99+			execvp(plumb_cmd[0], plumb_cmd);
100+		_exit(1);
101+	}
102+}
103+
104 void
105 die(const char *errstr, ...)
106 {
107@@ -1227,15 +1271,18 @@ sigchld(int a)
108 	int stat;
109 	pid_t p;
110 
111-	if ((p = waitpid(pid, &stat, WNOHANG)) < 0)
112-		die("Waiting for pid %hd failed: %s\n", pid, strerror(errno));
113-
114-	if (pid != p)
115-		return;
116-
117-	if (!WIFEXITED(stat) || WEXITSTATUS(stat))
118-		die("child finished with error '%d'\n", stat);
119-	exit(0);
120+	for (;;) {
121+		p = waitpid(-1, &stat, WNOHANG);
122+		if (p == 0)
123+			break;
124+		if (p < 0)
125+			die("waitpid: %s\n", strerror(errno));
126+		if (pid == p) {
127+			if (!WIFEXITED(stat) || WEXITSTATUS(stat))
128+				die("child finished with error '%d'\n", stat);
129+			exit(0);
130+		}
131+	}
132 }
133 
134 
135@@ -4224,16 +4271,23 @@ ptrbutton(void * data, struct wl_pointer * pointer, uint32_t serial,
136 
137 	switch (state) {
138 	case WL_POINTER_BUTTON_STATE_RELEASED:
139-		if (button == BTN_MIDDLE) {
140+		switch (button) {
141+		case BTN_MIDDLE:
142 			selpaste(NULL);
143-		} else if (button == BTN_LEFT) {
144+			break;
145+		case BTN_LEFT:
146 			if (sel.mode == SEL_READY) {
147 				getbuttoninfo();
148 				selcopy(serial);
149-			} else
150+			} else {
151 				selclear();
152+			}
153 			sel.mode = SEL_IDLE;
154 			tsetdirt(sel.nb.y, sel.ne.y);
155+			break;
156+		case BTN_RIGHT:
157+			plumb(sel.primary);
158+			break;
159 		}
160 		break;
161 
162@@ -4557,6 +4611,7 @@ main(int argc, char *argv[])
163 	} ARGEND;
164 
165 run:
166+	plumbinit();
167 	if (argc > 0) {
168 		/* eat all remaining arguments */
169 		opt_cmd = argv;
170-- 
1712.37.3
172