diff --git a/src/config.def.h.rej b/src/config.def.h.rej new file mode 100644 index 0000000..82ea963 --- /dev/null +++ b/src/config.def.h.rej @@ -0,0 +1,13 @@ +--- config.def.h ++++ config.def.h +@@ -5,6 +5,10 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int usealtbar = 1; /* 1 means use non-dwm status bar */ ++static const char *altbarclass = "Polybar"; /* Alternate bar class name */ ++static const char *alttrayname = "tray"; /* Polybar tray instance name */ ++static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; diff --git a/src/config.h b/src/config.h index 1e3fec2..43aa1e2 100644 --- a/src/config.h +++ b/src/config.h @@ -17,6 +17,12 @@ static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display static const int showsystray = 1; /* 0 means no systray */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ + +static const int usealtbar = 1; /* 1 means use non-dwm status bar */ +static const char *altbarclass = "Polybar"; /* Alternate bar class name */ +static const char *alttrayname = "tray"; /* Polybar tray instance name */ +static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */ + static const char *fonts[] = { "monospace:size=11", "Noto Color Emoji:size=11", "Nerd Font Mono:weight=bold:size=15:antialias=true:hinting=true" }; static const char dmenufont[] = "monospace:size=11"; @@ -24,8 +30,6 @@ static const char dmenufont[] = "monospace:size=11"; // Autostart programs static const char *const autostart[] = { - // Start my build of slstatus - "slstatus", NULL, // Keyboard layouts switch (requires setxkbmap) "setxkbmap", "-model", "pc101", "-layout", "us,ar", "-variant", ",,", "-option", "grp:win_space_toggle", NULL, // "xkbset", "exp", "=sticky", "-twokey", "-latchlock", NULL, // sticky keys diff --git a/src/dwm.c b/src/dwm.c index eb423c5..0499e58 100644 --- a/src/dwm.c +++ b/src/dwm.c @@ -47,8 +47,8 @@ /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) -#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ + * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) @@ -137,7 +137,8 @@ struct Monitor { float mfact; int nmaster; int num; - int by; /* bar geometry */ + int by, bh; /* bar geometry */ + int tx, tw; /* bar tray geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ unsigned int seltags; @@ -150,6 +151,7 @@ struct Monitor { Client *stack; Monitor *next; Window barwin; + Window traywin; const Layout *lt[2]; Pertag *pertag; }; @@ -208,6 +210,8 @@ static void incnmaster(const Arg *arg); static void keypress(XEvent *e); static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); +static void managealtbar(Window win, XWindowAttributes *wa); +static void managetray(Window win, XWindowAttributes *wa); static void mappingnotify(XEvent *e); static void maprequest(XEvent *e); static void monocle(Monitor *m); @@ -227,6 +231,7 @@ static void resizerequest(XEvent *e); static void restack(Monitor *m); static void run(void); static void scan(void); +static void scantray(void); static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); @@ -240,6 +245,7 @@ static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); +static void spawnbar(); static Monitor *systraytomon(Monitor *m); static void tag(const Arg *arg); static void tagmon(const Arg *arg); @@ -251,6 +257,8 @@ static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); static void unfocus(Client *c, int setfocus); static void unmanage(Client *c, int destroyed); +static void unmanagealtbar(Window w); +static void unmanagetray(Window w); static void unmapnotify(XEvent *e); static void updatebarpos(Monitor *m); static void updatebars(void); @@ -269,6 +277,7 @@ static void view(const Arg *arg); static Client *wintoclient(Window w); static Monitor *wintomon(Window w); static Client *wintosystrayicon(Window w); +static int wmclasscontains(Window win, const char *class, const char *name); static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); @@ -595,8 +604,10 @@ cleanupmon(Monitor *mon) for (m = mons; m && m->next != mon; m = m->next); m->next = mon->next; } - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); + if (!usealtbar) { + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + } free(mon); } @@ -779,6 +790,7 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->bh = bh; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -803,10 +815,15 @@ void destroynotify(XEvent *e) { Client *c; + Monitor *m; XDestroyWindowEvent *ev = &e->xdestroywindow; if ((c = wintoclient(ev->window))) unmanage(c, 1); + else if ((m = wintomon(ev->window)) && m->barwin == ev->window) + unmanagealtbar(ev->window); + else if (m->traywin == ev->window) + unmanagetray(ev->window); else if ((c = wintosystrayicon(ev->window))) { removesystrayicon(c); resizebarwin(selmon); @@ -855,6 +872,8 @@ dirtomon(int dir) void drawbar(Monitor *m) { + if (usealtbar) return; + int x, w, tw = 0, stw = 0; int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; @@ -1325,6 +1344,8 @@ maprequest(XEvent *e) return; if (wa.override_redirect) return; + if (wmclasscontains(ev->window, altbarclass, "")) + managealtbar(ev->window, &wa); if (!wintoclient(ev->window)) manage(ev->window, &wa); } @@ -1525,7 +1546,7 @@ resizebarwin(Monitor *m) { unsigned int w = m->ww; if (showsystray && m == systraytomon(m) && !systrayonleft) w -= getsystraywidth(); - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh); } void @@ -1668,8 +1689,10 @@ scan(void) for (i = 0; i < num; i++) { if (!XGetWindowAttributes(dpy, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) - continue; - if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + continue; + if (wmclasscontains(wins[i], altbarclass, "")) + managealtbar(wins[i], &wa); + else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); } for (i = 0; i < num; i++) { /* now the transients */ @@ -1684,6 +1707,28 @@ scan(void) } } + +void +scantray(void) +{ + unsigned int num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (unsigned int i = 0; i < num; i++) { + if (wmclasscontains(wins[i], altbarclass, alttrayname)) { + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + break; + managetray(wins[i], &wa); + } + } + } + + if (wins) + XFree(wins); +} + void sendmon(Client *c, Monitor *m) { @@ -1848,7 +1893,7 @@ setup(void) if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; + bh = usealtbar ? 0 : drw->fonts->h + 2; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1906,6 +1951,7 @@ setup(void) XSelectInput(dpy, root, wa.event_mask); grabkeys(); focus(NULL); + spawnbar(); } @@ -1980,6 +2026,13 @@ spawn(const Arg *arg) } } +void +spawnbar() +{ + if (*altbarcmd) + system(altbarcmd); +} + void tag(const Arg *arg) { @@ -2001,9 +2054,19 @@ tagmon(const Arg *arg) void togglebar(const Arg *arg) { + /** + * Polybar tray does not raise maprequest event. It must be manually scanned + * for. Scanning it too early while the tray is being populated would give + * wrong dimensions. + */ + if (!selmon->traywin) + scantray(); + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); resizebarwin(selmon); + //TODO: 2022-07-17 Test + XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh); if (showsystray) { XWindowChanges wc; if (!selmon->showbar) @@ -2018,6 +2081,38 @@ togglebar(const Arg *arg) arrange(selmon); } + +void +unmanagealtbar(Window w) +{ + Monitor *m = wintomon(w); + + if (!m) + return; + + m->barwin = 0; + m->by = 0; + m->bh = 0; + updatebarpos(m); + arrange(m); +} + +void +unmanagetray(Window w) +{ + Monitor *m = wintomon(w); + + if (!m) + return; + + m->traywin = 0; + m->tx = 0; + m->tw = 0; + updatebarpos(m); + arrange(m); +} + + void togglefloating(const Arg *arg) { @@ -2134,6 +2229,7 @@ void unmapnotify(XEvent *e) { Client *c; + Monitor *m; XUnmapEvent *ev = &e->xunmap; if ((c = wintoclient(ev->window))) { @@ -2141,7 +2237,10 @@ unmapnotify(XEvent *e) setclientstate(c, WithdrawnState); else unmanage(c, 0); - } + } else if ((m = wintomon(ev->window)) && m->barwin == ev->window) + unmanagealtbar(ev->window); + else if (m->traywin == ev->window) + unmanagetray(ev->window); else if ((c = wintosystrayicon(ev->window))) { /* KLUDGE! sometimes icons occasionally unmap their windows, but do * _not_ destroy them. We map those windows back */ @@ -2153,6 +2252,8 @@ unmapnotify(XEvent *e) void updatebars(void) { + if (usealtbar) return; + unsigned int w; Monitor *m; XSetWindowAttributes wa = { @@ -2184,11 +2285,11 @@ updatebarpos(Monitor *m) m->wy = m->my; m->wh = m->mh; if (m->showbar) { - m->wh -= bh; + m->wh -= m->bh; m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; + m->wy = m->topbar ? m->wy + m->bh : m->wy; } else - m->by = -bh; + m->by = -m->bh; } void @@ -2491,6 +2592,45 @@ updatewindowtype(Client *c) c->isfloating = 1; } + +void +managealtbar(Window win, XWindowAttributes *wa) +{ + Monitor *m; + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) + return; + + m->barwin = win; + m->by = wa->y; + bh = m->bh = wa->height; + updatebarpos(m); + arrange(m); + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); + XMapWindow(dpy, win); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &win, 1); +} + +void +managetray(Window win, XWindowAttributes *wa) +{ + Monitor *m; + if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height))) + return; + + m->traywin = win; + m->tx = wa->x; + m->tw = wa->width; + updatebarpos(m); + arrange(m); + XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height); + XMapWindow(dpy, win); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &win, 1); +} + void updatewmhints(Client *c) { @@ -2581,13 +2721,36 @@ wintomon(Window w) if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); for (m = mons; m; m = m->next) - if (w == m->barwin) + if (w == m->barwin || w == m->traywin) return m; if ((c = wintoclient(w))) return c->mon; return selmon; } + +int +wmclasscontains(Window win, const char *class, const char *name) +{ + XClassHint ch = { NULL, NULL }; + int res = 1; + + if (XGetClassHint(dpy, win, &ch)) { + if (ch.res_name && strstr(ch.res_name, name) == NULL) + res = 0; + if (ch.res_class && strstr(ch.res_class, class) == NULL) + res = 0; + } else + res = 0; + + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + + return res; +} + /* There's no way to check accesses to destroyed windows, thus those cases are * ignored (especially on UnmapNotify's). Other types of errors call Xlibs * default error handler, which may call exit. */ diff --git a/src/dwm.c.rej b/src/dwm.c.rej new file mode 100644 index 0000000..7e375c6 --- /dev/null +++ b/src/dwm.c.rej @@ -0,0 +1,112 @@ +--- dwm.c ++++ dwm.c +@@ -47,8 +47,8 @@ + /* macros */ + #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ +- * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) ++#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \ ++ * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) +@@ -199,6 +203,7 @@ static void resizemouse(const Arg *arg); + static void restack(Monitor *m); + static void run(void); + static void scan(void); ++static void scantray(void); + static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); +@@ -211,6 +216,7 @@ static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static void spawnbar(); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -236,6 +244,7 @@ static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static int wmclasscontains(Window win, const char *class, const char *name); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); +@@ -576,7 +587,7 @@ configurenotify(XEvent *e) + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); +- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); ++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh); + } + focus(NULL); + arrange(NULL); +@@ -658,10 +670,15 @@ void + destroynotify(XEvent *e) + { + Client *c; ++ Monitor *m; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ else if ((m = wintomon(ev->window)) && m->barwin == ev->window) ++ unmanagealtbar(ev->window); ++ else if (m->traywin == ev->window) ++ unmanagetray(ev->window); + } + + void +@@ -705,6 +722,9 @@ dirtomon(int dir) + void + drawbar(Monitor *m) + { ++ if (usealtbar) ++ return; ++ + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; +@@ -1785,9 +1879,18 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { ++ /** ++ * Polybar tray does not raise maprequest event. It must be manually scanned ++ * for. Scanning it too early while the tray is being populated would give ++ * wrong dimensions. ++ */ ++ if (!selmon->traywin) ++ scantray(); ++ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); +- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); ++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh); ++ XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh); + arrange(selmon); + } + +@@ -1912,12 +2046,18 @@ unmapnotify(XEvent *e) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); +- } ++ } else if ((m = wintomon(ev->window)) && m->barwin == ev->window) ++ unmanagealtbar(ev->window); ++ else if (m->traywin == ev->window) ++ unmanagetray(ev->window); + } + + void + updatebars(void) + { ++ if (usealtbar) ++ return; ++ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True,