Compare commits

...

17 Commits

Author SHA1 Message Date
Aaron Lindsay
35a7b328bc Remove 'monitor' setting from dmenu_run command
This was added recently and is unsupported on some distributions
2016-12-22 11:22:44 -05:00
Aaron Lindsay
16a3334616 Add initial config file 2016-12-22 11:20:15 -05:00
Aaron Lindsay
f22c769958 Apply 'push' patch
From http://dwm.suckless.org/patches/push
2016-12-22 11:14:52 -05:00
Anselm R Garbe
bb3bd6fec3 applied Markus' tagset purge of alternative view on _NET_ACTIVE_WINDOW event 2016-12-05 10:16:46 +01:00
Anselm R Garbe
e63bf22948 applied Ivan Delalande's NET_SUPPORTING_WM_CHECK patch for gtk3 compatibility 2016-12-05 10:09:49 +01:00
Anselm R Garbe
5376947571 applied Ian Remmler's man page adjustment suggestions 2016-12-05 10:05:00 +01:00
Anselm R Garbe
975c898376 applied Markus' decouple color-scheme patch 2016-12-05 10:01:33 +01:00
Anselm R Garbe
a137a86a23 applied Markus' clarify status text padding patch 2016-12-05 09:54:20 +01:00
Quentin Rameau
839c7f6939 LICENSE: update people 2016-11-15 17:35:33 +01:00
Quentin Rameau
7a59cd1457 dwm.1: add keybinding for spawning dmenu 2016-11-15 17:35:30 +01:00
Hiltjo Posthuma
24849acada die() on calloc failure
thanks Markus Teich and David!
2016-11-05 11:34:52 +01:00
Hiltjo Posthuma
ab9571bbc5 die() consistency: always add newline 2016-08-12 14:36:35 +02:00
Hiltjo Posthuma
56a31dc4a7 config.def.h: style improvement, use color Scheme enum 2016-06-28 18:04:56 +02:00
Markus Teich
7af4d439bd import new drw from libsl and minor fixes.
- better scaling for occupied tag squares.
- draw statusline first to omitt some complicated calculations.
2016-06-26 13:52:36 +02:00
Eric Pruitt
cd2d7549b3 Configure geometry before applying rules
Configuring geometry before applying rules makes it possible to have
more complex constraints in applyrules that depend on the initial window
dimensions and location.
2016-06-24 05:38:58 +02:00
Hiltjo Posthuma
3465bed290 fix fullscreen clients not resized on X display resolution change
patch provided by Bert Münnich <ber.t_AT_posteo.de>, thanks!
2015-12-19 20:25:26 +01:00
Quentin Rameau
4ec3a673ff Shut up glibc about _BSD_SOURCE being deprecated 2015-12-19 20:20:26 +01:00
11 changed files with 472 additions and 264 deletions

16
LICENSE
View File

@@ -1,18 +1,22 @@
MIT/X Consortium License
© 2006-2014 Anselm R Garbe <anselm@garbe.us>
© 2010-2014 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
© 2010-2011 Connor Lane Smith <cls@lubutu.com>
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
© 2007-2009 Christof Musik <christof at sendfax dot de>
© 2009 Mate Nagy <mnagy at port70 dot net>
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
© 2008 Neale Pickett <neale dot woozle dot org>
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2009 Mate Nagy <mnagy at port70 dot net>
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2011 Christoph Lohmann <20h@r-36.net>
© 2015-2016 Quentin Rameau <quinq@fifth.space>
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
© 2016 Markus Teich <markus.teich@stusta.mhn.de>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View File

@@ -1,20 +1,22 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const char *fonts[] = {
"monospace:size=10"
};
static const char dmenufont[] = "monospace:size=10";
static const char normbordercolor[] = "#444444";
static const char normbgcolor[] = "#222222";
static const char normfgcolor[] = "#bbbbbb";
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 snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#005577";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
@@ -54,7 +56,7 @@ static const Layout layouts[] = {
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
static Key keys[] = {

119
config.h Normal file
View File

@@ -0,0 +1,119 @@
/* See LICENSE file for copyright and license details. */
#include "push.c"
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=8" };
static const char dmenufont[] = "monospace:size=8";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#005577";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
// { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
};
/* key definitions */
#define MODKEY Mod3Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
static const char *dmenucmd[] = { "dmenu_run", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY, 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|ShiftMask, 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} },
{ MODKEY|ShiftMask, XK_j, pushdown, {0} },
{ MODKEY|ShiftMask, XK_k, pushup, {0} },
};
/* button definitions */
/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
/* click event mask button function argument */
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};

