Integrate dmenu as a preloaded zero-lag DWM plugin (dmenu.so)

This commit is contained in:
Luxferre
2026-10-21 17:37:51 +03:00
parent 7da7352a6d
commit d240f25131
34 changed files with 2835 additions and 1232 deletions
+151 -1
View File
@@ -1,15 +1,131 @@
#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "../sxmo-dwm/dwm_plugin.h"
static int write_all(int fd, const void *buf, size_t len) {
const char *p = (const char *)buf;
while (len > 0) {
ssize_t n = write(fd, p, len);
if (n < 0) {
if (errno == EINTR)
continue;
return -1;
}
p += n;
len -= (size_t)n;
}
return 0;
}
static int is_dmenu_builtin_arg(const char *arg) {
if (!arg || !arg[0])
return 0;
return strcmp(arg, "sys") == 0 ||
strcmp(arg, "ctx") == 0 ||
strcmp(arg, "applications") == 0 ||
strcmp(arg, "scripts") == 0 ||
strcmp(arg, "modem") == 0 ||
strcmp(arg, "config") == 0 ||
strcmp(arg, "power") == 0 ||
strcmp(arg, "st") == 0 ||
strcmp(arg, "nano") == 0 ||
strcmp(arg, "sthotkeys") == 0;
}
static int try_dmenu_socket_client(int sub_argc, char **sub_argv, int *exit_code_out) {
FILE *pf = fopen("/tmp/dwm_plugin_dmenu.pid", "r");
if (!pf)
return 0;
int pid = 0;
int ok = (fscanf(pf, "%d", &pid) == 1 && pid > 1 && kill((pid_t)pid, 0) == 0);
fclose(pf);
if (!ok)
return 0;
int sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (sock < 0)
return 0;
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, "/tmp/dwm_plugin_dmenu.sock", sizeof(addr.sun_path) - 1);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(sock);
return 0;
}
uint32_t c_argc = (uint32_t)sub_argc;
if (write_all(sock, &c_argc, sizeof(c_argc)) != 0) {
close(sock);
return 0;
}
for (int i = 0; i < sub_argc; i++) {
const char *s = sub_argv[i] ? sub_argv[i] : "";
uint32_t slen = (uint32_t)strlen(s);
if (write_all(sock, &slen, sizeof(slen)) != 0 ||
(slen > 0 && write_all(sock, s, slen) != 0)) {
close(sock);
return 0;
}
}
char buf[4096];
for (;;) {
ssize_t n = read(STDIN_FILENO, buf, sizeof(buf));
if (n < 0) {
if (errno == EINTR)
continue;
break;
}
if (n == 0)
break;
if (write_all(sock, buf, (size_t)n) != 0) {
close(sock);
return 0;
}
}
shutdown(sock, SHUT_WR);
uint8_t status_byte = 1;
ssize_t first = read(sock, &status_byte, 1);
if (first <= 0) {
close(sock);
*exit_code_out = 1;
return 1;
}
for (;;) {
ssize_t n = read(sock, buf, sizeof(buf));
if (n < 0) {
if (errno == EINTR)
continue;
break;
}
if (n == 0)
break;
(void)write_all(STDOUT_FILENO, buf, (size_t)n);
}
close(sock);
*exit_code_out = (int)status_byte;
return 1;
}
static int try_send_plugin_fifo(const char *plugin_name, int sub_argc, char **sub_argv) {
if (sub_argc >= 2 && sub_argv[1] && strcmp(sub_argv[1], "--preload") == 0) {
return 0;
@@ -38,6 +154,9 @@ static int try_send_plugin_fifo(const char *plugin_name, int sub_argc, char **su
int len = 0;
if (strcmp(plugin_name, "xdrawer") == 0) {
len = snprintf(cmd, sizeof(cmd), "TOGGLE\n");
} else if (strcmp(plugin_name, "dmenu") == 0 && sub_argc >= 2 && sub_argv[1] &&
strcmp(sub_argv[1], "close") == 0) {
len = snprintf(cmd, sizeof(cmd), "CLOSE\n");
} else if (sub_argc >= 2 && sub_argv[1] && strcmp(sub_argv[1], "newcontact") == 0) {
const char *num = (sub_argc >= 3 && sub_argv[2]) ? sub_argv[2] : "";
len = snprintf(cmd, sizeof(cmd), "OPEN new:%s\n", num);
@@ -69,6 +188,9 @@ static const char *const kPluginDirs[] = {
static const char *resolve_plugin_name_from_argv0(const char *argv0) {
const char *base = strrchr(argv0, '/');
base = base ? (base + 1) : argv0;
if (strcasecmp(base, "dmenu") == 0 || strcasecmp(base, "xdmenu") == 0) {
return "dmenu";
}
if (strcasecmp(base, "xdrawer") == 0) {
return "xdrawer";
}
@@ -126,6 +248,7 @@ static int list_plugins(void) {
}
int main(int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
const char *plugin_name = resolve_plugin_name_from_argv0(argv[0]);
int sub_argc = argc;
char **sub_argv = argv;
@@ -143,7 +266,34 @@ int main(int argc, char **argv) {
sub_argv = argv + 1;
}
if (try_send_plugin_fifo(plugin_name, sub_argc, sub_argv)) {
if (strcmp(plugin_name, "dmenu") == 0) {
if (sub_argc >= 2 && sub_argv[1]) {
if (strcmp(sub_argv[1], "-v") == 0) {
puts("dmenu-5.0.14-bananarchy");
return 0;
}
if (strcmp(sub_argv[1], "isopen") == 0) {
return access("/tmp/dwm_plugin_dmenu.active", F_OK) == 0 ? 0 : 1;
}
if (strcmp(sub_argv[1], "close") == 0) {
try_send_plugin_fifo("dmenu", sub_argc, sub_argv);
unlink("/tmp/dwm_plugin_dmenu.active");
return 0;
}
if (is_dmenu_builtin_arg(sub_argv[1])) {
if (try_send_plugin_fifo("dmenu", sub_argc, sub_argv)) {
return 0;
}
}
}
if (!(sub_argc >= 2 && sub_argv[1] &&
(strcmp(sub_argv[1], "--preload") == 0 || is_dmenu_builtin_arg(sub_argv[1])))) {
int exit_code = 1;
if (try_dmenu_socket_client(sub_argc, sub_argv, &exit_code)) {
return exit_code;
}
}
} else if (try_send_plugin_fifo(plugin_name, sub_argc, sub_argv)) {
return 0;
}