summaryrefslogtreecommitdiff
path: root/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwm.c')
-rw-r--r--dwm.c154
1 files changed, 112 insertions, 42 deletions
diff --git a/dwm.c b/dwm.c
index 1722089..6f26857 100644
--- a/dwm.c
+++ b/dwm.c
@@ -209,6 +209,7 @@ static void focusstack(const Arg *arg);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
+static pid_t getstatusbarpid();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -247,7 +248,6 @@ static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
#ifndef __OpenBSD__
-static int getdwmblockspid();
static void sigdwmblocks(const Arg *arg);
#endif
static void sighup(int unused);
@@ -298,8 +298,9 @@ static pid_t winpid(Window w);
static const char broken[] = "broken";
static char stext[1024];
static char rawstext[256];
-static int dwmblockssig;
-pid_t dwmblockspid = 0;
+static int statussig;
+static int statusw;
+static pid_t statuspid = -1;
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh; /* bar height */
@@ -546,6 +547,48 @@ unswallow(Client *c)
arrange(c->mon);
}
+
+static int
+status2d_width(const char *str)
+{
+ int i, w = 0;
+ short isCode = 0;
+ char *text, *p;
+
+ if (!str)
+ return 0;
+
+ /* make a writable copy because we insert '\0' */
+ if (!(text = strdup(str)))
+ die("strdup");
+ p = text;
+
+ i = -1;
+ while (text[++i]) {
+ if (text[i] == '^') {
+ if (!isCode) {
+ isCode = 1;
+ text[i] = '\0';
+ w += TEXTW(text) - lrpad;
+ text[i] = '^';
+
+ if (text[++i] == 'f')
+ w += atoi(text + ++i);
+ } else {
+ isCode = 0;
+ text = text + i + 1;
+ i = -1;
+ }
+ }
+ }
+
+ if (!isCode)
+ w += TEXTW(text) - lrpad;
+
+ free(p);
+ return w;
+}
+
void
buttonpress(XEvent *e)
{
@@ -556,7 +599,6 @@ buttonpress(XEvent *e)
XButtonPressedEvent *ev = &e->xbutton;
click = ClkRootWin;
- /* focus monitor if necessary */
if ((m = wintomon(ev->window)) && m != selmon) {
unfocus(selmon->sel, 1);
selmon = m;
@@ -567,7 +609,6 @@ buttonpress(XEvent *e)
for (c = m->clients; c; c = c->next)
occ |= c->tags == 255 ? 0 : c->tags;
do {
- /* do not reserve space for vacant tags */
if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i))
continue;
x += TEXTW(tags[i]);
@@ -577,23 +618,26 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
click = ClkLtSymbol;
- else if (ev->x > (x = selmon->ww - (int)TEXTW(stext) + lrpad)) {
+ else if (ev->x > selmon->ww - statusw) {
+ x = selmon->ww - statusw;
click = ClkStatusText;
+ char *text, *s, ch;
+ statussig = 0;
+
+ for (text = s = rawstext; *s && x <= ev->x; s++) {
+ if ((unsigned char)(*s) < ' ') {
+ ch = *s;
+ *s = '\0';
- char *text = rawstext;
- int i = -1;
- char ch;
- dwmblockssig = 0;
- while (text[++i]) {
- if ((unsigned char)text[i] < ' ') {
- ch = text[i];
- text[i] = '\0';
- x += TEXTW(text) - lrpad;
- text[i] = ch;
- text += i+1;
- i = -1;
- if (x >= ev->x) break;
- dwmblockssig = ch;
+ x += status2d_width(text);
+
+ *s = ch;
+ text = s + 1;
+
+ if (x >= ev->x)
+ break;
+
+ statussig = ch;
}
}
} else
@@ -870,7 +914,7 @@ dirtomon(int dir)
int
drawstatusbar(Monitor *m, int bh, char* stext) {
- int ret, i, w, x, len;
+ int ret, i, j, w, x, len;
short isCode = 0;
char *text;
char *p;
@@ -879,7 +923,12 @@ drawstatusbar(Monitor *m, int bh, char* stext) {
if (!(text = (char*) malloc(sizeof(char)*len)))
die("malloc");
p = text;
- memcpy(text, stext, len);
+
+ i = -1, j = 0;
+ while (stext[++i])
+ if ((unsigned char)stext[i] >= ' ')
+ text[j++] = stext[i];
+ text[j] = '\0';
/* compute width of the status text */
w = 0;
@@ -990,7 +1039,7 @@ drawbar(Monitor *m)
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
- tw = m->ww - drawstatusbar(m, bh, stext);
+ tw = statusw = m->ww - drawstatusbar(m, bh, stext);
}
for (c = m->clients; c; c = c->next) {
@@ -1150,17 +1199,35 @@ getatomprop(Client *c, Atom prop)
return atom;
}
+
#ifndef __OpenBSD__
-int
-getdwmblockspid()
-{
- char buf[16];
- FILE *fp = popen("pidof -s dwmblocks", "r");
- fgets(buf, sizeof(buf), fp);
- pid_t pid = strtoul(buf, NULL, 10);
- pclose(fp);
- dwmblockspid = pid;
- return pid != 0 ? 0 : -1;
+pid_t
+getstatusbarpid(void)
+{
+ char buf[32], *str = buf, *c;
+ FILE *fp;
+
+ if (statuspid > 0) {
+ snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid);
+ if ((fp = fopen(buf, "r"))) {
+ fgets(buf, sizeof(buf), fp);
+ while ((c = strchr(str, '/')))
+ str = c + 1;
+ fclose(fp);
+ if (!strcmp(str, STATUSBAR))
+ return statuspid;
+ }
+ }
+ if (!(fp = popen("pidof -s " STATUSBAR, "r")))
+ return -1;
+ if (!fgets(buf, sizeof(buf), fp)) {
+ pclose(fp);
+ return -1;
+ }
+ pclose(fp);
+
+ statuspid = strtoul(buf, NULL, 10);
+ return statuspid ? statuspid : -1;
}
#endif
@@ -2041,16 +2108,19 @@ void
sigdwmblocks(const Arg *arg)
{
union sigval sv;
- sv.sival_int = 0 | (dwmblockssig << 8) | arg->i;
- if (!dwmblockspid)
- if (getdwmblockspid() == -1)
- return;
+ pid_t pid;
- if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) {
- if (errno == ESRCH) {
- if (!getdwmblockspid())
- sigqueue(dwmblockspid, SIGUSR1, sv);
- }
+ sv.sival_int = 0 | (statussig << 8) | arg->i;
+
+ pid = getstatusbarpid();
+ if (pid == -1)
+ return;
+
+ if (sigqueue(pid, SIGUSR1, sv) == -1 && errno == ESRCH) {
+ statuspid = -1; /* cached pid is stale */
+ pid = getstatusbarpid();
+ if (pid != -1)
+ sigqueue(pid, SIGUSR1, sv);
}
}
#endif