View File

@@ -25,7 +25,7 @@ INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
# flags
CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}

259
drw.c
View File

@@ -63,9 +63,8 @@ utf8decode(const char *c, long *u, size_t clen)
Drw *
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
{
Drw *drw;
Drw *drw = ecalloc(1, sizeof(Drw));
drw = ecalloc(1, sizeof(Drw));
drw->dpy = dpy;
drw->screen = screen;
drw->root = root;
@@ -73,7 +72,6 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
drw->h = h;
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
drw->gc = XCreateGC(dpy, root, 0, NULL);
drw->fontcount = 0;
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
return drw;
@@ -82,6 +80,9 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
void
drw_resize(Drw *drw, unsigned int w, unsigned int h)
{
if (!drw)
return;
drw->w = w;
drw->h = h;
if (drw->drawable)
@@ -92,84 +93,56 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
void
drw_free(Drw *drw)
{
size_t i;
for (i = 0; i < drw->fontcount; i++)
drw_font_free(drw->fonts[i]);
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
free(drw);
}
/* This function is an implementation detail. Library users should use
* drw_font_create instead.
* drw_fontset_create instead.
*/
static Fnt *
drw_font_xcreate(Drw *drw, const char *fontname, FcPattern *fontpattern)
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
{
Fnt *font;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield same
* the same substitution results as using the pattern returned by
/* Using the pattern found at font->xfont->pattern does not yield the
* same substitution results as using the pattern returned by
* FcNameParse; using the latter results in the desired fallback
* behaviour whereas the former just results in
* missing-character-rectangles being drawn, at least with some fonts.
*/
* behaviour whereas the former just results in missing-character
* rectangles being drawn, at least with some fonts. */
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
return NULL;
}
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
fprintf(stderr, "error, cannot load font: '%s'\n", fontname);
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
XftFontClose(drw->dpy, xfont);
return NULL;
}
} else if (fontpattern) {
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
fprintf(stderr, "error, cannot load font pattern.\n");
fprintf(stderr, "error, cannot load font from pattern.\n");
return NULL;
}
} else {
die("no font specified.\n");
die("no font specified.");
}
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font->pattern = pattern;
font->ascent = xfont->ascent;
font->descent = xfont->descent;
font->h = font->ascent + font->descent;
font->h = xfont->ascent + xfont->descent;
font->dpy = drw->dpy;
return font;
}
Fnt*
drw_font_create(Drw *drw, const char *fontname)
{
return drw_font_xcreate(drw, fontname, NULL);
}
void
drw_load_fonts(Drw* drw, const char *fonts[], size_t fontcount)
{
size_t i;
Fnt *font;
for (i = 0; i < fontcount; i++) {
if (drw->fontcount >= DRW_FONT_CACHE_SIZE) {
die("font cache exhausted.\n");
} else if ((font = drw_font_xcreate(drw, fonts[i], NULL))) {
drw->fonts[drw->fontcount++] = font;
}
}
}
void
drw_font_free(Fnt *font)
static void
xfont_free(Fnt *font)
{
if (!font)
return;
@@ -179,55 +152,98 @@ drw_font_free(Fnt *font)
free(font);
}
Clr *
drw_clr_create(Drw *drw, const char *clrname)
Fnt*
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
{
Clr *clr;
Fnt *cur, *ret = NULL;
size_t i;
if (!drw || !fonts)
return NULL;
for (i = 1; i <= fontcount; i++) {
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
cur->next = ret;
ret = cur;
}
}
return (drw->fonts = ret);
}
void
drw_fontset_free(Fnt *font)
{
if (font) {
drw_fontset_free(font->next);
xfont_free(font);
}
}
void
drw_clr_create(Drw *drw, XftColor *dest, const char *clrname)
{
if (!drw || !dest || !clrname)
return;
clr = ecalloc(1, sizeof(Clr));
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen),
clrname, &clr->rgb))
die("error, cannot allocate color '%s'\n", clrname);
clr->pix = clr->rgb.pixel;
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
}
return clr;
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
Scm
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
{
size_t i;
Scm ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
return NULL;
for (i = 0; i < clrcount; i++)
drw_clr_create(drw, &ret[i], clrnames[i]);
return ret;
}
void
drw_clr_free(Clr *clr)
drw_setfontset(Drw *drw, Fnt *set)
{
free(clr);
if (drw)
drw->fonts = set;
}
void
drw_setscheme(Drw *drw, ClrScheme *scheme)
drw_setscheme(Drw *drw, Scm scm)
{
drw->scheme = scheme;
if (drw)
drw->scheme = scm;
}
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int empty, int invert)
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
{
if (!drw->scheme)
if (!drw || !drw->scheme)
return;
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme->bg->pix : drw->scheme->fg->pix);
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
if (filled)
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w + 1, h + 1);
else if (empty)
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
else
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
}
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int invert)
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
{
char buf[1024];
int tx, ty, th;
Extnts tex;
int ty;
unsigned int ew;
XftDraw *d = NULL;
Fnt *curfont, *nextfont;
Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render;
int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
FcCharSet *fccharset;
@@ -236,66 +252,67 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
XftResult result;
int charexists = 0;
if (!drw->scheme || !drw->fontcount)
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
return 0;
if (!(render = x || y || w || h)) {
if (!render) {
w = ~w;
} else {
XSetForeground(drw->dpy, drw->gc, invert ?
drw->scheme->fg->pix : drw->scheme->bg->pix);
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen));
x += lpad;
w -= lpad;
}
curfont = drw->fonts[0];
usedfont = drw->fonts;
while (1) {
utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
for (i = 0; i < drw->fontcount; i++) {
charexists = charexists || XftCharExists(drw->dpy, drw->fonts[i]->xfont, utf8codepoint);
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
if (drw->fonts[i] == curfont) {
if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
} else {
nextfont = drw->fonts[i];
nextfont = curfont;
}
break;
}
}
if (!charexists || (nextfont && nextfont != curfont))
if (!charexists || nextfont)
break;
else
charexists = 0;
}
if (utf8strlen) {
drw_font_getexts(curfont, utf8str, utf8strlen, &tex);
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
/* shorten text if necessary */
for (len = MIN(utf8strlen, (sizeof buf) - 1); len && (tex.w > w - drw->fonts[0]->h || w < drw->fonts[0]->h); len--)
drw_font_getexts(curfont, utf8str, len, &tex);
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
if (len) {
memcpy(buf, utf8str, len);
buf[len] = '\0';
if (len < utf8strlen)
for (i = len; i && i > len - 3; buf[--i] = '.');
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (render) {
th = curfont->ascent + curfont->descent;
ty = y + (h / 2) - (th / 2) + curfont->ascent;
tx = x + (h / 2);
XftDrawStringUtf8(d, invert ? &drw->scheme->bg->rgb : &drw->scheme->fg->rgb, curfont->xfont, tx, ty, (XftChar8 *)buf, len);
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
}
x += tex.w;
w -= tex.w;
x += ew;
w -= ew;
}
}
@@ -303,26 +320,21 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
break;
} else if (nextfont) {
charexists = 0;
curfont = nextfont;
usedfont = nextfont;
} else {
/* Regardless of whether or not a fallback font is found, the
* character must be drawn.
*/
* character must be drawn. */
charexists = 1;
if (drw->fontcount >= DRW_FONT_CACHE_SIZE)
continue;
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
if (!drw->fonts[0]->pattern) {
/* Refer to the comment in drw_font_xcreate for more
* information. */
die("the first font in the cache must be loaded from a font string.\n");
if (!drw->fonts->pattern) {
/* Refer to the comment in xfont_create for more information. */
die("the first font in the cache must be loaded from a font string.");
}
fcpattern = FcPatternDuplicate(drw->fonts[0]->pattern);
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
@@ -334,12 +346,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
FcPatternDestroy(fcpattern);
if (match) {
curfont = drw_font_xcreate(drw, NULL, match);
if (curfont && XftCharExists(drw->dpy, curfont->xfont, utf8codepoint)) {
drw->fonts[drw->fontcount++] = curfont;
usedfont = xfont_create(drw, NULL, match);
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
; /* NOP */
curfont->next = usedfont;
} else {
drw_font_free(curfont);
curfont = drw->fonts[0];
xfont_free(usedfont);
usedfont = drw->fonts;
}
}
}
@@ -347,34 +361,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *tex
if (d)
XftDrawDestroy(d);
return x;
return x + (render ? w : 0);
}
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
{
if (!drw)
return;
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
XSync(drw->dpy, False);
}
unsigned int
drw_fontset_getwidth(Drw *drw, const char *text)
{
if (!drw || !drw->fonts || !text)
return 0;
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
}
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, Extnts *tex)
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
XGlyphInfo ext;
if (!font || !text)
return;
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
tex->h = font->h;
tex->w = ext.xOff;
}
unsigned int
drw_font_getexts_width(Fnt *font, const char *text, unsigned int len)
{
Extnts tex;
drw_font_getexts(font, text, len, &tex);
return tex.w;
if (w)
*w = ext.xOff;
if (h)
*h = font->h;
}
Cur *
@@ -382,7 +402,9 @@ drw_cur_create(Drw *drw, int shape)
{
Cur *cur;
cur = ecalloc(1, sizeof(Cur));
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
return NULL;
cur->cursor = XCreateFontCursor(drw->dpy, shape);
return cur;
@@ -393,6 +415,7 @@ drw_cur_free(Drw *drw, Cur *cursor)
{
if (!cursor)
return;
XFreeCursor(drw->dpy, cursor->cursor);
free(cursor);
}

63
drw.h
View File

@@ -1,29 +1,19 @@
/* See LICENSE file for copyright and license details. */
#define DRW_FONT_CACHE_SIZE 32
typedef struct {
unsigned long pix;
XftColor rgb;
} Clr;
typedef struct {
Cursor cursor;
} Cur;
typedef struct {
typedef struct Fnt {
Display *dpy;
int ascent;
int descent;
unsigned int h;
XftFont *xfont;
FcPattern *pattern;
struct Fnt *next;
} Fnt;
typedef struct {
Clr *fg;
Clr *bg;
Clr *border;
} ClrScheme;
enum { ColFg, ColBg, ColCount }; /* Scm index */
typedef XftColor *Scm;
typedef struct {
unsigned int w, h;
@@ -32,43 +22,36 @@ typedef struct {
Window root;
Drawable drawable;
GC gc;
ClrScheme *scheme;
size_t fontcount;
Fnt *fonts[DRW_FONT_CACHE_SIZE];
Scm scheme;
Fnt *fonts;
} Drw;
typedef struct {
unsigned int w;
unsigned int h;
} Extnts;
/* Drawable abstraction */
Drw *drw_create(Display *, int, Window, unsigned int, unsigned int);
void drw_resize(Drw *, unsigned int, unsigned int);
void drw_free(Drw *);
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
void drw_free(Drw *drw);
/* Fnt abstraction */
Fnt *drw_font_create(Drw *, const char *);
void drw_load_fonts(Drw *, const char *[], size_t);
void drw_font_free(Fnt *);
void drw_font_getexts(Fnt *, const char *, unsigned int, Extnts *);
unsigned int drw_font_getexts_width(Fnt *, const char *, unsigned int);
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colour abstraction */
Clr *drw_clr_create(Drw *, const char *);
void drw_clr_free(Clr *);
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, XftColor *dest, const char *clrname);
Scm drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *, int);
void drw_cur_free(Drw *, Cur *);
Cur *drw_cur_create(Drw *drw, int shape);
void drw_cur_free(Drw *drw, Cur *cursor);
/* Drawing context manipulation */
void drw_setfont(Drw *, Fnt *);
void drw_setscheme(Drw *, ClrScheme *);
void drw_setfontset(Drw *drw, Fnt *set);
void drw_setscheme(Drw *drw, Scm scm);
/* Drawing functions */
void drw_rect(Drw *, int, int, unsigned int, unsigned int, int, int, int);
int drw_text(Drw *, int, int, unsigned int, unsigned int, const char *, int);
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
/* Map functions */
void drw_map(Drw *, Window, int, int, unsigned int, unsigned int);
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);

