Compare commits

..

28 Commits
1.4 ... 1.6

Author SHA1 Message Date
2511b5c675 added visibility check to enternotify as well 2006-09-15 14:21:25 +02:00
28aba061ec offscreen client appearance fixes 2006-09-15 10:54:32 +02:00
8e37c78ce3 focus() enforces visibility of a client if not NULL 2006-09-15 10:49:05 +02:00
ca68975ff8 removed useless inclusion 2006-09-14 11:07:44 +02:00
529be52fea fixed executing of dmenu output to handle args correctly 2006-09-12 19:09:04 +02:00
ca65478c89 removed a bunch of lines through making function signatures more consistent with my style ( { does not belong to a new line, if function args are single-lined) 2006-09-12 10:57:28 +02:00
a1e9362d38 some more simplifications of intro comment in dwm.h, this should suffice for comments in dwm 2006-09-12 09:50:06 +02:00
cbfc69e310 made introduction comment in dwm.h shorter 2006-09-12 09:46:19 +02:00
1d7674bb22 applied Christof Musik's multihead patch for a pathologic cornercase 2006-09-12 08:27:11 +02:00
e6cc22396a added a general comment to dwm.h how dwm is basically organized 2006-09-12 08:14:22 +02:00
868159fd0a some other simplifications 2006-09-11 17:31:21 +02:00
b597fa4637 fixed some other comments, now also the code side seems to be at a level to be reviewed by experienced programmers 2006-09-11 11:28:28 +02:00
d2d394eccf small change to comments, renamed two set* functions in client.c into update* 2006-09-11 10:00:56 +02:00
438beeabde small fix 2006-09-11 08:58:58 +02:00
281f0981a6 added some comments 2006-09-11 07:40:41 +02:00
6ff346bed9 Added tag 1.5 for changeset 728c9089b079721b43c3347124639a29baa22a97 2006-09-08 08:32:08 +02:00
0925dd588c applied sanders patch of not manipulating sel 2006-09-08 08:19:54 +02:00
6f20315dff really small changes to dwm.1 2006-09-08 07:40:16 +02:00
2e68f22118 hotfix 2006-09-07 18:13:19 +02:00
8aa860d270 simplified unmanage 2006-09-07 18:12:40 +02:00
15abade272 using a global stack for focus recovery on arrange() - seems to work great 2006-09-07 17:53:40 +02:00
7ab8c87281 made markups in dwm.1 more consistent 2006-09-07 09:26:01 +02:00
4ff8f71643 small addition to dwm.1 2006-09-07 07:53:29 +02:00
d22abeee86 this patch keeps track of global z-layer order of clients which are floating or if floating mode is enabled 2006-09-06 17:31:52 +02:00
a33150eb4b no this is better 2006-09-06 15:36:42 +02:00
fd00b3a186 does this preserve z order for anthony? 2006-09-06 15:30:28 +02:00
e8389a4cc0 maybe this might work 2006-09-06 13:56:46 +02:00
6078d756bc Added tag 1.4 for changeset 3cff9403766bf83a9fc2a0aef230115d68de2a8e 2006-09-06 12:19:07 +02:00
12 changed files with 278 additions and 357 deletions

View File

@ -11,3 +11,5 @@ bbc98e77ae89a7c9232a5be0835f60ea00d8036e 1.0
44a55e6e46bf6c231780b09d919977d6f01083de 1.1 44a55e6e46bf6c231780b09d919977d6f01083de 1.1
e3179ce2b90451d2807cd53b589d768412b8666b 1.2 e3179ce2b90451d2807cd53b589d768412b8666b 1.2
f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3 f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3
3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4
728c9089b079721b43c3347124639a29baa22a97 1.5

View File

@ -11,11 +11,17 @@
/* static functions */ /* static functions */
static void static void
grabbuttons(Client *c, Bool focus) detachstack(Client *c) {
{ Client **tc;
for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
*tc = c->snext;
}
static void
grabbuttons(Client *c, Bool focused) {
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focus) { if(focused) {
XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK, XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK, XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
@ -46,12 +52,10 @@ grabbuttons(Client *c, Bool focus)
else else
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
} }
static void static void
resizetitle(Client *c) resizetitle(Client *c) {
{
c->tw = textw(c->name); c->tw = textw(c->name);
if(c->tw > c->w) if(c->tw > c->w)
c->tw = c->w + 2; c->tw = c->w + 2;
@ -61,30 +65,26 @@ resizetitle(Client *c)
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th); XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else else
XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th); XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th);
} }
static int static int
xerrordummy(Display *dsply, XErrorEvent *ee) xerrordummy(Display *dsply, XErrorEvent *ee) {
{
return 0; return 0;
} }
/* extern functions */ /* extern functions */
void void
ban(Client *c) ban(Client *c) {
{
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty); XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty);
} }
void void
focus(Client *c) focus(Client *c) {
{
Client *old; Client *old;
if(!issel) if(!issel || (c && !isvisible(c)))
return; return;
if(!sel) if(!sel)
sel = c; sel = c;
@ -99,6 +99,9 @@ focus(Client *c)
} }
} }
if(c) { if(c) {
detachstack(c);
c->snext = stack;
stack = c;
grabbuttons(c, True); grabbuttons(c, True);
drawtitle(c); drawtitle(c);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
@ -108,8 +111,7 @@ focus(Client *c)
} }
Client * Client *
getclient(Window w) getclient(Window w) {
{
Client *c; Client *c;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
@ -119,8 +121,7 @@ getclient(Window w)
} }
Client * Client *
getctitle(Window w) getctitle(Window w) {
{
Client *c; Client *c;
for(c = clients; c; c = c->next) for(c = clients; c; c = c->next)
@ -130,8 +131,7 @@ getctitle(Window w)
} }
void void
gravitate(Client *c, Bool invert) gravitate(Client *c, Bool invert) {
{
int dx = 0, dy = 0; int dx = 0, dy = 0;
switch(c->grav) { switch(c->grav) {
@ -185,8 +185,7 @@ gravitate(Client *c, Bool invert)
} }
void void
killclient(Arg *arg) killclient(Arg *arg) {
{
if(!sel) if(!sel)
return; return;
if(sel->proto & PROTODELWIN) if(sel->proto & PROTODELWIN)
@ -196,9 +195,7 @@ killclient(Arg *arg)
} }
void void
manage(Window w, XWindowAttributes *wa) manage(Window w, XWindowAttributes *wa) {
{
unsigned int i;
Client *c; Client *c;
Window trans; Window trans;
XSetWindowAttributes twa; XSetWindowAttributes twa;
@ -213,7 +210,7 @@ manage(Window w, XWindowAttributes *wa)
c->th = bh; c->th = bh;
c->border = 0; c->border = 0;
setsize(c); updatesize(c);
if(c->x + c->w + 2 > sw) if(c->x + c->w + 2 > sw)
c->x = sw - c->w - 2; c->x = sw - c->w - 2;
@ -247,9 +244,10 @@ manage(Window w, XWindowAttributes *wa)
if(clients) if(clients)
clients->prev = c; clients->prev = c;
c->next = clients; c->next = clients;
clients = c; c->snext = stack;
stack = clients = c;
settitle(c); updatetitle(c);
ban(c); ban(c);
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin); XMapWindow(dpy, c->twin);
@ -259,8 +257,7 @@ manage(Window w, XWindowAttributes *wa)
} }
void void
resize(Client *c, Bool sizehints, Corner sticky) resize(Client *c, Bool sizehints, Corner sticky) {
{
int bottom = c->y + c->h; int bottom = c->y + c->h;
int right = c->x + c->w; int right = c->x + c->w;
XWindowChanges wc; XWindowChanges wc;
@ -284,6 +281,16 @@ resize(Client *c, Bool sizehints, Corner sticky)
if(sticky == BotLeft || sticky == BotRight) if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h; c->y = bottom - c->h;
/* offscreen appearance fixes */
if(c->x + c->w < 0)
c->x = 0;
if(c->y + c->h < bh)
c->y = bh;
if(c->x > sw)
c->x = sw - c->w;
if(c->y > sh)
c->y = sh - c->h;
resizetitle(c); resizetitle(c);
wc.x = c->x; wc.x = c->x;
wc.y = c->y; wc.y = c->y;
@ -293,13 +300,12 @@ resize(Client *c, Bool sizehints, Corner sticky)
wc.border_width = 0; wc.border_width = 0;
else else
wc.border_width = 1; wc.border_width = 1;
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
XSync(dpy, False); XSync(dpy, False);
} }
void void
setsize(Client *c) updatesize(Client *c) {
{
long msize; long msize;
XSizeHints size; XSizeHints size;
@ -337,8 +343,7 @@ setsize(Client *c)
} }
void void
settitle(Client *c) updatetitle(Client *c) {
{
char **list = NULL; char **list = NULL;
int n; int n;
XTextProperty name; XTextProperty name;
@ -365,8 +370,7 @@ settitle(Client *c)
} }
void void
togglemax(Arg *arg) togglemax(Arg *arg) {
{
int ox, oy, ow, oh; int ox, oy, ow, oh;
Client *c; Client *c;
XEvent ev; XEvent ev;
@ -401,21 +405,17 @@ togglemax(Arg *arg)
} }
void void
unmanage(Client *c) unmanage(Client *c) {
{ Client *nc;
Client *tc, *fc;
Window trans;
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(xerrordummy); XSetErrorHandler(xerrordummy);
detach(c); detach(c);
detachstack(c);
if(sel == c) { if(sel == c) {
XGetTransientForHint(dpy, c->win, &trans); for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
if(trans && (tc = getclient(trans)) && isvisible(tc)) focus(nc);
fc = tc;
else
fc = getnext(clients);
focus(fc);
} }
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);

View File

@ -29,7 +29,7 @@ static Key key[] = { \
{ MODKEY, XK_p, spawn, \ { MODKEY, XK_p, spawn, \
{ .cmd = "exe=\"$(IFS=:; for dir in $PATH; do " \ { .cmd = "exe=\"$(IFS=:; for dir in $PATH; do " \
"for file in \"$dir\"/*; do [ -x \"$file\" ] && echo \"${file##*/}\"; done; " \ "for file in \"$dir\"/*; do [ -x \"$file\" ] && echo \"${file##*/}\"; done; " \
"done | sort -u | dmenu)\" && exec \"$exe\"" } }, \ "done | sort -u | dmenu)\" && exec $exe" } }, \
{ MODKEY, XK_j, focusnext, { 0 } }, \ { MODKEY, XK_j, focusnext, { 0 } }, \
{ MODKEY, XK_k, focusprev, { 0 } }, \ { MODKEY, XK_k, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \ { MODKEY, XK_Return, zoom, { 0 } }, \

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 1.4 VERSION = 1.6
# Customize below to fit your system # Customize below to fit your system

24
draw.c
View File

@ -10,8 +10,7 @@
/* static */ /* static */
static unsigned int static unsigned int
textnw(const char *text, unsigned int len) textnw(const char *text, unsigned int len) {
{
XRectangle r; XRectangle r;
if(dc.font.set) { if(dc.font.set) {
@ -22,8 +21,7 @@ textnw(const char *text, unsigned int len)
} }
static void static void
drawtext(const char *text, unsigned long col[ColLast], Bool highlight) drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
{
int x, y, w, h; int x, y, w, h;
static char buf[256]; static char buf[256];
unsigned int len, olen; unsigned int len, olen;
@ -82,8 +80,7 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight)
/* extern */ /* extern */
void void
drawall() drawall() {
{
Client *c; Client *c;
for(c = clients; c; c = getnext(c->next)) for(c = clients; c; c = getnext(c->next))
@ -92,8 +89,7 @@ drawall()
} }
void void
drawstatus() drawstatus() {
{
int i, x; int i, x;
dc.x = dc.y = 0; dc.x = dc.y = 0;
@ -131,8 +127,7 @@ drawstatus()
} }
void void
drawtitle(Client *c) drawtitle(Client *c) {
{
if(c == sel && issel) { if(c == sel && issel) {
drawstatus(); drawstatus();
XUnmapWindow(dpy, c->twin); XUnmapWindow(dpy, c->twin);
@ -150,8 +145,7 @@ drawtitle(Client *c)
} }
unsigned long unsigned long
getcolor(const char *colstr) getcolor(const char *colstr) {
{
Colormap cmap = DefaultColormap(dpy, screen); Colormap cmap = DefaultColormap(dpy, screen);
XColor color; XColor color;
@ -160,8 +154,7 @@ getcolor(const char *colstr)
} }
void void
setfont(const char *fontstr) setfont(const char *fontstr) {
{
char **missing, *def; char **missing, *def;
int i, n; int i, n;
@ -211,7 +204,6 @@ setfont(const char *fontstr)
} }
unsigned int unsigned int
textw(const char *text) textw(const char *text) {
{
return textnw(text, strlen(text)) + dc.font.height; return textnw(text, strlen(text)) + dc.font.height;
} }

136
dwm.1
View File

@ -5,10 +5,9 @@ dwm \- dynamic window manager
.B dwm .B dwm
.RB [ \-v ] .RB [ \-v ]
.SH DESCRIPTION .SH DESCRIPTION
.B dwm dwm is a dynamic window manager for X. It manages windows in tiling and
is a dynamic window manager for X. It manages windows in tiling and floating floating modes. Either mode can be applied dynamically, optimizing the
modes. Either mode can be applied dynamically, optimizing the environment for environment for the application in use and the task performed.
the application in use and the task performed.
.P .P
In tiling mode windows are managed in a master and stacking column. The master In tiling mode windows are managed in a master and stacking column. The master
column contains the window which currently needs most attention, whereas the column contains the window which currently needs most attention, whereas the
@ -17,16 +16,14 @@ resized and moved freely. Dialog windows are always managed floating,
regardless of the mode selected. regardless of the mode selected.
.P .P
Windows are grouped by tags. Each window can be tagged with one or multiple Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting a certain tag for viewing will display all windows with that tags. Selecting certain tags displays all windows with that tag.
tag.
.P .P
.B dwm dwm contains a small status bar which displays all available tags, the mode,
contains a small status bar which displays all available tags, the mode, the the title of the focused window, and the text read from standard input. The
title of the focused window, and the text read from standard input. The tags of selected tags are highlighted with a different color, the tags of the focused
the focused window are highlighted with a small point. window are highlighted with a small point.
.P .P
.B dwm dwm draws a 1-pixel border around windows to indicate the focus state.
draws a 1-pixel border around windows to indicate the focus state.
Unfocused windows contain a small bar in front of them displaying their title. Unfocused windows contain a small bar in front of them displaying their title.
.SH OPTIONS .SH OPTIONS
.TP .TP
@ -39,30 +36,17 @@ prints version information to standard output, then exits.
is read and displayed in the status text area. is read and displayed in the status text area.
.TP .TP
.B Button1 .B Button1
click on a tag label views all windows with that click on a tag label to display all windows with that tag, click on the mode
.BR tag , label toggles between tiled and floating mode.
click on the mode label toggles between
.B tiled
and
.B floating
mode.
.TP .TP
.B Button3 .B Button3
click on a tag label adds/removes all windows with that click on a tag label adds/removes all windows with that tag to/from the view.
.B tag
to/from the view.
.TP .TP
.B Mod1-Button1 .B Mod1-Button1
click on a tag label applies that click on a tag label applies that tag to the focused window.
.B tag
to the focused
.BR window .
.TP .TP
.B Mod1-Button3 .B Mod1-Button3
click on a tag label adds/removes that click on a tag label adds/removes that tag to/from the focused window.
.B tag
to/from the focused
.BR window .
.SS Keyboard commands .SS Keyboard commands
.TP .TP
.B Mod1-Shift-Return .B Mod1-Shift-Return
@ -70,114 +54,72 @@ Start
.BR xterm (1). .BR xterm (1).
.TP .TP
.B Mod1-Tab .B Mod1-Tab
Focus next Focus next window.
.BR window .
.TP .TP
.B Mod1-Shift-Tab .B Mod1-Shift-Tab
Focus previous Focus previous window.
.BR window .
.TP .TP
.B Mod1-Return .B Mod1-Return
Zoom current Zoom current window to the master column (tiling mode only).
.B window
to the
.B master
column
.RB ( tiling
mode only).
.TP .TP
.B Mod1-m .B Mod1-m
Maximize current Maximize current window.
.BR window .
.TP .TP
.B Mod1-g .B Mod1-g
Grow current Grow current column (tiling mode only).
.BR column
.RB ( tiling
mode only).
.TP .TP
.B Mod1-s .B Mod1-s
Shrink current Shrink current column (tiling mode only).
.BR column
.RB ( tiling
mode only).
.TP .TP
.B Mod1-Shift-[1..n] .B Mod1-Shift-[1..n]
Apply Apply
.B nth tag .RB nth
to current tag to current window.
.BR window .
.TP .TP
.B Mod1-Control-Shift-[1..n] .B Mod1-Control-Shift-[1..n]
Add/remove Add/remove
.B nth tag .B nth
to/from current tag to/from current window.
.BR window .
.TP .TP
.B Mod1-Shift-c .B Mod1-Shift-c
Close focused Close focused window.
.B window.
.TP .TP
.B Mod1-space .B Mod1-space
Toggle between Toggle between tiled and floating mode (affects all windows).
.B tiled
and
.B floating
mode (affects
.BR "all windows" ).
.TP .TP
.B Mod1-[1..n] .B Mod1-[1..n]
View all windows with View all windows with
.BR "tag n" . .BR nth
tag.
.TP .TP
.B Mod1-0 .B Mod1-0
View all windows with any View all windows with any tag.
.BR "tag" .
.TP .TP
.B Mod1-Control-[1..n] .B Mod1-Control-[1..n]
Add/remove all windows with Add/remove all windows with
.B tag n .BR nth
to/from the view. tag to/from the view.
.TP .TP
.B Mod1-Shift-q .B Mod1-Shift-q
Quit Quit dwm.
.B dwm.
.SS Mouse commands .SS Mouse commands
.TP .TP
.B Mod1-Button1 .B Mod1-Button1
Move current Move current window while dragging (floating mode only).
.B window
while dragging
.RB ( floating
mode only).
.TP .TP
.B Mod1-Button2 .B Mod1-Button2
Zoom current Zoom current window to the master column (tiling mode only).
.B window
to the
.B master
column
.RB ( tiling
mode only).
.TP .TP
.B Mod1-Button3 .B Mod1-Button3
Resize current Resize current window while dragging (floating mode only).
.B window
while dragging
.RB ( floating
mode only).
.SH CUSTOMIZATION .SH CUSTOMIZATION
.B dwm dwm is customized by creating a custom config.h and (re)compiling the source
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple. code. This keeps it fast, secure and simple.
.SH CAVEATS .SH CAVEATS
The status bar may display The status bar may display
.B broken pipe .BR "broken pipe"
when when dwm has been started by
.B dwm
has been started by
.BR xdm (1), .BR xdm (1),
because it closes standard output before executing because it closes standard output before executing dwm.
.BR dwm .
.SH SEE ALSO .SH SEE ALSO
.BR dmenu (1) .BR dmenu (1)

173
dwm.h
View File

@ -1,6 +1,35 @@
/* /*
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*
* dynamic window manager is designed like any other X client as well. It is
* driven through handling X events. In contrast to other X clients, a window
* manager like dwm selects for SubstructureRedirectMask on the root window, to
* receive events about window appearance and disappearance. Only one X
* connection at a time is allowed to select for this event mask.
*
* Calls to fetch an X event from the X event queue connection are blocking.
* Due reading status text from standard input, a select-driven main loop has
* been implemented which selects for reads on the X connection and
* STDIN_FILENO to handle all data smoothly and without busy-loop quirks. The
* event handlers of dwm are organized in an array which is accessed whenever a
* new event has been fetched. This allows event dispatching in O(1) time.
*
* Each child of the root window is called a client, except windows which have
* set the override_redirect flag. Clients are organized in a global
* doubly-linked client list, the focus history is remembered through a global
* stack list. Each client contains an array of Bools of the same size as the
* global tags array to indicate the tags of a client. For each client dwm
* creates a small title window which is resized whenever the WM_NAME or
* _NET_WM_NAME properties are updated or the client is resized.
*
* Keys and tagging rules are organized as arrays and defined in the config.h
* file. These arrays are kept static in event.o and tag.o respectively,
* because no other part of dwm needs access to them. The current mode is
* represented by the arrange function pointer which wether points to dofloat
* or dotile.
*
* To understand everything else, start with reading main.c:main().
*/ */
#include "config.h" #include "config.h"
@ -11,23 +40,19 @@
#define MOUSEMASK (BUTTONMASK | PointerMotionMask) #define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define PROTODELWIN 1 #define PROTODELWIN 1
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMLast }; /* default atoms */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColFG, ColBG, ColLast }; /* color */
typedef enum {
TopLeft, TopRight, BotLeft, BotRight
} Corner; /* window corners */
typedef union { typedef union {
const char *cmd; const char *cmd;
int i; int i;
} Arg; } Arg; /* argument type */
/* atoms */
enum { NetSupported, NetWMName, NetLast };
enum { WMProtocols, WMDelete, WMLast };
/* cursor */
enum { CurNormal, CurResize, CurMove, CurLast };
/* color */
enum { ColFG, ColBG, ColLast };
/* window corners */
typedef enum { TopLeft, TopRight, BotLeft, BotRight } Corner;
typedef struct { typedef struct {
int ascent; int ascent;
@ -37,7 +62,7 @@ typedef struct {
XFontStruct *xfont; XFontStruct *xfont;
} Fnt; } Fnt;
typedef struct { /* draw context */ typedef struct {
int x, y, w, h; int x, y, w, h;
unsigned long norm[ColLast]; unsigned long norm[ColLast];
unsigned long sel[ColLast]; unsigned long sel[ColLast];
@ -45,14 +70,14 @@ typedef struct { /* draw context */
Drawable drawable; Drawable drawable;
Fnt font; Fnt font;
GC gc; GC gc;
} DC; } DC; /* draw context */
typedef struct Client Client; typedef struct Client Client;
struct Client { struct Client {
char name[256]; char name[256];
int proto; int proto;
int x, y, w, h; int x, y, w, h;
int tx, ty, tw, th; /* title */ int tx, ty, tw, th; /* title window geometry */
int basew, baseh, incw, inch, maxw, maxh, minw, minh; int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int grav; int grav;
long flags; long flags;
@ -61,81 +86,83 @@ struct Client {
Bool *tags; Bool *tags;
Client *next; Client *next;
Client *prev; Client *prev;
Client *snext;
Window win; Window win;
Window twin; Window twin;
}; };
extern const char *tags[]; extern const char *tags[]; /* all tags */
extern char stext[1024]; extern char stext[1024]; /* status text */
extern int bx, by, bw, bh, bmw, mw, screen, sx, sy, sw, sh; extern int bx, by, bw, bh, bmw; /* bar geometry, bar mode label width */
extern unsigned int ntags, numlockmask; extern int mw, screen, sx, sy, sw, sh; /* screen geometry, master width */
extern void (*handler[LASTEvent])(XEvent *); extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */
extern void (*arrange)(Arg *); extern void (*handler[LASTEvent])(XEvent *); /* event handler */
extern void (*arrange)(Arg *); /* arrange function, indicates mode */
extern Atom wmatom[WMLast], netatom[NetLast]; extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel, maximized, *seltag; extern Bool running, issel, maximized, *seltag; /* seltag is array of Bool */
extern Client *clients, *sel; extern Client *clients, *sel, *stack; /* global cleint list and stack */
extern Cursor cursor[CurLast]; extern Cursor cursor[CurLast];
extern DC dc; extern DC dc; /* global draw context */
extern Display *dpy; extern Display *dpy;
extern Window root, barwin; extern Window root, barwin;
/* client.c */ /* client.c */
extern void ban(Client *c); extern void ban(Client *c); /* ban c from screen */
extern void focus(Client *c); extern void focus(Client *c); /* focus c, c may be NULL */
extern Client *getclient(Window w); extern Client *getclient(Window w); /* return client of w */
extern Client *getctitle(Window w); extern Client *getctitle(Window w); /* return client of title window */
extern void gravitate(Client *c, Bool invert); extern void gravitate(Client *c, Bool invert); /* gravitate c */
extern void killclient(Arg *arg); extern void killclient(Arg *arg); /* kill c nicely */
extern void manage(Window w, XWindowAttributes *wa); extern void manage(Window w, XWindowAttributes *wa); /* manage new client */
extern void resize(Client *c, Bool sizehints, Corner sticky); extern void resize(Client *c, Bool sizehints, Corner sticky); /* resize c*/
extern void setsize(Client *c); extern void updatesize(Client *c); /* update the size structs of c */
extern void settitle(Client *c); extern void updatetitle(Client *c); /* update the name of c */
extern void togglemax(Arg *arg); extern void togglemax(Arg *arg); /* (un)maximize c */
extern void unmanage(Client *c); extern void unmanage(Client *c); /* destroy c */
/* draw.c */ /* draw.c */
extern void drawall(); extern void drawall(); /* draw all visible client titles and the bar */
extern void drawstatus(); extern void drawstatus(); /* draw the bar */
extern void drawtitle(Client *c); extern void drawtitle(Client *c); /* draw title of c */
extern unsigned long getcolor(const char *colstr); extern unsigned long getcolor(const char *colstr); /* return color of colstr */
extern void setfont(const char *fontstr); extern void setfont(const char *fontstr); /* set the font for DC */
extern unsigned int textw(const char *text); extern unsigned int textw(const char *text); /* return the width of text in px*/
/* event.c */ /* event.c */
extern void grabkeys(); extern void grabkeys(); /* grab all keys defined in config.h */
extern void procevent(); extern void procevent(); /* process pending X events */
/* main.c */ /* main.c */
extern int getproto(Window w); extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */
extern void quit(Arg *arg); extern void quit(Arg *arg); /* quit dwm nicely */
extern void sendevent(Window w, Atom a, long value); extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */
extern int xerror(Display *dsply, XErrorEvent *ee); extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */
/* tag.c */ /* tag.c */
extern void initrregs(); extern void initrregs(); /* initialize regexps of rules defined in config.h */
extern Client *getnext(Client *c); extern Client *getnext(Client *c); /* returns next visible client */
extern Client *getprev(Client *c); extern Client *getprev(Client *c); /* returns previous visible client */
extern void settags(Client *c, Client *trans); extern void settags(Client *c, Client *trans); /* sets tags of c */
extern void tag(Arg *arg); extern void tag(Arg *arg); /* tags c with arg's index */
extern void toggletag(Arg *arg); extern void toggletag(Arg *arg); /* toggles c tags with arg's index */
/* util.c */ /* util.c */
extern void *emallocz(unsigned int size); extern void *emallocz(unsigned int size); /* allocates zero-initialized memory, exits on error */
extern void eprint(const char *errstr, ...); extern void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */
extern void *erealloc(void *ptr, unsigned int size); extern void *erealloc(void *ptr, unsigned int size); /* reallocates memory, exits on error */
extern void spawn(Arg *arg); extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */
/* view.c */ /* view.c */
extern void detach(Client *c); extern void detach(Client *c); /* detaches c from global client list */
extern void dofloat(Arg *arg); extern void dofloat(Arg *arg); /* arranges all windows floating, arg is ignored */
extern void dotile(Arg *arg); extern void dotile(Arg *arg); /* arranges all windows, arg is ignored */
extern void focusnext(Arg *arg); extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */
extern void focusprev(Arg *arg); extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */
extern Bool isvisible(Client *c); extern Bool isvisible(Client *c); /* returns True if client is visible */
extern void resizecol(Arg *arg); extern void resizecol(Arg *arg); /* resizes the master width with arg's index value */
extern void restack(); extern void restack(); /* restores z layers of all clients */
extern void togglemode(Arg *arg); extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */
extern void toggleview(Arg *arg); extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */
extern void view(Arg *arg); extern void view(Arg *arg); /* views the tag with arg's index */
extern void viewall(Arg *arg); extern void viewall(Arg *arg); /* views all tags, arg is ignored */
extern void zoom(Arg *arg); extern void zoom(Arg *arg); /* zooms the focused client to master column, arg is ignored */

65
event.c
View File

@ -21,8 +21,7 @@ KEYS
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
static void static void
movemouse(Client *c) movemouse(Client *c) {
{
int x1, y1, ocx, ocy, di; int x1, y1, ocx, ocy, di;
unsigned int dui; unsigned int dui;
Window dummy; Window dummy;
@ -37,7 +36,8 @@ movemouse(Client *c)
for(;;) { for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch (ev.type) { switch (ev.type) {
default: break; default:
break;
case Expose: case Expose:
handler[Expose](&ev); handler[Expose](&ev);
break; break;
@ -55,8 +55,7 @@ movemouse(Client *c)
} }
static void static void
resizemouse(Client *c) resizemouse(Client *c) {
{
int ocx, ocy; int ocx, ocy;
int nw, nh; int nw, nh;
Corner sticky; Corner sticky;
@ -71,7 +70,8 @@ resizemouse(Client *c)
for(;;) { for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch(ev.type) { switch(ev.type) {
default: break; default:
break;
case Expose: case Expose:
handler[Expose](&ev); handler[Expose](&ev);
break; break;
@ -97,8 +97,7 @@ resizemouse(Client *c)
} }
static void static void
buttonpress(XEvent *e) buttonpress(XEvent *e) {
{
int x; int x;
Arg a; Arg a;
Client *c; Client *c;
@ -147,8 +146,7 @@ buttonpress(XEvent *e)
} }
static void static void
synconfig(Client *c, int x, int y, int w, int h, unsigned int border) synconfig(Client *c, int x, int y, int w, int h, unsigned int border) {
{
XEvent synev; XEvent synev;
synev.type = ConfigureNotify; synev.type = ConfigureNotify;
@ -165,8 +163,7 @@ synconfig(Client *c, int x, int y, int w, int h, unsigned int border)
} }
static void static void
configurerequest(XEvent *e) configurerequest(XEvent *e) {
{
unsigned long newmask; unsigned long newmask;
Client *c; Client *c;
XConfigureRequestEvent *ev = &e->xconfigurerequest; XConfigureRequestEvent *ev = &e->xconfigurerequest;
@ -219,8 +216,7 @@ configurerequest(XEvent *e)
} }
static void static void
destroynotify(XEvent *e) destroynotify(XEvent *e) {
{
Client *c; Client *c;
XDestroyWindowEvent *ev = &e->xdestroywindow; XDestroyWindowEvent *ev = &e->xdestroywindow;
@ -229,15 +225,14 @@ destroynotify(XEvent *e)
} }
static void static void
enternotify(XEvent *e) enternotify(XEvent *e) {
{
Client *c; Client *c;
XCrossingEvent *ev = &e->xcrossing; XCrossingEvent *ev = &e->xcrossing;
if(ev->mode != NotifyNormal || ev->detail == NotifyInferior) if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
return; return;
if((c = getclient(ev->window)) || (c = getctitle(ev->window))) if(((c = getclient(ev->window)) || (c = getctitle(ev->window))) && isvisible(c))
focus(c); focus(c);
else if(ev->window == root) { else if(ev->window == root) {
issel = True; issel = True;
@ -247,8 +242,7 @@ enternotify(XEvent *e)
} }
static void static void
expose(XEvent *e) expose(XEvent *e) {
{
Client *c; Client *c;
XExposeEvent *ev = &e->xexpose; XExposeEvent *ev = &e->xexpose;
@ -261,8 +255,7 @@ expose(XEvent *e)
} }
static void static void
keypress(XEvent *e) keypress(XEvent *e) {
{
static unsigned int len = sizeof(key) / sizeof(key[0]); static unsigned int len = sizeof(key) / sizeof(key[0]);
unsigned int i; unsigned int i;
KeySym keysym; KeySym keysym;
@ -270,8 +263,8 @@ keypress(XEvent *e)
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
if(keysym == key[i].keysym && if(keysym == key[i].keysym
CLEANMASK(key[i].mod) == CLEANMASK(ev->state)) && CLEANMASK(key[i].mod) == CLEANMASK(ev->state))
{ {
if(key[i].func) if(key[i].func)
key[i].func(&key[i].arg); key[i].func(&key[i].arg);
@ -281,8 +274,7 @@ keypress(XEvent *e)
} }
static void static void
leavenotify(XEvent *e) leavenotify(XEvent *e) {
{
XCrossingEvent *ev = &e->xcrossing; XCrossingEvent *ev = &e->xcrossing;
if((ev->window == root) && !ev->same_screen) { if((ev->window == root) && !ev->same_screen) {
@ -292,8 +284,7 @@ leavenotify(XEvent *e)
} }
static void static void
mappingnotify(XEvent *e) mappingnotify(XEvent *e) {
{
XMappingEvent *ev = &e->xmapping; XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev); XRefreshKeyboardMapping(ev);
@ -302,8 +293,7 @@ mappingnotify(XEvent *e)
} }
static void static void
maprequest(XEvent *e) maprequest(XEvent *e) {
{
static XWindowAttributes wa; static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest; XMapRequestEvent *ev = &e->xmaprequest;
@ -321,8 +311,7 @@ maprequest(XEvent *e)
} }
static void static void
propertynotify(XEvent *e) propertynotify(XEvent *e) {
{
Client *c; Client *c;
Window trans; Window trans;
XPropertyEvent *ev = &e->xproperty; XPropertyEvent *ev = &e->xproperty;
@ -343,19 +332,18 @@ propertynotify(XEvent *e)
arrange(NULL); arrange(NULL);
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:
setsize(c); updatesize(c);
break; break;
} }
if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
settitle(c); updatetitle(c);
drawtitle(c); drawtitle(c);
} }
} }
} }
static void static void
unmapnotify(XEvent *e) unmapnotify(XEvent *e) {
{
Client *c; Client *c;
XUnmapEvent *ev = &e->xunmap; XUnmapEvent *ev = &e->xunmap;
@ -380,8 +368,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
}; };
void void
grabkeys() grabkeys() {
{
static unsigned int len = sizeof(key) / sizeof(key[0]); static unsigned int len = sizeof(key) / sizeof(key[0]);
unsigned int i; unsigned int i;
KeyCode code; KeyCode code;
@ -401,8 +388,7 @@ grabkeys()
} }
void void
procevent() procevent() {
{
XEvent ev; XEvent ev;
while(XPending(dpy)) { while(XPending(dpy)) {
@ -411,4 +397,3 @@ procevent()
(handler[ev.type])(&ev); /* call handler */ (handler[ev.type])(&ev); /* call handler */
} }
} }

38
main.c
View File

@ -27,6 +27,7 @@ Bool issel = True;
Bool maximized = False; Bool maximized = False;
Client *clients = NULL; Client *clients = NULL;
Client *sel = NULL; Client *sel = NULL;
Client *stack = NULL;
Cursor cursor[CurLast]; Cursor cursor[CurLast];
Display *dpy; Display *dpy;
DC dc = {0}; DC dc = {0};
@ -38,8 +39,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm, readin; static Bool otherwm, readin;
static void static void
cleanup() cleanup() {
{
close(STDIN_FILENO); close(STDIN_FILENO);
while(sel) { while(sel) {
resize(sel, True, TopLeft); resize(sel, True, TopLeft);
@ -59,8 +59,7 @@ cleanup()
} }
static void static void
scan() scan() {
{
unsigned int i, num; unsigned int i, num;
Window *wins, d1, d2; Window *wins, d1, d2;
XWindowAttributes wa; XWindowAttributes wa;
@ -81,8 +80,7 @@ scan()
} }
static void static void
setup() setup() {
{
int i, j; int i, j;
unsigned int mask; unsigned int mask;
Window w; Window w;
@ -111,7 +109,8 @@ setup()
} }
XFree(modmap); XFree(modmap);
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask; wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
| EnterWindowMask | LeaveWindowMask;
wa.cursor = cursor[CurNormal]; wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
@ -162,8 +161,7 @@ setup()
* is already running. * is already running.
*/ */
static int static int
xerrorstart(Display *dsply, XErrorEvent *ee) xerrorstart(Display *dsply, XErrorEvent *ee) {
{
otherwm = True; otherwm = True;
return -1; return -1;
} }
@ -171,8 +169,7 @@ xerrorstart(Display *dsply, XErrorEvent *ee)
/* extern */ /* extern */
int int
getproto(Window w) getproto(Window w) {
{
int i, format, protos, status; int i, format, protos, status;
unsigned long extra, res; unsigned long extra, res;
Atom *protocols, real; Atom *protocols, real;
@ -190,8 +187,7 @@ getproto(Window w)
} }
void void
sendevent(Window w, Atom a, long value) sendevent(Window w, Atom a, long value) {
{
XEvent e; XEvent e;
e.type = ClientMessage; e.type = ClientMessage;
@ -205,35 +201,33 @@ sendevent(Window w, Atom a, long value)
} }
void void
quit(Arg *arg) quit(Arg *arg) {
{
readin = running = False; readin = running = False;
} }
/* /*
* There's no way to check accesses to destroyed windows, thus those cases are * 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 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which calls exit(). * default error handler, which may call exit.
*/ */
int int
xerror(Display *dpy, XErrorEvent *ee) xerror(Display *dpy, XErrorEvent *ee) {
{
if(ee->error_code == BadWindow if(ee->error_code == BadWindow
|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)) || (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
return 0; return 0;
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
ee->request_code, ee->error_code); ee->request_code, ee->error_code);
return xerrorxlib(dpy, ee); /* may call exit() */ return xerrorxlib(dpy, ee); /* may call exit */
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[]) {
{
int r, xfd; int r, xfd;
fd_set rd; fd_set rd;

18
tag.c
View File

@ -33,22 +33,19 @@ static unsigned int len = 0;
/* extern */ /* extern */
Client * Client *
getnext(Client *c) getnext(Client *c) {
{
for(; c && !isvisible(c); c = c->next); for(; c && !isvisible(c); c = c->next);
return c; return c;
} }
Client * Client *
getprev(Client *c) getprev(Client *c) {
{
for(; c && !isvisible(c); c = c->prev); for(; c && !isvisible(c); c = c->prev);
return c; return c;
} }
void void
initrregs() initrregs() {
{
unsigned int i; unsigned int i;
regex_t *reg; regex_t *reg;
@ -76,8 +73,7 @@ initrregs()
} }
void void
settags(Client *c, Client *trans) settags(Client *c, Client *trans) {
{
char prop[512]; char prop[512];
unsigned int i, j; unsigned int i, j;
regmatch_t tmp; regmatch_t tmp;
@ -114,8 +110,7 @@ settags(Client *c, Client *trans)
} }
void void
tag(Arg *arg) tag(Arg *arg) {
{
unsigned int i; unsigned int i;
if(!sel) if(!sel)
@ -129,8 +124,7 @@ tag(Arg *arg)
} }
void void
toggletag(Arg *arg) toggletag(Arg *arg) {
{
unsigned int i; unsigned int i;
if(!sel) if(!sel)

12
util.c
View File

@ -12,8 +12,7 @@
/* extern */ /* extern */
void * void *
emallocz(unsigned int size) emallocz(unsigned int size) {
{
void *res = calloc(1, size); void *res = calloc(1, size);
if(!res) if(!res)
@ -22,8 +21,7 @@ emallocz(unsigned int size)
} }
void void
eprint(const char *errstr, ...) eprint(const char *errstr, ...) {
{
va_list ap; va_list ap;
va_start(ap, errstr); va_start(ap, errstr);
@ -33,8 +31,7 @@ eprint(const char *errstr, ...)
} }
void * void *
erealloc(void *ptr, unsigned int size) erealloc(void *ptr, unsigned int size) {
{
void *res = realloc(ptr, size); void *res = realloc(ptr, size);
if(!res) if(!res)
eprint("fatal: could not malloc() %u bytes\n", size); eprint("fatal: could not malloc() %u bytes\n", size);
@ -42,8 +39,7 @@ erealloc(void *ptr, unsigned int size)
} }
void void
spawn(Arg *arg) spawn(Arg *arg) {
{
static char *shell = NULL; static char *shell = NULL;
if(!shell && !(shell = getenv("SHELL"))) if(!shell && !(shell = getenv("SHELL")))

69
view.c
View File

@ -3,25 +3,23 @@
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdio.h>
/* static */ /* static */
static Client * static Client *
minclient() minclient() {
{
Client *c, *min; Client *c, *min;
if((clients && clients->isfloat) || arrange == dofloat)
return clients; /* don't touch floating order */
for(min = c = clients; c; c = c->next) for(min = c = clients; c; c = c->next)
if(c->weight < min->weight) if(c->weight < min->weight)
min = c; min = c;
return min; return min;
} }
static void static void
reorder() reorder() {
{
Client *c, *newclients, *tail; Client *c, *newclients, *tail;
newclients = tail = NULL; newclients = tail = NULL;
@ -39,8 +37,7 @@ reorder()
} }
static Client * static Client *
nexttiled(Client *c) nexttiled(Client *c) {
{
for(c = getnext(c); c && c->isfloat; c = getnext(c->next)); for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
return c; return c;
} }
@ -50,8 +47,7 @@ nexttiled(Client *c)
void (*arrange)(Arg *) = DEFMODE; void (*arrange)(Arg *) = DEFMODE;
void void
detach(Client *c) detach(Client *c) {
{
if(c->prev) if(c->prev)
c->prev->next = c->next; c->prev->next = c->next;
if(c->next) if(c->next)
@ -62,8 +58,7 @@ detach(Client *c)
} }
void void
dofloat(Arg *arg) dofloat(Arg *arg) {
{
Client *c; Client *c;
maximized = False; maximized = False;
@ -75,14 +70,15 @@ dofloat(Arg *arg)
else else
ban(c); ban(c);
} }
if(!sel || !isvisible(sel)) if(!sel || !isvisible(sel)) {
focus(getnext(clients)); for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
}
restack(); restack();
} }
void void
dotile(Arg *arg) dotile(Arg *arg) {
{
int h, i, n, w; int h, i, n, w;
Client *c; Client *c;
@ -137,14 +133,15 @@ dotile(Arg *arg)
else else
ban(c); ban(c);
} }
if(!sel || !isvisible(sel)) if(!sel || !isvisible(sel)) {
focus(getnext(clients)); for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
}
restack(); restack();
} }
void void
focusnext(Arg *arg) focusnext(Arg *arg) {
{
Client *c; Client *c;
if(!sel) if(!sel)
@ -159,8 +156,7 @@ focusnext(Arg *arg)
} }
void void
focusprev(Arg *arg) focusprev(Arg *arg) {
{
Client *c; Client *c;
if(!sel) if(!sel)
@ -177,8 +173,7 @@ focusprev(Arg *arg)
} }
Bool Bool
isvisible(Client *c) isvisible(Client *c) {
{
unsigned int i; unsigned int i;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
@ -188,8 +183,7 @@ isvisible(Client *c)
} }
void void
resizecol(Arg *arg) resizecol(Arg *arg) {
{
unsigned int n; unsigned int n;
Client *c; Client *c;
@ -213,8 +207,7 @@ resizecol(Arg *arg)
} }
void void
restack() restack() {
{
Client *c; Client *c;
XEvent ev; XEvent ev;
@ -226,7 +219,7 @@ restack()
XRaiseWindow(dpy, sel->win); XRaiseWindow(dpy, sel->win);
XRaiseWindow(dpy, sel->twin); XRaiseWindow(dpy, sel->twin);
} }
if(arrange != dofloat) if(arrange != dofloat)
for(c = nexttiled(clients); c; c = nexttiled(c->next)) { for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
XLowerWindow(dpy, c->twin); XLowerWindow(dpy, c->twin);
XLowerWindow(dpy, c->win); XLowerWindow(dpy, c->win);
@ -237,8 +230,7 @@ restack()
} }
void void
togglemode(Arg *arg) togglemode(Arg *arg) {
{
arrange = (arrange == dofloat) ? dotile : dofloat; arrange = (arrange == dofloat) ? dotile : dofloat;
if(sel) if(sel)
arrange(NULL); arrange(NULL);
@ -247,8 +239,7 @@ togglemode(Arg *arg)
} }
void void
toggleview(Arg *arg) toggleview(Arg *arg) {
{
unsigned int i; unsigned int i;
seltag[arg->i] = !seltag[arg->i]; seltag[arg->i] = !seltag[arg->i];
@ -260,8 +251,7 @@ toggleview(Arg *arg)
} }
void void
view(Arg *arg) view(Arg *arg) {
{
unsigned int i; unsigned int i;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
@ -272,8 +262,7 @@ view(Arg *arg)
} }
void void
viewall(Arg *arg) viewall(Arg *arg) {
{
unsigned int i; unsigned int i;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
@ -283,8 +272,7 @@ viewall(Arg *arg)
} }
void void
zoom(Arg *arg) zoom(Arg *arg) {
{
unsigned int n; unsigned int n;
Client *c; Client *c;
@ -298,8 +286,9 @@ zoom(Arg *arg)
if(!(c = nexttiled(c->next))) if(!(c = nexttiled(c->next)))
return; return;
detach(c); detach(c);
if(clients)
clients->prev = c;
c->next = clients; c->next = clients;
clients->prev = c;
clients = c; clients = c;
focus(c); focus(c);
arrange(NULL); arrange(NULL);