Compare commits

...

31 Commits
1.6 ... 1.7

Author SHA1 Message Date
e87bed6df2 updated README 2006-09-26 14:32:02 +02:00
4ee05b3294 small change 2006-09-26 14:08:42 +02:00
e81eb46a78 added slight error check to getcolor 2006-09-26 13:49:16 +02:00
f315832f75 small fix 2006-09-26 13:30:30 +02:00
97ced11e53 changed order of colordefs in config.h's, changed config.arg.h to fit to new dmenu 2006-09-26 13:24:14 +02:00
4d6c4d36ce removed useless debug info 2006-09-26 08:17:35 +02:00
b4d53bf194 added configure(), but this doesn't really fix those frking broken SDL apps 2006-09-26 07:40:19 +02:00
67bc08d1b9 slight change of event handling order 2006-09-25 21:28:00 +02:00
bcb07de750 simplified mouse resizals 2006-09-25 21:19:18 +02:00
7d7cde0fd6 applied sanders jukka patch 2006-09-25 20:38:30 +02:00
6b25d06d7d applied Jukkas patch 2006-09-25 08:21:51 +02:00
cff951c650 removed all dotile checks 2006-09-22 18:48:35 +02:00
114cc3ec02 applied Jukkas remark (dunno if this is correct though) 2006-09-22 16:35:49 +02:00
3c4b7672a8 applied jukkas patch 2006-09-22 15:39:38 +02:00
6de149eb22 man page fix 2006-09-22 14:02:41 +02:00
da909dd1e8 ismax toggling on mouse based action 2006-09-22 14:00:54 +02:00
67986e81ee hotfix 2006-09-22 13:58:21 +02:00
346bdea946 small change to achieve Jukka's last proposal 2006-09-22 13:53:28 +02:00
05c10c5776 fixed issue pointed out by Jukka 2006-09-22 11:49:24 +02:00
b2cb925d99 patched resizemouse according to sanders remark 2006-09-22 11:24:01 +02:00
9fb6502b3b small man page fix 2006-09-22 10:01:51 +02:00
9eb226ff78 sander check this 2006-09-22 09:43:21 +02:00
e34c4eaf61 slight change to config.arg.h (I use ff floating) 2006-09-22 08:22:39 +02:00
9e75bcfc75 updated man page 2006-09-22 08:17:42 +02:00
d800ec05ff implemented the maximization as I described on the mailinglist, this feels better to me. 2006-09-22 07:37:56 +02:00
bda53ac6ad reviewed client.c 2006-09-20 09:53:21 +02:00
4230932563 reviewed util.c 2006-09-20 09:49:32 +02:00
f17e898bd1 fixed a nuance in dwm.1 2006-09-20 09:45:39 +02:00
886b2088f1 improved intro comment in dwm.h, updated config.mk 2006-09-20 09:40:35 +02:00
551d6bb23d some simplifications to intro in dwm.h 2006-09-19 16:13:44 +02:00
d504005e91 Added tag 1.6 for changeset ad3fa2d185426c51fd5deceae809770363f8d33c 2006-09-16 11:21:01 +02:00
14 changed files with 131 additions and 146 deletions

View File

@ -13,3 +13,4 @@ e3179ce2b90451d2807cd53b589d768412b8666b 1.2
f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3 f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3
3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4 3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4
728c9089b079721b43c3347124639a29baa22a97 1.5 728c9089b079721b43c3347124639a29baa22a97 1.5
ad3fa2d185426c51fd5deceae809770363f8d33c 1.6

2
README
View File

@ -1,5 +1,5 @@
dwm - dynamic window manager dwm - dynamic window manager
---------------------------- ============================
dwm is an extremely fast, small, and dynamic window manager for X. dwm is an extremely fast, small, and dynamic window manager for X.

View File

