Compare commits

...

144 Commits
1.7 ... 2.8

Author SHA1 Message Date
b5d297f02f fixed cleanup, using clients instead of sel 2007-01-02 14:40:18 +01:00
9056d7ea88 changed comment of updatesizehints 2007-01-02 12:28:02 +01:00
ebd17e4827 renamed updatesize into updatesizehints (thx to Sander for this hint) 2007-01-01 19:10:31 +01:00
7e59c89250 small simplification to dotile() (thx to Ross for this hint) 2006-12-20 12:07:05 +01:00
9e4e4d9022 migrated arg's config.h to new dmenu command line options 2006-12-19 11:38:08 +01:00
71fd06f843 added Solaris hints 2006-12-18 14:39:34 +01:00
58e6866d86 Added tag 2.7 for changeset 21951c0dfbae5af68ed77821a4d87253ee91803f 2006-12-14 08:50:49 +01:00
c7da124149 applied Sanders patch 2006-12-13 14:15:38 +01:00
21bd90d7d3 fixed man page, status bar displays EOF instead of "broken pipe" 2006-12-13 13:53:10 +01:00
c8f96b5b4c added the java odyssee to CAVEATS section 2006-12-13 13:42:17 +01:00
ded60365d4 removed Client->grav 2006-12-12 19:14:38 +01:00
629647dfee removed gravitate for the moment 2006-12-11 16:45:02 +01:00
4ca3d861f0 disabling configure() during resize 2006-12-11 09:42:16 +01:00
069e7a6e24 made gravitate effectless, waiting for complains ;) 2006-12-11 08:31:30 +01:00
ac6e34ea06 fixed diagnostic error message 2006-12-08 11:11:52 +01:00
a308b7507a removed the hardcoded fixed fallback, it is useless in non-Latin1 environments 2006-12-08 10:40:09 +01:00
630e7ff26f we don't use the term clients anymore, windows is the better term 2006-12-07 16:38:57 +01:00
3764ab471b Added tag 2.6 for changeset 5308dd22b6ee8e3218c81d9e7e4125f235bb5778 2006-12-07 14:55:29 +01:00
a3319c6f8e found compromise for fonts 2006-12-07 14:39:31 +01:00
66c699a701 nah, people should define 'fixed' to be compatible with their locale 2006-12-07 12:03:15 +01:00
aaf1e44da9 using a UTF-8 capable fixed font 2006-12-07 11:55:04 +01:00
1ef2307ec4 switching to uxterm again, I get kretze from this urxvt crap 2006-12-07 10:43:34 +01:00
d42c3ba2dc with this patch everything works fine for me 2006-12-07 10:02:46 +01:00
4b06155873 don't use Xlocale crap, let's use locale.h instead 2006-12-07 09:49:45 +01:00
857d825eeb using the portable Xmb+UTF-8 way of life, will see if this works well... 2006-12-07 09:47:55 +01:00
6b345353e3 improved the memory leak prevention 2006-12-06 11:19:06 +01:00
ab3b3a8f61 making terminus more explicit a regular font (otherwise olique font might be used in some setups like mine). 2006-12-05 14:21:18 +01:00
71b82fb1f6 also setting LC_CTYPE only 2006-12-05 13:31:29 +01:00
9bd9ea423e enforcing using fontsets even if they are incomplete for some encodings 2006-12-05 10:30:31 +01:00
99964398e7 Added tag 2.5.1 for changeset c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2006-12-04 21:01:14 +01:00
7009ebfa69 hotfix of a serious crashing bug 2006-12-04 21:00:26 +01:00
760e23dd3a Added tag 2.5 for changeset dcbbfabc8ecc5f33a6cc950584de87da1a368045 2006-12-04 15:39:43 +01:00
c53d9d516a applied Manuel's regex patch 2006-12-03 11:21:25 +01:00
7739e6b466 made squares equally sized, and 1px bigger 2006-12-01 17:55:46 +01:00
4881857458 if client is focused, the emptysquare don't needs to be drawed 2006-12-01 17:51:05 +01:00
c73d5cb7b6 and the winner is 2006-12-01 17:45:27 +01:00
6458803d21 sander1 proposal 2006-12-01 17:36:37 +01:00
6e72d781f7 dood 2006-12-01 16:55:42 +01:00
4e926a9ef2 darkening the fg colors somewhat 2006-12-01 15:50:22 +01:00
4ba3cfaee9 less obtrusive indicator (only a top line) 2006-12-01 15:03:42 +01:00
e655e8a7d5 final2 indicator 2006-12-01 12:52:16 +01:00
c34e4e4b39 removing the -1 on final indicators, looks cleaner 2006-12-01 12:39:13 +01:00
a678ee6365 final indicators 2006-12-01 12:25:23 +01:00
49f0ee329d changed things like I described in last mail 2006-12-01 10:16:10 +01:00
0c9d9a3d94 improved tag indicator 2006-12-01 09:52:15 +01:00
89e1acb0bb removed viewall signature from dwm.h 2006-11-30 17:01:39 +01:00
c2ed26b711 next version will be 2.5 2006-11-30 15:51:26 +01:00
42fd392e05 removed viewall(), replaced with view(-1); added tag(-1) to tag a client with all tags (new key combo MODKEY-Shift-0) 2006-11-30 15:27:43 +01:00
e06447ee88 Added tag 2.4 for changeset 32b246925086910d63147483160281a91a47479f 2006-11-30 09:19:52 +01:00
683dabe5e6 extended dwm.1 with last change 2006-11-28 17:36:00 +01:00
3aff96177c togglefloat should only work in dotile mode (thanks to Sander for this hint) 2006-11-28 17:35:31 +01:00
0a915eba8f applied Alex Elide's tricky patch, thanks! 2006-11-27 17:51:50 +01:00
19dcbc5717 returning to old Key struct 2006-11-27 17:49:58 +01:00
d2a4952956 applied Szabolcs Nagy's patch (thank you!) 2006-11-27 17:46:02 +01:00
0c97b21b61 applied patch by Jukka 2006-11-27 17:30:06 +01:00
19390b1a91 changing Key.func into Key.func[NFUNCS], this allows sequences execution of functions per keypress (avoids implementing useless masterfunctions which call atomic ones) 2006-11-27 13:21:38 +01:00
8dc86051df added man page entry 2006-11-27 11:05:47 +01:00
46d5f9d1bf added togglefloat to hg tip (i consider this useful for some cases), using MODKEY-Shift-space as shortcut 2006-11-27 10:57:37 +01:00
35e96b8deb applied Jukka's patch preventing some cornercases and making the EOF error message correct 2006-11-27 10:29:47 +01:00
2210ea7e3b applied yet another proposal of Manuel 2006-11-26 15:43:16 +01:00
61a1910f91 applied Jukka's sizeof K&R compliance patch, applied Manuels' last-line printage proposal for stdin reading. 2006-11-26 14:26:53 +01:00
27ef73507b applied Jukka's stdinread patch 2006-11-26 13:31:36 +01:00
2b35fb643e next version will be 2.4 2006-11-25 19:26:31 +01:00
478f6f95f1 applied Manuels patch (thanks to Manuel!) 2006-11-25 19:26:16 +01:00
44411d2d48 small fix of man page 2006-11-24 17:02:41 +01:00
a2175cf71a Added tag 2.3 for changeset 719b37b37b0df829d7cf017ac70e353088fe5849 2006-11-24 15:46:32 +01:00
4606d218c3 using the term 'indicated' instead of 'higlighted' 2006-11-23 16:00:16 +01:00
d37d0f24e6 updated man page with the bottom right corner indicator 2006-11-23 15:59:16 +01:00
321e8d51ed fififif 2006-11-22 16:17:50 +01:00
78f4b51757 added a similiar patch to Daves solution to indicate if there are clients with a specific tag 2006-11-22 14:57:09 +01:00
7d168a2621 returning to old bar colorization behavior, like sander proposed for consistency reasons 2006-11-21 15:03:08 +01:00
931e712eac applied Gottox patches 2006-11-21 14:49:13 +01:00
4ec04209e0 using iso10646 explicitely in arg's config.h 2006-11-21 12:17:47 +01:00
82ddba88a2 Added tag 2.2 for changeset 7e92f58754ae6edb3225f26d754bd89c1ff458cf 2006-11-21 09:41:33 +01:00
52a8cc8d46 nah reverting to my prev style, that's really the best 2006-11-18 21:33:33 +01:00
d175df8aa3 applying aluminium style for arg's config.h 2006-11-18 21:26:53 +01:00
b003a35fde applied Gottox' windowarea patch 2006-11-16 14:40:57 +01:00
df1a0f9445 using a more blue-ish color... 2006-11-08 17:16:38 +01:00
5b07b85838 making the selected color more lightning 2006-11-08 17:10:51 +01:00
f320cd203b next release will be 2.2 2006-11-03 09:22:40 +01:00
f78c16f8c6 applied Jukkas patch 2006-11-03 08:29:39 +01:00
0c5f47e720 Added tag 2.1 for changeset a2c465098a3b972bbed00feda9804b6aae1e9531 2006-11-02 10:18:22 +01:00
4b5b3d90af renamed resizecol into resizemaster 2006-10-31 12:07:32 +01:00
2cce4b95cd applied Gottox patch to simplify the resizing of col, instead of resizing the current area, it only resizes the master area in the future (seems more predictable) 2006-10-31 12:06:38 +01:00
8e6eb52196 Added tag 2.0 for changeset 12deea36603da407e3f32640048846a3bd74a9ec 2006-10-31 09:02:42 +01:00
04b633ddf3 make sure that changing sx has no impact on snapping 2006-10-31 09:02:16 +01:00
b76561a212 in a 1920x1200 setup 40 pixels of snap value are much better than 20 2006-10-30 12:40:10 +01:00
51c7589c87 fixed stupid bug of snap-to-screen 2006-10-30 12:26:55 +01:00
99785382ae changing snap priority 2006-10-30 12:07:00 +01:00
dc1690ce0f removed useless abs() calls 2006-10-30 12:04:08 +01:00
b6614261ea added screen-border snapping in floating mode, feels quite well 2006-10-30 11:58:05 +01:00
91e569ca37 and another fix 2006-10-27 13:29:35 +02:00
0f395c1b11 applied sanders try2 patch 2006-10-27 13:28:26 +02:00
2b13e7466f applied sanders max size fix 2006-10-27 12:05:47 +02:00
0982e47408 stupid urxvt needs bg to highlight selections in a sane way, though that makes sense to some extend 2006-10-27 10:24:15 +02:00
b93ebcf42f reverting to original 2006-10-26 15:41:40 +02:00
a08d83ba62 applied sander's config.*h nitpick patch 2006-10-26 15:29:20 +02:00
2b7c275ce8 some other change 2006-10-26 15:26:17 +02:00
040d0f48a0 apply small fix to prevent apps like mplayer wandering when toggling fullscreen 2006-10-26 15:05:45 +02:00
724f35a664 forgot to use -tr, which actually prevents the ugly flicker (using xsetroot -solid black as root window pixmap to make this work nicely) 2006-10-26 12:22:26 +02:00
6f3872edbd using MASTER 600 again, it is definately better, and using urxvtc for the moment (it doesn't flickers on refreshes, but this is not because of Marc Lehmann, it is because of the original rxvt code) 2006-10-26 12:13:41 +02:00
87324e680c changing MASTER in config.arg.h from 600 to 550 per thousand 2006-10-26 11:21:45 +02:00
c2b908f603 my new 1920x1200 Z61p arrived, now I can use terminus in a sane way... 2006-10-26 10:21:27 +02:00
d7734f996f moved MOUSEMASK into event.c (not used in other places) 2006-10-16 16:50:03 +02:00
8b68890650 now being at v2.0 2006-10-14 18:21:39 +02:00
b60406cb9b using lsx instead of Jukka's shell construct 2006-10-13 18:47:24 +02:00
ce9a9934ec hotfix 2006-10-06 14:01:53 +02:00
720b2abe17 Added tag 1.9 for changeset a5567a0d30112822db2627a04a2e7aa3b6c38148 2006-10-06 13:43:59 +02:00
5983c00b95 do* has no Arg arument anymore (never called directly) 2006-10-06 13:06:37 +02:00
6651dd7fd9 code polishing, removed unnecessary newlines 2006-10-06 11:50:15 +02:00
acdea31916 yet another small fix and simplification of dotile 2006-10-06 11:37:12 +02:00
10885d349a removed the stack position stuff 2006-10-05 19:27:28 +02:00
1c1d09f3e9 small boundary check fix 2006-10-05 18:23:28 +02:00
0384faeee5 changing MASTER value from percent into per mill 2006-10-05 18:18:47 +02:00
6cca3999c8 Added tag 1.8 for changeset c71952fa3c7ca848ec38a6923b5c6d0e18fff431 2006-10-05 19:00:58 +02:00
69408d384d simplified dotile(), removed misleading line 2006-10-05 13:47:30 +02:00
4aea423f06 final fix for man page 2006-10-05 13:44:48 +02:00
6fc8a63041 keep master ratio on resizecol -> arrange 2006-10-05 12:59:35 +02:00
2583a7c0d1 yet another simplification of dotile() 2006-10-05 12:18:04 +02:00
0ef6e3103c simplified dotile() 2006-10-05 12:13:24 +02:00
7c052b37c8 applied resizecol fix by Jukka 2006-10-05 11:00:55 +02:00
d9c475d7f4 Button3 click on mode label toggles stack position now 2006-10-05 09:37:11 +02:00
c8e57332d1 applied dave's highlight patch for big fonts 2006-09-29 19:06:27 +02:00
c045459917 using ff tiled again, seems to work perfectly with new bottom stack 2006-09-29 18:40:32 +02:00
e0f64e63db applied ality's hardcode-0 patches 2006-09-29 18:21:02 +02:00
dddd58a8cd added symbols for different modes 2006-09-29 18:08:20 +02:00
010fd21b20 removed useless updatemaster 2006-09-29 17:25:49 +02:00
1802fad2f9 documented the new behavior in man page 2006-09-29 17:20:05 +02:00
f833d109d1 fixed small offset issue 2006-09-29 17:15:05 +02:00
7225c99903 fixed the z-layer issue described on mailinglist 2006-09-29 17:12:57 +02:00
36178933ed removed the direction flipping 2006-09-29 17:02:56 +02:00
ad0da9a571 small fix of a corner case 2006-09-29 16:54:15 +02:00
6646468125 small change 2006-09-29 16:44:02 +02:00
fee8df6ccf added the new dotile as described on ml 2006-09-29 16:22:20 +02:00
8fa47ac679 prelim of dotile() 2006-09-29 14:39:03 +02:00
b427a2c6cb I changed sanders patch to fix the ff issue to be simplier, though it needs testing if this really fixes the issue 2006-09-29 12:56:01 +02:00
14d05e7c72 first step to a more flexible dotile() algorithm 2006-09-29 12:38:27 +02:00
a118a57fe3 renamed column into area 2006-09-28 21:29:20 +02:00
02cea3b47e small change to README 2006-09-28 16:14:48 +02:00
1c2d673ded applied Jukkas patch 2006-09-28 14:03:39 +02:00
c34df2c1b6 Added tag 1.7.1 for changeset d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 2006-09-27 17:21:25 +02:00
6092aa977e fixing the settags issue, preparing 1.7.1 2006-09-27 17:18:46 +02:00
c9cc2b385a removed an unused var 2006-09-26 17:42:14 +02:00
b39d0c521a Added tag 1.7 for changeset 4dbdb61c8b8ce21dee5c7050a6b103855964ed20 2006-09-26 17:39:30 +02:00
14 changed files with 335 additions and 415 deletions

13
.hgtags
View File

@ -14,3 +14,16 @@ f5f5cbf016a94b48a8fe9c47f0736e96d166d5d4 1.3
3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4 3cff9403766bf83a9fc2a0aef230115d68de2a8e 1.4
728c9089b079721b43c3347124639a29baa22a97 1.5 728c9089b079721b43c3347124639a29baa22a97 1.5
ad3fa2d185426c51fd5deceae809770363f8d33c 1.6 ad3fa2d185426c51fd5deceae809770363f8d33c 1.6
4dbdb61c8b8ce21dee5c7050a6b103855964ed20 1.7
d5ad819f2a66a40fa75dd2e44429f3bfc884d07b 1.7.1
c71952fa3c7ca848ec38a6923b5c6d0e18fff431 1.8
a5567a0d30112822db2627a04a2e7aa3b6c38148 1.9
12deea36603da407e3f32640048846a3bd74a9ec 2.0
a2c465098a3b972bbed00feda9804b6aae1e9531 2.1
7e92f58754ae6edb3225f26d754bd89c1ff458cf 2.2
719b37b37b0df829d7cf017ac70e353088fe5849 2.3
32b246925086910d63147483160281a91a47479f 2.4
dcbbfabc8ecc5f33a6cc950584de87da1a368045 2.5
c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1
5308dd22b6ee8e3218c81d9e7e4125f235bb5778 2.6
21951c0dfbae5af68ed77821a4d87253ee91803f 2.7

2
README
View File

@ -37,7 +37,7 @@ like this in your .xinitrc:
while true while true
do do
echo `date` `uptime | sed 's/.*://; s/,//g'` echo `date` `uptime | sed 's/.*,//'`
sleep 1 sleep 1
done | dwm done | dwm

142
client.c
View File

@ -1,5 +1,4 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
@ -54,19 +53,6 @@ grabbuttons(Client *c, Bool focused) {
GrabModeAsync, GrabModeSync, None, None); GrabModeAsync, GrabModeSync, None, None);
} }
static void
resizetitle(Client *c) {
c->tw = textw(c->name);
if(c->tw > c->w)
c->tw = c->w + 2;
c->tx = c->x + c->w - c->tw + 2;
c->ty = c->y;
if(isvisible(c))
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else
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;
@ -145,60 +131,6 @@ getctitle(Window w) {
return NULL; return NULL;
} }
void
gravitate(Client *c, Bool invert) {
int dx = 0, dy = 0;
switch(c->grav) {
default:
break;
case StaticGravity:
case NorthWestGravity:
case NorthGravity:
case NorthEastGravity:
dy = c->border;
break;
case EastGravity:
case CenterGravity:
case WestGravity:
dy = -(c->h / 2) + c->border;
break;
case SouthEastGravity:
case SouthGravity:
case SouthWestGravity:
dy = -(c->h);
break;
}
switch (c->grav) {
default:
break;
case StaticGravity:
case NorthWestGravity:
case WestGravity:
case SouthWestGravity:
dx = c->border;
break;
case NorthGravity:
case CenterGravity:
case SouthGravity:
dx = -(c->w / 2) + c->border;
break;
case NorthEastGravity:
case EastGravity:
case SouthEastGravity:
dx = -(c->w + c->border);
break;
}
if(invert) {
dx = -dx;
dy = -dy;
}
c->x += dx;
c->y += dy;
}
void void
killclient(Arg *arg) { killclient(Arg *arg) {
if(!sel) if(!sel)
@ -218,24 +150,21 @@ manage(Window w, XWindowAttributes *wa) {
c = emallocz(sizeof(Client)); c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool)); c->tags = emallocz(ntags * sizeof(Bool));
c->win = w; c->win = w;
c->border = 0;
c->x = c->tx = wa->x; c->x = c->tx = wa->x;
c->y = c->ty = wa->y; c->y = c->ty = wa->y;
c->w = c->tw = wa->width; c->w = c->tw = wa->width;
c->h = wa->height; c->h = wa->height;
c->th = bh; c->th = bh;
updatesizehints(c);
c->border = 0; if(c->x + c->w + 2 * BORDERPX > sw)
updatesize(c); c->x = sw - c->w - 2 * BORDERPX;
if(c->x < sx)
if(c->x + c->w + 2 > sw) c->x = sx;
c->x = sw - c->w - 2; if(c->y + c->h + 2 * BORDERPX > sh)
if(c->x < 0) c->y = sh - c->h - 2 * BORDERPX;
c->x = 0;
if(c->y + c->h + 2 > sh)
c->y = sh - c->h - 2;
if(c->h != sh && c->y < bh) if(c->h != sh && c->y < bh)
c->y = bh; c->y = bh;
c->proto = getproto(c->win); c->proto = getproto(c->win);
XSelectInput(dpy, c->win, XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask); StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
@ -243,32 +172,27 @@ manage(Window w, XWindowAttributes *wa) {
twa.override_redirect = 1; twa.override_redirect = 1;
twa.background_pixmap = ParentRelative; twa.background_pixmap = ParentRelative;
twa.event_mask = ExposureMask | EnterWindowMask; twa.event_mask = ExposureMask | EnterWindowMask;
c->twin = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, c->twin = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
0, DefaultDepth(dpy, screen), CopyFromParent, 0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen), DefaultVisual(dpy, screen),
CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
grabbuttons(c, False); grabbuttons(c, False);
updatetitle(c);
settags(c, getclient(trans)); settags(c, getclient(trans));
if(!c->isfloat) if(!c->isfloat)
c->isfloat = trans c->isfloat = trans || c->isfixed;
|| (c->maxw && c->minw && resizetitle(c);
c->maxw == c->minw && c->maxh == c->minh);
if(clients) if(clients)
clients->prev = c; clients->prev = c;
c->next = clients; c->next = clients;
c->snext = stack; c->snext = stack;
stack = clients = c; stack = clients = c;
updatetitle(c);
ban(c); ban(c);
XMapWindow(dpy, c->win); XMapWindow(dpy, c->win);
XMapWindow(dpy, c->twin); XMapWindow(dpy, c->twin);
if(isvisible(c)) if(isvisible(c))
focus(c); focus(c);
arrange(NULL); arrange();
} }
void void
@ -295,17 +219,15 @@ resize(Client *c, Bool sizehints, Corner sticky) {
c->x = right - c->w; c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight) if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h; c->y = bottom - c->h;
/* offscreen appearance fixes */ /* offscreen appearance fixes */
if(c->x + c->w < 0) if(c->x + c->w < sx)
c->x = 0; c->x = sx;
if(c->y + c->h < bh) if(c->y + c->h < bh)
c->y = bh; c->y = bh;
if(c->x > sw) if(c->x > sw)
c->x = sw - c->w; c->x = sw - c->w;
if(c->y > sh) if(c->y > sh)
c->y = sh - c->h; 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;
@ -314,14 +236,27 @@ resize(Client *c, Bool sizehints, Corner sticky) {
if(c->w == sw && c->h == sh) if(c->w == sw && c->h == sh)
wc.border_width = 0; wc.border_width = 0;
else else
wc.border_width = 1; wc.border_width = BORDERPX;
XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc); XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
configure(c); configure(c);
XSync(dpy, False); XSync(dpy, False);
} }
void void
updatesize(Client *c) { resizetitle(Client *c) {
c->tw = textw(c->name);
if(c->tw > c->w)
c->tw = c->w + 2 * BORDERPX;
c->tx = c->x + c->w - c->tw + 2 * BORDERPX;
c->ty = c->y;
if(isvisible(c))
XMoveResizeWindow(dpy, c->twin, c->tx, c->ty, c->tw, c->th);
else
XMoveResizeWindow(dpy, c->twin, c->tx + 2 * sw, c->ty, c->tw, c->th);
}
void
updatesizehints(Client *c) {
long msize; long msize;
XSizeHints size; XSizeHints size;
@ -352,10 +287,8 @@ updatesize(Client *c) {
} }
else else
c->minw = c->minh = 0; c->minw = c->minh = 0;
if(c->flags & PWinGravity) c->isfixed = (c->maxw && c->minw && c->maxh && c->minh &&
c->grav = size.win_gravity; c->maxw == c->minw && c->maxh == c->minh);
else
c->grav = NorthWestGravity;
} }
void void
@ -372,17 +305,16 @@ updatetitle(Client *c) {
if(!name.nitems) if(!name.nitems)
return; return;
if(name.encoding == XA_STRING) if(name.encoding == XA_STRING)
strncpy(c->name, (char *)name.value, sizeof(c->name)); strncpy(c->name, (char *)name.value, sizeof c->name);
else { else {
if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
&& n > 0 && *list) && n > 0 && *list)
{ {
strncpy(c->name, *list, sizeof(c->name)); strncpy(c->name, *list, sizeof c->name);
XFreeStringList(list); XFreeStringList(list);
} }
} }
XFree(name.value); XFree(name.value);
resizetitle(c);
} }
void void
@ -392,22 +324,18 @@ unmanage(Client *c) {
/* The server grab construct avoids race conditions. */ /* The server grab construct avoids race conditions. */
XGrabServer(dpy); XGrabServer(dpy);
XSetErrorHandler(xerrordummy); XSetErrorHandler(xerrordummy);
detach(c); detach(c);
detachstack(c); detachstack(c);
if(sel == c) { if(sel == c) {
for(nc = stack; nc && !isvisible(nc); nc = nc->snext); for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
focus(nc); focus(nc);
} }
XUngrabButton(dpy, AnyButton, AnyModifier, c->win); XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
XDestroyWindow(dpy, c->twin); XDestroyWindow(dpy, c->twin);
free(c->tags); free(c->tags);
free(c); free(c);
XSync(dpy, False); XSync(dpy, False);
XSetErrorHandler(xerror); XSetErrorHandler(xerror);
XUngrabServer(dpy); XUngrabServer(dpy);
arrange(NULL); arrange();
} }

