aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dmenu/config.mk2
-rw-r--r--dmenu/dmenu.13
-rw-r--r--dmenu/dmenu.c164
-rw-r--r--dmenu/patches/dmenu-qalc-5.2.diff259
-rw-r--r--dwm/config.def.h5
-rw-r--r--dwm/config.h5
6 files changed, 405 insertions, 33 deletions
diff --git a/dmenu/config.mk b/dmenu/config.mk
index fa2b4fc..39f8bd4 100644
--- a/dmenu/config.mk
+++ b/dmenu/config.mk
@@ -24,7 +24,7 @@ INCS = -I$(X11INC) -I$(FREETYPEINC)
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lXrender
# flags
-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
+CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
LDFLAGS = $(LIBS)
diff --git a/dmenu/dmenu.1 b/dmenu/dmenu.1
index 57ea184..2bf9c77 100644
--- a/dmenu/dmenu.1
+++ b/dmenu/dmenu.1
@@ -45,6 +45,9 @@ dmenu appears at the bottom of the screen.
.B \-c
dmenu appears centered on the screen.
.TP
+.B \-C
+dmenu becomes a calculator.
+.TP
.B \-f
dmenu grabs the keyboard before reading stdin if not reading from a tty. This
is faster, but will lock up X until stdin reaches end\-of\-file.
diff --git a/dmenu/dmenu.c b/dmenu/dmenu.c
index 3293a88..3f462d9 100644
--- a/dmenu/dmenu.c
+++ b/dmenu/dmenu.c
@@ -1,11 +1,16 @@
/* See LICENSE file for copyright and license details. */
#include <X11/X.h>
#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
#include <locale.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <sys/prctl.h>
+#include <sys/select.h>
#include <time.h>
#include <unistd.h>
@@ -39,6 +44,12 @@ struct item {
int out;
};
+static struct {
+ pid_t pid;
+ int enable, in[2], out[2];
+ char buf[256];
+} qalc;
+
static char text[BUFSIZ] = "";
static char *embed;
static int bh, mw, mh;
@@ -231,7 +242,72 @@ static void grabkeyboard(void) {
die("cannot grab keyboard");
}
+static void init_qalc(void) {
+ pipe(qalc.in);
+ pipe2(qalc.out, O_NONBLOCK);
+ qalc.pid = fork();
+ if (qalc.pid == -1)
+ die("failed to fork for qalc");
+ if (qalc.pid == 0) {
+ dup2(qalc.in[0], STDIN_FILENO);
+ dup2(qalc.out[1], STDOUT_FILENO);
+ close(qalc.in[1]);
+ close(qalc.out[0]);
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+ execl("/usr/bin/qalc", "qalc", "-c0", "-t", NULL);
+ die("execl qalc failed");
+ } else { // parent
+ close(qalc.in[0]);
+ close(qalc.out[1]);
+ items = malloc(sizeof(struct item) * 2);
+ items[0].text = malloc(LENGTH(qalc.buf));
+ strcpy(items[0].text, "no result");
+ items[1].out = 0;
+ items[1].text = NULL;
+ }
+}
+
+static void recv_qalc(void) {
+ ssize_t r = read(qalc.out[0], qalc.buf, LENGTH(qalc.buf));
+
+ if (r < 0)
+ die("error reading qalc.out");
+
+ if (qalc.buf[0] == '\n') {
+ int i;
+ for (i = 3; i < LENGTH(qalc.buf) && qalc.buf[i] != '\n'; i++)
+ items[0].text[i - 3] = qalc.buf[i];
+ items[0].text[i - 3] = 0;
+ if (r != LENGTH(qalc.buf))
+ return;
+ }
+
+ while (read(qalc.out[0], qalc.buf, LENGTH(qalc.buf)) != -1)
+ ; // empty the pipe
+ if (errno != EAGAIN && errno != EWOULDBLOCK)
+ die("error emptying qalc.out");
+}
+
+static void send_qalc(void) {
+ int s = strlen(text);
+ text[s] = '\n';
+ write(qalc.in[1], text, s + 1);
+ text[s] = 0;
+}
+
+static void match_qalc(void) {
+ matches = matchend = NULL;
+ appenditem(items, &matches, &matchend);
+ curr = sel = matches;
+ calcoffsets();
+}
+
static void match(void) {
+ if (qalc.enable) {
+ match_qalc();
+ return;
+ }
+
static char **tokv = NULL;
static int tokn = 0;
@@ -555,6 +631,9 @@ static void keypress(XKeyEvent *ev) {
break;
}
+ if (qalc.enable)
+ send_qalc();
+
draw:
drawmenu();
}
@@ -603,35 +682,50 @@ static void readstdin(void) {
static void run(void) {
XEvent ev;
- while (!XNextEvent(dpy, &ev)) {
- if (XFilterEvent(&ev, win))
- continue;
- switch (ev.type) {
- case DestroyNotify:
- if (ev.xdestroywindow.window != win)
- break;
- cleanup();
- exit(1);
- case Expose:
- if (ev.xexpose.count == 0)
- drw_map(drw, win, 0, 0, mw, mh);
- break;
- case FocusIn:
- /* regrab focus from parent window */
- if (ev.xfocus.window != win)
- grabfocus();
- break;
- case KeyPress:
- keypress(&ev.xkey);
- break;
- case SelectionNotify:
- if (ev.xselection.property == utf8)
- paste();
- break;
- case VisibilityNotify:
- if (ev.xvisibility.state != VisibilityUnobscured)
- XRaiseWindow(dpy, win);
- break;
+ fd_set rfds;
+ int xfd = ConnectionNumber(dpy);
+
+ for (;;) {
+ FD_ZERO(&rfds);
+ FD_SET(xfd, &rfds);
+ FD_SET(qalc.out[0], &rfds);
+
+ if (select(MAX(xfd, qalc.out[0]) + 1, &rfds, NULL, NULL, NULL) > 0) {
+ if (qalc.enable && FD_ISSET(qalc.out[0], &rfds)) {
+ recv_qalc();
+ drawmenu();
+ }
+ while (XPending(dpy) && !XNextEvent(dpy, &ev)) {
+ if (XFilterEvent(&ev, win))
+ continue;
+ switch (ev.type) {
+ case DestroyNotify:
+ if (ev.xdestroywindow.window != win)
+ break;
+ cleanup();
+ exit(1);
+ case Expose:
+ if (ev.xexpose.count == 0)
+ drw_map(drw, win, 0, 0, mw, mh);
+ break;
+ case FocusIn:
+ /* regrab focus from parent window */
+ if (ev.xfocus.window != win)
+ grabfocus();
+ break;
+ case KeyPress:
+ keypress(&ev.xkey);
+ break;
+ case SelectionNotify:
+ if (ev.xselection.property == utf8)
+ paste();
+ break;
+ case VisibilityNotify:
+ if (ev.xvisibility.state != VisibilityUnobscured)
+ XRaiseWindow(dpy, win);
+ break;
+ }
+ }
}
}
}
@@ -682,7 +776,8 @@ static void setup(void) {
i = j;
}
}
- /* no focused window is on screen, so use pointer location instead */
+ /* no focused window is on screen, so use pointer location instead
+ */
if (mon < 0 && !area &&
XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
for (i = 0; i < n; i++)
@@ -755,7 +850,7 @@ static void setup(void) {
}
static void usage(void) {
- die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ die("usage: dmenu [-bCfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
" [-nb color] [-nf color] [-sb color] [-sf color] [-w "
"windowid]");
}
@@ -771,6 +866,8 @@ int main(int argc, char *argv[]) {
exit(0);
} else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
topbar = 0;
+ else if (!strcmp(argv[i], "-C")) /* grabs keyboard before reading stdin */
+ qalc.enable = 1;
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
fast = 1;
else if (!strcmp(argv[i], "-c")) /* centers dmenu on screen */
@@ -829,7 +926,10 @@ int main(int argc, char *argv[]) {
die("pledge");
#endif
- if (fast && !isatty(0)) {
+ if (qalc.enable) {
+ init_qalc();
+ grabkeyboard();
+ } else if (fast && !isatty(0)) {
grabkeyboard();
readstdin();
} else {
diff --git a/dmenu/patches/dmenu-qalc-5.2.diff b/dmenu/patches/dmenu-qalc-5.2.diff
new file mode 100644
index 0000000..37653f8
--- /dev/null
+++ b/dmenu/patches/dmenu-qalc-5.2.diff
@@ -0,0 +1,259 @@
+diff -up dmenu-5.2/config.mk dmenu-qalc-5.2/config.mk
+--- dmenu-5.2/config.mk 2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/config.mk 2023-10-27 19:29:48.197693355 -0400
+@@ -24,7 +24,7 @@ INCS = -I$(X11INC) -I$(FREETYPEINC)
+ LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
+
+ # flags
+-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
++CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
+ CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
+ LDFLAGS = $(LIBS)
+
+diff -up dmenu-5.2/dmenu.1 dmenu-qalc-5.2/dmenu.1
+--- dmenu-5.2/dmenu.1 2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/dmenu.1 2023-10-27 19:28:48.676578875 -0400
+@@ -40,6 +40,9 @@ which lists programs in the user's $PATH
+ .B \-b
+ dmenu appears at the bottom of the screen.
+ .TP
++.B \-C
++dmenu becomes a calculator.
++.TP
+ .B \-f
+ dmenu grabs the keyboard before reading stdin if not reading from a tty. This
+ is faster, but will lock up X until stdin reaches end\-of\-file.
+diff -up dmenu-5.2/dmenu.c dmenu-qalc-5.2/dmenu.c
+--- dmenu-5.2/dmenu.c 2022-10-04 13:36:58.000000000 -0400
++++ dmenu-qalc-5.2/dmenu.c 2023-10-27 20:00:21.438467597 -0400
+@@ -7,6 +7,11 @@
+ #include <strings.h>
+ #include <time.h>
+ #include <unistd.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <sys/prctl.h>
++#include <sys/select.h>
+
+ #include <X11/Xlib.h>
+ #include <X11/Xatom.h>
+@@ -34,6 +39,12 @@ struct item {
+ int out;
+ };
+
++static struct {
++ pid_t pid;
++ int enable, in[2], out[2];
++ char buf[256];
++} qalc;
++
+ static char text[BUFSIZ] = "";
+ static char *embed;
+ static int bh, mw, mh;
+@@ -228,8 +239,81 @@ grabkeyboard(void)
+ }
+
+ static void
++init_qalc(void)
++{
++ pipe(qalc.in);
++ pipe2(qalc.out, O_NONBLOCK);
++ qalc.pid = fork();
++ if (qalc.pid == -1)
++ die("failed to fork for qalc");
++ if (qalc.pid == 0) {
++ dup2(qalc.in[0], STDIN_FILENO);
++ dup2(qalc.out[1], STDOUT_FILENO);
++ close(qalc.in[1]);
++ close(qalc.out[0]);
++ prctl(PR_SET_PDEATHSIG, SIGTERM);
++ execl("/usr/bin/qalc", "qalc", "-c0", "-t", NULL);
++ die ("execl qalc failed");
++ } else { // parent
++ close(qalc.in[0]);
++ close(qalc.out[1]);
++ items = malloc(sizeof(struct item)*2);
++ items[0].text = malloc(LENGTH(qalc.buf));
++ strcpy(items[0].text, "no result");
++ items[1].out = 0;
++ items[1].text = NULL;
++ }
++}
++
++static void
++recv_qalc(void)
++{
++ ssize_t r = read(qalc.out[0], qalc.buf, LENGTH(qalc.buf));
++
++ if (r < 0)
++ die("error reading qalc.out");
++
++ if (qalc.buf[0] == '\n') {
++ int i;
++ for (i = 3; i < LENGTH(qalc.buf) && qalc.buf[i] != '\n'; ++i)
++ items[0].text[i-3] = qalc.buf[i];
++ items[0].text[i-3] = 0;
++ if (r != LENGTH(qalc.buf))
++ return;
++ }
++
++ while (read(qalc.out[0], qalc.buf, LENGTH(qalc.buf)) != -1)
++ ; // empty the pipe
++ if (errno != EAGAIN && errno != EWOULDBLOCK)
++ die("error emptying qalc.out");
++}
++
++static void
++send_qalc(void)
++{
++ int s = strlen(text);
++ text[s] = '\n';
++ write(qalc.in[1], text, s+1);
++ text[s] = 0;
++}
++
++static void
++match_qalc(void)
++{
++ matches = matchend = NULL;
++ appenditem(items, &matches, &matchend);
++ curr = sel = matches;
++ calcoffsets();
++}
++
++static void
+ match(void)
+ {
++ if (qalc.enable) {
++ match_qalc();
++ return;
++ }
++
+ static char **tokv = NULL;
+ static int tokn = 0;
+
+@@ -524,6 +608,9 @@ insert:
+ break;
+ }
+
++ if (qalc.enable)
++ send_qalc();
++
+ draw:
+ drawmenu();
+ }
+@@ -573,37 +660,52 @@ run(void)
+ {
+ XEvent ev;
+
+- while (!XNextEvent(dpy, &ev)) {
+- if (XFilterEvent(&ev, win))
+- continue;
+- switch(ev.type) {
+- case DestroyNotify:
+- if (ev.xdestroywindow.window != win)
+- break;
+- cleanup();
+- exit(1);
+- case Expose:
+- if (ev.xexpose.count == 0)
+- drw_map(drw, win, 0, 0, mw, mh);
+- break;
+- case FocusIn:
+- /* regrab focus from parent window */
+- if (ev.xfocus.window != win)
+- grabfocus();
+- break;
+- case KeyPress:
+- keypress(&ev.xkey);
+- break;
+- case SelectionNotify:
+- if (ev.xselection.property == utf8)
+- paste();
+- break;
+- case VisibilityNotify:
+- if (ev.xvisibility.state != VisibilityUnobscured)
+- XRaiseWindow(dpy, win);
+- break;
+- }
+- }
++ fd_set rfds;
++ int xfd = ConnectionNumber(dpy);
++
++ for (;;) {
++ FD_ZERO(&rfds);
++ FD_SET(xfd, &rfds);
++ FD_SET(qalc.out[0], &rfds);
++
++ if (select(MAX(xfd, qalc.out[0])+1, &rfds, NULL, NULL, NULL) > 0) {
++ if (qalc.enable && FD_ISSET(qalc.out[0], &rfds)) {
++ recv_qalc();
++ drawmenu();
++ }
++ while (XPending(dpy) && !XNextEvent(dpy, &ev)) {
++ if (XFilterEvent(&ev, win))
++ continue;
++ switch(ev.type) {
++ case DestroyNotify:
++ if (ev.xdestroywindow.window != win)
++ break;
++ cleanup();
++ exit(1);
++ case Expose:
++ if (ev.xexpose.count == 0)
++ drw_map(drw, win, 0, 0, mw, mh);
++ break;
++ case FocusIn:
++ /* regrab focus from parent window */
++ if (ev.xfocus.window != win)
++ grabfocus();
++ break;
++ case KeyPress:
++ keypress(&ev.xkey);
++ break;
++ case SelectionNotify:
++ if (ev.xselection.property == utf8)
++ paste();
++ break;
++ case VisibilityNotify:
++ if (ev.xvisibility.state != VisibilityUnobscured)
++ XRaiseWindow(dpy, win);
++ break;
++ }
++ }
++ }
++ }
+ }
+
+ static void
+@@ -710,7 +812,7 @@ setup(void)
+ static void
+ usage(void)
+ {
+- die("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
++ die("usage: dmenu [-bCfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
+ }
+
+@@ -727,6 +829,8 @@ main(int argc, char *argv[])
+ exit(0);
+ } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
+ topbar = 0;
++ else if (!strcmp(argv[i], "-C")) /* grabs keyboard before reading stdin */
++ qalc.enable = 1;
+ else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
+ fast = 1;
+ else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
+@@ -777,7 +881,10 @@ main(int argc, char *argv[])
+ die("pledge");
+ #endif
+
+- if (fast && !isatty(0)) {
++ if (qalc.enable) {
++ init_qalc();
++ grabkeyboard();
++ } else if (fast && !isatty(0)) {
+ grabkeyboard();
+ readstdin();
+ } else {
diff --git a/dwm/config.def.h b/dwm/config.def.h
index 31a82aa..abb5b51 100644
--- a/dwm/config.def.h
+++ b/dwm/config.def.h
@@ -88,6 +88,10 @@ static const char *nextcmd[] = {"adb", "shell", "input",
"keyevent", "87", NULL};
static const char *previouscmd[] = {"adb", "shell", "input",
"keyevent", "88", NULL};
+static const char *qalccmd[] = {
+ "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb",
+ col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf",
+ col_gray4, "-C", "-l", "1", NULL};
static const Key keys[] = {
/* modifier key function argument */
@@ -126,6 +130,7 @@ static const Key keys[] = {
{MODKEY | ShiftMask, XK_n, spawn, {.v = nextcmd}},
{MODKEY | ShiftMask, XK_p, spawn, {.v = previouscmd}},
{MODKEY, XK_s, spawn, {.v = adbscreencmd}},
+ {MODKEY, XK_c, spawn, {.v = qalccmd}},
};
/* button definitions */
diff --git a/dwm/config.h b/dwm/config.h
index 31a82aa..abb5b51 100644
--- a/dwm/config.h
+++ b/dwm/config.h
@@ -88,6 +88,10 @@ static const char *nextcmd[] = {"adb", "shell", "input",
"keyevent", "87", NULL};
static const char *previouscmd[] = {"adb", "shell", "input",
"keyevent", "88", NULL};
+static const char *qalccmd[] = {
+ "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb",
+ col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf",
+ col_gray4, "-C", "-l", "1", NULL};
static const Key keys[] = {
/* modifier key function argument */
@@ -126,6 +130,7 @@ static const Key keys[] = {
{MODKEY | ShiftMask, XK_n, spawn, {.v = nextcmd}},
{MODKEY | ShiftMask, XK_p, spawn, {.v = previouscmd}},
{MODKEY, XK_s, spawn, {.v = adbscreencmd}},
+ {MODKEY, XK_c, spawn, {.v = qalccmd}},
};
/* button definitions */