14
dwm.1
View File

@@ -10,8 +10,9 @@ and floating layouts. Either layout can be applied dynamically, optimising the
environment for the application in use and the task performed.
.P
In tiled layouts windows are managed in a master and stacking area. The master
area contains the window which currently needs most attention, whereas the
stacking area contains all other windows. In monocle layout all windows are
area on the left contains one window by default, and the stacking area on the
right contains all other windows. The number of master area windows can be
adjusted from zero to an arbitrary number. In monocle layout all windows are
maximised to the screen size. In floating layout windows can be resized and
moved freely. Dialog windows are always managed floating, regardless of the
layout applied.
@@ -59,6 +60,11 @@ click on a tag label adds/removes that tag to/from the focused window.
Start
.BR st(1).
.TP
.B Mod1\-p
Spawn
.BR dmenu(1)
for launching other programs.
.TP
.B Mod1\-,
Focus previous screen, if any.
.TP
@@ -93,10 +99,10 @@ Focus next window.
Focus previous window.
.TP
.B Mod1\-i
Increase clients in master area.
Increase number of windows in master area.
.TP
.B Mod1\-d
Decrease clients in master area.
Decrease number of windows in master area.
.TP
.B Mod1\-l
Increase master area size.

173
dwm.c
View File

@@ -55,12 +55,13 @@
#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) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
#define ColBorder 2
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState,
enum { SchemeNorm, SchemeSel }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
@@ -152,7 +153,6 @@ static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
static void clearurgent(Client *c);
static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
@@ -203,6 +203,7 @@ static void setfullscreen(Client *c, int fullscreen);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
@@ -240,6 +241,7 @@ static char stext[256];
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
@@ -261,11 +263,11 @@ static void (*handler[LASTEvent]) (XEvent *) = {
static Atom wmatom[WMLast], netatom[NetLast];
static int running = 1;
static Cur *cursor[CurLast];
static ClrScheme scheme[SchemeLast];
static Scm *scheme;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
static Window root;
static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
#include "config.h"
@@ -481,11 +483,9 @@ cleanup(void)
cleanupmon(mons);
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < SchemeLast; i++) {
drw_clr_free(scheme[i].border);
drw_clr_free(scheme[i].bg);
drw_clr_free(scheme[i].fg);
}
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
XSync(dpy, False);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
@@ -508,19 +508,6 @@ cleanupmon(Monitor *mon)
free(mon);
}
void
clearurgent(Client *c)
{
XWMHints *wmh;
c->isurgent = 0;
if (!(wmh = XGetWMHints(dpy, c->win)))
return;
wmh->flags &= ~XUrgencyHint;
XSetWMHints(dpy, c->win, wmh);
XFree(wmh);
}
void
clientmessage(XEvent *e)
{
@@ -534,11 +521,8 @@ clientmessage(XEvent *e)
setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
} else if (cme->message_type == netatom[NetActiveWindow]) {
if (!ISVISIBLE(c)) {
c->mon->seltags ^= 1;
c->mon->tagset[c->mon->seltags] = c->tags;
}
pop(c);
if (c != selmon->sel && !c->isurgent)
seturgent(c, 1);
}
}
@@ -565,6 +549,7 @@ void
configurenotify(XEvent *e)
{
Monitor *m;
Client *c;
XConfigureEvent *ev = &e->xconfigure;
int dirty;
@@ -576,8 +561,12 @@ configurenotify(XEvent *e)
if (updategeom() || dirty) {
drw_resize(drw, sw, bh);
updatebars();
for (m = mons; m; m = m->next)
for (m = mons; m; m = m->next) {
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
}
focus(NULL);
arrange(NULL);
}
@@ -704,11 +693,18 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
int x, xx, w, dx;
int x, w, sw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
Client *c;
dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4;
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]);
sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
}
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
@@ -718,36 +714,27 @@ drawbar(Monitor *m)
x = 0;
for (i = 0; i < LENGTH(tags); i++) {
w = TEXTW(tags[i]);
drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i);
drw_rect(drw, x + 1, 1, dx, dx, m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
occ & 1 << i, urg & 1 << i);
drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
if (occ & 1 << i)
drw_rect(drw, x + boxs, boxs, boxw, boxw,
m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
urg & 1 << i);
x += w;
}
w = blw = TEXTW(m->ltsymbol);
drw_setscheme(drw, &scheme[SchemeNorm]);
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);
} else
x = m->ww;
if ((w = x - xx) > bh) {
x = xx;
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
if ((w = m->ww - sw - x) > bh) {
if (m->sel) {
drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, m->sel->name, 0);
drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0);
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
if (m->sel->isfloating)
drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
} else {
drw_setscheme(drw, &scheme[SchemeNorm]);
drw_rect(drw, x, 0, w, bh, 1, 0, 1);
drw_setscheme(drw, scheme[SchemeNorm]);
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
drw_map(drw, m->barwin, 0, 0, m->ww, bh);
@@ -803,11 +790,11 @@ focus(Client *c)
if (c->mon != selmon)
selmon = c->mon;
if (c->isurgent)
clearurgent(c);
seturgent(c, 0);
detachstack(c);
attachstack(c);
grabbuttons(c, 1);
XSetWindowBorder(dpy, c->win, scheme[SchemeSel].border->pix);
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
setfocus(c);
} else {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
@@ -1038,6 +1025,13 @@ manage(Window w, XWindowAttributes *wa)
c = ecalloc(1, sizeof(Client));
c->win = w;
/* geometry */
c->x = c->oldx = wa->x;
c->y = c->oldy = wa->y;
c->w = c->oldw = wa->width;
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
updatetitle(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
@@ -1046,12 +1040,6 @@ manage(Window w, XWindowAttributes *wa)
c->mon = selmon;
applyrules(c);
}
/* geometry */
c->x = c->oldx = wa->x;
c->y = c->oldy = wa->y;
c->w = c->oldw = wa->width;
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
c->x = c->mon->mx + c->mon->mw - WIDTH(c);
@@ -1065,7 +1053,7 @@ manage(Window w, XWindowAttributes *wa)
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix);
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
configure(c); /* propagates border_width, if size doesn't change */
updatewindowtype(c);
updatesizehints(c);
@@ -1546,7 +1534,9 @@ setmfact(const Arg *arg)
void
setup(void)
{
int i;
XSetWindowAttributes wa;
Atom utf8string;
/* clean up any zombies immediately */
sigchld(0);
@@ -1557,12 +1547,13 @@ setup(void)
sh = DisplayHeight(dpy, screen);
root = RootWindow(dpy, screen);
drw = drw_create(dpy, screen, root, sw, sh);
drw_load_fonts(drw, fonts, LENGTH(fonts));
if (!drw->fontcount)
die("no fonts could be loaded.\n");
bh = drw->fonts[0]->h + 2;
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
bh = drw->fonts->h + 2;
updategeom();
/* init atoms */
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
@@ -1571,6 +1562,7 @@ setup(void)
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
@@ -1580,15 +1572,20 @@ setup(void)
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
/* init appearance */
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].border = drw_clr_create(drw, selbordercolor);
scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor);
scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor);
scheme = ecalloc(LENGTH(colors), sizeof(Scm));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
/* init bars */
updatebars();
updatestatus();
/* supporting window for NetWMCheck */
wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &wmcheckwin, 1);
XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
PropModeReplace, (unsigned char *) "dwm", 4);
XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &wmcheckwin, 1);
/* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
@@ -1603,6 +1600,20 @@ setup(void)
focus(NULL);
}
void
seturgent(Client *c, int urg)
{
XWMHints *wmh;
c->isurgent = urg;
if (!(wmh = XGetWMHints(dpy, c->win)))
return;
wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
XSetWMHints(dpy, c->win, wmh);
XFree(wmh);
}
void
showhide(Client *c)
{
@@ -1745,7 +1756,7 @@ unfocus(Client *c, int setfocus)
if (!c)
return;
grabbuttons(c, 0);
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->pix);
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
if (setfocus) {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
@@ -2102,7 +2113,7 @@ xerrordummy(Display *dpy, XErrorEvent *ee)
int
xerrorstart(Display *dpy, XErrorEvent *ee)
{
die("dwm: another window manager is already running\n");
die("dwm: another window manager is already running");
return -1;
}
@@ -2124,13 +2135,13 @@ int
main(int argc, char *argv[])
{
if (argc == 2 && !strcmp("-v", argv[1]))
die("dwm-"VERSION "\n");
die("dwm-"VERSION);
else if (argc != 1)
die("usage: dwm [-v]\n");
die("usage: dwm [-v]");
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display\n");
die("dwm: cannot open display");
checkotherwm();
setup();
scan();

58
push.c Normal file
View File

@@ -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);
}

4
util.c
View File

@@ -12,7 +12,7 @@ ecalloc(size_t nmemb, size_t size)
void *p;
if (!(p = calloc(nmemb, size)))
perror(NULL);
die("calloc:");
return p;
}
@@ -27,6 +27,8 @@ die(const char *fmt, ...) {
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
fputc(' ', stderr);
perror(NULL);
} else {
fputc('\n', stderr);
}
exit(1);

4
util.h
View File

@@ -4,5 +4,5 @@
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
void die(const char *errstr, ...);
void *ecalloc(size_t, size_t);
void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);