View File

@ -1,41 +1,41 @@
/* /* (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.
*/ */
#define TAGS \ #define TAGS \
const char *tags[] = { "dev", "work", "net", "fnord", NULL }; const char *tags[] = { "dev", "work", "net", "fnord", NULL };
#define DEFMODE dotile /* dofloat */ #define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>" #define FLOATSYMBOL "><>"
#define TILESYMBOL "[]=" #define TILESYMBOL "[]="
#define FONT "-*-terminus-medium-*-*-*-12-*-*-*-*-*-iso10646-*" #define FONT "-*-terminus-medium-r-*-*-14-*-*-*-*-*-*-*"
#define NORMBGCOLOR "#333333" #define NORMBGCOLOR "#333333"
#define NORMFGCOLOR "#dddddd" #define NORMFGCOLOR "#cccccc"
#define SELBGCOLOR "#333366" #define SELBGCOLOR "#336699"
#define SELFGCOLOR "#eeeeee" #define SELFGCOLOR "#dddddd"
#define STATUSBGCOLOR "#222222" #define STATUSBGCOLOR "#222222"
#define STATUSFGCOLOR "#9999cc" #define STATUSFGCOLOR "#99ccff"
#define MASTERW 60 /* percent */ #define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define SNAP 40 /* pixel */
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
/* modifier key function arguments */ \ /* modifier key function argument */ \
{ MODKEY|ShiftMask, XK_Return, spawn, \ { MODKEY|ShiftMask, XK_Return, spawn, \
{ .cmd = "exec uxterm -bg '#111111' -fg '#eeeeee' -cr '#eeeeee' +sb -fn '"FONT"'" } }, \ { .cmd = "exec uxterm -bg black -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=\"$(lsx `echo $PATH | sed 's/:/ /g'` | sort -u " \
"for file in \"$dir\"/*; do [ -x \"$file\" ] && echo \"${file##*/}\"; done; done " \ " | dmenu -fn '"FONT"' -nb '"NORMBGCOLOR"' -nf '"NORMFGCOLOR"' " \
"| sort -u | dmenu -font '"FONT"' -normbg '"NORMBGCOLOR"' -normfg '"NORMFGCOLOR"' " \ "-sb '"SELBGCOLOR"' -sf '"SELFGCOLOR"')\" && exec $exe" } }, \
"-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_g, resizecol, { .i = 20 } }, \ { MODKEY, XK_g, resizemaster, { .i = 15 } }, \
{ MODKEY, XK_s, resizecol, { .i = -20 } }, \ { MODKEY, XK_s, resizemaster, { .i = -15 } }, \
{ MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \
@ -46,7 +46,8 @@ static Key key[] = { \
{ MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \ { MODKEY|ControlMask|ShiftMask, XK_4, toggletag, { .i = 3 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \ { MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_0, viewall, { 0 } }, \ { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \
{ MODKEY, XK_0, view, { .i = -1 } }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \ { MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \ { MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \ { MODKEY, XK_3, view, { .i = 2 } }, \
@ -61,8 +62,8 @@ 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", True}, \ { "Firefox.*", "net", False }, \
{ "Gimp.*", NULL, True}, \ { "Gimp.*", NULL, True }, \
{ "MPlayer.*", NULL, True}, \ { "MPlayer.*", NULL, True }, \
{ "Acroread.*", NULL, True}, \ { "Acroread.*", NULL, True }, \
}; };

