sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit b409ecdb13dfb458b65f1008508847d86eafde34
parent fbeee4715f7c5bf34206ce5aeb13ab6fa6d07ff3
Author: Philippe Gras <philippe.gras@free.fr>
Date:   Sun, 16 Feb 2014 18:56:54 +0100

Merge branch 'master' of git://git.suckless.org/sites

Diffstat:
Mdwm.suckless.org/dwmstatus/index.md | 1-
Ddwm.suckless.org/dwmstatus/p1c0-dwmstatus-volume.c | 232-------------------------------------------------------------------------------
Mdwm.suckless.org/index.md | 2+-
Mdwm.suckless.org/patches/attachabove.md | 3++-
Adwm.suckless.org/patches/center.md | 18++++++++++++++++++
Adwm.suckless.org/patches/cfacts.md | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-gaps.diff | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-keycode.diff | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-pango.diff | 285+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-stacker.diff | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-xtile-gaps.diff | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.0-xtile.diff | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-attachabove.diff | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-cfacts.diff | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-dwmfifo.diff | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-float_border_color2.diff | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-gaplessgrid.diff | 43+++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-maximize_vert_horz.diff | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-moveresize.diff | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-pertag.diff | 206+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-push.diff | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-runorraise.diff | 41+++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-save_floats.diff | 47+++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-single_tagset.diff | 567+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-single_window_no_border.diff | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-statusallmons.diff | 44++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-swapfocus.diff | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/dwm-6.1-systray.diff | 211+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Adwm.suckless.org/patches/dwm-6.1-tagall.diff | 33+++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-6.1-zoomswap.diff | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwm-cdec978-center.diff | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/dwmfifo.md | 38++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/float_border_color.md | 3++-
Mdwm.suckless.org/patches/gapless_grid.md | 1+
Adwm.suckless.org/patches/gaps.md | 27+++++++++++++++++++++++++++
Adwm.suckless.org/patches/keycode.md | 12++++++++++++
Mdwm.suckless.org/patches/maximize.md | 7++-----
Mdwm.suckless.org/patches/moveresize.md | 1+
Mdwm.suckless.org/patches/noborder.md | 3++-
Adwm.suckless.org/patches/pango.md | 40++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/pertag.md | 1+
Mdwm.suckless.org/patches/push.md | 4++--
Adwm.suckless.org/patches/runorraise.md | 35+++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/save_floats.md | 3++-
Mdwm.suckless.org/patches/single_tagset.md | 7++++---
Adwm.suckless.org/patches/stacker.md | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/statusallmons.md | 3++-
Mdwm.suckless.org/patches/swapfocus.md | 3++-
Mdwm.suckless.org/patches/systray.md | 4++--
Mdwm.suckless.org/patches/tagall.md | 3++-
Adwm.suckless.org/patches/xtile.md | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.suckless.org/patches/zoomswap.md | 3++-
Ast.suckless.org/patches/externalpipe.md | 38++++++++++++++++++++++++++++++++++++++
Ast.suckless.org/patches/st-0.4.1-externalpipe.diff | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msta.li/faq.md | 4++--
Msta.li/filesystem.md | 1-
Msta.li/index.md | 4++--
Msta.li/sandbox.md | 2+-
Msta.li/technologies.md | 8+++++++-
Msuckless.org/index.md | 4++++
Msuckless.org/other_projects.md | 2++
Asuckless.org/people/Sin.md | 7+++++++
Msuckless.org/rocks.md | 4----
Dsurf.suckless.org/patches/fullscreen.md | 18------------------
Asurf.suckless.org/patches/smoothscrolling-via-GTK3.md | 18++++++++++++++++++
Asurf.suckless.org/patches/surf-0.6-smoothscrolling.diff | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtools.suckless.org/slock.md -> tools.suckless.org/slock/index.md | 0
Atools.suckless.org/slock/patches/failcolor.md | 17+++++++++++++++++
Atools.suckless.org/slock/patches/slock-1.1-failcolor.diff | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools.suckless.org/tabbed/index.md | 2+-
Atools.suckless.org/tabbed/patches/clientnumber.md | 12++++++++++++
Mtools.suckless.org/tabbed/patches/index.md | 14+++++++-------
Atools.suckless.org/tabbed/patches/keycode.md | 12++++++++++++
Atools.suckless.org/tabbed/patches/tabbed-0.6-clientnumber.diff | 36++++++++++++++++++++++++++++++++++++
Atools.suckless.org/tabbed/patches/tabbed-0.6-keycode.diff | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
75 files changed, 4295 insertions(+), 375 deletions(-)