@ -80,6 +80,23 @@ ban(Client *c) {
XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty); XMoveWindow(dpy, c->twin, c->tx + 2 * sw, c->ty);
} }
void
configure(Client *c) {
XEvent synev;
synev.type = ConfigureNotify;
synev.xconfigure.display = dpy;
synev.xconfigure.event = c->win;
synev.xconfigure.window = c->win;
synev.xconfigure.x = c->x;
synev.xconfigure.y = c->y;
synev.xconfigure.width = c->w;
synev.xconfigure.height = c->h;
synev.xconfigure.border_width = c->border;
synev.xconfigure.above = None;
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
void void
focus(Client *c) { focus(Client *c) {
Client *old; Client *old;
@ -89,8 +106,6 @@ focus(Client *c) {
if(!sel) if(!sel)
sel = c; sel = c;
else if(sel != c) { else if(sel != c) {
if(maximized)
togglemax(NULL);
old = sel; old = sel;
sel = c; sel = c;
if(old) { if(old) {
@ -301,6 +316,7 @@ resize(Client *c, Bool sizehints, Corner sticky) {
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);
configure(c);
XSync(dpy, False); XSync(dpy, False);
} }
@ -369,45 +385,11 @@ updatetitle(Client *c) {
resizetitle(c); resizetitle(c);
} }
void
togglemax(Arg *arg) {
int ox, oy, ow, oh;
Client *c;
XEvent ev;
if(!sel)
return;
if((maximized = !maximized)) {
ox = sel->x;
oy = sel->y;
ow = sel->w;
oh = sel->h;
sel->x = sx;
sel->y = sy + bh;
sel->w = sw - 2;
sel->h = sh - 2 - bh;
restack();
for(c = getnext(clients); c; c = getnext(c->next))
if(c != sel)
ban(c);
resize(sel, arrange == dofloat, TopLeft);
sel->x = ox;
sel->y = oy;
sel->w = ow;
sel->h = oh;
}
else
arrange(NULL);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
void void
unmanage(Client *c) { unmanage(Client *c) {
Client *nc; Client *nc;
/* The server grab construct avoids race conditions. */
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(xerrordummy); XSetErrorHandler(xerrordummy);

View File

@ -11,15 +11,15 @@ const char *tags[] = { "dev", "work", "net", "fnord", NULL };
#define TILESYMBOL "[]=" #define TILESYMBOL "[]="
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*" #define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*"
#define SELBGCOLOR "#333366"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333333" #define NORMBGCOLOR "#333333"
#define NORMFGCOLOR "#dddddd" #define NORMFGCOLOR "#dddddd"
#define SELBGCOLOR "#333366"
#define SELFGCOLOR "#eeeeee"
#define STATUSBGCOLOR "#222222" #define STATUSBGCOLOR "#222222"
#define STATUSFGCOLOR "#9999cc" #define STATUSFGCOLOR "#9999cc"
#define MODKEY Mod1Mask
#define MASTERW 60 /* percent */ #define MASTERW 60 /* percent */
#define MODKEY Mod1Mask
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
@ -28,12 +28,12 @@ static Key key[] = { \
{ .cmd = "exec uxterm -bg '#111111' -fg '#eeeeee' -cr '#eeeeee' +sb -fn '"FONT"'" } }, \ { .cmd = "exec uxterm -bg '#111111' -fg '#eeeeee' -cr '#eeeeee' +sb -fn '"FONT"'" } }, \
{ 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 " \
"done | sort -u | dmenu)\" && exec $exe" } }, \ "| sort -u | dmenu -font '"FONT"' -normbg '"NORMBGCOLOR"' -normfg '"NORMFGCOLOR"' " \
"-selbg '"SELBGCOLOR"' -selfg '"SELFGCOLOR"')\" && 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 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY, XK_g, resizecol, { .i = 20 } }, \ { MODKEY, XK_g, resizecol, { .i = 20 } }, \
{ MODKEY, XK_s, resizecol, { .i = -20 } }, \ { MODKEY, XK_s, resizecol, { .i = -20 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
@ -61,7 +61,7 @@ static Key key[] = { \
#define RULES \ #define RULES \
static Rule rule[] = { \ static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \ /* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "net", False }, \ { "Firefox.*", "net", True}, \
{ "Gimp.*", NULL, True}, \ { "Gimp.*", NULL, True}, \
{ "MPlayer.*", NULL, True}, \ { "MPlayer.*", NULL, True}, \
{ "Acroread.*", NULL, True}, \ { "Acroread.*", NULL, True}, \

View File

@ -11,15 +11,15 @@ const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define TILESYMBOL "[]=" #define TILESYMBOL "[]="
#define FONT "fixed" #define FONT "fixed"
#define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee"
#define NORMBGCOLOR "#333366" #define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc" #define NORMFGCOLOR "#cccccc"
#define SELBGCOLOR "#666699"
#define SELFGCOLOR "#eeeeee"
#define STATUSBGCOLOR "#dddddd" #define STATUSBGCOLOR "#dddddd"
#define STATUSFGCOLOR "#222222" #define STATUSFGCOLOR "#222222"
#define MODKEY Mod1Mask
#define MASTERW 60 /* percent */ #define MASTERW 60 /* percent */
#define MODKEY Mod1Mask
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
@ -28,7 +28,6 @@ static Key key[] = { \
{ MODKEY, XK_Tab, focusnext, { 0 } }, \ { MODKEY, XK_Tab, focusnext, { 0 } }, \
{ MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \ { MODKEY|ShiftMask, XK_Tab, focusprev, { 0 } }, \
{ MODKEY, XK_Return, zoom, { 0 } }, \ { MODKEY, XK_Return, zoom, { 0 } }, \
{ MODKEY, XK_m, togglemax, { 0 } }, \
{ MODKEY, XK_g, resizecol, { .i = 20 } }, \ { MODKEY, XK_g, resizecol, { .i = 20 } }, \
{ MODKEY, XK_s, resizecol, { .i = -20 } }, \ { MODKEY, XK_s, resizecol, { .i = -20 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \

View File

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

9
draw.c
View File

@ -80,7 +80,7 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
/* extern */ /* extern */
void void
drawall() { drawall(void) {
Client *c; Client *c;
for(c = clients; c; c = getnext(c->next)) for(c = clients; c; c = getnext(c->next))
@ -89,7 +89,7 @@ drawall() {
} }
void void
drawstatus() { drawstatus(void) {
int i, x; int i, x;
dc.x = dc.y = 0; dc.x = dc.y = 0;
@ -104,7 +104,7 @@ drawstatus() {
} }
dc.w = bmw; dc.w = bmw;
drawtext(arrange == dotile ? TILESYMBOL : FLOATSYMBOL, dc.status, False); drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.status, False);
x = dc.x + dc.w; x = dc.x + dc.w;
dc.w = textw(stext); dc.w = textw(stext);
@ -149,7 +149,8 @@ getcolor(const char *colstr) {
Colormap cmap = DefaultColormap(dpy, screen); Colormap cmap = DefaultColormap(dpy, screen);
XColor color; XColor color;
XAllocNamedColor(dpy, cmap, colstr, &color, &color); if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color))
eprint("error, cannot allocate color '%s'\n", colstr);
return color.pixel; return color.pixel;
} }

7
dwm.1
View File

@ -16,7 +16,7 @@ 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 certain tags displays all windows with that tag. tags. Selecting certain tags displays all windows with these tags.
.P .P
dwm contains a small status bar which displays all available tags, the mode, dwm contains a small status bar which displays all available tags, the mode,
the title of the focused window, and the text read from standard input. The the title of the focused window, and the text read from standard input. The
@ -60,10 +60,7 @@ Focus next window.
Focus previous window. Focus previous window.
.TP .TP
.B Mod1-Return .B Mod1-Return
Zoom current window to the master column (tiling mode only). Zooms/cycles current window to/from master column (tiling mode), toggles maximization current window (floating mode).
.TP
.B Mod1-m
Maximize current window.
.TP .TP
.B Mod1-g .B Mod1-g
Grow current column (tiling mode only). Grow current column (tiling mode only).

49
dwm.h
View File

@ -4,32 +4,32 @@
* *
* dynamic window manager is designed like any other X client as well. It is * 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 * driven through handling X events. In contrast to other X clients, a window
* manager like dwm selects for SubstructureRedirectMask on the root window, to * manager selects for SubstructureRedirectMask on the root window, to receive
* receive events about window appearance and disappearance. Only one X * events about window (dis-)appearance. Only one X connection at a time is
* connection at a time is allowed to select for this event mask. * allowed to select for this event mask.
* *
* Calls to fetch an X event from the X event queue connection are blocking. * Calls to fetch an X event from the event queue are blocking. Due reading
* Due reading status text from standard input, a select-driven main loop has * status text from standard input, a select()-driven main loop has been
* been implemented which selects for reads on the X connection and * implemented which selects for reads on the X connection and STDIN_FILENO to
* STDIN_FILENO to handle all data smoothly and without busy-loop quirks. The * handle all data smoothly. The event handlers of dwm are organized in an
* event handlers of dwm are organized in an array which is accessed whenever a * array which is accessed whenever a new event has been fetched. This allows
* new event has been fetched. This allows event dispatching in O(1) time. * event dispatching in O(1) time.
* *
* Each child of the root window is called a client, except windows which have * 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 * set the override_redirect flag. Clients are organized in a global
* doubly-linked client list, the focus history is remembered through 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 * 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 * 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 * creates a small title window, which is resized whenever the (_NET_)WM_NAME
* _NET_WM_NAME properties are updated or the client is resized. * properties are updated or the client is moved/resized.
* *
* Keys and tagging rules are organized as arrays and defined in the config.h * 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, * 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 * 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 * represented by the arrange() function pointer, which wether points to
* or dotile. * dofloat() or dotile().
* *
* To understand everything else, start with reading main.c:main(). * To understand everything else, start reading main.c:main().
*/ */
#include "config.h" #include "config.h"
@ -77,12 +77,13 @@ struct Client {
char name[256]; char name[256];
int proto; int proto;
int x, y, w, h; int x, y, w, h;
int rx, ry, rw, rh; /* revert geometry */
int tx, ty, tw, th; /* title window geometry */ 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;
unsigned int border, weight; unsigned int border, weight;
Bool isfloat; Bool isfloat, ismax;
Bool *tags; Bool *tags;
Client *next; Client *next;
Client *prev; Client *prev;
@ -99,8 +100,8 @@ extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */
extern void (*handler[LASTEvent])(XEvent *); /* event handler */ extern void (*handler[LASTEvent])(XEvent *); /* event handler */
extern void (*arrange)(Arg *); /* arrange function, indicates mode */ 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; /* seltag is array of Bool */ extern Bool running, issel, *seltag; /* seltag is array of Bool */
extern Client *clients, *sel, *stack; /* global cleint list and stack */ extern Client *clients, *sel, *stack; /* global client list and stack */
extern Cursor cursor[CurLast]; extern Cursor cursor[CurLast];
extern DC dc; /* global draw context */ extern DC dc; /* global draw context */
extern Display *dpy; extern Display *dpy;
@ -108,6 +109,7 @@ extern Window root, barwin;
/* client.c */ /* client.c */
extern void ban(Client *c); /* ban c from screen */ extern void ban(Client *c); /* ban c from screen */
extern void configure(Client *c); /* send synthetic configure event */
extern void focus(Client *c); /* focus c, c may be NULL */ extern void focus(Client *c); /* focus c, c may be NULL */
extern Client *getclient(Window w); /* return client of w */ extern Client *getclient(Window w); /* return client of w */
extern Client *getctitle(Window w); /* return client of title window */ extern Client *getctitle(Window w); /* return client of title window */
@ -117,20 +119,19 @@ extern void manage(Window w, XWindowAttributes *wa); /* manage new client */
extern void resize(Client *c, Bool sizehints, Corner sticky); /* resize c*/ extern void resize(Client *c, Bool sizehints, Corner sticky); /* resize c*/
extern void updatesize(Client *c); /* update the size structs of c */ extern void updatesize(Client *c); /* update the size structs of c */
extern void updatetitle(Client *c); /* update the name of c */ extern void updatetitle(Client *c); /* update the name of c */
extern void togglemax(Arg *arg); /* (un)maximize c */
extern void unmanage(Client *c); /* destroy c */ extern void unmanage(Client *c); /* destroy c */
/* draw.c */ /* draw.c */
extern void drawall(); /* draw all visible client titles and the bar */ extern void drawall(void); /* draw all visible client titles and the bar */
extern void drawstatus(); /* draw the bar */ extern void drawstatus(void); /* draw the bar */
extern void drawtitle(Client *c); /* draw title of c */ extern void drawtitle(Client *c); /* draw title of c */
extern unsigned long getcolor(const char *colstr); /* return color of colstr */ extern unsigned long getcolor(const char *colstr); /* return color of colstr */
extern void setfont(const char *fontstr); /* set the font for DC */ extern void setfont(const char *fontstr); /* set the font for DC */
extern unsigned int textw(const char *text); /* return the width of text in px*/ extern unsigned int textw(const char *text); /* return the width of text in px*/
/* event.c */ /* event.c */
extern void grabkeys(); /* grab all keys defined in config.h */ extern void grabkeys(void); /* grab all keys defined in config.h */
extern void procevent(); /* process pending X events */ extern void procevent(void); /* process pending X events */
/* main.c */ /* main.c */
extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */ extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */
@ -139,7 +140,7 @@ extern void sendevent(Window w, Atom a, long value); /* send synthetic event to
extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */ extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */
/* tag.c */ /* tag.c */
extern void initrregs(); /* initialize regexps of rules defined in config.h */ extern void initrregs(void); /* initialize regexps of rules defined in config.h */
extern Client *getnext(Client *c); /* returns next visible client */ extern Client *getnext(Client *c); /* returns next visible client */
extern Client *getprev(Client *c); /* returns previous visible client */ extern Client *getprev(Client *c); /* returns previous visible client */
extern void settags(Client *c, Client *trans); /* sets tags of c */ extern void settags(Client *c, Client *trans); /* sets tags of c */
@ -160,7 +161,7 @@ extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored
extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */ extern void focusprev(Arg *arg); /* focuses previous visible client, arg is ignored */
extern Bool isvisible(Client *c); /* returns True if client is visible */ extern Bool isvisible(Client *c); /* returns True if client is visible */
extern void resizecol(Arg *arg); /* resizes the master width with arg's index value */ extern void resizecol(Arg *arg); /* resizes the master width with arg's index value */
extern void restack(); /* restores z layers of all clients */ extern void restack(void); /* restores z layers of all clients */
extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */ extern void togglemode(Arg *arg); /* toggles global arrange function (dotile/dofloat) */
extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */ extern void toggleview(Arg *arg); /* toggles the tag with arg's index (in)visible */
extern void view(Arg *arg); /* views the tag with arg's index */ extern void view(Arg *arg); /* views the tag with arg's index */

60
event.c
View File

@ -32,12 +32,15 @@ movemouse(Client *c) {
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove], CurrentTime) != GrabSuccess) None, cursor[CurMove], CurrentTime) != GrabSuccess)
return; return;
c->ismax = False;
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
for(;;) { for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch (ev.type) { switch (ev.type) {
default: case ButtonRelease:
break; resize(c, True, TopLeft);
XUngrabPointer(dpy, CurrentTime);
return;
case Expose: case Expose:
handler[Expose](&ev); handler[Expose](&ev);
break; break;
@ -47,9 +50,6 @@ movemouse(Client *c) {
c->y = ocy + (ev.xmotion.y - y1); c->y = ocy + (ev.xmotion.y - y1);
resize(c, False, TopLeft); resize(c, False, TopLeft);
break; break;
case ButtonRelease:
XUngrabPointer(dpy, CurrentTime);
return;
} }
} }
} }
@ -66,21 +66,24 @@ resizemouse(Client *c) {
if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize], CurrentTime) != GrabSuccess) None, cursor[CurResize], CurrentTime) != GrabSuccess)
return; return;
c->ismax = False;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h); XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
for(;;) { for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev); XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
switch(ev.type) { switch(ev.type) {
default: case ButtonRelease:
break; resize(c, True, TopLeft);
XUngrabPointer(dpy, CurrentTime);
return;
case Expose: case Expose:
handler[Expose](&ev); handler[Expose](&ev);
break; break;
case MotionNotify: case MotionNotify:
XSync(dpy, False); XSync(dpy, False);
if((nw = abs(ocx - ev.xmotion.x))) if((nw = abs(ocx - ev.xmotion.x)))
c->w = abs(ocx - ev.xmotion.x); c->w = nw;
if((nh = abs(ocy - ev.xmotion.y))) if((nh = abs(ocy - ev.xmotion.y)))
c->h = abs(ocy - ev.xmotion.y); c->h = nh;
c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w; c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h; c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
if(ocx <= ev.xmotion.x) if(ocx <= ev.xmotion.x)
@ -89,9 +92,6 @@ resizemouse(Client *c) {
sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight; sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
resize(c, True, sticky); resize(c, True, sticky);
break; break;
case ButtonRelease:
XUngrabPointer(dpy, CurrentTime);
return;
} }
} }
} }
@ -130,51 +130,31 @@ buttonpress(XEvent *e) {
} }
else if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
focus(c); focus(c);
if(maximized || CLEANMASK(ev->state) != MODKEY) if(CLEANMASK(ev->state) != MODKEY)
return; return;
if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) { if(ev->button == Button1 && (arrange == dofloat || c->isfloat)) {
restack(c); restack();
movemouse(c); movemouse(c);
} }
else if(ev->button == Button2) else if(ev->button == Button2)
zoom(NULL); zoom(NULL);
else if(ev->button == Button3 && (arrange == dofloat || c->isfloat)) { else if(ev->button == Button3 && (arrange == dofloat || c->isfloat)) {
restack(c); restack();
resizemouse(c); resizemouse(c);
} }
} }
} }
static void
synconfig(Client *c, int x, int y, int w, int h, unsigned int border) {
XEvent synev;
synev.type = ConfigureNotify;
synev.xconfigure.display = dpy;
synev.xconfigure.event = c->win;
synev.xconfigure.window = c->win;
synev.xconfigure.x = x;
synev.xconfigure.y = y;
synev.xconfigure.width = w;
synev.xconfigure.height = h;
synev.xconfigure.border_width = border;
synev.xconfigure.above = None;
XSendEvent(dpy, c->win, True, NoEventMask, &synev);
}
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;
XEvent synev;
XWindowChanges wc; XWindowChanges wc;
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
if((c == sel) && !c->isfloat && (arrange != dofloat) && maximized) { c->ismax = False;
synconfig(c, sx, sy + bh, sw - 2, sh - 2 - bh, ev->border_width);
XSync(dpy, False);
return;
}
gravitate(c, True); gravitate(c, True);
if(ev->value_mask & CWX) if(ev->value_mask & CWX)
c->x = ev->x; c->x = ev->x;
@ -195,7 +175,7 @@ configurerequest(XEvent *e) {
if(newmask) if(newmask)
XConfigureWindow(dpy, c->win, newmask, &wc); XConfigureWindow(dpy, c->win, newmask, &wc);
else else
synconfig(c, c->x, c->y, c->w, c->h, c->border); configure(c);
XSync(dpy, False); XSync(dpy, False);
if(c->isfloat) if(c->isfloat)
resize(c, False, TopLeft); resize(c, False, TopLeft);
@ -368,7 +348,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
}; };
void void
grabkeys() { grabkeys(void) {
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;
@ -388,7 +368,7 @@ grabkeys() {
} }
void void
procevent() { procevent(void) {
XEvent ev; XEvent ev;
while(XPending(dpy)) { while(XPending(dpy)) {

7
main.c
View File

@ -24,7 +24,6 @@ unsigned int ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast]; Atom wmatom[WMLast], netatom[NetLast];
Bool running = True; Bool running = True;
Bool issel = True; Bool issel = True;
Bool maximized = False;
Client *clients = NULL; Client *clients = NULL;
Client *sel = NULL; Client *sel = NULL;
Client *stack = NULL; Client *stack = NULL;
@ -39,7 +38,7 @@ static int (*xerrorxlib)(Display *, XErrorEvent *);
static Bool otherwm, readin; static Bool otherwm, readin;
static void static void
cleanup() { cleanup(void) {
close(STDIN_FILENO); close(STDIN_FILENO);
while(sel) { while(sel) {
resize(sel, True, TopLeft); resize(sel, True, TopLeft);
@ -59,7 +58,7 @@ cleanup() {
} }
static void static void
scan() { scan(void) {
unsigned int i, num; unsigned int i, num;
Window *wins, d1, d2; Window *wins, d1, d2;
XWindowAttributes wa; XWindowAttributes wa;
@ -80,7 +79,7 @@ scan() {
} }
static void static void
setup() { setup(void) {
int i, j; int i, j;
unsigned int mask; unsigned int mask;
Window w; Window w;

2
tag.c
View File

@ -45,7 +45,7 @@ getprev(Client *c) {
} }
void void
initrregs() { initrregs(void) {
unsigned int i; unsigned int i;
regex_t *reg; regex_t *reg;

3
util.c
View File

@ -47,7 +47,8 @@ spawn(Arg *arg) {
if(!arg->cmd) if(!arg->cmd)
return; return;
/* the double-fork construct avoids zombie processes */ /* The double-fork construct avoids zombie processes and keeps the code
* clean from stupid signal handlers. */
if(fork() == 0) { if(fork() == 0) {
if(fork() == 0) { if(fork() == 0) {
if(dpy) if(dpy)

58
view.c
View File

@ -7,7 +7,7 @@
/* static */ /* static */
static Client * static Client *
minclient() { minclient(void) {
Client *c, *min; Client *c, *min;
if((clients && clients->isfloat) || arrange == dofloat) if((clients && clients->isfloat) || arrange == dofloat)
@ -18,8 +18,14 @@ minclient() {
return min; return min;
} }
static Client *
nexttiled(Client *c) {
for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
return c;
}
static void static void
reorder() { reorder(void) {
Client *c, *newclients, *tail; Client *c, *newclients, *tail;
newclients = tail = NULL; newclients = tail = NULL;
@ -36,10 +42,24 @@ reorder() {
clients = newclients; clients = newclients;
} }
static Client * static void
nexttiled(Client *c) { togglemax(Client *c)
for(c = getnext(c); c && c->isfloat; c = getnext(c->next)); {
return c; XEvent ev;
if((c->ismax = !c->ismax)) {
c->rx = c->x; c->x = sx;
c->ry = c->y; c->y = bh;
c->rw = c->w; c->w = sw;
c->rh = c->h; c->h = sh - bh - 2;
}
else {
c->x = c->rx;
c->y = c->ry;
c->w = c->rw;
c->h = c->rh;
}
resize(c, True, TopLeft);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
} }
/* extern */ /* extern */
@ -61,8 +81,6 @@ void
dofloat(Arg *arg) { dofloat(Arg *arg) {
Client *c; Client *c;
maximized = False;
for(c = clients; c; c = c->next) { for(c = clients; c; c = c->next) {
if(isvisible(c)) { if(isvisible(c)) {
resize(c, True, TopLeft); resize(c, True, TopLeft);
@ -82,12 +100,9 @@ dotile(Arg *arg) {
int h, i, n, w; int h, i, n, w;
Client *c; Client *c;
maximized = False;
w = sw - mw; w = sw - mw;
for(n = 0, c = clients; c; c = c->next) for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
if(isvisible(c) && !c->isfloat) n++;
n++;
if(n > 1) if(n > 1)
h = (sh - bh) / (n - 1); h = (sh - bh) / (n - 1);
@ -100,6 +115,7 @@ dotile(Arg *arg) {
resize(c, True, TopLeft); resize(c, True, TopLeft);
continue; continue;
} }
c->ismax = False;
if(n == 1) { if(n == 1) {
c->x = sx; c->x = sx;
c->y = sy + bh; c->y = sy + bh;
@ -190,7 +206,7 @@ resizecol(Arg *arg) {
for(n = 0, c = clients; c; c = c->next) for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat) if(isvisible(c) && !c->isfloat)
n++; n++;
if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized) if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
return; return;
if(sel == getnext(clients)) { if(sel == getnext(clients)) {
@ -207,10 +223,10 @@ resizecol(Arg *arg) {
} }
void void
restack() { restack(void) {
Client *c; Client *c;
XEvent ev; XEvent ev;
if(!sel) { if(!sel) {
drawstatus(); drawstatus();
return; return;
@ -276,10 +292,18 @@ zoom(Arg *arg) {
unsigned int n; unsigned int n;
Client *c; Client *c;
if(!sel)
return;
if(sel->isfloat || (arrange == dofloat)) {
togglemax(sel);
return;
}
for(n = 0, c = clients; c; c = c->next) for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat) if(isvisible(c) && !c->isfloat)
n++; n++;
if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized) if(n < 2 || (arrange == dofloat))
return; return;
if((c = sel) == nexttiled(clients)) if((c = sel) == nexttiled(clients))