View File

@ -1,5 +1,4 @@
/* /* (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.
*/ */
@ -10,7 +9,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define FLOATSYMBOL "><>" #define FLOATSYMBOL "><>"
#define TILESYMBOL "[]=" #define TILESYMBOL "[]="
#define FONT "fixed" #define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*"
#define NORMBGCOLOR "#333366" #define NORMBGCOLOR "#333366"
#define NORMFGCOLOR "#cccccc" #define NORMFGCOLOR "#cccccc"
#define SELBGCOLOR "#666699" #define SELBGCOLOR "#666699"
@ -18,18 +17,20 @@ const char *tags[] = { "1", "2", "3", "4", "5", NULL };
#define STATUSBGCOLOR "#dddddd" #define STATUSBGCOLOR "#dddddd"
#define STATUSFGCOLOR "#222222" #define STATUSFGCOLOR "#222222"
#define MASTERW 60 /* percent */ #define MASTER 600 /* per thousand */
#define MODKEY Mod1Mask #define MODKEY Mod1Mask
#define SNAP 20 /* pixel */
#define KEYS \ #define KEYS \
static Key key[] = { \ static Key key[] = { \
/* modifier key function arguments */ \ /* modifier key function argument */ \
{ MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \ { MODKEY|ShiftMask, XK_Return, spawn, { .cmd = "exec xterm" } }, \
{ 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_g, resizecol, { .i = 20 } }, \ { MODKEY, XK_g, resizemaster, { .i = 15 } }, \
{ MODKEY, XK_s, resizecol, { .i = -20 } }, \ { MODKEY, XK_s, resizemaster, { .i = -15 } }, \
{ MODKEY|ShiftMask, XK_0, tag, { .i = -1 } }, \
{ MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \ { MODKEY|ShiftMask, XK_1, tag, { .i = 0 } }, \
{ MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \ { MODKEY|ShiftMask, XK_2, tag, { .i = 1 } }, \
{ MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \ { MODKEY|ShiftMask, XK_3, tag, { .i = 2 } }, \
@ -42,7 +43,8 @@ static Key key[] = { \
{ MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \ { MODKEY|ControlMask|ShiftMask, XK_5, toggletag, { .i = 4 } }, \
{ MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \ { MODKEY|ShiftMask, XK_c, killclient, { 0 } }, \
{ MODKEY, XK_space, togglemode, { 0 } }, \ { MODKEY, XK_space, togglemode, { 0 } }, \
{ MODKEY, XK_0, viewall, { 0 } }, \ { MODKEY|ShiftMask, XK_space, togglefloat, { 0 } }, \
{ MODKEY, XK_0, view, { .i = -1 } }, \
{ MODKEY, XK_1, view, { .i = 0 } }, \ { MODKEY, XK_1, view, { .i = 0 } }, \
{ MODKEY, XK_2, view, { .i = 1 } }, \ { MODKEY, XK_2, view, { .i = 1 } }, \
{ MODKEY, XK_3, view, { .i = 2 } }, \ { MODKEY, XK_3, view, { .i = 2 } }, \
@ -62,5 +64,5 @@ static Key key[] = { \
static Rule rule[] = { \ static Rule rule[] = { \
/* class:instance:title regex tags regex isfloat */ \ /* class:instance:title regex tags regex isfloat */ \
{ "Firefox.*", "2", False }, \ { "Firefox.*", "2", False }, \
{ "Gimp.*", NULL, True}, \ { "Gimp.*", NULL, True }, \
}; };

View File

@ -1,5 +1,5 @@
# dwm version # dwm version
VERSION = 1.7 VERSION = 2.8
# Customize below to fit your system # Customize below to fit your system
@ -20,6 +20,11 @@ LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" #CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = -g ${LIBS} #LDFLAGS = -g ${LIBS}
# Solaris
#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\"
#LDFLAGS = ${LIBS}
#CFLAGS += -xtarget=ultra
# compiler and linker # compiler and linker
CC = cc CC = cc
LD = ${CC} LD = ${CC}

85
draw.c
View File

@ -1,14 +1,22 @@
/* /* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details. * See LICENSE file for license details.
*/ */
#include "dwm.h" #include "dwm.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <X11/Xlocale.h>
/* static */ /* static */
static Bool
isoccupied(unsigned int t)
{
Client *c;
for(c = clients; c; c = c->next)
if(c->tags[t])
return True;
return False;
}
static unsigned int static unsigned int
textnw(const char *text, unsigned int len) { textnw(const char *text, unsigned int len) {
XRectangle r; XRectangle r;
@ -21,30 +29,27 @@ 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 filledsquare, Bool emptysquare) {
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;
XGCValues gcv; XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XPoint pt[5];
XSetForeground(dpy, dc.gc, col[ColBG]); XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
if(!text) if(!text)
return; return;
w = 0; w = 0;
olen = len = strlen(text); olen = len = strlen(text);
if(len >= sizeof(buf)) if(len >= sizeof buf)
len = sizeof(buf) - 1; len = sizeof buf - 1;
memcpy(buf, text, len); memcpy(buf, text, len);
buf[len] = 0; buf[len] = 0;
h = dc.font.ascent + dc.font.descent; h = dc.font.ascent + dc.font.descent;
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
x = dc.x + (h / 2); x = dc.x + (h / 2);
/* shorten text if necessary */ /* shorten text if necessary */
while(len && (w = textnw(buf, len)) > dc.w - h) while(len && (w = textnw(buf, len)) > dc.w - h)
buf[--len] = 0; buf[--len] = 0;
@ -56,7 +61,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
if(len > 3) if(len > 3)
buf[len - 3] = '.'; buf[len - 3] = '.';
} }
if(w > dc.w) if(w > dc.w)
return; /* too long */ return; /* too long */
gcv.foreground = col[ColFG]; gcv.foreground = col[ColFG];
@ -69,12 +73,26 @@ drawtext(const char *text, unsigned long col[ColLast], Bool highlight) {
XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv); XChangeGC(dpy, dc.gc, GCForeground | GCFont, &gcv);
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
} }
if(highlight) { x = (h + 2) / 4;
r.x = dc.x + 2; if(filledsquare) {
r.y = dc.y + 2; r.x = dc.x + 1;
r.width = r.height = 3; r.y = dc.y + 1;
r.width = r.height = x + 1;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
} }
else if(emptysquare) {
pt[0].x = dc.x + 1;
pt[0].y = dc.y + 1;
pt[1].x = x;
pt[1].y = 0;
pt[2].x = 0;
pt[2].y = x;
pt[3].x = -x;
pt[3].y = 0;
pt[4].x = 0;
pt[4].y = -x;
XDrawLines(dpy, dc.drawable, dc.gc, pt, 5, CoordModePrevious);
}
} }
/* extern */ /* extern */
@ -93,34 +111,27 @@ drawstatus(void) {
int i, x; int i, x;
dc.x = dc.y = 0; dc.x = dc.y = 0;
for(i = 0; i < ntags; i++) { for(i = 0; i < ntags; i++) {
dc.w = textw(tags[i]); dc.w = textw(tags[i]);
if(seltag[i]) if(seltag[i])
drawtext(tags[i], dc.sel, sel && sel->tags[i]); drawtext(tags[i], dc.sel, sel && sel->tags[i], isoccupied(i));
else else
drawtext(tags[i], dc.norm, sel && sel->tags[i]); drawtext(tags[i], dc.norm, sel && sel->tags[i], isoccupied(i));
dc.x += dc.w; dc.x += dc.w;
} }
dc.w = bmw; dc.w = bmw;
drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.status, False); drawtext(arrange == dofloat ? FLOATSYMBOL : TILESYMBOL, dc.status, False, False);
x = dc.x + dc.w; x = dc.x + dc.w;
dc.w = textw(stext); dc.w = textw(stext);
dc.x = bx + bw - dc.w; dc.x = bw - dc.w;
if(dc.x < x) { if(dc.x < x) {
dc.x = x; dc.x = x;
dc.w = bw - x; dc.w = bw - x;
} }
drawtext(stext, dc.status, False); drawtext(stext, dc.status, False, False);
if((dc.w = dc.x - x) > bh) { if((dc.w = dc.x - x) > bh) {
dc.x = x; dc.x = x;
if(sel) drawtext(sel ? sel->name : NULL, sel ? dc.sel : dc.norm, False, False);
drawtext(sel->name, dc.sel, False);
else
drawtext(NULL, dc.norm, False);
} }
XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0); XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
XSync(dpy, False); XSync(dpy, False);
@ -134,12 +145,11 @@ drawtitle(Client *c) {
XSetWindowBorder(dpy, c->win, dc.sel[ColBG]); XSetWindowBorder(dpy, c->win, dc.sel[ColBG]);
return; return;
} }
XSetWindowBorder(dpy, c->win, dc.norm[ColBG]); XSetWindowBorder(dpy, c->win, dc.norm[ColBG]);
XMapWindow(dpy, c->twin); XMapWindow(dpy, c->twin);
dc.x = dc.y = 0; dc.x = dc.y = 0;
dc.w = c->tw; dc.w = c->tw;
drawtext(c->name, dc.norm, False); drawtext(c->name, dc.norm, False,False);
XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0); XCopyArea(dpy, dc.drawable, c->twin, dc.gc, 0, 0, c->tw, c->th, 0, 0);
XSync(dpy, False); XSync(dpy, False);
} }
@ -156,11 +166,10 @@ getcolor(const char *colstr) {
void void
setfont(const char *fontstr) { setfont(const char *fontstr) {
char **missing, *def; char *def, **missing;
int i, n; int i, n;
missing = NULL; missing = NULL;
setlocale(LC_ALL, "");
if(dc.font.set) if(dc.font.set)
XFreeFontSet(dpy, dc.font.set); XFreeFontSet(dpy, dc.font.set);
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
@ -168,16 +177,11 @@ setfont(const char *fontstr) {
while(n--) while(n--)
fprintf(stderr, "missing fontset: %s\n", missing[n]); fprintf(stderr, "missing fontset: %s\n", missing[n]);
XFreeStringList(missing); XFreeStringList(missing);
if(dc.font.set) {
XFreeFontSet(dpy, dc.font.set);
dc.font.set = NULL;
}
} }
if(dc.font.set) { if(dc.font.set) {
XFontSetExtents *font_extents; XFontSetExtents *font_extents;
XFontStruct **xfonts; XFontStruct **xfonts;
char **font_names; char **font_names;
dc.font.ascent = dc.font.descent = 0; dc.font.ascent = dc.font.descent = 0;
font_extents = XExtentsOfFontSet(dc.font.set); font_extents = XExtentsOfFontSet(dc.font.set);
n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
@ -193,11 +197,8 @@ setfont(const char *fontstr) {
if(dc.font.xfont) if(dc.font.xfont)
XFreeFont(dpy, dc.font.xfont); XFreeFont(dpy, dc.font.xfont);
dc.font.xfont = NULL; dc.font.xfont = NULL;
dc.font.xfont = XLoadQueryFont(dpy, fontstr); if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)))
if (!dc.font.xfont) eprint("error, cannot load font: '%s'\n", fontstr);
dc.font.xfont = XLoadQueryFont(dpy, "fixed");
if (!dc.font.xfont)
eprint("error, cannot init 'fixed' font\n");
dc.font.ascent = dc.font.xfont->ascent; dc.font.ascent = dc.font.xfont->ascent;
dc.font.descent = dc.font.xfont->descent; dc.font.descent = dc.font.xfont->descent;
} }

44
dwm.1
View File

@ -9,9 +9,9 @@ dwm is a dynamic window manager for X. It manages windows in tiling and
floating modes. Either mode can be applied dynamically, optimizing the floating modes. Either mode can be applied dynamically, optimizing the
environment for the application in use and the task performed. environment for 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 area. The master
column contains the window which currently needs most attention, whereas the area contains the window which currently needs most attention, whereas the
stacking column contains all other windows. In floating mode windows can be stacking area contains all other windows. In floating mode windows can be
resized and moved freely. Dialog windows are always managed floating, resized and moved freely. Dialog windows are always managed floating,
regardless of the mode selected. regardless of the mode selected.
.P .P
@ -20,8 +20,10 @@ 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
selected tags are highlighted with a different color, the tags of the focused selected tags are indicated with a different color. The tags of the focused
window are highlighted with a small point. window are indicated with a filled square in the top left corner. The tags
which are applied to one or more windows are indicated with an empty square in
the top left corner.
.P .P
dwm draws a 1-pixel border around windows to indicate the focus state. dwm 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.
@ -37,7 +39,7 @@ is read and displayed in the status text area.
.TP .TP
.B Button1 .B Button1
click on a tag label to display all windows with that tag, click on the mode click on a tag label to display all windows with that tag, click on the mode
label toggles between tiled and floating mode. label toggles between tiling and floating mode.
.TP .TP
.B Button3 .B Button3
click on a tag label adds/removes all windows with that tag to/from the view. click on a tag label adds/removes all windows with that tag to/from the view.
@ -60,19 +62,22 @@ Focus next window.
Focus previous window. Focus previous window.
.TP .TP
.B Mod1-Return .B Mod1-Return
Zooms/cycles current window to/from master column (tiling mode), toggles maximization current window (floating mode). Zooms/cycles current window to/from master area (tiling mode), toggles maximization current window (floating mode).
.TP .TP
.B Mod1-g .B Mod1-g
Grow current column (tiling mode only). Grow master area (tiling mode only).
.TP .TP
.B Mod1-s .B Mod1-s
Shrink current column (tiling mode only). Shrink master area (tiling mode only).
.TP .TP
.B Mod1-Shift-[1..n] .B Mod1-Shift-[1..n]
Apply Apply
.RB nth .RB nth
tag to current window. tag to current window.
.TP .TP
.B Mod1-Shift-0
Apply all tags to current window.
.TP
.B Mod1-Control-Shift-[1..n] .B Mod1-Control-Shift-[1..n]
Add/remove Add/remove
.B nth .B nth
@ -82,7 +87,10 @@ tag to/from current window.
Close focused window. Close focused window.
.TP .TP
.B Mod1-space .B Mod1-space
Toggle between tiled and floating mode (affects all windows). Toggle between tiling and floating mode (affects all windows).
.TP
.B Mod1-Shift-space
Toggle focused window between floating and non-floating state (tiling mode only).
.TP .TP
.B Mod1-[1..n] .B Mod1-[1..n]
View all windows with View all windows with
@ -105,7 +113,7 @@ Quit dwm.
Move current window while dragging (floating mode only). Move current window while dragging (floating mode only).
.TP .TP
.B Mod1-Button2 .B Mod1-Button2
Zoom current window to the master column (tiling mode only). Zoom current window to the master area (tiling mode only).
.TP .TP
.B Mod1-Button3 .B Mod1-Button3
Resize current window while dragging (floating mode only). Resize current window while dragging (floating mode only).
@ -114,9 +122,17 @@ dwm 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
.BR "broken pipe" .BR "EOF"
when dwm has been started by when dwm has been started by an X session manager like
.BR xdm (1), .BR xdm (1),
because it closes standard output before executing dwm. because those close standard output before executing dwm.
.P
Java applications which use the XToolkit/XAWT backend may draw grey windows
only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
JDK 1.6 versions, because it assumes a reparenting window manager. As a workaround
you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
can set the following environment variable (to use the older Motif
backend instead):
.BR AWT_TOOLKIT=MToolkit .
.SH SEE ALSO .SH SEE ALSO
.BR dmenu (1) .BR dmenu (1)

32
dwm.h
View File

@ -1,5 +1,4 @@
/* /* (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 * dynamic window manager is designed like any other X client as well. It is
@ -37,7 +36,8 @@
/* mask shorthands, used in event.c and client.c */ /* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask) /* other stuff used in different places */
#define BORDERPX 1
#define PROTODELWIN 1 #define PROTODELWIN 1
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
@ -80,10 +80,9 @@ struct Client {
int rx, ry, rw, rh; /* revert geometry */ 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;
long flags; long flags;
unsigned int border, weight; unsigned int border;
Bool isfloat, ismax; Bool isfloat, isfixed, ismax;
Bool *tags; Bool *tags;
Client *next; Client *next;
Client *prev; Client *prev;
@ -95,10 +94,11 @@ struct Client {
extern const char *tags[]; /* all tags */ extern const char *tags[]; /* all tags */
extern char stext[1024]; /* status text */ extern char stext[1024]; /* status text */
extern int bx, by, bw, bh, bmw; /* bar geometry, bar mode label width */ extern int bx, by, bw, bh, bmw; /* bar geometry, bar mode label width */
extern int mw, screen, sx, sy, sw, sh; /* screen geometry, master width */ extern int screen, sx, sy, sw, sh; /* screen geometry */
extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */ extern int wax, way, wah, waw; /* windowarea geometry */
extern unsigned int master, ntags, numlockmask; /* master percent, 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)(void); /* arrange function, indicates mode */
extern Atom wmatom[WMLast], netatom[NetLast]; extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel, *seltag; /* seltag is array of Bool */ extern Bool running, issel, *seltag; /* seltag is array of Bool */
extern Client *clients, *sel, *stack; /* global client list and stack */ extern Client *clients, *sel, *stack; /* global client list and stack */
@ -113,11 +113,11 @@ 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 */
extern void gravitate(Client *c, Bool invert); /* gravitate c */
extern void killclient(Arg *arg); /* kill c nicely */ extern void killclient(Arg *arg); /* kill c nicely */
extern void manage(Window w, XWindowAttributes *wa); /* manage new client */ 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 resizetitle(Client *c); /* resizes c->twin correctly */
extern void updatesizehints(Client *c); /* update the size hint variables of c */
extern void updatetitle(Client *c); /* update the name of c */ extern void updatetitle(Client *c); /* update the name of c */
extern void unmanage(Client *c); /* destroy c */ extern void unmanage(Client *c); /* destroy c */
@ -155,15 +155,15 @@ extern void spawn(Arg *arg); /* forks a new subprocess with to arg's cmd */
/* view.c */ /* view.c */
extern void detach(Client *c); /* detaches c from global client list */ extern void detach(Client *c); /* detaches c from global client list */
extern void dofloat(Arg *arg); /* arranges all windows floating, arg is ignored */ extern void dofloat(void); /* arranges all windows floating */
extern void dotile(Arg *arg); /* arranges all windows, arg is ignored */ extern void dotile(void); /* arranges all windows tiled */
extern void focusnext(Arg *arg); /* focuses next visible client, arg is ignored */ 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 resizemaster(Arg *arg); /* resizes the master percent with arg's index value */
extern void restack(void); /* restores z layers of all clients */ extern void restack(void); /* restores z layers of all clients */
extern void togglefloat(Arg *arg); /* toggles focusesd client between floating/non-floating state */
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 */
extern void viewall(Arg *arg); /* views all tags, arg is ignored */ extern void zoom(Arg *arg); /* zooms the focused client to master area, arg is ignored */
extern void zoom(Arg *arg); /* zooms the focused client to master column, arg is ignored */

47
event.c
View File

@ -1,5 +1,4 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
@ -19,6 +18,7 @@ typedef struct {
KEYS KEYS
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask))
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
static void static void
movemouse(Client *c) { movemouse(Client *c) {
@ -48,6 +48,14 @@ movemouse(Client *c) {
XSync(dpy, False); XSync(dpy, False);
c->x = ocx + (ev.xmotion.x - x1); c->x = ocx + (ev.xmotion.x - x1);
c->y = ocy + (ev.xmotion.y - y1); c->y = ocy + (ev.xmotion.y - y1);
if(abs(wax + c->x) < SNAP)
c->x = wax;
else if(abs((wax + waw) - (c->x + c->w)) < SNAP)
c->x = wax + waw - c->w - 2 * BORDERPX;
if(abs(way - c->y) < SNAP)
c->y = way;
else if(abs((way + wah) - (c->y + c->h)) < SNAP)
c->y = way + wah - c->h - 2 * BORDERPX;
resize(c, False, TopLeft); resize(c, False, TopLeft);
break; break;
} }
@ -64,7 +72,7 @@ resizemouse(Client *c) {
ocx = c->x; ocx = c->x;
ocy = c->y; ocy = c->y;
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; 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);
@ -123,10 +131,8 @@ buttonpress(XEvent *e) {
return; return;
} }
} }
if(ev->x < x + bmw) { if((ev->x < x + bmw) && (ev->button == Button1))
if(ev->button == Button1) togglemode(NULL);
togglemode(NULL);
}
} }
else if((c = getclient(ev->window))) { else if((c = getclient(ev->window))) {
focus(c); focus(c);
@ -138,7 +144,8 @@ buttonpress(XEvent *e) {
} }
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) &&
!c->isfixed) {
restack(); restack();
resizemouse(c); resizemouse(c);
} }
@ -150,12 +157,10 @@ 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))) {
c->ismax = False; c->ismax = False;
gravitate(c, True);
if(ev->value_mask & CWX) if(ev->value_mask & CWX)
c->x = ev->x; c->x = ev->x;
if(ev->value_mask & CWY) if(ev->value_mask & CWY)
@ -166,7 +171,6 @@ configurerequest(XEvent *e) {
c->h = ev->height; c->h = ev->height;
if(ev->value_mask & CWBorderWidth) if(ev->value_mask & CWBorderWidth)
c->border = ev->border_width; c->border = ev->border_width;
gravitate(c, False);
wc.x = c->x; wc.x = c->x;
wc.y = c->y; wc.y = c->y;
wc.width = c->w; wc.width = c->w;
@ -177,10 +181,13 @@ configurerequest(XEvent *e) {
else else
configure(c); configure(c);
XSync(dpy, False); XSync(dpy, False);
if(c->isfloat) if(c->isfloat) {
resize(c, False, TopLeft); resize(c, False, TopLeft);
if(!isvisible(c))
ban(c);
}
else else
arrange(NULL); arrange();
} }
else { else {
wc.x = ev->x; wc.x = ev->x;
@ -211,7 +218,6 @@ enternotify(XEvent *e) {
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))) && isvisible(c)) 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) {
@ -236,7 +242,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;
XKeyEvent *ev = &e->xkey; XKeyEvent *ev = &e->xkey;
@ -248,7 +254,6 @@ keypress(XEvent *e) {
{ {
if(key[i].func) if(key[i].func)
key[i].func(&key[i].arg); key[i].func(&key[i].arg);
return;
} }
} }
} }
@ -279,13 +284,11 @@ maprequest(XEvent *e) {
if(!XGetWindowAttributes(dpy, ev->window, &wa)) if(!XGetWindowAttributes(dpy, ev->window, &wa))
return; return;
if(wa.override_redirect) { if(wa.override_redirect) {
XSelectInput(dpy, ev->window, XSelectInput(dpy, ev->window,
(StructureNotifyMask | PropertyChangeMask)); (StructureNotifyMask | PropertyChangeMask));
return; return;
} }
if(!getclient(ev->window)) if(!getclient(ev->window))
manage(ev->window, &wa); manage(ev->window, &wa);
} }
@ -298,7 +301,6 @@ propertynotify(XEvent *e) {
if(ev->state == PropertyDelete) if(ev->state == PropertyDelete)
return; /* ignore */ return; /* ignore */
if((c = getclient(ev->window))) { if((c = getclient(ev->window))) {
if(ev->atom == wmatom[WMProtocols]) { if(ev->atom == wmatom[WMProtocols]) {
c->proto = getproto(c->win); c->proto = getproto(c->win);
@ -309,14 +311,15 @@ propertynotify(XEvent *e) {
case XA_WM_TRANSIENT_FOR: case XA_WM_TRANSIENT_FOR:
XGetTransientForHint(dpy, c->win, &trans); XGetTransientForHint(dpy, c->win, &trans);
if(!c->isfloat && (c->isfloat = (trans != 0))) if(!c->isfloat && (c->isfloat = (trans != 0)))
arrange(NULL); arrange();
break; break;
case XA_WM_NORMAL_HINTS: case XA_WM_NORMAL_HINTS:
updatesize(c); updatesizehints(c);
break; break;
} }
if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
updatetitle(c); updatetitle(c);
resizetitle(c);
drawtitle(c); drawtitle(c);
} }
} }
@ -349,7 +352,7 @@ void (*handler[LASTEvent]) (XEvent *) = {
void void
grabkeys(void) { 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;

100
main.c
View File

@ -1,10 +1,10 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
#include <errno.h> #include <errno.h>
#include <locale.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -19,8 +19,8 @@
char stext[1024]; char stext[1024];
Bool *seltag; Bool *seltag;
int bx, by, bw, bh, bmw, mw, screen, sx, sy, sw, sh; int bx, by, bw, bh, bmw, masterd, screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int ntags, numlockmask; unsigned int master, ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast]; Atom wmatom[WMLast], netatom[NetLast];
Bool running = True; Bool running = True;
Bool issel = True; Bool issel = True;
@ -40,9 +40,9 @@ static Bool otherwm, readin;
static void static void
cleanup(void) { cleanup(void) {
close(STDIN_FILENO); close(STDIN_FILENO);
while(sel) { while(clients) {
resize(sel, True, TopLeft); resize(clients, True, TopLeft);
unmanage(sel); unmanage(clients);
} }
if(dc.font.set) if(dc.font.set)
XFreeFontSet(dpy, dc.font.set); XFreeFontSet(dpy, dc.font.set);
@ -52,6 +52,9 @@ cleanup(void) {
XFreePixmap(dpy, dc.drawable); XFreePixmap(dpy, dc.drawable);
XFreeGC(dpy, dc.gc); XFreeGC(dpy, dc.gc);
XDestroyWindow(dpy, barwin); XDestroyWindow(dpy, barwin);
XFreeCursor(dpy, cursor[CurNormal]);
XFreeCursor(dpy, cursor[CurResize]);
XFreeCursor(dpy, cursor[CurMove]);
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
XSync(dpy, False); XSync(dpy, False);
free(seltag); free(seltag);
@ -93,12 +96,11 @@ setup(void) {
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast); PropModeReplace, (unsigned char *) netatom, NetLast);
/* init cursors */ /* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
/* init modifier map */
modmap = XGetModifierMapping(dpy); modmap = XGetModifierMapping(dpy);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
for (j = 0; j < modmap->max_keypermod; j++) { for (j = 0; j < modmap->max_keypermod; j++) {
@ -106,20 +108,17 @@ setup(void) {
numlockmask = (1 << i); numlockmask = (1 << i);
} }
} }
XFree(modmap); XFreeModifiermap(modmap);
/* select for events */
wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
| EnterWindowMask | LeaveWindowMask; | EnterWindowMask | LeaveWindowMask;
wa.cursor = cursor[CurNormal]; wa.cursor = cursor[CurNormal];
XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
grabkeys(); grabkeys();
initrregs(); initrregs();
for(ntags = 0; tags[ntags]; ntags++); for(ntags = 0; tags[ntags]; ntags++);
seltag = emallocz(sizeof(Bool) * ntags); seltag = emallocz(sizeof(Bool) * ntags);
seltag[0] = True; seltag[0] = True;
/* style */ /* style */
dc.norm[ColBG] = getcolor(NORMBGCOLOR); dc.norm[ColBG] = getcolor(NORMBGCOLOR);
dc.norm[ColFG] = getcolor(NORMFGCOLOR); dc.norm[ColFG] = getcolor(NORMFGCOLOR);
@ -128,14 +127,15 @@ setup(void) {
dc.status[ColBG] = getcolor(STATUSBGCOLOR); dc.status[ColBG] = getcolor(STATUSBGCOLOR);
dc.status[ColFG] = getcolor(STATUSFGCOLOR); dc.status[ColFG] = getcolor(STATUSFGCOLOR);
setfont(FONT); setfont(FONT);
/* geometry */
bmw = textw(FLOATSYMBOL) > textw(TILESYMBOL) ? textw(FLOATSYMBOL) : textw(TILESYMBOL); bmw = textw(TILESYMBOL) > textw(FLOATSYMBOL) ? textw(TILESYMBOL) : textw(FLOATSYMBOL);
sx = sy = 0; sx = sy = 0;
sw = DisplayWidth(dpy, screen); sw = DisplayWidth(dpy, screen);
sh = DisplayHeight(dpy, screen); sh = DisplayHeight(dpy, screen);
mw = (sw * MASTERW) / 100; master = MASTER;
/* bar */
bx = by = 0; bx = sx;
by = sy;
bw = sw; bw = sw;
dc.h = bh = dc.font.height + 2; dc.h = bh = dc.font.height + 2;
wa.override_redirect = 1; wa.override_redirect = 1;
@ -146,13 +146,18 @@ setup(void) {
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
XDefineCursor(dpy, barwin, cursor[CurNormal]); XDefineCursor(dpy, barwin, cursor[CurNormal]);
XMapRaised(dpy, barwin); XMapRaised(dpy, barwin);
strcpy(stext, "dwm-"VERSION);
/* windowarea */
wax = sx;
way = sy + bh;
wah = sh - bh;
waw = sw;
/* pixmap for everything */
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
dc.gc = XCreateGC(dpy, root, 0, 0); dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
/* multihead support */
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
strcpy(stext, "dwm-"VERSION);
} }
/* /*
@ -204,8 +209,7 @@ 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 may call exit. * default error handler, which may call exit.
*/ */
@ -227,6 +231,7 @@ xerror(Display *dpy, XErrorEvent *ee) {
int int
main(int argc, char *argv[]) { main(int argc, char *argv[]) {
char *p;
int r, xfd; int r, xfd;
fd_set rd; fd_set rd;
@ -236,21 +241,18 @@ main(int argc, char *argv[]) {
} }
else if(argc != 1) else if(argc != 1)
eprint("usage: dwm [-v]\n"); eprint("usage: dwm [-v]\n");
setlocale(LC_CTYPE, "");
dpy = XOpenDisplay(0); dpy = XOpenDisplay(0);
if(!dpy) if(!dpy)
eprint("dwm: cannot open display\n"); eprint("dwm: cannot open display\n");
xfd = ConnectionNumber(dpy); xfd = ConnectionNumber(dpy);
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
otherwm = False; otherwm = False;
XSetErrorHandler(xerrorstart); XSetErrorHandler(xerrorstart);
/* this causes an error if some other window manager is running */ /* this causes an error if some other window manager is running */
XSelectInput(dpy, root, SubstructureRedirectMask); XSelectInput(dpy, root, SubstructureRedirectMask);
XSync(dpy, False); XSync(dpy, False);
if(otherwm) if(otherwm)
eprint("dwm: another window manager is already running\n"); eprint("dwm: another window manager is already running\n");
@ -258,7 +260,6 @@ main(int argc, char *argv[]) {
XSetErrorHandler(NULL); XSetErrorHandler(NULL);
xerrorxlib = XSetErrorHandler(xerror); xerrorxlib = XSetErrorHandler(xerror);
XSync(dpy, False); XSync(dpy, False);
setup(); setup();
drawstatus(); drawstatus();
scan(); scan();
@ -272,25 +273,34 @@ main(int argc, char *argv[]) {
if(readin) if(readin)
FD_SET(STDIN_FILENO, &rd); FD_SET(STDIN_FILENO, &rd);
FD_SET(xfd, &rd); FD_SET(xfd, &rd);
r = select(xfd + 1, &rd, NULL, NULL, NULL); if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
if((r == -1) && (errno == EINTR)) if(errno == EINTR)
continue; continue;
if(r > 0) {
if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
readin = NULL != fgets(stext, sizeof(stext), stdin);
if(readin)
stext[strlen(stext) - 1] = 0;
else
strcpy(stext, "broken pipe");
drawstatus();
}
}
else if(r < 0)
eprint("select failed\n"); eprint("select failed\n");
procevent(); }
if(FD_ISSET(STDIN_FILENO, &rd)) {
switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
case -1:
strncpy(stext, strerror(errno), sizeof stext - 1);
stext[sizeof stext - 1] = '\0';
readin = False;
break;
case 0:
strncpy(stext, "EOF", 4);
readin = False;
break;
default:
for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
for(p = stext + strlen(stext) - 1; p >= stext && *p != '\n'; --p);
if(p > stext)
strncpy(stext, p + 1, sizeof stext);
}
drawstatus();
}
if(FD_ISSET(xfd, &rd))
procevent();
} }
cleanup(); cleanup();
XCloseDisplay(dpy); XCloseDisplay(dpy);
return 0; return 0;
} }

