diff --git a/src/dwm.c b/src/dwm.c index 63c69a5..3b5f083 100644 --- a/src/dwm.c +++ b/src/dwm.c @@ -56,10 +56,7 @@ #include "unit.h" #include "util.h" -/********** - * macros * - **********/ - +/* 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)) \ @@ -69,6 +66,7 @@ #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) /********* * types * @@ -129,6 +127,7 @@ typedef struct { typedef struct Bar { int by; int topbar; + Window barwin; int bh; } *Bar; @@ -137,6 +136,7 @@ struct Monitor { Bar bar; Pertag *pertag; + char ltsymbol[16]; int nmaster; int num; int mx, my, mw, mh; /* screen size */ @@ -266,6 +266,7 @@ static Unit global_unit = NULL; static const char broken[] = "broken"; static int screen; static int sw, sh; /* X display screen geometry width, height */ +static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { @@ -274,6 +275,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [ConfigureRequest] = on_configure_request, [ConfigureNotify] = on_configure_notify, [DestroyNotify] = on_destroy_notify, + [Expose] = on_expose, [FocusIn] = on_focus_in, [KeyPress] = on_key_press, [MappingNotify] = on_mapping_notify, @@ -485,6 +487,14 @@ arrangemon(Monitor *m) if (ISVISIBLE(client)) ++visible_clients; } + layouts_symbol_func( + m->lt[m->sellt]->symbol_func, + m->ltsymbol, + sizeof(m->ltsymbol), + m->nmaster, + visible_clients + ); + if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); else { @@ -594,7 +604,11 @@ cleanupmon(Monitor *mon) UNIT_DELETE(mon->pertag->units[i]); } free(mon->pertag); - free(mon->bar); + { + XUnmapWindow(dpy, mon->bar->barwin); + XDestroyWindow(dpy, mon->bar->barwin); + free(mon->bar); + } UNIT_DELETE(mon->unit); free(mon); } @@ -642,6 +656,14 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; + layouts_symbol_func( + layouts[0].symbol_func, + m->ltsymbol, + sizeof(m->ltsymbol), + m->nmaster, + 0 + ); + if (!(m->pertag = ecalloc(1, sizeof(Pertag)))) goto fail_without_pertag; m->pertag->curtag = m->pertag->prevtag = 1; @@ -744,6 +766,7 @@ focus(Client *c) XDeleteProperty(dpy, root, atoms->netatom[NetActiveWindow]); } selmon->sel = c; + drawbars(); } void @@ -1177,6 +1200,8 @@ nametag(__attribute__((unused)) const Arg *arg) { tags_rename(i, name); } } + + drawbars(); } void @@ -1385,15 +1410,14 @@ restack(Monitor *m) XEvent ev; XWindowChanges wc; + drawbar(m); if (!m->sel) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) XRaiseWindow(dpy, m->sel->win); if (m->lt[m->sellt]->arrange) { wc.stack_mode = Below; - // TODO: Learn what is sibling and what - // is the following line responsible for. - // wc.sibling = m->bar->barwin; + wc.sibling = m->bar->barwin; for (c = m->stack; c; c = c->snext) if (!c->isfloating && ISVISIBLE(c)) { XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); @@ -1540,8 +1564,18 @@ setlayout(const Arg *arg) if (ISVISIBLE(client)) ++visible_clients; } + layouts_symbol_func( + selmon->lt[selmon->sellt]->symbol_func, + selmon->ltsymbol, + sizeof(selmon->ltsymbol), + selmon->nmaster, + visible_clients + ); + if (selmon->sel) { arrange(selmon); + } else { + drawbar(selmon); } } @@ -1578,6 +1612,7 @@ setup(void) drw = drw_create(dpy, screen, root, sw, sh); if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); + lrpad = drw->fonts->h; updategeom(); /* init atoms */ atoms = atoms_create(dpy); @@ -1590,6 +1625,8 @@ setup(void) scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); for (unsigned int i = 0; i < LENGTH(colors); i++) scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + createbars(); /* supporting window for NetWMCheck */ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); @@ -2152,9 +2189,13 @@ wintomon(Window w) { int x, y; Client *c; + Monitor *m; if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->bar->barwin) + return m; if ((c = wintoclient(w))) return c->mon; return selmon; diff --git a/src/dwm/bar.c b/src/dwm/bar.c index 9a9b39f..d2ac448 100644 --- a/src/dwm/bar.c +++ b/src/dwm/bar.c @@ -1,6 +1,83 @@ #ifndef _DWM_BAR_C #define _DWM_BAR_C +void +createbars(void) +{ + XClassHint ch = {"polytreewm", "polytreewm"}; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + + for (Monitor *m = mons; m; m = m->next) { + if (m->bar->barwin) continue; + + m->bar->barwin = XCreateWindow( + dpy, + root, + m->wx, + m->bar->by, + m->ww, + m->bar->bh, + 0, + DefaultDepth(dpy, screen), + CopyFromParent, + DefaultVisual(dpy, screen), + CWOverrideRedirect | CWBackPixmap | CWEventMask, + &wa + ); + + XDefineCursor(dpy, m->bar->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->bar->barwin); + XSetClassHint(dpy, m->bar->barwin, &ch); + } +} + +void +drawbar(Monitor *m) +{ + int x, w, tw = 0; + unsigned int i, occ = 0, urg = 0; + Client *c; + + for (c = m->clients; c; c = c->next) { + occ |= c->tags == 255 ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < TAGS_COUNT; i++) { + /* do not draw vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i || tags_get(i)->has_custom_name)) + continue; + + w = TEXTW(tags_get(i)->name.cstr); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, m->bar->bh, lrpad / 2, tags_get(i)->name.cstr, urg & 1 << i); + x += w; + } + w = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, m->bar->bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > m->bar->bh) { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, m->bar->bh, 1, 1); + } + + drw_map(drw, m->bar->barwin, 0, 0, m->ww, m->bar->bh); +} + +void +drawbars(void) +{ + for (Monitor *m = mons; m; m = m->next) { + drawbar(m); + } +} + void togglebar(const Arg *arg) { @@ -15,6 +92,7 @@ updatebar(Monitor *m) m->show_bar = unit_get_show_bar(m->pertag->units[m->pertag->curtag]); updatebarpos(m); + XMoveResizeWindow(dpy, selmon->bar->barwin, selmon->wx, selmon->bar->by, selmon->ww, m->bar->bh); arrange(m); } diff --git a/src/dwm/bar.h b/src/dwm/bar.h index 64576fe..be0e465 100644 --- a/src/dwm/bar.h +++ b/src/dwm/bar.h @@ -1,6 +1,9 @@ #ifndef _DWM_BAR_H #define _DWM_BAR_H +static void createbars(void); +static void drawbar(Monitor *m); +static void drawbars(void); static void togglebar(const Arg *arg); static void updatebarpos(Monitor *m); static void updatebar(Monitor *m); diff --git a/src/dwm/handlers.c b/src/dwm/handlers.c index 4536c45..15e2857 100644 --- a/src/dwm/handlers.c +++ b/src/dwm/handlers.c @@ -121,6 +121,7 @@ on_configure_request(XEvent *e) void on_configure_notify(XEvent *e) { + Monitor *m; XConfigureEvent *ev = &e->xconfigure; int dirty; @@ -130,6 +131,11 @@ on_configure_notify(XEvent *e) sw = ev->width; sh = ev->height; if (updategeom() || dirty) { + createbars(); + for (m = mons; m; m = m->next) { + drw_resize(drw, sw, m->bar->bh); + XMoveResizeWindow(dpy, m->bar->barwin, m->wx, m->bar->by, m->ww, m->bar->bh); + } focus(NULL); arrange(NULL); } @@ -150,6 +156,17 @@ on_destroy_notify(XEvent *e) } } +void +on_expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); + } +} + /* there are some broken focus acquiring clients needing extra handling */ void on_focus_in(XEvent *e) @@ -222,10 +239,13 @@ on_property_notify(XEvent *e) break; case XA_WM_HINTS: updatewmhints(c); + drawbars(); break; } if (ev->atom == XA_WM_NAME || ev->atom == atoms->netatom[NetWMName]) { updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); } if (ev->atom == atoms->netatom[NetWMWindowType]) updatewindowtype(c); diff --git a/src/dwm/handlers.h b/src/dwm/handlers.h index abd59e4..98b63a2 100644 --- a/src/dwm/handlers.h +++ b/src/dwm/handlers.h @@ -6,6 +6,7 @@ static void on_client_message(XEvent *e); static void on_configure_notify(XEvent *e); static void on_configure_request(XEvent *e); static void on_destroy_notify(XEvent *e); +static void on_expose(XEvent *e); static void on_focus_in(XEvent *e); static void on_key_press(XEvent *e); static void on_mapping_notify(XEvent *e);