aboutsummaryrefslogtreecommitdiffstats
path: root/dwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwm.c')
-rw-r--r--dwm.c150
1 files changed, 142 insertions, 8 deletions
diff --git a/dwm.c b/dwm.c
index 5f2d154..600cbd9 100644
--- a/dwm.c
+++ b/dwm.c
@@ -30,6 +30,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/epoll.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
@@ -105,9 +106,21 @@ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms *
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+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;
+};
+
typedef union {
- int i;
- unsigned int ui;
+ long i;
+ unsigned long ui;
float f;
const void *v;
} Arg;
@@ -138,6 +151,7 @@ struct Client {
Client *swallowing;
Monitor *mon;
Window win;
+ ClientState prevstate;
};
typedef struct {
@@ -155,6 +169,7 @@ typedef struct {
typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
+ char lastltsymbol[16];
float mfact;
int nmaster;
int num;
@@ -168,14 +183,17 @@ struct Monitor {
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
+ TagState tagstate;
int showbar;
int topbar;
Client *clients;
Client *sel;
+ Client *lastsel;
Client *stack;
Monitor *next;
Window barwin;
const Layout *lt[2];
+ const Layout *lastlt;
Pertag *pertag;
};
@@ -232,6 +250,7 @@ static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
+static int handlexevent(struct epoll_event *ev);
static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
@@ -263,9 +282,11 @@ static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg);
+static void setlayoutsafe(const Arg *arg);
static void setcfact(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
+static void setupepoll(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void spawn(const Arg *arg);
@@ -340,23 +361,33 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[UnmapNotify] = unmapnotify
};
static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
+static int epoll_fd;
+static int dpy_fd;
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
static Display *dpy;
static Drw *drw;
-static Monitor *mons, *selmon;
+static Monitor *mons, *selmon, *lastselmon;
static Window root, wmcheckwin;
static int useargb = 0;
static Visual *visual;
static int depth;
static Colormap cmap;
+#include "ipc.h"
+
static xcb_connection_t *xcon;
/* configuration, allows nested code to access above variables */
#include "config.h"
+#ifdef VERSION
+#include "IPCClient.c"
+#include "yajl_dumps.c"
+#include "ipc.c"
+#endif
+
struct Pertag {
unsigned int curtag, prevtag; /* current and previous tag */
int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
@@ -660,6 +691,12 @@ cleanup(void)
XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
+
+ ipc_cleanup();
+
+ if (close(epoll_fd) < 0) {
+ fprintf(stderr, "Failed to close epoll file descriptor\n");
+ }
}
void
@@ -1251,6 +1288,25 @@ grabkeys(void)
}
}
+int
+handlexevent(struct epoll_event *ev)
+{
+ if (ev->events & EPOLLIN) {
+ XEvent ev;
+ while (running && XPending(dpy)) {
+ XNextEvent(dpy, &ev);
+ if (handler[ev.type]) {
+ handler[ev.type](&ev); /* call handler */
+ ipc_send_events(mons, &lastselmon, selmon);
+ }
+ }
+ } else if (ev-> events & EPOLLHUP) {
+ return -1;
+ }
+
+ return 0;
+}
+
void
incnmaster(const Arg *arg)
{
@@ -1757,12 +1813,40 @@ restack(Monitor *m)
void
run(void)
{
- XEvent ev;
- /* main event loop */
+ int event_count = 0;
+ const int MAX_EVENTS = 10;
+ struct epoll_event events[MAX_EVENTS];
+
XSync(dpy, False);
- while (running && !XNextEvent(dpy, &ev))
- if (handler[ev.type])
- handler[ev.type](&ev); /* call handler */
+
+ /* 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,
+ tags, LENGTH(tags), 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;
+ }
+ }
+ }
}
void
@@ -1928,6 +2012,18 @@ setcfact(const Arg *arg) {
arrange(selmon);
}
+void
+setlayoutsafe(const Arg *arg)
+{
+ const Layout *ltptr = (Layout *)arg->v;
+ if (ltptr == 0)
+ setlayout(arg);
+ for (int i = 0; i < LENGTH(layouts); i++) {
+ if (ltptr == &layouts[i])
+ setlayout(arg);
+ }
+}
+
/* arg > 1.0 will set mfact absolutely */
void
setmfact(const Arg *arg)
@@ -2033,6 +2129,36 @@ setup(void)
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
focus(NULL);
+ setupepoll();
+}
+
+void
+setupepoll(void)
+{
+ epoll_fd = epoll_create1(0);
+ dpy_fd = ConnectionNumber(dpy);
+ struct epoll_event dpy_event;
+
+ // Initialize struct to 0
+ memset(&dpy_event, 0, sizeof(dpy_event));
+
+ DEBUG("Display socket is fd %d\n", dpy_fd);
+
+ if (epoll_fd == -1) {
+ fputs("Failed to create epoll file descriptor", stderr);
+ }
+
+ dpy_event.events = EPOLLIN;
+ dpy_event.data.fd = dpy_fd;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, dpy_fd, &dpy_event)) {
+ fputs("Failed to add display file descriptor to epoll", stderr);
+ close(epoll_fd);
+ exit(1);
+ }
+
+ if (ipc_init(ipcsockpath, epoll_fd, ipccommands, LENGTH(ipccommands)) < 0) {
+ fputs("Failed to initialize IPC\n", stderr);
+ }
}
void
@@ -2600,10 +2726,18 @@ updatesystray(void)
void
updatetitle(Client *c)
{
+ char oldname[sizeof(c->name)];
+ strcpy(oldname, c->name);
+
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);
+
+ 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);
+ }
}
void