diff --git a/Makefile b/Makefile index 00c684f..090c0a8 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ${OBJ_DIR}/%.o: %.c mkdir -p $(@D) ${CC} -c ${CFLAGS} $< -o $@ -${OBJ}: src/config/config.h config.mk +${OBJ}: src/config.h config.mk config.h: cp config.def.h $@ diff --git a/archpackage/archy-dwm-git/.SRCINFO b/archpackage/archy-dwm-git/.SRCINFO new file mode 100644 index 0000000..1b55a29 --- /dev/null +++ b/archpackage/archy-dwm-git/.SRCINFO @@ -0,0 +1,22 @@ +pkgbase = archy-dwm-git + pkgdesc = A dynamic window manager for X with some patches applied + pkgver = 1.0.0.r1.gfeb819c + pkgrel = 1 + url = https://github.com/archy-linux/archy-dwm + arch = i686 + arch = x86_64 + license = MIT + makedepends = git + makedepends = make + depends = libx11 + depends = libxinerama + depends = libxft + depends = freetype2 + depends = archy-slstatus-git + depends = archy-dmenu-git + provides = archy-dwm + conflicts = archy-dwm + source = archy-dwm::git+https://github.com/archy-linux/archy-dwm.git + sha256sums = SKIP + +pkgname = archy-dwm-git diff --git a/archpackage/archy-dwm-git/PKGBUILD b/archpackage/archy-dwm-git/PKGBUILD new file mode 100644 index 0000000..efd8bf8 --- /dev/null +++ b/archpackage/archy-dwm-git/PKGBUILD @@ -0,0 +1,41 @@ +# Maintainer: Anas Elgarhy +pkgname=archy-dwm-git +_pkgname=archy-dwm +pkgver=1.0.0.r1.gfeb819c +pkgrel=1 +pkgdesc="A dynamic window manager for X with some patches applied" +url="https://github.com/archy-linux/$_pkgname" +arch=('i686' 'x86_64') +license=('MIT') +options=() +depends=('libx11' 'libxinerama' 'libxft' 'freetype2' 'archy-slstatus-git' 'archy-dmenu-git') +makedepends=('git' 'make') +install= +provides=("$_pkgname") +conflicts=("$_pkgname") +source=("$_pkgname::git+$url.git") +sha256sums=('SKIP') + +pkgver(){ + cd $_pkgname || exit 1 + git describe --long --tags | sed -E 's/([^-]*-g)/r\1/;s/-/./g' +} + +prepare() { + cd $_pkgname || exit 1 + make archy-dwm.desktop +} + +build() { + cd $_pkgname || exit 1 + make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11 +} + +package() { + cd $_pkgname || exit 1 + # shellcheck disable=SC2154 + make PREFIX=/usr DESTDIR="$pkgdir" install + install -m644 -D LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -m644 -D README.md "$pkgdir/usr/share/doc/$pkgname/README" + install -m644 -D build/archy-dwm.desktop "$pkgdir/usr/share/xsessions/archy-dwm.desktop" +} diff --git a/archpackage/archy-dwm-git/archy-dwm-git-aur b/archpackage/archy-dwm-git/archy-dwm-git-aur new file mode 160000 index 0000000..4ee5417 --- /dev/null +++ b/archpackage/archy-dwm-git/archy-dwm-git-aur @@ -0,0 +1 @@ +Subproject commit 4ee54178fef085aad3256c22c060cac3cf4a05f9 diff --git a/archpackage/archy-dwm/.SRCINFO b/archpackage/archy-dwm/.SRCINFO new file mode 100644 index 0000000..1b256a1 --- /dev/null +++ b/archpackage/archy-dwm/.SRCINFO @@ -0,0 +1,18 @@ +pkgbase = archy-dwm + pkgdesc = A dynamic window manager for X with some patches applied + pkgver = 1.0.0 + pkgrel = 1 + url = https://github.com/archy-linux/archy-dwm + arch = i686 + arch = x86_64 + license = MIT + depends = libx11 + depends = libxinerama + depends = libxft + depends = freetype2 + depends = archy-slstatus + depends = archy-dmenu + source = https://github.com/archy-linux/archy-dwm/archive/refs/tags/1.0.0.tar.gz + sha256sums = 4e56232bd78971e20a9e6fa7dda16f7047be086aa3a066f5c410c4e3ae5d7add + +pkgname = archy-dwm diff --git a/archpackage/archy-dwm/PKGBUILD b/archpackage/archy-dwm/PKGBUILD new file mode 100644 index 0000000..47b89fc --- /dev/null +++ b/archpackage/archy-dwm/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: Anas Elgarhy +pkgname=archy-dwm +pkgver=1.0.0 +pkgrel=1 +pkgdesc="A dynamic window manager for X with some patches applied" +url="https://github.com/archy-linux/$pkgname" +arch=('i686' 'x86_64') +license=('MIT') +options=() +depends=('libx11' 'libxinerama' 'libxft' 'freetype2' 'archy-slstatus' 'archy-dmenu') +install= +provides=("$pkgname") +conflicts=("$pkgname") +source=("https://github.com/archy-linux/$pkgname/archive/refs/tags/$pkgname_$pkgver.tar.gz") +sha256sums=('4e56232bd78971e20a9e6fa7dda16f7047be086aa3a066f5c410c4e3ae5d7add') + +package() { + cd "$pkgname_$pkgver" || exit 1 + # shellcheck disable=SC2154 + install -Dm755 "$pkgname" "$pkgdir/usr/bin/$pkgname" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 README.md "$pkgdir/usr/share/doc/$pkgname/README.md" + install -Dm644 "$pkgname.desktop" "$pkgdir/usr/share/xsessions/$pkgname.desktop" +} diff --git a/archpackage/archy-dwm/archy-dwm-aur b/archpackage/archy-dwm/archy-dwm-aur new file mode 160000 index 0000000..92c2edf --- /dev/null +++ b/archpackage/archy-dwm/archy-dwm-aur @@ -0,0 +1 @@ +Subproject commit 92c2edf888b0974cee206d2a657781384112bce0 diff --git a/patches/92f77de7deb4b5b9fc2dcf958264093458123497.diff b/patches/92f77de7deb4b5b9fc2dcf958264093458123497.diff new file mode 100644 index 0000000..1a6575c --- /dev/null +++ b/patches/92f77de7deb4b5b9fc2dcf958264093458123497.diff @@ -0,0 +1,562 @@ +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, diff --git a/patches/dwm-alwayscenter-20200625-f04cac6.diff b/patches/dwm-alwayscenter-20200625-f04cac6.diff new file mode 100644 index 0000000..03ea9ef --- /dev/null +++ b/patches/dwm-alwayscenter-20200625-f04cac6.diff @@ -0,0 +1,12 @@ +diff -up dwm/dwm.c dwmmod/dwm.c +--- dwm/dwm.c 2020-06-25 00:21:30.383692180 -0300 ++++ dwmmod/dwm.c 2020-06-25 00:20:35.643692330 -0300 +@@ -1057,6 +1057,8 @@ manage(Window w, XWindowAttributes *wa) + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); ++ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; ++ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) diff --git a/patches/dwm-centeredmaster-20160719-56a31dc.diff b/patches/dwm-centeredmaster-20160719-56a31dc.diff new file mode 100644 index 0000000..1968e61 --- /dev/null +++ b/patches/dwm-centeredmaster-20160719-56a31dc.diff @@ -0,0 +1,142 @@ +diff --git a/config.def.h b/config.def.h +index fd77a07..f025619 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -41,6 +41,8 @@ static const Layout layouts[] = { + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "|M|", centeredmaster }, ++ { ">M>", centeredfloatingmaster }, + }; + + /* key definitions */ +@@ -76,6 +78,8 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} }, ++ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index b2bc9bd..9ecabae 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -234,6 +234,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void centeredmaster(Monitor *m); ++static void centeredfloatingmaster(Monitor *m); + + /* variables */ + static const char broken[] = "broken"; +@@ -2138,3 +2140,106 @@ main(int argc, char *argv[]) + XCloseDisplay(dpy); + return EXIT_SUCCESS; + } ++ ++void ++centeredmaster(Monitor *m) ++{ ++ unsigned int i, n, h, mw, mx, my, oty, ety, tw; ++ Client *c; ++ ++ /* count number of clients in the selected monitor */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (n == 0) ++ return; ++ ++ /* initialize areas */ ++ mw = m->ww; ++ mx = 0; ++ my = 0; ++ tw = mw; ++ ++ if (n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ mw = m->nmaster ? m->ww * m->mfact : 0; ++ tw = m->ww - mw; ++ ++ if (n - m->nmaster > 1) { ++ /* only one client */ ++ mx = (m->ww - mw) / 2; ++ tw = (m->ww - mw) / 2; ++ } ++ } ++ ++ oty = 0; ++ ety = 0; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked vertically, in the center ++ * of the screen */ ++ h = (m->wh - my) / (MIN(n, m->nmaster) - i); ++ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), ++ h - (2*c->bw), 0); ++ my += HEIGHT(c); ++ } else { ++ /* stack clients are stacked vertically */ ++ if ((i - m->nmaster) % 2 ) { ++ h = (m->wh - ety) / ( (1 + n - i) / 2); ++ resize(c, m->wx, m->wy + ety, tw - (2*c->bw), ++ h - (2*c->bw), 0); ++ ety += HEIGHT(c); ++ } else { ++ h = (m->wh - oty) / ((1 + n - i) / 2); ++ resize(c, m->wx + mx + mw, m->wy + oty, ++ tw - (2*c->bw), h - (2*c->bw), 0); ++ oty += HEIGHT(c); ++ } ++ } ++} ++ ++void ++centeredfloatingmaster(Monitor *m) ++{ ++ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; ++ Client *c; ++ ++ /* count number of clients in the selected monitor */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (n == 0) ++ return; ++ ++ /* initialize nmaster area */ ++ if (n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ if (m->ww > m->wh) { ++ mw = m->nmaster ? m->ww * m->mfact : 0; ++ mh = m->nmaster ? m->wh * 0.9 : 0; ++ } else { ++ mh = m->nmaster ? m->wh * m->mfact : 0; ++ mw = m->nmaster ? m->ww * 0.9 : 0; ++ } ++ mx = mxo = (m->ww - mw) / 2; ++ my = myo = (m->wh - mh) / 2; ++ } else { ++ /* go fullscreen if all clients are in the master area */ ++ mh = m->wh; ++ mw = m->ww; ++ mx = mxo = 0; ++ my = myo = 0; ++ } ++ ++ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked horizontally, in the center ++ * of the screen */ ++ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); ++ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), ++ mh - (2*c->bw), 0); ++ mx += WIDTH(c); ++ } else { ++ /* stack clients are stacked horizontally */ ++ w = (m->ww - tx) / (n - i); ++ resize(c, m->wx + tx, m->wy, w - (2*c->bw), ++ m->wh - (2*c->bw), 0); ++ tx += WIDTH(c); ++ } ++} diff --git a/patches/dwm-cool-autostart-6.2.diff b/patches/dwm-cool-autostart-6.2.diff new file mode 100644 index 0000000..84a93ea --- /dev/null +++ b/patches/dwm-cool-autostart-6.2.diff @@ -0,0 +1,116 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..ed056a4 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -18,6 +18,11 @@ static const char *colors[][3] = { + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + ++static const char *const autostart[] = { ++ "st", NULL, ++ NULL /* terminate */ ++}; ++ + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +diff --git a/dwm.c b/dwm.c +index 9fd0286..1facd56 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -234,6 +234,7 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void autostart_exec(void); + + /* variables */ + static const char broken[] = "broken"; +@@ -275,6 +276,34 @@ static Window root, wmcheckwin; + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + ++/* dwm will keep pid's of processes from autostart array and kill them at quit */ ++static pid_t *autostart_pids; ++static size_t autostart_len; ++ ++/* execute command from autostart array */ ++static void ++autostart_exec() { ++ const char *const *p; ++ size_t i = 0; ++ ++ /* count entries */ ++ for (p = autostart; *p; autostart_len++, p++) ++ while (*++p); ++ ++ autostart_pids = malloc(autostart_len * sizeof(pid_t)); ++ for (p = autostart; *p; i++, p++) { ++ if ((autostart_pids[i] = fork()) == 0) { ++ setsid(); ++ execvp(*p, (char *const *)p); ++ fprintf(stderr, "dwm: execvp %s\n", *p); ++ perror(" failed"); ++ _exit(EXIT_FAILURE); ++ } ++ /* skip arguments */ ++ while (*++p); ++ } ++} ++ + /* function implementations */ + void + applyrules(Client *c) +@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e) + void + quit(const Arg *arg) + { ++ size_t i; ++ ++ /* kill child processes */ ++ for (i = 0; i < autostart_len; i++) { ++ if (0 < autostart_pids[i]) { ++ kill(autostart_pids[i], SIGTERM); ++ waitpid(autostart_pids[i], NULL, 0); ++ } ++ } ++ + running = 0; + } + +@@ -1632,9 +1671,25 @@ showhide(Client *c) + void + sigchld(int unused) + { ++ pid_t pid; ++ + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); +- while (0 < waitpid(-1, NULL, WNOHANG)); ++ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { ++ pid_t *p, *lim; ++ ++ if (!(p = autostart_pids)) ++ continue; ++ lim = &p[autostart_len]; ++ ++ for (; p < lim; p++) { ++ if (*p == pid) { ++ *p = -1; ++ break; ++ } ++ } ++ ++ } + } + + void +@@ -2139,6 +2194,7 @@ main(int argc, char *argv[]) + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); ++ autostart_exec(); + setup(); + #ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) + diff --git a/patches/dwm-fibonacci-20200418-c82db69.diff b/patches/dwm-fibonacci-20200418-c82db69.diff new file mode 100644 index 0000000..81bba7a --- /dev/null +++ b/patches/dwm-fibonacci-20200418-c82db69.diff @@ -0,0 +1,114 @@ +From ec9f55b6005cfa3b025b3d700c61af3ce539d057 Mon Sep 17 00:00:00 2001 +From: Niki Yoshiuchi +Date: Sat, 18 Apr 2020 09:55:26 -0700 +Subject: [PATCH] Adding the fibonacci layout patch + +--- + config.def.h | 5 ++++ + fibonacci.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 71 insertions(+) + create mode 100644 fibonacci.c + +diff --git a/config.def.h b/config.def.h +index 1c0b587..5708487 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -36,11 +36,14 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] + static const int nmaster = 1; /* number of clients in master area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + ++#include "fibonacci.c" + static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "[@]", spiral }, ++ { "[\\]", dwindle }, + }; + + /* key definitions */ +@@ -76,6 +79,8 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_r, setlayout, {.v = &layouts[3]} }, ++ { MODKEY|ShiftMask, XK_r, setlayout, {.v = &layouts[4]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/fibonacci.c b/fibonacci.c +new file mode 100644 +index 0000000..fce0a57 +--- /dev/null ++++ b/fibonacci.c +@@ -0,0 +1,66 @@ ++void ++fibonacci(Monitor *mon, int s) { ++ unsigned int i, n, nx, ny, nw, nh; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++); ++ if(n == 0) ++ return; ++ ++ nx = mon->wx; ++ ny = 0; ++ nw = mon->ww; ++ nh = mon->wh; ++ ++ for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) { ++ if((i % 2 && nh / 2 > 2 * c->bw) ++ || (!(i % 2) && nw / 2 > 2 * c->bw)) { ++ if(i < n - 1) { ++ if(i % 2) ++ nh /= 2; ++ else ++ nw /= 2; ++ if((i % 4) == 2 && !s) ++ nx += nw; ++ else if((i % 4) == 3 && !s) ++ ny += nh; ++ } ++ if((i % 4) == 0) { ++ if(s) ++ ny += nh; ++ else ++ ny -= nh; ++ } ++ else if((i % 4) == 1) ++ nx += nw; ++ else if((i % 4) == 2) ++ ny += nh; ++ else if((i % 4) == 3) { ++ if(s) ++ nx += nw; ++ else ++ nx -= nw; ++ } ++ if(i == 0) ++ { ++ if(n != 1) ++ nw = mon->ww * mon->mfact; ++ ny = mon->wy; ++ } ++ else if(i == 1) ++ nw = mon->ww - nw; ++ i++; ++ } ++ resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False); ++ } ++} ++ ++void ++dwindle(Monitor *mon) { ++ fibonacci(mon, 1); ++} ++ ++void ++spiral(Monitor *mon) { ++ fibonacci(mon, 0); ++} +-- +2.20.1 + diff --git a/patches/dwm-fullscreen-6.2.diff b/patches/dwm-fullscreen-6.2.diff new file mode 100644 index 0000000..36e3140 --- /dev/null +++ b/patches/dwm-fullscreen-6.2.diff @@ -0,0 +1,56 @@ +From 54719285bd1a984e2efce6e8a8eab184fec11abf Mon Sep 17 00:00:00 2001 +From: Sermak +Date: Mon, 8 Jul 2019 01:06:44 +0200 +Subject: [PATCH] Simulate toggleable fullscreen mode + +--- + config.def.h | 1 + + dwm.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..f774cc5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -76,6 +76,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY|ShiftMask, XK_f, fullscreen, {0} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 4465af1..04b1e06 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -199,6 +199,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void fullscreen(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -1497,6 +1498,19 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++Layout *last_layout; ++void ++fullscreen(const Arg *arg) ++{ ++ if (selmon->showbar) { ++ for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++); ++ setlayout(&((Arg) { .v = &layouts[2] })); ++ } else { ++ setlayout(&((Arg) { .v = last_layout })); ++ } ++ togglebar(arg); ++} ++ + void + setlayout(const Arg *arg) + { +-- +2.22.0 diff --git a/patches/dwm-gridmode-20170909-ceac8c9.diff b/patches/dwm-gridmode-20170909-ceac8c9.diff new file mode 100644 index 0000000..feec67b --- /dev/null +++ b/patches/dwm-gridmode-20170909-ceac8c9.diff @@ -0,0 +1,73 @@ +From b04bb473cf9818277d33a591f7fe2dfae96afaaf Mon Sep 17 00:00:00 2001 +From: Joshua Haase +Date: Mon, 15 Aug 2016 17:06:18 -0500 +Subject: [PATCH] Apply modified gridmode patch. + +--- + config.def.h | 3 +++ + layouts.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + create mode 100644 layouts.c + +diff --git a/config.def.h b/config.def.h +index a9ac303..30b7c4a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -36,11 +36,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95] + static const int nmaster = 1; /* number of clients in master area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + ++#include "layouts.c" + static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "HHH", grid }, + }; + + /* key definitions */ +@@ -76,6 +78,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_g, setlayout, {.v = &layouts[3]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/layouts.c b/layouts.c +new file mode 100644 +index 0000000..d26acf3 +--- /dev/null ++++ b/layouts.c +@@ -0,0 +1,27 @@ ++void ++grid(Monitor *m) { ++ unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) ++ n++; ++ ++ /* grid dimensions */ ++ for(rows = 0; rows <= n/2; rows++) ++ if(rows*rows >= n) ++ break; ++ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; ++ ++ /* window geoms (cell height/width) */ ++ ch = m->wh / (rows ? rows : 1); ++ cw = m->ww / (cols ? cols : 1); ++ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { ++ cx = m->wx + (i / rows) * cw; ++ cy = m->wy + (i % rows) * ch; ++ /* adjust height/width of last row/column's windows */ ++ ah = ((i + 1) % rows == 0) ? m->wh - ch * rows : 0; ++ aw = (i >= rows * (cols - 1)) ? m->ww - cw * cols : 0; ++ resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False); ++ i++; ++ } ++} +-- +2.14.1 + diff --git a/patches/dwm-movestack-20211115-a786211.diff b/patches/dwm-movestack-20211115-a786211.diff new file mode 100644 index 0000000..134abb8 --- /dev/null +++ b/patches/dwm-movestack-20211115-a786211.diff @@ -0,0 +1,95 @@ +From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001 +From: BrunoCooper17 +Date: Mon, 15 Nov 2021 14:04:53 -0600 +Subject: [PATCH] MoveStack patch + +This plugin allows you to move clients around in the stack and swap them +with the master. It emulates the behavior off mod+shift+j and mod+shift+k +in Xmonad. movestack(+1) will swap the client with the current focus with +the next client. movestack(-1) will swap the client with the current focus +with the previous client. +--- + config.def.h | 3 +++ + movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + create mode 100644 movestack.c + +diff --git a/config.def.h b/config.def.h +index a2ac963..33efa5b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++#include "movestack.c" + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -71,6 +72,8 @@ static Key keys[] = { + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +diff --git a/movestack.c b/movestack.c +new file mode 100644 +index 0000000..520f4ae +--- /dev/null ++++ b/movestack.c +@@ -0,0 +1,48 @@ ++void ++movestack(const Arg *arg) { ++ Client *c = NULL, *p = NULL, *pc = NULL, *i; ++ ++ if(arg->i > 0) { ++ /* find the client after selmon->sel */ ++ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); ++ if(!c) ++ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); ++ ++ } ++ else { ++ /* find the client before selmon->sel */ ++ for(i = selmon->clients; i != selmon->sel; i = i->next) ++ if(ISVISIBLE(i) && !i->isfloating) ++ c = i; ++ if(!c) ++ for(; i; i = i->next) ++ if(ISVISIBLE(i) && !i->isfloating) ++ c = i; ++ } ++ /* find the client before selmon->sel and c */ ++ for(i = selmon->clients; i && (!p || !pc); i = i->next) { ++ if(i->next == selmon->sel) ++ p = i; ++ if(i->next == c) ++ pc = i; ++ } ++ ++ /* swap c and selmon->sel selmon->clients in the selmon->clients list */ ++ if(c && c != selmon->sel) { ++ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; ++ selmon->sel->next = c->next==selmon->sel?c:c->next; ++ c->next = temp; ++ ++ if(p && p != c) ++ p->next = c; ++ if(pc && pc != selmon->sel) ++ pc->next = selmon->sel; ++ ++ if(selmon->sel == selmon->clients) ++ selmon->clients = c; ++ else if(c == selmon->clients) ++ selmon->clients = selmon->sel; ++ ++ arrange(selmon); ++ } ++} +\ No newline at end of file +-- +2.33.1 + diff --git a/patches/dwm-noborderfloatingfix-6.2.diff b/patches/dwm-noborderfloatingfix-6.2.diff new file mode 100644 index 0000000..4db7a4f --- /dev/null +++ b/patches/dwm-noborderfloatingfix-6.2.diff @@ -0,0 +1,31 @@ +From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001 +From: Aidan Hall +Date: Tue, 2 Jun 2020 14:41:53 +0000 +Subject: [PATCH] Prevents hiding the border if layout is floating. + +--- + dwm.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/dwm.c b/dwm.c +index 4465af1..2dd959d 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h) + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; ++ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) ++ || &monocle == c->mon->lt[c->mon->sellt]->arrange) ++ && !c->isfullscreen && !c->isfloating ++ && NULL != c->mon->lt[c->mon->sellt]->arrange) { ++ c->w = wc.width += c->bw * 2; ++ c->h = wc.height += c->bw * 2; ++ wc.border_width = 0; ++ } + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +-- +2.26.2 + diff --git a/patches/dwm-noborderselflickerfix-2022042627-d93ff48803f0.diff b/patches/dwm-noborderselflickerfix-2022042627-d93ff48803f0.diff new file mode 100644 index 0000000..e69de29 diff --git a/patches/dwm-notitle-6.2.diff b/patches/dwm-notitle-6.2.diff new file mode 100644 index 0000000..efd5ebc --- /dev/null +++ b/patches/dwm-notitle-6.2.diff @@ -0,0 +1,81 @@ +From 969dbbc548f16da5d94630e3d54e9c96c5296520 Mon Sep 17 00:00:00 2001 +From: Ryan Kes +Date: Thu, 28 Mar 2019 14:36:07 +0100 +Subject: [PATCH] dwm-notitle-6.2 + +--- + config.def.h | 1 - + dwm.c | 20 ++++---------------- + 2 files changed, 4 insertions(+), 17 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..19330cd 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -102,7 +102,6 @@ static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, +- { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..bcf5cb1 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -64,8 +64,8 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +-enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, +- ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ ++enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkClientWin, ++ ClkRootWin, ClkLast }; /* clicks */ + + typedef union { + int i; +@@ -439,10 +439,8 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - TEXTW(stext)) +- click = ClkStatusText; + else +- click = ClkWinTitle; ++ click = ClkStatusText; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); +@@ -729,15 +727,8 @@ drawbar(Monitor *m) + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - sw - x) > bh) { +- if (m->sel) { +- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +- if (m->sel->isfloating) +- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); +- } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); +- } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); + } +@@ -1235,11 +1226,8 @@ propertynotify(XEvent *e) + drawbars(); + break; + } +- if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { ++ if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) + updatetitle(c); +- if (c == c->mon->sel) +- drawbar(c->mon); +- } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +-- +2.21.0 + diff --git a/patches/dwm-pertag-20200914-61bb8b2.diff b/patches/dwm-pertag-20200914-61bb8b2.diff new file mode 100644 index 0000000..c8d7fbc --- /dev/null +++ b/patches/dwm-pertag-20200914-61bb8b2.diff @@ -0,0 +1,177 @@ +diff --git a/dwm.c b/dwm.c +index 664c527..ac8e4ec 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -111,6 +111,7 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -130,6 +131,7 @@ struct Monitor { + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -272,6 +274,15 @@ static Window root, wmcheckwin; + /* configuration, allows nested code to access above variables */ + #include "config.h" + ++struct Pertag { ++ unsigned int curtag, prevtag; /* current and previous tag */ ++ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ ++ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ ++ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ ++ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ ++}; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -632,6 +643,7 @@ Monitor * + createmon(void) + { + Monitor *m; ++ unsigned int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; +@@ -642,6 +654,20 @@ createmon(void) + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ m->pertag = ecalloc(1, sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ ++ for (i = 0; i <= LENGTH(tags); i++) { ++ m->pertag->nmasters[i] = m->nmaster; ++ m->pertag->mfacts[i] = m->mfact; ++ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ m->pertag->showbars[i] = m->showbar; ++ } ++ + return m; + } + +@@ -967,7 +993,7 @@ grabkeys(void) + void + incnmaster(const Arg *arg) + { +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -1502,9 +1528,9 @@ void + setlayout(const Arg *arg) + { + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1523,7 +1549,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1702,7 +1728,7 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +@@ -1741,9 +1767,33 @@ void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; ++ ++ if (newtagset == ~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ ++ /* test if the user did not select the same tag */ ++ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i = 0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); ++ + focus(NULL); + arrange(selmon); + } +@@ -2038,11 +2088,37 @@ updatewmhints(Client *c) + void + view(const Arg *arg) + { ++ int i; ++ unsigned int tmptag; ++ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ ++ if (arg->ui == ~0) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i = 0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); ++ + focus(NULL); + arrange(selmon); + } diff --git a/patches/dwm-sticky-6.1.diff b/patches/dwm-sticky-6.1.diff new file mode 100644 index 0000000..717793f --- /dev/null +++ b/patches/dwm-sticky-6.1.diff @@ -0,0 +1,58 @@ +diff --git a/config.def.h b/config.def.h +index 7054c06..9b5d5b8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -76,6 +76,7 @@ static Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_s, togglesticky, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff --git a/dwm.c b/dwm.c +index 0362114..0ef5c7f 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -49,7 +49,7 @@ + #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 ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) ++#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) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) +@@ -92,7 +92,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky; + Client *next; + Client *snext; + Monitor *mon; +@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglesticky(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -1713,6 +1714,15 @@ togglefloating(const Arg *arg) + } + + void ++togglesticky(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ selmon->sel->issticky = !selmon->sel->issticky; ++ arrange(selmon); ++} ++ ++void + toggletag(const Arg *arg) + { + unsigned int newtags; diff --git a/patches/dwm-systray-6.3.diff b/patches/dwm-systray-6.3.diff new file mode 100644 index 0000000..6dbd5da --- /dev/null +++ b/patches/dwm-systray-6.3.diff @@ -0,0 +1,763 @@ +diff --git a/config.def.h b/config.def.h +index a2ac963..4be4c06 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,9 +2,14 @@ + + /* appearance */ + 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 unsigned int snap = 32; /* snap pixel */ ++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ ++static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ ++static const unsigned int systrayspacing = 2; /* systray spacing */ ++static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ ++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 char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -101,8 +106,8 @@ static Key keys[] = { + /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ + static Button buttons[] = { + /* click event mask button function argument */ +- { ClkLtSymbol, 0, Button1, setlayout, {0} }, +- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, ++ { ClkTagBar, MODKEY, Button1, tag, {0} }, ++ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index a96f33c..941c1c0 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -57,12 +57,27 @@ + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + ++#define SYSTEM_TRAY_REQUEST_DOCK 0 ++/* XEMBED messages */ ++#define XEMBED_EMBEDDED_NOTIFY 0 ++#define XEMBED_WINDOW_ACTIVATE 1 ++#define XEMBED_FOCUS_IN 4 ++#define XEMBED_MODALITY_ON 10 ++#define XEMBED_MAPPED (1 << 0) ++#define XEMBED_WINDOW_ACTIVATE 1 ++#define XEMBED_WINDOW_DEACTIVATE 2 ++#define VERSION_MAJOR 0 ++#define VERSION_MINOR 0 ++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR ++ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, ++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ ++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ +@@ -141,6 +156,12 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct Systray Systray; ++struct Systray { ++ Window win; ++ Client *icons; ++}; ++ + /* function declarations */ + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +@@ -172,6 +193,7 @@ static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); + static long getstate(Window w); ++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); +@@ -189,13 +211,16 @@ static void pop(Client *); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); ++static void removesystrayicon(Client *i); + static void resize(Client *c, int x, int y, int w, int h, int interact); ++static void resizebarwin(Monitor *m); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); ++static void resizerequest(XEvent *e); + static void restack(Monitor *m); + static void run(void); + static void scan(void); +-static int sendevent(Client *c, Atom proto); ++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); + static void setfocus(Client *c); +@@ -207,6 +232,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 Monitor *systraytomon(Monitor *m); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -224,18 +250,23 @@ static int updategeom(void); + static void updatenumlockmask(void); + static void updatesizehints(Client *c); + static void updatestatus(void); ++static void updatesystray(void); ++static void updatesystrayicongeom(Client *i, int w, int h); ++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); + static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static Client *wintosystrayicon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + + /* variables */ ++static Systray *systray = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, ++ [ResizeRequest] = resizerequest, + [UnmapNotify] = unmapnotify + }; +-static Atom wmatom[WMLast], netatom[NetLast]; ++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; + static int running = 1; + static Cur *cursor[CurLast]; + static Clr **scheme; +@@ -440,7 +472,7 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth()) + click = ClkStatusText; + else + click = ClkWinTitle; +@@ -483,7 +515,14 @@ cleanup(void) + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); +- for (i = 0; i < CurLast; i++) ++ ++ if (showsystray) { ++ XUnmapWindow(dpy, systray->win); ++ XDestroyWindow(dpy, systray->win); ++ free(systray); ++ } ++ ++ for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); +@@ -513,9 +552,58 @@ cleanupmon(Monitor *mon) + void + clientmessage(XEvent *e) + { ++ XWindowAttributes wa; ++ XSetWindowAttributes swa; + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + ++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { ++ /* add systray icons */ ++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { ++ if (!(c = (Client *)calloc(1, sizeof(Client)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); ++ if (!(c->win = cme->data.l[2])) { ++ free(c); ++ return; ++ } ++ c->mon = selmon; ++ c->next = systray->icons; ++ systray->icons = c; ++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { ++ /* use sane defaults */ ++ wa.width = bh; ++ wa.height = bh; ++ wa.border_width = 0; ++ } ++ c->x = c->oldx = c->y = c->oldy = 0; ++ c->w = c->oldw = wa.width; ++ c->h = c->oldh = wa.height; ++ c->oldbw = wa.border_width; ++ c->bw = 0; ++ c->isfloating = True; ++ /* reuse tags field as mapped status */ ++ c->tags = 1; ++ updatesizehints(c); ++ updatesystrayicongeom(c, wa.width, wa.height); ++ XAddToSaveSet(dpy, c->win); ++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); ++ XReparentWindow(dpy, c->win, systray->win, 0, 0); ++ /* use parents background color */ ++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ /* FIXME not sure if I have to send these events, too */ ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); ++ XSync(dpy, False); ++ resizebarwin(selmon); ++ updatesystray(); ++ setclientstate(c, NormalState); ++ } ++ return; ++ } ++ + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { +@@ -568,7 +656,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); ++ resizebarwin(m); + } + focus(NULL); + arrange(NULL); +@@ -653,6 +741,11 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ else if ((c = wintosystrayicon(ev->window))) { ++ removesystrayicon(c); ++ resizebarwin(selmon); ++ updatesystray(); ++ } + } + + void +@@ -696,7 +789,7 @@ dirtomon(int dir) + void + drawbar(Monitor *m) + { +- int x, w, tw = 0; ++ int x, w, tw = 0, stw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; +@@ -705,13 +798,17 @@ drawbar(Monitor *m) + if (!m->showbar) + return; + ++ if(showsystray && m == systraytomon(m) && !systrayonleft) ++ stw = getsystraywidth(); ++ + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); +- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px extra right padding */ ++ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0); + } + ++ resizebarwin(m); + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) +@@ -732,7 +829,7 @@ drawbar(Monitor *m) + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + +- if ((w = m->ww - tw - x) > bh) { ++ if ((w = m->ww - tw - stw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +@@ -743,7 +840,7 @@ drawbar(Monitor *m) + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } +- drw_map(drw, m->barwin, 0, 0, m->ww, bh); ++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); + } + + void +@@ -780,8 +877,11 @@ expose(XEvent *e) + Monitor *m; + XExposeEvent *ev = &e->xexpose; + +- if (ev->count == 0 && (m = wintomon(ev->window))) ++ if (ev->count == 0 && (m = wintomon(ev->window))) { + drawbar(m); ++ if (m == selmon) ++ updatesystray(); ++ } + } + + void +@@ -867,9 +967,17 @@ getatomprop(Client *c, Atom prop) + unsigned char *p = NULL; + Atom da, atom = None; + +- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, ++ /* FIXME getatomprop should return the number of items and a pointer to ++ * the stored data instead of this workaround */ ++ Atom req = XA_ATOM; ++ if (prop == xatom[XembedInfo]) ++ req = xatom[XembedInfo]; ++ ++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; ++ if (da == xatom[XembedInfo] && dl == 2) ++ atom = ((Atom *)p)[1]; + XFree(p); + } + return atom; +@@ -903,6 +1011,16 @@ getstate(Window w) + return result; + } + ++unsigned int ++getsystraywidth() ++{ ++ unsigned int w = 0; ++ Client *i; ++ if(showsystray) ++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; ++ return w ? w + systrayspacing : 1; ++} ++ + int + gettextprop(Window w, Atom atom, char *text, unsigned int size) + { +@@ -1007,7 +1125,8 @@ killclient(const Arg *arg) + { + if (!selmon->sel) + return; +- if (!sendevent(selmon->sel, wmatom[WMDelete])) { ++ ++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); +@@ -1096,6 +1215,13 @@ maprequest(XEvent *e) + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + ++ Client *i; ++ if ((i = wintosystrayicon(ev->window))) { ++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); ++ resizebarwin(selmon); ++ updatesystray(); ++ } ++ + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; + if (wa.override_redirect) +@@ -1219,7 +1345,18 @@ propertynotify(XEvent *e) + Window trans; + XPropertyEvent *ev = &e->xproperty; + +- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) ++ if ((c = wintosystrayicon(ev->window))) { ++ if (ev->atom == XA_WM_NORMAL_HINTS) { ++ updatesizehints(c); ++ updatesystrayicongeom(c, c->w, c->h); ++ } ++ else ++ updatesystrayiconstate(c, ev); ++ resizebarwin(selmon); ++ updatesystray(); ++ } ++ ++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ +@@ -1269,6 +1406,19 @@ recttomon(int x, int y, int w, int h) + return r; + } + ++void ++removesystrayicon(Client *i) ++{ ++ Client **ii; ++ ++ if (!showsystray || !i) ++ return; ++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); ++ if (ii) ++ *ii = i->next; ++ free(i); ++} ++ + void + resize(Client *c, int x, int y, int w, int h, int interact) + { +@@ -1276,6 +1426,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) + resizeclient(c, x, y, w, h); + } + ++void ++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); ++} ++ + void + resizeclient(Client *c, int x, int y, int w, int h) + { +@@ -1348,6 +1506,19 @@ resizemouse(const Arg *arg) + } + } + ++void ++resizerequest(XEvent *e) ++{ ++ XResizeRequestEvent *ev = &e->xresizerequest; ++ Client *i; ++ ++ if ((i = wintosystrayicon(ev->window))) { ++ updatesystrayicongeom(i, ev->width, ev->height); ++ resizebarwin(selmon); ++ updatesystray(); ++ } ++} ++ + void + restack(Monitor *m) + { +@@ -1437,26 +1608,37 @@ setclientstate(Client *c, long state) + } + + int +-sendevent(Client *c, Atom proto) ++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) + { + int n; +- Atom *protocols; ++ Atom *protocols, mt; + int exists = 0; + XEvent ev; + +- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { +- while (!exists && n--) +- exists = protocols[n] == proto; +- XFree(protocols); ++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { ++ mt = wmatom[WMProtocols]; ++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { ++ while (!exists && n--) ++ exists = protocols[n] == proto; ++ XFree(protocols); ++ } + } ++ else { ++ exists = True; ++ mt = proto; ++ } ++ + if (exists) { + ev.type = ClientMessage; +- ev.xclient.window = c->win; +- ev.xclient.message_type = wmatom[WMProtocols]; ++ ev.xclient.window = w; ++ ev.xclient.message_type = mt; + ev.xclient.format = 32; +- ev.xclient.data.l[0] = proto; +- ev.xclient.data.l[1] = CurrentTime; +- XSendEvent(dpy, c->win, False, NoEventMask, &ev); ++ ev.xclient.data.l[0] = d0; ++ ev.xclient.data.l[1] = d1; ++ ev.xclient.data.l[2] = d2; ++ ev.xclient.data.l[3] = d3; ++ ev.xclient.data.l[4] = d4; ++ XSendEvent(dpy, w, False, mask, &ev); + } + return exists; + } +@@ -1470,7 +1652,7 @@ setfocus(Client *c) + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } +- sendevent(c, wmatom[WMTakeFocus]); ++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); + } + + void +@@ -1558,15 +1740,22 @@ setup(void) + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); +- netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); +- netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); ++ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); ++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); ++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); ++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); ++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); ++ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); +- /* init cursors */ ++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); ++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); ++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); ++ /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); +@@ -1574,6 +1763,8 @@ setup(void) + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); ++ /* init system tray */ ++ updatesystray(); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1707,7 +1898,18 @@ togglebar(const Arg *arg) + { + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); +- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); ++ resizebarwin(selmon); ++ if (showsystray) { ++ XWindowChanges wc; ++ if (!selmon->showbar) ++ wc.y = -bh; ++ else if (selmon->showbar) { ++ wc.y = 0; ++ if (!selmon->topbar) ++ wc.y = selmon->mh - bh; ++ } ++ XConfigureWindow(dpy, systray->win, CWY, &wc); ++ } + arrange(selmon); + } + +@@ -1802,11 +2004,18 @@ unmapnotify(XEvent *e) + else + unmanage(c, 0); + } ++ else if ((c = wintosystrayicon(ev->window))) { ++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do ++ * _not_ destroy them. We map those windows back */ ++ XMapRaised(dpy, c->win); ++ updatesystray(); ++ } + } + + void + updatebars(void) + { ++ unsigned int w; + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, +@@ -1817,10 +2026,15 @@ updatebars(void) + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; +- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), ++ w = m->ww; ++ if (showsystray && m == systraytomon(m)) ++ w -= getsystraywidth(); ++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); ++ if (showsystray && m == systraytomon(m)) ++ XMapRaised(dpy, systray->win); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +@@ -1996,6 +2210,125 @@ updatestatus(void) + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); ++ updatesystray(); ++} ++ ++ ++void ++updatesystrayicongeom(Client *i, int w, int h) ++{ ++ if (i) { ++ i->h = bh; ++ if (w == h) ++ i->w = bh; ++ else if (h == bh) ++ i->w = w; ++ else ++ i->w = (int) ((float)bh * ((float)w / (float)h)); ++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); ++ /* force icons into the systray dimensions if they don't want to */ ++ if (i->h > bh) { ++ if (i->w == i->h) ++ i->w = bh; ++ else ++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); ++ i->h = bh; ++ } ++ } ++} ++ ++void ++updatesystrayiconstate(Client *i, XPropertyEvent *ev) ++{ ++ long flags; ++ int code = 0; ++ ++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || ++ !(flags = getatomprop(i, xatom[XembedInfo]))) ++ return; ++ ++ if (flags & XEMBED_MAPPED && !i->tags) { ++ i->tags = 1; ++ code = XEMBED_WINDOW_ACTIVATE; ++ XMapRaised(dpy, i->win); ++ setclientstate(i, NormalState); ++ } ++ else if (!(flags & XEMBED_MAPPED) && i->tags) { ++ i->tags = 0; ++ code = XEMBED_WINDOW_DEACTIVATE; ++ XUnmapWindow(dpy, i->win); ++ setclientstate(i, WithdrawnState); ++ } ++ else ++ return; ++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, ++ systray->win, XEMBED_EMBEDDED_VERSION); ++} ++ ++void ++updatesystray(void) ++{ ++ XSetWindowAttributes wa; ++ XWindowChanges wc; ++ Client *i; ++ Monitor *m = systraytomon(NULL); ++ unsigned int x = m->mx + m->mw; ++ unsigned int sw = TEXTW(stext) - lrpad + systrayspacing; ++ unsigned int w = 1; ++ ++ if (!showsystray) ++ return; ++ if (systrayonleft) ++ x -= sw + lrpad / 2; ++ if (!systray) { ++ /* init systray */ ++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); ++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); ++ wa.event_mask = ButtonPressMask | ExposureMask; ++ wa.override_redirect = True; ++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); ++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, ++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); ++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); ++ XMapRaised(dpy, systray->win); ++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); ++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { ++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); ++ XSync(dpy, False); ++ } ++ else { ++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); ++ free(systray); ++ systray = NULL; ++ return; ++ } ++ } ++ for (w = 0, i = systray->icons; i; i = i->next) { ++ /* make sure the background color stays the same */ ++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; ++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); ++ XMapRaised(dpy, i->win); ++ w += systrayspacing; ++ i->x = w; ++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); ++ w += i->w; ++ if (i->mon != m) ++ i->mon = m; ++ } ++ w = w ? w + systrayspacing : 1; ++ x -= w; ++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); ++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; ++ wc.stack_mode = Above; wc.sibling = m->barwin; ++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); ++ XMapWindow(dpy, systray->win); ++ XMapSubwindows(dpy, systray->win); ++ /* redraw background */ ++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); ++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); ++ XSync(dpy, False); + } + + void +@@ -2063,6 +2396,16 @@ wintoclient(Window w) + return NULL; + } + ++Client * ++wintosystrayicon(Window w) { ++ Client *i = NULL; ++ ++ if (!showsystray || !w) ++ return i; ++ for (i = systray->icons; i && i->win != w; i = i->next) ; ++ return i; ++} ++ + Monitor * + wintomon(Window w) + { +@@ -2116,6 +2459,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) + return -1; + } + ++Monitor * ++systraytomon(Monitor *m) { ++ Monitor *t; ++ int i, n; ++ if(!systraypinning) { ++ if(!m) ++ return selmon; ++ return m == selmon ? m : NULL; ++ } ++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; ++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; ++ if(systraypinningfailfirst && n < systraypinning) ++ return mons; ++ return t; ++} ++ + void + zoom(const Arg *arg) + { diff --git a/screenshots/dwm-6.3-0.1.0.png b/screenshots/dwm-6.3-0.1.0.png new file mode 100644 index 0000000..653a869 Binary files /dev/null and b/screenshots/dwm-6.3-0.1.0.png differ diff --git a/screenshots/dwm_alacritty-6.3-0.1.0.png b/screenshots/dwm_alacritty-6.3-0.1.0.png new file mode 100644 index 0000000..de76dfe Binary files /dev/null and b/screenshots/dwm_alacritty-6.3-0.1.0.png differ diff --git a/screenshots/dwm_alacritty_cmus_cava-6.3-0.1.1.png b/screenshots/dwm_alacritty_cmus_cava-6.3-0.1.1.png new file mode 100644 index 0000000..0fa91bf Binary files /dev/null and b/screenshots/dwm_alacritty_cmus_cava-6.3-0.1.1.png differ diff --git a/screenshots/dwm_bpytop_and_ufetch_tile_layout-6.3-0.1.0.png b/screenshots/dwm_bpytop_and_ufetch_tile_layout-6.3-0.1.0.png new file mode 100644 index 0000000..16ba711 Binary files /dev/null and b/screenshots/dwm_bpytop_and_ufetch_tile_layout-6.3-0.1.0.png differ diff --git a/src/archy_dwm.c b/src/archy_dwm.c index f0d7a23..453284e 100644 --- a/src/archy_dwm.c +++ b/src/archy_dwm.c @@ -99,11 +99,15 @@ static Monitor *mons, *selmon; static Window root, wmcheckwin; /* configuration, allows nested code to access above variables */ -#include "config/config.h" +#include "config.h" /* Layouts */ #include "layouts/layouts.h" /* Movestack patch */ #include "movestack.c" +/* Keys bindings */ +#include "keys/keys.h" +/* Mouse bindings */ +#include "keys/mouse.h" struct Pertag { unsigned int curtag, prevtag; /* current and previous tag */ @@ -1654,6 +1658,20 @@ sigchld(int unused) { } } +void +spawn(const Arg *arg) { + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **) arg->v)[0], (char **) arg->v); + fprintf(stderr, "archy-dwm: execvp %s", ((char **) arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} void tag(const Arg *arg) { diff --git a/src/archy_dwm.h b/src/archy_dwm.h index 6ebf6cc..78e15a6 100644 --- a/src/archy_dwm.h +++ b/src/archy_dwm.h @@ -2,8 +2,8 @@ // Created by anas on 10/31/22. // -#ifndef ARCHY_DWM_H -#define ARCHY_DWM_H +#ifndef DWM_H +#define DWM_H /* enums */ enum { @@ -270,4 +270,4 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); static void autostart_exec(void); -#endif //ARCHY_DWM_H +#endif //DWM_H diff --git a/src/colors/gruvbox_dark_hard.h b/src/colors/gruvbox_dark_hard.h index e212ba8..ec863c5 100644 --- a/src/colors/gruvbox_dark_hard.h +++ b/src/colors/gruvbox_dark_hard.h @@ -4,11 +4,11 @@ #ifndef GRUVBOX_DARK_HARD_H #define GRUVBOX_DARK_HARD_H -static const char norm_fg[] = "#D5C4A1"; // light2 +static const char norm_fg[] = "#EBDBB2"; // light1 static const char norm_bg[] = "#1D2021"; // dark0_hard static const char norm_border[] = "#504945"; // dark2 -static const char sel_fg[] = "#D79921"; // neutral_yellow +static const char sel_fg[] = "#FE8019"; // bright_orange static const char sel_bg[] = "#1D2021"; // dark0_hard static const char sel_border[] = "#7C6F64"; // dark4 diff --git a/src/config/config.h b/src/config.h similarity index 80% rename from src/config/config.h rename to src/config.h index 3e80fcf..8e65ef3 100644 --- a/src/config/config.h +++ b/src/config.h @@ -3,15 +3,6 @@ /* def */ #define TERMINAL "st" -#ifndef STDDEF_H -#include -#endif -#ifndef ARCHY_DWM_H -#include "../archy_dwm.h" -#endif -#include "keys.h" -#include "mouse.h" - /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int gappx = 3; /* gaps size between windows */ @@ -28,30 +19,21 @@ static const char *fonts[] = { "Nerd Font Mono:size=10:antialias=true:hinting=true"}; static const char dmenufont[] = "monospace:size=8"; -/* Colors - Gruvbox dark hard */ -static const char norm_fg[] = "#D5C4A1"; // light2 -static const char norm_bg[] = "#1D2021"; // dark0_hard -static const char norm_border[] = "#504945"; // dark2 +#ifndef STDDEF_H -static const char sel_fg[] = "#D79921"; // neutral_yellow -static const char sel_bg[] = "#1D2021"; // dark0_hard -static const char sel_border[] = "#7C6F64"; // dark4 +#include -static const char urg_fg[] = "#D5C4A1"; // light4 -static const char urg_bg[] = "#FB4934"; // bright_red -static const char urg_border[] = "#458588"; // neutral_blue +#endif -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = {norm_fg, norm_bg, norm_border}, // unfocused wins - [SchemeSel] = {sel_fg, sel_bg, sel_border}, // the focused win - [SchemeUrg] = {urg_fg, urg_bg, urg_border}, -}; +#include "colors/gruvbox_dark_hard.h" +#include "archy_dwm.h" // Autostart programs static const char *const autostart[] = { // Start my build of slstatus "archy-slstatus", NULL, + // Start the terminal with tmux + TERMINAL, "-e", "tmux", NULL, NULL /* terminate */ }; @@ -92,7 +74,7 @@ static const Rule rules[] = { }; /* layout(s) */ -static const float mfact = 0.60f; /* factor of master area size [0.05..0.95] */ +static const float mfact = 0.55f; /* factor of master area size [0.05..0.95] */ static const int nmaster = 1; /* number of clients in master area */ static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ diff --git a/src/config/keys.h b/src/config/keys.h deleted file mode 100644 index 1af7390..0000000 --- a/src/config/keys.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef KEYS_H -#define KEYS_H - -#include "../archy_dwm.h" -#include - -typedef struct { - unsigned int mod; - KeySym keysym; - - void (*func)(const Arg *); - - const Arg arg; -} Key; - -/* key definitions */ -#define MODKEY Mod4Mask // The super key - -#define TAGKEYS(KEY, TAG) \ - {MODKEY, KEY, view, {.ui = 1 << TAG}}, \ - {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ - {MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \ - {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, - -#ifndef ACTIONS_H -#include "../actions.h" -#endif //ACTIONS_H -#ifndef LAYOUTS_H -#include "../layouts/layouts.h" -#endif //LAYOUTS_H -// X11 keysym definitions -#include // req (libxinerama1 and libxinerama-dev) - -#include - -static Key keys[] = { - /* modifier key function argument */ - {MODKEY, XK_f, fullscreen, {0}}, - {MODKEY|ShiftMask, XK_b, togglebar, {0}}, - // Change the focus - {MODKEY, XK_e, focusstack, {.i = +1}}, - {MODKEY, XK_a, focusstack, {.i = -1}}, - // incress and decrees the masters - {MODKEY, XK_i, incnmaster, {.i = +1}}, - {MODKEY, XK_d, incnmaster, {.i = -1}}, - // Change the focus window size (in the tile mode) - {MODKEY, XK_equal, setmfact, {.f = -0.05f}}, - {MODKEY, XK_minus, setmfact, {.f = +0.05f}}, - {MODKEY, XK_Tab, view, {0}}, - {MODKEY | ShiftMask, XK_e, movestack, {.i = +1}}, - {MODKEY | ShiftMask, XK_a, movestack, {.i = -1}}, - // Toogle styky mode - {MODKEY | ShiftMask, XK_s, togglesticky, {0}}, - // Quit from the foucsed window (kill) - {MODKEY|ShiftMask, XK_q, killclient, {0}}, - /************************* Switch between layouts *************************/ - // Tiled layout - {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, - // Floating layout - {MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, - // Monocle layout - {MODKEY, XK_m, setlayout, {.v = &layouts[2]}}, - // Grid layout - {MODKEY, XK_g, setlayout, {.v = &layouts[3]}}, - // Spiral layout - {MODKEY, XK_r, setlayout, {.v = &layouts[4]}}, - // Dwindle layout - {MODKEY, XK_d, setlayout, {.v = &layouts[5]}}, - // Centerd master layout - {MODKEY, XK_c, setlayout, {.v = &layouts[6]}}, - // Centerd floating master layout - {MODKEY, XK_x, setlayout, {.v = &layouts[7]}}, - // Toggle between current layout and tile layout - {MODKEY, XK_s, setlayout, {0}}, - // Toggle floating window - {MODKEY | ShiftMask, XK_f, togglefloating, {0}}, - // Mirror the current tagg in all tags - {MODKEY, XK_0, tag, {.ui = ~0}}, - // Multi monitor stuff - {MODKEY, XK_comma, focusmon, {.i = -1}}, - {MODKEY, XK_period, focusmon, {.i = +1}}, - {MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}}, - {MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}}, - /************************* Tag keys *************************/ - TAGKEYS(XK_1, 0) - TAGKEYS(XK_2, 1) - TAGKEYS(XK_3, 2) - TAGKEYS(XK_4, 3) - TAGKEYS(XK_5, 4) - TAGKEYS(XK_6, 5) - TAGKEYS(XK_7, 6) - TAGKEYS(XK_8, 7) - TAGKEYS(XK_9, 8) - TAGKEYS(XK_semicolon, 9) -}; - -#endif // keys_H diff --git a/src/actions.h b/src/keys/functions.h similarity index 85% rename from src/actions.h rename to src/keys/functions.h index bcc6806..f9a98e4 100644 --- a/src/actions.h +++ b/src/keys/functions.h @@ -2,10 +2,12 @@ // Created by anas on 10/31/22. // -#ifndef ACTIONS_H -#define ACTIONS_H +#ifndef FUNCTIONS_H +#define FUNCTIONS_H -#include "archy_dwm.h" +#include "../archy_dwm.h" + +static void spawn(const Arg *arg); static void focusmon(const Arg *arg); @@ -41,4 +43,4 @@ static void zoom(const Arg *arg); static void quit(const Arg *arg); -#endif //ACTIONS_H +#endif //FUNCTIONS_H diff --git a/src/keys/keys.c b/src/keys/keys.c new file mode 100644 index 0000000..22f402a --- /dev/null +++ b/src/keys/keys.c @@ -0,0 +1,152 @@ +#include "../config.h" +#include "keys.h" +#include "functions.h" +#include "../layouts/layouts.h" +// X11 keysym definitions +#include // req (libxinerama1 and libxinerama-dev) + +#include + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = {"dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", norm_bg, + "-nf", norm_fg, "-sb", sel_bg, "-sf", sel_fg, NULL}; +static const char *termcmd[] = {TERMINAL, NULL}; +// Music +static const char *CMUS[] = {TERMINAL, "--class=cmus", "-e", "cmus"}; // Just start cmus :) +static const char *SPOTIFY[] = {"brave-browser-beta", "--app=https://open.spotify.com"}; // because I love music :D + +static Key keys[] = { + /* modifier chain key key function argument */ + /* ---------------------------------- Apps Keys ---------------------------------- */ + // Dmenu (launcher) + {MODKEY, XK_p, spawn, {.v = dmenucmd}}, + // Rofi launcher (small) + {MODKEY, XK_r, spawn, SHCMD("rofi -show drun")}, + {MODKEY, XK_Return, spawn, {.v = termcmd}}, + /************************************* Start the web browers *************************************/ + // Firefox-developer-edition + {MODKEY | ShiftMask, XK_f, spawn, SHCMD("firefox-developer-edition")}, + // brave-beta + {MODKEY | ShiftMask, XK_b, spawn, SHCMD("brave-beta")}, + // Google chrome stable + {MODKEY | ShiftMask, XK_g, spawn, SHCMD("google-chrome-stable")}, + // Tor brower + {MODKEY | ShiftMask, XK_t, spawn, SHCMD("tor-browser")}, + /************************************* Start the caht/email/\* apps *************************************/ + // Discord + {MODKEY | ShiftMask, XK_d, spawn, SHCMD("discord")}, + // Obsidian + {MODKEY | ShiftMask, XK_o, spawn, SHCMD("obsidian")}, + /************************************* Start the dev apps *************************************/ + // Jetbrains toolbox + {MODKEY | ShiftMask, XK_j, spawn, SHCMD("jetbrains-toolbox")}, + + /************************************* Start multi media apps *************************************/ + {MODKEY, XK_l, spawn, SHCMD("luncher")}, + // cmus + {MODKEY | ShiftMask, XK_c, spawn, {.v = CMUS}}, + // Spotify + {MODKEY | ShiftMask, XK_s, spawn, {.v = SPOTIFY}}, + /************************************* Start the emoji piker apps *************************************/ + // Emoji selector (rofi) + {Mod4Mask, XK_e, spawn, SHCMD("rofimoji")}, + /************************************* dwm keys *************************************/ + // Full screen mode + {MODKEY, XK_f, fullscreen, {0}}, + // Toggle the slstatus bar (hide/show) + {MODKEY, XK_b, togglebar, {0}}, + // Change the focus + {MODKEY, XK_j, focusstack, {.i = +1}}, + {MODKEY, XK_k, focusstack, {.i = -1}}, + // Change the stack layout (horizontal/virtecal) + {MODKEY, XK_i, incnmaster, {.i = +1}}, + {MODKEY, XK_d, incnmaster, {.i = -1}}, + // Change the focus window size (in the tile mode) + {MODKEY, XK_h, setmfact, {.f = -0.05f}}, + {MODKEY, XK_l, setmfact, {.f = +0.05f}}, + {MODKEY, XK_Tab, view, {0}}, + {MODKEY | ShiftMask, XK_j, movestack, {.i = +1}}, + {MODKEY | ShiftMask, XK_k, movestack, {.i = -1}}, + // Toogle styky mode + {MODKEY | ShiftMask, XK_s, togglesticky, {0}}, + + // Quit from the foucsed window (kill) + {MODKEY, XK_q, killclient, {0}}, + /************************* Switch between layouts *************************/ + // Tiled layout + {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, + // Floating layout + {MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, + // Monocle layout + {MODKEY, XK_m, setlayout, {.v = &layouts[2]}}, + // Grid layout + {MODKEY, XK_g, setlayout, {.v = &layouts[3]}}, + // Spiral layout + {MODKEY, XK_r, setlayout, {.v = &layouts[4]}}, + // Dwindle layout + {MODKEY, XK_d, setlayout, {.v = &layouts[5]}}, + // Centerd master layout + {MODKEY, XK_c, setlayout, {.v = &layouts[6]}}, + // Centerd floating master layout + {MODKEY, XK_x, setlayout, {.v = &layouts[7]}}, + // Toggle between current layout and tile layout + {MODKEY, XK_s, setlayout, {0}}, + + // Toggle floating window + {MODKEY | Mod1Mask, XK_f, togglefloating, {0}}, + // View all tags + {MODKEY, XK_0, view, {.ui = ~0}}, + // Mirror the current tagg in all tags + {MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}}, + // I don't know + {MODKEY, XK_comma, focusmon, {.i = -1}}, + {MODKEY, XK_period, focusmon, {.i = +1}}, + {MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}}, + {MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}}, + /************************* Tag keys *************************/ + TAGKEYS(XK_1, 0) + TAGKEYS(XK_2, 1) + TAGKEYS(XK_3, 2) + TAGKEYS(XK_4, 3) + TAGKEYS(XK_5, 4) + TAGKEYS(XK_6, 5) + TAGKEYS(XK_7, 6) + TAGKEYS(XK_8, 7) + TAGKEYS(XK_9, 8) + TAGKEYS(XK_semicolon, 9) + /* ---------------------------------- Control Keys ---------------------------------- */ + // Brightness controllers (requires xbacklight) + {0, XF86XK_MonBrightnessUp, spawn, SHCMD("brightness up")}, + {0, XF86XK_MonBrightnessDown, spawn, SHCMD("brightness down")}, + // Sound controllers (requires pamixer) + {0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume-control up")}, + {0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume-control down")}, + {0, XF86XK_AudioMute, spawn, SHCMD("volume-control mute")}, + // Media controls (requires playerctl) + {0, XF86XK_AudioPlay, spawn, SHCMD("playerctl play-pause")}, + {0, XF86XK_AudioStop, spawn, SHCMD("playerctl stop")}, + {0, XF86XK_AudioNext, spawn, SHCMD("playerctl next")}, + {0, XF86XK_AudioPrev, spawn, SHCMD("playerctl previous")}, + + {Mod1Mask, XK_F1, spawn, SHCMD("playerctl volume 0.0")}, + {Mod1Mask, XK_F2, spawn, SHCMD("playerctl volume 0.1-")}, + {Mod1Mask, XK_F3, spawn, SHCMD("playerctl volume 0.1+")}, + // Mute and unmute mic + {0, XF86XK_AudioMicMute, spawn, SHCMD("pactl set-source-mute @DEFAULT_SOURCE@ toggle")}, + // Take a screenshot + {0, XK_Print, spawn, SHCMD("~/take-screenshot")}, + {Mod1Mask, XK_Print, spawn, SHCMD("take-screenshot --region")}, + {Mod2Mask, XK_Print, spawn, SHCMD("take-screenshot --activewindow")}, + {Mod1Mask | Mod2Mask, XK_Print, spawn, SHCMD("take-screenshot --fullscreen --background --copy-image")}, + /* ---------------------------------- lock Keys ---------------------------------- */ + // Lock the screen + {MODKEY | ShiftMask, XK_x, spawn, SHCMD("betterlockscreen -l dim")}, + // // Kill dwm (super + shift + alt + q) + // { MODKEY|ShiftMask|Mod1Mask, XK_q, quit, {0} }, +}; + + diff --git a/src/keys/keys.h b/src/keys/keys.h new file mode 100644 index 0000000..f8ae274 --- /dev/null +++ b/src/keys/keys.h @@ -0,0 +1,30 @@ +#ifndef KEYS_H +#define KEYS_H + +#include "../archy_dwm.h" +#include + +typedef struct { + unsigned int mod; + KeySym keysym; + + void (*func)(const Arg *); + + const Arg arg; +} Key; + +/* key definitions */ +#define MODKEY Mod1Mask // The alt key + +#define TAGKEYS(KEY, TAG) \ + {MODKEY, KEY, view, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, \ + {MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, \ + {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, + +// Include all the key bindings +#ifndef KEYS_C +#include "keys.c" +#endif + +#endif // keys_H diff --git a/src/config/mouse.h b/src/keys/mouse.c similarity index 71% rename from src/config/mouse.h rename to src/keys/mouse.c index 6c1e890..f28961d 100644 --- a/src/config/mouse.h +++ b/src/keys/mouse.c @@ -2,25 +2,8 @@ // Created by anas on 10/31/22. // -#ifndef MOUSE_H -#define MOUSE_H - -#include - -typedef struct { - unsigned int click; - unsigned int mask; - unsigned int button; - - void (*func)(const Arg *arg); - - const Arg arg; -} Button; - -enum { - ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast -}; /* clicks */ +#include "mouse.h" +#include "keys.h" /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ @@ -28,6 +11,7 @@ static Button buttons[] = { /* click event mask button function argument */ {ClkTagBar, MODKEY, Button1, tag, {0}}, {ClkTagBar, MODKEY, Button3, toggletag, {0}}, + {ClkStatusText, 0, Button2, spawn, {.v = termcmd}}, {ClkClientWin, MODKEY, Button1, movemouse, {0}}, {ClkClientWin, MODKEY, Button2, togglefloating, {0}}, {ClkClientWin, MODKEY, Button3, resizemouse, {0}}, @@ -36,5 +20,3 @@ static Button buttons[] = { {ClkTagBar, MODKEY, Button1, tag, {0}}, {ClkTagBar, MODKEY, Button3, toggletag, {0}}, }; - -#endif //MOUSE_H diff --git a/src/keys/mouse.h b/src/keys/mouse.h new file mode 100644 index 0000000..75c4c58 --- /dev/null +++ b/src/keys/mouse.h @@ -0,0 +1,29 @@ +// +// Created by anas on 10/31/22. +// + +#ifndef MOUSE_H +#define MOUSE_H + +#include + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + + void (*func)(const Arg *arg); + + const Arg arg; +} Button; + +enum { + ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast +}; /* clicks */ + +#ifndef MOUSE_C +#include "mouse.c" +#endif + +#endif //MOUSE_H