summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h110
-rw-r--r--config.mk5
-rw-r--r--drw.c91
-rw-r--r--drw.h1
-rw-r--r--dwm.115
-rw-r--r--dwm.c364
6 files changed, 240 insertions, 346 deletions
diff --git a/config.h b/config.h
index 17cc135..41adc9f 100644
--- a/config.h
+++ b/config.h
@@ -2,15 +2,11 @@
/* appearance */
static const unsigned int borderpx = 2; /* border pixel of windows */
-static const unsigned int gappx = 12; /* gaps between windows */
+static const unsigned int gappx = 12; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
-static const int user_bh = 22; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
-static const int usealtbar = 0; /* 1 means use non-dwm status bar */
-static const char *altbarclass = "Polybar";/* Alternate bar class name */
-static const char *alttrayname = "tray"; /* Polybar tray instance name */
-static const char *altbarcmd = ""; /* Alternate bar launch command */
+static const int user_bh = 22; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
static const char *fonts[] = { "FiraCode Nerd Font Mono:style=Regular:size=10" };
static const char dmenufont[] = "FiraCode Nerd Font Mono:style=Regular:size=10";
static const char col_gray1[] = "#282828";
@@ -41,6 +37,7 @@ static const Rule rules[] = {
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const Layout layouts[] = {
/* symbol arrange function */
@@ -63,8 +60,8 @@ 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", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
-static const char *dmenunmcmd[] = { "networkmanager_dmenu", NULL };
static const char *termcmd[] = { "st", NULL };
+static const char *dmenunmcmd[] = { "networkmanager_dmenu", NULL };
static const char *browsercmd[] = { "firefox", NULL };
static const char *volup[] = { "pactl", "set-sink-volume", "0", "+10%", NULL };
static const char *voldown[] = { "pactl", "set-sink-volume", "0", "-10%", NULL };
@@ -72,69 +69,56 @@ static const char *volmax[] = { "pactl", "set-sink-volume", "0", "100%", NULL };
static const char *volmute[] = { "pactl", "set-sink-volume", "0", "0%", NULL };
static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_space, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_space, spawn, {.v = dmenunmcmd } },
- { MODKEY, XK_a, spawn, {.v = termcmd } },
- { MODKEY, XK_f, spawn, {.v = browsercmd } },
- { MODKEY, XK_j, spawn, {.v = volup } },
- { MODKEY, XK_k, spawn, {.v = voldown } },
- { MODKEY, XK_l, spawn, {.v = volmax } },
- { MODKEY|ShiftMask, XK_l, spawn, {.v = volmute } },
+ /* modifier key function argument */
+ { MODKEY, XK_space, spawn, {.v = dmenucmd } },
+ { MODKEY|ShiftMask, XK_space, spawn, {.v = dmenunmcmd } },
+ { MODKEY, XK_a, spawn, {.v = termcmd } },
+ { MODKEY, XK_f, spawn, {.v = browsercmd } },
+ { MODKEY, XK_j, spawn, {.v = volup } },
+ { MODKEY, XK_k, spawn, {.v = voldown } },
+ { MODKEY, XK_l, spawn, {.v = volmax } },
+ { MODKEY|ShiftMask, XK_l, spawn, {.v = volmute } },
- { 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, XK_w, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- //{ MODKEY, XK_o, setlayout, {.v = &layouts[1]} },
- //{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY, XK_m, fullscreen, {0} },
- //{ MODKEY, XK_p, setlayout, {0} },
- { MODKEY|ShiftMask, XK_f, 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 } },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY, XK_w, killclient, {0} },
+ { MODKEY|ShiftMask, XK_m, togglefullscr, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefloating, {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 } },
- { MODKEY, XK_minus, setgaps, {.i = -1 } },
- { MODKEY, XK_equal, setgaps, {.i = +1 } },
- { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
+ { MODKEY, XK_minus, setgaps, {.i = -1 } },
+ { MODKEY, XK_equal, setgaps, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
- TAGKEYS( XK_1, 0)
- TAGKEYS( XK_2, 1)
- TAGKEYS( XK_3, 2)
- TAGKEYS( XK_4, 3)
- TAGKEYS( XK_5, 4)
- TAGKEYS( XK_6, 5)
- TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
- TAGKEYS( XK_9, 8)
+ TAGKEYS( XK_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_q, quit, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static Button buttons[] = {
- /* click event mask button function argument */
- { ClkLtSymbol, 0, Button1, setlayout, {0} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
- { 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} },
+ /* 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} },
};
diff --git a/config.mk b/config.mk
index 6d36cb7..81c493e 100644
--- a/config.mk
+++ b/config.mk
@@ -1,5 +1,5 @@
# dwm version
-VERSION = 6.2
+VERSION = 6.3
# Customize below to fit your system
@@ -19,13 +19,14 @@ FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
+#MANPREFIX = ${PREFIX}/man
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
# flags
-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS}
diff --git a/drw.c b/drw.c
index 490a592..ced7d37 100644
--- a/drw.c
+++ b/drw.c
@@ -95,6 +95,7 @@ drw_free(Drw *drw)
{
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
+ drw_fontset_free(drw->fonts);
free(drw);
}
@@ -202,8 +203,6 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
DefaultColormap(drw->dpy, drw->screen),
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
-
- dest->pixel |= 0xff << 24;
}
/* Wrapper to create color schemes. The caller has to call free(3) on the
@@ -252,12 +251,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
int
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 ty;
- unsigned int ew;
+ int i, ty, ellipsis_x = 0;
+ unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont;
- size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
@@ -265,13 +262,17 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
FcPattern *fcpattern;
FcPattern *match;
XftResult result;
- int charexists = 0;
+ int charexists = 0, overflow = 0;
+ /* keep track of a couple codepoints for which we have no match. */
+ enum { nomatches_len = 64 };
+ static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
+ static unsigned int ellipsis_width = 0;
- if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
+ if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0;
if (!render) {
- w = ~w;
+ w = invert ? invert : ~invert;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@@ -283,8 +284,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
}
usedfont = drw->fonts;
+ if (!ellipsis_width && render)
+ ellipsis_width = drw_fontset_getwidth(drw, "...");
while (1) {
- utf8strlen = 0;
+ ew = ellipsis_len = utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
@@ -292,9 +295,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
- if (curfont == usedfont) {
+ drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
+ if (ew + ellipsis_width <= w) {
+ /* keep track where the ellipsis still fits */
+ ellipsis_x = x + ew;
+ ellipsis_w = w - ew;
+ ellipsis_len = utf8strlen;
+ }
+
+ if (ew + tmpw > w) {
+ overflow = 1;
+ /* called from drw_fontset_getwidth_clamp():
+ * it wants the width AFTER the overflow
+ */
+ if (!render)
+ x += tmpw;
+ else
+ utf8strlen = ellipsis_len;
+ } else if (curfont == usedfont) {
utf8strlen += utf8charlen;
text += utf8charlen;
+ ew += tmpw;
} else {
nextfont = curfont;
}
@@ -302,36 +323,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
}
}
- if (!charexists || nextfont)
+ if (overflow || !charexists || nextfont)
break;
else
charexists = 0;
}
if (utf8strlen) {
- drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
- /* shorten text if necessary */
- 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] = '.')
- ; /* NOP */
-
- if (render) {
- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
- usedfont->xfont, x, ty, (XftChar8 *)buf, len);
- }
- x += ew;
- w -= ew;
+ if (render) {
+ ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
+ XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
+ usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
}
+ x += ew;
+ w -= ew;
}
+ if (render && overflow)
+ drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
- if (!*text) {
+ if (!*text || overflow) {
break;
} else if (nextfont) {
charexists = 0;
@@ -341,6 +351,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
* character must be drawn. */
charexists = 1;
+ for (i = 0; i < nomatches_len; ++i) {
+ /* avoid calling XftFontMatch if we know we won't find a match */
+ if (utf8codepoint == nomatches.codepoint[i])
+ goto no_match;
+ }
+
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
@@ -369,6 +385,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
curfont->next = usedfont;
} else {
xfont_free(usedfont);
+ nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
+no_match:
usedfont = drw->fonts;
}
}
@@ -398,6 +416,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
}
+unsigned int
+drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
+{
+ unsigned int tmp = 0;
+ if (drw && drw->fonts && text && n)
+ tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
+ return MIN(n, tmp);
+}
+
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
diff --git a/drw.h b/drw.h
index 4bcd5ad..6471431 100644
--- a/drw.h
+++ b/drw.h
@@ -35,6 +35,7 @@ void drw_free(Drw *drw);
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);
+unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */
diff --git a/dwm.1 b/dwm.1
index 0202d96..3d310ac 100644
--- a/dwm.1
+++ b/dwm.1
@@ -33,7 +33,7 @@ dwm draws a small border around windows to indicate the focus state.
.SH OPTIONS
.TP
.B \-v
-prints version information to standard output, then exits.
+prints version information to stderr, then exits.
.SH USAGE
.SS Status bar
.TP
@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
.B Mod1\-Shift\-c
Close focused window.
.TP
+.B Mod1\-Shift\-f
+Toggle fullscreen for focused window.
+.TP
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state.
.TP
@@ -140,16 +143,6 @@ View all windows with any tag.
.B Mod1\-Control\-[1..n]
Add/remove all windows with nth tag to/from the view.
.TP
-.B Mod1\--
-Decrease the gaps around windows.
-.TP
-.B Mod1\-=
-Increase the gaps around windows.
-.TP
-.B Mod1\-Shift-=
-Reset the gaps around windows to
-.BR 0 .
-.TP
.B Mod1\-Shift\-q
Quit dwm.
.SS Mouse commands
diff --git a/dwm.c b/dwm.c
index f5bdff0..f79ad07 100644
--- a/dwm.c
+++ b/dwm.c
@@ -47,8 +47,8 @@
/* macros */
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
-#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->mx+(m)->mw) - MAX((x),(m)->mx)) \
- * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my)))
+#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 LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
@@ -89,7 +89,7 @@ struct Client {
float mina, maxa;
int x, y, w, h;
int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
@@ -116,8 +116,7 @@ struct Monitor {
float mfact;
int nmaster;
int num;
- int by, bh; /* bar geometry */
- int tx, tw; /* bar tray geometry */
+ int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
int gappx; /* gaps between windows */
@@ -131,7 +130,6 @@ struct Monitor {
Client *stack;
Monitor *next;
Window barwin;
- Window traywin;
const Layout *lt[2];
};
@@ -171,16 +169,17 @@ static void expose(XEvent *e);
static void focus(Client *c);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
+static void focusstack(const Arg *arg);
+static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
+static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
-static void managealtbar(Window win, XWindowAttributes *wa);
-static void managetray(Window win, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
@@ -197,32 +196,29 @@ static void resizemouse(const Arg *arg);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
-static void scantray(void);
static int sendevent(Client *c, Atom proto);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
-static void fullscreen(const Arg *arg);
static void setgaps(const Arg *arg);
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);
-static void spawnbar();
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
-static void unmanagealtbar(Window w);
-static void unmanagetray(Window w);
static void unmapnotify(XEvent *e);
static void updatebarpos(Monitor *m);
static void updatebars(void);
@@ -237,7 +233,6 @@ static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
-static int wmclasscontains(Window win, const char *class, const char *name);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
@@ -353,6 +348,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
if (*w < bh)
*w = bh;
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
+ if (!c->hintsvalid)
+ updatesizehints(c);
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh;
if (!baseismin) { /* temporarily remove base dimensions */
@@ -448,7 +445,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
+ else if (ev->x > selmon->ww - (int)TEXTW(stext))
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -495,6 +492,7 @@ cleanup(void)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
+ free(scheme);
XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
XSync(dpy, False);
@@ -513,10 +511,8 @@ cleanupmon(Monitor *mon)
for (m = mons; m && m->next != mon; m = m->next);
m->next = mon->next;
}
- if (!usealtbar) {
- XUnmapWindow(dpy, mon->barwin);
- XDestroyWindow(dpy, mon->barwin);
- }
+ XUnmapWindow(dpy, mon->barwin);
+ XDestroyWindow(dpy, mon->barwin);
free(mon);
}
@@ -578,7 +574,7 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, m->bh);
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
}
focus(NULL);
arrange(NULL);
@@ -648,9 +644,8 @@ createmon(void)
m->mfact = mfact;
m->nmaster = nmaster;
m->showbar = showbar;
- m->gappx = gappx;
m->topbar = topbar;
- m->bh = bh;
+ m->gappx = gappx;
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@@ -661,15 +656,10 @@ void
destroynotify(XEvent *e)
{
Client *c;
- Monitor *m;
XDestroyWindowEvent *ev = &e->xdestroywindow;
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
- else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
- unmanagealtbar(ev->window);
- else if (m->traywin == ev->window)
- unmanagetray(ev->window);
}
void
@@ -713,20 +703,20 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- if (usealtbar)
- return;
-
- int x, w, sw = 0;
+ int x, w, tw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
Client *c;
+ if (!m->showbar)
+ return;
+
/* 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);
+ tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
}
for (c = m->clients; c; c = c->next) {
@@ -749,7 +739,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
- if ((w = m->ww - sw - x) > bh) {
+ if ((w = m->ww - tw - x) > bh) {
if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
@@ -850,6 +840,32 @@ focusmon(const Arg *arg)
focus(NULL);
}
+void
+focusstack(const Arg *arg)
+{
+ Client *c = NULL, *i;
+
+ if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
+ 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);
+ }
+}
+
Atom
getatomprop(Client *c, Atom prop)
{
@@ -958,6 +974,13 @@ grabkeys(void)
}
}
+void
+incnmaster(const Arg *arg)
+{
+ selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
+ arrange(selmon);
+}
+
#ifdef XINERAMA
static int
isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
@@ -1067,45 +1090,6 @@ manage(Window w, XWindowAttributes *wa)
}
void
-managealtbar(Window win, XWindowAttributes *wa)
-{
- Monitor *m;
- if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
- return;
-
- m->barwin = win;
- m->by = wa->y;
- bh = m->bh = wa->height;
- updatebarpos(m);
- arrange(m);
- XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
- XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
- XMapWindow(dpy, win);
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &win, 1);
-}
-
-void
-managetray(Window win, XWindowAttributes *wa)
-{
- Monitor *m;
- if (!(m = recttomon(wa->x, wa->y, wa->width, wa->height)))
- return;
-
- m->traywin = win;
- m->tx = wa->x;
- m->tw = wa->width;
- updatebarpos(m);
- arrange(m);
- XSelectInput(dpy, win, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
- XMoveResizeWindow(dpy, win, wa->x, wa->y, wa->width, wa->height);
- XMapWindow(dpy, win);
- XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &win, 1);
-}
-
-
-void
mappingnotify(XEvent *e)
{
XMappingEvent *ev = &e->xmapping;
@@ -1125,9 +1109,7 @@ maprequest(XEvent *e)
return;
if (wa.override_redirect)
return;
- if (wmclasscontains(ev->window, altbarclass, ""))
- managealtbar(ev->window, &wa);
- else if (!wintoclient(ev->window))
+ if (!wintoclient(ev->window))
manage(ev->window, &wa);
}
@@ -1259,7 +1241,7 @@ propertynotify(XEvent *e)
arrange(c->mon);
break;
case XA_WM_NORMAL_HINTS:
- updatesizehints(c);
+ c->hintsvalid = 0;
break;
case XA_WM_HINTS:
updatewmhints(c);
@@ -1423,9 +1405,7 @@ scan(void)
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
continue;
- if (wmclasscontains(wins[i], altbarclass, ""))
- managealtbar(wins[i], &wa);
- else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
+ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
manage(wins[i], &wa);
}
for (i = 0; i < num; i++) { /* now the transients */
@@ -1441,29 +1421,6 @@ scan(void)
}
void
-scantray(void)
-{
- unsigned int num;
- Window d1, d2, *wins = NULL;
- XWindowAttributes wa;
-
- if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
- for (unsigned int i = 0; i < num; i++) {
- if (wmclasscontains(wins[i], altbarclass, alttrayname)) {
- if (!XGetWindowAttributes(dpy, wins[i], &wa))
- break;
- managetray(wins[i], &wa);
- }
- }
- }
-
- if (wins)
- XFree(wins);
-}
-
-
-
-void
sendmon(Client *c, Monitor *m)
{
if (c->mon == m)
@@ -1563,19 +1520,6 @@ setgaps(const Arg *arg)
arrange(selmon);
}
-Layout *last_layout;
-void
-fullscreen(const Arg *arg)
-{
- if (selmon->showbar) {
- for(last_layout = (Layout *)layouts; last_layout != selmon->lt[selmon->sellt]; last_layout++);
- setlayout(&((Arg) { .v = &layouts[2] }));
- } else {
- setlayout(&((Arg) { .v = last_layout }));
- }
- togglebar(arg);
-}
-
void
setlayout(const Arg *arg)
{
@@ -1590,6 +1534,21 @@ setlayout(const Arg *arg)
drawbar(selmon);
}
+/* arg > 1.0 will set mfact absolutely */
+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.05 || f > 0.95)
+ return;
+ selmon->mfact = f;
+ arrange(selmon);
+}
+
void
setup(void)
{
@@ -1609,8 +1568,7 @@ setup(void)
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
- bh = user_bh ? user_bh : drw->fonts->h + 2;
- //bh = usealtbar ? 0 : drw->fonts->h + 2;
+ bh = user_bh ? user_bh : drw->fonts->h + 2;
updategeom();
/* init atoms */
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
@@ -1659,7 +1617,6 @@ setup(void)
XSelectInput(dpy, root, wa.event_mask);
grabkeys();
focus(NULL);
- spawnbar();
}
@@ -1719,13 +1676,6 @@ spawn(const Arg *arg)
}
void
-spawnbar()
-{
- if (*altbarcmd)
- system(altbarcmd);
-}
-
-void
tag(const Arg *arg)
{
if (selmon->sel && arg->ui & TAGMASK) {
@@ -1761,31 +1711,20 @@ tile(Monitor *m)
if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
- if (my + HEIGHT(c) + m->gappx < m->wh)
- my += HEIGHT(c) + m->gappx;
+ my += HEIGHT(c) + m->gappx;
} else {
h = (m->wh - ty) / (n - i) - m->gappx;
resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
- if (ty + HEIGHT(c) + m->gappx < m->wh)
- ty += HEIGHT(c) + m->gappx;
+ ty += HEIGHT(c) + m->gappx;
}
}
void
togglebar(const Arg *arg)
{
- /**
- * Polybar tray does not raise maprequest event. It must be manually scanned
- * for. Scanning it too early while the tray is being populated would give
- * wrong dimensions.
- */
- if (!selmon->traywin)
- scantray();
-
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, selmon->bh);
- XMoveResizeWindow(dpy, selmon->traywin, selmon->tx, selmon->by, selmon->tw, selmon->bh);
+ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
arrange(selmon);
}
@@ -1804,6 +1743,13 @@ togglefloating(const Arg *arg)
}
void
+togglefullscr(const Arg *arg)
+{
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;
@@ -1869,40 +1815,9 @@ unmanage(Client *c, int destroyed)
}
void
-unmanagealtbar(Window w)
-{
- Monitor *m = wintomon(w);
-
- if (!m)
- return;
-
- m->barwin = 0;
- m->by = 0;
- m->bh = 0;
- updatebarpos(m);
- arrange(m);
-}
-
-void
-unmanagetray(Window w)
-{
- Monitor *m = wintomon(w);
-
- if (!m)
- return;
-
- m->traywin = 0;
- m->tx = 0;
- m->tw = 0;
- updatebarpos(m);
- arrange(m);
-}
-
-void
unmapnotify(XEvent *e)
{
Client *c;
- Monitor *m;
XUnmapEvent *ev = &e->xunmap;
if ((c = wintoclient(ev->window))) {
@@ -1910,18 +1825,12 @@ unmapnotify(XEvent *e)
setclientstate(c, WithdrawnState);
else
unmanage(c, 0);
- } else if ((m = wintomon(ev->window)) && m->barwin == ev->window)
- unmanagealtbar(ev->window);
- else if (m->traywin == ev->window)
- unmanagetray(ev->window);
+ }
}
void
updatebars(void)
{
- if (usealtbar)
- return;
-
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -1947,11 +1856,11 @@ updatebarpos(Monitor *m)
m->wy = m->my;
m->wh = m->mh;
if (m->showbar) {
- m->wh -= m->bh;
+ m->wh -= bh;
m->by = m->topbar ? m->wy : m->wy + m->wh;
- m->wy = m->topbar ? m->wy + m->bh : m->wy;
+ m->wy = m->topbar ? m->wy + bh : m->wy;
} else
- m->by = -m->bh;
+ m->by = -bh;
}
void
@@ -1989,42 +1898,42 @@ updategeom(void)
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info);
nn = j;
- if (n <= nn) { /* new monitors available */
- for (i = 0; i < (nn - n); i++) {
- for (m = mons; m && m->next; m = m->next);
- if (m)
- m->next = createmon();
- else
- mons = createmon();
+
+ /* new monitors if nn > n */
+ for (i = n; i < nn; i++) {
+ for (m = mons; m && m->next; m = m->next);
+ if (m)
+ m->next = createmon();
+ else
+ mons = createmon();
+ }
+ for (i = 0, m = mons; i < nn && m; m = m->next, i++)
+ if (i >= n
+ || unique[i].x_org != m->mx || unique[i].y_org != m->my
+ || unique[i].width != m->mw || unique[i].height != m->mh)
+ {
+ dirty = 1;
+ m->num = i;
+ m->mx = m->wx = unique[i].x_org;
+ m->my = m->wy = unique[i].y_org;
+ m->mw = m->ww = unique[i].width;
+ m->mh = m->wh = unique[i].height;
+ updatebarpos(m);
}
- for (i = 0, m = mons; i < nn && m; m = m->next, i++)
- if (i >= n
- || unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh)
- {
- dirty = 1;
- m->num = i;
- m->mx = m->wx = unique[i].x_org;
- m->my = m->wy = unique[i].y_org;
- m->mw = m->ww = unique[i].width;
- m->mh = m->wh = unique[i].height;
- updatebarpos(m);
- }
- } else { /* less monitors available nn < n */
- for (i = nn; i < n; i++) {
- for (m = mons; m && m->next; m = m->next);
- while ((c = m->clients)) {
- dirty = 1;
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- attach(c);
- attachstack(c);
- }
- if (m == selmon)
- selmon = mons;
- cleanupmon(m);
+ /* removed monitors if n > nn */
+ for (i = nn; i < n; i++) {
+ for (m = mons; m && m->next; m = m->next);
+ while ((c = m->clients)) {
+ dirty = 1;
+ m->clients = c->next;
+ detachstack(c);
+ c->mon = mons;
+ attach(c);
+ attachstack(c);
}
+ if (m == selmon)
+ selmon = mons;
+ cleanupmon(m);
}
free(unique);
} else
@@ -2103,6 +2012,7 @@ updatesizehints(Client *c)
} else
c->maxa = c->mina = 0.0;
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
+ c->hintsvalid = 1;
}
void
@@ -2188,35 +2098,13 @@ wintomon(Window w)
if (w == root && getrootptr(&x, &y))
return recttomon(x, y, 1, 1);
for (m = mons; m; m = m->next)
- if (w == m->barwin || w == m->traywin)
+ if (w == m->barwin)
return m;
if ((c = wintoclient(w)))
return c->mon;
return selmon;
}
-int
-wmclasscontains(Window win, const char *class, const char *name)
-{
- XClassHint ch = { NULL, NULL };
- int res = 1;
-
- if (XGetClassHint(dpy, win, &ch)) {
- if (ch.res_name && strstr(ch.res_name, name) == NULL)
- res = 0;
- if (ch.res_class && strstr(ch.res_class, class) == NULL)
- res = 0;
- } else
- res = 0;
-
- if (ch.res_class)
- XFree(ch.res_class);
- if (ch.res_name)
- XFree(ch.res_name);
-
- return res;
-}
-
/* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which may call exit. */