diff --git a/dwm.suckless.org/dwmstatus/index.md b/dwm.suckless.org/dwmstatus/index.md @@ -21,7 +21,6 @@ Please add your own version of dwmstatus here. * [dwmsd](https://github.com/johnko/dwmsd) - a daemon that listens on localhost tcp (may be useful as a base for asynchronous updates) * [profil-dwmstatus-1.0.c](profil-dwmstatus-1.0.c) - cpufreq, battery percent and date/time -* [p1c0-dwmstatus-volume.c](p1c0-dwmstatus-volume.c) - volume percentage & bar display * [suspend-statusbar.c](suspend-statusbar.c) - loadavg, wifi, battery and date. If battery goes below threshold - run suspend command diff --git a/dwm.suckless.org/dwmstatus/p1c0-dwmstatus-volume.c b/dwm.suckless.org/dwmstatus/p1c0-dwmstatus-volume.c @@ -1,232 +0,0 @@ -/* made by p1c0 2013-1-23. -** -** Compile with: -** gcc -Wall -pedantic -std=c99 status.c -lX11 -** -** Notes: -** bind volume keys in dwm config.h -** -** static const char *volup[] = { "dwmstatus", "volume", "up", NULL}; -** static const char *voldown[] = { "dwmstatus", "volume", "down", NULL}; -** -** static Key keys[] = { -** { 0, XF86XK_AudioRaiseVolume, spawn, {.v = volup } }, -** { 0, XF86XK_AudioLowerVolume, spawn, {.v = voldown } }, -** //{ MODKEY, XK_F11, spawn, {.v = voldown } }, -** //{ MODKEY, XK_F12, spawn, {.v = volup } }, -** }; -*/ - -#define _BSD_SOURCE -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <strings.h> -#include <sys/time.h> -#include <time.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include <X11/Xlib.h> - -char *tzargentina = "America/Buenos_Aires"; -char *tzutc = "UTC"; -char *tzberlin = "Europe/Berlin"; -char *tzla = "America/Los_Angeles"; - -static Display *dpy; - -char * -smprintf(char *fmt, ...) -{ - va_list fmtargs; - char *ret; - int len; - - va_start(fmtargs, fmt); - len = vsnprintf(NULL, 0, fmt, fmtargs); - va_end(fmtargs); - - ret = malloc(++len); - if (ret == NULL) { - perror("malloc"); - exit(1); - } - - va_start(fmtargs, fmt); - vsnprintf(ret, len, fmt, fmtargs); - va_end(fmtargs); - - return ret; -} - -void -settz(char *tzname) -{ - setenv("TZ", tzname, 1); -} - -char * -mktimes(char *fmt, char *tzname) -{ - char buf[129]; - time_t tim; - struct tm *timtm; - - memset(buf, 0, sizeof(buf)); - settz(tzname); - tim = time(NULL); - timtm = localtime(&tim); - if (timtm == NULL) { - perror("localtime"); - exit(1); - } - - if (!strftime(buf, sizeof(buf)-1, fmt, timtm)) { - fprintf(stderr, "strftime == 0\n"); - exit(1); - } - - return smprintf("%s", buf); -} - -void -setstatus(char *str) -{ - XStoreName(dpy, DefaultRootWindow(dpy), str); - XSync(dpy, False); -} - -char * -loadavg(void) -{ - double avgs[3]; - - if (getloadavg(avgs, 3) < 0) { - perror("getloadavg"); - exit(1); - } - - return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]); -} - -char* -runcmd(char* cmd) { - FILE* fp = popen(cmd, "r"); - if (fp == NULL) return NULL; - char ln[30]; - fgets(ln, sizeof(ln)-1, fp); - pclose(fp); - ln[strlen(ln)-1]='\0'; - return smprintf("%s", ln); -} - -int -getvolume() { - int volume; - sscanf(runcmd("amixer | grep -A 6 PCM | grep 'Front Left: Playback'\ - | grep -o '[0-9%]*%'"), "%i%%", &volume); - return volume; -} - -void -setvolume(int percent) { - char volcmd[32]; - sprintf(volcmd, "amixer set PCM %i%%", percent); - system(volcmd); -} - -char* -mkprogressbar(unsigned int size, unsigned int percent) { - unsigned int num = ((size-2)*percent)/100; - char *bar = malloc(size+1); - if (bar == NULL) { - perror("malloc"); - exit(1); - } - bar[0] = '['; - for (int i = 1; i < num+1; i++) { - bar[i] = '*'; - } - for (int i = num+1; i < size-1; i++) { - bar[i] = ' '; - } - bar[size-1] = ']'; - bar[size] = '\0'; - return bar; -} - -int -main(int argc, char *argv[]) -{ - char *status; - char *avgs; - char *tla; - int volume; - char *volumebar; - - if (!(dpy = XOpenDisplay(NULL))) { - fprintf(stderr, "dwmstatus: cannot open display.\n"); - return 1; - } - - if (argc > 1) { - if (strcmp(argv[1], "volume") == 0) { - if (strcmp(argv[2], "up") == 0) { - volume = getvolume(); - if (volume < 100) - volume += 5; - setvolume(volume); - volumebar = mkprogressbar(22, volume); - avgs = loadavg(); - tla = mktimes("%H:%M", tzla); - status = smprintf("%i%% %s | %s | %s", - volume, volumebar, avgs, tla); - setstatus(status); - free(avgs); - free(tla); - free(volumebar); - free(status); - exit(0); - } else if (strcmp(argv[2], "down") == 0) { - volume = getvolume(); - if (volume > 0) - volume -= 5; - setvolume(volume); - volumebar = mkprogressbar(22, volume); - avgs = loadavg(); - tla = mktimes("%H:%M", tzla); - status = smprintf("%i%% %s | %s | %s", - volume, volumebar, avgs, tla); - setstatus(status); - free(avgs); - free(tla); - free(volumebar); - free(status); - exit(0); - } - } - exit(0); - } - - for (;;sleep(90)) { - avgs = loadavg(); - tla = mktimes("%H:%M", tzla); - volume = getvolume(); - volumebar = mkprogressbar(22, volume); - status = smprintf("%i%% %s | %s | %s", - volume, volumebar, avgs, tla); - setstatus(status); - free(avgs); - free(tla); - free(volumebar); - free(status); - } - - XCloseDisplay(dpy); - - return 0; -} - diff --git a/dwm.suckless.org/index.md b/dwm.suckless.org/index.md @@ -99,6 +99,6 @@ Related discussion * <http://www.halbmoendli.ch/blog/archive/2007/03/31/dwm-dynamic-window-manager.html> * <http://peterstuifzand.nl/20060816212719.html> * <http://forums.debian.net/viewtopic.php?f=16&t=65110> -* <http://www.wongdev.com/blog/2013/01/24/dwm-tags-are-not-workspaces/> +* <http://wongdev.com/blog/dwm-tags-are-not-workspaces/> * [dwm usage and configuration page (french)](http://yeuxdelibad.net/Logiciel-libre/Suckless/dwm/index.html) diff --git a/dwm.suckless.org/patches/attachabove.md b/dwm.suckless.org/patches/attachabove.md @@ -9,8 +9,9 @@ always becoming the new master) - basically how Xmonad does it. Download -------- Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-attachabove.diff](dwm-6.1-attachabove.diff) (1786b) (20140209) * [dwm-10e232f9ace7-attachabove.diff](dwm-10e232f9ace7-attachabove.diff) (1709b) (20120406) * [dwm-6.0-attachabove.diff](dwm-6.0-attachabove.diff) (1707b) (20120406) * [dwm-5.6.1-attachabove.diff](dwm-5.6.1-attachabove.diff) (1.1K) (20090817) diff --git a/dwm.suckless.org/patches/center.md b/dwm.suckless.org/patches/center.md @@ -0,0 +1,18 @@ +center +====== + +Description +----------- + +Adds an "iscentered" rule to automatically center clients on the current +monitor. + +Download +-------- + +* [dwm-cdec978-center.diff](dwm-cdec978-center.diff) (2k) (20140123) + +Author +------ + +* [Chris Down](https://chrisdown.name) (cdown) <chris@chrisdown.name> diff --git a/dwm.suckless.org/patches/cfacts.md b/dwm.suckless.org/patches/cfacts.md @@ -0,0 +1,56 @@ +ctags +===== + +Description +----------- + +This patch provides the ability to assign different weights to +clients in their respective stack in tiled layout. It implements +a new function setcfact which will modify the cfact-value for the +currently selected client. It accepts the following values: + +* A positive float to increase a clients weight, thus increasing + the space the client is allocated in its current stack. + +* A negative float to decrease a clients weight, thus decreasing + the space the client is allocated in its current stack. + +* A zero-value float to reset a clients weight to default. + +Default cfact-value for each client is 1.0. If a client is +assigned a cfact value of 0.5 it will be allocated half of the +space other clients would be allocated. If a client is assigned a +cfact value of 2.0 it will be allocated twice the space other +clients would be allocated. + +The following illustrates the behavior. The clients cfact-values +are represented by floats inside the clients rectangles. + + +---------------------+ + | | 0.5 | + | 1.0 +----------+ + +----------+ | + | | 1.0 | + | +----------+ + | 2.0 | | + | | 1.0 | + +----------+----------+ + +Default key bindings +-------------------- + + Key | Argument | Description +:---------:|:----------:|:---------------- + `Mod-H` | `+0.25` | Increase cfact + `Mod-L` | `-0.25` | Decrease cfact + `Mod-O` | ` 0.00` | Reset cfact + +Download +-------- + +* [dwm-6.1-cfacts.diff](dwm-6.1-cfacts.diff) + +Author +------ + +* Patrick Steinhardt (pks) <ps@pks.im> diff --git a/dwm.suckless.org/patches/dwm-6.0-gaps.diff b/dwm.suckless.org/patches/dwm-6.0-gaps.diff @@ -0,0 +1,53 @@ +diff --git a/config.def.h b/config.def.h +index 77ff358..a4e496b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -9,6 +9,7 @@ static const char selbordercolor[] = "#005577"; + static const char selbgcolor[] = "#005577"; + static const char selfgcolor[] = "#eeeeee"; + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappx = 1; /* gap pixel between windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const Bool showbar = True; /* False means no bar */ + static const Bool topbar = True; /* False means bottom bar */ +diff --git a/dwm.c b/dwm.c +index 1d78655..6cc96ff 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1703,7 +1703,7 @@ textnw(const char *text, unsigned int len) { + + void + tile(Monitor *m) { +- unsigned int i, n, h, mw, my, ty; ++ unsigned int i, n, h, r, g = 0, mw, my, ty; + Client *c; + + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +@@ -1711,19 +1711,21 @@ tile(Monitor *m) { + return; + + if(n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; ++ mw = m->nmaster ? (m->ww - (g = gappx)) * m->mfact : 0; + else + mw = m->ww; + for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if(i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); ++ r = MIN(n, m->nmaster) - i; ++ h = (m->wh - my - gappx * (r - 1)) / r; + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); +- my += HEIGHT(c); ++ my += HEIGHT(c) + gappx; + } + else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); +- ty += HEIGHT(c); ++ r = n - i; ++ h = (m->wh - ty - gappx * (r - 1)) / r; ++ resize(c, m->wx + mw + g, m->wy + ty, m->ww - mw - g - (2*c->bw), h - (2*c->bw), False); ++ ty += HEIGHT(c) + gappx; + } + } + diff --git a/dwm.suckless.org/patches/dwm-6.0-keycode.diff b/dwm.suckless.org/patches/dwm-6.0-keycode.diff @@ -0,0 +1,133 @@ +diff --git a/config.def.h b/config.def.h +index 875885b..2ef8679 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -55,40 +55,40 @@ static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb + static const char *termcmd[] = { "st", NULL }; + + static Key keys[] = { +- /* modifier key function argument */ +- { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, +- { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, +- { MODKEY, XK_i, incnmaster, {.i = +1 } }, +- { MODKEY, XK_d, incnmaster, {.i = -1 } }, +- { MODKEY, XK_h, setmfact, {.f = -0.05} }, +- { MODKEY, XK_l, setmfact, {.f = +0.05} }, +- { MODKEY, XK_Return, zoom, {0} }, +- { MODKEY, XK_Tab, view, {0} }, +- { MODKEY|ShiftMask, XK_c, killclient, {0} }, +- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XK_space, setlayout, {0} }, +- { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, +- { MODKEY, XK_0, view, {.ui = ~0 } }, +- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, +- { 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 } }, +- 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) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ /* modifier key function argument */ ++ { MODKEY, 33, spawn, {.v = dmenucmd } }, // p ++ { MODKEY|ShiftMask, 36, spawn, {.v = termcmd } }, // Return ++ { MODKEY, 56, togglebar, {0} }, // b ++ { MODKEY, 44, focusstack, {.i = +1 } }, // j ++ { MODKEY, 45, focusstack, {.i = -1 } }, // k ++ { MODKEY, 31, incnmaster, {.i = +1 } }, // i ++ { MODKEY, 40, incnmaster, {.i = -1 } }, // d ++ { MODKEY, 43, setmfact, {.f = -0.05} }, // h ++ { MODKEY, 46, setmfact, {.f = +0.05} }, // l ++ { MODKEY, 36, zoom, {0} }, // Return ++ { MODKEY, 23, view, {0} }, // Tab ++ { MODKEY|ShiftMask, 54, killclient, {0} }, // c ++ { MODKEY, 28, setlayout, {.v = &layouts[0]} }, // t ++ { MODKEY, 41, setlayout, {.v = &layouts[1]} }, // f ++ { MODKEY, 58, setlayout, {.v = &layouts[2]} }, // m ++ { MODKEY, 65, setlayout, {0} }, // space ++ { MODKEY|ShiftMask, 65, togglefloating, {0} }, // space ++ { MODKEY, 19, view, {.ui = ~0 } }, // 0 ++ { MODKEY|ShiftMask, 19, tag, {.ui = ~0 } }, // 0 ++ { MODKEY, 59, focusmon, {.i = -1 } }, // comma ++ { MODKEY, 60, focusmon, {.i = +1 } }, // period ++ { MODKEY|ShiftMask, 59, tagmon, {.i = -1 } }, // comma ++ { MODKEY|ShiftMask, 60, tagmon, {.i = +1 } }, // period ++ TAGKEYS( 10, 0) // 1 ++ TAGKEYS( 11, 1) // 2 ++ TAGKEYS( 12, 2) // 3 ++ TAGKEYS( 13, 3) // 4 ++ TAGKEYS( 14, 4) // 5 ++ TAGKEYS( 15, 5) // 6 ++ TAGKEYS( 16, 6) // 7 ++ TAGKEYS( 17, 7) // 8 ++ TAGKEYS( 18, 8) // 9 ++ { MODKEY|ShiftMask, 24, quit, {0} }, // q + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 1bbb4b3..54ddf00 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -31,7 +31,6 @@ + #include <sys/types.h> + #include <sys/wait.h> + #include <X11/cursorfont.h> +-#include <X11/keysym.h> + #include <X11/Xatom.h> + #include <X11/Xlib.h> + #include <X11/Xproto.h> +@@ -100,7 +99,7 @@ struct Client { + + typedef struct { + unsigned int mod; +- KeySym keysym; ++ KeyCode keycode; + void (*func)(const Arg *); + const Arg arg; + } Key; +@@ -945,14 +944,12 @@ grabkeys(void) { + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; +- KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for(i = 0; i < LENGTH(keys); i++) +- if((code = XKeysymToKeycode(dpy, keys[i].keysym))) +- for(j = 0; j < LENGTH(modifiers); j++) +- XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, +- True, GrabModeAsync, GrabModeAsync); ++ for(j = 0; j < LENGTH(modifiers); j++) ++ XGrabKey(dpy, keys[i].keycode, keys[i].mod | modifiers[j], root, ++ True, GrabModeAsync, GrabModeAsync); + } + } + +@@ -976,13 +973,11 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { + void + keypress(XEvent *e) { + unsigned int i; +- KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; +- keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for(i = 0; i < LENGTH(keys); i++) +- if(keysym == keys[i].keysym ++ if(ev->keycode == keys[i].keycode + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); diff --git a/dwm.suckless.org/patches/dwm-6.0-pango.diff b/dwm.suckless.org/patches/dwm-6.0-pango.diff @@ -0,0 +1,285 @@ +diff --git a/config.def.h b/config.def.h +index 77ff358..3bee2e7 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -1,7 +1,7 @@ + /* See LICENSE file for copyright and license details. */ + + /* appearance */ +-static const char font[] = "-*-terminus-medium-r-*-*-16-*-*-*-*-*-*-*"; ++static const char font[] = "Sans 8"; + static const char normbordercolor[] = "#444444"; + static const char normbgcolor[] = "#222222"; + static const char normfgcolor[] = "#bbbbbb"; +@@ -12,6 +12,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const Bool showbar = True; /* False means no bar */ + static const Bool topbar = True; /* False means bottom bar */ ++static const Bool statusmarkup = True; /* True means use pango markup in status message */ + + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +diff --git a/config.mk b/config.mk +index 484554a..cdfb642 100644 +--- a/config.mk ++++ b/config.mk +@@ -15,8 +15,8 @@ XINERAMALIBS = -L${X11LIB} -lXinerama + XINERAMAFLAGS = -DXINERAMA + + # includes and libs +-INCS = -I. -I/usr/include -I${X11INC} +-LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} ++INCS = -I. -I/usr/include -I${X11INC} `pkg-config --cflags xft pango pangoxft` ++LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs xft pango pangoxft` + + # flags + CPPFLAGS = -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index 1d78655..4e73727 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -36,6 +36,9 @@ + #include <X11/Xlib.h> + #include <X11/Xproto.h> + #include <X11/Xutil.h> ++#include <X11/Xft/Xft.h> ++#include <pango/pango.h> ++#include <pango/pangoxft.h> + #ifdef XINERAMA + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ +@@ -47,8 +50,12 @@ + * 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 LENGTH(X) (sizeof X / sizeof X[0]) ++#ifndef MAX + #define MAX(A, B) ((A) > (B) ? (A) : (B)) ++#endif ++#ifndef MIN + #define MIN(A, B) ((A) < (B) ? (A) : (B)) ++#endif + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) +@@ -104,11 +111,15 @@ typedef struct { + Drawable drawable; + GC gc; + struct { ++ XftColor norm[ColLast]; ++ XftColor sel[ColLast]; ++ XftDraw *drawable; ++ } xft; ++ struct { + int ascent; + int descent; + int height; +- XFontSet set; +- XFontStruct *xfont; ++ PangoLayout *layout; + } font; + } DC; /* draw context */ + +@@ -186,7 +197,7 @@ static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); +-static unsigned long getcolor(const char *colstr); ++static unsigned long getcolor(const char *colstr, XftColor *color); + static Bool getrootptr(int *x, int *y); + static long getstate(Window w); + static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); +@@ -254,7 +265,7 @@ static void zoom(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +-static char stext[256]; ++static char stext[512]; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +@@ -479,18 +490,21 @@ cleanup(void) { + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; ++ int i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for(m = mons; m; m = m->next) + while(m->stack) + unmanage(m->stack, False); +- if(dc.font.set) +- XFreeFontSet(dpy, dc.font.set); +- else +- XFreeFont(dpy, dc.font.xfont); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XFreePixmap(dpy, dc.drawable); ++ for(i = ColBorder; i < ColLast; i++) { ++ XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), dc.xft.norm + i); ++ XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), dc.xft.sel + i); ++ } ++ XftDrawDestroy(dc.xft.drawable); ++ g_object_unref(dc.font.layout); + XFreeGC(dpy, dc.gc); + XFreeCursor(dpy, cursor[CurNormal]); + XFreeCursor(dpy, cursor[CurResize]); +@@ -581,6 +595,7 @@ configurenotify(XEvent *e) { + if(dc.drawable != 0) + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); ++ XftDrawChange(dc.xft.drawable, dc.drawable); + updatebars(); + for(m = mons; m; m = m->next) + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); +@@ -796,20 +811,25 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { + return; + olen = strlen(text); + h = dc.font.ascent + dc.font.descent; +- y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; ++ y = dc.y + (dc.h / 2) - (h / 2); + x = dc.x + (h / 2); +- /* shorten text if necessary */ ++ /* shorten text if necessary (this could wreak havoc with pango markup but fortunately ++ dc.w is adjusted to the width of the status text and not the other way around) */ + for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--); + if(!len) + return; + memcpy(buf, text, len); + if(len < olen) + for(i = len; i && i > len - 3; buf[--i] = '.'); +- XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); +- if(dc.font.set) +- XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); ++ if(text == stext && statusmarkup) ++ pango_layout_set_markup(dc.font.layout, buf, len); + else +- XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); ++ pango_layout_set_text(dc.font.layout, buf, len); ++ pango_xft_render_layout(dc.xft.drawable, ++ (col == dc.norm ? dc.xft.norm : dc.xft.sel) + (invert ? ColBG : ColFG), ++ dc.font.layout, x * PANGO_SCALE, y * PANGO_SCALE); ++ if(text == stext && statusmarkup) /* clear markup attributes */ ++ pango_layout_set_attributes(dc.font.layout, NULL); + } + + void +@@ -927,13 +947,13 @@ getatomprop(Client *c, Atom prop) { + } + + unsigned long +-getcolor(const char *colstr) { ++getcolor(const char *colstr, XftColor *color) { + Colormap cmap = DefaultColormap(dpy, screen); +- XColor color; ++ Visual *vis = DefaultVisual(dpy, screen); + +- if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) ++ if(!XftColorAllocName(dpy, vis, cmap, colstr, color)) + die("error, cannot allocate color '%s'\n", colstr); +- return color.pixel; ++ return color->pixel; + } + + Bool +@@ -1034,36 +1054,24 @@ incnmaster(const Arg *arg) { + + void + initfont(const char *fontstr) { +- char *def, **missing; +- int n; +- +- dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); +- if(missing) { +- while(n--) +- fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]); +- XFreeStringList(missing); +- } +- if(dc.font.set) { +- XFontStruct **xfonts; +- char **font_names; +- +- dc.font.ascent = dc.font.descent = 0; +- XExtentsOfFontSet(dc.font.set); +- n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); +- while(n--) { +- dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); +- dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); +- xfonts++; +- } +- } +- else { +- if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) +- && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) +- die("error, cannot load font: '%s'\n", fontstr); +- dc.font.ascent = dc.font.xfont->ascent; +- dc.font.descent = dc.font.xfont->descent; +- } ++ PangoFontMap *fontmap; ++ PangoContext *context; ++ PangoFontDescription *desc; ++ PangoFontMetrics *metrics; ++ ++ fontmap = pango_xft_get_font_map(dpy, screen); ++ context = pango_font_map_create_context(fontmap); ++ desc = pango_font_description_from_string(fontstr); ++ dc.font.layout = pango_layout_new(context); ++ pango_layout_set_font_description(dc.font.layout, desc); ++ ++ metrics = pango_context_get_metrics(context, desc, NULL); ++ dc.font.ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; ++ dc.font.descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE; + dc.font.height = dc.font.ascent + dc.font.descent; ++ ++ pango_font_metrics_unref(metrics); ++ g_object_unref(context); + } + + #ifdef XINERAMA +@@ -1612,17 +1620,16 @@ setup(void) { + cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); + cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); + /* init appearance */ +- dc.norm[ColBorder] = getcolor(normbordercolor); +- dc.norm[ColBG] = getcolor(normbgcolor); +- dc.norm[ColFG] = getcolor(normfgcolor); +- dc.sel[ColBorder] = getcolor(selbordercolor); +- dc.sel[ColBG] = getcolor(selbgcolor); +- dc.sel[ColFG] = getcolor(selfgcolor); ++ dc.norm[ColBorder] = getcolor(normbordercolor, dc.xft.norm + ColBorder); ++ dc.norm[ColBG] = getcolor(normbgcolor, dc.xft.norm + ColBG); ++ dc.norm[ColFG] = getcolor(normfgcolor, dc.xft.norm + ColFG); ++ dc.sel[ColBorder] = getcolor(selbordercolor, dc.xft.sel + ColBorder); ++ dc.sel[ColBG] = getcolor(selbgcolor, dc.xft.sel + ColBG); ++ dc.sel[ColFG] = getcolor(selfgcolor, dc.xft.sel + ColFG); + dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen)); ++ dc.xft.drawable = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); + dc.gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); +- if(!dc.font.set) +- XSetFont(dpy, dc.gc, dc.font.xfont->fid); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1692,13 +1699,15 @@ tagmon(const Arg *arg) { + + int + textnw(const char *text, unsigned int len) { +- XRectangle r; +- +- if(dc.font.set) { +- XmbTextExtents(dc.font.set, text, len, NULL, &r); +- return r.width; +- } +- return XTextWidth(dc.font.xfont, text, len); ++ PangoRectangle r; ++ if(text == stext && statusmarkup) ++ pango_layout_set_markup(dc.font.layout, text, len); ++ else ++ pango_layout_set_text(dc.font.layout, text, len); ++ pango_layout_get_extents(dc.font.layout, 0, &r); ++ if(text == stext && statusmarkup) /* clear markup attributes */ ++ pango_layout_set_attributes(dc.font.layout, NULL); ++ return r.width / PANGO_SCALE; + } + + void diff --git a/dwm.suckless.org/patches/dwm-6.0-stacker.diff b/dwm.suckless.org/patches/dwm-6.0-stacker.diff @@ -0,0 +1,187 @@ +diff --git a/config.def.h b/config.def.h +index 77ff358..566e0c7 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -41,6 +41,14 @@ static const Layout layouts[] = { + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, ++#define STACKKEYS(MOD,ACTION) \ ++ { MOD, XK_j, ACTION##stack, {.i = INC(+1) } }, \ ++ { MOD, XK_k, ACTION##stack, {.i = INC(-1) } }, \ ++ { MOD, XK_grave, ACTION##stack, {.i = PREVSEL } }, \ ++ { MOD, XK_q, ACTION##stack, {.i = 0 } }, \ ++ { MOD, XK_a, ACTION##stack, {.i = 1 } }, \ ++ { MOD, XK_z, ACTION##stack, {.i = 2 } }, \ ++ { MOD, XK_x, ACTION##stack, {.i = -1 } }, + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +@@ -54,8 +62,8 @@ static Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, ++ STACKKEYS(MODKEY, focus) ++ STACKKEYS(MODKEY|ShiftMask, push) + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, +@@ -83,7 +91,7 @@ static Key keys[] = { + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ShiftMask, XK_BackSpace, quit, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 1d78655..6129f56 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -43,17 +43,23 @@ + /* macros */ + #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) ++#define GETINC(X) ((X) - 2000) ++#define INC(X) ((X) + 2000) + #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 ISINC(X) ((X) > 1000 && (X) < 3000) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) ++#define PREVSEL 3000 + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MAX(A, B) ((A) > (B) ? (A) : (B)) + #define MIN(A, B) ((A) < (B) ? (A) : (B)) ++#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) ++#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -205,6 +211,7 @@ static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); + static void pop(Client *); + static void propertynotify(XEvent *e); ++static void pushstack(const Arg *arg); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); + static void resize(Client *c, int x, int y, int w, int h, Bool interact); +@@ -224,6 +231,7 @@ static void setup(void); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static int stackpos(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static int textnw(const char *text, unsigned int len); +@@ -887,28 +895,16 @@ focusmon(const Arg *arg) { + + void + focusstack(const Arg *arg) { +- Client *c = NULL, *i; ++ int i = stackpos(arg); ++ Client *c, *p; + +- if(!selmon->sel) ++ if(i < 0) + return; +- if(arg->i > 0) { +- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); +- if(!c) +- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next); +- } +- else { +- for(i = selmon->clients; i != selmon->sel; i = i->next) +- if(ISVISIBLE(i)) +- c = i; +- if(!c) +- for(; i; i = i->next) +- if(ISVISIBLE(i)) +- c = i; +- } +- if(c) { +- focus(c); +- restack(selmon); +- } ++ ++ for(p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c)); ++ i -= ISVISIBLE(c) ? 1 : 0, p = c, c = c->next); ++ focus(c ? c : p); ++ restack(selmon); + } + + Atom +@@ -1324,6 +1320,29 @@ propertynotify(XEvent *e) { + } + + void ++pushstack(const Arg *arg) { ++ int i = stackpos(arg); ++ Client *sel = selmon->sel, *c, *p; ++ ++ if(i < 0) ++ return; ++ else if(i == 0) { ++ detach(sel); ++ attach(sel); ++ } ++ else { ++ for(p = NULL, c = selmon->clients; c; p = c, c = c->next) ++ if(!(i -= (ISVISIBLE(c) && c != sel))) ++ break; ++ c = c ? c : p; ++ detach(sel); ++ sel->next = c->next; ++ c->next = sel; ++ } ++ arrange(selmon); ++} ++ ++void + quit(const Arg *arg) { + running = False; + } +@@ -1674,6 +1693,36 @@ spawn(const Arg *arg) { + } + } + ++int ++stackpos(const Arg *arg) { ++ int n, i; ++ Client *c, *l; ++ ++ if(!selmon->clients) ++ return -1; ++ ++ if(arg->i == PREVSEL) { ++ for(l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext); ++ if(!l) ++ return -1; ++ for(i = 0, c = selmon->clients; c != l; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return i; ++ } ++ else if(ISINC(arg->i)) { ++ if(!selmon->sel) ++ return -1; ++ for(i = 0, c = selmon->clients; c != selmon->sel; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ for(n = i; c; n += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return MOD(i + GETINC(arg->i), n); ++ } ++ else if(arg->i < 0) { ++ for(i = 0, c = selmon->clients; c; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return MAX(i + arg->i, 0); ++ } ++ else ++ return arg->i; ++} ++ + void + tag(const Arg *arg) { + if(selmon->sel && arg->ui & TAGMASK) { diff --git a/dwm.suckless.org/patches/dwm-6.0-xtile-gaps.diff b/dwm.suckless.org/patches/dwm-6.0-xtile-gaps.diff @@ -0,0 +1,60 @@ +diff --git a/config.def.h b/config.def.h +index ac895db..ef72871 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -9,6 +9,7 @@ static const char selbordercolor[] = "#005577"; + static const char selbgcolor[] = "#005577"; + static const char selfgcolor[] = "#eeeeee"; + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappx = 1; /* gap pixel between windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const Bool showbar = True; /* False means no bar */ + static const Bool topbar = True; /* False means bottom bar */ +diff --git a/dwm.c b/dwm.c +index 5dd2673..2c3268e 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1763,7 +1763,7 @@ void + tile(Monitor *m) { + Client *c; + Area *ga = m->pertag->areas[m->pertag->curtag], *ma = ga + 1, *sa = ga + 2, *a; +- unsigned int n, i, w, h, ms, ss; ++ unsigned int n, i, w, h, g, ms, ss; + float f; + + /* print layout symbols */ +@@ -1778,23 +1778,24 @@ tile(Monitor *m) { + ma->n = MIN(n, m->nmaster), sa->n = n - ma->n; + /* calculate area rectangles */ + f = ma->n == 0 ? 0 : (sa->n == 0 ? 1 : ga->fact / 2); ++ g = ma->n == 0 || sa->n == 0 ? 0 : gappx; + if(ga->dir == DirHor || ga->dir == DirRotHor) +- ms = f * m->ww, ss = m->ww - ms, +- ma->x = ga->dir == DirHor ? 0 : ss, ma->y = 0, ma->fx = ma->x + ms, ma->fy = m->wh, +- sa->x = ga->dir == DirHor ? ms : 0, sa->y = 0, sa->fx = sa->x + ss, sa->fy = m->wh; ++ ms = f * (m->ww - g), ss = m->ww - ms - g, ++ ma->x = ga->dir == DirHor ? 0 : ss + g, ma->y = 0, ma->fx = ma->x + ms, ma->fy = m->wh, ++ sa->x = ga->dir == DirHor ? ms + g: 0, sa->y = 0, sa->fx = sa->x + ss, sa->fy = m->wh; + else +- ms = f * m->wh, ss = m->wh - ms, +- ma->x = 0, ma->y = ga->dir == DirVer ? 0 : ss, ma->fx = m->ww, ma->fy = ma->y + ms, +- sa->x = 0, sa->y = ga->dir == DirVer ? ms : 0, sa->fx = m->ww, sa->fy = sa->y + ss; ++ ms = f * (m->wh - g), ss = m->wh - ms - g, ++ ma->x = 0, ma->y = ga->dir == DirVer ? 0 : ss + g, ma->fx = m->ww, ma->fy = ma->y + ms, ++ sa->x = 0, sa->y = ga->dir == DirVer ? ms + g : 0, sa->fx = m->ww, sa->fy = sa->y + ss; + /* tile clients */ + for(c = nexttiled(m->clients), i = 0; i < n; c = nexttiled(c->next), i++) { + a = ma->n > 0 ? ma : sa; + f = i == 0 || ma->n == 0 ? a->fact : 1, f /= --a->n + f; +- w = (a->dir == DirVer ? 1 : f) * (a->fx - a->x); +- h = (a->dir == DirHor ? 1 : f) * (a->fy - a->y); ++ w = a->dir == DirVer ? a->fx - a->x : f * (a->fx - a->x - a->n * gappx); ++ h = a->dir == DirHor ? a->fy - a->y : f * (a->fy - a->y - a->n * gappx);; + resize(c, m->wx + a->x, m->wy + a->y, w - 2 * c->bw, h - 2 * c->bw, False); +- a->x += a->dir == DirHor ? w : 0; +- a->y += a->dir == DirVer ? h : 0; ++ a->x += a->dir == DirHor ? w + gappx : 0; ++ a->y += a->dir == DirVer ? h + gappx : 0; + } + } + diff --git a/dwm.suckless.org/patches/dwm-6.0-xtile.diff b/dwm.suckless.org/patches/dwm-6.0-xtile.diff @@ -0,0 +1,298 @@ +diff --git a/config.def.h b/config.def.h +index 77ff358..ac895db 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -23,7 +23,8 @@ static const Rule rules[] = { + }; + + /* layout(s) */ +-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ ++static const int dirs[3] = { DirHor, DirVer, DirVer }; /* tiling dirs */ ++static const float facts[3] = { 1.1, 1.1, 1.1 }; /* tiling facts */ + static const int nmaster = 1; /* number of clients in master area */ + static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ + +@@ -41,6 +42,10 @@ static const Layout layouts[] = { + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, ++#define TILEKEYS(MOD,G,M,S) \ ++ { MOD, XK_r, setdirs, {.v = (int[]) { INC(G * +1), INC(M * +1), INC(S * +1) } } }, \ ++ { MOD, XK_h, setfacts, {.v = (float[]){ INC(G * -0.1), INC(M * -0.1), INC(S * -0.1) } } }, \ ++ { MOD, XK_l, setfacts, {.v = (float[]){ INC(G * +0.1), INC(M * +0.1), INC(S * +0.1) } } }, + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +@@ -58,8 +63,6 @@ static Key keys[] = { + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, +- { MODKEY, XK_h, setmfact, {.f = -0.05} }, +- { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +@@ -67,6 +70,12 @@ static Key keys[] = { + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, ++ TILEKEYS(MODKEY, 1, 0, 0) ++ TILEKEYS(MODKEY|ShiftMask, 0, 1, 0) ++ TILEKEYS(MODKEY|ControlMask, 0, 0, 1) ++ TILEKEYS(MODKEY|ShiftMask|ControlMask, 1, 1, 1) ++ { MODKEY|ShiftMask, XK_t, setdirs, {.v = (int[]){ DirHor, DirVer, DirVer } } }, ++ { MODKEY|ControlMask, XK_t, setdirs, {.v = (int[]){ DirVer, DirHor, DirHor } } }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index c9ad1f2..9cae5b5 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -43,17 +43,22 @@ + /* macros */ + #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) ++#define GETINC(X) ((X) - 2000) ++#define INC(X) ((X) + 2000) + #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 ISINC(X) ((X) > 1000 && (X) < 3000) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MAX(A, B) ((A) > (B) ? (A) : (B)) + #define MIN(A, B) ((A) < (B) ? (A) : (B)) ++#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) ++#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -64,6 +69,7 @@ enum { NetSupported, NetWMName, NetWMState, + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ ++enum { DirHor, DirVer, DirRotHor, DirRotVer, DirLast }; /* tiling dirs */ + + typedef union { + int i; +@@ -73,6 +79,11 @@ typedef union { + } Arg; + + typedef struct { ++ unsigned int x, y, fx, fy, n, dir; ++ float fact; ++} Area; ++ ++typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; +@@ -127,7 +138,6 @@ typedef struct { + typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; +- float mfact; + int nmaster; + int num; + int by; /* bar geometry */ +@@ -218,10 +228,11 @@ static void scan(void); + static Bool sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); ++static void setdirs(const Arg *arg); ++static void setfacts(const Arg *arg); + static void setfocus(Client *c); + static void setfullscreen(Client *c, Bool fullscreen); + static void setlayout(const Arg *arg); +-static void setmfact(const Arg *arg); + static void setup(void); + static void showhide(Client *c); + static void sigchld(int unused); +@@ -292,7 +303,7 @@ static Window root; + 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 */ ++ Area areas[LENGTH(tags) + 1][3]; /* tiling areas */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ +@@ -543,6 +554,7 @@ void + clientmessage(XEvent *e) { + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); ++ int i; + + if(!c) + return; +@@ -553,8 +565,8 @@ clientmessage(XEvent *e) { + } + else if(cme->message_type == netatom[NetActiveWindow]) { + if(!ISVISIBLE(c)) { +- c->mon->seltags ^= 1; +- c->mon->tagset[c->mon->seltags] = c->tags; ++ for(i=0; !(c->tags & 1 << i); i++); ++ view(&(Arg){.ui = 1 << i}); + } + pop(c); + } +@@ -657,12 +669,11 @@ configurerequest(XEvent *e) { + Monitor * + createmon(void) { + Monitor *m; +- int i; ++ int i, j; + + if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; +- m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; +@@ -676,8 +687,11 @@ createmon(void) { + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; + +- /* init mfacts */ +- m->pertag->mfacts[i] = m->mfact; ++ /* init tiling dirs and facts */ ++ for(j = 0; j < 3; j++) { ++ m->pertag->areas[i][j].dir = MIN(dirs[j], ((int[]){ 3, 1, 1 }[j])); ++ m->pertag->areas[i][j].fact = TRUNC(facts[j], 0.1, 10); ++ } + + /* init layouts */ + m->pertag->ltidxs[i][0] = m->lt[0]; +@@ -1524,6 +1538,31 @@ setclientstate(Client *c, long state) { + PropModeReplace, (unsigned char *)data, 2); + } + ++void ++setdirs(const Arg *arg) { ++ int *dirs = (int *)arg->v, i, n; ++ Area *areas = selmon->pertag->areas[selmon->pertag->curtag]; ++ ++ for(i = 0; i < 3; i++) { ++ n = (int[]){ 4, 2, 2 }[i]; ++ areas[i].dir = ISINC(dirs[i]) ? ++ MOD((int)areas[i].dir + GETINC(dirs[i]), n) : TRUNC(dirs[i], 0, n - 1); ++ } ++ arrange(selmon); ++} ++ ++void ++setfacts(const Arg *arg) { ++ float *facts = (float *)arg->v; ++ Area *areas = selmon->pertag->areas[selmon->pertag->curtag]; ++ int i; ++ ++ for(i = 0; i < 3; i++) ++ areas[i].fact = TRUNC(ISINC(facts[i]) ? ++ areas[i].fact + GETINC(facts[i]) : facts[i], 0.1, 10); ++ arrange(selmon); ++} ++ + Bool + sendevent(Client *c, Atom proto) { + int n; +@@ -1599,20 +1638,6 @@ setlayout(const Arg *arg) { + drawbar(selmon); + } + +-/* arg > 1.0 will set mfact absolutly */ +-void +-setmfact(const Arg *arg) { +- float f; +- +- if(!arg || !selmon->lt[selmon->sellt]->arrange) +- return; +- f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; +- if(f < 0.1 || f > 0.9) +- return; +- selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; +- arrange(selmon); +-} +- + void + setup(void) { + XSetWindowAttributes wa; +@@ -1736,28 +1761,41 @@ textnw(const char *text, unsigned int len) { + + void + tile(Monitor *m) { +- unsigned int i, n, h, mw, my, ty; + Client *c; ++ Area *ga = m->pertag->areas[m->pertag->curtag], *ma = ga + 1, *sa = ga + 2, *a; ++ unsigned int n, i, w, h, ms, ss; ++ float f; + ++ /* print layout symbols */ ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", ++ (char[]){ '<', '^', '>', 'v' }[ga->dir], ++ (char[]){ '-', '|' }[ma->dir], ++ (char[]){ '-', '|' }[sa->dir]); ++ /* calculate number of clients */ + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if(n == 0) + return; +- +- if(n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; ++ ma->n = MIN(n, m->nmaster), sa->n = n - ma->n; ++ /* calculate area rectangles */ ++ f = ma->n == 0 ? 0 : (sa->n == 0 ? 1 : ga->fact / 2); ++ if(ga->dir == DirHor || ga->dir == DirRotHor) ++ ms = f * m->ww, ss = m->ww - ms, ++ ma->x = ga->dir == DirHor ? 0 : ss, ma->y = 0, ma->fx = ma->x + ms, ma->fy = m->wh, ++ sa->x = ga->dir == DirHor ? ms : 0, sa->y = 0, sa->fx = sa->x + ss, sa->fy = m->wh; + else +- mw = m->ww; +- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if(i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); +- my += HEIGHT(c); +- } +- else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); +- ty += HEIGHT(c); +- } ++ ms = f * m->wh, ss = m->wh - ms, ++ ma->x = 0, ma->y = ga->dir == DirVer ? 0 : ss, ma->fx = m->ww, ma->fy = ma->y + ms, ++ sa->x = 0, sa->y = ga->dir == DirVer ? ms : 0, sa->fx = m->ww, sa->fy = sa->y + ss; ++ /* tile clients */ ++ for(c = nexttiled(m->clients), i = 0; i < n; c = nexttiled(c->next), i++) { ++ a = ma->n > 0 ? ma : sa; ++ f = i == 0 || ma->n == 0 ? a->fact : 1, f /= --a->n + f; ++ w = (a->dir == DirVer ? 1 : f) * (a->fx - a->x); ++ h = (a->dir == DirHor ? 1 : f) * (a->fy - a->y); ++ resize(c, m->wx + a->x, m->wy + a->y, w - 2 * c->bw, h - 2 * c->bw, False); ++ a->x += a->dir == DirHor ? w : 0; ++ a->y += a->dir == DirVer ? h : 0; ++ } + } + + void +@@ -1813,7 +1851,6 @@ toggleview(const Arg *arg) { + + /* 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]; +@@ -2117,7 +2154,6 @@ view(const Arg *arg) { + 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]; diff --git a/dwm.suckless.org/patches/dwm-6.1-attachabove.diff b/dwm.suckless.org/patches/dwm-6.1-attachabove.diff @@ -0,0 +1,64 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/attachabove +attachabove makes new clients attach above the selected client (instead of +always becoming the new master) – basically how Xmonad does it. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:20.560117200 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:20.552117200 +0100 +@@ -146,6 +146,7 @@ + static void arrange(Monitor *m); + static void arrangemon(Monitor *m); + static void attach(Client *c); ++static void attachabove(Client *c); + static void attachstack(Client *c); + static void buttonpress(XEvent *e); + static void checkotherwm(void); +@@ -401,6 +402,19 @@ + } + + void ++attachabove(Client *c) { ++ if(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating) { ++ attach(c); ++ return; ++ } ++ ++ Client *at; ++ for(at = c->mon->clients; at->next != c->mon->sel; at = at->next); ++ c->next = at->next; ++ at->next = c; ++} ++ ++void + attachstack(Client *c) { + c->snext = c->mon->stack; + c->mon->stack = c; +@@ -1051,7 +1065,7 @@ + c->isfloating = c->oldstate = trans != None || c->isfixed; + if(c->isfloating) + XRaiseWindow(dpy, c->win); +- attach(c); ++ attachabove(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +@@ -1383,7 +1397,7 @@ + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ +- attach(c); ++ attachabove(c); + attachstack(c); + focus(NULL); + arrange(NULL); +@@ -1818,7 +1832,7 @@ + m->clients = c->next; + detachstack(c); + c->mon = mons; +- attach(c); ++ attachabove(c); + attachstack(c); + } + if(m == selmon) diff --git a/dwm.suckless.org/patches/dwm-6.1-cfacts.diff b/dwm.suckless.org/patches/dwm-6.1-cfacts.diff @@ -0,0 +1,102 @@ +diff --git a/config.def.h b/config.def.h +index 875885b..809788b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -65,6 +65,9 @@ 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_h, setcfact, {.f = +0.25} }, ++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, ++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +diff --git a/dwm.c b/dwm.c +index 1bbb4b3..4ff74cc 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -86,6 +86,7 @@ typedef struct Client Client; + struct Client { + char name[256]; + float mina, maxa; ++ float cfact; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; +@@ -200,6 +201,7 @@ static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, Bool fullscreen); + static void setlayout(const Arg *arg); ++static void setcfact(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); + static void showhide(Client *c); +@@ -1027,6 +1029,7 @@ manage(Window w, XWindowAttributes *wa) { + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; ++ c->cfact = 1.0; + + if(c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); +@@ -1473,6 +1476,23 @@ setlayout(const Arg *arg) { + drawbar(selmon); + } + ++void setcfact(const Arg *arg) { ++ float f; ++ Client *c; ++ ++ c = selmon->sel; ++ ++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ f = arg->f + c->cfact; ++ if(arg->f == 0.0) ++ f = 1.0; ++ else if(f < 0.25 || f > 4.0) ++ return; ++ c->cfact = f; ++ arrange(selmon); ++} ++ + /* arg > 1.0 will set mfact absolutly */ + void + setmfact(const Arg *arg) { +@@ -1602,9 +1622,15 @@ tagmon(const Arg *arg) { + void + tile(Monitor *m) { + unsigned int i, n, h, mw, my, ty; ++ float mfacts = 0, sfacts = 0; + Client *c; + +- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { ++ if(n < m->nmaster) ++ mfacts += c->cfact; ++ else ++ sfacts += c->cfact; ++ } + if(n == 0) + return; + +@@ -1614,14 +1640,16 @@ tile(Monitor *m) { + mw = m->ww; + for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if(i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); ++ h = (m->wh - my) * (c->cfact / mfacts); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); + my += HEIGHT(c); ++ mfacts -= c->cfact; + } + else { +- h = (m->wh - ty) / (n - i); ++ h = (m->wh - ty) * (c->cfact / sfacts); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); + ty += HEIGHT(c); ++ sfacts -= c->cfact; + } + } + diff --git a/dwm.suckless.org/patches/dwm-6.1-dwmfifo.diff b/dwm.suckless.org/patches/dwm-6.1-dwmfifo.diff @@ -0,0 +1,215 @@ +diff --git a/config.def.h b/config.def.h +index 875885b..c0a01fa 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -108,3 +108,65 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ++static const char *dwmfifo = "/tmp/dwm.fifo"; ++static Command commands[] = { ++ { "dmenu", spawn, {.v = dmenucmd} }, ++ { "term", spawn, {.v = termcmd} }, ++ { "togglebar", togglebar, {0} }, ++ { "focusstack+", focusstack, {.i = +1} }, ++ { "focusstack-", focusstack, {.i = -1} }, ++ { "incnmaster+", incnmaster, {.i = +1} }, ++ { "incnmaster-", incnmaster, {.i = -1} }, ++ { "setmfact+", setmfact, {.f = +0.05} }, ++ { "setmfact-", setmfact, {.f = -0.05} }, ++ { "zoom", zoom, {0} }, ++ { "view", view, {0} }, ++ { "killclient", killclient, {0} }, ++ { "setlayout-tiled", setlayout, {.v = &layouts[0]} }, ++ { "setlayout-float", setlayout, {.v = &layouts[1]} }, ++ { "setlayout-mono", setlayout, {.v = &layouts[2]} }, ++ { "togglelayout", setlayout, {0} }, ++ { "togglefloating", togglefloating, {0} }, ++ { "viewall", view, {.ui = ~0} }, ++ { "tag", tag, {.ui = ~0} }, ++ { "focusmon+", focusmon, {.i = +1} }, ++ { "focusmon-", focusmon, {.i = -1} }, ++ { "tagmon+", tagmon, {.i = +1} }, ++ { "tagmon-", tagmon, {.i = -1} }, ++ { "view1", view, {.ui = 1 << 0} }, ++ { "view2", view, {.ui = 1 << 1} }, ++ { "view3", view, {.ui = 1 << 2} }, ++ { "view4", view, {.ui = 1 << 3} }, ++ { "view5", view, {.ui = 1 << 4} }, ++ { "view6", view, {.ui = 1 << 5} }, ++ { "view7", view, {.ui = 1 << 6} }, ++ { "view8", view, {.ui = 1 << 7} }, ++ { "view9", view, {.ui = 1 << 8} }, ++ { "toggleview1", toggleview, {.ui = 1 << 0} }, ++ { "toggleview2", toggleview, {.ui = 1 << 1} }, ++ { "toggleview3", toggleview, {.ui = 1 << 2} }, ++ { "toggleview4", toggleview, {.ui = 1 << 3} }, ++ { "toggleview5", toggleview, {.ui = 1 << 4} }, ++ { "toggleview6", toggleview, {.ui = 1 << 5} }, ++ { "toggleview7", toggleview, {.ui = 1 << 6} }, ++ { "toggleview8", toggleview, {.ui = 1 << 7} }, ++ { "toggleview9", toggleview, {.ui = 1 << 8} }, ++ { "tag1", tag, {.ui = 1 << 0} }, ++ { "tag2", tag, {.ui = 1 << 1} }, ++ { "tag3", tag, {.ui = 1 << 2} }, ++ { "tag4", tag, {.ui = 1 << 3} }, ++ { "tag5", tag, {.ui = 1 << 4} }, ++ { "tag6", tag, {.ui = 1 << 5} }, ++ { "tag7", tag, {.ui = 1 << 6} }, ++ { "tag8", tag, {.ui = 1 << 7} }, ++ { "tag9", tag, {.ui = 1 << 8} }, ++ { "toggletag1", toggletag, {.ui = 1 << 0} }, ++ { "toggletag2", toggletag, {.ui = 1 << 1} }, ++ { "toggletag3", toggletag, {.ui = 1 << 2} }, ++ { "toggletag4", toggletag, {.ui = 1 << 3} }, ++ { "toggletag5", toggletag, {.ui = 1 << 4} }, ++ { "toggletag6", toggletag, {.ui = 1 << 5} }, ++ { "toggletag7", toggletag, {.ui = 1 << 6} }, ++ { "toggletag8", toggletag, {.ui = 1 << 7} }, ++ { "toggletag9", toggletag, {.ui = 1 << 8} }, ++}; +diff --git a/dwm.c b/dwm.c +index 1bbb4b3..cd7ddd1 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -21,6 +21,7 @@ + * To understand everything else, start reading main(). + */ + #include <errno.h> ++#include <fcntl.h> + #include <locale.h> + #include <stdarg.h> + #include <signal.h> +@@ -28,6 +29,8 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#include <sys/select.h> ++#include <sys/stat.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <X11/cursorfont.h> +@@ -140,6 +143,12 @@ typedef struct { + int monitor; + } Rule; + ++typedef struct { ++ const char *name; ++ void (*func)(const Arg *arg); ++ const Arg arg; ++} Command; ++ + /* function declarations */ + static void applyrules(Client *c); + static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); +@@ -161,9 +170,11 @@ static void destroynotify(XEvent *e); + static void detach(Client *c); + static void detachstack(Client *c); + static Monitor *dirtomon(int dir); ++static void dispatchcmd(void); + static void drawbar(Monitor *m); + static void drawbars(void); + static void enternotify(XEvent *e); ++static Bool evpredicate(); + static void expose(XEvent *e); + static void focus(Client *c); + static void focusin(XEvent *e); +@@ -266,6 +277,7 @@ static Drw *drw; + static Fnt *fnt; + static Monitor *mons, *selmon; + static Window root; ++static int fifofd; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -485,6 +497,7 @@ cleanup(void) { + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); ++ close(fifofd); + } + + void +@@ -691,6 +704,25 @@ dirtomon(int dir) { + } + + void ++dispatchcmd(void) ++{ ++ int i; ++ char buf[BUFSIZ]; ++ ssize_t n; ++ ++ n = read(fifofd, buf, sizeof(buf) - 1); ++ if (n == -1) ++ die("Failed to read from DWM fifo\n"); ++ buf[n] = '\0'; ++ for (i = 0; i < LENGTH(commands); i++) { ++ if (strcmp(commands[i].name, buf) == 0) { ++ commands[i].func(&commands[i].arg); ++ break; ++ } ++ } ++} ++ ++void + drawbar(Monitor *m) { + int x, xx, w; + unsigned int i, occ = 0, urg = 0; +@@ -768,6 +800,12 @@ enternotify(XEvent *e) { + focus(c); + } + ++Bool ++evpredicate() ++{ ++ return True; ++} ++ + void + expose(XEvent *e) { + Monitor *m; +@@ -1341,11 +1379,30 @@ restack(Monitor *m) { + void + run(void) { + XEvent ev; ++ fd_set rfds; ++ int n; ++ int dpyfd, maxfd; + /* main event loop */ + XSync(dpy, False); +- while(running && !XNextEvent(dpy, &ev)) +- if(handler[ev.type]) +- handler[ev.type](&ev); /* call handler */ ++ dpyfd = ConnectionNumber(dpy); ++ maxfd = fifofd; ++ if (dpyfd > maxfd) ++ maxfd = dpyfd; ++ maxfd++; ++ while (running) { ++ FD_ZERO(&rfds); ++ FD_SET(fifofd, &rfds); ++ FD_SET(dpyfd, &rfds); ++ n = select(maxfd, &rfds, NULL, NULL, NULL); ++ if (n > 0) { ++ if (FD_ISSET(fifofd, &rfds)) ++ dispatchcmd(); ++ if (FD_ISSET(dpyfd, &rfds)) ++ while (XCheckIfEvent(dpy, &ev, evpredicate, NULL)) ++ if (handler[ev.type]) ++ handler[ev.type](&ev); /* call handler */ ++ } ++ } + } + + void +@@ -1543,6 +1600,9 @@ setup(void) { + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); ++ fifofd = open(dwmfifo, O_RDWR | O_NONBLOCK); ++ if (fifofd < 0) ++ die("Failed to open DWM fifo\n"); + } + + void diff --git a/dwm.suckless.org/patches/dwm-6.1-float_border_color2.diff b/dwm.suckless.org/patches/dwm-6.1-float_border_color2.diff @@ -0,0 +1,89 @@ +URL: http://dwm.suckless.org/patches/historical/float_border_color +float_border_color2 allows you to specify a different border color for floating +windows. + +Index: dwm/config.def.h +=================================================================== +--- dwm/config.def.h.orig 2014-02-09 15:24:13.708117011 +0100 ++++ dwm/config.def.h 2014-02-09 15:24:13.700117011 +0100 +@@ -8,6 +8,8 @@ + static const char selbordercolor[] = "#005577"; + static const char selbgcolor[] = "#005577"; + static const char selfgcolor[] = "#eeeeee"; ++static const char floatnormbordercolor[] = "#005577"; ++static const char floatselbordercolor[] = "#005577"; + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const Bool showbar = True; /* False means no bar */ +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:13.708117011 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:13.700117011 +0100 +@@ -792,7 +792,10 @@ + detachstack(c); + attachstack(c); + grabbuttons(c, True); +- XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel].floatborder->rgb); ++ else ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->rgb); + setfocus(c); + } + else { +@@ -1040,7 +1043,10 @@ + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +- XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm].floatborder->rgb); ++ else ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); +@@ -1051,6 +1057,8 @@ + c->isfloating = c->oldstate = trans != None || c->isfixed; + if(c->isfloating) + XRaiseWindow(dpy, c->win); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm].floatborder->rgb); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, +@@ -1522,9 +1530,11 @@ + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ ++ scheme[SchemeNorm].floatborder = drw_clr_create(drw, floatnormbordercolor); + scheme[SchemeNorm].border = drw_clr_create(drw, normbordercolor); + scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor); + scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor); ++ scheme[SchemeSel].floatborder = drw_clr_create(drw, floatselbordercolor); + scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor); + scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor); + scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor); +@@ -1641,6 +1651,10 @@ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if(selmon->sel->isfloating) ++ XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel].floatborder->rgb); ++ else ++ XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel].border->rgb); ++ if(selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, False); + arrange(selmon); +Index: dwm/drw.h +=================================================================== +--- dwm/drw.h.orig 2014-02-09 15:24:13.708117011 +0100 ++++ dwm/drw.h 2014-02-09 15:24:13.700117011 +0100 +@@ -20,6 +20,7 @@ + Clr *fg; + Clr *bg; + Clr *border; ++ Clr *floatborder; + } ClrScheme; + + typedef struct { diff --git a/dwm.suckless.org/patches/dwm-6.1-gaplessgrid.diff b/dwm.suckless.org/patches/dwm-6.1-gaplessgrid.diff @@ -0,0 +1,43 @@ +URL: http://dwm.suckless.org/patches/gapless_grid +Add gapless grid layout. + +Index: dwm/gaplessgrid.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/gaplessgrid.c 2014-02-09 15:24:17.132117105 +0100 +@@ -0,0 +1,35 @@ ++void ++gaplessgrid(Monitor *m) { ++ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ; ++ if(n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for(cols = 0; cols <= n/2; cols++) ++ if(cols*cols >= n) ++ break; ++ if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n/cols; ++ ++ /* window geometries */ ++ cw = cols ? m->ww / cols : m->ww; ++ cn = 0; /* current column number */ ++ rn = 0; /* current row number */ ++ for(i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { ++ if(i/rows + 1 > cols - n%cols) ++ rows = n/cols + 1; ++ ch = rows ? m->wh / rows : m->wh; ++ cx = m->wx + cn*cw; ++ cy = m->wy + rn*ch; ++ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False); ++ rn++; ++ if(rn >= rows) { ++ rn = 0; ++ cn++; ++ } ++ } ++} diff --git a/dwm.suckless.org/patches/dwm-6.1-maximize_vert_horz.diff b/dwm.suckless.org/patches/dwm-6.1-maximize_vert_horz.diff @@ -0,0 +1,77 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/historical/moveresize +These patches provide helper functions for moving and resizing floating windows +using keybindings. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:12.552116979 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:12.548116979 +0100 +@@ -91,7 +91,7 @@ + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ Bool ismax, wasfloating, isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; +@@ -1047,6 +1047,8 @@ + updatewmhints(c); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, False); ++ c->wasfloating = False; ++ c->ismax = False; + if(!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if(c->isfloating) +Index: dwm/maximize.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/maximize.c 2014-02-09 15:24:12.548116979 +0100 +@@ -0,0 +1,45 @@ ++void ++maximize(int x, int y, int w, int h) { ++ XEvent ev; ++ ++ if(!selmon->sel || selmon->sel->isfixed) ++ return; ++ XRaiseWindow(dpy, selmon->sel->win); ++ if(!selmon->sel->ismax) { ++ if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) ++ selmon->sel->wasfloating = True; ++ else { ++ togglefloating(NULL); ++ selmon->sel->wasfloating = False; ++ } ++ selmon->sel->oldx = selmon->sel->x; ++ selmon->sel->oldy = selmon->sel->y; ++ selmon->sel->oldw = selmon->sel->w; ++ selmon->sel->oldh = selmon->sel->h; ++ resize(selmon->sel, x, y, w, h, True); ++ selmon->sel->ismax = True; ++ } ++ else { ++ resize(selmon->sel, selmon->sel->oldx, selmon->sel->oldy, selmon->sel->oldw, selmon->sel->oldh, True); ++ if(!selmon->sel->wasfloating) ++ togglefloating(NULL); ++ selmon->sel->ismax = False; ++ } ++ drawbar(selmon); ++ while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); ++} ++ ++void ++togglemaximize(const Arg *arg) { ++ maximize(selmon->wx, selmon->wy, selmon->ww - 2 * borderpx, selmon->wh - 2 * borderpx); ++} ++ ++void ++toggleverticalmax(const Arg *arg) { ++ maximize(selmon->sel->x, selmon->wy, selmon->sel->w, selmon->wh - 2 * borderpx); ++} ++ ++void ++togglehorizontalmax(const Arg *arg) { ++ maximize(selmon->wx, selmon->sel->y, selmon->ww - 2 * borderpx, selmon->sel->h); ++} diff --git a/dwm.suckless.org/patches/dwm-6.1-moveresize.diff b/dwm.suckless.org/patches/dwm-6.1-moveresize.diff @@ -0,0 +1,74 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/historical/moveresize +These patches provide helper functions for moving and resizing floating windows +using keybindings. + +Index: dwm/moveresize.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/moveresize.c 2014-02-09 15:24:09.244116888 +0100 +@@ -0,0 +1,64 @@ ++void ++moveresize(const Arg *arg) { ++ /* only floating windows can be moved */ ++ Client *c; ++ c = selmon->sel; ++ int x, y, w, h, nx, ny, nw, nh, ox, oy, ow, oh; ++ char xAbs, yAbs, wAbs, hAbs; ++ int msx, msy, dx, dy, nmx, nmy; ++ unsigned int dui; ++ Window dummy; ++ ++ if (!c || !arg) ++ return; ++ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) ++ return; ++ if(sscanf((char *)arg->v, "%d%c %d%c %d%c %d%c", &x, &xAbs, &y, &yAbs, &w, &wAbs, &h, &hAbs) != 8) ++ return; ++ /* compute new window position; prevent window from be positioned outside the current monitor */ ++ nw = c->w + w; ++ if(wAbs == 'W') ++ nw = w < selmon->mw - 2 * c->bw ? w : selmon->mw - 2 * c->bw; ++ ++ nh = c->h + h; ++ if(hAbs == 'H') ++ nh = h < selmon->mh - 2 * c->bw ? h : selmon->mh - 2 * c->bw; ++ ++ nx = c->x + x; ++ if(xAbs == 'X') { ++ if(x < selmon->mx) ++ nx = selmon->mx; ++ else if(x > selmon->mx + selmon->mw) ++ nx = selmon->mx + selmon->mw - nw - 2 * c->bw; ++ else ++ nx = x; ++ } ++ ++ ny = c->y + y; ++ if(yAbs == 'Y') { ++ if(y < selmon->my) ++ ny = selmon->my; ++ else if(y > selmon->my + selmon->mh) ++ ny = selmon->my + selmon->mh - nh - 2 * c->bw; ++ else ++ ny = y; ++ } ++ ++ ox = c->x; ++ oy = c->y; ++ ow = c->w; ++ oh = c->h; ++ ++ XRaiseWindow(dpy, c->win); ++ Bool xqp = XQueryPointer(dpy, root, &dummy, &dummy, &msx, &msy, &dx, &dy, &dui); ++ resize(c, nx, ny, nw, nh, True); ++ ++ /* move cursor along with the window to avoid problems caused by the sloppy focus */ ++ if (xqp && ox <= msx && (ox + ow) >= msx && oy <= msy && (oy + oh) >= msy) ++ { ++ nmx = c->x - ox + c->w - ow; ++ nmy = c->y - oy + c->h - oh; ++ XWarpPointer(dpy, None, None, 0, 0, 0, 0, nmx, nmy); ++ } ++} ++ diff --git a/dwm.suckless.org/patches/dwm-6.1-pertag.diff b/dwm.suckless.org/patches/dwm-6.1-pertag.diff @@ -0,0 +1,206 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/pertag +This patch keeps layout, mwfact, barpos and nmaster per tag. + +Contributors: +- Carlos Pita, thanks for debugging NetActiveWindow issues and sending a patch + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:18.232117136 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:18.224117135 +0100 +@@ -110,6 +110,7 @@ + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -129,6 +130,7 @@ + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -270,6 +272,16 @@ + /* 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 */ ++ Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ ++ Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ ++}; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -518,6 +530,7 @@ + clientmessage(XEvent *e) { + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); ++ int i; + + if(!c) + return; +@@ -530,6 +543,8 @@ + if(!ISVISIBLE(c)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; ++ for(i=0; !(c->tags & 1 << i); i++); ++ view(&(Arg){.ui = 1 << i}); + } + pop(c); + } +@@ -631,6 +646,7 @@ + Monitor * + createmon(void) { + Monitor *m; ++ int i; + + if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); +@@ -642,6 +658,27 @@ + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ for(i=0; i <= LENGTH(tags); i++) { ++ /* init nmaster */ ++ m->pertag->nmasters[i] = m->nmaster; ++ ++ /* init mfacts */ ++ m->pertag->mfacts[i] = m->mfact; ++ ++ /* init layouts */ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ /* init showbar */ ++ m->pertag->showbars[i] = m->showbar; ++ ++ /* swap focus and zoomswap*/ ++ m->pertag->prevzooms[i] = NULL; ++ } + return m; + } + +@@ -958,7 +995,7 @@ + + 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); + } + +@@ -1462,10 +1499,13 @@ + + void + setlayout(const Arg *arg) { +- if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { ++ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ } + if(arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if(selmon->sel) + arrange(selmon); +@@ -1483,7 +1523,7 @@ + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if(f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1627,7 +1667,7 @@ + + 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); +@@ -1663,9 +1703,29 @@ + void + toggleview(const Arg *arg) { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if(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; ++ } + selmon->tagset[selmon->seltags] = newtagset; ++ ++ /* 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); + } +@@ -1960,11 +2020,33 @@ + + 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->pertag->prevtag = selmon->pertag->curtag; + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ 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/dwm.suckless.org/patches/dwm-6.1-push.diff b/dwm.suckless.org/patches/dwm-6.1-push.diff @@ -0,0 +1,66 @@ +URL: http://dwm.suckless.org/patches/push +pushup and pushdown provide a way to move clients inside the clients list. + +Index: dwm/push.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/push.c 2014-02-09 15:24:21.652117230 +0100 +@@ -0,0 +1,58 @@ ++static Client * ++prevtiled(Client *c) { ++ Client *p, *r; ++ ++ for(p = selmon->clients, r = NULL; p && p != c; p = p->next) ++ if(!p->isfloating && ISVISIBLE(p)) ++ r = p; ++ return r; ++} ++ ++static void ++pushup(const Arg *arg) { ++ Client *sel = selmon->sel; ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = prevtiled(sel))) { ++ /* attach before c */ ++ detach(sel); ++ sel->next = c; ++ if(selmon->clients == c) ++ selmon->clients = sel; ++ else { ++ for(c = selmon->clients; c->next != sel->next; c = c->next); ++ c->next = sel; ++ } ++ } else { ++ /* move to the end */ ++ for(c = sel; c->next; c = c->next); ++ detach(sel); ++ sel->next = NULL; ++ c->next = sel; ++ } ++ focus(sel); ++ arrange(selmon); ++} ++ ++static void ++pushdown(const Arg *arg) { ++ Client *sel = selmon->sel; ++ Client *c; ++ ++ if(!sel || sel->isfloating) ++ return; ++ if((c = nexttiled(sel->next))) { ++ /* attach after c */ ++ detach(sel); ++ sel->next = c->next; ++ c->next = sel; ++ } else { ++ /* move to the front */ ++ detach(sel); ++ attach(sel); ++ } ++ focus(sel); ++ arrange(selmon); ++} diff --git a/dwm.suckless.org/patches/dwm-6.1-runorraise.diff b/dwm.suckless.org/patches/dwm-6.1-runorraise.diff @@ -0,0 +1,41 @@ +--- dwm.c.orig 2013-11-29 13:58:49.673588564 +0100 ++++ dwm.c 2013-11-23 22:56:49.725007370 +0100 +@@ -193,6 +193,7 @@ + static void resizemouse(const Arg *arg); + static void restack(Monitor *m); + static void run(void); ++static void runorraise(const Arg *arg); + static void scan(void); + static Bool sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); +@@ -1349,6 +1350,30 @@ + } + + void ++runorraise(const Arg *arg) { ++ char *app = ((char **)arg->v)[4]; ++ Arg a = { .ui = ~0 }; ++ Monitor *mon; ++ Client *c; ++ XClassHint hint = { NULL, NULL }; ++ /* Tries to find the client */ ++ for (mon = mons; mon; mon = mon->next) { ++ for (c = mon->clients; c; c = c->next) { ++ XGetClassHint(dpy, c->win, &hint); ++ if (hint.res_class && strcmp(app, hint.res_class) == 0) { ++ a.ui = c->tags; ++ view(&a); ++ focus(c); ++ XRaiseWindow(dpy, c->win); ++ return; ++ } ++ } ++ } ++ /* Client not found: spawn it */ ++ spawn(arg); ++} ++ ++void + scan(void) { + unsigned int i, num; +} diff --git a/dwm.suckless.org/patches/dwm-6.1-save_floats.diff b/dwm.suckless.org/patches/dwm-6.1-save_floats.diff @@ -0,0 +1,47 @@ +URL: http://dwm.suckless.org/patches/historical/save_floats +This patch saves size and position of every floating window before it is forced +into tiled mode. If the window is made floating again, the old dimensions will +be restored. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:10.344116918 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:10.336116918 +0100 +@@ -87,6 +87,7 @@ + char name[256]; + float mina, maxa; + int x, y, w, h; ++ int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; +@@ -1045,6 +1046,10 @@ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); ++ c->sfx = c->x; ++ c->sfy = c->y; ++ c->sfw = c->w; ++ c->sfh = c->h; + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, False); + if(!c->isfloating) +@@ -1641,8 +1646,16 @@ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if(selmon->sel->isfloating) +- resize(selmon->sel, selmon->sel->x, selmon->sel->y, +- selmon->sel->w, selmon->sel->h, False); ++ /*restore last known float dimensions*/ ++ resize(selmon->sel, selmon->sel->sfx, selmon->sel->sfy, ++ selmon->sel->sfw, selmon->sel->sfh, False); ++ else { ++ /*save last known float dimensions*/ ++ selmon->sel->sfx = selmon->sel->x; ++ selmon->sel->sfy = selmon->sel->y; ++ selmon->sel->sfw = selmon->sel->w; ++ selmon->sel->sfh = selmon->sel->h; ++ } + arrange(selmon); + } + diff --git a/dwm.suckless.org/patches/dwm-6.1-single_tagset.diff b/dwm.suckless.org/patches/dwm-6.1-single_tagset.diff @@ -0,0 +1,567 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/single_tagset +This patch addresses the multi-monitor setup. Instead of having separate tags +for every monitor there is just one list of tags for all monitors. Instead of +moving windows from one monitor to the other, the desired tag from the +other monitor can just be selected and all windows will be drawn on the +current monitor. + +Several deep changes needed to be made: +1. Macro ISVISIBLE expects a second parameter, the monitor +2. Monitor->clients and Monitor->stack were moved to the global variable + Clientlist cl. All monitors refer to this one list. +3. A new method attachclients was added. When changing between tags this + function ensures that all clients are pointing to the right monitor. + +Please be aware that this patch probably breaks any other patch! + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:26.156117354 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:26.148117354 +0100 +@@ -48,7 +48,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, M) ((C->tags & M->tagset[M->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) +@@ -110,6 +110,7 @@ + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Clientlist Clientlist; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -123,9 +124,8 @@ + unsigned int tagset[2]; + Bool showbar; + Bool topbar; +- Client *clients; ++ Clientlist *cl; + Client *sel; +- Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +@@ -140,12 +140,18 @@ + int monitor; + } Rule; + ++struct Clientlist { ++ Client *clients; ++ Client *stack; ++}; ++ + /* function declarations */ + static void applyrules(Client *c); + static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); + static void arrange(Monitor *m); + static void arrangemon(Monitor *m); + static void attach(Client *c); ++static void attachclients(Monitor *m); + static void attachstack(Client *c); + static void buttonpress(XEvent *e); + static void checkotherwm(void); +@@ -183,7 +189,7 @@ + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); +-static Client *nexttiled(Client *c); ++static Client *nexttiled(Client *c, Monitor *m); + static void pop(Client *); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); +@@ -266,6 +272,7 @@ + static Fnt *fnt; + static Monitor *mons, *selmon; + static Window root; ++static Clientlist *cl; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -296,7 +303,7 @@ + { + c->isfloating = r->isfloating; + c->tags |= r->tags; +- for(m = mons; m && m->num != r->monitor; m = m->next); ++ for(m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next) ; + if(m) + c->mon = m; + } +@@ -377,9 +384,9 @@ + void + arrange(Monitor *m) { + if(m) +- showhide(m->stack); ++ showhide(m->cl->stack); + else for(m = mons; m; m = m->next) +- showhide(m->stack); ++ showhide(m->cl->stack); + if(m) { + arrangemon(m); + restack(m); +@@ -396,14 +403,47 @@ + + void + attach(Client *c) { +- c->next = c->mon->clients; +- c->mon->clients = c; ++ c->next = c->mon->cl->clients; ++ c->mon->cl->clients = c; ++} ++ ++void ++attachclients(Monitor *m) { ++ /* attach clients to the specified monitor */ ++ Monitor *tm; ++ Client *c; ++ unsigned int utags = 0; ++ Bool rmons = False; ++ if(!m) ++ return; ++ ++ /* collect information about the tags in use */ ++ for(tm = mons; tm; tm = tm->next) ++ if(tm != m) ++ utags |= m->tagset[m->seltags]; ++ ++ for(c = m->cl->clients; c; c = c->next) ++ if(ISVISIBLE(c, m)) { ++ /* if client is also visible on other tags that are displayed on ++ * other monitors, remove these tags */ ++ if(c->tags & utags) { ++ c->tags = c->tags & m->tagset[m->seltags]; ++ rmons = True; ++ } ++ unfocus(c, True); ++ c->mon = m; ++ } ++ ++ if(rmons) ++ for(tm = mons; tm; tm = tm->next) ++ if(tm != m) ++ arrange(tm); + } + + void + attachstack(Client *c) { +- c->snext = c->mon->stack; +- c->mon->stack = c; ++ c->snext = c->mon->cl->stack; ++ c->mon->cl->stack = c; + } + + void +@@ -466,8 +506,8 @@ + view(&a); + selmon->lt[selmon->sellt] = &foo; + for(m = mons; m; m = m->next) +- while(m->stack) +- unmanage(m->stack, False); ++ while(m->cl->stack) ++ unmanage(m->cl->stack, False); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while(mons) + cleanupmon(mons); +@@ -527,7 +567,7 @@ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } + else if(cme->message_type == netatom[NetActiveWindow]) { +- if(!ISVISIBLE(c)) { ++ if(!ISVISIBLE(c, c->mon)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; + } +@@ -609,7 +649,7 @@ + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); +- if(ISVISIBLE(c)) ++ if(ISVISIBLE(c, m)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } + else +@@ -630,11 +670,18 @@ + + Monitor * + createmon(void) { +- Monitor *m; ++ Monitor *m, *tm; ++ int i; + + if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); +- m->tagset[0] = m->tagset[1] = 1; ++ m->cl = cl; ++ /* reassing tags when creating a new monitor */ ++ for(i=1, tm = mons; tm; tm = tm->next, i++) { ++ tm->seltags ^= 1; ++ tm->tagset[tm->seltags] = i; ++ } ++ m->tagset[0] = m->tagset[1] = i; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; +@@ -658,7 +705,7 @@ + detach(Client *c) { + Client **tc; + +- for(tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); ++ for(tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + } + +@@ -666,11 +713,11 @@ + detachstack(Client *c) { + Client **tc, *t; + +- for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); ++ for(tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if(c == c->mon->sel) { +- for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); ++ for(t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext); + c->mon->sel = t; + } + } +@@ -696,7 +743,7 @@ + unsigned int i, occ = 0, urg = 0; + Client *c; + +- for(c = m->clients; c; c = c->next) { ++ for(c = m->cl->clients; c; c = c->next) { + occ |= c->tags; + if(c->isurgent) + urg |= c->tags; +@@ -779,8 +826,8 @@ + + void + focus(Client *c) { +- if(!c || !ISVISIBLE(c)) +- for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); ++ if(!c || !ISVISIBLE(c, selmon)) ++ for(c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext); + /* was if(selmon->sel) */ + if(selmon->sel && selmon->sel != c) + unfocus(selmon->sel, False); +@@ -832,17 +879,17 @@ + if(!selmon->sel) + return; + if(arg->i > 0) { +- for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); ++ for(c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next); + if(!c) +- for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next); ++ for(c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next); + } + else { +- for(i = selmon->clients; i != selmon->sel; i = i->next) +- if(ISVISIBLE(i)) ++ for(i = selmon->cl->clients; i != selmon->sel; i = i->next) ++ if(ISVISIBLE(i, selmon)) + c = i; + if(!c) + for(; i; i = i->next) +- if(ISVISIBLE(i)) ++ if(ISVISIBLE(i, selmon)) + c = i; + } + if(c) { +@@ -1092,12 +1139,12 @@ + unsigned int n = 0; + Client *c; + +- for(c = m->clients; c; c = c->next) +- if(ISVISIBLE(c)) ++ for(c = m->cl->clients; c; c = c->next) ++ if(ISVISIBLE(c, m)) + n++; + if(n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); +- for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) ++ for(c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); + } + +@@ -1175,8 +1222,8 @@ + } + + Client * +-nexttiled(Client *c) { +- for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); ++nexttiled(Client *c, Monitor *m) { ++ for(; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next); + return c; + } + +@@ -1328,8 +1375,8 @@ + if(m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; +- for(c = m->stack; c; c = c->snext) +- if(!c->isfloating && ISVISIBLE(c)) { ++ for(c = m->cl->stack; c; c = c->snext) ++ if(!c->isfloating && ISVISIBLE(c, m)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } +@@ -1379,7 +1426,6 @@ + if(c->mon == m) + return; + unfocus(c, True); +- detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ +@@ -1501,6 +1547,8 @@ + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + bh = fnt->h + 2; ++ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Clientlist)); + drw = drw_create(dpy, screen, root, sw, sh); + drw_setfont(drw, fnt); + updategeom(); +@@ -1549,9 +1597,11 @@ + showhide(Client *c) { + if(!c) + return; +- if(ISVISIBLE(c)) { /* show clients top down */ ++ if(ISVISIBLE(c, c->mon)) { /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) ++ if(c->isfloating) ++ keepfloatingposition(c); + resize(c, c->x, c->y, c->w, c->h, False); + showhide(c->snext); + } +@@ -1585,7 +1635,22 @@ + + void + tag(const Arg *arg) { ++ Monitor *m; ++ unsigned int newtags; + if(selmon->sel && arg->ui & TAGMASK) { ++ newtags = arg->ui & TAGMASK; ++ for(m = mons; m; m = m->next) ++ /* if tag is visible on another monitor, move client to the new monitor */ ++ if(m != selmon && m->tagset[m->seltags] & newtags) { ++ /* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */ ++ if(newtags & selmon->tagset[selmon->seltags]) ++ return; ++ selmon->sel->tags = newtags; ++ selmon->sel->mon = m; ++ arrange(m); ++ break; ++ } ++ /* workaround in case just one monitor is connected */ + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +@@ -1604,7 +1669,7 @@ + unsigned int i, n, h, mw, my, ty; + Client *c; + +- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ for(n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++); + if(n == 0) + return; + +@@ -1612,7 +1677,7 @@ + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; +- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ for(i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++) + if(i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); +@@ -1648,12 +1713,17 @@ + + void + toggletag(const Arg *arg) { ++ Monitor *m; + unsigned int newtags; + + if(!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if(newtags) { ++ /* prevent adding tags that are in use on other monitors */ ++ for(m = mons; m; m = m->next) ++ if(m != selmon && newtags & m->tagset[m->seltags]) ++ return; + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); +@@ -1662,9 +1732,14 @@ + + void + toggleview(const Arg *arg) { ++ Monitor *m; + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if(newtagset) { ++ /* prevent displaying the same tags on multiple monitors */ ++ for(m = mons; m; m = m->next) ++ if(m != selmon && newtagset & m->tagset[m->seltags]) ++ return; + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); +@@ -1703,6 +1778,7 @@ + XUngrabServer(dpy); + } + free(c); ++ attachclients(selmon); + focus(NULL); + updateclientlist(); + arrange(m); +@@ -1760,7 +1836,7 @@ + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for(m = mons; m; m = m->next) +- for(c = m->clients; c; c = c->next) ++ for(c = m->cl->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +@@ -1790,8 +1866,10 @@ + if(n <= nn) { + for(i = 0; i < (nn - n); i++) { /* new monitors available */ + for(m = mons; m && m->next; m = m->next); +- if(m) ++ if(m) { + m->next = createmon(); ++ attachclients(m->next); ++ } + else + mons = createmon(); + } +@@ -1812,17 +1890,13 @@ + else { /* less monitors available nn < n */ + for(i = nn; i < n; i++) { + for(m = mons; m && m->next; m = m->next); +- while(m->clients) { +- dirty = True; +- c = m->clients; +- m->clients = c->next; +- detachstack(c); +- c->mon = mons; +- attach(c); +- attachstack(c); +- } + if(m == selmon) + selmon = mons; ++ for(c = m->cl->clients; c; c = c->next) { ++ dirty = True; ++ if(c->mon == m) ++ c->mon = selmon; ++ } + cleanupmon(m); + } + } +@@ -1960,11 +2034,31 @@ + + void + view(const Arg *arg) { ++ Monitor *m; ++ unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1]; + if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; ++ ++ /* swap tags when trying to display a tag from another monitor */ ++ if(arg->ui & TAGMASK) ++ newtagset = arg->ui & TAGMASK; ++ for(m = mons; m; m = m->next) ++ if(m != selmon && newtagset & m->tagset[m->seltags]) { ++ /* prevent displaying all tags (MODKEY-0) when multiple monitors ++ * are connected */ ++ if(newtagset & selmon->tagset[selmon->seltags]) ++ return; ++ m->seltags ^= 1; ++ m->tagset[m->seltags] = selmon->tagset[selmon->seltags]; ++ attachclients(m); ++ arrange(m); ++ break; ++ } ++ + selmon->seltags ^= 1; /* toggle sel tagset */ + if(arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ attachclients(selmon); + focus(NULL); + arrange(selmon); + } +@@ -1975,7 +2069,7 @@ + Monitor *m; + + for(m = mons; m; m = m->next) +- for(c = m->clients; c; c = c->next) ++ for(c = m->cl->clients; c; c = c->next) + if(c->win == w) + return c; + return NULL; +@@ -2037,8 +2131,8 @@ + if(!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; +- if(c == nexttiled(selmon->clients)) +- if(!c || !(c = nexttiled(c->next))) ++ if(c == nexttiled(selmon->cl->clients, selmon)) ++ if(!c || !(c = nexttiled(c->next, selmon))) + return; + pop(c); + } +Index: dwm/config.def.h +=================================================================== +--- dwm/config.def.h.orig 2014-02-09 15:24:26.156117354 +0100 ++++ dwm/config.def.h 2014-02-09 15:24:26.148117354 +0100 +@@ -54,6 +54,7 @@ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++#include "keepfloatingposition.c" + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +Index: dwm/keepfloatingposition.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/keepfloatingposition.c 2014-02-09 15:24:26.148117354 +0100 +@@ -0,0 +1,30 @@ ++static void ++keepfloatingposition(Client *c) { ++ Monitor *m; ++ int cmmx = c->mon->mx; ++ int cmmy = c->mon->my; ++ int cmmw = c->mon->mw; ++ int cmmh = c->mon->mh; ++ int mmx, mmy; ++ if(!(cmmx <= c->x && ++ cmmx + cmmw - 1 >= c->x && ++ cmmy <= c->y && ++ cmmy + cmmh - 1 >= c->y)) ++ for(m = mons; m; m = m->next) { ++ mmx = m->mx; ++ mmy = m->my; ++ if(mmx <= c->x && ++ mmx + m->mw - 1 >= c->x && ++ mmy <= c->y && ++ mmy + m->mh - 1 >= c->y) { ++ c->x = c->x - mmx + cmmx; ++ c->y = c->y - mmy + cmmy; ++ if(c->x + c->w + 2 * c->bw > cmmx + cmmw - 1) ++ c->x -= c->x + c->w + 2 * c->bw - cmmx - cmmw; ++ if(c->y + c->h + 2 * c->bw > cmmy + cmmh - 1) ++ c->y -= c->y + c->h + 2 * c->bw - cmmy - cmmh; ++ resizeclient(c, c->x, c->y, c->w, c->h); ++ break; ++ } ++ } ++} diff --git a/dwm.suckless.org/patches/dwm-6.1-single_window_no_border.diff b/dwm.suckless.org/patches/dwm-6.1-single_window_no_border.diff @@ -0,0 +1,102 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/noborder +This patch removes the border when there is just one window visible in tiled or +monocle layout. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:19.404117168 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:19.396117168 +0100 +@@ -1089,7 +1089,7 @@ + + void + monocle(Monitor *m) { +- unsigned int n = 0; ++ unsigned int n = 0, r = 0; + Client *c; + + for(c = m->clients; c; c = c->next) +@@ -1097,8 +1097,17 @@ + n++; + if(n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); +- for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) +- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False); ++ for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) { ++ /* remove border when in monocle layout */ ++ if(c->bw) { ++ c->oldbw = c->bw; ++ c->bw = 0; ++ r = 1; ++ } ++ resize(c, m->wx, m->wy, m->ww - (2 * c->bw), m->wh - (2 * c->bw), False); ++ if(r) ++ resizeclient(c, m->wx, m->wy, m->ww - (2 * c->bw), m->wh - (2 * c->bw)); ++ } + } + + void +@@ -1601,7 +1610,7 @@ + + void + tile(Monitor *m) { +- unsigned int i, n, h, mw, my, ty; ++ unsigned int i, n, h, mw, my, ty, r; + Client *c; + + for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +@@ -1612,17 +1621,36 @@ + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww; +- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, r = 0) { ++ if(n == 1) { ++ if (c->bw) { ++ /* remove border when only one window is on the current tag */ ++ c->oldbw = c->bw; ++ c->bw = 0; ++ r = 1; ++ } ++ } ++ else if(!c->bw && c->oldbw) { ++ /* restore border when more than one window is displayed */ ++ c->bw = c->oldbw; ++ c->oldbw = 0; ++ r = 1; ++ } + if(i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); ++ if(r) ++ resizeclient(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw)); + my += HEIGHT(c); + } + else { + h = (m->wh - ty) / (n - i); + resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); ++ if(r) ++ resizeclient(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw)); + ty += HEIGHT(c); + } ++ } + } + + void +@@ -1640,9 +1668,15 @@ + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; +- if(selmon->sel->isfloating) ++ if(selmon->sel->isfloating) { ++ /* restore border when moving window into floating mode */ ++ if(!selmon->sel->bw && selmon->sel->oldbw) { ++ selmon->sel->bw = selmon->sel->oldbw; ++ selmon->sel->oldbw = 0; ++ } + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, False); ++ } + arrange(selmon); + } + diff --git a/dwm.suckless.org/patches/dwm-6.1-statusallmons.diff b/dwm.suckless.org/patches/dwm-6.1-statusallmons.diff @@ -0,0 +1,44 @@ +URL: http://dwm.suckless.org/patches/statusallmons +This patch draws and updates the statusbar on all monitors. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:22.768117261 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:22.764117260 +0100 +@@ -715,17 +715,13 @@ + drw_text(drw, x, 0, w, bh, m->ltsymbol, 0); + x += w; + xx = x; +- if(m == selmon) { /* status is only drawn on selected monitor */ +- w = TEXTW(stext); +- x = m->ww - w; +- if(x < xx) { +- x = xx; +- w = m->ww - xx; +- } +- drw_text(drw, x, 0, w, bh, stext, 0); ++ w = TEXTW(stext); ++ x = m->ww - w; ++ if(x < xx) { ++ x = xx; ++ w = m->ww - xx; + } +- else +- x = m->ww; ++ drw_text(drw, x, 0, w, bh, stext, 0); + if((w = x - xx) > bh) { + x = xx; + if(m->sel) { +@@ -1923,9 +1919,11 @@ + + void + updatestatus(void) { ++ Monitor* m; + if(!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); +- drawbar(selmon); ++ for(m = mons; m; m = m->next) ++ drawbar(m); + } + + void diff --git a/dwm.suckless.org/patches/dwm-6.1-swapfocus.diff b/dwm.suckless.org/patches/dwm-6.1-swapfocus.diff @@ -0,0 +1,66 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/swapfocus +This patch makes it possible to switch focus with one single shortcut (alt-s) +instead of having to think if you should use alt-j or alt-k for reaching the +last used window. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:14.868117043 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:14.864117043 +0100 +@@ -205,6 +205,7 @@ + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static void swapfocus(); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -234,6 +235,7 @@ + static void zoom(const Arg *arg); + + /* variables */ ++static Client *prevclient = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -1584,6 +1586,16 @@ + } + + void ++swapfocus(){ ++ Client *c; ++ for(c = selmon->clients; c && c != prevclient; c = c->next) ; ++ if(c == prevclient) { ++ focus(prevclient); ++ restack(prevclient->mon); ++ } ++} ++ ++void + tag(const Arg *arg) { + if(selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; +@@ -1675,6 +1687,7 @@ + unfocus(Client *c, Bool setfocus) { + if(!c) + return; ++ prevclient = c; + grabbuttons(c, False); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb); + if(setfocus) { +@@ -2033,12 +2046,13 @@ + void + zoom(const Arg *arg) { + Client *c = selmon->sel; ++ prevclient = nexttiled(selmon->clients); + + if(!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; + if(c == nexttiled(selmon->clients)) +- if(!c || !(c = nexttiled(c->next))) ++ if(!c || !(c = prevclient = nexttiled(c->next))) + return; + pop(c); + } diff --git a/dwm.suckless.org/patches/dwm-6.1-systray.diff b/dwm.suckless.org/patches/dwm-6.1-systray.diff @@ -1,28 +1,34 @@ -Author: Branislav Blaskovic <branislav@blaskovic.sk>, rewrited patch from Jan Christoph Ebersbach <jceb@e-jc.de> for DWM 6.1 +Author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus URL: http://dwm.suckless.org/patches/systray Implements a system tray for dwm. -diff --git a/config.def.h b/../dwm-suckless/config.def.h -index d300687..9da950f 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -10,6 +10,8 @@ static const char selbgcolor[] = "#005577"; +Contributors: +- Carlos Pita, thanks for investigating multi monitor issues and sending in a + patch + +Index: dwm/config.def.h +=================================================================== +--- dwm/config.def.h.orig 2014-02-09 15:24:27.348117387 +0100 ++++ dwm/config.def.h 2014-02-09 15:24:27.340117386 +0100 +@@ -10,6 +10,10 @@ static const char selfgcolor[] = "#eeeeee"; static const unsigned int borderpx = 1; /* border pixel of windows */ 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 systrayspacing = 2; /* systray spacing */ ++static const Bool systraypinningfailfirst = True; /* True: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ +static const Bool showsystray = True; /* False means no systray */ static const Bool showbar = True; /* False means no bar */ static const Bool topbar = True; /* False means bottom bar */ - -diff --git a/dwm.c b/../dwm-suckless/dwm.c -index 314adf4..24a0113 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -55,13 +55,30 @@ - #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:27.348117387 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:27.340117386 +0100 +@@ -56,12 +56,30 @@ #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h) + +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 + @@ -39,19 +45,21 @@ index 314adf4..24a0113 100644 +#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, SchemeLast }; /* color schemes */ -enum { NetSupported, NetWMName, NetWMState, -+enum { NetSupported, NetWMName, NetWMState, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +- NetWMFullscreen, NetActiveWindow, NetWMWindowType, +- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ ++enum { NetSupported, NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, ++ NetWMName, NetWMState, 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 */ -@@ -140,6 +157,12 @@ typedef struct { +@@ -140,6 +158,12 @@ int monitor; } Rule; @@ -64,7 +72,7 @@ index 314adf4..24a0113 100644 /* function declarations */ static void applyrules(Client *c); static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact); -@@ -169,8 +192,10 @@ static void focus(Client *c); +@@ -169,8 +193,10 @@ static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); @@ -75,7 +83,7 @@ index 314adf4..24a0113 100644 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, Bool focused); static void grabkeys(void); -@@ -188,13 +213,16 @@ static void pop(Client *); +@@ -188,13 +214,15 @@ static void propertynotify(XEvent *e); static void quit(const Arg *arg); static Monitor *recttomon(int x, int y, int w, int h); @@ -84,7 +92,6 @@ index 314adf4..24a0113 100644 +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); @@ -93,7 +100,15 @@ index 314adf4..24a0113 100644 static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); -@@ -222,18 +250,24 @@ static void updateclientlist(void); +@@ -205,6 +233,7 @@ + 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 *); +@@ -222,18 +251,24 @@ static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); @@ -118,11 +133,8 @@ index 314adf4..24a0113 100644 static const char broken[] = "broken"; static char stext[256]; static int screen; -@@ -255,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { - [MapRequest] = maprequest, - [MotionNotify] = motionnotify, +@@ -257,7 +292,7 @@ [PropertyNotify] = propertynotify, -+ [ResizeRequest] = resizerequest, [UnmapNotify] = unmapnotify }; -static Atom wmatom[WMLast], netatom[NetLast]; @@ -130,7 +142,7 @@ index 314adf4..24a0113 100644 static Bool running = True; static Cur *cursor[CurLast]; static ClrScheme scheme[SchemeLast]; -@@ -471,6 +506,11 @@ cleanup(void) { +@@ -471,6 +506,11 @@ XUngrabKey(dpy, AnyKey, AnyModifier, root); while(mons) cleanupmon(mons); @@ -142,7 +154,7 @@ index 314adf4..24a0113 100644 drw_cur_free(drw, cursor[CurNormal]); drw_cur_free(drw, cursor[CurResize]); drw_cur_free(drw, cursor[CurMove]); -@@ -516,9 +556,49 @@ clearurgent(Client *c) { +@@ -516,9 +556,49 @@ void clientmessage(XEvent *e) { @@ -174,15 +186,15 @@ index 314adf4..24a0113 100644 + XAddToSaveSet(dpy, c->win); + XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); + XReparentWindow(dpy, c->win, systray->win, 0, 0); -+ /* use parents background pixmap */ -+ swa.background_pixmap = ParentRelative; ++ /* use parents background color */ + swa.background_pixel = scheme[SchemeNorm].bg->rgb; -+ XChangeWindowAttributes(dpy, c->win, CWBackPixmap|CWBackPixel, &swa); ++ 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); @@ -192,7 +204,7 @@ index 314adf4..24a0113 100644 if(!c) return; if(cme->message_type == netatom[NetWMState]) { -@@ -568,7 +648,7 @@ configurenotify(XEvent *e) { +@@ -568,7 +648,7 @@ drw_resize(drw, sw, bh); updatebars(); for(m = mons; m; m = m->next) @@ -201,7 +213,7 @@ index 314adf4..24a0113 100644 focus(NULL); arrange(NULL); } -@@ -652,6 +732,11 @@ destroynotify(XEvent *e) { +@@ -652,6 +732,11 @@ if((c = wintoclient(ev->window))) unmanage(c, True); @@ -213,7 +225,7 @@ index 314adf4..24a0113 100644 } void -@@ -696,6 +781,7 @@ drawbar(Monitor *m) { +@@ -696,6 +781,7 @@ unsigned int i, occ = 0, urg = 0; Client *c; @@ -221,17 +233,17 @@ index 314adf4..24a0113 100644 for(c = m->clients; c; c = c->next) { occ |= c->tags; if(c->isurgent) -@@ -718,6 +804,9 @@ drawbar(Monitor *m) { +@@ -718,6 +804,9 @@ if(m == selmon) { /* status is only drawn on selected monitor */ w = TEXTW(stext); x = m->ww - w; -+ if(showsystray && m == selmon) { ++ if(showsystray && m == systraytomon(m)) { + x -= getsystraywidth(); + } if(x < xx) { x = xx; w = m->ww - xx; -@@ -747,6 +836,7 @@ drawbars(void) { +@@ -747,6 +836,7 @@ for(m = mons; m; m = m->next) drawbar(m); @@ -239,7 +251,20 @@ index 314adf4..24a0113 100644 } void -@@ -857,10 +947,17 @@ getatomprop(Client *c, Atom prop) { +@@ -773,8 +863,11 @@ + 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 +@@ -857,10 +950,17 @@ unsigned long dl; unsigned char *p = NULL; Atom da, atom = None; @@ -258,7 +283,7 @@ index 314adf4..24a0113 100644 XFree(p); } return atom; -@@ -892,6 +989,15 @@ getstate(Window w) { +@@ -892,6 +992,15 @@ return result; } @@ -274,7 +299,7 @@ index 314adf4..24a0113 100644 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size) { char **list = NULL; -@@ -992,7 +1098,7 @@ void +@@ -992,7 +1101,7 @@ killclient(const Arg *arg) { if(!selmon->sel) return; @@ -283,7 +308,7 @@ index 314adf4..24a0113 100644 XGrabServer(dpy); XSetErrorHandler(xerrordummy); XSetCloseDownMode(dpy, DestroyAll); -@@ -1078,6 +1184,12 @@ void +@@ -1078,6 +1187,12 @@ maprequest(XEvent *e) { static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; @@ -296,7 +321,7 @@ index 314adf4..24a0113 100644 if(!XGetWindowAttributes(dpy, ev->window, &wa)) return; -@@ -1194,6 +1306,16 @@ propertynotify(XEvent *e) { +@@ -1194,6 +1309,16 @@ Window trans; XPropertyEvent *ev = &e->xproperty; @@ -313,7 +338,7 @@ index 314adf4..24a0113 100644 if((ev->window == root) && (ev->atom == XA_WM_NAME)) updatestatus(); else if(ev->state == PropertyDelete) -@@ -1243,12 +1365,33 @@ recttomon(int x, int y, int w, int h) { +@@ -1243,12 +1368,33 @@ } void @@ -338,7 +363,7 @@ index 314adf4..24a0113 100644 void +resizebarwin(Monitor *m) { + unsigned int w = m->ww; -+ if(showsystray && m == selmon) ++ if(showsystray && m == systraytomon(m)) + w -= getsystraywidth(); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); +} @@ -347,26 +372,7 @@ index 314adf4..24a0113 100644 resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; -@@ -1315,6 +1458,18 @@ 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) { - Client *c; - XEvent ev; -@@ -1398,25 +1553,35 @@ setclientstate(Client *c, long state) { +@@ -1398,25 +1544,35 @@ } Bool @@ -413,7 +419,7 @@ index 314adf4..24a0113 100644 } return exists; } -@@ -1429,7 +1594,7 @@ setfocus(Client *c) { +@@ -1429,7 +1585,7 @@ XA_WINDOW, 32, PropModeReplace, (unsigned char *) &(c->win), 1); } @@ -422,7 +428,7 @@ index 314adf4..24a0113 100644 } void -@@ -1511,11 +1676,17 @@ setup(void) { +@@ -1511,12 +1667,18 @@ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); @@ -434,13 +440,14 @@ index 314adf4..24a0113 100644 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); + xatom[Manager] = XInternAtom(dpy, "MANAGER", False); + xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); + xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); - netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -@@ -1528,6 +1699,8 @@ setup(void) { + cursor[CurResize] = drw_cur_create(drw, XC_sizing); +@@ -1528,6 +1690,8 @@ scheme[SchemeSel].border = drw_clr_create(drw, selbordercolor); scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor); scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor); @@ -449,7 +456,30 @@ index 314adf4..24a0113 100644 /* init bars */ updatebars(); updatestatus(); -@@ -1626,7 +1799,18 @@ void +@@ -1583,6 +1747,22 @@ + } + } + ++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 + tag(const Arg *arg) { + if(selmon->sel && arg->ui & TAGMASK) { +@@ -1629,7 +1809,18 @@ togglebar(const Arg *arg) { selmon->showbar = !selmon->showbar; updatebarpos(selmon); @@ -469,7 +499,7 @@ index 314adf4..24a0113 100644 arrange(selmon); } -@@ -1716,11 +1900,17 @@ unmapnotify(XEvent *e) { +@@ -1719,11 +1910,18 @@ else unmanage(c, False); } @@ -482,24 +512,30 @@ index 314adf4..24a0113 100644 void updatebars(void) { - Monitor *m; + unsigned int w; + Monitor *m; ++ XSetWindowAttributes wa = { .override_redirect = True, .background_pixmap = ParentRelative, -@@ -1729,7 +1919,10 @@ updatebars(void) { +@@ -1732,10 +1930,15 @@ 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 == selmon) ++ 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); -@@ -1926,6 +2119,107 @@ updatestatus(void) { ++ if(showsystray && m == systraytomon(m)) ++ XMapRaised(dpy, systray->win); + XMapRaised(dpy, m->barwin); + } + } +@@ -1929,6 +2132,114 @@ } void @@ -554,8 +590,10 @@ index 314adf4..24a0113 100644 +void +updatesystray(void) { + XSetWindowAttributes wa; ++ XWindowChanges wc; + Client *i; -+ unsigned int x = selmon->mx + selmon->mw; ++ Monitor *m = systraytomon(NULL); ++ unsigned int x = m->mx + m->mw; + unsigned int w = 1; + + if(!showsystray) @@ -564,15 +602,14 @@ index 314adf4..24a0113 100644 + /* 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, selmon->by, w, bh, 0, 0, scheme[SchemeSel].bg->rgb); ++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel].bg->rgb); + wa.event_mask = ButtonPressMask | ExposureMask; + wa.override_redirect = True; -+ wa.background_pixmap = ParentRelative; + wa.background_pixel = scheme[SchemeNorm].bg->rgb; + XSelectInput(dpy, systray->win, SubstructureNotifyMask); + XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&systrayorientation, 1); -+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel|CWBackPixmap, &wa); ++ 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) { @@ -587,16 +624,22 @@ index 314adf4..24a0113 100644 + } + } + for(w = 0, i = systray->icons; i; i = i->next) { -+ XMapRaised(dpy, i->win); ++ /* make sure the background color stays the same */ ++ wa.background_pixel = scheme[SchemeNorm].bg->rgb; ++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); + w += systrayspacing; + XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->h); + w += i->w; -+ if(i->mon != selmon) -+ i->mon = selmon; ++ if(i->mon != m) ++ i->mon = m; + } + w = w ? w + systrayspacing : 1; -+ x -= w; -+ XMoveResizeWindow(dpy, systray->win, x, selmon->by, w, bh); ++ x -= w; ++ 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].bg->rgb); + XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); @@ -607,7 +650,7 @@ index 314adf4..24a0113 100644 updatewindowtype(Client *c) { Atom state = getatomprop(c, netatom[NetWMState]); Atom wtype = getatomprop(c, netatom[NetWMWindowType]); -@@ -1994,6 +2288,16 @@ wintomon(Window w) { +@@ -1997,6 +2308,16 @@ return selmon; } diff --git a/dwm.suckless.org/patches/dwm-6.1-tagall.diff b/dwm.suckless.org/patches/dwm-6.1-tagall.diff @@ -0,0 +1,33 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/historical/tagall +Shortcut to move all (floating) windows from one tag to another. + +Index: dwm/tagall.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/tagall.c 2014-02-09 15:24:11.468116949 +0100 +@@ -0,0 +1,24 @@ ++void ++tagall(const Arg *arg) { ++ if (!selmon->clients) ++ return; ++ /* if parameter starts with F, just move floating windows */ ++ int floating_only = (char *)arg->v && ((char *)arg->v)[0] == 'F' ? 1 : 0; ++ int tag = (char *)arg->v ? atoi(((char *)arg->v) + floating_only) : 0; ++ int j; ++ Client* c; ++ if(tag >= 0 && tag < LENGTH(tags)) ++ for(c = selmon->clients; c; c = c->next) ++ { ++ if(!floating_only || c->isfloating) ++ for(j = 0; j < LENGTH(tags); j++) ++ { ++ if(c->tags & 1 << j && selmon->tagset[selmon->seltags] & 1 << j) ++ { ++ c->tags = c->tags ^ (1 << j & TAGMASK); ++ c->tags = c->tags | 1 << (tag-1); ++ } ++ } ++ } ++ arrange(selmon); ++} diff --git a/dwm.suckless.org/patches/dwm-6.1-zoomswap.diff b/dwm.suckless.org/patches/dwm-6.1-zoomswap.diff @@ -0,0 +1,86 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: http://dwm.suckless.org/patches/zoomswap +This patch swaps the current window with the previous master when zooming. + +Index: dwm/dwm.c +=================================================================== +--- dwm/dwm.c.orig 2014-02-09 15:24:16.008117074 +0100 ++++ dwm/dwm.c 2014-02-09 15:24:16.000117074 +0100 +@@ -234,6 +234,7 @@ + static void zoom(const Arg *arg); + + /* variables */ ++static Client *prevzoom = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -2033,14 +2034,38 @@ + void + zoom(const Arg *arg) { + Client *c = selmon->sel; ++ Client *at = NULL, *cold, *cprevious = NULL; + + if(!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; +- if(c == nexttiled(selmon->clients)) +- if(!c || !(c = nexttiled(c->next))) +- return; +- pop(c); ++ if(c == nexttiled(selmon->clients)) { ++ at = findbefore(prevzoom); ++ if(at) ++ cprevious = nexttiled(at->next); ++ if(!cprevious || cprevious != prevzoom) { ++ prevzoom = NULL; ++ if(!c || !(c = nexttiled(c->next))) ++ return; ++ } else ++ c = cprevious; ++ } ++ cold = nexttiled(selmon->clients); ++ if(c != cold && !at) ++ at = findbefore(c); ++ detach(c); ++ attach(c); ++ /* swap windows instead of pushing the previous one down */ ++ if(c != cold && at) { ++ prevzoom = cold; ++ if(cold && at != cold) { ++ detach(cold); ++ cold->next = at->next; ++ at->next = cold; ++ } ++ } ++ focus(c); ++ arrange(c->mon); + } + + int +Index: dwm/zoomswap.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ dwm/zoomswap.c 2014-02-09 15:24:16.004117074 +0100 +@@ -0,0 +1,10 @@ ++static Client * findbefore(Client *c); ++ ++Client * ++findbefore(Client *c) { ++ Client *tmp; ++ if(c == selmon->clients) ++ return NULL; ++ for(tmp = selmon->clients; tmp && tmp->next != c; tmp = tmp->next) ; ++ return tmp; ++} +Index: dwm/config.def.h +=================================================================== +--- dwm/config.def.h.orig 2014-02-09 15:24:16.008117074 +0100 ++++ dwm/config.def.h 2014-02-09 15:24:16.004117074 +0100 +@@ -54,6 +54,7 @@ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++#include "zoomswap.c" + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, diff --git a/dwm.suckless.org/patches/dwm-cdec978-center.diff b/dwm.suckless.org/patches/dwm-cdec978-center.diff @@ -0,0 +1,58 @@ +diff --git a/config.def.h b/config.def.h +index 875885b..2e3a9fb 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -21,9 +21,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, True, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, False, -1 }, ++ /* class instance title tags mask iscentered isfloating monitor */ ++ { "Gimp", NULL, NULL, 0, False, True, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, False, False, -1 }, + }; + + /* layout(s) */ +diff --git a/dwm.c b/dwm.c +index 1bbb4b3..a8a3356 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -91,7 +91,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ Bool isfixed, iscentered, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; +@@ -136,6 +136,7 @@ typedef struct { + const char *instance; + const char *title; + unsigned int tags; ++ Bool iscentered; + Bool isfloating; + int monitor; + } Rule; +@@ -294,6 +295,7 @@ applyrules(Client *c) { + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { ++ c->iscentered = r->iscentered; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for(m = mons; m && m->num != r->monitor; m = m->next); +@@ -1038,6 +1040,11 @@ manage(Window w, XWindowAttributes *wa) { + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; + ++ if(c->iscentered) { ++ c->x = (c->mon->mw - WIDTH(c)) / 2; ++ c->y = (c->mon->mh - HEIGHT(c)) / 2; ++ } ++ + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->rgb); diff --git a/dwm.suckless.org/patches/dwmfifo.md b/dwm.suckless.org/patches/dwmfifo.md @@ -0,0 +1,38 @@ +dwmfifo +======= + +Description +----------- + +This patch adds support for using a command/control FIFO for +dwm. I've added commands that map 1-1 with the existing keybind +actions. You can use this patch to script dwm. As an example the +following sequence of commands starts 2 terminals on each of the +2 monitors. + + echo -n term > /tmp/dwm.fifo + sleep 0.5 + echo -n term > /tmp/dwm.fifo + sleep 0.5 + echo -n focusmon+ > /tmp/dwm.fifo + sleep 0.5 + echo -n term > /tmp/dwm.fifo + sleep 0.5 + echo -n term > /tmp/dwm.fifo + +The sleep in between is currently needed to avoid buffering up +more than a single command. You may experiment with the actual +sleep value. + +Similarly you can modify your config.h and add more commands +that you may want to execute (like tabbed-surf or similar). + +Download +-------- + + * [dwm-6.1-dwmfifo.diff](dwm-6.1-dwmfifo.diff) (6.9k) (29.01.2014) + +Author +------ + + * sin - <sin@2f30.org> diff --git a/dwm.suckless.org/patches/float_border_color.md b/dwm.suckless.org/patches/float_border_color.md @@ -5,8 +5,9 @@ This patch allows you to specify a different border color for floating windows. ## Download ## Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-float_border_color2.diff](dwm-6.1-float_border_color2.diff) (3594b) (20140209) * [dwm-10e232f9ace7-float_border_color2.diff](dwm-10e232f9ace7-float_border_color2.diff) (3432b) (20120406) * [dwm-6.0-float_border_color2.diff](dwm-6.0-float_border_color2.diff) (3356b) (20120406) diff --git a/dwm.suckless.org/patches/gapless_grid.md b/dwm.suckless.org/patches/gapless_grid.md @@ -26,6 +26,7 @@ Download `gaplessgrid.c` and add the gapless layout to your `config.h`: ## Download +* [dwm-6.1-gaplessgrid.diff](dwm-6.1-gaplessgrid.diff) (1180b) (20140209) * [gaplessgrid.c](gaplessgrid.c) (dwm 5.6.1) (20090908) * [dwm-r1437-gaplessgrid.diff](historical/dwm-r1437-gaplessgrid.diff) (1.9k) (20090704) * [dwm-5.2-gaplessgrid.diff](historical/dwm-5.2-gaplessgrid.diff) (1.9k) (20081020) diff --git a/dwm.suckless.org/patches/gaps.md b/dwm.suckless.org/patches/gaps.md @@ -0,0 +1,27 @@ + +Gaps +==== + +Description +----------- + +This patch modifies the tile layout to add a gap between clients that helps to visually +differentiate between selected borders and normal borders and so provides an additional +visual hint to identify the currently selected client. OTOH, there's no gap between a +client and the screen frame in order to reduce the waste of screen space. + +To configure the gap size just set the configuration variable `gappx`. + +There is a variation of the patch for the [xtile](xtile) layout also. + +Download +-------- + +* For vanilla tile: [dwm-6.0-gaps.diff](dwm-6.0-gaps.diff) + +* For xtile tile: [dwm-6.0-xtile-gaps.diff](dwm-6.0-xtile-gaps.diff) + +Author +------ + +* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/keycode.md b/dwm.suckless.org/patches/keycode.md @@ -0,0 +1,12 @@ +Keycode +======== +With this patch, handling key input is done with keycodes instead of keysyms. +This way, input is keyboard layout independant (adapt config.h to your keyboard using for exemple xev). + +Download +-------- +* [dwm-6.0-keycode.diff](dwm-6.0-keycode.diff) + +Author +------ +* Quentin Rameau <quinq@quinq.eu.org> diff --git a/dwm.suckless.org/patches/maximize.md b/dwm.suckless.org/patches/maximize.md @@ -3,7 +3,6 @@ maximize Description ----------- - These patch provide helper functions for maximizing, horizontally and vertically, floating windows using keybindings. @@ -19,11 +18,9 @@ Insert the bindings into the keys list. Here is an example: Download -------- -* [dwm-6.0-moveresize.diff][0] - -[0]: dwm-6.0-moveresize.diff +* [dwm-6.1-maximize_vert_horz.diff](dwm-6.1-maximize_vert_horz.diff) (2532b) (20140209) +* [dwm-6.0-maximize_vert_horz.diff](dwm-6.0-maximize_vert_horz.diff) (2013b) (20120406) Author ------ - * Jan Christoph Ebersbach - <jceb@e-jc.de> diff --git a/dwm.suckless.org/patches/moveresize.md b/dwm.suckless.org/patches/moveresize.md @@ -61,6 +61,7 @@ Download Patches against different versions of dwm are available at [dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). + * [dwm-6.1-moveresize.diff](dwm-6.1-moveresize.diff) (2095b) (20140209) * [dwm-10e232f9ace7-moveresize.diff](dwm-10e232f9ace7-moveresize.diff) (2025b) (20120406) * [dwm-10e232f9ace7-maximize_vert_horz.diff](dwm-10e232f9ace7-maximize_vert_horz.diff) (2385b) (20120406) * [dwm-6.0-moveresize.diff](dwm-6.0-moveresize.diff) (2025b) (20120406) diff --git a/dwm.suckless.org/patches/noborder.md b/dwm.suckless.org/patches/noborder.md @@ -8,8 +8,9 @@ This patch removes the border when there is just one window visible in tiled or Download -------- Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-single_window_no_border.diff](dwm-6.1-single_window_no_border.diff) (3025b) (20140209) * [dwm-10e232f9ace7-statusallmons.diff](dwm-10e232f9ace7-statusallmons.diff) (982b) (20120406) * [dwm-6.0-single_window_no_border.diff](dwm-6.0-single_window_no_border.diff) (2865b) (20120406) diff --git a/dwm.suckless.org/patches/pango.md b/dwm.suckless.org/patches/pango.md @@ -0,0 +1,40 @@ +Pango +===== + +Description +----------- + +This relatively simple patch adds pango support for the status bar. This not only adds +TrueType font support but also opens a couple of interesting possibilities that are +not possible under barebone xft: + +* **Simple markup** for status messages (optional, enable/disable it in your config.h) + using [pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html). + So you can format your status messages specifying fg/bg colors, sizes, sub/superscripts, + underline, emphasis, bold, etc. You can do dynamic font switching, also! To play safe + with the rest of the status bar, markup support is restricted to the status message area + over which you have direct control. + +* **Fallback fonts**, so you can use -for example- some set of iconic fonts as your second + family: "DejaVu Sans, Icons 8" [1]. There are tons of monochromatic nice looking TTF + icons around the web these days as webfonts are becoming more and more popular. Notice + that you can also use the more powerful font switching enabled by pango markup to + achieve the same goal. Also don't be mislead by the fact that fontconfig understands + descriptors like "DejaVu Sans, Icons-8" or even font sequences defined as alias in your + fonts.conf. xft will pick one font once and for all, not on a char-by-char basis. + +[1] The [Icons family](https://aur.archlinux.org/packages/ttf-font-icons/) is a + non-overlapping merge of Awesome and Ionicons fonts I've made for my statusbar. In case + you want to take a look at it, there is a + [cheatsheet](https://www.dropbox.com/s/9iysh2i0gadi4ic/icons.pdf) listing the icons and + their unicode points. + +Download +-------- + +* [dwm-6.0-pango.diff](dwm-6.0-pango.diff) + +Author +------ + +* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/pertag.md b/dwm.suckless.org/patches/pertag.md @@ -11,6 +11,7 @@ Download Patches against different versions of dwm are available at [dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). + * [dwm-6.1-pertag.diff](dwm-6.1-pertag.diff) (6630b) (20140209) * [dwm-10e232f9ace7-pertag.diff](dwm-10e232f9ace7-pertag.diff) (5955b) (20120406) * [dwm-6.0-pertag.diff](dwm-6.0-pertag.diff) (5955b) (20120406) * [dwm-r1578-pertag.diff][9] (nmaster included in mainline) diff --git a/dwm.suckless.org/patches/push.md b/dwm.suckless.org/patches/push.md @@ -15,8 +15,9 @@ ## Download Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-push.diff](dwm-6.1-push.diff) (1402b) (20140209) * [dwm-10e232f9ace7-push.diff](dwm-10e232f9ace7-push.diff) (1332b) (20120406) * [dwm-6.0-push.diff](dwm-6.0-push.diff) (1332b) (20120406) * [dwm-6.0-push_no_master.diff](dwm-6.0-push_no_master.diff) @@ -25,7 +26,6 @@ Patches against different versions of dwm are available at * [push-5.3.c](historical/push-5.3.c) (1K) (20090124) ## Note - This patch seems to be equivalent to the [movestack](movestack) patch. ## Author diff --git a/dwm.suckless.org/patches/runorraise.md b/dwm.suckless.org/patches/runorraise.md @@ -0,0 +1,35 @@ +runorraise +========== + +Description +----------- +This patch adds a equivalent to stumpwm's [run-or-raise] action for DWM. + +The idea is to have each frequently-used application one key combination away at all times, irrespective of which workspace it is on, +or how recently it has been used, or even whether it’s running or not. + +Usage +----- + +1. In your config.h: + + static const char *emacs[] = { "emacsclient", "-c", NULL, NULL, "Emacs" }; + static const char *browser[] = { "firefox", NULL, NULL, NULL, "Firefox" }; + +1. In your keybindings add something like: + + { Modkey, XK_e, runorraise, {.v = emacs } }, + { Modkey, XK_f, runorraise, {.v = firefox } }, + +Download +-------- + +* [dwm-6.1-runorraise.diff](dwm-6.1-runorraise.diff) + +Authors +------- +* Quentin Stievenart (acieroid) - `<quentin.stievenart at gmail dot com>` + +Contributors +------------ +* Ivaylo Kuzev (ivoarch) - `<ivkuzev at gmail dot com>` diff --git a/dwm.suckless.org/patches/save_floats.md b/dwm.suckless.org/patches/save_floats.md @@ -7,8 +7,9 @@ be restored. ## Download ## Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-save_floats.diff](dwm-6.1-save_floats.diff) (1605b) (20140209) * [dwm-10e232f9ace7-save_floats.diff](dwm-10e232f9ace7-save_floats.diff) (1604b) (20120406) * [dwm-6.0-save_floats.diff](dwm-6.0-save_floats.diff) (1528b) (20120406) diff --git a/dwm.suckless.org/patches/single_tagset.md b/dwm.suckless.org/patches/single_tagset.md @@ -22,8 +22,9 @@ Download Please be aware that this patch probably breaks any other patch! Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-single_tagset.diff](dwm-6.1-single_tagset.diff) (16634b) (20140209) * [dwm-10e232f9ace7-single_tagset.diff](dwm-10e232f9ace7-single_tagset.diff) (14748b) (20120406) * [dwm-6.0-single_tagset.diff](dwm-6.0-single_tagset.diff) (14417b) (20120406) @@ -32,7 +33,7 @@ Special Version This is a special version of the patch that was created with following patches being applied: * [attachabove](attachabove) * [float_border_color](float_border_color) - * [focusmaster](https://bitbucket.org/jceb81/dwm-patches/src/90fb0feedff9/focusmaster.patch) + * [focusmaster](https://raw.github.com/jceb/dwm-patches/master/patches/focusmaster.patch) * [moveresize](moveresize) * [noborder](noborder) * [pertag](pertag) @@ -43,7 +44,7 @@ This is a special version of the patch that was created with following patches b * [tagall](tagall) * [zoomswap](zoomswap) -[dwm-6.0-single_tagset_all.diff](https://bitbucket.org/jceb81/dwm-patches/raw/cc88093b8acb/single_tagset_all.patch) +[dwm-6.1-single_tagset_all.diff](https://raw.github.com/jceb/dwm-patches/master/patches/single_tagset_all.patch) Authors ------- diff --git a/dwm.suckless.org/patches/stacker.md b/dwm.suckless.org/patches/stacker.md @@ -0,0 +1,61 @@ +Stacker +======= + +Description +----------- + +This patch provides comprehensive utilities for managing the client stack. It implements +two new commands: `focusstack` (which is a replacement for the original `focusstack` +command) and `pushstack`. The first one is for focusing clients while the second one moves +clients around the stack. Both commands take the same kind of argument: + +* Pass `PREVSEL` to focus/push the previously selected client in the current tagset. + +* Pass `INC(+/-inc)` to focus/push relatively to the selected client. This will wrap + around the stack limits. + +* Pass a positive number to focus/push relatively to the beginning of the stack. Out of + limit values will be truncated to the position of the last visible client and won't wrap + around. + +* Pass a negative number to focus/push relatively to the last visible client in the stack. + Here -1 means the last client, -2 the previous to last client, etc. Out of limit values + will be truncated to the position of the first visible client (0) and won't wrap + around. + +Default key bindings +-------------------- + +There are two parallel sets of bindings: one for the `focus*` family and the other for the +`push*` family. The keys are the same for both sets but they do differ in the modifiers: +simply `MODKEY` for the `focus*` family and `MODKEY|ShiftMask` for the `push*` family. + + Key | Argument | Description +:------:|:-----------:|----------------------- + \` | `PREVSEL` | Previously selected + `j` | `INC(+1)` | Next to selected + `k` | `INC(-1)` | Previous to selected + `q` | `0` | First position + `a` | `1` | Second position + `z` | `2` | Third position + `x` | `-1` | Last position + +The `q`, `a`, `z` keys are aligned more or less vertically in the us keyboard layout. They +are intended to be used as quick positional shortcuts to specific applications. So if you +have 9 tags you get 9\*3=27 shortcuts in a two-level hierarchy of clients. The \` key is +above the `Tab` key and it's intended to complement the "move to previously selected +tag" function of dwm at the intra-tag level. Finally, the `x` key is like "I don't care so +much about you just right now but you can still live in this tag". + +Notice that `MODKEY|ShiftMask+q` collides with the default binding for quitting dwm, which +stacker changes to `MODKEY|ShiftMask+BackSpace`. + +Download +-------- + +* [dwm-6.0-stacker.diff](dwm-6.0-stacker.diff) + +Author +------ + +* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/statusallmons.md b/dwm.suckless.org/patches/statusallmons.md @@ -8,8 +8,9 @@ This patch draws and updates the statusbar on all monitors. Download -------- Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-statusallmons.diff](dwm-6.1-statusallmons.diff) (1026b) (20140209) * [dwm-10e232f9ace7-statusallmons.diff](dwm-10e232f9ace7-statusallmons.diff) (982b) (20120406) * [dwm-6.0-statusallmons.diff](dwm-6.0-statusallmons.diff) (982b) (20120406) * [dwm-5.8.2-statusallmons.diff](dwm-5.8.2-statusallmons.diff) (4.0K) (20110318) diff --git a/dwm.suckless.org/patches/swapfocus.md b/dwm.suckless.org/patches/swapfocus.md @@ -5,8 +5,9 @@ This patch makes it possible to switch focus with one single shortcut (alt-s) in ## Download Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-swapfocus.diff](dwm-6.1-swapfocus.diff) (1807b) (20140209) * [dwm-10e232f9ace7-swapfocus.diff](dwm-10e232f9ace7-swapfocus.diff) (1484b) (20120406) * [dwm-6.0-swapfocus.diff](dwm-6.0-swapfocus.diff) (1482b) (20120406) * [dwm-5.8.2-swap.diff](dwm-5.8.2-swap.diff) (dwm 5.8.2) diff --git a/dwm.suckless.org/patches/systray.md b/dwm.suckless.org/patches/systray.md @@ -9,11 +9,11 @@ is following the selected monitor. Download -------- Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-systray.diff](dwm-6.1-systray.diff) (21630b) (20140209) * [dwm-c794a9f5ae5e-systray.diff](dwm-c794a9f5ae5e-systray.diff) (19946b) (20130119) * [dwm-6.0-systray.diff](dwm-6.0-systray.diff) (19788b) (20130119) - * [dwm-6.1-systray.diff](dwm-6.1-systray.diff) (20714b) (20130119) Author ------ diff --git a/dwm.suckless.org/patches/tagall.md b/dwm.suckless.org/patches/tagall.md @@ -6,8 +6,9 @@ Shortcut to move all (floating) windows from one tag to another. ## Download ## Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-tagall.diff](dwm-6.1-tagall.diff) (1058b) (20140209) * [dwm-10e232f9ace7-tagall.diff](dwm-10e232f9ace7-tagall.diff) (988b) (20120406) * [dwm-6.0-tagall.diff](dwm-6.0-tagall.diff) (988b) (20120406) diff --git a/dwm.suckless.org/patches/xtile.md b/dwm.suckless.org/patches/xtile.md @@ -0,0 +1,169 @@ +Xtile +===== + +Description +----------- + +This patch implements a generalization of the tile layout which adds two attributes +(direction and fact) to three areas (global, master, stack). The global area is the entire +allocatable visual space and it's subdivided into the master and stack subareas. + +The direction of the global area controls the position of the master area relatively to +the stack area and it can be one of `DirHor` (traditional right stack), `DirVer` (bottom +stack), `DirRotHor` (left stack) and `DirRotVer` (top stack). The direction of the master +and of the stack areas are independently set and can be one of `DirHor` and `DirVer`. +This combines to a total of 4\*2\*2=16 layouts. + +The fact numbers indicate the relative size of the first subarea/client along the +direction of the considered area (i.e. width for `DirHor` and `DirRotHor` and height for +`DirVer` and `DirRotVer`). A fact of 1 means that the first subarea/client is on par the +rest, while a fact of 2 means that its size must double the size of each of the remaining +subareas/clients, etc. So the fact for the global area is similar to the traditional +mfact in the sense that it manages the relative allocation of visual space between the +master and stack subareas, while the fact for the master area stands for the relative +importance of the first master client against the rest of masters and, similarly, the fact +for the stack area stands for the importance of the first slave client in relation to the +rest of slaves. + +xtile adds two new commands to dwm: `setdir` and `setfact` (which supersedes `setmfact`). +Both commands take an array of three values (of type `int` for `setdir` and `float` for +`setfact`), one value for each area (the first one for the global area, the second one for +the master area and the third one for the stack area). If you pass the value `v` as +`INC(v)` it will be taken as a relative increment to be added to the current value, +otherwise it will be taken as an absolute value. Usually the resulting value will be +truncated to the valid range of values for each area/attribute combination, but relative +increments for directions wrap around the limits of the valid range. Notice that INC(0) +means "do nothing here", so it gives you a way to easily modify the value for some area +while leaving the rest untouched. + +Default key bindings +-------------------- + +The areas are selected by modifiers as follows: + + Modifier | Area +----------------------|:-------------------------------: +`MODKEY` | Global +`MODKEY+Shift` | Master +`MODKEY+Control` | Stack +`MODKEY+Shift+Control`| All three areas simultaneously + +Each of the modifiers then combines with each of the following keys up to a total of +4\*3=12 key bindings: + + Key | Function +:------:|:-----------------------: + `r` | Rotate direction + `h` | Decrement fact by 10%. + `l` | Increment fact by 10%. + +There are two provided default "presets" or "schemas" also: + + Modifier | Key | Preset +------------------|:------:|:-------------: +`MODKEY+Shift` | `t` | Right stack +`MODKEY+Control` | `t` | Bottom stack + +These presets allow to quickly switch between different no-nonsense tilings avoiding the +need to rotate through all the nonsense combinations in-between. But notice that +`MODKEY+Shift+Control+r` (i.e. simultaneously rotate all three areas) usually produces +sensible layouts (due to the way directions were designed to rotate). + +You can also easily define your own presets by calling `setdir` and `setfact` as needed. +For example, here is the configuration code for the default presets described above: + + { MODKEY|ShiftMask, XK_t, setdirs, {.v = (int[]){ DirHor, DirVer, DirVer } } }, + { MODKEY|ControlMask, XK_t, setdirs, {.v = (int[]){ DirVer, DirHor, DirHor } } }, + +Layout symbol +------------- + +The layout symbol will probably look cryptic at first sight but it's very easily decoded. +It consists of three characters, one for the direction of each area: + +* Global area: '<', '>', 'v', '^', just think of it as an arrow that points in the + direction of the master area. + +* Master area: '|' for vertically tiled masters and '-' for horizontally tiled masters. + +* Stack area: same as for the master area. + +For example, '<||' stands for the default right stack tile provided by dwm and '^--' +stands for bstack (as defined by the bottom stack patch). + +Digressions +----------- + +### Why facts per area? + +There is some arbitrariness in the way facts are defined by xtile: why facts for the first +master and the first slave and not, say, for the first two clients instead? Considering +that most real life layouts will have one or two masters and a variable number of slaves, +the road xtile took will enable the user to effectively control the relative size of the +three/four most important clients in a very intuitive way that built on his previous +understanding of the mfact and the master and stack area concepts. OTOH it's not clear to +me how to allow the specification of facts for the first two clients in an intuitive way: + +* If there is only one master this alternative approach is equivalent to xtile's one. +* If there are two masters, only one fact will be required to specify the share of the + master area that belongs to each one, so what to do with the second fact? +* If this second fact is taken as the share of the second master vs the share of the + rest (the slaves), it's not clear how to define these inter-area shares. + +### Why not deck area? + +One obvious additional generalization would have been to extrapolate the nmaster idea to +all three areas, or at least to the stack area. So if you allowed only m masters and n +slaves you would end up with m+n tiled windows and with the rest of the clients in the +current tagset stacked or decked "below" the last tiled client. flextile, +clients-per-tag and deck patches provide variations on this kind of layout. I've also +implemented a version of xtile that supports it and even subsumes monocle, but I think +this promotes a bad pattern of usage. Coupled with stack manipulation operations as the +ones provided by the stacker or push patches, there is the temptation to manage visibility +by moving the desired clients in the current tagset to the first n+m visible positions of +the focus stack (not to be confused with the stack area). There are a number of problems +with this approach: + +* The stack is global to dwm, so pushing around clients in one tag will rearrange them in + other tags also. This could become a problem if you rely too much on explicit stack + management. + +* The deck area badly violates the principle of least surprise. If you only change focus + sequentially by using `mod-j`/`mod-k` there is no way to exit the deck at a client + different to the last/first decked one. If you use the mouse or the `focusstack` command + provided by the stacker patch to jump directly from the deck to a non-decked client, + each time you reach the deck again by using `mod-j`/`mod-k` the visible decked client + will be replaced by the first/last decked one. In general, there is a devilish interplay + of the focus stack and the z-stack that makes the deck unusable as a tabbed view of the + decked clients, at least for more than one or two decked clients. + +Fortunately, dwm provides a much better mechanism to restrict visibility: tags. IMO there +is no need to provide a half-assed alternative to one of dwm's strongest selling points. + +Other patches +------------- + +Recommended complementary patches: + +* [gaps](gaps): to add mostly useless gaps that nevertheless make more apparent which + client has the focus. + +* [stacker](stacker): to better accommodate the clients to the more elaborate layouts + allowed by xtile. But I would add: subject to the caveats that I've expressed above. + +Mandatory dependencies: + +* [pertag](pertag): we all know this one. + +Related patches: [bottom stack](bottom_stack), [flextile](flextile), cfacts, +[stackmfact](stackmfact). + +Download +-------- + +* [dwm-6.0-xtile.diff](dwm-6.0-xtile.diff) + +Author +------ + +* Carlos Pita (memeplex) <carlosjosepita@gmail.com> diff --git a/dwm.suckless.org/patches/zoomswap.md b/dwm.suckless.org/patches/zoomswap.md @@ -41,8 +41,9 @@ This patch swaps the current window (C) with the previous master (P) when zoomin Download -------- Patches against different versions of dwm are available at -[dwm-clean-patches](https://bitbucket.org/jceb81/dwm-clean-patches/src). +[dwm-clean-patches](https://github.com/jceb/dwm-clean-patches). + * [dwm-6.1-zoomswap.diff](dwm-6.1-zoomswap.diff) (2585b) (20120406) * [dwm-10e232f9ace7-attachabove.diff](dwm-10e232f9ace7-attachabove.diff) (1.7K) (20120406) * [dwm-6.0-zoomswap.diff](dwm-6.0-zoomswap.diff) (1.6K) (20120406) diff --git a/st.suckless.org/patches/externalpipe.md b/st.suckless.org/patches/externalpipe.md @@ -0,0 +1,38 @@ +External Pipe +============= + +Description +----------- + +This patch lets you write st's screen text out through a pipe, for example, +url-select (below). + +Example +------- + +Bind alt+u to extract all visible urls and present dmenu, to choose and open +said urls: + + static Shortcut shortcuts[] = { + ... + { MODKEY, 'u', externalpipe, { .s = "xurls | dmenu -l 10 | xargs -r open" } }, + }; + + +([xurls][1] and [open][2] are external scripts) + + +Download +-------- + +* [st-0.4.1-externalpipe.diff][0] + +[0]: st-0.4.1-externalpipe.diff +[1]: https://raw.github.com/bobrippling/perlbin/master/xurls +[2]: https://github.com/bobrippling/open + + +Author +------ + + * Rob Pilling - my name @ gmail diff --git a/st.suckless.org/patches/st-0.4.1-externalpipe.diff b/st.suckless.org/patches/st-0.4.1-externalpipe.diff @@ -0,0 +1,121 @@ +From 7982a2d238925028b45d5143db470e408b97469a Mon Sep 17 00:00:00 2001 +From: Rob Pilling <robpilling@gmail.com> +Date: Fri, 20 Dec 2013 12:40:55 +0000 +Subject: [PATCH] Add externalpipe() for piping out screen text + +--- + st.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 68 insertions(+), 6 deletions(-) + +diff --git a/st.c b/st.c +index 4fb3311..adef257 100644 +--- a/st.c ++++ b/st.c +@@ -299,6 +299,7 @@ typedef union { + unsigned int ui; + float f; + const void *v; ++ const char *s; + } Arg; + + typedef struct { +@@ -313,6 +314,7 @@ static void clippaste(const Arg *); + static void numlock(const Arg *); + static void selpaste(const Arg *); + static void xzoom(const Arg *); ++static void externalpipe(const Arg *); + + /* Config.h for applying patches and the configuration. */ + #include "config.h" +@@ -1204,15 +1206,22 @@ execsh(void) { + void + sigchld(int a) { + int stat = 0; ++ pid_t r; + +- if(waitpid(pid, &stat, 0) < 0) +- die("Waiting for pid %hd failed: %s\n", pid, SERRNO); ++ r = wait(&stat); ++ if(r < 0) ++ die("wait(): %s\n", SERRNO); + +- if(WIFEXITED(stat)) { +- exit(WEXITSTATUS(stat)); +- } else { +- exit(EXIT_FAILURE); ++ if(r == pid){ ++ /* _the_ sub porcess */ ++ if(WIFEXITED(stat)) { ++ exit(WEXITSTATUS(stat)); ++ } else { ++ exit(EXIT_FAILURE); ++ } + } ++ ++ /* something else we've forked out */ + } + + void +@@ -2928,6 +2937,59 @@ xzoom(const Arg *arg) { + } + + void ++externalpipe(const Arg *arg) ++{ ++ int to[2]; /* 0 = read, 1 = write */ ++ pid_t child; ++ int y, x; ++ void (*oldsigpipe)(int); ++ ++ if(pipe(to) == -1) ++ return; ++ ++ /* sigchld() handles this */ ++ switch((child = fork())){ ++ case -1: ++ close(to[0]), close(to[1]); ++ return; ++ case 0: ++ /* child */ ++ close(to[1]); ++ dup2(to[0], STDIN_FILENO); /* 0<&to */ ++ close(to[0]); ++ execvp( ++ "sh", ++ (char *const []){ ++ "/bin/sh", ++ "-c", ++ (char *)arg->s, ++ 0 ++ }); ++ exit(127); ++ } ++ ++ /* parent */ ++ close(to[0]); ++ /* ignore sigpipe for now, in case child exits early */ ++ oldsigpipe = signal(SIGPIPE, SIG_IGN); ++ ++ for(y = 0; y < term.row; y++){ ++ for(x = 0; x < term.col; x++){ ++ if(write(to[1], term.line[y][x].c, 1) == -1) ++ goto done; ++ } ++ if(write(to[1], "\n", 1) == -1) ++ break; ++ } ++ ++done: ++ close(to[1]); ++ ++ /* restore */ ++ signal(SIGPIPE, oldsigpipe); ++} ++ ++void + xinit(void) { + XGCValues gcvalues; + Cursor cursor; +-- +1.7.10.4 + diff --git a/sta.li/faq.md b/sta.li/faq.md @@ -133,7 +133,7 @@ complicated and add many more points of total failure. See also -------- -* <http://web.archive.org/web/20120509105723/http://teddziuba.com/2008/09/a-web-os-are-you-dense.html> -* <http://www.nth-dimension.org.uk/pub/BTL.pdf> +* [A Web OS? Are You Dense?](http://web.archive.org/web/20120509105723/http://teddziuba.com/2008/09/a-web-os-are-you-dense.html) +* [Breaking the links: Exploiting the linker](http://www.nth-dimension.org.uk/pub/BTL.pdf) * [On the Effectiveness of Address-Space Randomization](http://benpfaff.org/papers/asrandom.pdf) diff --git a/sta.li/filesystem.md b/sta.li/filesystem.md @@ -8,7 +8,6 @@ will fit the changed principles of the OS. /boot - all boot files /dev - devices /etc - system configuration - /svc - services /home - user directories /root - the root home /var - spool, run, log, cache diff --git a/sta.li/index.md b/sta.li/index.md @@ -29,7 +29,7 @@ Some related links * [Bifrost/Linux](http://bifrost.slu.se/) - a minimalist Linux distro for USB media * [$6M libc](http://codingrelic.geekhold.com/2008/11/six-million-dollar-libc.html) - Bionic is a nice library, though only usable for sane stuff * [ldd arbitrary code execution](http://www.catonmat.net/blog/ldd-arbitrary-code-execution/) - Nice exploit -* [static linking](http://blog.garbe.us/2008/02/08/01_Static_linking/) - My old blog entry -* [blog post about stali](http://elevenislouder.blogspot.com/2010/02/stali.html) +* [static linking](http://wayback.archive.org/web/20090525150626/http://blog.garbe.us/2008/02/08/01_Static_linking/) - My old blog entry +* [blog post about stali](http://wayback.archive.org/web/20110727064007/http://elevenislouder.blogspot.com/2010/02/stali.html) * [On the Effectiveness of Address-Space Randomization](http://benpfaff.org/papers/asrandom.pdf) * [musl libc](http://www.musl-libc.org/) diff --git a/sta.li/sandbox.md b/sta.li/sandbox.md @@ -30,7 +30,7 @@ Quick Ideas * use mdev for device management * add a »dev« command for controlling mdev * make some minor/major/netlink extractor to a script -* use busybox as first userland, then gradually move to stools +* use busybox as first userland, then gradually move to sbase + ubase * use svc for services * first use X11 for graphics until Wayland is getting sane * if kernel graphics is getting faster use a framebuffer diff --git a/sta.li/technologies.md b/sta.li/technologies.md @@ -4,17 +4,23 @@ Software / Techologies sta.li could use This list is a proposal of software, which sta.li should include. The rules are: Be as simple as possible and as useful as possible. -* [asm_utils](http://www.energymech.net/users/proton/) +* base system + * [sbase](http://git.suckless.org/sbase/) + * [ubase](http://git.suckless.org/ubase/) * init * [cinit](http://www.nico.schottelius.org/software/cinit/) + * [sinit](http://git.2f30.org/sinit/) * services * [runit](http://smarden.org/runit/) + * [svc](http://git.r-36.net/svc/) * logging * [socklog](http://smarden.org/socklog/) * documents * [ted](http://www.nllgg.nl/ted/) * udev * [mdev](http://lists.busybox.net/pipermail/busybox/2005-December/017183.html) + * [nldev](http://git.r-36.net/nldev/) + * [smdev](http://git.2f30.org/smdev/) * wm * [dwm](http://dwm.suckless.org) * [nowm](https://github.com/patrickhaller/no-wm) diff --git a/suckless.org/index.md b/suckless.org/index.md @@ -5,6 +5,10 @@ Read more about our [philosophy](/philosophy) and join us on the [mailing list]( News ==== +2014-01-21 +---------- +[tabbed 0.6](http://tools.suckless.org/tabbed) released: [download](http://dl.suckless.org/tools/tabbed-0.6.tar.gz) + 2013-06-16 ---------- [sic 1.2](http://tools.suckless.org/sic) released: [download](http://dl.suckless.org/tools/sic-1.2.tar.gz) diff --git a/suckless.org/other_projects.md b/suckless.org/other_projects.md @@ -29,3 +29,5 @@ There are several other projects which are inspired by the spirit of suckless. * [sup](http://git.suckless.org/sup) - minimalistic sudo replacement * [sw](http://nibble.develsec.org/projects/sw.html) - minimalistic web framework * [xicon](http://hg.youterm.com/xicon/) (dead link) - small icon-based dzen-like utility +* [xkev](https://github.com/vlaadbrain/xkev) - simply simulate KeyPress/KeyRelease +* [xbmouse](https://github.com/vlaadbrain/xbmouse) - simply bind a mouse button to a command diff --git a/suckless.org/people/Sin.md b/suckless.org/people/Sin.md @@ -0,0 +1,7 @@ +sin +=== + +I am the original author and maintainer of [ubase](http://git.suckless.org/ubase). +I also maintain and actively contribute to [sbase](http://git.suckless.org/sbase). + +Some of my other projects are hosted at [2f30](http://git.2f30.org). diff --git a/suckless.org/rocks.md b/suckless.org/rocks.md @@ -15,10 +15,6 @@ libc implementations * [musl](http://www.musl-libc.org/) - standard C library that attempts to be even smaller than uClibc * See also: [embedded libc comparison](http://www.etalabs.net/compare_libcs.html) -Configuration file parsers --------------------------- -* [iniparser](http://ndevilla.free.fr/iniparser/) - relatively small ini parsing library, contains a dictionary data structure and accessory functions (MIT licensed) - Compression ----------- * [liblzf](http://oldhome.schmorp.de/marc/liblzf.html) - very fast, legally unencumbered compression library (dual licensed: 2-clause BSD or GPL License) diff --git a/surf.suckless.org/patches/fullscreen.md b/surf.suckless.org/patches/fullscreen.md @@ -1,18 +0,0 @@ -Fullscreen -========== - -Description ------------ - -Adds optional fullscreen mode (-f). - -Download --------- - -* [surf-0.4.1-fullscreen.diff](surf-0.4.1-fullscreen.diff) (917) (20111020) - -Author ------- - -* Don Mahurin <[dmahurin@users.sf.net](mailto:dmahurin@users.sf.net)> - diff --git a/surf.suckless.org/patches/smoothscrolling-via-GTK3.md b/surf.suckless.org/patches/smoothscrolling-via-GTK3.md @@ -0,0 +1,18 @@ +smoothscrolling via GTK3 +======================== + +Description +----------- + +Enable smooth scrolling by compiling surf with GTK3 instead of GTK2. + +Download +-------- + +* [surf-0.6-smoothscrolling.diff](surf-0.6-smoothscrolling.diff) (9.4K) (20131229) + +Author +------ + +* Charles Lehner <[http://celehner.com](http://celehner.com)> + diff --git a/surf.suckless.org/patches/surf-0.6-smoothscrolling.diff b/surf.suckless.org/patches/surf-0.6-smoothscrolling.diff @@ -0,0 +1,219 @@ +diff --git a/config.def.h b/config.def.h +index b81e6b0..8e192aa 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -53,47 +53,47 @@ static Bool allowgeolocation = TRUE; + */ + static Key keys[] = { + /* modifier keyval function arg Focus */ +- { MODKEY|GDK_SHIFT_MASK,GDK_r, reload, { .b = TRUE } }, +- { MODKEY, GDK_r, reload, { .b = FALSE } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_p, print, { 0 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_r, reload, { .b = TRUE } }, ++ { MODKEY, GDK_KEY_r, reload, { .b = FALSE } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_p, print, { 0 } }, + +- { MODKEY, GDK_p, clipboard, { .b = TRUE } }, +- { MODKEY, GDK_y, clipboard, { .b = FALSE } }, ++ { MODKEY, GDK_KEY_p, clipboard, { .b = TRUE } }, ++ { MODKEY, GDK_KEY_y, clipboard, { .b = FALSE } }, + +- { MODKEY|GDK_SHIFT_MASK,GDK_j, zoom, { .i = -1 } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_k, zoom, { .i = +1 } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_q, zoom, { .i = 0 } }, +- { MODKEY, GDK_minus, zoom, { .i = -1 } }, +- { MODKEY, GDK_plus, zoom, { .i = +1 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_j, zoom, { .i = -1 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_k, zoom, { .i = +1 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_q, zoom, { .i = 0 } }, ++ { MODKEY, GDK_KEY_minus, zoom, { .i = -1 } }, ++ { MODKEY, GDK_KEY_plus, zoom, { .i = +1 } }, + +- { MODKEY, GDK_l, navigate, { .i = +1 } }, +- { MODKEY, GDK_h, navigate, { .i = -1 } }, ++ { MODKEY, GDK_KEY_l, navigate, { .i = +1 } }, ++ { MODKEY, GDK_KEY_h, navigate, { .i = -1 } }, + +- { MODKEY, GDK_j, scroll_v, { .i = +1 } }, +- { MODKEY, GDK_k, scroll_v, { .i = -1 } }, +- { MODKEY, GDK_b, scroll_v, { .i = -10000 } }, +- { MODKEY, GDK_space, scroll_v, { .i = +10000 } }, +- { MODKEY, GDK_i, scroll_h, { .i = +1 } }, +- { MODKEY, GDK_u, scroll_h, { .i = -1 } }, ++ { MODKEY, GDK_KEY_j, scroll_v, { .i = +1 } }, ++ { MODKEY, GDK_KEY_k, scroll_v, { .i = -1 } }, ++ { MODKEY, GDK_KEY_b, scroll_v, { .i = -10000 } }, ++ { MODKEY, GDK_KEY_space, scroll_v, { .i = +10000 } }, ++ { MODKEY, GDK_KEY_i, scroll_h, { .i = +1 } }, ++ { MODKEY, GDK_KEY_u, scroll_h, { .i = -1 } }, + +- { 0, GDK_F11, fullscreen, { 0 } }, +- { 0, GDK_Escape, stop, { 0 } }, +- { MODKEY, GDK_o, source, { 0 } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_o, inspector, { 0 } }, ++ { 0, GDK_KEY_F11, fullscreen, { 0 } }, ++ { 0, GDK_KEY_Escape, stop, { 0 } }, ++ { MODKEY, GDK_KEY_o, source, { 0 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_o, inspector, { 0 } }, + +- { MODKEY, GDK_g, spawn, SETPROP("_SURF_URI", "_SURF_GO") }, +- { MODKEY, GDK_f, spawn, SETPROP("_SURF_FIND", "_SURF_FIND") }, +- { MODKEY, GDK_slash, spawn, SETPROP("_SURF_FIND", "_SURF_FIND") }, ++ { MODKEY, GDK_KEY_g, spawn, SETPROP("_SURF_URI", "_SURF_GO") }, ++ { MODKEY, GDK_KEY_f, spawn, SETPROP("_SURF_FIND", "_SURF_FIND") }, ++ { MODKEY, GDK_KEY_slash, spawn, SETPROP("_SURF_FIND", "_SURF_FIND") }, + +- { MODKEY, GDK_n, find, { .b = TRUE } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_n, find, { .b = FALSE } }, ++ { MODKEY, GDK_KEY_n, find, { .b = TRUE } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_n, find, { .b = FALSE } }, + +- { MODKEY|GDK_SHIFT_MASK,GDK_c, toggle, { .v = "enable-caret-browsing" } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_i, toggle, { .v = "auto-load-images" } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_s, toggle, { .v = "enable-scripts" } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_v, toggle, { .v = "enable-plugins" } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_m, togglestyle,{ 0 } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_b, togglescrollbars,{ 0 } }, +- { MODKEY|GDK_SHIFT_MASK,GDK_g, togglegeolocation, { 0 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_c, toggle, { .v = "enable-caret-browsing" } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_i, toggle, { .v = "auto-load-images" } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_s, toggle, { .v = "enable-scripts" } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_v, toggle, { .v = "enable-plugins" } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_m, togglestyle,{ 0 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_b, togglescrollbars,{ 0 } }, ++ { MODKEY|GDK_SHIFT_MASK,GDK_KEY_g, togglegeolocation, { 0 } }, + }; + +diff --git a/config.mk b/config.mk +index b7a902f..82ebe38 100644 +--- a/config.mk ++++ b/config.mk +@@ -10,8 +10,8 @@ MANPREFIX = ${PREFIX}/share/man + X11INC = /usr/X11R6/include + X11LIB = /usr/X11R6/lib + +-GTKINC = `pkg-config --cflags gtk+-2.0 webkit-1.0` +-GTKLIB = `pkg-config --libs gtk+-2.0 webkit-1.0` ++GTKINC = `pkg-config --cflags gtk+-3.0 webkitgtk-3.0` ++GTKLIB = `pkg-config --libs gtk+-3.0 webkitgtk-3.0` + + # includes and libs + INCS = -I. -I/usr/include -I${X11INC} ${GTKINC} +diff --git a/surf.c b/surf.c +index d970f7f..3a083d3 100644 +--- a/surf.c ++++ b/surf.c +@@ -7,6 +7,7 @@ + #include <X11/X.h> + #include <X11/Xatom.h> + #include <gtk/gtk.h> ++#include <gtk/gtkx.h> + #include <gdk/gdkx.h> + #include <gdk/gdk.h> + #include <gdk/gdkkeysyms.h> +@@ -74,7 +75,7 @@ G_DEFINE_TYPE(CookieJar, cookiejar, SOUP_TYPE_COOKIE_JAR_TEXT) + static Display *dpy; + static Atom atoms[AtomLast]; + static Client *clients = NULL; +-static GdkNativeWindow embed = 0; ++static Window embed = 0; + static gboolean showxid = FALSE; + static char winid[64]; + static gboolean usingproxy = 0; +@@ -472,7 +473,7 @@ getatom(Client *c, int a) { + unsigned long ldummy; + unsigned char *p = NULL; + +- XGetWindowProperty(dpy, GDK_WINDOW_XID(GTK_WIDGET(c->win)->window), ++ XGetWindowProperty(dpy, GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(c->win))), + atoms[a], 0L, BUFSIZ, False, XA_STRING, + &adummy, &idummy, &ldummy, &ldummy, &p); + if(p) { +@@ -660,6 +661,7 @@ newclient(void) { + WebKitWebFrame *frame; + GdkGeometry hints = { 1, 1 }; + GdkScreen *screen; ++ GdkWindow *window; + gdouble dpi; + char *uri, *ua; + +@@ -686,6 +688,10 @@ newclient(void) { + */ + gtk_window_set_role(GTK_WINDOW(c->win), "Surf"); + } ++ ++ gtk_widget_realize(GTK_WIDGET(c->win)); ++ window = gtk_widget_get_window(GTK_WIDGET(c->win)); ++ + gtk_window_set_default_size(GTK_WINDOW(c->win), 800, 600); + g_signal_connect(G_OBJECT(c->win), + "destroy", +@@ -695,10 +701,10 @@ newclient(void) { + addaccelgroup(c); + + /* Pane */ +- c->pane = gtk_vpaned_new(); ++ c->pane = gtk_paned_new(GTK_ORIENTATION_VERTICAL); + + /* VBox */ +- c->vbox = gtk_vbox_new(FALSE, 0); ++ c->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_paned_pack1(GTK_PANED(c->pane), c->vbox, TRUE, TRUE); + + /* Webview */ +@@ -778,8 +784,8 @@ newclient(void) { + gtk_widget_show(c->win); + gtk_window_set_geometry_hints(GTK_WINDOW(c->win), NULL, &hints, + GDK_HINT_MIN_SIZE); +- gdk_window_set_events(GTK_WIDGET(c->win)->window, GDK_ALL_EVENTS_MASK); +- gdk_window_add_filter(GTK_WIDGET(c->win)->window, processx, c); ++ gdk_window_set_events(window, GDK_ALL_EVENTS_MASK); ++ gdk_window_add_filter(window, processx, c); + webkit_web_view_set_full_content_zoom(c->view, TRUE); + + runscript(frame); +@@ -811,7 +817,7 @@ newclient(void) { + * It is equivalent to firefox's "layout.css.devPixelsPerPx" setting. + */ + if(zoomto96dpi) { +- screen = gdk_window_get_screen(GTK_WIDGET(c->win)->window); ++ screen = gdk_window_get_screen(window); + dpi = gdk_screen_get_resolution(screen); + if(dpi != -1) { + g_object_set(G_OBJECT(settings), "enforce-96-dpi", true, +@@ -856,7 +862,7 @@ newclient(void) { + if(showxid) { + gdk_display_sync(gtk_widget_get_display(c->win)); + printf("%u\n", +- (guint)GDK_WINDOW_XID(GTK_WIDGET(c->win)->window)); ++ (guint)GDK_WINDOW_XID(window)); + fflush(NULL); + if (fclose(stdout) != 0) { + die("Error closing stdout"); +@@ -1031,7 +1037,7 @@ scroll(GtkAdjustment *a, const Arg *arg) { + static void + setatom(Client *c, int a, const char *v) { + XSync(dpy, False); +- XChangeProperty(dpy, GDK_WINDOW_XID(GTK_WIDGET(c->win)->window), ++ XChangeProperty(dpy, GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(c->win))), + atoms[a], XA_STRING, 8, PropModeReplace, + (unsigned char *)v, strlen(v) + 1); + } +@@ -1047,7 +1053,7 @@ setup(void) { + sigchld(0); + gtk_init(NULL, NULL); + +- dpy = GDK_DISPLAY(); ++ dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + + /* atoms */ + atoms[AtomFind] = XInternAtom(dpy, "_SURF_FIND", False); +@@ -1276,7 +1282,7 @@ updatetitle(Client *c) { + static void + updatewinid(Client *c) { + snprintf(winid, LENGTH(winid), "%u", +- (int)GDK_WINDOW_XID(GTK_WIDGET(c->win)->window)); ++ (int)GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(c->win)))); + } + + static void diff --git a/tools.suckless.org/slock.md b/tools.suckless.org/slock/index.md diff --git a/tools.suckless.org/slock/patches/failcolor.md b/tools.suckless.org/slock/patches/failcolor.md @@ -0,0 +1,17 @@ +Failcolor +========= + +Description +----------- + +Introduces an additional color to indicate an failed login attempt. + +Download +-------- + +* [slock-1.1-failcolor.diff](slock-1.1-failcolor.diff) + +Author +------ + +* Michael Stummvoll <[michael@stummi.org](mailto:michael@stummi.org)> diff --git a/tools.suckless.org/slock/patches/slock-1.1-failcolor.diff b/tools.suckless.org/slock/patches/slock-1.1-failcolor.diff @@ -0,0 +1,67 @@ +diff --git a/config.mk b/config.mk +index 8cc3f68..016a851 100644 +--- a/config.mk ++++ b/config.mk +@@ -14,7 +14,7 @@ INCS = -I. -I/usr/include -I${X11INC} + LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext + + # flags +-CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H -DCOLOR1=\"black\" -DCOLOR2=\"\#005577\" ++CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H -DCOLOR1=\"black\" -DCOLOR2=\"\#005577\" -DCOLOR3=\"\#550000\" + CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} + LDFLAGS = -s ${LIBS} + +diff --git a/slock.c b/slock.c +index 467937c..32f5d96 100644 +--- a/slock.c ++++ b/slock.c +@@ -27,12 +27,13 @@ typedef struct { + int screen; + Window root, win; + Pixmap pmap; +- unsigned long colors[2]; ++ unsigned long colors[3]; + } Lock; + + static Lock **locks; + static int nscreens; + static Bool running = True; ++static Bool tried = False; + + static void + die(const char *errstr, ...) { +@@ -130,6 +131,7 @@ readpw(Display *dpy, const char *pws) + #ifdef HAVE_BSD_AUTH + running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd); + #else ++ tried=True; + running = !!strcmp(crypt(passwd, pws), pws); + #endif + if(running) +@@ -157,7 +159,7 @@ readpw(Display *dpy, const char *pws) + } + } else if(llen != 0 && len == 0) { + for(screen = 0; screen < nscreens; screen++) { +- XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]); ++ XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[tried ? 2 : 0]); + XClearWindow(dpy, locks[screen]->win); + } + } +@@ -174,7 +176,7 @@ unlockscreen(Display *dpy, Lock *lock) { + return; + + XUngrabPointer(dpy, CurrentTime); +- XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, 2, 0); ++ XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, 3, 0); + XFreePixmap(dpy, lock->pmap); + XDestroyWindow(dpy, lock->win); + +@@ -207,6 +209,8 @@ lockscreen(Display *dpy, int screen) { + lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), + 0, DefaultDepth(dpy, lock->screen), CopyFromParent, + DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); ++ XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR3, &color, &dummy); ++ lock->colors[2] = color.pixel; + XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR2, &color, &dummy); + lock->colors[1] = color.pixel; + XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR1, &color, &dummy); diff --git a/tools.suckless.org/tabbed/index.md b/tools.suckless.org/tabbed/index.md @@ -17,5 +17,5 @@ or get a copy using the following command: Download -------- -* [tabbed-0.5](http://dl.suckless.org/tools/tabbed-0.5.tar.gz) (20130506) +* [tabbed-0.6](http://dl.suckless.org/tools/tabbed-0.6.tar.gz) (20140121) diff --git a/tools.suckless.org/tabbed/patches/clientnumber.md b/tools.suckless.org/tabbed/patches/clientnumber.md @@ -0,0 +1,12 @@ +Client number +======== +With this patch, tabbed prints the position number of the client before the +window title. + +Download +-------- +* [tabbed-0.6-clientnumber.diff](tabbed-0.6-clientnumber.diff) + +Author +------ +* Quentin Rameau <quinq@quinq.eu.org> diff --git a/tools.suckless.org/tabbed/patches/index.md b/tools.suckless.org/tabbed/patches/index.md @@ -5,26 +5,26 @@ diff generation --------------- For git users: - cd dmenu-directory - git diff > dmenu-X.Y-yourpatchname.diff + cd tabbed-directory + git diff > tabbed-X.Y-yourpatchname.diff For tarballs: - cd modified-dmenu-directory/.. - diff -up original-dmenu-directory modified-dmenu-directory > dmenu-X.Y-yourpatchname.diff + cd modified-tabbed-directory/.. + diff -up original-tabbed-directory modified-tabbed-directory > tabbed-X.Y-yourpatchname.diff -where `X.Y` is a dmenu tag name or version number. +where `X.Y` is a tabbed tag name or version number. patch application ----------------- For git users: - cd dmenu-directory + cd tabbed-directory git apply path/to/patch.diff For tarballs: - cd dmenu-directory + cd tabbed-directory patch -p1 < path/to/patch.diff diff --git a/tools.suckless.org/tabbed/patches/keycode.md b/tools.suckless.org/tabbed/patches/keycode.md @@ -0,0 +1,12 @@ +Keycode +======== +With this patch, handling key input is done with keycodes instead of keysyms. +This way, input is keyboard layout independant (adapt config.h to your keyboard using for exemple xev). + +Download +-------- +* [tabbed-0.6-keycode.diff](tabbed-0.6-keycode.diff) + +Author +------ +* Quentin Rameau <quinq@quinq.eu.org> diff --git a/tools.suckless.org/tabbed/patches/tabbed-0.6-clientnumber.diff b/tools.suckless.org/tabbed/patches/tabbed-0.6-clientnumber.diff @@ -0,0 +1,36 @@ +diff --git a/config.mk b/config.mk +index 5279711..b0c212c 100644 +--- a/config.mk ++++ b/config.mk +@@ -12,7 +12,7 @@ INCS = -I. -I/usr/include + LIBS = -L/usr/lib -lc -lX11 + + # flags +-CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE ++CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_GNU_SOURCE + CFLAGS = -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} + LDFLAGS = -s ${LIBS} + +diff --git a/tabbed.c b/tabbed.c +index b2adf29..19b5bbb 100644 +--- a/tabbed.c ++++ b/tabbed.c +@@ -308,6 +308,7 @@ drawbar(void) { + unsigned long *col; + int c, fc, width, n = 0; + char *name = NULL; ++ char *tabtitle = NULL; + + if(nclients == 0) { + dc.x = 0; +@@ -353,7 +354,9 @@ drawbar(void) { + } else { + col = dc.norm; + } +- drawtext(clients[c]->name, col); ++ asprintf(&tabtitle, "%d: %s", c + 1, clients[c]->name); ++ drawtext(tabtitle, col); ++ free(tabtitle); + dc.x += dc.w; + clients[c]->tabx = dc.x; + } diff --git a/tools.suckless.org/tabbed/patches/tabbed-0.6-keycode.diff b/tools.suckless.org/tabbed/patches/tabbed-0.6-keycode.diff @@ -0,0 +1,113 @@ +diff --git a/config.def.h b/config.def.h +index ceda9f7..088201a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -29,30 +29,30 @@ static Bool npisrelative = False; + + #define MODKEY ControlMask + static Key keys[] = { \ +- /* modifier key function argument */ +- { MODKEY|ShiftMask, XK_Return, focusonce, { 0 } }, +- { MODKEY|ShiftMask, XK_Return, spawn, { 0 } }, +- { MODKEY, XK_t, spawn, SETPROP("_TABBED_SELECT_TAB") }, +- +- { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, +- { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, +- { MODKEY|ShiftMask, XK_j, movetab, { .i = -1 } }, +- { MODKEY|ShiftMask, XK_k, movetab, { .i = +1 } }, +- { MODKEY, XK_Tab, rotate, { .i = 0 } }, +- +- { MODKEY, XK_1, move, { .i = 0 } }, +- { MODKEY, XK_2, move, { .i = 1 } }, +- { MODKEY, XK_3, move, { .i = 2 } }, +- { MODKEY, XK_4, move, { .i = 3 } }, +- { MODKEY, XK_5, move, { .i = 4 } }, +- { MODKEY, XK_6, move, { .i = 5 } }, +- { MODKEY, XK_7, move, { .i = 6 } }, +- { MODKEY, XK_8, move, { .i = 7 } }, +- { MODKEY, XK_9, move, { .i = 8 } }, +- { MODKEY, XK_0, move, { .i = 9 } }, +- +- { MODKEY, XK_q, killclient, { 0 } }, +- +- { 0, XK_F11, fullscreen, { 0 } }, ++ /* modifier key function argument */ ++ { MODKEY|ShiftMask, 36, focusonce, { 0 } }, // Return ++ { MODKEY|ShiftMask, 36, spawn, { 0 } }, // Return ++ { MODKEY, 44, spawn, SETPROP("_TABBED_SELECT_TAB") }, // t ++ ++ { MODKEY|ShiftMask, 46, rotate, { .i = +1 } }, // l ++ { MODKEY|ShiftMask, 43, rotate, { .i = -1 } }, // h ++ { MODKEY|ShiftMask, 44, movetab, { .i = -1 } }, // j ++ { MODKEY|ShiftMask, 45, movetab, { .i = +1 } }, // k ++ { MODKEY, 23, rotate, { .i = 0 } }, // Tab ++ ++ { MODKEY, 10, move, { .i = 0 } }, // 1 ++ { MODKEY, 11, move, { .i = 1 } }, // 2 ++ { MODKEY, 12, move, { .i = 2 } }, // 3 ++ { MODKEY, 13, move, { .i = 3 } }, // 4 ++ { MODKEY, 14, move, { .i = 4 } }, // 5 ++ { MODKEY, 15, move, { .i = 5 } }, // 6 ++ { MODKEY, 16, move, { .i = 6 } }, // 7 ++ { MODKEY, 17, move, { .i = 7 } }, // 8 ++ { MODKEY, 18, move, { .i = 8 } }, // 9 ++ { MODKEY, 19, move, { .i = 9 } }, // 0 ++ ++ { MODKEY, 24, killclient, { 0 } }, // q ++ ++ { 0, 95, fullscreen, { 0 } }, // F11 + }; + +diff --git a/tabbed.c b/tabbed.c +index 93a213a..744fe4e 100644 +--- a/tabbed.c ++++ b/tabbed.c +@@ -57,7 +57,7 @@ typedef union { + + typedef struct { + unsigned int mod; +- KeySym keysym; ++ KeyCode keycode; + void (*func)(const Arg *); + const Arg arg; + } Key; +@@ -644,11 +644,9 @@ void + keypress(const XEvent *e) { + const XKeyEvent *ev = &e->xkey; + unsigned int i; +- KeySym keysym; + +- keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); + for(i = 0; i < LENGTH(keys); i++) { +- if(keysym == keys[i].keysym ++ if(ev->keycode == keys[i].keycode + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) { + keys[i].func(&(keys[i].arg)); +@@ -684,7 +682,6 @@ manage(Window w) { + int i, j, nextpos; + unsigned int modifiers[] = { 0, LockMask, numlockmask, + numlockmask|LockMask }; +- KeyCode code; + Client *c; + XEvent e; + +@@ -695,13 +692,11 @@ manage(Window w) { + XSync(dpy, False); + + for(i = 0; i < LENGTH(keys); i++) { +- if((code = XKeysymToKeycode(dpy, keys[i].keysym))) { +- for(j = 0; j < LENGTH(modifiers); j++) { +- XGrabKey(dpy, code, keys[i].mod +- | modifiers[j], w, +- True, GrabModeAsync, +- GrabModeAsync); +- } ++ for(j = 0; j < LENGTH(modifiers); j++) { ++ XGrabKey(dpy, keys[i].keycode, keys[i].mod ++ | modifiers[j], w, ++ True, GrabModeAsync, ++ GrabModeAsync); + } + } +