diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 16 | ||||
| -rw-r--r-- | README.md | 6 | ||||
| -rw-r--r-- | config.def.h | 20 | ||||
| -rw-r--r-- | config.mk | 8 | ||||
| -rw-r--r-- | dwm.c | 91 | ||||
| -rw-r--r-- | patch/dwmc.c | 8 | ||||
| -rw-r--r-- | patch/include.c | 9 | ||||
| -rw-r--r-- | patch/include.h | 5 | ||||
| -rw-r--r-- | patches.def.h | 14 | ||||
| -rw-r--r-- | util.h | 6 |
11 files changed, 181 insertions, 3 deletions
@@ -1,4 +1,5 @@ *.o dwm +dwm-msg config.h patches.h @@ -6,7 +6,11 @@ include config.mk SRC = drw.c dwm.c util.c OBJ = ${SRC:.c=.o} +ifdef YAJLLIBS +all: options dwm dwm-msg +else all: options dwm +endif options: @echo dwm build options: @@ -28,8 +32,14 @@ patches.h: dwm: ${OBJ} ${CC} -o $@ ${OBJ} ${LDFLAGS} +ifdef YAJLLIBS +dwm-msg: + ${CC} -o $@ patch/ipc/dwm-msg.c ${LDFLAGS} +endif + clean: rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz + rm -f dwm-msg dist: clean mkdir -p dwm-${VERSION} @@ -42,8 +52,14 @@ dist: clean install: all mkdir -p ${DESTDIR}${PREFIX}/bin cp -f dwm ${DESTDIR}${PREFIX}/bin +ifdef YAJLLIBS + cp -f dwm-msg ${DESTDIR}${PREFIX}/bin +endif #cp -f patch/dwmc ${DESTDIR}${PREFIX}/bin chmod 755 ${DESTDIR}${PREFIX}/bin/dwm +ifdef YAJLLIBS + chmod 755 ${DESTDIR}${PREFIX}/bin/dwm-msg +endif mkdir -p ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 @@ -15,7 +15,7 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: -2020-09-07 - Scratchpads improvement (multi-monitor support) +2020-09-07 - Scratchpads improvement (multi-monitor support). Added ipc v1.5.5 patch. 2020-09-05 - Assortment of fullscreen improvements @@ -350,6 +350,10 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - lets custom insets from each edge of the screen to be defined - an example use case would be to make space for an external bar + - [ipc](https://github.com/mihirlad55/dwm-ipc) + - implements inter-process communication through a UNIX socket for dwm + - allows for the window manager to be queried for information, e.g. listen for events such as tag or layout changes, as well as send commands to control the window manager via other programs + - [ispermanent](https://dwm.suckless.org/patches/ispermanent/) - adds rule option for clients to avoid accidental termination by killclient for sticky windows diff --git a/config.def.h b/config.def.h index 2a5dbf9..695b50c 100644 --- a/config.def.h +++ b/config.def.h @@ -1308,3 +1308,23 @@ static Button buttons[] = { { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; + +#if IPC_PATCH +static const char *ipcsockpath = "/tmp/dwm.sock"; +static IPCCommand ipccommands[] = { + IPCCOMMAND( view, 1, {ARG_TYPE_UINT} ), + IPCCOMMAND( toggleview, 1, {ARG_TYPE_UINT} ), + IPCCOMMAND( tag, 1, {ARG_TYPE_UINT} ), + IPCCOMMAND( toggletag, 1, {ARG_TYPE_UINT} ), + IPCCOMMAND( tagmon, 1, {ARG_TYPE_UINT} ), + IPCCOMMAND( focusmon, 1, {ARG_TYPE_SINT} ), + IPCCOMMAND( focusstack, 1, {ARG_TYPE_SINT} ), + IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ), + IPCCOMMAND( incnmaster, 1, {ARG_TYPE_SINT} ), + IPCCOMMAND( killclient, 1, {ARG_TYPE_SINT} ), + IPCCOMMAND( togglefloating, 1, {ARG_TYPE_NONE} ), + IPCCOMMAND( setmfact, 1, {ARG_TYPE_FLOAT} ), + IPCCOMMAND( setlayoutsafe, 1, {ARG_TYPE_PTR} ), + IPCCOMMAND( quit, 1, {ARG_TYPE_NONE} ) +}; +#endif // IPC_PATCH
\ No newline at end of file @@ -30,6 +30,10 @@ FREETYPEINC = /usr/include/freetype2 #PANGOINC = `pkg-config --cflags xft pango pangoxft` #PANGOLIB = `pkg-config --libs xft pango pangoxft` +# Uncomment for the ipc patch / IPC_PATCH +#YAJLLIBS = -I-lyajl +#YAJLINC = /usr/include/yajl + # Uncomment this for the rounded corners patch / ROUNDED_CORNERS_PATCH #XEXTLIB = -lXext @@ -37,8 +41,8 @@ FREETYPEINC = /usr/include/freetype2 #XCBLIBS = -lX11-xcb -lxcb -lxcb-res # includes and libs -INCS = -I${X11INC} -I${FREETYPEINC} ${PANGOINC} -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${PANGOLIB} +INCS = -I${X11INC} -I${FREETYPEINC} ${PANGOINC} ${YAJLLIBS} +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT} ${XEXTLIB} ${XCBLIBS} ${PANGOLIB} ${YAJLLIBS} # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} @@ -219,9 +219,28 @@ enum { BAR_ALIGN_LAST }; /* bar alignment */ +#if IPC_PATCH +typedef struct TagState TagState; +struct TagState { + int selected; + int occupied; + int urgent; +}; + +typedef struct ClientState ClientState; +struct ClientState { + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; +}; +#endif // IPC_PATCH + typedef union { + #if IPC_PATCH + long i; + unsigned long ui; + #else int i; unsigned int ui; + #endif // IPC_PATCH float f; const void *v; } Arg; @@ -333,6 +352,9 @@ struct Client { #endif // SWALLOW_PATCH Monitor *mon; Window win; + #if IPC_PATCH + ClientState prevstate; + #endif // IPC_PATCH }; typedef struct { @@ -414,6 +436,12 @@ struct Monitor { #if INSETS_PATCH Inset inset; #endif // INSETS_PATCH + #if IPC_PATCH + char lastltsymbol[16]; + TagState tagstate; + Client *lastsel; + const Layout *lastlt; + #endif // IPC_PATCH }; typedef struct { @@ -1039,6 +1067,13 @@ cleanup(void) XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + + #if IPC_PATCH + ipc_cleanup(); + + if (close(epoll_fd) < 0) + fprintf(stderr, "Failed to close epoll file descriptor\n"); + #endif // IPC_PATCH } void @@ -2638,6 +2673,46 @@ restack(Monitor *m) #endif // WARP_PATCH } +#if IPC_PATCH +void +run(void) +{ + int event_count = 0; + const int MAX_EVENTS = 10; + struct epoll_event events[MAX_EVENTS]; + + XSync(dpy, False); + + /* main event loop */ + while (running) { + event_count = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); + + for (int i = 0; i < event_count; i++) { + int event_fd = events[i].data.fd; + DEBUG("Got event from fd %d\n", event_fd); + + if (event_fd == dpy_fd) { + // -1 means EPOLLHUP + if (handlexevent(events + i) == -1) + return; + } else if (event_fd == ipc_get_sock_fd()) { + ipc_handle_socket_epoll_event(events + i); + } else if (ipc_is_client_registered(event_fd)) { + if (ipc_handle_client_epoll_event(events + i, mons, &lastselmon, selmon, + NUMTAGS, layouts, LENGTH(layouts)) < 0) { + fprintf(stderr, "Error handling IPC event on fd %d\n", event_fd); + } + } else { + fprintf(stderr, "Got event from unknown fd %d, ptr %p, u32 %d, u64 %lu", + event_fd, events[i].data.ptr, events[i].data.u32, + events[i].data.u64); + fprintf(stderr, " with events %d\n", events[i].events); + return; + } + } + } +} +#else void run(void) { @@ -2648,6 +2723,7 @@ run(void) if (handler[ev.type]) handler[ev.type](&ev); /* call handler */ } +#endif // IPC_PATCH void scan(void) @@ -3096,6 +3172,9 @@ setup(void) XSelectInput(dpy, root, wa.event_mask); grabkeys(); focus(NULL); + #if IPC_PATCH + setupepoll(); + #endif // IPC_PATCH } @@ -3910,10 +3989,22 @@ updatestatus(void) void updatetitle(Client *c) { + #if IPC_PATCH + char oldname[sizeof(c->name)]; + strcpy(oldname, c->name); + #endif // IPC_PATCH + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); if (c->name[0] == '\0') /* hack to mark broken clients */ strcpy(c->name, broken); + + #if IPC_PATCH + for (Monitor *m = mons; m; m = m->next) { + if (m->sel == c && strcmp(oldname, c->name) != 0) + ipc_focused_title_change_event(m->num, c->win, oldname, c->name); + } + #endif // IPC_PATCH } void diff --git a/patch/dwmc.c b/patch/dwmc.c index 065e64d..4dedcbc 100644 --- a/patch/dwmc.c +++ b/patch/dwmc.c @@ -62,9 +62,17 @@ fake_signal(void) if (paramn == 1) arg = (Arg) {0}; else if (paramn > 2) return 1; else if (strncmp(param, "i", n - len_str_sig) == 0) + #if IPC_PATCH + sscanf(fsignal + len_indicator + n, "%li", &(arg.i)); + #else sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); + #endif // IPC_PATCH else if (strncmp(param, "ui", n - len_str_sig) == 0) + #if IPC_PATCH + sscanf(fsignal + len_indicator + n, "%lu", &(arg.ui)); + #else sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); + #endif // IPC_PATCH else if (strncmp(param, "f", n - len_str_sig) == 0) sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); else return 1; diff --git a/patch/include.c b/patch/include.c index e13348e..66eba15 100644 --- a/patch/include.c +++ b/patch/include.c @@ -138,6 +138,15 @@ #if INPLACEROTATE_PATCH #include "inplacerotate.c" #endif +#if IPC_PATCH +#include "ipc.c" +#ifdef VERSION +#include "ipc/IPCClient.c" +#include "ipc/yajl_dumps.c" +#include "ipc/ipc.c" +#include "ipc/util.c" +#endif +#endif // IPC_PATCH #if INSETS_PATCH #include "insets.c" #endif diff --git a/patch/include.h b/patch/include.h index 9130311..94b5a59 100644 --- a/patch/include.h +++ b/patch/include.h @@ -138,6 +138,11 @@ #if INPLACEROTATE_PATCH #include "inplacerotate.h" #endif +#if IPC_PATCH +#include "ipc.h" +#include "ipc/ipc.h" +#include "ipc/util.h" +#endif #if INSETS_PATCH #include "insets.h" #endif diff --git a/patches.def.h b/patches.def.h index bbed419..4a5048d 100644 --- a/patches.def.h +++ b/patches.def.h @@ -532,6 +532,20 @@ */ #define INSETS_PATCH 0 +/* This patch (v1.5.5) implements inter-process communication through a UNIX socket for dwm. This + * allows for the window manager to be queried for information, e.g. listen for events such as tag + * or layout changes, as well as send commands to control the window manager via other programs. + * + * You need to uncomment the corresponding lines in config.mk to use the -lyajl library + * when including this patch. + * This patch depends on the following additional library: + * - yajl + * + * https://github.com/mihirlad55/dwm-ipc + * https://dwm.suckless.org/patches/ipc/ + */ +#define IPC_PATCH 0 + /* Adds rule option for clients to avoid accidental termination by killclient for sticky windows. * https://dwm.suckless.org/patches/ispermanent/ */ @@ -8,5 +8,11 @@ #endif #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#ifdef _DEBUG +#define DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG(...) +#endif + void die(const char *fmt, ...); void *ecalloc(size_t nmemb, size_t size); |