28
tag.c
View File

@ -1,5 +1,4 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
@ -51,20 +50,19 @@ initrregs(void) {
if(rreg) if(rreg)
return; return;
len = sizeof(rule) / sizeof(rule[0]); len = sizeof rule / sizeof rule[0];
rreg = emallocz(len * sizeof(RReg)); rreg = emallocz(len * sizeof(RReg));
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
if(rule[i].clpattern) { if(rule[i].clpattern) {
reg = emallocz(sizeof(regex_t)); reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].clpattern, 0)) if(regcomp(reg, rule[i].clpattern, REG_EXTENDED))
free(reg); free(reg);
else else
rreg[i].clregex = reg; rreg[i].clregex = reg;
} }
if(rule[i].tpattern) { if(rule[i].tpattern) {
reg = emallocz(sizeof(regex_t)); reg = emallocz(sizeof(regex_t));
if(regcomp(reg, rule[i].tpattern, 0)) if(regcomp(reg, rule[i].tpattern, REG_EXTENDED))
free(reg); free(reg);
else else
rreg[i].tregex = reg; rreg[i].tregex = reg;
@ -85,10 +83,10 @@ settags(Client *c, Client *trans) {
c->tags[i] = trans->tags[i]; c->tags[i] = trans->tags[i];
} }
else if(XGetClassHint(dpy, c->win, &ch)) { else if(XGetClassHint(dpy, c->win, &ch)) {
snprintf(prop, sizeof(prop), "%s:%s:%s", snprintf(prop, sizeof prop, "%s:%s:%s",
ch.res_class ? ch.res_class : "", ch.res_class ? ch.res_class : "",
ch.res_name ? ch.res_name : "", c->name); ch.res_name ? ch.res_name : "", c->name);
for(i = 0; !matched && i < len; i++) for(i = 0; i < len; i++)
if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) { if(rreg[i].clregex && !regexec(rreg[i].clregex, prop, 1, &tmp, 0)) {
c->isfloat = rule[i].isfloat; c->isfloat = rule[i].isfloat;
for(j = 0; rreg[i].tregex && j < ntags; j++) { for(j = 0; rreg[i].tregex && j < ntags; j++) {
@ -106,7 +104,6 @@ settags(Client *c, Client *trans) {
if(!matched) if(!matched)
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
c->tags[i] = seltag[i]; c->tags[i] = seltag[i];
for(c->weight = 0; c->weight < ntags && !c->tags[c->weight]; c->weight++);
} }
void void
@ -115,12 +112,11 @@ tag(Arg *arg) {
if(!sel) if(!sel)
return; return;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
sel->tags[i] = False; sel->tags[i] = (arg->i == -1) ? True : False;
sel->tags[arg->i] = True; if(arg->i >= 0 && arg->i < ntags)
sel->weight = arg->i; sel->tags[arg->i] = True;
arrange(NULL); arrange();
} }
void void
@ -129,11 +125,9 @@ toggletag(Arg *arg) {
if(!sel) if(!sel)
return; return;
sel->tags[arg->i] = !sel->tags[arg->i]; sel->tags[arg->i] = !sel->tags[arg->i];
for(i = 0; i < ntags && !sel->tags[i]; i++); for(i = 0; i < ntags && !sel->tags[i]; i++);
if(i == ntags) if(i == ntags)
sel->tags[arg->i] = True; sel->tags[arg->i] = True;
sel->weight = (i == ntags) ? arg->i : i; arrange();
arrange(NULL);
} }

5
util.c
View File

@ -1,5 +1,4 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
@ -33,6 +32,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);
return res; return res;
@ -44,7 +44,6 @@ spawn(Arg *arg) {
if(!shell && !(shell = getenv("SHELL"))) if(!shell && !(shell = getenv("SHELL")))
shell = "/bin/sh"; shell = "/bin/sh";
if(!arg->cmd) if(!arg->cmd)
return; return;
/* The double-fork construct avoids zombie processes and keeps the code /* The double-fork construct avoids zombie processes and keeps the code

180
view.c
View File

@ -1,23 +1,10 @@
/* /* (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.
*/ */
#include "dwm.h" #include "dwm.h"
/* static */ /* static */
static Client *
minclient(void) {
Client *c, *min;
if((clients && clients->isfloat) || arrange == dofloat)
return clients; /* don't touch floating order */
for(min = c = clients; c; c = c->next)
if(c->weight < min->weight)
min = c;
return min;
}
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));
@ -25,32 +12,17 @@ nexttiled(Client *c) {
} }
static void static void
reorder(void) { togglemax(Client *c) {
Client *c, *newclients, *tail;
newclients = tail = NULL;
while((c = minclient())) {
detach(c);
if(tail) {
c->prev = tail;
tail->next = c;
tail = c;
}
else
tail = newclients = c;
}
clients = newclients;
}
static void
togglemax(Client *c)
{
XEvent ev; XEvent ev;
if(c->isfixed)
return;
if((c->ismax = !c->ismax)) { if((c->ismax = !c->ismax)) {
c->rx = c->x; c->x = sx; c->rx = c->x; c->x = wax;
c->ry = c->y; c->y = bh; c->ry = c->y; c->y = way;
c->rw = c->w; c->w = sw; c->rw = c->w; c->w = waw - 2 * BORDERPX;
c->rh = c->h; c->h = sh - bh - 2; c->rh = c->h; c->h = wah - 2 * BORDERPX;
} }
else { else {
c->x = c->rx; c->x = c->rx;
@ -64,7 +36,7 @@ togglemax(Client *c)
/* extern */ /* extern */
void (*arrange)(Arg *) = DEFMODE; void (*arrange)(void) = DEFMODE;
void void
detach(Client *c) { detach(Client *c) {
@ -78,7 +50,7 @@ detach(Client *c) {
} }
void void
dofloat(Arg *arg) { dofloat(void) {
Client *c; Client *c;
for(c = clients; c; c = c->next) { for(c = clients; c; c = c->next) {
@ -96,59 +68,48 @@ dofloat(Arg *arg) {
} }
void void
dotile(Arg *arg) { dotile(void) {
int h, i, n, w; unsigned int i, n, mpw, th;
Client *c; Client *c;
w = sw - mw;
for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
n++; n++;
mpw = (waw * master) / 1000;
if(n > 1) for(i = 0, c = clients; c; c = c->next)
h = (sh - bh) / (n - 1);
else
h = sh - bh;
for(i = 0, c = clients; c; c = c->next) {
if(isvisible(c)) { if(isvisible(c)) {
if(c->isfloat) { if(c->isfloat) {
resize(c, True, TopLeft); resize(c, True, TopLeft);
continue; continue;
} }
c->ismax = False; c->ismax = False;
if(n == 1) { c->x = wax;
c->x = sx; c->y = way;
c->y = sy + bh; if(n == 1) { /* only 1 window */
c->w = sw - 2; c->w = waw - 2 * BORDERPX;
c->h = sh - 2 - bh; c->h = wah - 2 * BORDERPX;
} }
else if(i == 0) { else if(i == 0) { /* master window */
c->x = sx; c->w = mpw - 2 * BORDERPX;
c->y = sy + bh; c->h = wah - 2 * BORDERPX;
c->w = mw - 2; th = wah / (n - 1);
c->h = sh - 2 - bh;
} }
else if(h > bh) { else { /* tile window */
c->x = sx + mw; c->x += mpw;
c->y = sy + (i - 1) * h + bh; c->w = (waw - mpw) - 2 * BORDERPX;
c->w = w - 2; if(th > bh) {
if(i + 1 == n) c->y += (i - 1) * th;
c->h = sh - c->y - 2; c->h = th - 2 * BORDERPX;
else }
c->h = h - 2; else /* fallback if th < bh */
} c->h = wah - 2 * BORDERPX;
else { /* fallback if h < bh */
c->x = sx + mw;
c->y = sy + bh;
c->w = w - 2;
c->h = sh - 2 - bh;
} }
resize(c, False, TopLeft); resize(c, False, TopLeft);
i++; i++;
} }
else else
ban(c); ban(c);
}
if(!sel || !isvisible(sel)) { if(!sel || !isvisible(sel)) {
for(c = stack; c && !isvisible(c); c = c->snext); for(c = stack; c && !isvisible(c); c = c->snext);
focus(c); focus(c);
@ -162,7 +123,6 @@ focusnext(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(!(c = getnext(sel->next))) if(!(c = getnext(sel->next)))
c = getnext(clients); c = getnext(clients);
if(c) { if(c) {
@ -177,7 +137,6 @@ focusprev(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(!(c = getprev(sel->prev))) { if(!(c = getprev(sel->prev))) {
for(c = clients; c && c->next; c = c->next); for(c = clients; c && c->next; c = c->next);
c = getprev(c); c = getprev(c);
@ -199,27 +158,15 @@ isvisible(Client *c) {
} }
void void
resizecol(Arg *arg) { resizemaster(Arg *arg) {
unsigned int n; if(arg->i == 0)
Client *c; master = MASTER;
for(n = 0, c = clients; c; c = c->next)
if(isvisible(c) && !c->isfloat)
n++;
if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
return;
if(sel == getnext(clients)) {
if(mw + arg->i > sw - 100 || mw + arg->i < 100)
return;
mw += arg->i;
}
else { else {
if(mw - arg->i > sw - 100 || mw - arg->i < 100) if(master + arg->i > 950 || master + arg->i < 50)
return; return;
mw -= arg->i; master += arg->i;
} }
arrange(NULL); arrange();
} }
void void
@ -235,21 +182,36 @@ restack(void) {
XRaiseWindow(dpy, sel->win); XRaiseWindow(dpy, sel->win);
XRaiseWindow(dpy, sel->twin); XRaiseWindow(dpy, sel->twin);
} }
if(arrange != dofloat) if(arrange != dofloat) {
if(!sel->isfloat) {
XLowerWindow(dpy, sel->twin);
XLowerWindow(dpy, sel->win);
}
for(c = nexttiled(clients); c; c = nexttiled(c->next)) { for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
if(c == sel)
continue;
XLowerWindow(dpy, c->twin); XLowerWindow(dpy, c->twin);
XLowerWindow(dpy, c->win); XLowerWindow(dpy, c->win);
} }
}
drawall(); drawall();
XSync(dpy, False); XSync(dpy, False);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
} }
void
togglefloat(Arg *arg) {
if (!sel || arrange == dofloat)
return;
sel->isfloat = !sel->isfloat;
arrange();
}
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();
else else
drawstatus(); drawstatus();
} }
@ -262,8 +224,7 @@ toggleview(Arg *arg) {
for(i = 0; i < ntags && !seltag[i]; i++); for(i = 0; i < ntags && !seltag[i]; i++);
if(i == ntags) if(i == ntags)
seltag[arg->i] = True; /* cannot toggle last view */ seltag[arg->i] = True; /* cannot toggle last view */
reorder(); arrange();
arrange(NULL);
} }
void void
@ -271,20 +232,10 @@ view(Arg *arg) {
unsigned int i; unsigned int i;
for(i = 0; i < ntags; i++) for(i = 0; i < ntags; i++)
seltag[i] = False; seltag[i] = (arg->i == -1) ? True : False;
seltag[arg->i] = True; if(arg->i >= 0 && arg->i < ntags)
reorder(); seltag[arg->i] = True;
arrange(NULL); arrange();
}
void
viewall(Arg *arg) {
unsigned int i;
for(i = 0; i < ntags; i++)
seltag[i] = True;
reorder();
arrange(NULL);
} }
void void
@ -294,18 +245,15 @@ zoom(Arg *arg) {
if(!sel) if(!sel)
return; return;
if(sel->isfloat || (arrange == dofloat)) { if(sel->isfloat || (arrange == dofloat)) {
togglemax(sel); togglemax(sel);
return; 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(n < 2 || (arrange == dofloat)) if(n < 2 || (arrange == dofloat))
return; return;
if((c = sel) == nexttiled(clients)) if((c = sel) == nexttiled(clients))
if(!(c = nexttiled(c->next))) if(!(c = nexttiled(c->next)))
return; return;
@ -315,5 +263,5 @@ zoom(Arg *arg) {
c->next = clients; c->next = clients;
clients = c; clients = c;
focus(c); focus(c);
arrange(NULL); arrange();
} }